050020dae74b41eea82b429992c715fdc3c8fa69
[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 "main.h"
35 #include "ralloc.h"
36 #include "gen.h"
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #define BETTER_LITERAL_SHIFT
41
42 char *aopLiteral (value * val, int offset);
43 extern int allocInfo;
44
45 /* this is the down and dirty file with all kinds of
46    kludgy & hacky stuff. This is what it is all about
47    CODE GENERATION for a specific MCU . some of the
48    routines may be reusable, will have to see */
49
50 static char *zero = "#0";
51 static char *one = "#1";
52 static char *spname;
53
54 #define D(x) x
55
56 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
57 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
58
59 short fReturnSizeDS390 = 5;
60 static char *fReturn24[] =
61 {"dpl", "dph", "dpx", "b", "a"};
62 static char *fReturn16[] =
63 {"dpl", "dph", "b", "a"};
64 static char **fReturn = fReturn24;
65 static char *accUse[] =
66 {"a", "b"};
67 static char *dptrn[2][3];
68 static char *javaRet[] = { "r0","r1","r2","r3"};
69 static short rbank = -1;
70
71 static struct
72   {
73     short r0Pushed;
74     short r1Pushed;
75     short accInUse;
76     short bInUse;
77     short inLine;
78     short debugLine;
79     short nRegsSaved;
80     short dptrInUse;
81     short dptr1InUse;
82     set *sendSet;
83     iCode *current_iCode;
84   }
85 _G;
86
87 static char *rb1regs[] = {
88     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
89 };
90
91 static void saveRBank (int, iCode *, bool);
92
93 #define RESULTONSTACK(x) \
94                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
95                          IC_RESULT(x)->aop->type == AOP_STK )
96
97 #define MOVA(x) _movA(x)
98 #define MOVB(x) _movB(x)
99
100 #define CLRC    emitcode("clr","c")
101 #define SETC    emitcode("setb","c")
102
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG  "_ap"
106
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
109
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112  0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115  0x07, 0x03, 0x01, 0x00};
116
117 #define LSB     0
118 #define MSB16   1
119 #define MSB24   2
120 #define MSB32   3
121 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
122                                 symbol *lbl = newiTempLabel(NULL);              \
123                                 emitcode ("setb","F1");                         \
124                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
125                                 emitcode ("clr","F1");                          \
126                                 emitcode ("","!tlabeldef",lbl->key+100);        \
127                         }}
128 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
129                                 symbol *lbl = newiTempLabel(NULL);              \
130                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
131                                 emitcode ("setb","EA");                         \
132                                 emitcode ("","!tlabeldef",lbl->key+100);        \
133                         }}
134
135 static int _currentDPS;         /* Current processor DPS. */
136 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
137 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
138
139 /*-----------------------------------------------------------------*/
140 /* emitcode - writes the code into a file : for now it is simple    */
141 /*-----------------------------------------------------------------*/
142 static void
143 emitcode (char *inst, const char *fmt,...)
144 {
145   va_list ap;
146   char lb[INITIAL_INLINEASM];
147   char *lbp = lb;
148
149   va_start (ap, fmt);
150
151   if (inst && *inst)
152     {
153       if (fmt && *fmt)
154         {
155           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
156         }
157       else
158         {
159           SNPRINTF (lb, sizeof(lb), "%s", inst);
160         }
161
162       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
163     }
164   else
165     {
166       tvsprintf (lb, sizeof(lb), fmt, ap);
167     }
168
169   while (isspace ((unsigned char)*lbp))
170     {
171       lbp++;
172     }
173
174   if (lbp && *lbp)
175     {
176       lineCurr = (lineCurr ?
177                   connectLine (lineCurr, newLineNode (lb)) :
178                   (lineHead = newLineNode (lb)));
179     }
180
181   lineCurr->isInline = _G.inLine;
182   lineCurr->isDebug = _G.debugLine;
183   lineCurr->ic = _G.current_iCode;
184   lineCurr->aln = ds390newAsmLineNode(_currentDPS);
185   va_end (ap);
186 }
187
188 /*-----------------------------------------------------------------*/
189 /* ds390_emitDebuggerSymbol - associate the current code location  */
190 /*   with a debugger symbol                                        */
191 /*-----------------------------------------------------------------*/
192 void
193 ds390_emitDebuggerSymbol (char * debugSym)
194 {
195   _G.debugLine = 1;
196   emitcode ("", "%s ==.", debugSym);
197   _G.debugLine = 0;
198 }
199
200 //
201 // Move the passed value into A unless it is already there.
202 //
203 static void
204 _movA(const char *s)
205 {
206     if (strcmp(s,"a") && strcmp(s,"acc"))
207     {
208         emitcode("mov","a,%s",s);
209     }
210 }
211
212 //
213 // Move the passed value into B unless it is already there.
214 //
215 static void
216 _movB(const char *s)
217 {
218     if (strcmp(s,"b"))
219     {
220         emitcode("mov","b,%s",s);
221     }
222 }
223
224 /*-----------------------------------------------------------------*/
225 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
226 /*-----------------------------------------------------------------*/
227 static regs *
228 getFreePtr (iCode * ic, asmop ** aopp, bool result)
229 {
230   bool r0iu, r1iu;
231   bool r0ou, r1ou;
232
233   /* the logic: if r0 & r1 used in the instruction
234      then we are in trouble otherwise */
235
236   /* first check if r0 & r1 are used by this
237      instruction, in which case we are in trouble */
238   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
239   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
240   if (r0iu && r1iu) {
241       goto endOfWorld;
242     }
243
244   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
245   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
246
247   /* if no usage of r0 then return it */
248   if (!r0iu && !r0ou)
249     {
250       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
251       (*aopp)->type = AOP_R0;
252
253       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
254     }
255
256   /* if no usage of r1 then return it */
257   if (!r1iu && !r1ou)
258     {
259       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
260       (*aopp)->type = AOP_R1;
261
262       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
263     }
264
265   /* now we know they both have usage */
266   /* if r0 not used in this instruction */
267   if (!r0iu)
268     {
269       /* push it if not already pushed */
270       if (!_G.r0Pushed)
271         {
272           emitcode ("push", "%s",
273                     ds390_regWithIdx (R0_IDX)->dname);
274           _G.r0Pushed++;
275         }
276
277       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
278       (*aopp)->type = AOP_R0;
279
280       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
281     }
282
283   /* if r1 not used then */
284
285   if (!r1iu)
286     {
287       /* push it if not already pushed */
288       if (!_G.r1Pushed)
289         {
290           emitcode ("push", "%s",
291                     ds390_regWithIdx (R1_IDX)->dname);
292           _G.r1Pushed++;
293         }
294
295       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
296       (*aopp)->type = AOP_R1;
297       return ds390_regWithIdx (R1_IDX);
298     }
299
300 endOfWorld:
301   /* I said end of world but not quite end of world yet */
302   /* if this is a result then we can push it on the stack */
303   if (result)
304     {
305       (*aopp)->type = AOP_STK;
306       return NULL;
307     }
308
309   /* other wise this is true end of the world */
310   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
311           "getFreePtr should never reach here");
312   exit (1);
313
314   return NULL; // notreached, but makes compiler happy.
315 }
316
317 /*-----------------------------------------------------------------*/
318 /* newAsmop - creates a new asmOp                                  */
319 /*-----------------------------------------------------------------*/
320 static asmop *
321 newAsmop (short type)
322 {
323   asmop *aop;
324
325   aop = Safe_calloc (1, sizeof (asmop));
326   aop->type = type;
327   return aop;
328 }
329
330
331 /*-----------------------------------------------------------------*/
332 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
333 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
334 /* alternate DPTR (DPL1/DPH1/DPX1).          */
335 /*-----------------------------------------------------------------*/
336 static void
337 genSetDPTR (int n)
338 {
339
340   /* If we are doing lazy evaluation, simply note the desired
341    * change, but don't emit any code yet.
342    */
343   if (_lazyDPS)
344     {
345       _desiredDPS = n;
346       return;
347     }
348
349   if (!n)
350     {
351       emitcode ("mov", "dps,#0");
352     }
353   else
354     {
355       TR_DPTR("#1");
356       emitcode ("mov", "dps,#1");
357     }
358 }
359
360 /*-----------------------------------------------------------------*/
361 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
362 /*                   */
363 /* Any code that operates on DPTR (NB: not on the individual     */
364 /* components, like DPH) *must* call _flushLazyDPS() before using  */
365 /* DPTR within a lazy DPS evaluation block.        */
366 /*                   */
367 /* Note that aopPut and aopGet already contain the proper calls to */
368 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
369 /* DPS evaluation block.             */
370 /*                   */
371 /* Also, _flushLazyDPS must be called before any flow control      */
372 /* operations that could potentially branch out of the block.    */
373 /*                         */
374 /* Lazy DPS evaluation is simply an optimization (though an      */
375 /* important one), so if in doubt, leave it out.       */
376 /*-----------------------------------------------------------------*/
377 static void
378 _startLazyDPSEvaluation (void)
379 {
380   _currentDPS = 0;
381   _desiredDPS = 0;
382 #ifdef BETTER_LITERAL_SHIFT
383   _lazyDPS++;
384 #else
385   _lazyDPS = 1;
386 #endif
387 }
388
389 /*-----------------------------------------------------------------*/
390 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
391 /* desired one. Call before using DPTR within a lazy DPS evaluation */
392 /* block.                */
393 /*-----------------------------------------------------------------*/
394 static void
395 _flushLazyDPS (void)
396 {
397   if (!_lazyDPS)
398     {
399       /* nothing to do. */
400       return;
401     }
402
403   if (_desiredDPS != _currentDPS)
404     {
405       if (_desiredDPS)
406         {
407           emitcode ("inc", "dps");
408         }
409       else
410         {
411           emitcode ("dec", "dps");
412         }
413       _currentDPS = _desiredDPS;
414     }
415 }
416
417 /*-----------------------------------------------------------------*/
418 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
419 /*                   */
420 /* Forces us back to the safe state (standard DPTR selected).    */
421 /*-----------------------------------------------------------------*/
422 static void
423 _endLazyDPSEvaluation (void)
424 {
425 #ifdef BETTER_LITERAL_SHIFT
426   _lazyDPS--;
427 #else
428   _lazyDPS = 0;
429 #endif
430   if (!_lazyDPS)
431   {
432     if (_currentDPS)
433     {
434       genSetDPTR (0);
435       _flushLazyDPS ();
436     }
437     _currentDPS = 0;
438     _desiredDPS = 0;
439   }
440 }
441
442
443
444 /*-----------------------------------------------------------------*/
445 /* pointerCode - returns the code for a pointer type               */
446 /*-----------------------------------------------------------------*/
447 static int
448 pointerCode (sym_link * etype)
449 {
450
451   return PTR_TYPE (SPEC_OCLS (etype));
452
453 }
454
455 /*-----------------------------------------------------------------*/
456 /* leftRightUseAcc - returns size of accumulator use by operands   */
457 /*-----------------------------------------------------------------*/
458 static int
459 leftRightUseAcc(iCode *ic)
460 {
461   operand *op;
462   int size;
463   int accuseSize = 0;
464   int accuse = 0;
465
466   if (!ic)
467     {
468       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
469               "null iCode pointer");
470       return 0;
471     }
472
473   if (ic->op == IFX)
474     {
475       op = IC_COND (ic);
476       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
477         {
478           accuse = 1;
479           size = getSize (OP_SYMBOL (op)->type);
480           if (size>accuseSize)
481             accuseSize = size;
482         }
483     }
484   else if (ic->op == JUMPTABLE)
485     {
486       op = IC_JTCOND (ic);
487       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
488         {
489           accuse = 1;
490           size = getSize (OP_SYMBOL (op)->type);
491           if (size>accuseSize)
492             accuseSize = size;
493         }
494     }
495   else
496     {
497       op = IC_LEFT (ic);
498       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
499         {
500           accuse = 1;
501           size = getSize (OP_SYMBOL (op)->type);
502           if (size>accuseSize)
503             accuseSize = size;
504         }
505       op = IC_RIGHT (ic);
506       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
507         {
508           accuse = 1;
509           size = getSize (OP_SYMBOL (op)->type);
510           if (size>accuseSize)
511             accuseSize = size;
512         }
513     }
514
515   if (accuseSize)
516     return accuseSize;
517   else
518     return accuse;
519 }
520
521 /*-----------------------------------------------------------------*/
522 /* aopForSym - for a true symbol                                   */
523 /*-----------------------------------------------------------------*/
524 static asmop *
525 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
526 {
527   asmop *aop;
528   memmap *space = SPEC_OCLS (sym->etype);
529   int accuse = leftRightUseAcc (ic);
530
531   /* if already has one */
532   if (sym->aop)
533     {
534       if ((sym->aop->type == AOP_DPTR && useDP2)
535           || (sym->aop->type == AOP_DPTR2 && !useDP2))
536         sym->aop = NULL;
537       else
538         return sym->aop;
539     }
540
541   /* assign depending on the storage class */
542   /* if it is on the stack or indirectly addressable */
543   /* space we need to assign either r0 or r1 to it   */
544   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
545     {
546       sym->aop = aop = newAsmop (0);
547       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
548       aop->size = getSize (sym->type);
549
550       /* now assign the address of the variable to
551          the pointer register */
552       if (aop->type != AOP_STK)
553         {
554
555           if (sym->onStack)
556             {
557               if (_G.accInUse || accuse)
558                 emitcode ("push", "acc");
559
560               if (_G.bInUse || (accuse>1))
561                 emitcode ("push", "b");
562
563               emitcode ("mov", "a,_bp");
564               emitcode ("add", "a,#!constbyte",
565                         ((sym->stack < 0) ?
566                          ((char) (sym->stack - _G.nRegsSaved)) :
567                          ((char) sym->stack)) & 0xff);
568               emitcode ("mov", "%s,a",
569                         aop->aopu.aop_ptr->name);
570
571               if (_G.bInUse || (accuse>1))
572                 emitcode ("pop", "b");
573
574               if (_G.accInUse || accuse)
575                 emitcode ("pop", "acc");
576             }
577           else
578             emitcode ("mov", "%s,#%s",
579                       aop->aopu.aop_ptr->name,
580                       sym->rname);
581           aop->paged = space->paged;
582         }
583       else
584         aop->aopu.aop_stk = sym->stack;
585       return aop;
586     }
587
588   if (sym->onStack && options.stack10bit)
589     {
590         short stack_val = -((sym->stack < 0) ?
591                             ((short) (sym->stack - _G.nRegsSaved)) :
592                             ((short) sym->stack)) ;
593         if (useDP2 && _G.dptr1InUse) {
594             emitcode ("push","dpl1");
595             emitcode ("push","dph1");
596             emitcode ("push","dpx1");
597         } else if (_G.dptrInUse ) {
598             emitcode ("push","dpl");
599             emitcode ("push","dph");
600             emitcode ("push","dpx");
601         }
602       /* It's on the 10 bit stack, which is located in
603        * far data space.
604        */
605         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
606             if (useDP2) {
607                 if (options.model == MODEL_FLAT24)
608                 {
609                     emitcode ("mov", "dpx1,#!constbyte",
610                               (options.stack_loc >> 16) & 0xff);
611                 }
612                 emitcode ("mov", "dph1,_bpx+1");
613
614                 emitcode ("mov", "dpl1,_bpx");
615                 emitcode ("mov","dps,#1");
616             } else {
617                 if (options.model == MODEL_FLAT24)
618                 {
619                     emitcode ("mov", "dpx,#!constbyte",
620                               (options.stack_loc >> 16) & 0xff);
621                 }
622                 emitcode ("mov", "dph,_bpx+1");
623                 emitcode ("mov", "dpl,_bpx");
624             }
625             stack_val = -stack_val;
626             while (stack_val--) {
627                 emitcode ("inc","dptr");
628             }
629             if (useDP2) {
630                 emitcode("mov","dps,#0");
631             }
632         }  else {
633             if (_G.accInUse || accuse)
634                 emitcode ("push", "acc");
635
636             if (_G.bInUse || (accuse>1))
637                 emitcode ("push", "b");
638
639             emitcode ("mov", "a,_bpx");
640             emitcode ("clr","c");
641             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
642             emitcode ("mov","b,a");
643             emitcode ("mov","a,_bpx+1");
644             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
645             if (useDP2) {
646                 if (options.model == MODEL_FLAT24)
647                 {
648                     emitcode ("mov", "dpx1,#!constbyte",
649                               (options.stack_loc >> 16) & 0xff);
650                 }
651                 emitcode ("mov", "dph1,a");
652                 emitcode ("mov", "dpl1,b");
653             } else {
654                 if (options.model == MODEL_FLAT24)
655                 {
656                     emitcode ("mov", "dpx,#!constbyte",
657                               (options.stack_loc >> 16) & 0xff);
658                 }
659                 emitcode ("mov", "dph,a");
660                 emitcode ("mov", "dpl,b");
661             }
662
663             if (_G.bInUse || (accuse>1))
664                 emitcode ("pop", "b");
665
666             if (_G.accInUse || accuse)
667                 emitcode ("pop", "acc");
668         }
669         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
670         aop->size = getSize (sym->type);
671         return aop;
672     }
673
674   /* if in bit space */
675   if (IN_BITSPACE (space))
676     {
677       sym->aop = aop = newAsmop (AOP_CRY);
678       aop->aopu.aop_dir = sym->rname;
679       aop->size = getSize (sym->type);
680       return aop;
681     }
682   /* if it is in direct space */
683   if (IN_DIRSPACE (space))
684     {
685       sym->aop = aop = newAsmop (AOP_DIR);
686       aop->aopu.aop_dir = sym->rname;
687       aop->size = getSize (sym->type);
688       return aop;
689     }
690
691   /* special case for a function */
692   if (IS_FUNC (sym->type) && !(sym->isitmp))
693     {
694       sym->aop = aop = newAsmop (AOP_IMMD);
695       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696       aop->size = FPTRSIZE;
697       return aop;
698     }
699
700   /* only remaining is far space */
701   /* in which case DPTR gets the address */
702   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
703   if (useDP2)
704     {
705       genSetDPTR (1);
706       _flushLazyDPS ();
707       emitcode ("mov", "dptr,#%s", sym->rname);
708       genSetDPTR (0);
709     }
710   else
711     {
712       emitcode ("mov", "dptr,#%s", sym->rname);
713     }
714   aop->size = getSize (sym->type);
715
716   /* if it is in code space */
717   if (IN_CODESPACE (space))
718     aop->code = 1;
719
720   return aop;
721 }
722
723 /*-----------------------------------------------------------------*/
724 /* aopForRemat - rematerialzes an object                           */
725 /*-----------------------------------------------------------------*/
726 static asmop *
727 aopForRemat (symbol * sym)
728 {
729   iCode *ic = sym->rematiCode;
730   asmop *aop = newAsmop (AOP_IMMD);
731   int ptr_type = 0;
732   int val = 0;
733
734   for (;;)
735     {
736       if (ic->op == '+')
737         val += (int) operandLitValue (IC_RIGHT (ic));
738       else if (ic->op == '-')
739         val -= (int) operandLitValue (IC_RIGHT (ic));
740       else if (IS_CAST_ICODE(ic)) {
741               sym_link *from_type = operandType(IC_RIGHT(ic));
742               aop->aopu.aop_immd.from_cast_remat = 1;
743               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
744               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
745               continue;
746       } else break;
747
748       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
749     }
750
751   if (val)
752   {
753       SNPRINTF (buffer, sizeof(buffer),
754                 "(%s %c 0x%04x)",
755                 OP_SYMBOL (IC_LEFT (ic))->rname,
756                 val >= 0 ? '+' : '-',
757                 abs (val) & 0xffffff);
758   }
759   else
760   {
761       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
762       {
763           SNPRINTF(buffer, sizeof(buffer),
764                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
765       }
766       else
767       {
768           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
769       }
770   }
771
772   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
773   /* set immd2 field if required */
774   if (aop->aopu.aop_immd.from_cast_remat)
775   {
776       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
777       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
778   }
779
780   return aop;
781 }
782
783 /*-----------------------------------------------------------------*/
784 /* aopHasRegs - returns true if aop has regs between from-to       */
785 /*-----------------------------------------------------------------*/
786 static int aopHasRegs(asmop *aop, int from, int to)
787 {
788     int size =0;
789
790     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
791
792     for (; size < aop->size ; size++) {
793         int reg;
794         for (reg = from ; reg <= to ; reg++)
795             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
796     }
797     return 0;
798 }
799
800 /*-----------------------------------------------------------------*/
801 /* regsInCommon - two operands have some registers in common       */
802 /*-----------------------------------------------------------------*/
803 static bool
804 regsInCommon (operand * op1, operand * op2)
805 {
806   symbol *sym1, *sym2;
807   int i;
808
809   /* if they have registers in common */
810   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
811     return FALSE;
812
813   sym1 = OP_SYMBOL (op1);
814   sym2 = OP_SYMBOL (op2);
815
816   if (sym1->nRegs == 0 || sym2->nRegs == 0)
817     return FALSE;
818
819   for (i = 0; i < sym1->nRegs; i++)
820     {
821       int j;
822       if (!sym1->regs[i])
823         continue;
824
825       for (j = 0; j < sym2->nRegs; j++)
826         {
827           if (!sym2->regs[j])
828             continue;
829
830           if (sym2->regs[j] == sym1->regs[i])
831             return TRUE;
832         }
833     }
834
835   return FALSE;
836 }
837
838 /*-----------------------------------------------------------------*/
839 /* operandsEqu - equivalent                                        */
840 /*-----------------------------------------------------------------*/
841 static bool
842 operandsEqu (operand * op1, operand * op2)
843 {
844   symbol *sym1, *sym2;
845
846   /* if they not symbols */
847   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
848     return FALSE;
849
850   sym1 = OP_SYMBOL (op1);
851   sym2 = OP_SYMBOL (op2);
852
853   /* if both are itemps & one is spilt
854      and the other is not then false */
855   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
856       sym1->isspilt != sym2->isspilt)
857     return FALSE;
858
859   /* if they are the same */
860   if (sym1 == sym2)
861     return TRUE;
862
863   if (sym1->rname[0] && sym2->rname[0]
864       && strcmp (sym1->rname, sym2->rname) == 0)
865     return TRUE;
866
867   /* if left is a tmp & right is not */
868   if (IS_ITEMP (op1) &&
869       !IS_ITEMP (op2) &&
870       sym1->isspilt &&
871       (sym1->usl.spillLoc == sym2))
872     return TRUE;
873
874   if (IS_ITEMP (op2) &&
875       !IS_ITEMP (op1) &&
876       sym2->isspilt &&
877       sym1->level > 0 &&
878       (sym2->usl.spillLoc == sym1))
879     return TRUE;
880
881   /* are they spilt to the same location */
882   if (IS_ITEMP (op2) &&
883       IS_ITEMP (op1) &&
884       sym2->isspilt &&
885       sym1->isspilt &&
886       (sym1->usl.spillLoc == sym2->usl.spillLoc))
887     return TRUE;
888
889   return FALSE;
890 }
891
892 /*-----------------------------------------------------------------*/
893 /* sameRegs - two asmops have the same registers                   */
894 /*-----------------------------------------------------------------*/
895 static bool
896 sameRegs (asmop * aop1, asmop * aop2)
897 {
898   int i;
899
900   if (aop1 == aop2)
901     {
902       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
903         {
904           return FALSE;
905         }
906       return TRUE;
907     }
908
909   if (aop1->type != AOP_REG ||
910       aop2->type != AOP_REG)
911     return FALSE;
912
913   if (aop1->size != aop2->size)
914     return FALSE;
915
916   for (i = 0; i < aop1->size; i++)
917     if (aop1->aopu.aop_reg[i] !=
918         aop2->aopu.aop_reg[i])
919       return FALSE;
920
921   return TRUE;
922 }
923
924 /*-----------------------------------------------------------------*/
925 /* aopOp - allocates an asmop for an operand  :                    */
926 /*-----------------------------------------------------------------*/
927 static void
928 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
929 {
930   asmop *aop;
931   symbol *sym;
932   int i;
933
934   if (!op)
935     return;
936
937   /* if this a literal */
938   if (IS_OP_LITERAL (op))
939     {
940       op->aop = aop = newAsmop (AOP_LIT);
941       aop->aopu.aop_lit = op->operand.valOperand;
942       aop->size = getSize (operandType (op));
943       return;
944     }
945
946   /* if already has a asmop then continue */
947   if (op->aop)
948     {
949       if ((op->aop->type == AOP_DPTR && useDP2)
950           || (op->aop->type == AOP_DPTR2 && !useDP2))
951         op->aop = NULL;
952       else
953         return;
954     }
955
956   /* if the underlying symbol has a aop */
957   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
958     {
959       op->aop = OP_SYMBOL (op)->aop;
960       if ((op->aop->type == AOP_DPTR && useDP2)
961           || (op->aop->type == AOP_DPTR2 && !useDP2))
962         op->aop = NULL;
963       else
964         return;
965     }
966
967   /* if this is a true symbol */
968   if (IS_TRUE_SYMOP (op))
969     {
970       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
971       return;
972     }
973
974   /* this is a temporary : this has
975      only four choices :
976      a) register
977      b) spillocation
978      c) rematerialize
979      d) conditional
980      e) can be a return use only */
981
982   sym = OP_SYMBOL (op);
983
984   /* if the type is a conditional */
985   if (sym->regType == REG_CND)
986     {
987       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
988       aop->size = 0;
989       return;
990     }
991
992   /* if it is spilt then two situations
993      a) is rematerialize
994      b) has a spill location */
995   if (sym->isspilt || sym->nRegs == 0)
996     {
997
998       /* rematerialize it NOW */
999       if (sym->remat)
1000         {
1001           sym->aop = op->aop = aop =
1002             aopForRemat (sym);
1003           aop->size = getSize (sym->type);
1004           return;
1005         }
1006
1007       if (sym->accuse)
1008         {
1009           int i;
1010           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1011           aop->size = getSize (sym->type);
1012           for (i = 0; i < 2; i++)
1013             aop->aopu.aop_str[i] = accUse[i];
1014           return;
1015         }
1016
1017       if (sym->ruonly)
1018         {
1019           int i;
1020
1021           if (useDP2)
1022             {
1023               /* a AOP_STR uses DPTR, but DPTR is already in use;
1024                * we're just hosed.
1025                */
1026                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1027             }
1028
1029           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1030           aop->size = getSize (sym->type);
1031           for (i = 0; i < fReturnSizeDS390; i++)
1032             aop->aopu.aop_str[i] = fReturn[i];
1033           return;
1034         }
1035
1036       if (sym->dptr) { /* has been allocated to a DPTRn */
1037           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1038           aop->size = getSize (sym->type);
1039           aop->aopu.dptr = sym->dptr;
1040           return ;
1041       }
1042
1043       if (sym->usl.spillLoc)
1044         {
1045           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1046             {
1047               /* force a new aop if sizes differ */
1048               sym->usl.spillLoc->aop = NULL;
1049             }
1050           sym->aop = op->aop = aop =
1051                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1052           aop->size = getSize (sym->type);
1053           return;
1054         }
1055
1056       /* else must be a dummy iTemp */
1057       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1058       aop->size = getSize (sym->type);
1059       return;
1060     }
1061
1062   /* must be in a register */
1063   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1064   aop->size = sym->nRegs;
1065   for (i = 0; i < sym->nRegs; i++)
1066     aop->aopu.aop_reg[i] = sym->regs[i];
1067 }
1068
1069 /*-----------------------------------------------------------------*/
1070 /* freeAsmop - free up the asmop given to an operand               */
1071 /*----------------------------------------------------------------*/
1072 static void
1073 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1074 {
1075   asmop *aop;
1076
1077   if (!op)
1078     aop = aaop;
1079   else
1080     aop = op->aop;
1081
1082   if (!aop)
1083     return;
1084
1085   if (aop->freed)
1086     goto dealloc;
1087
1088   aop->freed = 1;
1089
1090   /* depending on the asmop type only three cases need work AOP_RO
1091      , AOP_R1 && AOP_STK */
1092   switch (aop->type)
1093     {
1094     case AOP_R0:
1095       if (_G.r0Pushed)
1096         {
1097           if (pop)
1098             {
1099               emitcode ("pop", "ar0");
1100               _G.r0Pushed--;
1101             }
1102         }
1103       bitVectUnSetBit (ic->rUsed, R0_IDX);
1104       break;
1105
1106     case AOP_R1:
1107       if (_G.r1Pushed)
1108         {
1109           if (pop)
1110             {
1111               emitcode ("pop", "ar1");
1112               _G.r1Pushed--;
1113             }
1114         }
1115       bitVectUnSetBit (ic->rUsed, R1_IDX);
1116       break;
1117
1118     case AOP_STK:
1119       {
1120         int sz = aop->size;
1121         int stk = aop->aopu.aop_stk + aop->size;
1122         bitVectUnSetBit (ic->rUsed, R0_IDX);
1123         bitVectUnSetBit (ic->rUsed, R1_IDX);
1124
1125         getFreePtr (ic, &aop, FALSE);
1126
1127         if (options.stack10bit)
1128           {
1129             /* I'm not sure what to do here yet... */
1130             /* #STUB */
1131             fprintf (stderr,
1132                      "*** Warning: probably generating bad code for "
1133                      "10 bit stack mode.\n");
1134           }
1135
1136         if (stk)
1137           {
1138             emitcode ("mov", "a,_bp");
1139             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1140             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1141           }
1142         else
1143           {
1144             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1145           }
1146
1147         while (sz--)
1148           {
1149             emitcode ("pop", "acc");
1150             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1151             if (!sz)
1152               break;
1153             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1154           }
1155         op->aop = aop;
1156         freeAsmop (op, NULL, ic, TRUE);
1157         if (_G.r0Pushed)
1158           {
1159             emitcode ("pop", "ar0");
1160             _G.r0Pushed--;
1161           }
1162
1163         if (_G.r1Pushed)
1164           {
1165             emitcode ("pop", "ar1");
1166             _G.r1Pushed--;
1167           }
1168       }
1169     case AOP_DPTR2:
1170         if (_G.dptr1InUse) {
1171             emitcode ("pop","dpx1");
1172             emitcode ("pop","dph1");
1173             emitcode ("pop","dpl1");
1174         }
1175         break;
1176     case AOP_DPTR:
1177         if (_G.dptrInUse) {
1178             emitcode ("pop","dpx");
1179             emitcode ("pop","dph");
1180             emitcode ("pop","dpl");
1181         }
1182         break;
1183     }
1184 dealloc:
1185   /* all other cases just dealloc */
1186   if (op)
1187     {
1188       op->aop = NULL;
1189       if (IS_SYMOP (op))
1190         {
1191           OP_SYMBOL (op)->aop = NULL;
1192           /* if the symbol has a spill */
1193           if (SPIL_LOC (op))
1194             SPIL_LOC (op)->aop = NULL;
1195         }
1196     }
1197 }
1198
1199 #define DEFAULT_ACC_WARNING 0
1200 static int saveAccWarn = DEFAULT_ACC_WARNING;
1201
1202 /*-------------------------------------------------------------------*/
1203 /* aopGet - for fetching value of the aop                            */
1204 /*                                                                   */
1205 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1206 /* in the accumulator. Set it to the name of a free register         */
1207 /* if acc must be preserved; the register will be used to preserve   */
1208 /* acc temporarily and to return the result byte.                    */
1209 /*-------------------------------------------------------------------*/
1210
1211 static char *
1212 aopGet (asmop *aop,
1213         int   offset,
1214         bool  bit16,
1215         bool  dname,
1216         char  *saveAcc)
1217 {
1218   /* offset is greater than
1219      size then zero */
1220   if (offset > (aop->size - 1) &&
1221       aop->type != AOP_LIT)
1222     return zero;
1223
1224   /* depending on type */
1225   switch (aop->type)
1226     {
1227     case AOP_DUMMY:
1228       return zero;
1229
1230     case AOP_R0:
1231     case AOP_R1:
1232       /* if we need to increment it */
1233       while (offset > aop->coff)
1234         {
1235           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1236           aop->coff++;
1237         }
1238
1239       while (offset < aop->coff)
1240         {
1241           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1242           aop->coff--;
1243         }
1244
1245       aop->coff = offset;
1246       if (aop->paged)
1247         {
1248           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1249           return (dname ? "acc" : "a");
1250         }
1251       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1252       return Safe_strdup(buffer);
1253
1254     case AOP_DPTRn:
1255         assert(offset <= 3);
1256         return dptrn[aop->aopu.dptr][offset];
1257
1258     case AOP_DPTR:
1259     case AOP_DPTR2:
1260
1261       if (aop->type == AOP_DPTR2)
1262         {
1263           genSetDPTR (1);
1264         }
1265
1266       if (saveAcc)
1267         {
1268             TR_AP("#1");
1269 //          if (aop->type != AOP_DPTR2)
1270 //          {
1271 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1272 //              emitcode(";", "spanky: saveAcc for DPTR");
1273 //          }
1274
1275             emitcode ("xch", "a, %s", saveAcc);
1276         }
1277
1278       _flushLazyDPS ();
1279
1280       while (offset > aop->coff)
1281         {
1282           emitcode ("inc", "dptr");
1283           aop->coff++;
1284         }
1285
1286       while (offset < aop->coff)
1287         {
1288           emitcode ("lcall", "__decdptr");
1289           aop->coff--;
1290         }
1291
1292       aop->coff = offset;
1293       if (aop->code)
1294         {
1295           emitcode ("clr", "a");
1296           emitcode ("movc", "a,@a+dptr");
1297         }
1298       else
1299         {
1300           emitcode ("movx", "a,@dptr");
1301         }
1302
1303       if (aop->type == AOP_DPTR2)
1304         {
1305           genSetDPTR (0);
1306         }
1307
1308         if (saveAcc)
1309         {
1310        TR_AP("#2");
1311               emitcode ("xch", "a, %s", saveAcc);
1312 //            if (strcmp(saveAcc, "_ap"))
1313 //            {
1314 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1315 //            }
1316
1317               return saveAcc;
1318         }
1319       return (dname ? "acc" : "a");
1320
1321     case AOP_IMMD:
1322       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1323       {
1324           SNPRINTF(buffer, sizeof(buffer),
1325                    "%s",aop->aopu.aop_immd.aop_immd2);
1326       }
1327       else if (bit16)
1328       {
1329          SNPRINTF(buffer, sizeof(buffer),
1330                   "#%s", aop->aopu.aop_immd.aop_immd1);
1331       }
1332       else if (offset)
1333       {
1334           switch (offset) {
1335           case 1:
1336               tsprintf(buffer, sizeof(buffer),
1337                        "#!his",aop->aopu.aop_immd.aop_immd1);
1338               break;
1339           case 2:
1340               tsprintf(buffer, sizeof(buffer),
1341                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1342               break;
1343           case 3:
1344               tsprintf(buffer, sizeof(buffer),
1345                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1346               break;
1347           default: /* should not need this (just in case) */
1348               SNPRINTF (buffer, sizeof(buffer),
1349                         "#(%s >> %d)",
1350                        aop->aopu.aop_immd.aop_immd1,
1351                        offset * 8);
1352           }
1353       }
1354       else
1355       {
1356         SNPRINTF (buffer, sizeof(buffer),
1357                   "#%s", aop->aopu.aop_immd.aop_immd1);
1358       }
1359       return Safe_strdup(buffer);
1360
1361     case AOP_DIR:
1362       if (offset)
1363       {
1364         SNPRINTF (buffer, sizeof(buffer),
1365                   "(%s + %d)",
1366                  aop->aopu.aop_dir,
1367                  offset);
1368       }
1369       else
1370       {
1371         SNPRINTF(buffer, sizeof(buffer),
1372                  "%s", aop->aopu.aop_dir);
1373       }
1374
1375       return Safe_strdup(buffer);
1376
1377     case AOP_REG:
1378       if (dname)
1379         return aop->aopu.aop_reg[offset]->dname;
1380       else
1381         return aop->aopu.aop_reg[offset]->name;
1382
1383     case AOP_CRY:
1384       emitcode ("clr", "a");
1385       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1386       emitcode ("rlc", "a");
1387       return (dname ? "acc" : "a");
1388
1389     case AOP_ACC:
1390       if (!offset && dname)
1391         return "acc";
1392       return aop->aopu.aop_str[offset];
1393
1394     case AOP_LIT:
1395       return aopLiteral (aop->aopu.aop_lit, offset);
1396
1397     case AOP_STR:
1398       aop->coff = offset;
1399       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1400           dname)
1401         return "acc";
1402
1403       return aop->aopu.aop_str[offset];
1404
1405     }
1406
1407   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1408           "aopget got unsupported aop->type");
1409   exit (1);
1410
1411   return NULL;  // not reached, but makes compiler happy.
1412 }
1413 /*-----------------------------------------------------------------*/
1414 /* aopPut - puts a string for a aop                                */
1415 /*-----------------------------------------------------------------*/
1416 static void
1417 aopPut (asmop * aop, char *s, int offset)
1418 {
1419   if (aop->size && offset > (aop->size - 1))
1420     {
1421       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1422               "aopPut got offset > aop->size");
1423       exit (1);
1424     }
1425
1426   /* will assign value to value */
1427   /* depending on where it is ofcourse */
1428   switch (aop->type)
1429     {
1430     case AOP_DUMMY:
1431       MOVA (s);         /* read s in case it was volatile */
1432       break;
1433
1434     case AOP_DIR:
1435         if (offset)
1436         {
1437             SNPRINTF (buffer, sizeof(buffer),
1438                       "(%s + %d)",
1439                       aop->aopu.aop_dir, offset);
1440         }
1441         else
1442         {
1443             SNPRINTF (buffer, sizeof(buffer),
1444                      "%s", aop->aopu.aop_dir);
1445         }
1446
1447
1448         if (strcmp (buffer, s))
1449         {
1450             emitcode ("mov", "%s,%s", buffer, s);
1451         }
1452       break;
1453
1454     case AOP_REG:
1455       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1456           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1457         {
1458           if (*s == '@' ||
1459               strcmp (s, "r0") == 0 ||
1460               strcmp (s, "r1") == 0 ||
1461               strcmp (s, "r2") == 0 ||
1462               strcmp (s, "r3") == 0 ||
1463               strcmp (s, "r4") == 0 ||
1464               strcmp (s, "r5") == 0 ||
1465               strcmp (s, "r6") == 0 ||
1466               strcmp (s, "r7") == 0)
1467             {
1468                 emitcode ("mov", "%s,%s",
1469                           aop->aopu.aop_reg[offset]->dname, s);
1470             }
1471             else
1472             {
1473                 emitcode ("mov", "%s,%s",
1474                           aop->aopu.aop_reg[offset]->name, s);
1475             }
1476         }
1477       break;
1478
1479     case AOP_DPTRn:
1480         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1481         break;
1482
1483     case AOP_DPTR:
1484     case AOP_DPTR2:
1485
1486       if (aop->type == AOP_DPTR2)
1487         {
1488           genSetDPTR (1);
1489         }
1490       _flushLazyDPS ();
1491
1492       if (aop->code)
1493         {
1494           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1495                   "aopPut writting to code space");
1496           exit (1);
1497         }
1498
1499       while (offset > aop->coff)
1500         {
1501           aop->coff++;
1502           emitcode ("inc", "dptr");
1503         }
1504
1505       while (offset < aop->coff)
1506         {
1507           aop->coff--;
1508           emitcode ("lcall", "__decdptr");
1509         }
1510
1511       aop->coff = offset;
1512
1513       /* if not in accumulater */
1514       MOVA (s);
1515
1516       emitcode ("movx", "@dptr,a");
1517
1518       if (aop->type == AOP_DPTR2)
1519         {
1520           genSetDPTR (0);
1521         }
1522       break;
1523
1524     case AOP_R0:
1525     case AOP_R1:
1526       while (offset > aop->coff)
1527         {
1528           aop->coff++;
1529           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1530         }
1531       while (offset < aop->coff)
1532         {
1533           aop->coff--;
1534           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1535         }
1536       aop->coff = offset;
1537
1538       if (aop->paged)
1539         {
1540           MOVA (s);
1541           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1542
1543         }
1544       else if (*s == '@')
1545         {
1546           MOVA (s);
1547           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1548         }
1549       else if (strcmp (s, "r0") == 0 ||
1550                strcmp (s, "r1") == 0 ||
1551                strcmp (s, "r2") == 0 ||
1552                strcmp (s, "r3") == 0 ||
1553                strcmp (s, "r4") == 0 ||
1554                strcmp (s, "r5") == 0 ||
1555                strcmp (s, "r6") == 0 ||
1556                strcmp (s, "r7") == 0)
1557         {
1558           char buff[10];
1559           SNPRINTF(buff, sizeof(buff),
1560                    "a%s", s);
1561           emitcode ("mov", "@%s,%s",
1562                     aop->aopu.aop_ptr->name, buff);
1563         }
1564         else
1565         {
1566             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1567         }
1568       break;
1569
1570     case AOP_STK:
1571       if (strcmp (s, "a") == 0)
1572         emitcode ("push", "acc");
1573       else
1574         if (*s=='@') {
1575           MOVA(s);
1576           emitcode ("push", "acc");
1577         } else {
1578           emitcode ("push", s);
1579         }
1580
1581       break;
1582
1583     case AOP_CRY:
1584       /* if bit variable */
1585       if (!aop->aopu.aop_dir)
1586         {
1587           emitcode ("clr", "a");
1588           emitcode ("rlc", "a");
1589         }
1590       else
1591         {
1592           if (s == zero)
1593             emitcode ("clr", "%s", aop->aopu.aop_dir);
1594           else if (s == one)
1595             emitcode ("setb", "%s", aop->aopu.aop_dir);
1596           else if (!strcmp (s, "c"))
1597             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1598           else
1599             {
1600               if (strcmp (s, "a"))
1601                 {
1602                   MOVA (s);
1603                 }
1604               {
1605                 /* set C, if a >= 1 */
1606                 emitcode ("add", "a,#!constbyte",0xff);
1607                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1608               }
1609             }
1610         }
1611       break;
1612
1613     case AOP_STR:
1614       aop->coff = offset;
1615       if (strcmp (aop->aopu.aop_str[offset], s))
1616         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1617       break;
1618
1619     case AOP_ACC:
1620       aop->coff = offset;
1621       if (!offset && (strcmp (s, "acc") == 0))
1622         break;
1623
1624       if (strcmp (aop->aopu.aop_str[offset], s))
1625         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1626       break;
1627
1628     default:
1629       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1630               "aopPut got unsupported aop->type");
1631       exit (1);
1632     }
1633
1634 }
1635
1636
1637 /*--------------------------------------------------------------------*/
1638 /* reAdjustPreg - points a register back to where it should (coff==0) */
1639 /*--------------------------------------------------------------------*/
1640 static void
1641 reAdjustPreg (asmop * aop)
1642 {
1643   if ((aop->coff==0) || (aop->size <= 1)) {
1644     return;
1645   }
1646
1647   switch (aop->type)
1648     {
1649     case AOP_R0:
1650     case AOP_R1:
1651       while (aop->coff--)
1652         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1653       break;
1654     case AOP_DPTR:
1655     case AOP_DPTR2:
1656       if (aop->type == AOP_DPTR2)
1657         {
1658           genSetDPTR (1);
1659           _flushLazyDPS ();
1660         }
1661       while (aop->coff--)
1662         {
1663           emitcode ("lcall", "__decdptr");
1664         }
1665
1666       if (aop->type == AOP_DPTR2)
1667         {
1668           genSetDPTR (0);
1669         }
1670       break;
1671
1672     }
1673   aop->coff=0;
1674 }
1675
1676 #define AOP(op) op->aop
1677 #define AOP_TYPE(op) AOP(op)->type
1678 #define AOP_SIZE(op) AOP(op)->size
1679 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1680                        AOP_TYPE(x) == AOP_R0))
1681
1682 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1683                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1684                          AOP(x)->paged))
1685
1686 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1687                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1688                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1689 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1690 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1691 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1692
1693 // The following two macros can be used even if the aop has not yet been aopOp'd.
1694 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1695 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1696
1697 /* Workaround for DS80C390 bug: div ab may return bogus results
1698  * if A is accessed in instruction immediately before the div.
1699  *
1700  * Will be fixed in B4 rev of processor, Dallas claims.
1701  */
1702
1703 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1704     if (!AOP_NEEDSACC(RIGHT))         \
1705     {               \
1706       /* We can load A first, then B, since     \
1707        * B (the RIGHT operand) won't clobber A,   \
1708        * thus avoiding touching A right before the div. \
1709        */             \
1710       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1711       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1712       MOVA(L);            \
1713       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1714       MOVB(L); \
1715     }               \
1716     else              \
1717     {               \
1718       /* Just stuff in a nop after loading A. */    \
1719       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1720       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1721       MOVA(L);            \
1722       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1723     }
1724
1725
1726 /*-----------------------------------------------------------------*/
1727 /* opIsGptr: returns non-zero if the passed operand is       */
1728 /* a generic pointer type.             */
1729 /*-----------------------------------------------------------------*/
1730 static int
1731 opIsGptr (operand * op)
1732 {
1733   sym_link *type = operandType (op);
1734
1735   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1736     {
1737       return 1;
1738     }
1739   return 0;
1740 }
1741
1742 /*-----------------------------------------------------------------*/
1743 /* getDataSize - get the operand data size                         */
1744 /*-----------------------------------------------------------------*/
1745 static int
1746 getDataSize (operand * op)
1747 {
1748   int size;
1749   size = AOP_SIZE (op);
1750   if (size == GPTRSIZE)
1751     {
1752       sym_link *type = operandType (op);
1753       if (IS_GENPTR (type))
1754         {
1755           /* generic pointer; arithmetic operations
1756            * should ignore the high byte (pointer type).
1757            */
1758           size--;
1759         }
1760     }
1761   return size;
1762 }
1763
1764 /*-----------------------------------------------------------------*/
1765 /* outAcc - output Acc                                             */
1766 /*-----------------------------------------------------------------*/
1767 static void
1768 outAcc (operand * result)
1769 {
1770   int size, offset;
1771   size = getDataSize (result);
1772   if (size)
1773     {
1774       aopPut (AOP (result), "a", 0);
1775       size--;
1776       offset = 1;
1777       /* unsigned or positive */
1778       while (size--)
1779         {
1780           aopPut (AOP (result), zero, offset++);
1781         }
1782     }
1783 }
1784
1785 /*-----------------------------------------------------------------*/
1786 /* outBitC - output a bit C                                        */
1787 /*-----------------------------------------------------------------*/
1788 static void
1789 outBitC (operand * result)
1790 {
1791   /* if the result is bit */
1792   if (AOP_TYPE (result) == AOP_CRY)
1793     {
1794       aopPut (AOP (result), "c", 0);
1795     }
1796   else
1797     {
1798       emitcode ("clr", "a");
1799       emitcode ("rlc", "a");
1800       outAcc (result);
1801     }
1802 }
1803
1804 /*-----------------------------------------------------------------*/
1805 /* toBoolean - emit code for orl a,operator(sizeop)                */
1806 /*-----------------------------------------------------------------*/
1807 static void
1808 toBoolean (operand * oper)
1809 {
1810   int   size = AOP_SIZE (oper) - 1;
1811   int   offset = 1;
1812   bool usedB = FALSE;
1813
1814   /* The generic part of a generic pointer should
1815    * not participate in it's truth value.
1816    *
1817    * i.e. 0x10000000 is zero.
1818    */
1819   if (opIsGptr (oper))
1820     {
1821       D (emitcode (";", "toBoolean: generic ptr special case."););
1822       size--;
1823     }
1824
1825   _startLazyDPSEvaluation ();
1826   if (AOP_NEEDSACC (oper) && size)
1827     {
1828       usedB = TRUE;
1829       if (_G.bInUse)
1830       {
1831           emitcode ("push", "b");
1832       }
1833       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1834     }
1835   else
1836     {
1837       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1838     }
1839
1840   while (size--)
1841     {
1842       if (usedB)
1843         {
1844           emitcode ("orl", "b,%s",
1845                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1846         }
1847       else
1848         {
1849           emitcode ("orl", "a,%s",
1850                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1851         }
1852     }
1853   _endLazyDPSEvaluation ();
1854
1855   if (usedB)
1856     {
1857       emitcode ("mov", "a,b");
1858       if (_G.bInUse)
1859       {
1860           emitcode ("pop", "b");
1861       }
1862
1863     }
1864 }
1865
1866
1867 /*-----------------------------------------------------------------*/
1868 /* genNot - generate code for ! operation                          */
1869 /*-----------------------------------------------------------------*/
1870 static void
1871 genNot (iCode * ic)
1872 {
1873   symbol *tlbl;
1874
1875   D (emitcode (";", "genNot "););
1876
1877   /* assign asmOps to operand & result */
1878   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1879   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1880
1881   /* if in bit space then a special case */
1882   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1883     {
1884       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1885       emitcode ("cpl", "c");
1886       outBitC (IC_RESULT (ic));
1887       goto release;
1888     }
1889
1890   toBoolean (IC_LEFT (ic));
1891
1892   tlbl = newiTempLabel (NULL);
1893   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1894   emitcode ("", "!tlabeldef", tlbl->key + 100);
1895   outBitC (IC_RESULT (ic));
1896
1897 release:
1898   /* release the aops */
1899   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1900   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1901 }
1902
1903
1904 /*-----------------------------------------------------------------*/
1905 /* genCpl - generate code for complement                           */
1906 /*-----------------------------------------------------------------*/
1907 static void
1908 genCpl (iCode * ic)
1909 {
1910   int offset = 0;
1911   int size;
1912   symbol *tlbl;
1913   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1914
1915   D(emitcode (";", "genCpl"));
1916
1917   /* assign asmOps to operand & result */
1918   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1919   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1920
1921   /* special case if in bit space */
1922   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1923     {
1924       char *l;
1925
1926       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1927           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1928         {
1929           /* promotion rules are responsible for this strange result:
1930              bit -> int -> ~int -> bit
1931              uchar -> int -> ~int -> bit
1932           */
1933           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1934           goto release;
1935         }
1936       tlbl=newiTempLabel(NULL);
1937       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE, NULL);
1938       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1939           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1940           IS_AOP_PREG (IC_LEFT (ic)))
1941         {
1942           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1943         }
1944       else
1945         {
1946           MOVA (l);
1947           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1948         }
1949       emitcode ("", "%05d$:", tlbl->key+100);
1950       outBitC (IC_RESULT(ic));
1951       goto release;
1952     }
1953
1954   size = AOP_SIZE (IC_RESULT (ic));
1955   _startLazyDPSEvaluation ();
1956   while (size--)
1957     {
1958       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1959       emitcode ("cpl", "a");
1960       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1961     }
1962   _endLazyDPSEvaluation ();
1963
1964
1965 release:
1966   /* release the aops */
1967   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1968   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1969 }
1970
1971 /*-----------------------------------------------------------------*/
1972 /* genUminusFloat - unary minus for floating points                */
1973 /*-----------------------------------------------------------------*/
1974 static void
1975 genUminusFloat (operand * op, operand * result)
1976 {
1977   int size, offset = 0;
1978
1979   D(emitcode (";", "genUminusFloat"););
1980
1981   /* for this we just copy and then flip the bit */
1982
1983   _startLazyDPSEvaluation ();
1984   size = AOP_SIZE (op) - 1;
1985
1986   while (size--)
1987     {
1988       aopPut (AOP (result),
1989               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1990               offset);
1991       offset++;
1992     }
1993
1994   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1995
1996   emitcode ("cpl", "acc.7");
1997   aopPut (AOP (result), "a", offset);
1998   _endLazyDPSEvaluation ();
1999 }
2000
2001 /*-----------------------------------------------------------------*/
2002 /* genUminus - unary minus code generation                         */
2003 /*-----------------------------------------------------------------*/
2004 static void
2005 genUminus (iCode * ic)
2006 {
2007   int offset, size;
2008   sym_link *optype;
2009
2010   D (emitcode (";", "genUminus "););
2011
2012   /* assign asmops */
2013   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2014   aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2015
2016   /* if both in bit space then special
2017      case */
2018   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2019       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2020     {
2021
2022       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2023       emitcode ("cpl", "c");
2024       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2025       goto release;
2026     }
2027
2028   optype = operandType (IC_LEFT (ic));
2029
2030   /* if float then do float stuff */
2031   if (IS_FLOAT (optype))
2032     {
2033       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2034       goto release;
2035     }
2036
2037   /* otherwise subtract from zero */
2038   size = AOP_SIZE (IC_LEFT (ic));
2039   offset = 0;
2040   _startLazyDPSEvaluation ();
2041   while (size--)
2042     {
2043       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2044       if (!strcmp (l, "a"))
2045         {
2046           if (offset == 0)
2047             SETC;
2048           emitcode ("cpl", "a");
2049           emitcode ("addc", "a,#0");
2050         }
2051       else
2052         {
2053           if (offset == 0)
2054             CLRC;
2055           emitcode ("clr", "a");
2056           emitcode ("subb", "a,%s", l);
2057         }
2058       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2059     }
2060   _endLazyDPSEvaluation ();
2061
2062   /* if any remaining bytes in the result */
2063   /* we just need to propagate the sign   */
2064   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2065     {
2066       emitcode ("rlc", "a");
2067       emitcode ("subb", "a,acc");
2068       while (size--)
2069         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2070     }
2071
2072 release:
2073   /* release the aops */
2074   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2075   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2076 }
2077
2078 /*-----------------------------------------------------------------*/
2079 /* savermask - saves registers in the mask                         */
2080 /*-----------------------------------------------------------------*/
2081 static void savermask(bitVect *rs_mask)
2082 {
2083     int i;
2084     if (options.useXstack) {
2085         if (bitVectBitValue (rs_mask, R0_IDX))
2086             emitcode ("mov", "b,r0");
2087         emitcode ("mov", "r0,%s", spname);
2088         for (i = 0; i < ds390_nRegs; i++) {
2089             if (bitVectBitValue (rs_mask, i)) {
2090                 if (i == R0_IDX)
2091                     emitcode ("mov", "a,b");
2092                 else
2093                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2094                 emitcode ("movx", "@r0,a");
2095                 emitcode ("inc", "r0");
2096             }
2097         }
2098         emitcode ("mov", "%s,r0", spname);
2099         if (bitVectBitValue (rs_mask, R0_IDX))
2100             emitcode ("mov", "r0,b");
2101     } else {
2102         for (i = 0; i < ds390_nRegs; i++) {
2103             if (bitVectBitValue (rs_mask, i))
2104                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2105         }
2106     }
2107 }
2108
2109 /*-----------------------------------------------------------------*/
2110 /* saveRegisters - will look for a call and save the registers     */
2111 /*-----------------------------------------------------------------*/
2112 static void
2113 saveRegisters (iCode * lic)
2114 {
2115   iCode *ic;
2116   bitVect *rsave;
2117
2118   /* look for call */
2119   for (ic = lic; ic; ic = ic->next)
2120     if (ic->op == CALL || ic->op == PCALL)
2121       break;
2122
2123   if (!ic)
2124     {
2125       fprintf (stderr, "found parameter push with no function call\n");
2126       return;
2127     }
2128
2129   /* if the registers have been saved already then
2130      do nothing */
2131   if (ic->regsSaved
2132       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2133     return ;
2134
2135   /* special case if DPTR alive across a function call then must save it
2136      even though callee saves */
2137   if (IS_SYMOP(IC_LEFT(ic)) &&
2138       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2139       int i;
2140       rsave = newBitVect(ic->rMask->size);
2141       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2142           if (bitVectBitValue(ic->rMask,i))
2143               rsave = bitVectSetBit(rsave,i);
2144       }
2145       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2146   } else {
2147     /* safe the registers in use at this time but skip the
2148        ones for the result */
2149     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2150                            ds390_rUmaskForOp (IC_RESULT(ic)));
2151   }
2152   ic->regsSaved = 1;
2153   savermask(rsave);
2154 }
2155
2156 /*-----------------------------------------------------------------*/
2157 /* usavermask - restore registers with mask                        */
2158 /*-----------------------------------------------------------------*/
2159 static void unsavermask(bitVect *rs_mask)
2160 {
2161     int i;
2162     if (options.useXstack) {
2163         emitcode ("mov", "r0,%s", spname);
2164         for (i = ds390_nRegs; i >= 0; i--) {
2165             if (bitVectBitValue (rs_mask, i)) {
2166                 emitcode ("dec", "r0");
2167                 emitcode ("movx", "a,@r0");
2168                 if (i == R0_IDX)
2169                     emitcode ("mov", "b,a");
2170                 else
2171                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2172             }
2173         }
2174         emitcode ("mov", "%s,r0", spname);
2175         if (bitVectBitValue (rs_mask, R0_IDX))
2176             emitcode ("mov", "r0,b");
2177     } else {
2178         for (i = ds390_nRegs; i >= 0; i--) {
2179             if (bitVectBitValue (rs_mask, i))
2180                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2181         }
2182     }
2183 }
2184
2185 /*-----------------------------------------------------------------*/
2186 /* unsaveRegisters - pop the pushed registers                      */
2187 /*-----------------------------------------------------------------*/
2188 static void
2189 unsaveRegisters (iCode * ic)
2190 {
2191   bitVect *rsave;
2192
2193   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2194       int i;
2195       rsave = newBitVect(ic->rMask->size);
2196       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2197           if (bitVectBitValue(ic->rMask,i))
2198               rsave = bitVectSetBit(rsave,i);
2199       }
2200       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2201   } else {
2202     /* restore the registers in use at this time but skip the
2203        ones for the result */
2204     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2205                            ds390_rUmaskForOp (IC_RESULT(ic)));
2206   }
2207   unsavermask(rsave);
2208 }
2209
2210
2211 /*-----------------------------------------------------------------*/
2212 /* pushSide -                */
2213 /*-----------------------------------------------------------------*/
2214 static void
2215 pushSide (operand * oper, int size)
2216 {
2217   int offset = 0;
2218   _startLazyDPSEvaluation ();
2219   while (size--)
2220     {
2221       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2222       if (AOP_TYPE (oper) != AOP_REG &&
2223           AOP_TYPE (oper) != AOP_DIR &&
2224           strcmp (l, "a"))
2225         {
2226           emitcode ("mov", "a,%s", l);
2227           emitcode ("push", "acc");
2228         }
2229       else
2230         emitcode ("push", "%s", l);
2231     }
2232   _endLazyDPSEvaluation ();
2233 }
2234
2235 /*-----------------------------------------------------------------*/
2236 /* assignResultValue -               */
2237 /*-----------------------------------------------------------------*/
2238 static void
2239 assignResultValue (operand * oper)
2240 {
2241   int offset = 0;
2242   int size = AOP_SIZE (oper);
2243   bool pushedAcc = FALSE;
2244
2245   if (size == fReturnSizeDS390)
2246   {
2247       /* I don't think this case can ever happen... */
2248       /* ACC is the last part of this. If writing the result
2249        * uses AC, we must preserve it.
2250        */
2251       if (AOP_NEEDSACC(oper))
2252       {
2253           emitcode(";", "assignResultValue special case for ACC.");
2254           emitcode("push", "acc");
2255           pushedAcc = TRUE;
2256           size--;
2257       }
2258   }
2259
2260
2261   _startLazyDPSEvaluation ();
2262   while (size--)
2263     {
2264       aopPut (AOP (oper), fReturn[offset], offset);
2265       offset++;
2266     }
2267   _endLazyDPSEvaluation ();
2268
2269   if (pushedAcc)
2270     {
2271         emitcode("pop", "acc");
2272         aopPut(AOP(oper), "a", offset);
2273     }
2274 }
2275
2276
2277 /*-----------------------------------------------------------------*/
2278 /* genXpush - pushes onto the external stack                       */
2279 /*-----------------------------------------------------------------*/
2280 static void
2281 genXpush (iCode * ic)
2282 {
2283   asmop *aop = newAsmop (0);
2284   regs *r;
2285   int size, offset = 0;
2286
2287   D (emitcode (";", "genXpush ");
2288     );
2289
2290   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2291   r = getFreePtr (ic, &aop, FALSE);
2292
2293
2294   emitcode ("mov", "%s,_spx", r->name);
2295
2296   size = AOP_SIZE (IC_LEFT (ic));
2297   _startLazyDPSEvaluation ();
2298   while (size--)
2299     {
2300
2301       MOVA (aopGet (AOP (IC_LEFT (ic)),
2302                         offset++, FALSE, FALSE, NULL));
2303       emitcode ("movx", "@%s,a", r->name);
2304       emitcode ("inc", "%s", r->name);
2305
2306     }
2307   _endLazyDPSEvaluation ();
2308
2309
2310   emitcode ("mov", "_spx,%s", r->name);
2311
2312   freeAsmop (NULL, aop, ic, TRUE);
2313   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2314 }
2315
2316 /*-----------------------------------------------------------------*/
2317 /* genIpush - generate code for pushing this gets a little complex  */
2318 /*-----------------------------------------------------------------*/
2319 static void
2320 genIpush (iCode * ic)
2321 {
2322   int size, offset = 0;
2323   char *l;
2324
2325   D (emitcode (";", "genIpush ");
2326     );
2327
2328   /* if this is not a parm push : ie. it is spill push
2329      and spill push is always done on the local stack */
2330   if (!ic->parmPush)
2331     {
2332
2333       /* and the item is spilt then do nothing */
2334       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2335         return;
2336
2337       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2338       size = AOP_SIZE (IC_LEFT (ic));
2339       /* push it on the stack */
2340       _startLazyDPSEvaluation ();
2341       while (size--)
2342         {
2343           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2344           if (*l == '#')
2345             {
2346               MOVA (l);
2347               l = "acc";
2348             }
2349           emitcode ("push", "%s", l);
2350         }
2351       _endLazyDPSEvaluation ();
2352       return;
2353     }
2354
2355   /* this is a paramter push: in this case we call
2356      the routine to find the call and save those
2357      registers that need to be saved */
2358   saveRegisters (ic);
2359
2360   /* if use external stack then call the external
2361      stack pushing routine */
2362   if (options.useXstack)
2363     {
2364       genXpush (ic);
2365       return;
2366     }
2367
2368   /* then do the push */
2369   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2370
2371   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2372   size = AOP_SIZE (IC_LEFT (ic));
2373
2374   _startLazyDPSEvaluation ();
2375   while (size--)
2376     {
2377       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2378       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2379           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2380           strcmp (l, "acc"))
2381         {
2382           emitcode ("mov", "a,%s", l);
2383           emitcode ("push", "acc");
2384         }
2385       else
2386         {
2387             emitcode ("push", "%s", l);
2388         }
2389     }
2390   _endLazyDPSEvaluation ();
2391
2392   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2393 }
2394
2395 /*-----------------------------------------------------------------*/
2396 /* genIpop - recover the registers: can happen only for spilling   */
2397 /*-----------------------------------------------------------------*/
2398 static void
2399 genIpop (iCode * ic)
2400 {
2401   int size, offset;
2402
2403   D (emitcode (";", "genIpop ");
2404     );
2405
2406
2407   /* if the temp was not pushed then */
2408   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2409     return;
2410
2411   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2412   size = AOP_SIZE (IC_LEFT (ic));
2413   offset = (size - 1);
2414   _startLazyDPSEvaluation ();
2415   while (size--)
2416     {
2417       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2418                                      FALSE, TRUE, NULL));
2419     }
2420   _endLazyDPSEvaluation ();
2421
2422   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2423 }
2424
2425 /*-----------------------------------------------------------------*/
2426 /* unsaveRBank - restores the resgister bank from stack            */
2427 /*-----------------------------------------------------------------*/
2428 static void
2429 unsaveRBank (int bank, iCode * ic, bool popPsw)
2430 {
2431   int i;
2432   asmop *aop = NULL;
2433   regs *r = NULL;
2434
2435   if (options.useXstack)
2436   {
2437       if (!ic)
2438       {
2439           /* Assume r0 is available for use. */
2440           r = ds390_regWithIdx (R0_IDX);;
2441       }
2442       else
2443       {
2444           aop = newAsmop (0);
2445           r = getFreePtr (ic, &aop, FALSE);
2446       }
2447       emitcode ("mov", "%s,_spx", r->name);
2448   }
2449
2450   if (popPsw)
2451     {
2452       if (options.useXstack)
2453       {
2454           emitcode ("movx", "a,@%s", r->name);
2455           emitcode ("mov", "psw,a");
2456           emitcode ("dec", "%s", r->name);
2457         }
2458       else
2459       {
2460         emitcode ("pop", "psw");
2461       }
2462     }
2463
2464   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2465     {
2466       if (options.useXstack)
2467         {
2468           emitcode ("movx", "a,@%s", r->name);
2469           emitcode ("mov", "(%s+%d),a",
2470                     regs390[i].base, 8 * bank + regs390[i].offset);
2471           emitcode ("dec", "%s", r->name);
2472
2473         }
2474       else
2475         emitcode ("pop", "(%s+%d)",
2476                   regs390[i].base, 8 * bank + regs390[i].offset);
2477     }
2478
2479   if (options.useXstack)
2480     {
2481       emitcode ("mov", "_spx,%s", r->name);
2482     }
2483
2484   if (aop)
2485   {
2486       freeAsmop (NULL, aop, ic, TRUE);
2487   }
2488 }
2489
2490 /*-----------------------------------------------------------------*/
2491 /* saveRBank - saves an entire register bank on the stack          */
2492 /*-----------------------------------------------------------------*/
2493 static void
2494 saveRBank (int bank, iCode * ic, bool pushPsw)
2495 {
2496   int i;
2497   asmop *aop = NULL;
2498   regs *r = NULL;
2499
2500   if (options.useXstack)
2501     {
2502         if (!ic)
2503         {
2504           /* Assume r0 is available for use. */
2505                   r = ds390_regWithIdx (R0_IDX);;
2506         }
2507         else
2508         {
2509           aop = newAsmop (0);
2510           r = getFreePtr (ic, &aop, FALSE);
2511         }
2512         emitcode ("mov", "%s,_spx", r->name);
2513     }
2514
2515   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2516     {
2517       if (options.useXstack)
2518         {
2519           emitcode ("inc", "%s", r->name);
2520           emitcode ("mov", "a,(%s+%d)",
2521                     regs390[i].base, 8 * bank + regs390[i].offset);
2522           emitcode ("movx", "@%s,a", r->name);
2523         }
2524       else
2525         emitcode ("push", "(%s+%d)",
2526                   regs390[i].base, 8 * bank + regs390[i].offset);
2527     }
2528
2529   if (pushPsw)
2530     {
2531       if (options.useXstack)
2532         {
2533           emitcode ("mov", "a,psw");
2534           emitcode ("movx", "@%s,a", r->name);
2535           emitcode ("inc", "%s", r->name);
2536           emitcode ("mov", "_spx,%s", r->name);
2537         }
2538       else
2539       {
2540         emitcode ("push", "psw");
2541       }
2542
2543       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2544     }
2545
2546   if (aop)
2547   {
2548     freeAsmop (NULL, aop, ic, TRUE);
2549   }
2550
2551   if (ic)
2552   {
2553     ic->bankSaved = 1;
2554   }
2555 }
2556
2557 /*-----------------------------------------------------------------*/
2558 /* genSend - gen code for SEND                                     */
2559 /*-----------------------------------------------------------------*/
2560 static void genSend(set *sendSet)
2561 {
2562     iCode *sic;
2563     int sendCount = 0 ;
2564     static int rb1_count = 0;
2565
2566     for (sic = setFirstItem (sendSet); sic;
2567          sic = setNextItem (sendSet)) {
2568         int size, offset = 0;
2569
2570         size=getSize(operandType(IC_LEFT(sic)));
2571         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2572         if (sendCount == 0) { /* first parameter */
2573             // we know that dpl(hxb) is the result, so
2574             rb1_count = 0 ;
2575             _startLazyDPSEvaluation ();
2576             if (size>1) {
2577                 aopOp (IC_LEFT (sic), sic, FALSE,
2578                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2579             } else {
2580                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2581             }
2582             while (size--) {
2583                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2584                                   FALSE, FALSE, NULL);
2585                 if (strcmp (l, fReturn[offset])) {
2586                     emitcode ("mov", "%s,%s",
2587                               fReturn[offset],
2588                               l);
2589                 }
2590                 offset++;
2591             }
2592             _endLazyDPSEvaluation ();
2593             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2594             rb1_count =0;
2595         } else { /* if more parameter in registers */
2596             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2597             while (size--) {
2598                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2599                                                                 FALSE, FALSE, NULL));
2600             }
2601             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2602         }
2603         sendCount++;
2604     }
2605 }
2606
2607 static void
2608 adjustEsp(const char *reg)
2609 {
2610     emitcode ("anl","%s,#3", reg);
2611     if (TARGET_IS_DS400)
2612     {
2613         emitcode ("orl","%s,#!constbyte",
2614                   reg,
2615                   (options.stack_loc >> 8) & 0xff);
2616     }
2617 }
2618
2619 /*-----------------------------------------------------------------*/
2620 /* genCall - generates a call statement                            */
2621 /*-----------------------------------------------------------------*/
2622 static void
2623 genCall (iCode * ic)
2624 {
2625   sym_link *dtype;
2626   bool restoreBank = FALSE;
2627   bool swapBanks = FALSE;
2628
2629   D (emitcode (";", "genCall "););
2630
2631   /* if we are calling a not _naked function that is not using
2632      the same register bank then we need to save the
2633      destination registers on the stack */
2634   dtype = operandType (IC_LEFT (ic));
2635   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2636       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2637       IFFUNC_ISISR (currFunc->type))
2638   {
2639       if (!ic->bankSaved)
2640       {
2641            /* This is unexpected; the bank should have been saved in
2642             * genFunction.
2643             */
2644            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2645            restoreBank = TRUE;
2646       }
2647       swapBanks = TRUE;
2648   }
2649
2650     /* if caller saves & we have not saved then */
2651     if (!ic->regsSaved)
2652       saveRegisters (ic);
2653
2654   /* if send set is not empty then assign */
2655   /* We've saved all the registers we care about;
2656   * therefore, we may clobber any register not used
2657   * in the calling convention (i.e. anything not in
2658   * fReturn.
2659   */
2660   if (_G.sendSet)
2661     {
2662         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2663             genSend(reverseSet(_G.sendSet));
2664         } else {
2665             genSend(_G.sendSet);
2666         }
2667       _G.sendSet = NULL;
2668     }
2669
2670   if (swapBanks)
2671   {
2672         emitcode ("mov", "psw,#!constbyte",
2673            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2674   }
2675
2676   /* make the call */
2677   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2678                             OP_SYMBOL (IC_LEFT (ic))->rname :
2679                             OP_SYMBOL (IC_LEFT (ic))->name));
2680
2681   if (swapBanks)
2682   {
2683        emitcode ("mov", "psw,#!constbyte",
2684           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2685   }
2686
2687   /* if we need assign a result value */
2688   if ((IS_ITEMP (IC_RESULT (ic)) &&
2689        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2690         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2691         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2692       IS_TRUE_SYMOP (IC_RESULT (ic)))
2693     {
2694       if (isOperandInFarSpace (IC_RESULT (ic))
2695           && getSize (operandType (IC_RESULT (ic))) <= 2)
2696         {
2697           int size = getSize (operandType (IC_RESULT (ic)));
2698
2699           /* Special case for 1 or 2 byte return in far space. */
2700           MOVA (fReturn[0]);
2701           if (size > 1)
2702             {
2703               emitcode ("mov", "b,%s", fReturn[1]);
2704               _G.bInUse++;
2705             }
2706
2707           _G.accInUse++;
2708           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2709           _G.accInUse--;
2710
2711           if (size > 1)
2712             _G.bInUse--;
2713
2714           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2715
2716           if (size > 1)
2717             {
2718               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2719             }
2720           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2721         }
2722       else
2723         {
2724           _G.bInUse++;
2725           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2726           _G.bInUse--;
2727
2728           assignResultValue (IC_RESULT (ic));
2729
2730           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2731         }
2732     }
2733
2734   /* adjust the stack for parameters if
2735      required */
2736   if (ic->parmBytes) {
2737       int i;
2738       if (options.stack10bit) {
2739           if (ic->parmBytes <= 10) {
2740               emitcode(";","stack adjustment for parms");
2741               for (i=0; i < ic->parmBytes ; i++) {
2742                   emitcode("pop","acc");
2743               }
2744           } else {
2745               PROTECT_SP;
2746               emitcode ("clr","c");
2747               emitcode ("mov","a,sp");
2748               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2749               emitcode ("mov","sp,a");
2750               emitcode ("mov","a,esp");
2751               adjustEsp("a");
2752               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2753               emitcode ("mov","esp,a");
2754               UNPROTECT_SP;
2755           }
2756       } else {
2757           if (ic->parmBytes > 3) {
2758               emitcode ("mov", "a,%s", spname);
2759               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2760               emitcode ("mov", "%s,a", spname);
2761           } else
2762               for (i = 0; i < ic->parmBytes; i++)
2763                   emitcode ("dec", "%s", spname);
2764       }
2765   }
2766
2767   /* if we hade saved some registers then unsave them */
2768   if (ic->regsSaved)
2769     unsaveRegisters (ic);
2770
2771   /* if register bank was saved then pop them */
2772   if (restoreBank)
2773     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2774 }
2775
2776 /*-----------------------------------------------------------------*/
2777 /* genPcall - generates a call by pointer statement                */
2778 /*-----------------------------------------------------------------*/
2779 static void
2780 genPcall (iCode * ic)
2781 {
2782   sym_link *dtype;
2783   symbol *rlbl = newiTempLabel (NULL);
2784   bool restoreBank=FALSE;
2785
2786   D (emitcode (";", "genPcall ");
2787     );
2788
2789
2790   /* if caller saves & we have not saved then */
2791   if (!ic->regsSaved)
2792     saveRegisters (ic);
2793
2794   /* if we are calling a function that is not using
2795      the same register bank then we need to save the
2796      destination registers on the stack */
2797   dtype = operandType (IC_LEFT (ic));
2798   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2799       IFFUNC_ISISR (currFunc->type) &&
2800       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2801     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2802     restoreBank=TRUE;
2803   }
2804
2805   /* push the return address on to the stack */
2806   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2807   emitcode ("push", "acc");
2808   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2809   emitcode ("push", "acc");
2810
2811   if (options.model == MODEL_FLAT24)
2812     {
2813       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2814       emitcode ("push", "acc");
2815     }
2816
2817   /* now push the calling address */
2818   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2819
2820   pushSide (IC_LEFT (ic), FPTRSIZE);
2821
2822   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2823
2824   /* if send set is not empty the assign */
2825   if (_G.sendSet)
2826     {
2827         genSend(reverseSet(_G.sendSet));
2828         _G.sendSet = NULL;
2829     }
2830
2831   emitcode ("ret", "");
2832   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2833
2834
2835   /* if we need assign a result value */
2836   if ((IS_ITEMP (IC_RESULT (ic)) &&
2837        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2838         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2839       IS_TRUE_SYMOP (IC_RESULT (ic)))
2840     {
2841
2842       _G.accInUse++;
2843       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2844       _G.accInUse--;
2845
2846       assignResultValue (IC_RESULT (ic));
2847
2848       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2849     }
2850
2851   /* adjust the stack for parameters if
2852      required */
2853   if (ic->parmBytes)
2854     {
2855       int i;
2856       if (options.stack10bit) {
2857           if (ic->parmBytes <= 10) {
2858               emitcode(";","stack adjustment for parms");
2859               for (i=0; i < ic->parmBytes ; i++) {
2860                   emitcode("pop","acc");
2861               }
2862           } else {
2863               PROTECT_SP;
2864               emitcode ("clr","c");
2865               emitcode ("mov","a,sp");
2866               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2867               emitcode ("mov","sp,a");
2868               emitcode ("mov","a,esp");
2869               adjustEsp("a");
2870               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2871               emitcode ("mov","esp,a");
2872               UNPROTECT_SP;
2873           }
2874       } else {
2875           if (ic->parmBytes > 3) {
2876               emitcode ("mov", "a,%s", spname);
2877               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2878               emitcode ("mov", "%s,a", spname);
2879           }
2880           else
2881               for (i = 0; i < ic->parmBytes; i++)
2882                   emitcode ("dec", "%s", spname);
2883
2884       }
2885     }
2886   /* if register bank was saved then unsave them */
2887   if (restoreBank)
2888     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2889
2890   /* if we hade saved some registers then
2891      unsave them */
2892   if (ic->regsSaved)
2893     unsaveRegisters (ic);
2894
2895 }
2896
2897 /*-----------------------------------------------------------------*/
2898 /* resultRemat - result  is rematerializable                       */
2899 /*-----------------------------------------------------------------*/
2900 static int
2901 resultRemat (iCode * ic)
2902 {
2903   if (SKIP_IC (ic) || ic->op == IFX)
2904     return 0;
2905
2906   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2907     {
2908       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2909       if (sym->remat && !POINTER_SET (ic))
2910         return 1;
2911     }
2912
2913   return 0;
2914 }
2915
2916 #if defined(__BORLANDC__) || defined(_MSC_VER)
2917 #define STRCASECMP stricmp
2918 #else
2919 #define STRCASECMP strcasecmp
2920 #endif
2921
2922 /*-----------------------------------------------------------------*/
2923 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2924 /*-----------------------------------------------------------------*/
2925 static int
2926 regsCmp(void *p1, void *p2)
2927 {
2928   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2929 }
2930
2931 static bool
2932 inExcludeList (char *s)
2933 {
2934   const char *p = setFirstItem(options.excludeRegsSet);
2935
2936   if (p == NULL || STRCASECMP(p, "none") == 0)
2937     return FALSE;
2938
2939
2940   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2941 }
2942
2943 /*-----------------------------------------------------------------*/
2944 /* genFunction - generated code for function entry                 */
2945 /*-----------------------------------------------------------------*/
2946 static void
2947 genFunction (iCode * ic)
2948 {
2949   symbol *sym;
2950   sym_link *ftype;
2951   bool   switchedPSW = FALSE;
2952
2953   D (emitcode (";", "genFunction "););
2954
2955   _G.nRegsSaved = 0;
2956   /* create the function header */
2957   emitcode (";", "-----------------------------------------");
2958   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2959   emitcode (";", "-----------------------------------------");
2960
2961   emitcode ("", "%s:", sym->rname);
2962   ftype = operandType (IC_LEFT (ic));
2963
2964   if (IFFUNC_ISNAKED(ftype))
2965   {
2966       emitcode(";", "naked function: no prologue.");
2967       return;
2968   }
2969
2970   if (options.stack_probe)
2971       emitcode ("lcall","__stack_probe");
2972
2973   /* here we need to generate the equates for the
2974      register bank if required */
2975   if (FUNC_REGBANK (ftype) != rbank)
2976     {
2977       int i;
2978
2979       rbank = FUNC_REGBANK (ftype);
2980       for (i = 0; i < ds390_nRegs; i++)
2981         {
2982           if (regs390[i].print) {
2983               if (strcmp (regs390[i].base, "0") == 0)
2984                   emitcode ("", "%s !equ !constbyte",
2985                             regs390[i].dname,
2986                             8 * rbank + regs390[i].offset);
2987               else
2988                   emitcode ("", "%s !equ %s + !constbyte",
2989                             regs390[i].dname,
2990                             regs390[i].base,
2991                             8 * rbank + regs390[i].offset);
2992           }
2993         }
2994     }
2995
2996   /* if this is an interrupt service routine then
2997      save acc, b, dpl, dph  */
2998   if (IFFUNC_ISISR (sym->type))
2999       { /* is ISR */
3000       if (!inExcludeList ("acc"))
3001         emitcode ("push", "acc");
3002       if (!inExcludeList ("b"))
3003         emitcode ("push", "b");
3004       if (!inExcludeList ("dpl"))
3005         emitcode ("push", "dpl");
3006       if (!inExcludeList ("dph"))
3007         emitcode ("push", "dph");
3008       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3009         {
3010           emitcode ("push", "dpx");
3011           /* Make sure we're using standard DPTR */
3012           emitcode ("push", "dps");
3013           emitcode ("mov", "dps,#0");
3014           if (options.stack10bit)
3015             {
3016               /* This ISR could conceivably use DPTR2. Better save it. */
3017               emitcode ("push", "dpl1");
3018               emitcode ("push", "dph1");
3019               emitcode ("push", "dpx1");
3020               emitcode ("push",  DP2_RESULT_REG);
3021             }
3022         }
3023       /* if this isr has no bank i.e. is going to
3024          run with bank 0 , then we need to save more
3025          registers :-) */
3026       if (!FUNC_REGBANK (sym->type))
3027         {
3028             int i;
3029
3030           /* if this function does not call any other
3031              function then we can be economical and
3032              save only those registers that are used */
3033           if (!IFFUNC_HASFCALL(sym->type))
3034             {
3035
3036               /* if any registers used */
3037               if (sym->regsUsed)
3038                 {
3039                   /* save the registers used */
3040                   for (i = 0; i < sym->regsUsed->size; i++)
3041                     {
3042                       if (bitVectBitValue (sym->regsUsed, i))
3043                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3044                     }
3045                 }
3046             }
3047           else
3048             {
3049               /* this function has  a function call cannot
3050                  determines register usage so we will have to push the
3051                  entire bank */
3052               saveRBank (0, ic, FALSE);
3053               if (options.parms_in_bank1) {
3054                   for (i=0; i < 8 ; i++ ) {
3055                       emitcode ("push","%s",rb1regs[i]);
3056                   }
3057               }
3058             }
3059         }
3060         else
3061         {
3062             /* This ISR uses a non-zero bank.
3063              *
3064              * We assume that the bank is available for our
3065              * exclusive use.
3066              *
3067              * However, if this ISR calls a function which uses some
3068              * other bank, we must save that bank entirely.
3069              */
3070             unsigned long banksToSave = 0;
3071
3072             if (IFFUNC_HASFCALL(sym->type))
3073             {
3074
3075 #define MAX_REGISTER_BANKS 4
3076
3077                 iCode *i;
3078                 int ix;
3079
3080                 for (i = ic; i; i = i->next)
3081                 {
3082                     if (i->op == ENDFUNCTION)
3083                     {
3084                         /* we got to the end OK. */
3085                         break;
3086                     }
3087
3088                     if (i->op == CALL)
3089                     {
3090                         sym_link *dtype;
3091
3092                         dtype = operandType (IC_LEFT(i));
3093                         if (dtype
3094                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3095                         {
3096                              /* Mark this bank for saving. */
3097                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3098                              {
3099                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3100                              }
3101                              else
3102                              {
3103                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3104                              }
3105
3106                              /* And note that we don't need to do it in
3107                               * genCall.
3108                               */
3109                              i->bankSaved = 1;
3110                         }
3111                     }
3112                     if (i->op == PCALL)
3113                     {
3114                         /* This is a mess; we have no idea what
3115                          * register bank the called function might
3116                          * use.
3117                          *
3118                          * The only thing I can think of to do is
3119                          * throw a warning and hope.
3120                          */
3121                         werror(W_FUNCPTR_IN_USING_ISR);
3122                     }
3123                 }
3124
3125                 if (banksToSave && options.useXstack)
3126                 {
3127                     /* Since we aren't passing it an ic,
3128                      * saveRBank will assume r0 is available to abuse.
3129                      *
3130                      * So switch to our (trashable) bank now, so
3131                      * the caller's R0 isn't trashed.
3132                      */
3133                     emitcode ("push", "psw");
3134                     emitcode ("mov", "psw,#!constbyte",
3135                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3136                     switchedPSW = TRUE;
3137                 }
3138
3139                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3140                 {
3141                      if (banksToSave & (1 << ix))
3142                      {
3143                          saveRBank(ix, NULL, FALSE);
3144                      }
3145                 }
3146             }
3147             // TODO: this needs a closer look
3148             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3149         }
3150     }
3151   else
3152     {
3153       /* if callee-save to be used for this function
3154          then save the registers being used in this function */
3155       if (IFFUNC_CALLEESAVES(sym->type))
3156         {
3157           int i;
3158
3159           /* if any registers used */
3160           if (sym->regsUsed)
3161             {
3162               /* save the registers used */
3163               for (i = 0; i < sym->regsUsed->size; i++)
3164                 {
3165                   if (bitVectBitValue (sym->regsUsed, i))
3166                     {
3167                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3168                       _G.nRegsSaved++;
3169                     }
3170                 }
3171             }
3172         }
3173     }
3174
3175   /* set the register bank to the desired value */
3176   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3177    && !switchedPSW)
3178     {
3179       emitcode ("push", "psw");
3180       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3181     }
3182
3183   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3184        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3185       if (options.stack10bit) {
3186           emitcode ("push","_bpx");
3187           emitcode ("push","_bpx+1");
3188           emitcode ("mov","_bpx,%s",spname);
3189           emitcode ("mov","_bpx+1,esp");
3190           adjustEsp("_bpx+1");
3191       } else {
3192           if (options.useXstack) {
3193               emitcode ("mov", "r0,%s", spname);
3194               emitcode ("mov", "a,_bp");
3195               emitcode ("movx", "@r0,a");
3196               emitcode ("inc", "%s", spname);
3197           } else {
3198               /* set up the stack */
3199               emitcode ("push", "_bp"); /* save the callers stack  */
3200           }
3201           emitcode ("mov", "_bp,%s", spname);
3202       }
3203   }
3204
3205   /* adjust the stack for the function */
3206   if (sym->stack) {
3207       int i = sym->stack;
3208       if (options.stack10bit) {
3209           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3210           assert (sym->recvSize <= 4);
3211           if (sym->stack <= 8) {
3212               while (i--) emitcode ("push","acc");
3213           } else {
3214               PROTECT_SP;
3215               emitcode ("mov","a,sp");
3216               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3217               emitcode ("mov","sp,a");
3218               emitcode ("mov","a,esp");
3219               adjustEsp("a");
3220               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3221               emitcode ("mov","esp,a");
3222               UNPROTECT_SP;
3223           }
3224       } else {
3225           if (i > 256)
3226               werror (W_STACK_OVERFLOW, sym->name);
3227
3228           if (i > 3 && sym->recvSize < 4) {
3229
3230               emitcode ("mov", "a,sp");
3231               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3232               emitcode ("mov", "sp,a");
3233
3234           } else
3235               while (i--)
3236                   emitcode ("inc", "sp");
3237       }
3238   }
3239
3240   if (sym->xstack)
3241     {
3242
3243       emitcode ("mov", "a,_spx");
3244       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3245       emitcode ("mov", "_spx,a");
3246     }
3247
3248   /* if critical function then turn interrupts off */
3249   if (IFFUNC_ISCRITICAL (ftype))
3250     {
3251       symbol *tlbl = newiTempLabel (NULL);
3252       emitcode ("setb", "c");
3253       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3254       emitcode ("clr", "c");
3255       emitcode ("", "%05d$:", (tlbl->key + 100));
3256       emitcode ("push", "psw"); /* save old ea via c in psw */
3257     }
3258
3259 }
3260
3261 /*-----------------------------------------------------------------*/
3262 /* genEndFunction - generates epilogue for functions               */
3263 /*-----------------------------------------------------------------*/
3264 static void
3265 genEndFunction (iCode * ic)
3266 {
3267   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3268   lineNode *lnp = lineCurr;
3269   bitVect *regsUsed;
3270   bitVect *regsUsedPrologue;
3271   bitVect *regsUnneeded;
3272   int idx;
3273
3274   D (emitcode (";", "genEndFunction "););
3275
3276   if (IFFUNC_ISNAKED(sym->type))
3277   {
3278       emitcode(";", "naked function: no epilogue.");
3279       if (options.debug && currFunc)
3280         debugFile->writeEndFunction (currFunc, ic, 0);
3281       return;
3282   }
3283
3284   if (IFFUNC_ISCRITICAL (sym->type))
3285     {
3286       emitcode ("pop", "psw"); /* restore ea via c in psw */
3287       emitcode ("mov", "ea,c");
3288     }
3289
3290   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3291        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3292
3293       if (options.stack10bit) {
3294           PROTECT_SP;
3295           emitcode ("mov", "sp,_bpx", spname);
3296           emitcode ("mov", "esp,_bpx+1", spname);
3297           UNPROTECT_SP;
3298       } else {
3299           emitcode ("mov", "%s,_bp", spname);
3300       }
3301   }
3302
3303   /* if use external stack but some variables were
3304      added to the local stack then decrement the
3305      local stack */
3306   if (options.useXstack && sym->stack) {
3307       emitcode ("mov", "a,sp");
3308       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3309       emitcode ("mov", "sp,a");
3310   }
3311
3312
3313   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3314        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3315
3316       if (options.useXstack) {
3317           emitcode ("mov", "r0,%s", spname);
3318           emitcode ("movx", "a,@r0");
3319           emitcode ("mov", "_bp,a");
3320           emitcode ("dec", "%s", spname);
3321       } else {
3322           if (options.stack10bit) {
3323               emitcode ("pop", "_bpx+1");
3324               emitcode ("pop", "_bpx");
3325           } else {
3326               emitcode ("pop", "_bp");
3327           }
3328       }
3329   }
3330
3331   /* restore the register bank  */
3332   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3333   {
3334     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3335      || !options.useXstack)
3336     {
3337         /* Special case of ISR using non-zero bank with useXstack
3338          * is handled below.
3339          */
3340         emitcode ("pop", "psw");
3341     }
3342   }
3343
3344   if (IFFUNC_ISISR (sym->type))
3345       { /* is ISR */
3346
3347       /* now we need to restore the registers */
3348       /* if this isr has no bank i.e. is going to
3349          run with bank 0 , then we need to save more
3350          registers :-) */
3351       if (!FUNC_REGBANK (sym->type))
3352         {
3353             int i;
3354           /* if this function does not call any other
3355              function then we can be economical and
3356              save only those registers that are used */
3357           if (!IFFUNC_HASFCALL(sym->type))
3358             {
3359
3360               /* if any registers used */
3361               if (sym->regsUsed)
3362                 {
3363                   /* save the registers used */
3364                   for (i = sym->regsUsed->size; i >= 0; i--)
3365                     {
3366                       if (bitVectBitValue (sym->regsUsed, i))
3367                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3368                     }
3369                 }
3370             }
3371           else
3372             {
3373               /* this function has  a function call cannot
3374                  determines register usage so we will have to pop the
3375                  entire bank */
3376               if (options.parms_in_bank1) {
3377                   for (i = 7 ; i >= 0 ; i-- ) {
3378                       emitcode ("pop","%s",rb1regs[i]);
3379                   }
3380               }
3381               unsaveRBank (0, ic, FALSE);
3382             }
3383         }
3384         else
3385         {
3386             /* This ISR uses a non-zero bank.
3387              *
3388              * Restore any register banks saved by genFunction
3389              * in reverse order.
3390              */
3391             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3392             int ix;
3393
3394             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3395             {
3396                 if (savedBanks & (1 << ix))
3397                 {
3398                     unsaveRBank(ix, NULL, FALSE);
3399                 }
3400             }
3401
3402             if (options.useXstack)
3403             {
3404                 /* Restore bank AFTER calling unsaveRBank,
3405                  * since it can trash r0.
3406                  */
3407                 emitcode ("pop", "psw");
3408             }
3409         }
3410
3411       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3412         {
3413           if (options.stack10bit)
3414             {
3415               emitcode ("pop", DP2_RESULT_REG);
3416               emitcode ("pop", "dpx1");
3417               emitcode ("pop", "dph1");
3418               emitcode ("pop", "dpl1");
3419             }
3420           emitcode ("pop", "dps");
3421           emitcode ("pop", "dpx");
3422         }
3423       if (!inExcludeList ("dph"))
3424         emitcode ("pop", "dph");
3425       if (!inExcludeList ("dpl"))
3426         emitcode ("pop", "dpl");
3427       if (!inExcludeList ("b"))
3428         emitcode ("pop", "b");
3429       if (!inExcludeList ("acc"))
3430         emitcode ("pop", "acc");
3431
3432       /* if debug then send end of function */
3433       if (options.debug && currFunc) {
3434           debugFile->writeEndFunction (currFunc, ic, 1);
3435         }
3436
3437       emitcode ("reti", "");
3438     }
3439   else
3440     {
3441       if (IFFUNC_CALLEESAVES(sym->type))
3442         {
3443           int i;
3444
3445           /* if any registers used */
3446           if (sym->regsUsed)
3447             {
3448               /* save the registers used */
3449               for (i = sym->regsUsed->size; i >= 0; i--)
3450                 {
3451                   if (bitVectBitValue (sym->regsUsed, i))
3452                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3453                 }
3454             }
3455         }
3456
3457       /* if debug then send end of function */
3458       if (options.debug && currFunc)
3459         {
3460           debugFile->writeEndFunction (currFunc, ic, 1);
3461         }
3462
3463       emitcode ("ret", "");
3464     }
3465
3466   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3467     return;
3468
3469   /* If this was an interrupt handler using bank 0 that called another */
3470   /* function, then all registers must be saved; nothing to optimized. */
3471   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3472       && !FUNC_REGBANK(sym->type))
3473     return;
3474
3475   /* There are no push/pops to optimize if not callee-saves or ISR */
3476   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3477     return;
3478
3479   /* If there were stack parameters, we cannot optimize without also    */
3480   /* fixing all of the stack offsets; this is too dificult to consider. */
3481   if (FUNC_HASSTACKPARM(sym->type))
3482     return;
3483
3484   /* Compute the registers actually used */
3485   regsUsed = newBitVect (ds390_nRegs);
3486   regsUsedPrologue = newBitVect (ds390_nRegs);
3487   while (lnp)
3488     {
3489       if (lnp->ic && lnp->ic->op == FUNCTION)
3490         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3491       else
3492         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3493
3494       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3495           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3496         break;
3497       if (!lnp->prev)
3498         break;
3499       lnp = lnp->prev;
3500     }
3501
3502   if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3503       && !bitVectBitValue (regsUsed, DPS_IDX))
3504     {
3505       bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3506     }
3507
3508   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3509       && !bitVectBitValue (regsUsed, CND_IDX))
3510     {
3511       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3512       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3513           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3514         bitVectUnSetBit (regsUsed, CND_IDX);
3515     }
3516   else
3517     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3518
3519   /* If this was an interrupt handler that called another function */
3520   /* function, then assume working registers may be modified by it. */
3521   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3522     {
3523       regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3524       regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3525       regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3526       regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3527       regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3528       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3529       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3530       regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3531       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3532       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3533       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3534     }
3535
3536   /* Remove the unneeded push/pops */
3537   regsUnneeded = newBitVect (ds390_nRegs);
3538   while (lnp)
3539     {
3540       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3541         {
3542           if (!strncmp(lnp->line, "push", 4))
3543             {
3544               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3545               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3546                 {
3547                   connectLine (lnp->prev, lnp->next);
3548                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3549                 }
3550             }
3551           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3552             {
3553               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3554               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3555                 {
3556                   connectLine (lnp->prev, lnp->next);
3557                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3558                 }
3559             }
3560         }
3561       lnp = lnp->next;
3562     }
3563
3564   for (idx = 0; idx < regsUnneeded->size; idx++)
3565     if (bitVectBitValue (regsUnneeded, idx))
3566       emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3567
3568   freeBitVect (regsUnneeded);
3569   freeBitVect (regsUsed);
3570   freeBitVect (regsUsedPrologue);
3571 }
3572
3573 /*-----------------------------------------------------------------*/
3574 /* genJavaNativeRet - generate code for return JavaNative          */
3575 /*-----------------------------------------------------------------*/
3576 static void genJavaNativeRet(iCode *ic)
3577 {
3578     int i, size;
3579
3580     aopOp (IC_LEFT (ic), ic, FALSE,
3581            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3582     size = AOP_SIZE (IC_LEFT (ic));
3583
3584     assert (size <= 4);
3585
3586     /* it is assigned to GPR0-R3 then push them */
3587     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3588         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3589         for (i = 0 ; i < size ; i++ ) {
3590             emitcode ("push","%s",
3591                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3592         }
3593         for (i = (size-1) ; i >= 0 ; i--) {
3594             emitcode ("pop","a%s",javaRet[i]);
3595         }
3596     } else {
3597         for (i = 0 ; i < size ; i++)
3598             emitcode ("mov","%s,%s",javaRet[i],
3599                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3600     }
3601     for (i = size ; i < 4 ; i++ )
3602             emitcode ("mov","%s,#0",javaRet[i]);
3603     return;
3604 }
3605
3606 /*-----------------------------------------------------------------*/
3607 /* genRet - generate code for return statement                     */
3608 /*-----------------------------------------------------------------*/
3609 static void
3610 genRet (iCode * ic)
3611 {
3612   int size, offset = 0, pushed = 0;
3613
3614   D (emitcode (";", "genRet "););
3615
3616   /* if we have no return value then
3617      just generate the "ret" */
3618   if (!IC_LEFT (ic))
3619     goto jumpret;
3620
3621   /* if this is a JavaNative function then return
3622      value in different register */
3623   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3624       genJavaNativeRet(ic);
3625       goto jumpret;
3626   }
3627   /* we have something to return then
3628      move the return value into place */
3629   aopOp (IC_LEFT (ic), ic, FALSE,
3630          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3631   size = AOP_SIZE (IC_LEFT (ic));
3632
3633   _startLazyDPSEvaluation ();
3634   while (size--)
3635     {
3636       char *l;
3637       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3638         {
3639           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3640                       FALSE, TRUE, NULL);
3641           emitcode ("push", "%s", l);
3642           pushed++;
3643         }
3644       else
3645         {
3646           /* Since A is the last element of fReturn,
3647            * is is OK to clobber it in the aopGet.
3648            */
3649           l = aopGet (AOP (IC_LEFT (ic)), offset,
3650                       FALSE, FALSE, NULL);
3651           if (strcmp (fReturn[offset], l))
3652             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3653         }
3654     }
3655   _endLazyDPSEvaluation ();
3656
3657   if (pushed)
3658     {
3659       while (pushed)
3660         {
3661           pushed--;
3662           if (strcmp (fReturn[pushed], "a"))
3663             emitcode ("pop", fReturn[pushed]);
3664           else
3665             emitcode ("pop", "acc");
3666         }
3667     }
3668   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3669
3670 jumpret:
3671   /* generate a jump to the return label
3672      if the next is not the return statement */
3673   if (!(ic->next && ic->next->op == LABEL &&
3674         IC_LABEL (ic->next) == returnLabel))
3675
3676     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3677
3678 }
3679
3680 /*-----------------------------------------------------------------*/
3681 /* genLabel - generates a label                                    */
3682 /*-----------------------------------------------------------------*/
3683 static void
3684 genLabel (iCode * ic)
3685 {
3686   /* special case never generate */
3687   if (IC_LABEL (ic) == entryLabel)
3688     return;
3689
3690   D (emitcode (";", "genLabel ");
3691     );
3692
3693   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3694 }
3695
3696 /*-----------------------------------------------------------------*/
3697 /* genGoto - generates a ljmp                                      */
3698 /*-----------------------------------------------------------------*/
3699 static void
3700 genGoto (iCode * ic)
3701 {
3702   D (emitcode (";", "genGoto ");
3703     );
3704   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3705 }
3706
3707 /*-----------------------------------------------------------------*/
3708 /* findLabelBackwards: walks back through the iCode chain looking  */
3709 /* for the given label. Returns number of iCode instructions     */
3710 /* between that label and given ic.          */
3711 /* Returns zero if label not found.          */
3712 /*-----------------------------------------------------------------*/
3713 static int
3714 findLabelBackwards (iCode * ic, int key)
3715 {
3716   int count = 0;
3717
3718   while (ic->prev)
3719     {
3720       ic = ic->prev;
3721       count++;
3722
3723       /* If we have any pushes or pops, we cannot predict the distance.
3724          I don't like this at all, this should be dealt with in the
3725          back-end */
3726       if (ic->op == IPUSH || ic->op == IPOP) {
3727         return 0;
3728       }
3729
3730       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3731         {
3732           /* printf("findLabelBackwards = %d\n", count); */
3733           return count;
3734         }
3735     }
3736
3737   return 0;
3738 }
3739
3740 /*-----------------------------------------------------------------*/
3741 /* genPlusIncr :- does addition with increment if possible         */
3742 /*-----------------------------------------------------------------*/
3743 static bool
3744 genPlusIncr (iCode * ic)
3745 {
3746   unsigned int icount;
3747   unsigned int size = getDataSize (IC_RESULT (ic));
3748
3749   /* will try to generate an increment */
3750   /* if the right side is not a literal
3751      we cannot */
3752   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3753     return FALSE;
3754
3755   /* if the literal value of the right hand side
3756      is greater than 4 then it is not worth it */
3757   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3758     return FALSE;
3759
3760   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3761       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3762       while (icount--) {
3763           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3764       }
3765       return TRUE;
3766   }
3767   /* if increment 16 bits in register */
3768   if (
3769        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3770        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3771        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3772        (size > 1) &&
3773        (icount == 1))
3774     {
3775       symbol  *tlbl;
3776       int     emitTlbl;
3777       int     labelRange;
3778       char    *l;
3779
3780       /* If the next instruction is a goto and the goto target
3781        * is <= 5 instructions previous to this, we can generate
3782        * jumps straight to that target.
3783        */
3784       if (ic->next && ic->next->op == GOTO
3785           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3786           && labelRange <= 5)
3787         {
3788           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3789           tlbl = IC_LABEL (ic->next);
3790           emitTlbl = 0;
3791         }
3792       else
3793         {
3794           tlbl = newiTempLabel (NULL);
3795           emitTlbl = 1;
3796         }
3797
3798       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3799       emitcode ("inc", "%s", l);
3800
3801       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3802           IS_AOP_PREG (IC_RESULT (ic)))
3803         {
3804           emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3805         }
3806       else
3807         {
3808           emitcode ("clr", "a");
3809           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3810         }
3811
3812       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3813       emitcode ("inc", "%s", l);
3814       if (size > 2)
3815         {
3816           if (!strcmp(l, "acc"))
3817             {
3818                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3819             }
3820           else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3821                    IS_AOP_PREG (IC_RESULT (ic)))
3822             {
3823                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3824             }
3825           else
3826             {
3827                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3828             }
3829
3830           l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3831           emitcode ("inc", "%s", l);
3832         }
3833       if (size > 3)
3834         {
3835           if (!strcmp(l, "acc"))
3836             {
3837                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3838             }
3839           else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3840                    IS_AOP_PREG (IC_RESULT (ic)))
3841             {
3842                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3843             }
3844           else
3845             {
3846                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3847             }
3848
3849           l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3850           emitcode ("inc", "%s", l);
3851         }
3852
3853       if (emitTlbl)
3854         {
3855           emitcode ("", "!tlabeldef", tlbl->key + 100);
3856         }
3857       return TRUE;
3858     }
3859
3860   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3861       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3862       options.model == MODEL_FLAT24 )
3863     {
3864       if (IC_RESULT(ic)->isGptr)
3865         {
3866           emitcode ("mov","b,%s",aopGet(AOP (IC_LEFT (ic)), 3, FALSE, FALSE, NULL));
3867         }
3868       switch (size) {
3869       case 3:
3870           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3871       case 2:
3872           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3873       case 1:
3874           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3875           break;
3876       }
3877       while (icount--) emitcode ("inc","dptr");
3878       return TRUE;
3879   }
3880
3881   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3882       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3883       icount <= 5 ) {
3884       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3885       while (icount--) emitcode ("inc","dptr");
3886       emitcode ("mov","dps,#0");
3887       return TRUE;
3888   }
3889
3890   /* if the sizes are greater than 1 then we cannot */
3891   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3892       AOP_SIZE (IC_LEFT (ic)) > 1)
3893     return FALSE;
3894
3895   /* we can if the aops of the left & result match or
3896      if they are in registers and the registers are the
3897      same */
3898   if (
3899        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3900        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3901        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3902     {
3903
3904       if (icount > 3)
3905         {
3906           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3907           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3908           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3909         }
3910       else
3911         {
3912
3913           _startLazyDPSEvaluation ();
3914           while (icount--)
3915             {
3916               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3917             }
3918           _endLazyDPSEvaluation ();
3919         }
3920
3921       return TRUE;
3922     }
3923
3924   return FALSE;
3925 }
3926
3927 /*-----------------------------------------------------------------*/
3928 /* outBitAcc - output a bit in acc                                 */
3929 /*-----------------------------------------------------------------*/
3930 static void
3931 outBitAcc (operand * result)
3932 {
3933   symbol *tlbl = newiTempLabel (NULL);
3934   /* if the result is a bit */
3935   if (AOP_TYPE (result) == AOP_CRY)
3936     {
3937       aopPut (AOP (result), "a", 0);
3938     }
3939   else
3940     {
3941       emitcode ("jz", "!tlabel", tlbl->key + 100);
3942       emitcode ("mov", "a,%s", one);
3943       emitcode ("", "!tlabeldef", tlbl->key + 100);
3944       outAcc (result);
3945     }
3946 }
3947
3948 /*-----------------------------------------------------------------*/
3949 /* genPlusBits - generates code for addition of two bits           */
3950 /*-----------------------------------------------------------------*/
3951 static void
3952 genPlusBits (iCode * ic)
3953 {
3954   D (emitcode (";", "genPlusBits "););
3955
3956   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3957     {
3958       symbol *lbl = newiTempLabel (NULL);
3959       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3960       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3961       emitcode ("cpl", "c");
3962       emitcode ("", "!tlabeldef", (lbl->key + 100));
3963       outBitC (IC_RESULT (ic));
3964     }
3965   else
3966     {
3967       emitcode ("clr", "a");
3968       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3969       emitcode ("rlc", "a");
3970       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3971       emitcode ("addc", "a,#0");
3972       outAcc (IC_RESULT (ic));
3973     }
3974 }
3975
3976 static void
3977 adjustArithmeticResult (iCode * ic)
3978 {
3979   if (opIsGptr (IC_RESULT (ic)) &&
3980       opIsGptr (IC_LEFT (ic)) &&
3981       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3982     {
3983       aopPut (AOP (IC_RESULT (ic)),
3984               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3985               GPTRSIZE - 1);
3986     }
3987
3988   if (opIsGptr (IC_RESULT (ic)) &&
3989       opIsGptr (IC_RIGHT (ic)) &&
3990       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3991     {
3992       aopPut (AOP (IC_RESULT (ic)),
3993             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3994               GPTRSIZE - 1);
3995     }
3996
3997   if (opIsGptr (IC_RESULT (ic)) &&
3998       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3999       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4000       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4001       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4002     {
4003       char buff[5];
4004       SNPRINTF (buff, sizeof(buff),
4005                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4006       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
4007     }
4008 }
4009
4010 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4011 // generates the result if possible. If result is generated, returns TRUE; otherwise
4012 // returns false and caller must deal with fact that result isn't aopOp'd.
4013 bool aopOp3(iCode * ic)
4014 {
4015     bool dp1InUse, dp2InUse;
4016     bool useDp2;
4017
4018     // First, generate the right opcode. DPTR may be used if neither left nor result are
4019     // of type AOP_STR.
4020
4021 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4022 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4023 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4024 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4025 //      );
4026 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4027 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4028 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4029 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4030 //      );
4031
4032     // Right uses DPTR unless left or result is an AOP_STR; however,
4033     // if right is an AOP_STR, it must use DPTR regardless.
4034     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4035      && !AOP_IS_STR(IC_RIGHT(ic)))
4036     {
4037         useDp2 = TRUE;
4038     }
4039     else
4040     {
4041         useDp2 = FALSE;
4042     }
4043
4044     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4045
4046     // if the right used DPTR, left MUST use DPTR2.
4047     // if the right used DPTR2, left MUST use DPTR.
4048     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4049     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4050     // enabling us to assign DPTR to result.
4051
4052     if (AOP_USESDPTR(IC_RIGHT(ic)))
4053     {
4054         useDp2 = TRUE;
4055     }
4056     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4057     {
4058         useDp2 = FALSE;
4059     }
4060     else
4061     {
4062         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4063         {
4064             useDp2 = TRUE;
4065         }
4066         else
4067         {
4068             useDp2 = FALSE;
4069         }
4070     }
4071
4072     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4073
4074
4075     // We've op'd the left & right. So, if left or right are the same operand as result,
4076     // we know aopOp will succeed, and we can just do it & bail.
4077     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4078       {
4079         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4080         return TRUE;
4081       }
4082     if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4083       {
4084 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
4085         aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4086         return TRUE;
4087       }
4088
4089     // Operands may be equivalent (but not equal) if they share a spill location. If
4090     // so, use the same DPTR or DPTR2.
4091     if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4092       {
4093         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4094         return TRUE;
4095       }
4096     if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4097       {
4098         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4099         return TRUE;
4100       }
4101
4102     // Note which dptrs are currently in use.
4103     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4104     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4105
4106     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4107     // generate it.
4108     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4109     {
4110         return FALSE;
4111     }
4112
4113     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4114     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4115     {
4116         return FALSE;
4117     }
4118
4119     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4120     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4121     {
4122         return FALSE;
4123     }
4124
4125     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4126
4127     // Some sanity checking...
4128     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4129     {
4130         fprintf(stderr,
4131                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4132                 __FILE__, __LINE__, ic->filename, ic->lineno);
4133         emitcode(";", ">>> unexpected DPTR here.");
4134     }
4135
4136     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4137     {
4138         fprintf(stderr,
4139                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4140                 __FILE__, __LINE__, ic->filename, ic->lineno);
4141         emitcode(";", ">>> unexpected DPTR2 here.");
4142     }
4143
4144     return TRUE;
4145 }
4146
4147 // Macro to aopOp all three operands of an ic. If this cannot be done,
4148 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4149 // will be set TRUE. The caller must then handle the case specially, noting
4150 // that the IC_RESULT operand is not aopOp'd.
4151 //
4152 #define AOP_OP_3_NOFATAL(ic, rc) \
4153             do { rc = !aopOp3(ic); } while (0)
4154
4155 // aopOp the left & right operands of an ic.
4156 #define AOP_OP_2(ic) \
4157     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4158     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4159
4160 // convienience macro.
4161 #define AOP_SET_LOCALS(ic) \
4162     left = IC_LEFT(ic); \
4163     right = IC_RIGHT(ic); \
4164     result = IC_RESULT(ic);
4165
4166
4167 // Given an integer value of pushedSize bytes on the stack,
4168 // adjust it to be resultSize bytes, either by discarding
4169 // the most significant bytes or by zero-padding.
4170 //
4171 // On exit from this macro, pushedSize will have been adjusted to
4172 // equal resultSize, and ACC may be trashed.
4173 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4174       /* If the pushed data is bigger than the result,          \
4175        * simply discard unused bytes. Icky, but works.          \
4176        */                                                       \
4177       while (pushedSize > resultSize)                           \
4178       {                                                         \
4179           D (emitcode (";", "discarding unused result byte."););\
4180           emitcode ("pop", "acc");                              \
4181           pushedSize--;                                         \
4182       }                                                         \
4183       if (pushedSize < resultSize)                              \
4184       {                                                         \
4185           emitcode ("clr", "a");                                \
4186           /* Conversly, we haven't pushed enough here.          \
4187            * just zero-pad, and all is well.                    \
4188            */                                                   \
4189           while (pushedSize < resultSize)                       \
4190           {                                                     \
4191               emitcode("push", "acc");                          \
4192               pushedSize++;                                     \
4193           }                                                     \
4194       }                                                         \
4195       assert(pushedSize == resultSize);
4196
4197 /*-----------------------------------------------------------------*/
4198 /* genPlus - generates code for addition                           */
4199 /*-----------------------------------------------------------------*/
4200 static void
4201 genPlus (iCode * ic)
4202 {
4203   int size, offset = 0;
4204   bool pushResult;
4205   int rSize;
4206
4207   D (emitcode (";", "genPlus "););
4208
4209   /* special cases :- */
4210   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4211       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4212       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4213       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4214       if (size <= 9) {
4215           while (size--) emitcode ("inc","dptr");
4216       } else {
4217           emitcode ("mov","a,dpl");
4218           emitcode ("add","a,#!constbyte",size & 0xff);
4219           emitcode ("mov","dpl,a");
4220           emitcode ("mov","a,dph");
4221           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4222           emitcode ("mov","dph,a");
4223           emitcode ("mov","a,dpx");
4224           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4225           emitcode ("mov","dpx,a");
4226       }
4227       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4228       return ;
4229   }
4230   if ( IS_SYMOP(IC_LEFT(ic)) &&
4231        OP_SYMBOL(IC_LEFT(ic))->remat &&
4232        isOperandInFarSpace(IC_RIGHT(ic))) {
4233       operand *op = IC_RIGHT(ic);
4234       IC_RIGHT(ic) = IC_LEFT(ic);
4235       IC_LEFT(ic) = op;
4236   }
4237
4238   AOP_OP_3_NOFATAL (ic, pushResult);
4239
4240   if (pushResult)
4241     {
4242       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4243     }
4244
4245   if (!pushResult)
4246     {
4247       /* if literal, literal on the right or
4248          if left requires ACC or right is already
4249          in ACC */
4250       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4251        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4252           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4253         {
4254           operand *t = IC_RIGHT (ic);
4255           IC_RIGHT (ic) = IC_LEFT (ic);
4256           IC_LEFT (ic) = t;
4257           emitcode (";", "Swapped plus args.");
4258         }
4259
4260       /* if both left & right are in bit
4261          space */
4262       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4263           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4264         {
4265           genPlusBits (ic);
4266           goto release;
4267         }
4268
4269       /* if left in bit space & right literal */
4270       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4271           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4272         {
4273           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4274           /* if result in bit space */
4275           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4276             {
4277               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4278                 emitcode ("cpl", "c");
4279               outBitC (IC_RESULT (ic));
4280             }
4281           else
4282             {
4283               size = getDataSize (IC_RESULT (ic));
4284               _startLazyDPSEvaluation ();
4285               while (size--)
4286                 {
4287                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4288                   emitcode ("addc", "a,#0");
4289                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4290                 }
4291               _endLazyDPSEvaluation ();
4292             }
4293           goto release;
4294         }
4295
4296       /* if I can do an increment instead
4297          of add then GOOD for ME */
4298       if (genPlusIncr (ic) == TRUE)
4299         {
4300           emitcode (";", "did genPlusIncr");
4301           goto release;
4302         }
4303
4304     }
4305   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4306
4307   _startLazyDPSEvaluation ();
4308   while (size--)
4309     {
4310       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4311         {
4312           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4313           if (offset == 0)
4314             emitcode ("add", "a,%s",
4315                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4316           else
4317             emitcode ("addc", "a,%s",
4318                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4319         }
4320       else
4321         {
4322           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4323           {
4324               /* right is going to use ACC or we would have taken the
4325                * above branch.
4326                */
4327               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4328        TR_AP("#3");
4329               D(emitcode(";", "+ AOP_ACC special case."););
4330               emitcode("xch", "a, %s", DP2_RESULT_REG);
4331           }
4332           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4333           if (offset == 0)
4334           {
4335             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4336             {
4337          TR_AP("#4");
4338                 emitcode("add", "a, %s", DP2_RESULT_REG);
4339             }
4340             else
4341             {
4342                 emitcode ("add", "a,%s",
4343                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4344                                   DP2_RESULT_REG));
4345             }
4346           }
4347           else
4348           {
4349             emitcode ("addc", "a,%s",
4350                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4351                           DP2_RESULT_REG));
4352           }
4353         }
4354       if (!pushResult)
4355         {
4356           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4357         }
4358       else
4359         {
4360           emitcode ("push", "acc");
4361         }
4362       offset++;
4363     }
4364   _endLazyDPSEvaluation ();
4365
4366   if (pushResult)
4367     {
4368       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4369
4370       size = getDataSize (IC_LEFT (ic));
4371       rSize = getDataSize (IC_RESULT (ic));
4372
4373       ADJUST_PUSHED_RESULT(size, rSize);
4374
4375       _startLazyDPSEvaluation ();
4376       while (size--)
4377         {
4378           emitcode ("pop", "acc");
4379           aopPut (AOP (IC_RESULT (ic)), "a", size);
4380         }
4381       _endLazyDPSEvaluation ();
4382     }
4383
4384   adjustArithmeticResult (ic);
4385
4386 release:
4387   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4388   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4390 }
4391
4392 /*-----------------------------------------------------------------*/
4393 /* genMinusDec :- does subtraction with deccrement if possible     */
4394 /*-----------------------------------------------------------------*/
4395 static bool
4396 genMinusDec (iCode * ic)
4397 {
4398   unsigned int icount;
4399   unsigned int size = getDataSize (IC_RESULT (ic));
4400
4401   /* will try to generate an increment */
4402   /* if the right side is not a literal
4403      we cannot */
4404   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4405     return FALSE;
4406
4407   /* if the literal value of the right hand side
4408      is greater than 4 then it is not worth it */
4409   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4410     return FALSE;
4411
4412   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4413       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4414       while (icount--) {
4415           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4416       }
4417       return TRUE;
4418   }
4419   /* if decrement 16 bits in register */
4420   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4421       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4422       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4423       (size > 1) &&
4424       (icount == 1))
4425     {
4426       symbol *tlbl;
4427       int    emitTlbl;
4428       int    labelRange;
4429       char   *l;
4430
4431       /* If the next instruction is a goto and the goto target
4432          * is <= 5 instructions previous to this, we can generate
4433          * jumps straight to that target.
4434        */
4435       if (ic->next && ic->next->op == GOTO
4436           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4437           && labelRange <= 5)
4438         {
4439           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4440           tlbl = IC_LABEL (ic->next);
4441           emitTlbl = 0;
4442         }
4443       else
4444         {
4445           tlbl = newiTempLabel (NULL);
4446           emitTlbl = 1;
4447         }
4448
4449       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4450       emitcode ("dec", "%s", l);
4451
4452       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4453           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4454           IS_AOP_PREG (IC_RESULT (ic)))
4455       {
4456           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4457       }
4458       else
4459       {
4460           emitcode ("mov", "a,#!constbyte",0xff);
4461           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4462       }
4463       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4464       emitcode ("dec", "%s", l);
4465       if (size > 2)
4466         {
4467             if (!strcmp(l, "acc"))
4468             {
4469                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4470             }
4471             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4472                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4473                      IS_AOP_PREG (IC_RESULT (ic)))
4474             {
4475                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4476             }
4477             else
4478             {
4479                 emitcode ("mov", "a,#!constbyte",0xff);
4480                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4481             }
4482             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4483             emitcode ("dec", "%s", l);
4484         }
4485       if (size > 3)
4486         {
4487             if (!strcmp(l, "acc"))
4488             {
4489                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4490             }
4491             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4492                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4493                      IS_AOP_PREG (IC_RESULT (ic)))
4494             {
4495                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4496             }
4497             else
4498             {
4499                 emitcode ("mov", "a,#!constbyte",0xff);
4500                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4501             }
4502             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4503             emitcode ("dec", "%s", l);
4504         }
4505       if (emitTlbl)
4506         {
4507           emitcode ("", "!tlabeldef", tlbl->key + 100);
4508         }
4509       return TRUE;
4510     }
4511
4512   /* if the sizes are greater than 1 then we cannot */
4513   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4514       AOP_SIZE (IC_LEFT (ic)) > 1)
4515     return FALSE;
4516
4517   /* we can if the aops of the left & result match or
4518      if they are in registers and the registers are the
4519      same */
4520   if (
4521        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4522        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4523        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4524     {
4525
4526       _startLazyDPSEvaluation ();
4527       while (icount--)
4528         {
4529           emitcode ("dec", "%s",
4530                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4531         }
4532       _endLazyDPSEvaluation ();
4533
4534       return TRUE;
4535     }
4536
4537   return FALSE;
4538 }
4539
4540 /*-----------------------------------------------------------------*/
4541 /* addSign - complete with sign                                    */
4542 /*-----------------------------------------------------------------*/
4543 static void
4544 addSign (operand * result, int offset, int sign)
4545 {
4546   int size = (getDataSize (result) - offset);
4547   if (size > 0)
4548     {
4549       _startLazyDPSEvaluation();
4550       if (sign)
4551         {
4552           emitcode ("rlc", "a");
4553           emitcode ("subb", "a,acc");
4554           while (size--)
4555           {
4556             aopPut (AOP (result), "a", offset++);
4557           }
4558         }
4559       else
4560       {
4561         while (size--)
4562         {
4563           aopPut (AOP (result), zero, offset++);
4564         }
4565       }
4566       _endLazyDPSEvaluation();
4567     }
4568 }
4569
4570 /*-----------------------------------------------------------------*/
4571 /* genMinusBits - generates code for subtraction  of two bits      */
4572 /*-----------------------------------------------------------------*/
4573 static void
4574 genMinusBits (iCode * ic)
4575 {
4576   symbol *lbl = newiTempLabel (NULL);
4577
4578   D (emitcode (";", "genMinusBits "););
4579
4580   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4581     {
4582       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4583       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4584       emitcode ("cpl", "c");
4585       emitcode ("", "!tlabeldef", (lbl->key + 100));
4586       outBitC (IC_RESULT (ic));
4587     }
4588   else
4589     {
4590       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4591       emitcode ("subb", "a,acc");
4592       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4593       emitcode ("inc", "a");
4594       emitcode ("", "!tlabeldef", (lbl->key + 100));
4595       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4596       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4597     }
4598 }
4599
4600 /*-----------------------------------------------------------------*/
4601 /* genMinus - generates code for subtraction                       */
4602 /*-----------------------------------------------------------------*/
4603 static void
4604 genMinus (iCode * ic)
4605 {
4606     int size, offset = 0;
4607     int rSize;
4608     long lit = 0L;
4609     bool pushResult;
4610
4611     D (emitcode (";", "genMinus "););
4612
4613     AOP_OP_3_NOFATAL(ic, pushResult);
4614
4615     if (!pushResult)
4616     {
4617       /* special cases :- */
4618       /* if both left & right are in bit space */
4619       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4620           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4621         {
4622           genMinusBits (ic);
4623           goto release;
4624         }
4625
4626       /* if I can do an decrement instead
4627          of subtract then GOOD for ME */
4628       if (genMinusDec (ic) == TRUE)
4629         goto release;
4630
4631     }
4632
4633   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4634
4635   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4636     {
4637       CLRC;
4638     }
4639   else
4640     {
4641       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4642       lit = -lit;
4643     }
4644
4645
4646   /* if literal, add a,#-lit, else normal subb */
4647   _startLazyDPSEvaluation ();
4648   while (size--) {
4649       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4650           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4651               emitcode ("mov","b,%s",
4652                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4653               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4654               emitcode ("subb","a,b");
4655           } else {
4656               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4657               emitcode ("subb", "a,%s",
4658                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4659                                 DP2_RESULT_REG));
4660           }
4661       } else {
4662           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4663           /* first add without previous c */
4664           if (!offset) {
4665               if (!size && lit==-1) {
4666                   emitcode ("dec", "a");
4667               } else {
4668                   emitcode ("add", "a,#!constbyte",
4669                             (unsigned int) (lit & 0x0FFL));
4670               }
4671           } else {
4672               emitcode ("addc", "a,#!constbyte",
4673                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4674           }
4675       }
4676
4677       if (pushResult) {
4678           emitcode ("push", "acc");
4679       } else {
4680           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4681       }
4682       offset++;
4683   }
4684   _endLazyDPSEvaluation ();
4685
4686   if (pushResult)
4687     {
4688       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4689
4690       size = getDataSize (IC_LEFT (ic));
4691       rSize = getDataSize (IC_RESULT (ic));
4692
4693       ADJUST_PUSHED_RESULT(size, rSize);
4694
4695       _startLazyDPSEvaluation ();
4696       while (size--)
4697         {
4698           emitcode ("pop", "acc");
4699           aopPut (AOP (IC_RESULT (ic)), "a", size);
4700         }
4701       _endLazyDPSEvaluation ();
4702     }
4703
4704   adjustArithmeticResult (ic);
4705
4706 release:
4707   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4708   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4709   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4710 }
4711
4712
4713 /*-----------------------------------------------------------------*/
4714 /* genMultbits :- multiplication of bits                           */
4715 /*-----------------------------------------------------------------*/
4716 static void
4717 genMultbits (operand * left,
4718              operand * right,
4719              operand * result,
4720              iCode   * ic)
4721 {
4722   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4723   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4724   aopOp(result, ic, TRUE, FALSE);
4725   outBitC (result);
4726 }
4727
4728
4729 /*-----------------------------------------------------------------*/
4730 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4731 /*-----------------------------------------------------------------*/
4732 static void
4733 genMultOneByte (operand * left,
4734                 operand * right,
4735                 operand * result,
4736                 iCode   * ic)
4737 {
4738   int size;
4739   symbol *lbl;
4740   bool runtimeSign, compiletimeSign;
4741   bool lUnsigned, rUnsigned;
4742
4743
4744   /* (if two literals: the value is computed before) */
4745   /* if one literal, literal on the right */
4746   if (AOP_TYPE (left) == AOP_LIT)
4747     {
4748       operand *t = right;
4749       right = left;
4750       left = t;
4751       emitcode (";", "swapped left and right");
4752     }
4753
4754   /* (if two literals: the value is computed before) */
4755   /* if one literal, literal on the right */
4756   if (AOP_TYPE (left) == AOP_LIT)
4757     {
4758       operand *t = right;
4759       right = left;
4760       left = t;
4761       /* emitcode (";", "swapped left and right"); */
4762     }
4763   /* if no literal, unsigned on the right: shorter code */
4764   if (   AOP_TYPE (right) != AOP_LIT
4765       && SPEC_USIGN (getSpec (operandType (left))))
4766     {
4767       operand *t = right;
4768       right = left;
4769       left = t;
4770     }
4771
4772   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4773   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4774
4775   if ((lUnsigned && rUnsigned)
4776 /* sorry, I don't know how to get size
4777    without calling aopOp (result,...);
4778    see Feature Request  */
4779       /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4780                    no need to take care about the signedness! */
4781     {
4782       /* just an unsigned 8 * 8 = 8 multiply
4783          or 8u * 8u = 16u */
4784       /* emitcode (";","unsigned"); */
4785       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4786       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4787       emitcode ("mul", "ab");
4788
4789       _G.accInUse++; _G.bInUse++;
4790       aopOp (result, ic, TRUE, FALSE);
4791       size = AOP_SIZE (result);
4792
4793       if (size < 1 || size > 2)
4794         {
4795           /* this should never happen */
4796           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4797                    size, __FILE__, lineno);
4798           exit (1);
4799         }
4800
4801       aopPut (AOP (result), "a", 0);
4802       _G.accInUse--; _G.bInUse--;
4803       if (size == 2)
4804         aopPut (AOP (result), "b", 1);
4805       return;
4806     }
4807
4808   /* we have to do a signed multiply */
4809   /* emitcode (";", "signed"); */
4810
4811   /* now sign adjust for both left & right */
4812
4813   /* let's see what's needed: */
4814   /* apply negative sign during runtime */
4815   runtimeSign = FALSE;
4816   /* negative sign from literals */
4817   compiletimeSign = FALSE;
4818
4819   if (!lUnsigned)
4820     {
4821       if (AOP_TYPE(left) == AOP_LIT)
4822         {
4823           /* signed literal */
4824           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4825           if (val < 0)
4826             compiletimeSign = TRUE;
4827         }
4828       else
4829         /* signed but not literal */
4830         runtimeSign = TRUE;
4831     }
4832
4833   if (!rUnsigned)
4834     {
4835       if (AOP_TYPE(right) == AOP_LIT)
4836         {
4837           /* signed literal */
4838           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4839           if (val < 0)
4840             compiletimeSign ^= TRUE;
4841         }
4842       else
4843         /* signed but not literal */
4844         runtimeSign = TRUE;
4845     }
4846
4847   /* initialize F0, which stores the runtime sign */
4848   if (runtimeSign)
4849     {
4850       if (compiletimeSign)
4851         emitcode ("setb", "F0"); /* set sign flag */
4852       else
4853         emitcode ("clr", "F0"); /* reset sign flag */
4854     }
4855
4856   /* save the signs of the operands */
4857   if (AOP_TYPE(right) == AOP_LIT)
4858     {
4859       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4860
4861       if (!rUnsigned && val < 0)
4862         emitcode ("mov", "b,#!constbyte", -val);
4863       else
4864         emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4865     }
4866   else /* ! literal */
4867     {
4868       if (rUnsigned)  /* emitcode (";", "signed"); */
4869         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4870       else
4871         {
4872           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4873           lbl = newiTempLabel (NULL);
4874           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4875           emitcode ("cpl", "F0"); /* complement sign flag */
4876           emitcode ("cpl", "a");  /* 2's complement */
4877           emitcode ("inc", "a");
4878           emitcode ("", "!tlabeldef", lbl->key + 100);
4879           emitcode ("mov", "b,a");
4880         }
4881     }
4882
4883   if (AOP_TYPE(left) == AOP_LIT)
4884     {
4885       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4886
4887       if (!lUnsigned && val < 0)
4888         emitcode ("mov", "a,#!constbyte", -val);
4889       else
4890         emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4891     }
4892   else /* ! literal */
4893     {
4894       if (lUnsigned)  /* emitcode (";", "signed"); */
4895
4896         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4897       else
4898         {
4899           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4900           lbl = newiTempLabel (NULL);
4901           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4902           emitcode ("cpl", "F0"); /* complement sign flag */
4903           emitcode ("cpl", "a");  /* 2's complement */
4904           emitcode ("inc", "a");
4905           emitcode ("", "!tlabeldef", lbl->key + 100);
4906         }
4907     }
4908
4909   /* now the multiplication */
4910   emitcode ("mul", "ab");
4911   _G.accInUse++;_G.bInUse++;
4912   aopOp(result, ic, TRUE, FALSE);
4913   size = AOP_SIZE (result);
4914
4915   if (size < 1 || size > 2)
4916     {
4917       /* this should never happen */
4918       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4919                size, __FILE__, lineno);
4920       exit (1);
4921     }
4922
4923   if (runtimeSign || compiletimeSign)
4924     {
4925       lbl = newiTempLabel (NULL);
4926       if (runtimeSign)
4927         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4928       emitcode ("cpl", "a"); /* lsb 2's complement */
4929       if (size != 2)
4930         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4931       else
4932         {
4933           emitcode ("add", "a,#1"); /* this sets carry flag */
4934           emitcode ("xch", "a,b");
4935           emitcode ("cpl", "a"); /* msb 2's complement */
4936           emitcode ("addc", "a,#0");
4937           emitcode ("xch", "a,b");
4938         }
4939       emitcode ("", "!tlabeldef", lbl->key + 100);
4940     }
4941   aopPut (AOP (result), "a", 0);
4942   _G.accInUse--;_G.bInUse--;
4943   if (size == 2)
4944     aopPut (AOP (result), "b", 1);
4945 }
4946
4947 /*-----------------------------------------------------------------*/
4948 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4949 /*-----------------------------------------------------------------*/
4950 static void genMultTwoByte (operand *left, operand *right,
4951                             operand *result, iCode *ic)
4952 {
4953         sym_link *retype = getSpec(operandType(right));
4954         sym_link *letype = getSpec(operandType(left));
4955         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4956         symbol *lbl;
4957
4958         if (AOP_TYPE (left) == AOP_LIT) {
4959                 operand *t = right;
4960                 right = left;
4961                 left = t;
4962         }
4963         /* save EA bit in F1 */
4964         lbl = newiTempLabel(NULL);
4965         emitcode ("setb","F1");
4966         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4967         emitcode ("clr","F1");
4968         emitcode("","!tlabeldef",lbl->key+100);
4969
4970         /* load up MB with right */
4971         if (!umult) {
4972                 emitcode("clr","F0");
4973                 if (AOP_TYPE(right) == AOP_LIT) {
4974                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4975                         if (val < 0) {
4976                                 emitcode("setb","F0");
4977                                 val = -val;
4978                         }
4979                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4980                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4981                 } else {
4982                         lbl = newiTempLabel(NULL);
4983                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4984                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4985                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4986                         emitcode ("xch", "a,b");
4987                         emitcode ("cpl","a");
4988                         emitcode ("add", "a,#1");
4989                         emitcode ("xch", "a,b");
4990                         emitcode ("cpl", "a"); // msb
4991                         emitcode ("addc", "a,#0");
4992                         emitcode ("setb","F0");
4993                         emitcode ("","!tlabeldef",lbl->key+100);
4994                         emitcode ("mov","mb,b");
4995                         emitcode ("mov","mb,a");
4996                 }
4997         } else {
4998                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4999                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5000         }
5001         /* load up MA with left */
5002         if (!umult) {
5003                 lbl = newiTempLabel(NULL);
5004                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5005                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5006                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5007                 emitcode ("xch", "a,b");
5008                 emitcode ("cpl","a");
5009                 emitcode ("add", "a,#1");
5010                 emitcode ("xch", "a,b");
5011                 emitcode ("cpl", "a"); // msb
5012                 emitcode ("addc","a,#0");
5013                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5014                 emitcode ("setb","F0");
5015                 emitcode ("","!tlabeldef",lbl->key+100);
5016                 emitcode ("mov","ma,b");
5017                 emitcode ("mov","ma,a");
5018         } else {
5019                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5020                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5021         }
5022         /* wait for multiplication to finish */
5023         lbl = newiTempLabel(NULL);
5024         emitcode("","!tlabeldef", lbl->key+100);
5025         emitcode("mov","a,mcnt1");
5026         emitcode("anl","a,#!constbyte",0x80);
5027         emitcode("jnz","!tlabel",lbl->key+100);
5028
5029         freeAsmop (left, NULL, ic, TRUE);
5030         freeAsmop (right, NULL, ic,TRUE);
5031         aopOp(result, ic, TRUE, FALSE);
5032
5033         /* if unsigned then simple */
5034         if (umult) {
5035                 emitcode ("mov","a,ma");
5036                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5037                 emitcode ("mov","a,ma");
5038                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5039                 aopPut(AOP(result),"ma",1);
5040                 aopPut(AOP(result),"ma",0);
5041         } else {
5042                 emitcode("push","ma");
5043                 emitcode("push","ma");
5044                 emitcode("push","ma");
5045                 MOVA("ma");
5046                 /* negate result if needed */
5047                 lbl = newiTempLabel(NULL);
5048                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5049                 emitcode("cpl","a");
5050                 emitcode("add","a,#1");
5051                 emitcode("","!tlabeldef", lbl->key+100);
5052                 if (AOP_TYPE(result) == AOP_ACC)
5053                 {
5054                     D(emitcode(";", "ACC special case."););
5055                     /* We know result is the only live aop, and
5056                      * it's obviously not a DPTR2, so AP is available.
5057                      */
5058                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
5059                 }
5060                 else
5061                 {
5062                     aopPut(AOP(result),"a",0);
5063                 }
5064
5065                 emitcode("pop","acc");
5066                 lbl = newiTempLabel(NULL);
5067                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5068                 emitcode("cpl","a");
5069                 emitcode("addc","a,#0");
5070                 emitcode("","!tlabeldef", lbl->key+100);
5071                 aopPut(AOP(result),"a",1);
5072                 emitcode("pop","acc");
5073                 if (AOP_SIZE(result) >= 3) {
5074                         lbl = newiTempLabel(NULL);
5075                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5076                         emitcode("cpl","a");
5077                         emitcode("addc","a,#0");
5078                         emitcode("","!tlabeldef", lbl->key+100);
5079                         aopPut(AOP(result),"a",2);
5080                 }
5081                 emitcode("pop","acc");
5082                 if (AOP_SIZE(result) >= 4) {
5083                         lbl = newiTempLabel(NULL);
5084                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5085                         emitcode("cpl","a");
5086                         emitcode("addc","a,#0");
5087                         emitcode("","!tlabeldef", lbl->key+100);
5088                         aopPut(AOP(result),"a",3);
5089                 }
5090                 if (AOP_TYPE(result) == AOP_ACC)
5091                 {
5092                     /* We stashed the result away above. */
5093                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
5094                 }
5095
5096         }
5097         freeAsmop (result, NULL, ic, TRUE);
5098
5099         /* restore EA bit in F1 */
5100         lbl = newiTempLabel(NULL);
5101         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5102         emitcode ("setb","EA");
5103         emitcode("","!tlabeldef",lbl->key+100);
5104         return ;
5105 }
5106
5107 /*-----------------------------------------------------------------*/
5108 /* genMult - generates code for multiplication                     */
5109 /*-----------------------------------------------------------------*/
5110 static void
5111 genMult (iCode * ic)
5112 {
5113   operand *left = IC_LEFT (ic);
5114   operand *right = IC_RIGHT (ic);
5115   operand *result = IC_RESULT (ic);
5116
5117   D (emitcode (";", "genMult "););
5118
5119   /* assign the amsops */
5120   AOP_OP_2 (ic);
5121
5122   /* special cases first */
5123   /* both are bits */
5124   if (AOP_TYPE (left) == AOP_CRY &&
5125       AOP_TYPE (right) == AOP_CRY)
5126     {
5127       genMultbits (left, right, result, ic);
5128       goto release;
5129     }
5130
5131   /* if both are of size == 1 */
5132   if (AOP_SIZE (left) == 1 &&
5133       AOP_SIZE (right) == 1)
5134     {
5135       genMultOneByte (left, right, result, ic);
5136       goto release;
5137     }
5138
5139   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5140           /* use the ds390 ARITHMETIC accel UNIT */
5141           genMultTwoByte (left, right, result, ic);
5142           return ;
5143   }
5144   /* should have been converted to function call */
5145   assert (0);
5146
5147 release:
5148   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5149   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5150   freeAsmop (result, NULL, ic, TRUE);
5151 }
5152
5153 /*-----------------------------------------------------------------*/
5154 /* genDivbits :- division of bits                                  */
5155 /*-----------------------------------------------------------------*/
5156 static void
5157 genDivbits (operand * left,
5158             operand * right,
5159             operand * result,
5160             iCode   * ic)
5161 {
5162
5163   char *l;
5164
5165   /* the result must be bit */
5166   LOAD_AB_FOR_DIV (left, right, l);
5167   emitcode ("div", "ab");
5168   emitcode ("rrc", "a");
5169   aopOp(result, ic, TRUE, FALSE);
5170
5171   aopPut (AOP (result), "c", 0);
5172 }
5173
5174 /*-----------------------------------------------------------------*/
5175 /* genDivOneByte : 8 bit division                                  */
5176 /*-----------------------------------------------------------------*/
5177 static void
5178 genDivOneByte (operand * left,
5179                operand * right,
5180                operand * result,
5181                iCode   * ic)
5182 {
5183   bool lUnsigned, rUnsigned;
5184   bool runtimeSign, compiletimeSign;
5185   char *l;
5186   symbol *lbl;
5187   int size, offset;
5188
5189   offset = 1;
5190   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5191   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5192
5193   /* signed or unsigned */
5194   if (lUnsigned && rUnsigned)
5195     {
5196       /* unsigned is easy */
5197       LOAD_AB_FOR_DIV (left, right, l);
5198       emitcode ("div", "ab");
5199
5200       _G.accInUse++;
5201       aopOp (result, ic, TRUE, FALSE);
5202       aopPut (AOP (result), "a", 0);
5203       _G.accInUse--;
5204
5205       size = AOP_SIZE (result) - 1;
5206
5207       while (size--)
5208         aopPut (AOP (result), zero, offset++);
5209       return;
5210     }
5211
5212   /* signed is a little bit more difficult */
5213
5214   /* now sign adjust for both left & right */
5215
5216   /* let's see what's needed: */
5217   /* apply negative sign during runtime */
5218   runtimeSign = FALSE;
5219   /* negative sign from literals */
5220   compiletimeSign = FALSE;
5221
5222   if (!lUnsigned)
5223     {
5224       if (AOP_TYPE(left) == AOP_LIT)
5225         {
5226           /* signed literal */
5227           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5228           if (val < 0)
5229             compiletimeSign = TRUE;
5230         }
5231       else
5232         /* signed but not literal */
5233         runtimeSign = TRUE;
5234     }
5235
5236   if (!rUnsigned)
5237     {
5238       if (AOP_TYPE(right) == AOP_LIT)
5239         {
5240           /* signed literal */
5241           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5242           if (val < 0)
5243             compiletimeSign ^= TRUE;
5244         }
5245       else
5246         /* signed but not literal */
5247         runtimeSign = TRUE;
5248     }
5249
5250   /* initialize F0, which stores the runtime sign */
5251   if (runtimeSign)
5252     {
5253       if (compiletimeSign)
5254         emitcode ("setb", "F0"); /* set sign flag */
5255       else
5256         emitcode ("clr", "F0"); /* reset sign flag */
5257     }
5258
5259   /* save the signs of the operands */
5260   if (AOP_TYPE(right) == AOP_LIT)
5261     {
5262       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5263
5264       if (!rUnsigned && val < 0)
5265         emitcode ("mov", "b,#0x%02x", -val);
5266       else
5267         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5268     }
5269   else /* ! literal */
5270     {
5271       if (rUnsigned)
5272         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5273       else
5274         {
5275           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5276           lbl = newiTempLabel (NULL);
5277           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5278           emitcode ("cpl", "F0"); /* complement sign flag */
5279           emitcode ("cpl", "a");  /* 2's complement */
5280           emitcode ("inc", "a");
5281           emitcode ("", "!tlabeldef", lbl->key + 100);
5282           emitcode ("mov", "b,a");
5283         }
5284     }
5285
5286   if (AOP_TYPE(left) == AOP_LIT)
5287     {
5288       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5289
5290       if (!lUnsigned && val < 0)
5291         emitcode ("mov", "a,#0x%02x", -val);
5292       else
5293         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5294     }
5295   else /* ! literal */
5296     {
5297       if (lUnsigned)
5298         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5299       else
5300         {
5301           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5302           lbl = newiTempLabel (NULL);
5303           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5304           emitcode ("cpl", "F0"); /* complement sign flag */
5305           emitcode ("cpl", "a");  /* 2's complement */
5306           emitcode ("inc", "a");
5307           emitcode ("", "!tlabeldef", lbl->key + 100);
5308         }
5309     }
5310
5311   /* now the division */
5312   emitcode ("nop", "; workaround for DS80C390 div bug.");
5313   emitcode ("div", "ab");
5314
5315   if (runtimeSign || compiletimeSign)
5316     {
5317       lbl = newiTempLabel (NULL);
5318       if (runtimeSign)
5319         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5320       emitcode ("cpl", "a"); /* lsb 2's complement */
5321       emitcode ("inc", "a");
5322       emitcode ("", "!tlabeldef", lbl->key + 100);
5323
5324       _G.accInUse++;     _G.bInUse++;
5325       aopOp (result, ic, TRUE, FALSE);
5326       size = AOP_SIZE (result) - 1;
5327
5328       if (size > 0)
5329         {
5330           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5331              then the result will be in b, a */
5332           emitcode ("mov", "b,a"); /* 1 */
5333           /* msb is 0x00 or 0xff depending on the sign */
5334           if (runtimeSign)
5335             {
5336               emitcode ("mov",  "c,F0");
5337               emitcode ("subb", "a,acc");
5338               emitcode ("xch",  "a,b"); /* 2 */
5339               while (size--)
5340                 aopPut (AOP (result), "b", offset++); /* write msb's */
5341             }
5342           else /* compiletimeSign */
5343             while (size--)
5344               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5345         }
5346       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5347     }
5348   else
5349     {
5350       _G.accInUse++;     _G.bInUse++;
5351       aopOp(result, ic, TRUE, FALSE);
5352       size = AOP_SIZE (result) - 1;
5353
5354       aopPut (AOP (result), "a", 0);
5355       while (size--)
5356         aopPut (AOP (result), zero, offset++);
5357     }
5358   _G.accInUse--;     _G.bInUse--;
5359
5360 }
5361
5362 /*-----------------------------------------------------------------*/
5363 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5364 /*-----------------------------------------------------------------*/
5365 static void genDivTwoByte (operand *left, operand *right,
5366                             operand *result, iCode *ic)
5367 {
5368         sym_link *retype = getSpec(operandType(right));
5369         sym_link *letype = getSpec(operandType(left));
5370         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5371         symbol *lbl;
5372
5373         /* save EA bit in F1 */
5374         lbl = newiTempLabel(NULL);
5375         emitcode ("setb","F1");
5376         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5377         emitcode ("clr","F1");
5378         emitcode("","!tlabeldef",lbl->key+100);
5379
5380         /* load up MA with left */
5381         if (!umult) {
5382                 emitcode("clr","F0");
5383                 lbl = newiTempLabel(NULL);
5384                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5385                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5386                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5387                 emitcode ("xch", "a,b");
5388                 emitcode ("cpl","a");
5389                 emitcode ("add", "a,#1");
5390                 emitcode ("xch", "a,b");
5391                 emitcode ("cpl", "a"); // msb
5392                 emitcode ("addc","a,#0");
5393                 emitcode ("setb","F0");
5394                 emitcode ("","!tlabeldef",lbl->key+100);
5395                 emitcode ("mov","ma,b");
5396                 emitcode ("mov","ma,a");
5397         } else {
5398                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5399                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5400         }
5401
5402         /* load up MB with right */
5403         if (!umult) {
5404                 if (AOP_TYPE(right) == AOP_LIT) {
5405                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5406                         if (val < 0) {
5407                                 lbl = newiTempLabel(NULL);
5408                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5409                                 emitcode("setb","F0");
5410                                 emitcode ("","!tlabeldef",lbl->key+100);
5411                                 val = -val;
5412                         }
5413                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5414                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5415                 } else {
5416                         lbl = newiTempLabel(NULL);
5417                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5418                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5419                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5420                         emitcode ("xch", "a,b");
5421                         emitcode ("cpl","a");
5422                         emitcode ("add", "a,#1");
5423                         emitcode ("xch", "a,b");
5424                         emitcode ("cpl", "a"); // msb
5425                         emitcode ("addc", "a,#0");
5426                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5427                         emitcode ("setb","F0");
5428                         emitcode ("","!tlabeldef",lbl->key+100);
5429                         emitcode ("mov","mb,b");
5430                         emitcode ("mov","mb,a");
5431                 }
5432         } else {
5433                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5434                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5435         }
5436
5437         /* wait for multiplication to finish */
5438         lbl = newiTempLabel(NULL);
5439         emitcode("","!tlabeldef", lbl->key+100);
5440         emitcode("mov","a,mcnt1");
5441         emitcode("anl","a,#!constbyte",0x80);
5442         emitcode("jnz","!tlabel",lbl->key+100);
5443
5444         freeAsmop (left, NULL, ic, TRUE);
5445         freeAsmop (right, NULL, ic,TRUE);
5446         aopOp(result, ic, TRUE, FALSE);
5447
5448         /* if unsigned then simple */
5449         if (umult) {
5450                 aopPut(AOP(result),"ma",1);
5451                 aopPut(AOP(result),"ma",0);
5452         } else {
5453                 emitcode("push","ma");
5454                 MOVA("ma");
5455                 /* negate result if needed */
5456                 lbl = newiTempLabel(NULL);
5457                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5458                 emitcode("cpl","a");
5459                 emitcode("add","a,#1");
5460                 emitcode("","!tlabeldef", lbl->key+100);
5461                 aopPut(AOP(result),"a",0);
5462                 emitcode("pop","acc");
5463                 lbl = newiTempLabel(NULL);
5464                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5465                 emitcode("cpl","a");
5466                 emitcode("addc","a,#0");
5467                 emitcode("","!tlabeldef", lbl->key+100);
5468                 aopPut(AOP(result),"a",1);
5469         }
5470         freeAsmop (result, NULL, ic, TRUE);
5471         /* restore EA bit in F1 */
5472         lbl = newiTempLabel(NULL);
5473         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5474         emitcode ("setb","EA");
5475         emitcode("","!tlabeldef",lbl->key+100);
5476         return ;
5477 }
5478
5479 /*-----------------------------------------------------------------*/
5480 /* genDiv - generates code for division                            */
5481 /*-----------------------------------------------------------------*/
5482 static void
5483 genDiv (iCode * ic)
5484 {
5485   operand *left = IC_LEFT (ic);
5486   operand *right = IC_RIGHT (ic);
5487   operand *result = IC_RESULT (ic);
5488
5489   D (emitcode (";", "genDiv "););
5490
5491   /* assign the amsops */
5492   AOP_OP_2 (ic);
5493
5494   /* special cases first */
5495   /* both are bits */
5496   if (AOP_TYPE (left) == AOP_CRY &&
5497       AOP_TYPE (right) == AOP_CRY)
5498     {
5499       genDivbits (left, right, result, ic);
5500       goto release;
5501     }
5502
5503   /* if both are of size == 1 */
5504   if (AOP_SIZE (left) == 1 &&
5505       AOP_SIZE (right) == 1)
5506     {
5507       genDivOneByte (left, right, result, ic);
5508       goto release;
5509     }
5510
5511   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5512           /* use the ds390 ARITHMETIC accel UNIT */
5513           genDivTwoByte (left, right, result, ic);
5514           return ;
5515   }
5516   /* should have been converted to function call */
5517   assert (0);
5518 release:
5519   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5520   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5521   freeAsmop (result, NULL, ic, TRUE);
5522 }
5523
5524 /*-----------------------------------------------------------------*/
5525 /* genModbits :- modulus of bits                                   */
5526 /*-----------------------------------------------------------------*/
5527 static void
5528 genModbits (operand * left,
5529             operand * right,
5530             operand * result,
5531             iCode   * ic)
5532 {
5533
5534   char *l;
5535
5536   /* the result must be bit */
5537   LOAD_AB_FOR_DIV (left, right, l);
5538   emitcode ("div", "ab");
5539   emitcode ("mov", "a,b");
5540   emitcode ("rrc", "a");
5541   aopOp(result, ic, TRUE, FALSE);
5542   aopPut (AOP (result), "c", 0);
5543 }
5544
5545 /*-----------------------------------------------------------------*/
5546 /* genModOneByte : 8 bit modulus                                   */
5547 /*-----------------------------------------------------------------*/
5548 static void
5549 genModOneByte (operand * left,
5550                operand * right,
5551                operand * result,
5552                iCode   * ic)
5553 {
5554   bool lUnsigned, rUnsigned;
5555   bool runtimeSign, compiletimeSign;
5556   char *l;
5557   symbol *lbl;
5558   int size, offset;
5559
5560   offset = 1;
5561   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5562   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5563
5564   /* signed or unsigned */
5565   if (lUnsigned && rUnsigned)
5566     {
5567       /* unsigned is easy */
5568       LOAD_AB_FOR_DIV (left, right, l);
5569       emitcode ("div", "ab");
5570       aopOp (result, ic, TRUE, FALSE);
5571       aopPut (AOP (result), "b", 0);
5572
5573       for (size = AOP_SIZE (result) - 1; size--;)
5574         aopPut (AOP (result), zero, offset++);
5575       return;
5576     }
5577
5578   /* signed is a little bit more difficult */
5579
5580   /* now sign adjust for both left & right */
5581
5582   /* modulus: sign of the right operand has no influence on the result! */
5583   if (AOP_TYPE(right) == AOP_LIT)
5584     {
5585       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5586
5587       if (!rUnsigned && val < 0)
5588         emitcode ("mov", "b,#0x%02x", -val);
5589       else
5590         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5591     }
5592   else /* ! literal */
5593     {
5594       if (rUnsigned)
5595         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5596       else
5597         {
5598           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5599           lbl = newiTempLabel (NULL);
5600           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5601           emitcode ("cpl", "a");  /* 2's complement */
5602           emitcode ("inc", "a");
5603           emitcode ("", "!tlabeldef", lbl->key + 100);
5604           emitcode ("mov", "b,a");
5605         }
5606     }
5607
5608   /* let's see what's needed: */
5609   /* apply negative sign during runtime */
5610   runtimeSign = FALSE;
5611   /* negative sign from literals */
5612   compiletimeSign = FALSE;
5613
5614   /* sign adjust left side */
5615   if (AOP_TYPE(left) == AOP_LIT)
5616     {
5617       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5618
5619       if (!lUnsigned && val < 0)
5620         {
5621           compiletimeSign = TRUE; /* set sign flag */
5622           emitcode ("mov", "a,#0x%02x", -val);
5623         }
5624       else
5625         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5626     }
5627   else /* ! literal */
5628     {
5629       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5630
5631       if (!lUnsigned)
5632         {
5633           runtimeSign = TRUE;
5634           emitcode ("clr", "F0"); /* clear sign flag */
5635
5636           lbl = newiTempLabel (NULL);
5637           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5638           emitcode ("setb", "F0"); /* set sign flag */
5639           emitcode ("cpl", "a");   /* 2's complement */
5640           emitcode ("inc", "a");
5641           emitcode ("", "!tlabeldef", lbl->key + 100);
5642         }
5643     }
5644
5645   /* now the modulus */
5646   emitcode ("nop", "; workaround for DS80C390 div bug.");
5647   emitcode ("div", "ab");
5648
5649   if (runtimeSign || compiletimeSign)
5650     {
5651       emitcode ("mov", "a,b");
5652       lbl = newiTempLabel (NULL);
5653       if (runtimeSign)
5654         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5655       emitcode ("cpl", "a"); /* lsb 2's complement */
5656       emitcode ("inc", "a");
5657       emitcode ("", "!tlabeldef", lbl->key + 100);
5658
5659       _G.accInUse++;     _G.bInUse++;
5660       aopOp (result, ic, TRUE, FALSE);
5661       size = AOP_SIZE (result) - 1;
5662
5663       if (size > 0)
5664         {
5665           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5666              then the result will be in b, a */
5667           emitcode ("mov", "b,a"); /* 1 */
5668           /* msb is 0x00 or 0xff depending on the sign */
5669           if (runtimeSign)
5670             {
5671               emitcode ("mov",  "c,F0");
5672               emitcode ("subb", "a,acc");
5673               emitcode ("xch",  "a,b"); /* 2 */
5674               while (size--)
5675                 aopPut (AOP (result), "b", offset++); /* write msb's */
5676             }
5677           else /* compiletimeSign */
5678             while (size--)
5679               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5680         }
5681       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5682     }
5683   else
5684     {
5685       _G.accInUse++;     _G.bInUse++;
5686       aopOp(result, ic, TRUE, FALSE);
5687       size = AOP_SIZE (result) - 1;
5688
5689       aopPut (AOP (result), "b", 0);
5690       while (size--)
5691         aopPut (AOP (result), zero, offset++);
5692     }
5693   _G.accInUse--;     _G.bInUse--;
5694
5695 }
5696
5697 /*-----------------------------------------------------------------*/
5698 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5699 /*-----------------------------------------------------------------*/
5700 static void genModTwoByte (operand *left, operand *right,
5701                             operand *result, iCode *ic)
5702 {
5703         sym_link *retype = getSpec(operandType(right));
5704         sym_link *letype = getSpec(operandType(left));
5705         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5706         symbol *lbl;
5707
5708         /* load up MA with left */
5709         /* save EA bit in F1 */
5710         lbl = newiTempLabel(NULL);
5711         emitcode ("setb","F1");
5712         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5713         emitcode ("clr","F1");
5714         emitcode("","!tlabeldef",lbl->key+100);
5715
5716         if (!umult) {
5717                 lbl = newiTempLabel(NULL);
5718                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5719                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5720                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5721                 emitcode ("xch", "a,b");
5722                 emitcode ("cpl","a");
5723                 emitcode ("add", "a,#1");
5724                 emitcode ("xch", "a,b");
5725                 emitcode ("cpl", "a"); // msb
5726                 emitcode ("addc","a,#0");
5727                 emitcode ("","!tlabeldef",lbl->key+100);
5728                 emitcode ("mov","ma,b");
5729                 emitcode ("mov","ma,a");
5730         } else {
5731                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5732                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5733         }
5734
5735         /* load up MB with right */
5736         if (!umult) {
5737                 if (AOP_TYPE(right) == AOP_LIT) {
5738                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5739                         if (val < 0) {
5740                                 val = -val;
5741                         }
5742                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5743                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5744                 } else {
5745                         lbl = newiTempLabel(NULL);
5746                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5747                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5748                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5749                         emitcode ("xch", "a,b");
5750                         emitcode ("cpl","a");
5751                         emitcode ("add", "a,#1");
5752                         emitcode ("xch", "a,b");
5753                         emitcode ("cpl", "a"); // msb
5754                         emitcode ("addc", "a,#0");
5755                         emitcode ("","!tlabeldef",lbl->key+100);
5756                         emitcode ("mov","mb,b");
5757                         emitcode ("mov","mb,a");
5758                 }
5759         } else {
5760                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5761                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5762         }
5763
5764         /* wait for multiplication to finish */
5765         lbl = newiTempLabel(NULL);
5766         emitcode("","!tlabeldef", lbl->key+100);
5767         emitcode("mov","a,mcnt1");
5768         emitcode("anl","a,#!constbyte",0x80);
5769         emitcode("jnz","!tlabel",lbl->key+100);
5770
5771         freeAsmop (left, NULL, ic, TRUE);
5772         freeAsmop (right, NULL, ic,TRUE);
5773         aopOp(result, ic, TRUE, FALSE);
5774
5775         aopPut(AOP(result),"mb",1);
5776         aopPut(AOP(result),"mb",0);
5777         freeAsmop (result, NULL, ic, TRUE);
5778
5779         /* restore EA bit in F1 */
5780         lbl = newiTempLabel(NULL);
5781         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5782         emitcode ("setb","EA");
5783         emitcode("","!tlabeldef",lbl->key+100);
5784         return ;
5785 }
5786
5787 /*-----------------------------------------------------------------*/
5788 /* genMod - generates code for division                            */
5789 /*-----------------------------------------------------------------*/
5790 static void
5791 genMod (iCode * ic)
5792 {
5793   operand *left = IC_LEFT (ic);
5794   operand *right = IC_RIGHT (ic);
5795   operand *result = IC_RESULT (ic);
5796
5797   D (emitcode (";", "genMod "); );
5798
5799   /* assign the amsops */
5800   AOP_OP_2 (ic);
5801
5802   /* special cases first */
5803   /* both are bits */
5804   if (AOP_TYPE (left) == AOP_CRY &&
5805       AOP_TYPE (right) == AOP_CRY)
5806     {
5807       genModbits (left, right, result, ic);
5808       goto release;
5809     }
5810
5811   /* if both are of size == 1 */
5812   if (AOP_SIZE (left) == 1 &&
5813       AOP_SIZE (right) == 1)
5814     {
5815       genModOneByte (left, right, result, ic);
5816       goto release;
5817     }
5818
5819   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5820           /* use the ds390 ARITHMETIC accel UNIT */
5821           genModTwoByte (left, right, result, ic);
5822           return ;
5823   }
5824
5825   /* should have been converted to function call */
5826   assert (0);
5827
5828 release:
5829   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5830   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5831   freeAsmop (result, NULL, ic, TRUE);
5832 }
5833
5834 /*-----------------------------------------------------------------*/
5835 /* genIfxJump :- will create a jump depending on the ifx           */
5836 /*-----------------------------------------------------------------*/
5837 static void
5838 genIfxJump (iCode * ic, char *jval)
5839 {
5840   symbol *jlbl;
5841   symbol *tlbl = newiTempLabel (NULL);
5842   char *inst;
5843
5844   D (emitcode (";", "genIfxJump"););
5845
5846   /* if true label then we jump if condition
5847      supplied is true */
5848   if (IC_TRUE (ic))
5849     {
5850       jlbl = IC_TRUE (ic);
5851       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5852                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5853     }
5854   else
5855     {
5856       /* false label is present */
5857       jlbl = IC_FALSE (ic);
5858       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5859                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5860     }
5861   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5862     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5863   else
5864     emitcode (inst, "!tlabel", tlbl->key + 100);
5865   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5866   emitcode ("", "!tlabeldef", tlbl->key + 100);
5867
5868   /* mark the icode as generated */
5869   ic->generated = 1;
5870 }
5871
5872 /*-----------------------------------------------------------------*/
5873 /* genCmp :- greater or less than comparison                       */
5874 /*-----------------------------------------------------------------*/
5875 static void
5876 genCmp (operand * left, operand * right,
5877         iCode * ic, iCode * ifx, int sign)
5878 {
5879   int size, offset = 0;
5880   unsigned long lit = 0L;
5881   operand *result;
5882
5883   D (emitcode (";", "genCmp"););
5884
5885   result = IC_RESULT (ic);
5886
5887   /* if left & right are bit variables */
5888   if (AOP_TYPE (left) == AOP_CRY &&
5889       AOP_TYPE (right) == AOP_CRY)
5890     {
5891       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5892       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5893     }
5894   else
5895     {
5896       /* subtract right from left if at the
5897          end the carry flag is set then we know that
5898          left is greater than right */
5899       size = max (AOP_SIZE (left), AOP_SIZE (right));
5900
5901       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5902       if ((size == 1) && !sign
5903           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5904         {
5905           symbol *lbl = newiTempLabel (NULL);
5906           emitcode ("cjne", "%s,%s,!tlabel",
5907                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5908                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5909                     lbl->key + 100);
5910           emitcode ("", "!tlabeldef", lbl->key + 100);
5911         }
5912       else
5913         {
5914           if (AOP_TYPE (right) == AOP_LIT)
5915             {
5916               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5917               /* optimize if(x < 0) or if(x >= 0) */
5918               if (lit == 0L)
5919                 {
5920                   if (!sign)
5921                     {
5922                       CLRC;
5923                     }
5924                   else
5925                     {
5926                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5927
5928                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5929                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5930
5931                       aopOp (result, ic, FALSE, FALSE);
5932
5933                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5934                         {
5935                           freeAsmop (result, NULL, ic, TRUE);
5936                           genIfxJump (ifx, "acc.7");
5937                           return;
5938                         }
5939                       else
5940                         {
5941                           emitcode ("rlc", "a");
5942                         }
5943                       goto release_freedLR;
5944                     }
5945                   goto release;
5946                 }
5947             }
5948           CLRC;
5949           while (size--)
5950             {
5951               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5952               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5953               // emitcode (";", "genCmp #2");
5954               if (sign && (size == 0))
5955                 {
5956                   // emitcode (";", "genCmp #3");
5957                   emitcode ("xrl", "a,#!constbyte",0x80);
5958                   if (AOP_TYPE (right) == AOP_LIT)
5959                     {
5960                       unsigned long lit = (unsigned long)
5961                       floatFromVal (AOP (right)->aopu.aop_lit);
5962                       // emitcode (";", "genCmp #3.1");
5963                       emitcode ("subb", "a,#!constbyte",
5964                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5965                     }
5966                   else
5967                     {
5968                       // emitcode (";", "genCmp #3.2");
5969                       saveAccWarn = 0;
5970                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5971                       saveAccWarn = DEFAULT_ACC_WARNING;
5972                       emitcode ("xrl", "b,#!constbyte",0x80);
5973                       emitcode ("subb", "a,b");
5974                     }
5975                 }
5976               else
5977                 {
5978                   const char *s;
5979
5980                   // emitcode (";", "genCmp #4");
5981                   saveAccWarn = 0;
5982                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5983                   saveAccWarn = DEFAULT_ACC_WARNING;
5984
5985                   emitcode ("subb", "a,%s", s);
5986                 }
5987             }
5988         }
5989     }
5990
5991 release:
5992 /* Don't need the left & right operands any more; do need the result. */
5993   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5994   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5995
5996   aopOp (result, ic, FALSE, FALSE);
5997
5998 release_freedLR:
5999
6000   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6001     {
6002       outBitC (result);
6003     }
6004   else
6005     {
6006       /* if the result is used in the next
6007          ifx conditional branch then generate
6008          code a little differently */
6009       if (ifx)
6010         {
6011           genIfxJump (ifx, "c");
6012         }
6013       else
6014         {
6015           outBitC (result);
6016         }
6017       /* leave the result in acc */
6018     }
6019   freeAsmop (result, NULL, ic, TRUE);
6020 }
6021
6022 /*-----------------------------------------------------------------*/
6023 /* genCmpGt :- greater than comparison                             */
6024 /*-----------------------------------------------------------------*/
6025 static void
6026 genCmpGt (iCode * ic, iCode * ifx)
6027 {
6028   operand *left, *right;
6029   sym_link *letype, *retype;
6030   int sign;
6031
6032   D (emitcode (";", "genCmpGt ");
6033     );
6034
6035   left = IC_LEFT (ic);
6036   right = IC_RIGHT (ic);
6037
6038   letype = getSpec (operandType (left));
6039   retype = getSpec (operandType (right));
6040   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6041
6042   /* assign the left & right amsops */
6043   AOP_OP_2 (ic);
6044
6045   genCmp (right, left, ic, ifx, sign);
6046 }
6047
6048 /*-----------------------------------------------------------------*/
6049 /* genCmpLt - less than comparisons                                */
6050 /*-----------------------------------------------------------------*/
6051 static void
6052 genCmpLt (iCode * ic, iCode * ifx)
6053 {
6054   operand *left, *right;
6055   sym_link *letype, *retype;
6056   int sign;
6057
6058   D (emitcode (";", "genCmpLt "););
6059
6060   left = IC_LEFT (ic);
6061   right = IC_RIGHT (ic);
6062
6063   letype = getSpec (operandType (left));
6064   retype = getSpec (operandType (right));
6065   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6066
6067   /* assign the left & right amsops */
6068   AOP_OP_2 (ic);
6069
6070   genCmp (left, right, ic, ifx, sign);
6071 }
6072
6073 /*-----------------------------------------------------------------*/
6074 /* gencjneshort - compare and jump if not equal                    */
6075 /*-----------------------------------------------------------------*/
6076 static void
6077 gencjneshort (operand * left, operand * right, symbol * lbl)
6078 {
6079   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6080   int offset = 0;
6081   unsigned long lit = 0L;
6082
6083   D (emitcode (";", "gencjneshort");
6084     );
6085
6086   /* if the left side is a literal or
6087      if the right is in a pointer register and left
6088      is not */
6089   if ((AOP_TYPE (left) == AOP_LIT) ||
6090       (AOP_TYPE (left) == AOP_IMMD) ||
6091       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6092     {
6093       operand *t = right;
6094       right = left;
6095       left = t;
6096     }
6097
6098   if (AOP_TYPE (right) == AOP_LIT)
6099     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6100
6101   if (opIsGptr (left) || opIsGptr (right))
6102     {
6103       /* We are comparing a generic pointer to something.
6104        * Exclude the generic type byte from the comparison.
6105        */
6106       size--;
6107       D (emitcode (";", "cjneshort: generic ptr special case."););
6108     }
6109
6110
6111   /* if the right side is a literal then anything goes */
6112   if (AOP_TYPE (right) == AOP_LIT &&
6113       AOP_TYPE (left) != AOP_DIR)
6114     {
6115       while (size--)
6116         {
6117           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6118           emitcode ("cjne", "a,%s,!tlabel",
6119                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6120                     lbl->key + 100);
6121           offset++;
6122         }
6123     }
6124
6125   /* if the right side is in a register or in direct space or
6126      if the left is a pointer register & right is not */
6127   else if (AOP_TYPE (right) == AOP_REG ||
6128            AOP_TYPE (right) == AOP_DIR ||
6129            AOP_TYPE (right) == AOP_LIT ||
6130            AOP_TYPE (right) == AOP_IMMD ||
6131            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6132            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6133     {
6134       while (size--)
6135         {
6136           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6137           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6138               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6139             emitcode ("jnz", "!tlabel", lbl->key + 100);
6140           else
6141             emitcode ("cjne", "a,%s,!tlabel",
6142                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6143                       lbl->key + 100);
6144           offset++;
6145         }
6146     }
6147   else
6148     {
6149       /* right is a pointer reg need both a & b */
6150       while (size--)
6151         {
6152           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6153           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6154           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6155           offset++;
6156         }
6157     }
6158 }
6159
6160 /*-----------------------------------------------------------------*/
6161 /* gencjne - compare and jump if not equal                         */
6162 /*-----------------------------------------------------------------*/
6163 static void
6164 gencjne (operand * left, operand * right, symbol * lbl)
6165 {
6166   symbol *tlbl = newiTempLabel (NULL);
6167
6168   D (emitcode (";", "gencjne");
6169     );
6170
6171   gencjneshort (left, right, lbl);
6172
6173   emitcode ("mov", "a,%s", one);
6174   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6175   emitcode ("", "!tlabeldef", lbl->key + 100);
6176   emitcode ("clr", "a");
6177   emitcode ("", "!tlabeldef", tlbl->key + 100);
6178 }
6179
6180 /*-----------------------------------------------------------------*/
6181 /* genCmpEq - generates code for equal to                          */
6182 /*-----------------------------------------------------------------*/
6183 static void
6184 genCmpEq (iCode * ic, iCode * ifx)
6185 {
6186   operand *left, *right, *result;
6187
6188   D (emitcode (";", "genCmpEq ");
6189     );
6190
6191   AOP_OP_2 (ic);
6192   AOP_SET_LOCALS (ic);
6193
6194   /* if literal, literal on the right or
6195      if the right is in a pointer register and left
6196      is not */
6197   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6198       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6199     {
6200       operand *t = IC_RIGHT (ic);
6201       IC_RIGHT (ic) = IC_LEFT (ic);
6202       IC_LEFT (ic) = t;
6203     }
6204
6205   if (ifx &&                    /* !AOP_SIZE(result) */
6206       OP_SYMBOL (result) &&
6207       OP_SYMBOL (result)->regType == REG_CND)
6208     {
6209       symbol *tlbl;
6210       /* if they are both bit variables */
6211       if (AOP_TYPE (left) == AOP_CRY &&
6212           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6213         {
6214           if (AOP_TYPE (right) == AOP_LIT)
6215             {
6216               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6217               if (lit == 0L)
6218                 {
6219                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6220                   emitcode ("cpl", "c");
6221                 }
6222               else if (lit == 1L)
6223                 {
6224                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6225                 }
6226               else
6227                 {
6228                   emitcode ("clr", "c");
6229                 }
6230               /* AOP_TYPE(right) == AOP_CRY */
6231             }
6232           else
6233             {
6234               symbol *lbl = newiTempLabel (NULL);
6235               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6236               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6237               emitcode ("cpl", "c");
6238               emitcode ("", "!tlabeldef", (lbl->key + 100));
6239             }
6240           /* if true label then we jump if condition
6241              supplied is true */
6242           tlbl = newiTempLabel (NULL);
6243           if (IC_TRUE (ifx))
6244             {
6245               emitcode ("jnc", "!tlabel", tlbl->key + 100);
6246               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6247             }
6248           else
6249             {
6250               emitcode ("jc", "!tlabel", tlbl->key + 100);
6251               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6252             }
6253           emitcode ("", "!tlabeldef", tlbl->key + 100);
6254         }
6255       else
6256         {
6257           tlbl = newiTempLabel (NULL);
6258           gencjneshort (left, right, tlbl);
6259           if (IC_TRUE (ifx))
6260             {
6261               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6262               emitcode ("", "!tlabeldef", tlbl->key + 100);
6263             }
6264           else
6265             {
6266               symbol *lbl = newiTempLabel (NULL);
6267               emitcode ("sjmp", "!tlabel", lbl->key + 100);
6268               emitcode ("", "!tlabeldef", tlbl->key + 100);
6269               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6270               emitcode ("", "!tlabeldef", lbl->key + 100);
6271             }
6272         }
6273       /* mark the icode as generated */
6274       ifx->generated = 1;
6275
6276       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6277       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6278       return;
6279     }
6280
6281   /* if they are both bit variables */
6282   if (AOP_TYPE (left) == AOP_CRY &&
6283       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6284     {
6285       if (AOP_TYPE (right) == AOP_LIT)
6286         {
6287           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6288           if (lit == 0L)
6289             {
6290               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6291               emitcode ("cpl", "c");
6292             }
6293           else if (lit == 1L)
6294             {
6295               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6296             }
6297           else
6298             {
6299               emitcode ("clr", "c");
6300             }
6301           /* AOP_TYPE(right) == AOP_CRY */
6302         }
6303       else
6304         {
6305           symbol *lbl = newiTempLabel (NULL);
6306           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6307           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6308           emitcode ("cpl", "c");
6309           emitcode ("", "!tlabeldef", (lbl->key + 100));
6310         }
6311
6312       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6313       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6314
6315       aopOp (result, ic, TRUE, FALSE);
6316
6317       /* c = 1 if egal */
6318       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6319         {
6320           outBitC (result);
6321           goto release;
6322         }
6323       if (ifx)
6324         {
6325           genIfxJump (ifx, "c");
6326           goto release;
6327         }
6328       /* if the result is used in an arithmetic operation
6329          then put the result in place */
6330       outBitC (result);
6331     }
6332   else
6333     {
6334       gencjne (left, right, newiTempLabel (NULL));
6335
6336       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6337       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6338
6339       aopOp (result, ic, TRUE, FALSE);
6340
6341       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6342         {
6343           aopPut (AOP (result), "a", 0);
6344           goto release;
6345         }
6346       if (ifx)
6347         {
6348           genIfxJump (ifx, "a");
6349           goto release;
6350         }
6351       /* if the result is used in an arithmetic operation
6352          then put the result in place */
6353       if (AOP_TYPE (result) != AOP_CRY)
6354         outAcc (result);
6355       /* leave the result in acc */
6356     }
6357
6358 release:
6359   freeAsmop (result, NULL, ic, TRUE);
6360 }
6361
6362 /*-----------------------------------------------------------------*/
6363 /* ifxForOp - returns the icode containing the ifx for operand     */
6364 /*-----------------------------------------------------------------*/
6365 static iCode *
6366 ifxForOp (operand * op, iCode * ic)
6367 {
6368   /* if true symbol then needs to be assigned */
6369   if (IS_TRUE_SYMOP (op))
6370     return NULL;
6371
6372   /* if this has register type condition and
6373      the next instruction is ifx with the same operand
6374      and live to of the operand is upto the ifx only then */
6375   if (ic->next &&
6376       ic->next->op == IFX &&
6377       IC_COND (ic->next)->key == op->key &&
6378       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6379     return ic->next;
6380
6381   return NULL;
6382 }
6383 /*-----------------------------------------------------------------*/
6384 /* hasInc - operand is incremented before any other use            */
6385 /*-----------------------------------------------------------------*/
6386 static iCode *
6387 hasInc (operand *op, iCode *ic, int osize)
6388 {
6389   sym_link *type = operandType(op);
6390   sym_link *retype = getSpec (type);
6391   iCode *lic = ic->next;
6392   int isize ;
6393
6394   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6395   if (!IS_SYMOP(op)) return NULL;
6396
6397   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6398   if (IS_AGGREGATE(type->next)) return NULL;
6399   if (osize != (isize = getSize(type->next))) return NULL;
6400
6401   while (lic) {
6402       /* if operand of the form op = op + <sizeof *op> */
6403       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6404           isOperandEqual(IC_RESULT(lic),op) &&
6405           isOperandLiteral(IC_RIGHT(lic)) &&
6406           operandLitValue(IC_RIGHT(lic)) == isize) {
6407           return lic;
6408       }
6409       /* if the operand used or deffed */
6410       if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6411           return NULL;
6412       }
6413       /* if GOTO or IFX */
6414       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6415       lic = lic->next;
6416   }
6417   return NULL;
6418 }
6419
6420 /*-----------------------------------------------------------------*/
6421 /* genAndOp - for && operation                                     */
6422 /*-----------------------------------------------------------------*/
6423 static void
6424 genAndOp (iCode * ic)
6425 {
6426   operand *left, *right, *result;
6427   symbol *tlbl;
6428
6429   D (emitcode (";", "genAndOp "););
6430
6431   /* note here that && operations that are in an
6432      if statement are taken away by backPatchLabels
6433      only those used in arthmetic operations remain */
6434   AOP_OP_2 (ic);
6435   AOP_SET_LOCALS (ic);
6436
6437   /* if both are bit variables */
6438   if (AOP_TYPE (left) == AOP_CRY &&
6439       AOP_TYPE (right) == AOP_CRY)
6440     {
6441       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6442       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6443       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6445
6446       aopOp (result,ic,FALSE, FALSE);
6447       outBitC (result);
6448     }
6449   else
6450     {
6451       tlbl = newiTempLabel (NULL);
6452       toBoolean (left);
6453       emitcode ("jz", "!tlabel", tlbl->key + 100);
6454       toBoolean (right);
6455       emitcode ("", "!tlabeldef", tlbl->key + 100);
6456       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6457       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6458
6459       aopOp (result,ic,FALSE, FALSE);
6460       outBitAcc (result);
6461     }
6462     freeAsmop (result, NULL, ic, TRUE);
6463 }
6464
6465
6466 /*-----------------------------------------------------------------*/
6467 /* genOrOp - for || operation                                      */
6468 /*-----------------------------------------------------------------*/
6469 static void
6470 genOrOp (iCode * ic)
6471 {
6472   operand *left, *right, *result;
6473   symbol *tlbl;
6474
6475   D (emitcode (";", "genOrOp "););
6476
6477   /* note here that || operations that are in an
6478      if statement are taken away by backPatchLabels
6479      only those used in arthmetic operations remain */
6480   AOP_OP_2 (ic);
6481   AOP_SET_LOCALS (ic);
6482
6483   /* if both are bit variables */
6484   if (AOP_TYPE (left) == AOP_CRY &&
6485       AOP_TYPE (right) == AOP_CRY)
6486     {
6487       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6488       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6489       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6490       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6491
6492       aopOp (result,ic,FALSE, FALSE);
6493
6494       outBitC (result);
6495     }
6496   else
6497     {
6498       tlbl = newiTempLabel (NULL);
6499       toBoolean (left);
6500       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6501       toBoolean (right);
6502       emitcode ("", "!tlabeldef", tlbl->key + 100);
6503       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6504       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6505
6506       aopOp (result,ic,FALSE, FALSE);
6507
6508       outBitAcc (result);
6509     }
6510
6511   freeAsmop (result, NULL, ic, TRUE);
6512 }
6513
6514 /*-----------------------------------------------------------------*/
6515 /* isLiteralBit - test if lit == 2^n                               */
6516 /*-----------------------------------------------------------------*/
6517 static int
6518 isLiteralBit (unsigned long lit)
6519 {
6520   unsigned long pw[32] =
6521   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6522    0x100L, 0x200L, 0x400L, 0x800L,
6523    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6524    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6525    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6526    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6527    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6528   int idx;
6529
6530   for (idx = 0; idx < 32; idx++)
6531     if (lit == pw[idx])
6532       return idx + 1;
6533   return 0;
6534 }
6535
6536 /*-----------------------------------------------------------------*/
6537 /* continueIfTrue -                                                */
6538 /*-----------------------------------------------------------------*/
6539 static void
6540 continueIfTrue (iCode * ic)
6541 {
6542   if (IC_TRUE (ic))
6543     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6544   ic->generated = 1;
6545 }
6546
6547 /*-----------------------------------------------------------------*/
6548 /* jmpIfTrue -                                                     */
6549 /*-----------------------------------------------------------------*/
6550 static void
6551 jumpIfTrue (iCode * ic)
6552 {
6553   if (!IC_TRUE (ic))
6554     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6555   ic->generated = 1;
6556 }
6557
6558 /*-----------------------------------------------------------------*/
6559 /* jmpTrueOrFalse -                                                */
6560 /*-----------------------------------------------------------------*/
6561 static void
6562 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6563 {
6564   // ugly but optimized by peephole
6565   if (IC_TRUE (ic))
6566     {
6567       symbol *nlbl = newiTempLabel (NULL);
6568       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6569       emitcode ("", "!tlabeldef", tlbl->key + 100);
6570       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6571       emitcode ("", "!tlabeldef", nlbl->key + 100);
6572     }
6573   else
6574     {
6575       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6576       emitcode ("", "!tlabeldef", tlbl->key + 100);
6577     }
6578   ic->generated = 1;
6579 }
6580
6581 // Generate code to perform a bit-wise logic operation
6582 // on two operands in far space (assumed to already have been
6583 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6584 // in far space. This requires pushing the result on the stack
6585 // then popping it into the result.
6586 static void
6587 genFarFarLogicOp(iCode *ic, char *logicOp)
6588 {
6589       int size, resultSize, compSize;
6590       int offset = 0;
6591
6592       TR_AP("#5");
6593       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6594       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6595                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6596
6597       _startLazyDPSEvaluation();
6598       for (size = compSize; (size--); offset++)
6599       {
6600           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6601           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6602           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6603
6604           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6605           emitcode ("push", "acc");
6606       }
6607       _endLazyDPSEvaluation();
6608
6609       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6610       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6611       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6612
6613       resultSize = AOP_SIZE(IC_RESULT(ic));
6614
6615       ADJUST_PUSHED_RESULT(compSize, resultSize);
6616
6617       _startLazyDPSEvaluation();
6618       while (compSize--)
6619       {
6620           emitcode ("pop", "acc");
6621           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6622       }
6623       _endLazyDPSEvaluation();
6624       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6625 }
6626
6627
6628 /*-----------------------------------------------------------------*/
6629 /* genAnd  - code for and                                          */
6630 /*-----------------------------------------------------------------*/
6631 static void
6632 genAnd (iCode * ic, iCode * ifx)
6633 {
6634   operand *left, *right, *result;
6635   int size, offset = 0;
6636   unsigned long lit = 0L;
6637   int bytelit;
6638   char buff[10];
6639   bool pushResult;
6640
6641   D (emitcode (";", "genAnd "););
6642
6643   AOP_OP_3_NOFATAL (ic, pushResult);
6644   AOP_SET_LOCALS (ic);
6645
6646   if (pushResult)
6647   {
6648       genFarFarLogicOp(ic, "anl");
6649       return;
6650   }
6651
6652 #ifdef DEBUG_TYPE
6653   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6654             AOP_TYPE (result),
6655             AOP_TYPE (left), AOP_TYPE (right));
6656   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6657             AOP_SIZE (result),
6658             AOP_SIZE (left), AOP_SIZE (right));
6659 #endif
6660
6661   /* if left is a literal & right is not then exchange them */
6662   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6663 #ifdef LOGIC_OPS_BROKEN
6664     ||  AOP_NEEDSACC (left)
6665 #endif
6666     )
6667     {
6668       operand *tmp = right;
6669       right = left;
6670       left = tmp;
6671     }
6672
6673   /* if result = right then exchange left and right */
6674   if (sameRegs (AOP (result), AOP (right)))
6675     {
6676       operand *tmp = right;
6677       right = left;
6678       left = tmp;
6679     }
6680
6681   /* if right is bit then exchange them */
6682   if (AOP_TYPE (right) == AOP_CRY &&
6683       AOP_TYPE (left) != AOP_CRY)
6684     {
6685       operand *tmp = right;
6686       right = left;
6687       left = tmp;
6688     }
6689   if (AOP_TYPE (right) == AOP_LIT)
6690     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6691
6692   size = AOP_SIZE (result);
6693
6694   // if(bit & yy)
6695   // result = bit & yy;
6696   if (AOP_TYPE (left) == AOP_CRY)
6697     {
6698       // c = bit & literal;
6699       if (AOP_TYPE (right) == AOP_LIT)
6700         {
6701           if (lit & 1)
6702             {
6703               if (size && sameRegs (AOP (result), AOP (left)))
6704                 // no change
6705                 goto release;
6706               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6707             }
6708           else
6709             {
6710               // bit(result) = 0;
6711               if (size && (AOP_TYPE (result) == AOP_CRY))
6712                 {
6713                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6714                   goto release;
6715                 }
6716               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6717                 {
6718                   jumpIfTrue (ifx);
6719                   goto release;
6720                 }
6721               emitcode ("clr", "c");
6722             }
6723         }
6724       else
6725         {
6726           if (AOP_TYPE (right) == AOP_CRY)
6727             {
6728               // c = bit & bit;
6729               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6730               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6731             }
6732           else
6733             {
6734               // c = bit & val;
6735               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6736               // c = lsb
6737               emitcode ("rrc", "a");
6738               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6739             }
6740         }
6741       // bit = c
6742       // val = c
6743       if (size)
6744         outBitC (result);
6745       // if(bit & ...)
6746       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6747         genIfxJump (ifx, "c");
6748       goto release;
6749     }
6750
6751   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6752   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6753   if ((AOP_TYPE (right) == AOP_LIT) &&
6754       (AOP_TYPE (result) == AOP_CRY) &&
6755       (AOP_TYPE (left) != AOP_CRY))
6756     {
6757       int posbit = isLiteralBit (lit);
6758       /* left &  2^n */
6759       if (posbit)
6760         {
6761           posbit--;
6762           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6763           // bit = left & 2^n
6764           if (size)
6765             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6766           // if(left &  2^n)
6767           else
6768             {
6769               if (ifx)
6770                 {
6771                   SNPRINTF (buff, sizeof(buff),
6772                             "acc.%d", posbit & 0x07);
6773                   genIfxJump (ifx, buff);
6774                 }
6775               else
6776                   {
6777                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6778                   }
6779               goto release;
6780             }
6781         }
6782       else
6783         {
6784           symbol *tlbl = newiTempLabel (NULL);
6785           int sizel = AOP_SIZE (left);
6786           if (size)
6787             emitcode ("setb", "c");
6788           while (sizel--)
6789             {
6790               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6791                 {
6792                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6793                   // byte ==  2^n ?
6794                   if ((posbit = isLiteralBit (bytelit)) != 0)
6795                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6796                   else
6797                     {
6798                       if (bytelit != 0x0FFL)
6799                         emitcode ("anl", "a,%s",
6800                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6801                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6802                     }
6803                 }
6804               offset++;
6805             }
6806           // bit = left & literal
6807           if (size)
6808             {
6809               emitcode ("clr", "c");
6810               emitcode ("", "!tlabeldef", tlbl->key + 100);
6811             }
6812           // if(left & literal)
6813           else
6814             {
6815               if (ifx)
6816                 jmpTrueOrFalse (ifx, tlbl);
6817               else
6818                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6819               goto release;
6820             }
6821         }
6822       outBitC (result);
6823       goto release;
6824     }
6825
6826   /* if left is same as result */
6827   if (sameRegs (AOP (result), AOP (left)))
6828     {
6829       for (; size--; offset++)
6830         {
6831           if (AOP_TYPE (right) == AOP_LIT)
6832             {
6833               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6834               if (bytelit == 0x0FF)
6835                 {
6836                   /* dummy read of volatile operand */
6837                   if (isOperandVolatile (left, FALSE))
6838                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6839                   else
6840                     continue;
6841                 }
6842               else if (bytelit == 0)
6843                 {
6844                   aopPut (AOP (result), zero, offset);
6845                 }
6846               else if (IS_AOP_PREG (result))
6847                 {
6848                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6849                   emitcode ("anl", "a,%s",
6850                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6851                   aopPut (AOP (result), "a", offset);
6852                 }
6853               else
6854                 emitcode ("anl", "%s,%s",
6855                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6856                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6857             }
6858           else
6859             {
6860               if (AOP_TYPE (left) == AOP_ACC)
6861                 emitcode ("anl", "a,%s",
6862                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6863               else
6864                 {
6865                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6866                   if (IS_AOP_PREG (result))
6867                     {
6868                       emitcode ("anl", "a,%s",
6869                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6870                       aopPut (AOP (result), "a", offset);
6871                     }
6872                   else
6873                     emitcode ("anl", "%s,a",
6874                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6875                 }
6876             }
6877         }
6878     }
6879   else
6880     {
6881       // left & result in different registers
6882       if (AOP_TYPE (result) == AOP_CRY)
6883         {
6884           // result = bit
6885           // if(size), result in bit
6886           // if(!size && ifx), conditional oper: if(left & right)
6887           symbol *tlbl = newiTempLabel (NULL);
6888           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6889           if (size)
6890             emitcode ("setb", "c");
6891           while (sizer--)
6892             {
6893               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6894                 emitcode ("anl", "a,%s",
6895                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6896               } else {
6897                 if (AOP_TYPE(left)==AOP_ACC) {
6898                   emitcode("mov", "b,a");
6899                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6900                   emitcode("anl", "a,b");
6901                 }else {
6902                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6903                   emitcode ("anl", "a,%s",
6904                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6905                 }
6906               }
6907               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6908               offset++;
6909             }
6910           if (size)
6911             {
6912               CLRC;
6913               emitcode ("", "!tlabeldef", tlbl->key + 100);
6914               outBitC (result);
6915             }
6916           else if (ifx)
6917             jmpTrueOrFalse (ifx, tlbl);
6918           else
6919             emitcode ("", "!tlabeldef", tlbl->key + 100);
6920         }
6921       else
6922         {
6923           for (; (size--); offset++)
6924             {
6925               // normal case
6926               // result = left & right
6927               if (AOP_TYPE (right) == AOP_LIT)
6928                 {
6929                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6930                   if (bytelit == 0x0FF)
6931                     {
6932                       aopPut (AOP (result),
6933                               aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6934                               offset);
6935                       continue;
6936                     }
6937                   else if (bytelit == 0)
6938                     {
6939                       /* dummy read of volatile operand */
6940                       if (isOperandVolatile (left, FALSE))
6941                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6942                       aopPut (AOP (result), zero, offset);
6943                       continue;
6944                     }
6945                   D (emitcode (";", "better literal AND."););
6946                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6947                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6948                                                     FALSE, FALSE, DP2_RESULT_REG));
6949
6950                 }
6951               else
6952                 {
6953                   // faster than result <- left, anl result,right
6954                   // and better if result is SFR
6955                   if (AOP_TYPE (left) == AOP_ACC)
6956                     {
6957                       emitcode ("anl", "a,%s",
6958                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6959                     }
6960                   else
6961                     {
6962                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6963                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6964                       {
6965                           emitcode("mov", "b,a");
6966                           rOp = "b";
6967                       }
6968
6969                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6970                       emitcode ("anl", "a,%s", rOp);
6971                     }
6972                 }
6973               aopPut (AOP (result), "a", offset);
6974             }
6975         }
6976     }
6977
6978 release:
6979   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6980   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6981   freeAsmop (result, NULL, ic, TRUE);
6982 }
6983
6984
6985 /*-----------------------------------------------------------------*/
6986 /* genOr  - code for or                                            */
6987 /*-----------------------------------------------------------------*/
6988 static void
6989 genOr (iCode * ic, iCode * ifx)
6990 {
6991   operand *left, *right, *result;
6992   int size, offset = 0;
6993   unsigned long lit = 0L;
6994   int bytelit = 0;
6995   bool     pushResult;
6996
6997   D (emitcode (";", "genOr "););
6998
6999   AOP_OP_3_NOFATAL (ic, pushResult);
7000   AOP_SET_LOCALS (ic);
7001
7002   if (pushResult)
7003   {
7004       genFarFarLogicOp(ic, "orl");
7005       return;
7006   }
7007
7008
7009 #ifdef DEBUG_TYPE
7010   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7011             AOP_TYPE (result),
7012             AOP_TYPE (left), AOP_TYPE (right));
7013   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7014             AOP_SIZE (result),
7015             AOP_SIZE (left), AOP_SIZE (right));
7016 #endif
7017
7018   /* if left is a literal & right is not then exchange them */
7019   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7020 #ifdef LOGIC_OPS_BROKEN
7021    || AOP_NEEDSACC (left) // I think this is a net loss now.
7022 #endif
7023       )
7024     {
7025       operand *tmp = right;
7026       right = left;
7027       left = tmp;
7028     }
7029
7030   /* if result = right then exchange them */
7031   if (sameRegs (AOP (result), AOP (right)))
7032     {
7033       operand *tmp = right;
7034       right = left;
7035       left = tmp;
7036     }
7037
7038   /* if right is bit then exchange them */
7039   if (AOP_TYPE (right) == AOP_CRY &&
7040       AOP_TYPE (left) != AOP_CRY)
7041     {
7042       operand *tmp = right;
7043       right = left;
7044       left = tmp;
7045     }
7046   if (AOP_TYPE (right) == AOP_LIT)
7047     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7048
7049   size = AOP_SIZE (result);
7050
7051   // if(bit | yy)
7052   // xx = bit | yy;
7053   if (AOP_TYPE (left) == AOP_CRY)
7054     {
7055       if (AOP_TYPE (right) == AOP_LIT)
7056         {
7057           // c = bit & literal;
7058           if (lit)
7059             {
7060               // lit != 0 => result = 1
7061               if (AOP_TYPE (result) == AOP_CRY)
7062                 {
7063                   if (size)
7064                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7065                   else if (ifx)
7066                     continueIfTrue (ifx);
7067                   goto release;
7068                 }
7069               emitcode ("setb", "c");
7070             }
7071           else
7072             {
7073               // lit == 0 => result = left
7074               if (size && sameRegs (AOP (result), AOP (left)))
7075                 goto release;
7076               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7077             }
7078         }
7079       else
7080         {
7081           if (AOP_TYPE (right) == AOP_CRY)
7082             {
7083               // c = bit | bit;
7084               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7085               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7086             }
7087           else
7088             {
7089               // c = bit | val;
7090               symbol *tlbl = newiTempLabel (NULL);
7091               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7092                 emitcode ("setb", "c");
7093               emitcode ("jb", "%s,!tlabel",
7094                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7095               toBoolean (right);
7096               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7097               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7098                 {
7099                   jmpTrueOrFalse (ifx, tlbl);
7100                   goto release;
7101                 }
7102               else
7103                 {
7104                   CLRC;
7105                   emitcode ("", "!tlabeldef", tlbl->key + 100);
7106                 }
7107             }
7108         }
7109       // bit = c
7110       // val = c
7111       if (size)
7112         outBitC (result);
7113       // if(bit | ...)
7114       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7115            genIfxJump (ifx, "c");
7116       goto release;
7117     }
7118
7119   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7120   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7121   if ((AOP_TYPE (right) == AOP_LIT) &&
7122       (AOP_TYPE (result) == AOP_CRY) &&
7123       (AOP_TYPE (left) != AOP_CRY))
7124     {
7125       if (lit)
7126         {
7127           // result = 1
7128           if (size)
7129             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7130           else
7131             continueIfTrue (ifx);
7132           goto release;
7133         }
7134       else
7135         {
7136           // lit = 0, result = boolean(left)
7137           if (size)
7138             emitcode ("setb", "c");
7139           toBoolean (right);
7140           if (size)
7141             {
7142               symbol *tlbl = newiTempLabel (NULL);
7143               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7144               CLRC;
7145               emitcode ("", "!tlabeldef", tlbl->key + 100);
7146             }
7147           else
7148             {
7149               genIfxJump (ifx, "a");
7150               goto release;
7151             }
7152         }
7153       outBitC (result);
7154       goto release;
7155     }
7156
7157   /* if left is same as result */
7158   if (sameRegs (AOP (result), AOP (left)))
7159     {
7160       for (; size--; offset++)
7161         {
7162           if (AOP_TYPE (right) == AOP_LIT)
7163             {
7164               bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7165               if (bytelit == 0x00L)
7166                 {
7167                   /* dummy read of volatile operand */
7168                   if (isOperandVolatile (left, FALSE))
7169                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7170                   else
7171                     continue;
7172                 }
7173               else if (bytelit == 0x0FF)
7174                 {
7175                   aopPut (AOP (result), "#0xFF", offset);
7176                 }
7177               else if (IS_AOP_PREG (left))
7178                 {
7179                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7180                   emitcode ("orl", "a,%s",
7181                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7182                   aopPut (AOP (result), "a", offset);
7183                 }
7184               else
7185                 {
7186                   emitcode ("orl", "%s,%s",
7187                             aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7188                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7189                 }
7190             }
7191           else
7192             {
7193               if (AOP_TYPE (left) == AOP_ACC)
7194                 {
7195                   emitcode ("orl", "a,%s",
7196                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7197                 }
7198               else
7199                 {
7200                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7201                   if (IS_AOP_PREG (left))
7202                     {
7203                       emitcode ("orl", "a,%s",
7204                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7205                       aopPut (AOP (result), "a", offset);
7206                     }
7207                   else
7208                     {
7209                       emitcode ("orl", "%s,a",
7210                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7211                     }
7212                 }
7213             }
7214         }
7215     }
7216   else
7217     {
7218       // left & result in different registers
7219       if (AOP_TYPE (result) == AOP_CRY)
7220         {
7221           // result = bit
7222           // if(size), result in bit
7223           // if(!size && ifx), conditional oper: if(left | right)
7224           symbol *tlbl = newiTempLabel (NULL);
7225           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7226           if (size)
7227             emitcode ("setb", "c");
7228           while (sizer--)
7229             {
7230               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7231                 emitcode ("orl", "a,%s",
7232                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7233               } else {
7234                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7235                 emitcode ("orl", "a,%s",
7236                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7237               }
7238               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7239               offset++;
7240             }
7241           if (size)
7242             {
7243               CLRC;
7244               emitcode ("", "!tlabeldef", tlbl->key + 100);
7245               outBitC (result);
7246             }
7247           else if (ifx)
7248             jmpTrueOrFalse (ifx, tlbl);
7249           else
7250             emitcode ("", "!tlabeldef", tlbl->key + 100);
7251         }
7252       else
7253         {
7254             _startLazyDPSEvaluation();
7255           for (; (size--); offset++)
7256             {
7257               // normal case
7258               // result = left & right
7259               if (AOP_TYPE (right) == AOP_LIT)
7260                 {
7261                   bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7262                   if (bytelit == 0x00L)
7263                     {
7264                       aopPut (AOP (result),
7265                               aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7266                               offset);
7267                       continue;
7268                     }
7269                   else if (bytelit == 0x0FF)
7270                     {
7271                       /* dummy read of volatile operand */
7272                       if (isOperandVolatile (left, FALSE))
7273                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7274                       aopPut (AOP (result), "#0xFF", offset);
7275                       continue;
7276                     }
7277                   D (emitcode (";", "better literal OR."););
7278                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7279                   emitcode ("orl", "a, %s",
7280                             aopGet (AOP (right), offset,
7281                                     FALSE, FALSE, DP2_RESULT_REG));
7282
7283                 }
7284               else
7285                 {
7286                   // faster than result <- left, anl result,right
7287                   // and better if result is SFR
7288                   if (AOP_TYPE (left) == AOP_ACC)
7289                     {
7290                       emitcode ("orl", "a,%s",
7291                                 aopGet (AOP (right), offset,
7292                                         FALSE, FALSE, DP2_RESULT_REG));
7293                     }
7294                   else
7295                     {
7296                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7297
7298                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7299                       {
7300                           emitcode("mov", "b,a");
7301                           rOp = "b";
7302                       }
7303
7304                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7305                       emitcode ("orl", "a,%s", rOp);
7306                     }
7307                 }
7308               aopPut (AOP (result), "a", offset);
7309             }
7310             _endLazyDPSEvaluation();
7311         }
7312     }
7313
7314 release:
7315   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7316   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7317   freeAsmop (result, NULL, ic, TRUE);
7318 }
7319
7320 /*-----------------------------------------------------------------*/
7321 /* genXor - code for xclusive or                                   */
7322 /*-----------------------------------------------------------------*/
7323 static void
7324 genXor (iCode * ic, iCode * ifx)
7325 {
7326   operand *left, *right, *result;
7327   int size, offset = 0;
7328   unsigned long lit = 0L;
7329   int bytelit = 0;
7330   bool pushResult;
7331
7332   D (emitcode (";", "genXor "););
7333
7334   AOP_OP_3_NOFATAL (ic, pushResult);
7335   AOP_SET_LOCALS (ic);
7336
7337   if (pushResult)
7338   {
7339       genFarFarLogicOp(ic, "xrl");
7340       return;
7341   }
7342
7343 #ifdef DEBUG_TYPE
7344   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7345             AOP_TYPE (result),
7346             AOP_TYPE (left), AOP_TYPE (right));
7347   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7348             AOP_SIZE (result),
7349             AOP_SIZE (left), AOP_SIZE (right));
7350 #endif
7351
7352   /* if left is a literal & right is not ||
7353      if left needs acc & right does not */
7354   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7355 #ifdef LOGIC_OPS_BROKEN
7356       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7357 #endif
7358      )
7359     {
7360       operand *tmp = right;
7361       right = left;
7362       left = tmp;
7363     }
7364
7365   /* if result = right then exchange them */
7366   if (sameRegs (AOP (result), AOP (right)))
7367     {
7368       operand *tmp = right;
7369       right = left;
7370       left = tmp;
7371     }
7372
7373   /* if right is bit then exchange them */
7374   if (AOP_TYPE (right) == AOP_CRY &&
7375       AOP_TYPE (left) != AOP_CRY)
7376     {
7377       operand *tmp = right;
7378       right = left;
7379       left = tmp;
7380     }
7381   if (AOP_TYPE (right) == AOP_LIT)
7382     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7383
7384   size = AOP_SIZE (result);
7385
7386   // if(bit ^ yy)
7387   // xx = bit ^ yy;
7388   if (AOP_TYPE (left) == AOP_CRY)
7389     {
7390       if (AOP_TYPE (right) == AOP_LIT)
7391         {
7392           // c = bit & literal;
7393           if (lit >> 1)
7394             {
7395               // lit>>1  != 0 => result = 1
7396               if (AOP_TYPE (result) == AOP_CRY)
7397                 {
7398                   if (size)
7399                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7400                   else if (ifx)
7401                     continueIfTrue (ifx);
7402                   goto release;
7403                 }
7404               emitcode ("setb", "c");
7405             }
7406           else
7407             {
7408               // lit == (0 or 1)
7409               if (lit == 0)
7410                 {
7411                   // lit == 0, result = left
7412                   if (size && sameRegs (AOP (result), AOP (left)))
7413                     goto release;
7414                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7415                 }
7416               else
7417                 {
7418                   // lit == 1, result = not(left)
7419                   if (size && sameRegs (AOP (result), AOP (left)))
7420                     {
7421                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7422                       goto release;
7423                     }
7424                   else
7425                     {
7426                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7427                       emitcode ("cpl", "c");
7428                     }
7429                 }
7430             }
7431
7432         }
7433       else
7434         {
7435           // right != literal
7436           symbol *tlbl = newiTempLabel (NULL);
7437           if (AOP_TYPE (right) == AOP_CRY)
7438             {
7439               // c = bit ^ bit;
7440               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7441             }
7442           else
7443             {
7444               int sizer = AOP_SIZE (right);
7445               // c = bit ^ val
7446               // if val>>1 != 0, result = 1
7447               emitcode ("setb", "c");
7448               while (sizer)
7449                 {
7450                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7451                   if (sizer == 1)
7452                     // test the msb of the lsb
7453                     emitcode ("anl", "a,#!constbyte",0xfe);
7454                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
7455                   sizer--;
7456                 }
7457               // val = (0,1)
7458               emitcode ("rrc", "a");
7459             }
7460           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7461           emitcode ("cpl", "c");
7462           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7463         }
7464       // bit = c
7465       // val = c
7466       if (size)
7467         outBitC (result);
7468       // if(bit | ...)
7469       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7470         genIfxJump (ifx, "c");
7471       goto release;
7472     }
7473
7474   /* if left is same as result */
7475   if (sameRegs (AOP (result), AOP (left)))
7476     {
7477       for (; size--; offset++)
7478         {
7479           if (AOP_TYPE (right) == AOP_LIT)
7480             {
7481               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7482               if (bytelit == 0x00L)
7483                 {
7484                   /* dummy read of volatile operand */
7485                   if (isOperandVolatile (left, FALSE))
7486                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7487                   else
7488                     continue;
7489                 }
7490               else if (IS_AOP_PREG (left))
7491                 {
7492                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7493                   emitcode ("xrl", "a,%s",
7494                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7495                   aopPut (AOP (result), "a", offset);
7496                 }
7497               else
7498                 {
7499                   emitcode ("xrl", "%s,%s",
7500                             aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7501                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7502                 }
7503             }
7504           else
7505             {
7506               if (AOP_TYPE (left) == AOP_ACC)
7507                 emitcode ("xrl", "a,%s",
7508                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7509               else
7510                 {
7511                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7512                   if (IS_AOP_PREG (left))
7513                     {
7514                       emitcode ("xrl", "a,%s",
7515                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7516                       aopPut (AOP (result), "a", offset);
7517                     }
7518                   else
7519                     emitcode ("xrl", "%s,a",
7520                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7521                 }
7522             }
7523         }
7524     }
7525   else
7526     {
7527       // left & result in different registers
7528       if (AOP_TYPE (result) == AOP_CRY)
7529         {
7530           // result = bit
7531           // if(size), result in bit
7532           // if(!size && ifx), conditional oper: if(left ^ right)
7533           symbol *tlbl = newiTempLabel (NULL);
7534           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7535
7536           if (size)
7537             emitcode ("setb", "c");
7538           while (sizer--)
7539             {
7540               if ((AOP_TYPE (right) == AOP_LIT) &&
7541                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7542                 {
7543                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7544                 }
7545               else
7546                 {
7547                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7548                     emitcode ("xrl", "a,%s",
7549                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7550                   } else {
7551                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7552                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7553                       {
7554                           emitcode("mov", "b,a");
7555                           rOp = "b";
7556                       }
7557
7558                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7559                       emitcode ("xrl", "a,%s", rOp);
7560                   }
7561                 }
7562               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7563               offset++;
7564             }
7565           if (size)
7566             {
7567               CLRC;
7568               emitcode ("", "!tlabeldef", tlbl->key + 100);
7569               outBitC (result);
7570             }
7571           else if (ifx)
7572             jmpTrueOrFalse (ifx, tlbl);
7573         }
7574       else
7575         {
7576         for (; (size--); offset++)
7577           {
7578             // normal case
7579             // result = left & right
7580             if (AOP_TYPE (right) == AOP_LIT)
7581               {
7582                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7583                   {
7584                     aopPut (AOP (result),
7585                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7586                             offset);
7587                     continue;
7588                   }
7589                 D (emitcode (";", "better literal XOR."););
7590                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7591                 emitcode ("xrl", "a, %s",
7592                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7593               }
7594             else
7595               {
7596                 // faster than result <- left, anl result,right
7597                 // and better if result is SFR
7598                 if (AOP_TYPE (left) == AOP_ACC)
7599                   {
7600                     emitcode ("xrl", "a,%s",
7601                               aopGet (AOP (right), offset,
7602                                       FALSE, FALSE, DP2_RESULT_REG));
7603                   }
7604                 else
7605                   {
7606                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7607                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7608                       {
7609                           emitcode("mov", "b,a");
7610                           rOp = "b";
7611                       }
7612
7613                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7614                       emitcode ("xrl", "a,%s", rOp);
7615                   }
7616               }
7617             aopPut (AOP (result), "a", offset);
7618           }
7619         }
7620
7621     }
7622
7623 release:
7624   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7625   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7626   freeAsmop (result, NULL, ic, TRUE);
7627 }
7628
7629 /*-----------------------------------------------------------------*/
7630 /* genInline - write the inline code out                           */
7631 /*-----------------------------------------------------------------*/
7632 static void
7633 genInline (iCode * ic)
7634 {
7635   char *buffer, *bp, *bp1;
7636
7637   D (emitcode (";", "genInline "); );
7638
7639   _G.inLine += (!options.asmpeep);
7640
7641   buffer = Safe_strdup(IC_INLINE(ic));
7642   bp = buffer;
7643   bp1 = buffer;
7644
7645   /* emit each line as a code */
7646   while (*bp)
7647     {
7648       if (*bp == '\n')
7649         {
7650           *bp++ = '\0';
7651           emitcode (bp1, "");
7652           bp1 = bp;
7653         }
7654       else
7655         {
7656           if (*bp == ':')
7657             {
7658               bp++;
7659               *bp = '\0';
7660               bp++;
7661               emitcode (bp1, "");
7662               bp1 = bp;
7663             }
7664           else
7665             bp++;
7666         }
7667     }
7668   if (bp1 != bp)
7669     emitcode (bp1, "");
7670   /*     emitcode("",buffer); */
7671   _G.inLine -= (!options.asmpeep);
7672 }
7673
7674 /*-----------------------------------------------------------------*/
7675 /* genRRC - rotate right with carry                                */
7676 /*-----------------------------------------------------------------*/
7677 static void
7678 genRRC (iCode * ic)
7679 {
7680   operand *left, *result;
7681   int     size, offset;
7682
7683   D (emitcode (";", "genRRC "););
7684
7685   /* rotate right with carry */
7686   left = IC_LEFT (ic);
7687   result = IC_RESULT (ic);
7688   aopOp (left, ic, FALSE, FALSE);
7689   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7690
7691   /* move it to the result */
7692   size = AOP_SIZE (result);
7693   offset = size - 1;
7694   CLRC;
7695
7696   _startLazyDPSEvaluation ();
7697   while (size--)
7698     {
7699       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7700       emitcode ("rrc", "a");
7701       if (AOP_SIZE (result) > 1)
7702         aopPut (AOP (result), "a", offset--);
7703     }
7704   _endLazyDPSEvaluation ();
7705
7706   /* now we need to put the carry into the
7707      highest order byte of the result */
7708   if (AOP_SIZE (result) > 1)
7709     {
7710       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7711     }
7712   emitcode ("mov", "acc.7,c");
7713   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7714   freeAsmop (left, NULL, ic, TRUE);
7715   freeAsmop (result, NULL, ic, TRUE);
7716 }
7717
7718 /*-----------------------------------------------------------------*/
7719 /* genRLC - generate code for rotate left with carry               */
7720 /*-----------------------------------------------------------------*/
7721 static void
7722 genRLC (iCode * ic)
7723 {
7724   operand *left, *result;
7725   int size, offset;
7726   char *l;
7727
7728   D (emitcode (";", "genRLC "););
7729
7730   /* rotate right with carry */
7731   left = IC_LEFT (ic);
7732   result = IC_RESULT (ic);
7733   aopOp (left, ic, FALSE, FALSE);
7734   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7735
7736   /* move it to the result */
7737   size = AOP_SIZE (result);
7738   offset = 0;
7739   if (size--)
7740     {
7741       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7742       MOVA (l);
7743       emitcode ("add", "a,acc");
7744       if (AOP_SIZE (result) > 1)
7745         {
7746           aopPut (AOP (result), "a", offset++);
7747         }
7748
7749       _startLazyDPSEvaluation ();
7750       while (size--)
7751         {
7752           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7753           MOVA (l);
7754           emitcode ("rlc", "a");
7755           if (AOP_SIZE (result) > 1)
7756             aopPut (AOP (result), "a", offset++);
7757         }
7758       _endLazyDPSEvaluation ();
7759     }
7760   /* now we need to put the carry into the
7761      highest order byte of the result */
7762   if (AOP_SIZE (result) > 1)
7763     {
7764       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7765       MOVA (l);
7766     }
7767   emitcode ("mov", "acc.0,c");
7768   aopPut (AOP (result), "a", 0);
7769   freeAsmop (left, NULL, ic, TRUE);
7770   freeAsmop (result, NULL, ic, TRUE);
7771 }
7772
7773 /*-----------------------------------------------------------------*/
7774 /* genGetHbit - generates code get highest order bit               */
7775 /*-----------------------------------------------------------------*/
7776 static void
7777 genGetHbit (iCode * ic)
7778 {
7779   operand *left, *result;
7780   left = IC_LEFT (ic);
7781   result = IC_RESULT (ic);
7782   aopOp (left, ic, FALSE, FALSE);
7783   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7784
7785   D (emitcode (";", "genGetHbit "););
7786
7787   /* get the highest order byte into a */
7788   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7789   if (AOP_TYPE (result) == AOP_CRY)
7790     {
7791       emitcode ("rlc", "a");
7792       outBitC (result);
7793     }
7794   else
7795     {
7796       emitcode ("rl", "a");
7797       emitcode ("anl", "a,#1");
7798       outAcc (result);
7799     }
7800
7801
7802   freeAsmop (left, NULL, ic, TRUE);
7803   freeAsmop (result, NULL, ic, TRUE);
7804 }
7805
7806 /*-----------------------------------------------------------------*/
7807 /* genSwap - generates code to swap nibbles or bytes               */
7808 /*-----------------------------------------------------------------*/
7809 static void
7810 genSwap (iCode * ic)
7811 {
7812   operand *left, *result;
7813
7814   D(emitcode (";     genSwap",""));
7815
7816   left = IC_LEFT (ic);
7817   result = IC_RESULT (ic);
7818   aopOp (left, ic, FALSE, FALSE);
7819   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7820
7821   _startLazyDPSEvaluation ();
7822   switch (AOP_SIZE (left))
7823     {
7824     case 1: /* swap nibbles in byte */
7825       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7826       emitcode ("swap", "a");
7827       aopPut (AOP (result), "a", 0);
7828       break;
7829     case 2: /* swap bytes in word */
7830       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7831         {
7832           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7833           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7834           aopPut (AOP (result), "a", 1);
7835         }
7836       else if (operandsEqu (left, result))
7837         {
7838           char * reg = "a";
7839           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7840           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7841             {
7842               emitcode ("mov", "b,a");
7843               reg = "b";
7844               _G.bInUse=1;
7845             }
7846           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7847           aopPut (AOP (result), reg, 1);
7848           _G.bInUse=0;
7849         }
7850       else
7851         {
7852           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7853           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7854         }
7855       break;
7856     default:
7857       wassertl(FALSE, "unsupported SWAP operand size");
7858     }
7859   _endLazyDPSEvaluation ();
7860
7861   freeAsmop (left, NULL, ic, TRUE);
7862   freeAsmop (result, NULL, ic, TRUE);
7863 }
7864
7865 /*-----------------------------------------------------------------*/
7866 /* AccRol - rotate left accumulator by known count                 */
7867 /*-----------------------------------------------------------------*/
7868 static void
7869 AccRol (int shCount)
7870 {
7871   shCount &= 0x0007;            // shCount : 0..7
7872
7873   switch (shCount)
7874     {
7875     case 0:
7876       break;
7877     case 1:
7878       emitcode ("rl", "a");
7879       break;
7880     case 2:
7881       emitcode ("rl", "a");
7882       emitcode ("rl", "a");
7883       break;
7884     case 3:
7885       emitcode ("swap", "a");
7886       emitcode ("rr", "a");
7887       break;
7888     case 4:
7889       emitcode ("swap", "a");
7890       break;
7891     case 5:
7892       emitcode ("swap", "a");
7893       emitcode ("rl", "a");
7894       break;
7895     case 6:
7896       emitcode ("rr", "a");
7897       emitcode ("rr", "a");
7898       break;
7899     case 7:
7900       emitcode ("rr", "a");
7901       break;
7902     }
7903 }
7904
7905 /*-----------------------------------------------------------------*/
7906 /* AccLsh - left shift accumulator by known count                  */
7907 /*-----------------------------------------------------------------*/
7908 static void
7909 AccLsh (int shCount)
7910 {
7911   if (shCount != 0)
7912     {
7913       if (shCount == 1)
7914         emitcode ("add", "a,acc");
7915       else if (shCount == 2)
7916         {
7917           emitcode ("add", "a,acc");
7918           emitcode ("add", "a,acc");
7919         }
7920       else
7921         {
7922           /* rotate left accumulator */
7923           AccRol (shCount);
7924           /* and kill the lower order bits */
7925           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7926         }
7927     }
7928 }
7929
7930 /*-----------------------------------------------------------------*/
7931 /* AccRsh - right shift accumulator by known count                 */
7932 /*-----------------------------------------------------------------*/
7933 static void
7934 AccRsh (int shCount)
7935 {
7936   if (shCount != 0)
7937     {
7938       if (shCount == 1)
7939         {
7940           CLRC;
7941           emitcode ("rrc", "a");
7942         }
7943       else
7944         {
7945           /* rotate right accumulator */
7946           AccRol (8 - shCount);
7947           /* and kill the higher order bits */
7948           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7949         }
7950     }
7951 }
7952
7953 #ifdef BETTER_LITERAL_SHIFT
7954 /*-----------------------------------------------------------------*/
7955 /* AccSRsh - signed right shift accumulator by known count                 */
7956 /*-----------------------------------------------------------------*/
7957 static void
7958 AccSRsh (int shCount)
7959 {
7960   symbol *tlbl;
7961   if (shCount != 0)
7962     {
7963       if (shCount == 1)
7964         {
7965           emitcode ("mov", "c,acc.7");
7966           emitcode ("rrc", "a");
7967         }
7968       else if (shCount == 2)
7969         {
7970           emitcode ("mov", "c,acc.7");
7971           emitcode ("rrc", "a");
7972           emitcode ("mov", "c,acc.7");
7973           emitcode ("rrc", "a");
7974         }
7975       else
7976         {
7977           tlbl = newiTempLabel (NULL);
7978           /* rotate right accumulator */
7979           AccRol (8 - shCount);
7980           /* and kill the higher order bits */
7981           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7982           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7983           emitcode ("orl", "a,#!constbyte",
7984                     (unsigned char) ~SRMask[shCount]);
7985           emitcode ("", "!tlabeldef", tlbl->key + 100);
7986         }
7987     }
7988 }
7989 #endif
7990
7991 #ifdef BETTER_LITERAL_SHIFT
7992 /*-----------------------------------------------------------------*/
7993 /* shiftR1Left2Result - shift right one byte from left to result   */
7994 /*-----------------------------------------------------------------*/
7995 static void
7996 shiftR1Left2Result (operand * left, int offl,
7997                     operand * result, int offr,
7998                     int shCount, int sign)
7999 {
8000   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8001   /* shift right accumulator */
8002   if (sign)
8003     AccSRsh (shCount);
8004   else
8005     AccRsh (shCount);
8006   aopPut (AOP (result), "a", offr);
8007 }
8008 #endif
8009
8010 #ifdef BETTER_LITERAL_SHIFT
8011 /*-----------------------------------------------------------------*/
8012 /* shiftL1Left2Result - shift left one byte from left to result    */
8013 /*-----------------------------------------------------------------*/
8014 static void
8015 shiftL1Left2Result (operand * left, int offl,
8016                     operand * result, int offr, int shCount)
8017 {
8018   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8019   /* shift left accumulator */
8020   AccLsh (shCount);
8021   aopPut (AOP (result), "a", offr);
8022 }
8023 #endif
8024
8025 #ifdef BETTER_LITERAL_SHIFT
8026 /*-----------------------------------------------------------------*/
8027 /* movLeft2Result - move byte from left to result                  */
8028 /*-----------------------------------------------------------------*/
8029 static void
8030 movLeft2Result (operand * left, int offl,
8031                 operand * result, int offr, int sign)
8032 {
8033   char *l;
8034   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8035   {
8036       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8037
8038       if (*l == '@' && (IS_AOP_PREG (result)))
8039       {
8040           emitcode ("mov", "a,%s", l);
8041           aopPut (AOP (result), "a", offr);
8042       }
8043       else
8044       {
8045           if (!sign)
8046           {
8047             aopPut (AOP (result), l, offr);
8048           }
8049           else
8050             {
8051               /* MSB sign in acc.7 ! */
8052               if (getDataSize (left) == offl + 1)
8053                 {
8054                   emitcode ("mov", "a,%s", l);
8055                   aopPut (AOP (result), "a", offr);
8056                 }
8057             }
8058       }
8059   }
8060 }
8061 #endif
8062
8063 #ifdef BETTER_LITERAL_SHIFT
8064 /*-----------------------------------------------------------------*/
8065 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8066 /*-----------------------------------------------------------------*/
8067 static void
8068 AccAXRrl1 (char *x)
8069 {
8070   emitcode ("rrc", "a");
8071   emitcode ("xch", "a,%s", x);
8072   emitcode ("rrc", "a");
8073   emitcode ("xch", "a,%s", x);
8074 }
8075 #endif
8076
8077 #ifdef BETTER_LITERAL_SHIFT
8078 //REMOVE ME!!!
8079 /*-----------------------------------------------------------------*/
8080 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8081 /*-----------------------------------------------------------------*/
8082 static void
8083 AccAXLrl1 (char *x)
8084 {
8085   emitcode ("xch", "a,%s", x);
8086   emitcode ("rlc", "a");
8087   emitcode ("xch", "a,%s", x);
8088   emitcode ("rlc", "a");
8089 }
8090 #endif
8091
8092 #ifdef BETTER_LITERAL_SHIFT
8093 /*-----------------------------------------------------------------*/
8094 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8095 /*-----------------------------------------------------------------*/
8096 static void
8097 AccAXLsh1 (char *x)
8098 {
8099   emitcode ("xch", "a,%s", x);
8100   emitcode ("add", "a,acc");
8101   emitcode ("xch", "a,%s", x);
8102   emitcode ("rlc", "a");
8103 }
8104 #endif
8105
8106 #ifdef BETTER_LITERAL_SHIFT
8107 /*-----------------------------------------------------------------*/
8108 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8109 /*-----------------------------------------------------------------*/
8110 static void
8111 AccAXLsh (char *x, int shCount)
8112 {
8113   switch (shCount)
8114     {
8115     case 0:
8116       break;
8117     case 1:
8118       AccAXLsh1 (x);
8119       break;
8120     case 2:
8121       AccAXLsh1 (x);
8122       AccAXLsh1 (x);
8123       break;
8124     case 3:
8125     case 4:
8126     case 5:                     // AAAAABBB:CCCCCDDD
8127
8128       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8129
8130       emitcode ("anl", "a,#!constbyte",
8131                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8132
8133       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8134
8135       AccRol (shCount);         // DDDCCCCC:BBB00000
8136
8137       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8138
8139       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8140
8141       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8142
8143       emitcode ("anl", "a,#!constbyte",
8144                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8145
8146       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8147
8148       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8149
8150       break;
8151     case 6:                     // AAAAAABB:CCCCCCDD
8152       emitcode ("anl", "a,#!constbyte",
8153                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8154       emitcode ("mov", "c,acc.0");      // c = B
8155       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8156 #if 0
8157       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8158       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8159 #else
8160       emitcode("rrc","a");
8161       emitcode("xch","a,%s", x);
8162       emitcode("rrc","a");
8163       emitcode("mov","c,acc.0"); //<< get correct bit
8164       emitcode("xch","a,%s", x);
8165
8166       emitcode("rrc","a");
8167       emitcode("xch","a,%s", x);
8168       emitcode("rrc","a");
8169       emitcode("xch","a,%s", x);
8170 #endif
8171       break;
8172     case 7:                     // a:x <<= 7
8173
8174       emitcode ("anl", "a,#!constbyte",
8175                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8176
8177       emitcode ("mov", "c,acc.0");      // c = B
8178
8179       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8180
8181       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8182
8183       break;
8184     default:
8185       break;
8186     }
8187 }
8188 #endif
8189
8190 #ifdef BETTER_LITERAL_SHIFT
8191 //REMOVE ME!!!
8192 /*-----------------------------------------------------------------*/
8193 /* AccAXRsh - right shift a:x known count (0..7)                   */
8194 /*-----------------------------------------------------------------*/
8195 static void
8196 AccAXRsh (char *x, int shCount)
8197 {
8198   switch (shCount)
8199     {
8200     case 0:
8201       break;
8202     case 1:
8203       CLRC;
8204       AccAXRrl1 (x);            // 0->a:x
8205
8206       break;
8207     case 2:
8208       CLRC;
8209       AccAXRrl1 (x);            // 0->a:x
8210
8211       CLRC;
8212       AccAXRrl1 (x);            // 0->a:x
8213
8214       break;
8215     case 3:
8216     case 4:
8217     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8218
8219       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8220
8221       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8222
8223       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8224
8225       emitcode ("anl", "a,#!constbyte",
8226                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8227
8228       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8229
8230       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8231
8232       emitcode ("anl", "a,#!constbyte",
8233                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8234
8235       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8236
8237       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8238
8239       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8240
8241       break;
8242     case 6:                     // AABBBBBB:CCDDDDDD
8243
8244       emitcode ("mov", "c,acc.7");
8245       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8246
8247       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8248
8249       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8250
8251       emitcode ("anl", "a,#!constbyte",
8252                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8253
8254       break;
8255     case 7:                     // ABBBBBBB:CDDDDDDD
8256
8257       emitcode ("mov", "c,acc.7");      // c = A
8258
8259       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8260
8261       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8262
8263       emitcode ("anl", "a,#!constbyte",
8264                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8265
8266       break;
8267     default:
8268       break;
8269     }
8270 }
8271 #endif
8272
8273 #ifdef BETTER_LITERAL_SHIFT
8274 /*-----------------------------------------------------------------*/
8275 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8276 /*-----------------------------------------------------------------*/
8277 static void
8278 AccAXRshS (char *x, int shCount)
8279 {
8280   symbol *tlbl;
8281   switch (shCount)
8282     {
8283     case 0:
8284       break;
8285     case 1:
8286       emitcode ("mov", "c,acc.7");
8287       AccAXRrl1 (x);            // s->a:x
8288
8289       break;
8290     case 2:
8291       emitcode ("mov", "c,acc.7");
8292       AccAXRrl1 (x);            // s->a:x
8293
8294       emitcode ("mov", "c,acc.7");
8295       AccAXRrl1 (x);            // s->a:x
8296
8297       break;
8298     case 3:
8299     case 4:
8300     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8301
8302       tlbl = newiTempLabel (NULL);
8303       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8304
8305       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8306
8307       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8308
8309       emitcode ("anl", "a,#!constbyte",
8310                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8311
8312       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8313
8314       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8315
8316       emitcode ("anl", "a,#!constbyte",
8317                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8318
8319       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8320
8321       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8322
8323       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8324
8325       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8326       emitcode ("orl", "a,#!constbyte",
8327                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8328
8329       emitcode ("", "!tlabeldef", tlbl->key + 100);
8330       break;                    // SSSSAAAA:BBBCCCCC
8331
8332     case 6:                     // AABBBBBB:CCDDDDDD
8333
8334       tlbl = newiTempLabel (NULL);
8335       emitcode ("mov", "c,acc.7");
8336       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8337
8338       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8339
8340       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8341
8342       emitcode ("anl", "a,#!constbyte",
8343                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8344
8345       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8346       emitcode ("orl", "a,#!constbyte",
8347                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8348
8349       emitcode ("", "!tlabeldef", tlbl->key + 100);
8350       break;
8351     case 7:                     // ABBBBBBB:CDDDDDDD
8352
8353       tlbl = newiTempLabel (NULL);
8354       emitcode ("mov", "c,acc.7");      // c = A
8355
8356       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8357
8358       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8359
8360       emitcode ("anl", "a,#!constbyte",
8361                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8362
8363       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8364       emitcode ("orl", "a,#!constbyte",
8365                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8366
8367       emitcode ("", "!tlabeldef", tlbl->key + 100);
8368       break;
8369     default:
8370       break;
8371     }
8372 }
8373 #endif
8374
8375 #ifdef BETTER_LITERAL_SHIFT
8376 static void
8377 _loadLeftIntoAx(char    **lsb,
8378                 operand *left,
8379                 operand *result,
8380                 int     offl,
8381                 int     offr)
8382 {
8383   // Get the initial value from left into a pair of registers.
8384   // MSB must be in A, LSB can be any register.
8385   //
8386   // If the result is held in registers, it is an optimization
8387   // if the LSB can be held in the register which will hold the,
8388   // result LSB since this saves us from having to copy it into
8389   // the result following AccAXLsh.
8390   //
8391   // If the result is addressed indirectly, this is not a gain.
8392   if (AOP_NEEDSACC(result))
8393   {
8394        char *leftByte;
8395
8396        _startLazyDPSEvaluation();
8397       if (AOP_TYPE(left) == AOP_DPTR2)
8398        {
8399            // Get MSB in A.
8400            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8401            // get LSB in DP2_RESULT_REG.
8402            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8403            assert(!strcmp(leftByte, DP2_RESULT_REG));
8404        }
8405        else
8406        {
8407            // get LSB into DP2_RESULT_REG
8408            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8409            if (strcmp(leftByte, DP2_RESULT_REG))
8410            {
8411                TR_AP("#7");
8412                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8413            }
8414            // And MSB in A.
8415            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8416            assert(strcmp(leftByte, DP2_RESULT_REG));
8417            MOVA(leftByte);
8418        }
8419        _endLazyDPSEvaluation();
8420        *lsb = DP2_RESULT_REG;
8421   }
8422   else
8423   {
8424       if (sameRegs (AOP (result), AOP (left)) &&
8425         ((offl + MSB16) == offr))
8426       {
8427           /* don't crash result[offr] */
8428           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8429           emitcode ("xch", "a,%s",
8430                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8431       }
8432       else
8433       {
8434           movLeft2Result (left, offl, result, offr, 0);
8435           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8436       }
8437       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8438       assert(strcmp(*lsb,"a"));
8439   }
8440 }
8441
8442 static void
8443 _storeAxResults(char    *lsb,
8444                 operand *result,
8445                 int     offr)
8446 {
8447   _startLazyDPSEvaluation();
8448   if (AOP_NEEDSACC(result))
8449   {
8450       /* We have to explicitly update the result LSB.
8451        */
8452       emitcode("xch","a,%s", lsb);
8453       aopPut(AOP(result), "a", offr);
8454       emitcode("mov","a,%s", lsb);
8455   }
8456   if (getDataSize (result) > 1)
8457   {
8458       aopPut (AOP (result), "a", offr + MSB16);
8459   }
8460   _endLazyDPSEvaluation();
8461 }
8462
8463 /*-----------------------------------------------------------------*/
8464 /* shiftL2Left2Result - shift left two bytes from left to result   */
8465 /*-----------------------------------------------------------------*/
8466 static void
8467 shiftL2Left2Result (operand * left, int offl,
8468                     operand * result, int offr, int shCount)
8469 {
8470   char *lsb;
8471
8472   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8473
8474   AccAXLsh (lsb, shCount);
8475
8476   _storeAxResults(lsb, result, offr);
8477 }
8478 #endif
8479
8480 #ifdef BETTER_LITERAL_SHIFT
8481 /*-----------------------------------------------------------------*/
8482 /* shiftR2Left2Result - shift right two bytes from left to result  */
8483 /*-----------------------------------------------------------------*/
8484 static void
8485 shiftR2Left2Result (operand * left, int offl,
8486                     operand * result, int offr,
8487                     int shCount, int sign)
8488 {
8489   char *lsb;
8490
8491   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8492
8493   /* a:x >> shCount (x = lsb(result)) */
8494   if (sign)
8495   {
8496      AccAXRshS(lsb, shCount);
8497   }
8498   else
8499   {
8500     AccAXRsh(lsb, shCount);
8501   }
8502
8503   _storeAxResults(lsb, result, offr);
8504 }
8505 #endif
8506
8507 /*-----------------------------------------------------------------*/
8508 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8509 /*-----------------------------------------------------------------*/
8510 static void
8511 shiftLLeftOrResult (operand * left, int offl,
8512                     operand * result, int offr, int shCount)
8513 {
8514   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8515   /* shift left accumulator */
8516   AccLsh (shCount);
8517   /* or with result */
8518   emitcode ("orl", "a,%s",
8519             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8520   /* back to result */
8521   aopPut (AOP (result), "a", offr);
8522 }
8523
8524 #if 0
8525 //REMOVE ME!!!
8526 /*-----------------------------------------------------------------*/
8527 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8528 /*-----------------------------------------------------------------*/
8529 static void
8530 shiftRLeftOrResult (operand * left, int offl,
8531                     operand * result, int offr, int shCount)
8532 {
8533   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8534   /* shift right accumulator */
8535   AccRsh (shCount);
8536   /* or with result */
8537   emitcode ("orl", "a,%s",
8538             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8539   /* back to result */
8540   aopPut (AOP (result), "a", offr);
8541 }
8542 #endif
8543
8544 #ifdef BETTER_LITERAL_SHIFT
8545 /*-----------------------------------------------------------------*/
8546 /* genlshOne - left shift a one byte quantity by known count       */
8547 /*-----------------------------------------------------------------*/
8548 static void
8549 genlshOne (operand * result, operand * left, int shCount)
8550 {
8551   D (emitcode (";", "genlshOne "););
8552   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8553 }
8554 #endif
8555
8556 #ifdef BETTER_LITERAL_SHIFT
8557 /*-----------------------------------------------------------------*/
8558 /* genlshTwo - left shift two bytes by known amount != 0           */
8559 /*-----------------------------------------------------------------*/
8560 static void
8561 genlshTwo (operand * result, operand * left, int shCount)
8562 {
8563   int size;
8564
8565   D (emitcode (";", "genlshTwo "););
8566
8567   size = getDataSize (result);
8568
8569   /* if shCount >= 8 */
8570   if (shCount >= 8)
8571   {
8572       shCount -= 8;
8573
8574       _startLazyDPSEvaluation();
8575
8576       if (size > 1)
8577         {
8578           if (shCount)
8579           {
8580             _endLazyDPSEvaluation();
8581             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8582             aopPut (AOP (result), zero, LSB);
8583           }
8584           else
8585           {
8586             movLeft2Result (left, LSB, result, MSB16, 0);
8587             aopPut (AOP (result), zero, LSB);
8588             _endLazyDPSEvaluation();
8589           }
8590         }
8591         else
8592         {
8593           aopPut (AOP (result), zero, LSB);
8594           _endLazyDPSEvaluation();
8595         }
8596   }
8597
8598   /*  1 <= shCount <= 7 */
8599   else
8600     {
8601       if (size == 1)
8602       {
8603         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8604       }
8605       else
8606       {
8607         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8608       }
8609     }
8610 }
8611 #endif
8612
8613 #if 0
8614 //REMOVE ME!!!
8615 /*-----------------------------------------------------------------*/
8616 /* shiftLLong - shift left one long from left to result            */
8617 /* offl = LSB or MSB16                                             */
8618 /*-----------------------------------------------------------------*/
8619 static void
8620 shiftLLong (operand * left, operand * result, int offr)
8621 {
8622   char *l;
8623   int size = AOP_SIZE (result);
8624
8625   if (size >= LSB + offr)
8626     {
8627       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8628       MOVA (l);
8629       emitcode ("add", "a,acc");
8630       if (sameRegs (AOP (left), AOP (result)) &&
8631           size >= MSB16 + offr && offr != LSB)
8632         emitcode ("xch", "a,%s",
8633                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8634       else
8635         aopPut (AOP (result), "a", LSB + offr);
8636     }
8637
8638   if (size >= MSB16 + offr)
8639     {
8640       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8641         {
8642           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8643         }
8644       emitcode ("rlc", "a");
8645       if (sameRegs (AOP (left), AOP (result)) &&
8646           size >= MSB24 + offr && offr != LSB)
8647         emitcode ("xch", "a,%s",
8648                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8649       else
8650         aopPut (AOP (result), "a", MSB16 + offr);
8651     }
8652
8653   if (size >= MSB24 + offr)
8654     {
8655       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8656         {
8657           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8658         }
8659       emitcode ("rlc", "a");
8660       if (sameRegs (AOP (left), AOP (result)) &&
8661           size >= MSB32 + offr && offr != LSB)
8662         emitcode ("xch", "a,%s",
8663                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8664       else
8665         aopPut (AOP (result), "a", MSB24 + offr);
8666     }
8667
8668   if (size > MSB32 + offr)
8669     {
8670       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8671         {
8672           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8673         }
8674       emitcode ("rlc", "a");
8675       aopPut (AOP (result), "a", MSB32 + offr);
8676     }
8677   if (offr != LSB)
8678     aopPut (AOP (result), zero, LSB);
8679 }
8680 #endif
8681
8682 #if 0
8683 //REMOVE ME!!!
8684 /*-----------------------------------------------------------------*/
8685 /* genlshFour - shift four byte by a known amount != 0             */
8686 /*-----------------------------------------------------------------*/
8687 static void
8688 genlshFour (operand * result, operand * left, int shCount)
8689 {
8690   int size;
8691
8692   D (emitcode (";", "genlshFour ");
8693     );
8694
8695   size = AOP_SIZE (result);
8696
8697   /* if shifting more that 3 bytes */
8698   if (shCount >= 24)
8699     {
8700       shCount -= 24;
8701       if (shCount)
8702         /* lowest order of left goes to the highest
8703            order of the destination */
8704         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8705       else
8706         movLeft2Result (left, LSB, result, MSB32, 0);
8707       aopPut (AOP (result), zero, LSB);
8708       aopPut (AOP (result), zero, MSB16);
8709       aopPut (AOP (result), zero, MSB24);
8710       return;
8711     }
8712
8713   /* more than two bytes */
8714   else if (shCount >= 16)
8715     {
8716       /* lower order two bytes goes to higher order two bytes */
8717       shCount -= 16;
8718       /* if some more remaining */
8719       if (shCount)
8720         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8721       else
8722         {
8723           movLeft2Result (left, MSB16, result, MSB32, 0);
8724           movLeft2Result (left, LSB, result, MSB24, 0);
8725         }
8726       aopPut (AOP (result), zero, MSB16);
8727       aopPut (AOP (result), zero, LSB);
8728       return;
8729     }
8730
8731   /* if more than 1 byte */
8732   else if (shCount >= 8)
8733     {
8734       /* lower order three bytes goes to higher order  three bytes */
8735       shCount -= 8;
8736       if (size == 2)
8737         {
8738           if (shCount)
8739             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8740           else
8741             movLeft2Result (left, LSB, result, MSB16, 0);
8742         }
8743       else
8744         {                       /* size = 4 */
8745           if (shCount == 0)
8746             {
8747               movLeft2Result (left, MSB24, result, MSB32, 0);
8748               movLeft2Result (left, MSB16, result, MSB24, 0);
8749               movLeft2Result (left, LSB, result, MSB16, 0);
8750               aopPut (AOP (result), zero, LSB);
8751             }
8752           else if (shCount == 1)
8753             shiftLLong (left, result, MSB16);
8754           else
8755             {
8756               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8757               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8758               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8759               aopPut (AOP (result), zero, LSB);
8760             }
8761         }
8762     }
8763
8764   /* 1 <= shCount <= 7 */
8765   else if (shCount <= 2)
8766     {
8767       shiftLLong (left, result, LSB);
8768       if (shCount == 2)
8769         shiftLLong (result, result, LSB);
8770     }
8771   /* 3 <= shCount <= 7, optimize */
8772   else
8773     {
8774       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8775       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8776       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8777     }
8778 }
8779 #endif
8780
8781 #ifdef BETTER_LITERAL_SHIFT
8782 /*-----------------------------------------------------------------*/
8783 /* genLeftShiftLiteral - left shifting by known count              */
8784 /*-----------------------------------------------------------------*/
8785 static bool
8786 genLeftShiftLiteral (operand * left,
8787                      operand * right,
8788                      operand * result,
8789                      iCode * ic)
8790 {
8791   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8792   int size;
8793
8794   size = getSize (operandType (result));
8795
8796   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8797
8798   /* We only handle certain easy cases so far. */
8799   if ((shCount != 0)
8800    && (shCount < (size * 8))
8801    && (size != 1)
8802    && (size != 2))
8803   {
8804       D(emitcode (";", "genLeftShiftLiteral wimping out"););
8805       return FALSE;
8806   }
8807
8808   freeAsmop (right, NULL, ic, TRUE);
8809
8810   aopOp(left, ic, FALSE, FALSE);
8811   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8812
8813 #if 0 // debug spew
8814   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8815   {
8816         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8817         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8818         {
8819            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8820         }
8821   }
8822   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8823   {
8824         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8825         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8826         {
8827            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8828         }
8829   }
8830 #endif
8831
8832 #if VIEW_SIZE
8833   emitcode ("; shift left ", "result %d, left %d", size,
8834             AOP_SIZE (left));
8835 #endif
8836
8837   /* I suppose that the left size >= result size */
8838   if (shCount == 0)
8839   {
8840         _startLazyDPSEvaluation();
8841         while (size--)
8842         {
8843           movLeft2Result (left, size, result, size, 0);
8844         }
8845         _endLazyDPSEvaluation();
8846   }
8847   else if (shCount >= (size * 8))
8848   {
8849     _startLazyDPSEvaluation();
8850     while (size--)
8851     {
8852       aopPut (AOP (result), zero, size);
8853     }
8854     _endLazyDPSEvaluation();
8855   }
8856   else
8857   {
8858       switch (size)
8859         {
8860         case 1:
8861           genlshOne (result, left, shCount);
8862           break;
8863
8864         case 2:
8865           genlshTwo (result, left, shCount);
8866           break;
8867 #if 0
8868         case 4:
8869           genlshFour (result, left, shCount);
8870           break;
8871 #endif
8872         default:
8873           fprintf(stderr, "*** ack! mystery literal shift!\n");
8874           break;
8875         }
8876     }
8877   freeAsmop (left, NULL, ic, TRUE);
8878   freeAsmop (result, NULL, ic, TRUE);
8879   return TRUE;
8880 }
8881 #endif
8882
8883 /*-----------------------------------------------------------------*/
8884 /* genLeftShift - generates code for left shifting                 */
8885 /*-----------------------------------------------------------------*/
8886 static void
8887 genLeftShift (iCode * ic)
8888 {
8889   operand *left, *right, *result;
8890   int size, offset;
8891   char *l;
8892   symbol *tlbl, *tlbl1;
8893
8894   D (emitcode (";", "genLeftShift "););
8895
8896   right = IC_RIGHT (ic);
8897   left = IC_LEFT (ic);
8898   result = IC_RESULT (ic);
8899
8900   aopOp (right, ic, FALSE, FALSE);
8901
8902
8903 #ifdef BETTER_LITERAL_SHIFT
8904   /* if the shift count is known then do it
8905      as efficiently as possible */
8906   if (AOP_TYPE (right) == AOP_LIT)
8907     {
8908       if (genLeftShiftLiteral (left, right, result, ic))
8909       {
8910         return;
8911       }
8912     }
8913 #endif
8914
8915   /* shift count is unknown then we have to form
8916      a loop get the loop count in B : Note: we take
8917      only the lower order byte since shifting
8918      more that 32 bits make no sense anyway, ( the
8919      largest size of an object can be only 32 bits ) */
8920
8921   if (AOP_TYPE (right) == AOP_LIT)
8922   {
8923       /* Really should be handled by genLeftShiftLiteral,
8924        * but since I'm too lazy to fix that today, at least we can make
8925        * some small improvement.
8926        */
8927        emitcode("mov", "b,#!constbyte",
8928                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8929   }
8930   else
8931   {
8932       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8933       emitcode ("inc", "b");
8934   }
8935   freeAsmop (right, NULL, ic, TRUE);
8936   aopOp (left, ic, FALSE, FALSE);
8937   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8938
8939   /* now move the left to the result if they are not the
8940      same */
8941   if (!sameRegs (AOP (left), AOP (result)) &&
8942       AOP_SIZE (result) > 1)
8943     {
8944
8945       size = AOP_SIZE (result);
8946       offset = 0;
8947       _startLazyDPSEvaluation ();
8948       while (size--)
8949         {
8950           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8951           if (*l == '@' && (IS_AOP_PREG (result)))
8952             {
8953
8954               emitcode ("mov", "a,%s", l);
8955               aopPut (AOP (result), "a", offset);
8956             }
8957           else
8958             aopPut (AOP (result), l, offset);
8959           offset++;
8960         }
8961       _endLazyDPSEvaluation ();
8962     }
8963
8964   tlbl = newiTempLabel (NULL);
8965   size = AOP_SIZE (result);
8966   offset = 0;
8967   tlbl1 = newiTempLabel (NULL);
8968
8969   /* if it is only one byte then */
8970   if (size == 1)
8971     {
8972       symbol *tlbl1 = newiTempLabel (NULL);
8973
8974       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8975       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8976       emitcode ("", "!tlabeldef", tlbl->key + 100);
8977       emitcode ("add", "a,acc");
8978       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8979       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8980       aopPut (AOP (result), "a", 0);
8981       goto release;
8982     }
8983
8984   reAdjustPreg (AOP (result));
8985
8986   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8987   emitcode ("", "!tlabeldef", tlbl->key + 100);
8988   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8989   emitcode ("add", "a,acc");
8990   aopPut (AOP (result), "a", offset++);
8991   _startLazyDPSEvaluation ();
8992   while (--size)
8993     {
8994       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8995       emitcode ("rlc", "a");
8996       aopPut (AOP (result), "a", offset++);
8997     }
8998   _endLazyDPSEvaluation ();
8999   reAdjustPreg (AOP (result));
9000
9001   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9002   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9003 release:
9004   freeAsmop (left, NULL, ic, TRUE);
9005   freeAsmop (result, NULL, ic, TRUE);
9006 }
9007
9008 #ifdef BETTER_LITERAL_SHIFT
9009 /*-----------------------------------------------------------------*/
9010 /* genrshOne - right shift a one byte quantity by known count      */
9011 /*-----------------------------------------------------------------*/
9012 static void
9013 genrshOne (operand * result, operand * left,
9014            int shCount, int sign)
9015 {
9016   D (emitcode (";", "genrshOne"););
9017   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9018 }
9019 #endif
9020
9021 #ifdef BETTER_LITERAL_SHIFT
9022 /*-----------------------------------------------------------------*/
9023 /* genrshTwo - right shift two bytes by known amount != 0          */
9024 /*-----------------------------------------------------------------*/
9025 static void
9026 genrshTwo (operand * result, operand * left,
9027            int shCount, int sign)
9028 {
9029   D (emitcode (";", "genrshTwo"););
9030
9031   /* if shCount >= 8 */
9032   if (shCount >= 8)
9033     {
9034       shCount -= 8;
9035       _startLazyDPSEvaluation();
9036       if (shCount)
9037       {
9038         shiftR1Left2Result (left, MSB16, result, LSB,
9039                             shCount, sign);
9040       }
9041       else
9042       {
9043         movLeft2Result (left, MSB16, result, LSB, sign);
9044       }
9045       addSign (result, MSB16, sign);
9046       _endLazyDPSEvaluation();
9047     }
9048
9049   /*  1 <= shCount <= 7 */
9050   else
9051   {
9052     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9053   }
9054 }
9055 #endif
9056
9057 /*-----------------------------------------------------------------*/
9058 /* shiftRLong - shift right one long from left to result           */
9059 /* offl = LSB or MSB16                                             */
9060 /*-----------------------------------------------------------------*/
9061 static void
9062 shiftRLong (operand * left, int offl,
9063             operand * result, int sign)
9064 {
9065   int isSameRegs=sameRegs(AOP(left),AOP(result));
9066
9067   if (isSameRegs && offl>1) {
9068     // we are in big trouble, but this shouldn't happen
9069     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9070   }
9071
9072   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9073
9074   if (offl==MSB16) {
9075     // shift is > 8
9076     if (sign) {
9077       emitcode ("rlc", "a");
9078       emitcode ("subb", "a,acc");
9079       emitcode ("xch", "a,%s",
9080                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9081     } else {
9082       aopPut (AOP(result), zero, MSB32);
9083     }
9084   }
9085
9086   if (!sign) {
9087     emitcode ("clr", "c");
9088   } else {
9089     emitcode ("mov", "c,acc.7");
9090   }
9091
9092   emitcode ("rrc", "a");
9093
9094   if (isSameRegs && offl==MSB16) {
9095     emitcode ("xch",
9096               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9097   } else {
9098     aopPut (AOP (result), "a", MSB32);
9099     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9100   }
9101
9102   emitcode ("rrc", "a");
9103   if (isSameRegs && offl==1) {
9104     emitcode ("xch", "a,%s",
9105               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9106   } else {
9107     aopPut (AOP (result), "a", MSB24);
9108     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9109   }
9110   emitcode ("rrc", "a");
9111   aopPut (AOP (result), "a", MSB16 - offl);
9112
9113   if (offl == LSB)
9114     {
9115       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9116       emitcode ("rrc", "a");
9117       aopPut (AOP (result), "a", LSB);
9118     }
9119 }
9120
9121 /*-----------------------------------------------------------------*/
9122 /* genrshFour - shift four byte by a known amount != 0             */
9123 /*-----------------------------------------------------------------*/
9124 static void
9125 genrshFour (operand * result, operand * left,
9126             int shCount, int sign)
9127 {
9128   D (emitcode (";", "genrshFour"););
9129
9130   /* if shifting more that 3 bytes */
9131   if (shCount >= 24)
9132     {
9133       shCount -= 24;
9134       _startLazyDPSEvaluation();
9135       if (shCount)
9136         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9137       else
9138         movLeft2Result (left, MSB32, result, LSB, sign);
9139       addSign (result, MSB16, sign);
9140       _endLazyDPSEvaluation();
9141     }
9142   else if (shCount >= 16)
9143     {
9144       shCount -= 16;
9145       _startLazyDPSEvaluation();
9146       if (shCount)
9147         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9148       else
9149         {
9150           movLeft2Result (left, MSB24, result, LSB, 0);
9151           movLeft2Result (left, MSB32, result, MSB16, sign);
9152         }
9153       addSign (result, MSB24, sign);
9154       _endLazyDPSEvaluation();
9155     }
9156   else if (shCount >= 8)
9157     {
9158       shCount -= 8;
9159       _startLazyDPSEvaluation();
9160       if (shCount == 1)
9161         {
9162             shiftRLong (left, MSB16, result, sign);
9163         }
9164       else if (shCount == 0)
9165         {
9166           movLeft2Result (left, MSB16, result, LSB, 0);
9167           movLeft2Result (left, MSB24, result, MSB16, 0);
9168           movLeft2Result (left, MSB32, result, MSB24, sign);
9169           addSign (result, MSB32, sign);
9170         }
9171       else
9172         {
9173           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9174           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9175           /* the last shift is signed */
9176           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9177           addSign (result, MSB32, sign);
9178         }
9179         _endLazyDPSEvaluation();
9180     }
9181   else
9182     {
9183         /* 1 <= shCount <= 7 */
9184       if (shCount <= 2)
9185         {
9186           shiftRLong (left, LSB, result, sign);
9187           if (shCount == 2)
9188             shiftRLong (result, LSB, result, sign);
9189         }
9190       else
9191         {
9192           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9193           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9194           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9195         }
9196     }
9197 }
9198
9199 #ifdef BETTER_LITERAL_SHIFT
9200 /*-----------------------------------------------------------------*/
9201 /* genRightShiftLiteral - right shifting by known count            */
9202 /*-----------------------------------------------------------------*/
9203 static bool
9204 genRightShiftLiteral (operand * left,
9205                       operand * right,
9206                       operand * result,
9207                       iCode * ic,
9208                       int sign)
9209 {
9210   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9211   int size;
9212
9213   size = getSize (operandType (result));
9214
9215   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9216
9217   /* We only handle certain easy cases so far. */
9218   if ((shCount != 0)
9219    && (shCount < (size * 8))
9220    && (size != 1)
9221    && (size != 2)
9222    && (size != 4))
9223   {
9224       D(emitcode (";", "genRightShiftLiteral wimping out"););
9225       return FALSE;
9226   }
9227
9228   freeAsmop (right, NULL, ic, TRUE);
9229
9230   aopOp (left, ic, FALSE, FALSE);
9231   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9232
9233 #if VIEW_SIZE
9234   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9235             AOP_SIZE (left));
9236 #endif
9237
9238   /* test the LEFT size !!! */
9239
9240   /* I suppose that the left size >= result size */
9241   if (shCount == 0)
9242   {
9243       size = getDataSize (result);
9244       _startLazyDPSEvaluation();
9245       while (size--)
9246       {
9247         movLeft2Result (left, size, result, size, 0);
9248       }
9249       _endLazyDPSEvaluation();
9250   }
9251   else if (shCount >= (size * 8))
9252     {
9253       if (sign)
9254       {
9255         /* get sign in acc.7 */
9256         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9257       }
9258       addSign (result, LSB, sign);
9259     }
9260   else
9261     {
9262       switch (size)
9263         {
9264         case 1:
9265           genrshOne (result, left, shCount, sign);
9266           break;
9267
9268         case 2:
9269           genrshTwo (result, left, shCount, sign);
9270           break;
9271 #if 1
9272         case 4:
9273           genrshFour (result, left, shCount, sign);
9274           break;
9275 #endif
9276         default:
9277           break;
9278         }
9279     }
9280   freeAsmop (left, NULL, ic, TRUE);
9281   freeAsmop (result, NULL, ic, TRUE);
9282
9283   return TRUE;
9284 }
9285 #endif
9286
9287 /*-----------------------------------------------------------------*/
9288 /* genSignedRightShift - right shift of signed number              */
9289 /*-----------------------------------------------------------------*/
9290 static void
9291 genSignedRightShift (iCode * ic)
9292 {
9293   operand *right, *left, *result;
9294   int size, offset;
9295   char *l;
9296   symbol *tlbl, *tlbl1;
9297
9298   D (emitcode (";", "genSignedRightShift "););
9299
9300   /* we do it the hard way put the shift count in b
9301      and loop thru preserving the sign */
9302
9303   right = IC_RIGHT (ic);
9304   left = IC_LEFT (ic);
9305   result = IC_RESULT (ic);
9306
9307   aopOp (right, ic, FALSE, FALSE);
9308
9309 #ifdef BETTER_LITERAL_SHIFT
9310   if (AOP_TYPE (right) == AOP_LIT)
9311     {
9312       if (genRightShiftLiteral (left, right, result, ic, 1))
9313       {
9314         return;
9315       }
9316     }
9317 #endif
9318   /* shift count is unknown then we have to form
9319      a loop get the loop count in B : Note: we take
9320      only the lower order byte since shifting
9321      more that 32 bits make no sense anyway, ( the
9322      largest size of an object can be only 32 bits ) */
9323
9324   if (AOP_TYPE (right) == AOP_LIT)
9325   {
9326       /* Really should be handled by genRightShiftLiteral,
9327        * but since I'm too lazy to fix that today, at least we can make
9328        * some small improvement.
9329        */
9330        emitcode("mov", "b,#!constbyte",
9331                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9332   }
9333   else
9334   {
9335         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9336         emitcode ("inc", "b");
9337   }
9338   freeAsmop (right, NULL, ic, TRUE);
9339   aopOp (left, ic, FALSE, FALSE);
9340   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9341
9342   /* now move the left to the result if they are not the
9343      same */
9344   if (!sameRegs (AOP (left), AOP (result)) &&
9345       AOP_SIZE (result) > 1)
9346     {
9347
9348       size = AOP_SIZE (result);
9349       offset = 0;
9350       _startLazyDPSEvaluation ();
9351       while (size--)
9352         {
9353           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9354           if (*l == '@' && IS_AOP_PREG (result))
9355             {
9356
9357               emitcode ("mov", "a,%s", l);
9358               aopPut (AOP (result), "a", offset);
9359             }
9360           else
9361             aopPut (AOP (result), l, offset);
9362           offset++;
9363         }
9364       _endLazyDPSEvaluation ();
9365     }
9366
9367   /* mov the highest order bit to OVR */
9368   tlbl = newiTempLabel (NULL);
9369   tlbl1 = newiTempLabel (NULL);
9370
9371   size = AOP_SIZE (result);
9372   offset = size - 1;
9373   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9374   emitcode ("rlc", "a");
9375   emitcode ("mov", "ov,c");
9376   /* if it is only one byte then */
9377   if (size == 1)
9378     {
9379       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9380       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9381       emitcode ("", "!tlabeldef", tlbl->key + 100);
9382       emitcode ("mov", "c,ov");
9383       emitcode ("rrc", "a");
9384       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9385       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9386       aopPut (AOP (result), "a", 0);
9387       goto release;
9388     }
9389
9390   reAdjustPreg (AOP (result));
9391   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9392   emitcode ("", "!tlabeldef", tlbl->key + 100);
9393   emitcode ("mov", "c,ov");
9394   _startLazyDPSEvaluation ();
9395   while (size--)
9396     {
9397       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9398       emitcode ("rrc", "a");
9399       aopPut (AOP (result), "a", offset--);
9400     }
9401   _endLazyDPSEvaluation ();
9402   reAdjustPreg (AOP (result));
9403   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9404   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9405
9406 release:
9407   freeAsmop (left, NULL, ic, TRUE);
9408   freeAsmop (result, NULL, ic, TRUE);
9409 }
9410
9411 /*-----------------------------------------------------------------*/
9412 /* genRightShift - generate code for right shifting                */
9413 /*-----------------------------------------------------------------*/
9414 static void
9415 genRightShift (iCode * ic)
9416 {
9417   operand *right, *left, *result;
9418   sym_link *letype;
9419   int size, offset;
9420   char *l;
9421   symbol *tlbl, *tlbl1;
9422
9423   D (emitcode (";", "genRightShift "););
9424
9425   /* if signed then we do it the hard way preserve the
9426      sign bit moving it inwards */
9427   letype = getSpec (operandType (IC_LEFT (ic)));
9428
9429   if (!SPEC_USIGN (letype))
9430     {
9431       genSignedRightShift (ic);
9432       return;
9433     }
9434
9435   /* signed & unsigned types are treated the same : i.e. the
9436      signed is NOT propagated inwards : quoting from the
9437      ANSI - standard : "for E1 >> E2, is equivalent to division
9438      by 2**E2 if unsigned or if it has a non-negative value,
9439      otherwise the result is implementation defined ", MY definition
9440      is that the sign does not get propagated */
9441
9442   right = IC_RIGHT (ic);
9443   left = IC_LEFT (ic);
9444   result = IC_RESULT (ic);
9445
9446   aopOp (right, ic, FALSE, FALSE);
9447
9448 #ifdef BETTER_LITERAL_SHIFT
9449   /* if the shift count is known then do it
9450      as efficiently as possible */
9451   if (AOP_TYPE (right) == AOP_LIT)
9452     {
9453       if (genRightShiftLiteral (left, right, result, ic, 0))
9454       {
9455         return;
9456       }
9457     }
9458 #endif
9459
9460   /* shift count is unknown then we have to form
9461      a loop get the loop count in B : Note: we take
9462      only the lower order byte since shifting
9463      more that 32 bits make no sense anyway, ( the
9464      largest size of an object can be only 32 bits ) */
9465
9466   if (AOP_TYPE (right) == AOP_LIT)
9467   {
9468       /* Really should be handled by genRightShiftLiteral,
9469        * but since I'm too lazy to fix that today, at least we can make
9470        * some small improvement.
9471        */
9472        emitcode("mov", "b,#!constbyte",
9473                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9474   }
9475   else
9476   {
9477       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9478       emitcode ("inc", "b");
9479   }
9480   freeAsmop (right, NULL, ic, TRUE);
9481   aopOp (left, ic, FALSE, FALSE);
9482   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9483
9484   /* now move the left to the result if they are not the
9485      same */
9486   if (!sameRegs (AOP (left), AOP (result)) &&
9487       AOP_SIZE (result) > 1)
9488     {
9489
9490       size = AOP_SIZE (result);
9491       offset = 0;
9492       _startLazyDPSEvaluation ();
9493       while (size--)
9494         {
9495           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9496           if (*l == '@' && IS_AOP_PREG (result))
9497             {
9498
9499               emitcode ("mov", "a,%s", l);
9500               aopPut (AOP (result), "a", offset);
9501             }
9502           else
9503             aopPut (AOP (result), l, offset);
9504           offset++;
9505         }
9506       _endLazyDPSEvaluation ();
9507     }
9508
9509   tlbl = newiTempLabel (NULL);
9510   tlbl1 = newiTempLabel (NULL);
9511   size = AOP_SIZE (result);
9512   offset = size - 1;
9513
9514   /* if it is only one byte then */
9515   if (size == 1)
9516     {
9517       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9518       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9519       emitcode ("", "!tlabeldef", tlbl->key + 100);
9520       CLRC;
9521       emitcode ("rrc", "a");
9522       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9523       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9524       aopPut (AOP (result), "a", 0);
9525       goto release;
9526     }
9527
9528   reAdjustPreg (AOP (result));
9529   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9530   emitcode ("", "!tlabeldef", tlbl->key + 100);
9531   CLRC;
9532   _startLazyDPSEvaluation ();
9533   while (size--)
9534     {
9535       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9536       emitcode ("rrc", "a");
9537       aopPut (AOP (result), "a", offset--);
9538     }
9539   _endLazyDPSEvaluation ();
9540   reAdjustPreg (AOP (result));
9541
9542   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9543   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9544
9545 release:
9546   freeAsmop (left, NULL, ic, TRUE);
9547   freeAsmop (result, NULL, ic, TRUE);
9548 }
9549
9550
9551 /*-----------------------------------------------------------------*/
9552 /* emitPtrByteGet - emits code to get a byte into A through a      */
9553 /*                  pointer register (R0, R1, or DPTR). The        */
9554 /*                  original value of A can be preserved in B.     */
9555 /*-----------------------------------------------------------------*/
9556 static void
9557 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9558 {
9559   switch (p_type)
9560     {
9561     case IPOINTER:
9562     case POINTER:
9563       if (preserveAinB)
9564         emitcode ("mov", "b,a");
9565       emitcode ("mov", "a,@%s", rname);
9566       break;
9567
9568     case PPOINTER:
9569       if (preserveAinB)
9570         emitcode ("mov", "b,a");
9571       emitcode ("movx", "a,@%s", rname);
9572       break;
9573
9574     case FPOINTER:
9575       if (preserveAinB)
9576         emitcode ("mov", "b,a");
9577       emitcode ("movx", "a,@dptr");
9578       break;
9579
9580     case CPOINTER:
9581       if (preserveAinB)
9582         emitcode ("mov", "b,a");
9583       emitcode ("clr", "a");
9584       emitcode ("movc", "a,@a+dptr");
9585       break;
9586
9587     case GPOINTER:
9588       if (preserveAinB)
9589         {
9590           emitcode ("push", "b");
9591           emitcode ("push", "acc");
9592         }
9593       emitcode ("lcall", "__gptrget");
9594       if (preserveAinB)
9595         emitcode ("pop", "b");
9596       break;
9597     }
9598 }
9599
9600 /*-----------------------------------------------------------------*/
9601 /* emitPtrByteSet - emits code to set a byte from src through a    */
9602 /*                  pointer register (R0, R1, or DPTR).            */
9603 /*-----------------------------------------------------------------*/
9604 static void
9605 emitPtrByteSet (char *rname, int p_type, char *src)
9606 {
9607   switch (p_type)
9608     {
9609     case IPOINTER:
9610     case POINTER:
9611       if (*src=='@')
9612         {
9613           MOVA (src);
9614           emitcode ("mov", "@%s,a", rname);
9615         }
9616       else
9617         emitcode ("mov", "@%s,%s", rname, src);
9618       break;
9619
9620     case PPOINTER:
9621       MOVA (src);
9622       emitcode ("movx", "@%s,a", rname);
9623       break;
9624
9625     case FPOINTER:
9626       MOVA (src);
9627       emitcode ("movx", "@dptr,a");
9628       break;
9629
9630     case GPOINTER:
9631       MOVA (src);
9632       emitcode ("lcall", "__gptrput");
9633       break;
9634     }
9635 }
9636
9637 /*-----------------------------------------------------------------*/
9638 /* genUnpackBits - generates code for unpacking bits               */
9639 /*-----------------------------------------------------------------*/
9640 static void
9641 genUnpackBits (operand * result, char *rname, int ptype)
9642 {
9643   int offset = 0;       /* result byte offset */
9644   int rsize;            /* result size */
9645   int rlen = 0;         /* remaining bitfield length */
9646   sym_link *etype;      /* bitfield type information */
9647   int blen;             /* bitfield length */
9648   int bstr;             /* bitfield starting bit within byte */
9649
9650   D(emitcode (";     genUnpackBits",""));
9651
9652   etype = getSpec (operandType (result));
9653   rsize = getSize (operandType (result));
9654   blen = SPEC_BLEN (etype);
9655   bstr = SPEC_BSTR (etype);
9656
9657   /* If the bitfield length is less than a byte */
9658   if (blen < 8)
9659     {
9660       emitPtrByteGet (rname, ptype, FALSE);
9661       AccRsh (bstr);
9662       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9663       aopPut (AOP (result), "a", offset++);
9664       goto finish;
9665     }
9666
9667   /* Bit field did not fit in a byte. Copy all
9668      but the partial byte at the end.  */
9669   for (rlen=blen;rlen>=8;rlen-=8)
9670     {
9671       emitPtrByteGet (rname, ptype, FALSE);
9672       aopPut (AOP (result), "a", offset++);
9673       if (rlen>8)
9674         emitcode ("inc", "%s", rname);
9675     }
9676
9677   /* Handle the partial byte at the end */
9678   if (rlen)
9679     {
9680       emitPtrByteGet (rname, ptype, FALSE);
9681       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9682       aopPut (AOP (result), "a", offset++);
9683     }
9684
9685 finish:
9686   if (offset < rsize)
9687     {
9688       rsize -= offset;
9689       while (rsize--)
9690         aopPut (AOP (result), zero, offset++);
9691     }
9692 }
9693
9694
9695 /*-----------------------------------------------------------------*/
9696 /* genDataPointerGet - generates code when ptr offset is known     */
9697 /*-----------------------------------------------------------------*/
9698 static void
9699 genDataPointerGet (operand * left,
9700                    operand * result,
9701                    iCode * ic)
9702 {
9703   char *l;
9704   char buff[256];
9705   int size, offset = 0;
9706   aopOp (result, ic, TRUE, FALSE);
9707
9708   /* get the string representation of the name */
9709   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9710   size = AOP_SIZE (result);
9711   _startLazyDPSEvaluation ();
9712   while (size--)
9713     {
9714         if (offset)
9715         {
9716             SNPRINTF (buff, sizeof(buff),
9717                       "(%s + %d)", l + 1, offset);
9718         }
9719         else
9720         {
9721             SNPRINTF (buff, sizeof(buff),
9722                       "%s", l + 1);
9723         }
9724       aopPut (AOP (result), buff, offset++);
9725     }
9726   _endLazyDPSEvaluation ();
9727
9728   freeAsmop (left, NULL, ic, TRUE);
9729   freeAsmop (result, NULL, ic, TRUE);
9730 }
9731
9732 /*-----------------------------------------------------------------*/
9733 /* genNearPointerGet - emitcode for near pointer fetch             */
9734 /*-----------------------------------------------------------------*/
9735 static void
9736 genNearPointerGet (operand * left,
9737                    operand * result,
9738                    iCode * ic,
9739                    iCode *pi)
9740 {
9741   asmop *aop = NULL;
9742   regs *preg;
9743   char *rname;
9744   sym_link *rtype, *retype, *letype;
9745   sym_link *ltype = operandType (left);
9746   char buff[80];
9747
9748   rtype = operandType (result);
9749   retype = getSpec (rtype);
9750   letype = getSpec (ltype);
9751
9752   aopOp (left, ic, FALSE, FALSE);
9753
9754   /* if left is rematerialisable and
9755      result is not bitfield variable type and
9756      the left is pointer to data space i.e
9757      lower 128 bytes of space */
9758   if (AOP_TYPE (left) == AOP_IMMD &&
9759       !IS_BITFIELD (retype) &&
9760       !IS_BITFIELD (letype) &&
9761       DCL_TYPE (ltype) == POINTER)
9762     {
9763       genDataPointerGet (left, result, ic);
9764       return;
9765     }
9766
9767   /* if the value is already in a pointer register
9768      then don't need anything more */
9769   if (!AOP_INPREG (AOP (left)))
9770     {
9771       /* otherwise get a free pointer register */
9772       aop = newAsmop (0);
9773       preg = getFreePtr (ic, &aop, FALSE);
9774       emitcode ("mov", "%s,%s",
9775                 preg->name,
9776                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9777       rname = preg->name;
9778     }
9779   else
9780     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9781
9782   freeAsmop (left, NULL, ic, TRUE);
9783   aopOp (result, ic, FALSE, FALSE);
9784
9785   /* if bitfield then unpack the bits */
9786   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9787     genUnpackBits (result, rname, POINTER);
9788   else
9789     {
9790       /* we have can just get the values */
9791       int size = AOP_SIZE (result);
9792       int offset = 0;
9793
9794       while (size--)
9795         {
9796           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9797             {
9798
9799               emitcode ("mov", "a,@%s", rname);
9800               aopPut (AOP (result), "a", offset);
9801             }
9802           else
9803             {
9804               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9805               aopPut (AOP (result), buff, offset);
9806             }
9807           offset++;
9808           if (size || pi)
9809             {
9810                 emitcode ("inc", "%s", rname);
9811             }
9812         }
9813     }
9814
9815   /* now some housekeeping stuff */
9816   if (aop)
9817     {
9818       /* we had to allocate for this iCode */
9819       if (pi) { /* post increment present */
9820         aopPut(AOP ( left ),rname,0);
9821       }
9822       freeAsmop (NULL, aop, ic, TRUE);
9823     }
9824   else
9825     {
9826       /* we did not allocate which means left
9827          already in a pointer register, then
9828          if size > 0 && this could be used again
9829          we have to point it back to where it
9830          belongs */
9831       if (AOP_SIZE (result) > 1 &&
9832           !OP_SYMBOL (left)->remat &&
9833           (OP_SYMBOL (left)->liveTo > ic->seq ||
9834            ic->depth) &&
9835           !pi)
9836         {
9837           int size = AOP_SIZE (result) - 1;
9838           while (size--)
9839             emitcode ("dec", "%s", rname);
9840         }
9841     }
9842
9843   /* done */
9844   freeAsmop (result, NULL, ic, TRUE);
9845   if (pi) pi->generated = 1;
9846 }
9847
9848 /*-----------------------------------------------------------------*/
9849 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9850 /*-----------------------------------------------------------------*/
9851 static void
9852 genPagedPointerGet (operand * left,
9853                     operand * result,
9854                     iCode * ic,
9855                     iCode * pi)
9856 {
9857   asmop *aop = NULL;
9858   regs *preg;
9859   char *rname;
9860   sym_link *rtype, *retype, *letype;
9861
9862   rtype = operandType (result);
9863   retype = getSpec (rtype);
9864   letype = getSpec (operandType (left));
9865   aopOp (left, ic, FALSE, FALSE);
9866
9867   /* if the value is already in a pointer register
9868      then don't need anything more */
9869   if (!AOP_INPREG (AOP (left)))
9870     {
9871       /* otherwise get a free pointer register */
9872       aop = newAsmop (0);
9873       preg = getFreePtr (ic, &aop, FALSE);
9874       emitcode ("mov", "%s,%s",
9875                 preg->name,
9876                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9877       rname = preg->name;
9878     }
9879   else
9880     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9881
9882   freeAsmop (left, NULL, ic, TRUE);
9883   aopOp (result, ic, FALSE, FALSE);
9884
9885   /* if bitfield then unpack the bits */
9886   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9887     genUnpackBits (result, rname, PPOINTER);
9888   else
9889     {
9890       /* we have can just get the values */
9891       int size = AOP_SIZE (result);
9892       int offset = 0;
9893
9894       while (size--)
9895         {
9896
9897           emitcode ("movx", "a,@%s", rname);
9898           aopPut (AOP (result), "a", offset);
9899
9900           offset++;
9901
9902           if (size || pi)
9903             emitcode ("inc", "%s", rname);
9904         }
9905     }
9906
9907   /* now some housekeeping stuff */
9908   if (aop)
9909     {
9910       /* we had to allocate for this iCode */
9911       if (pi) aopPut ( AOP (left), rname, 0);
9912       freeAsmop (NULL, aop, ic, TRUE);
9913     }
9914   else
9915     {
9916       /* we did not allocate which means left
9917          already in a pointer register, then
9918          if size > 0 && this could be used again
9919          we have to point it back to where it
9920          belongs */
9921       if (AOP_SIZE (result) > 1 &&
9922           !OP_SYMBOL (left)->remat &&
9923           (OP_SYMBOL (left)->liveTo > ic->seq ||
9924            ic->depth) &&
9925           !pi)
9926         {
9927           int size = AOP_SIZE (result) - 1;
9928           while (size--)
9929             emitcode ("dec", "%s", rname);
9930         }
9931     }
9932
9933   /* done */
9934   freeAsmop (result, NULL, ic, TRUE);
9935   if (pi) pi->generated = 1;
9936 }
9937
9938 /*-----------------------------------------------------------------*/
9939 /* genFarPointerGet - gget value from far space                    */
9940 /*-----------------------------------------------------------------*/
9941 static void
9942 genFarPointerGet (operand * left,
9943                   operand * result, iCode * ic, iCode *pi)
9944 {
9945     int size, offset, dopi=1;
9946   sym_link *retype = getSpec (operandType (result));
9947   sym_link *letype = getSpec (operandType (left));
9948   D (emitcode (";", "genFarPointerGet"););
9949
9950   aopOp (left, ic, FALSE, FALSE);
9951
9952   /* if the operand is already in dptr
9953      then we do nothing else we move the value to dptr */
9954   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9955     {
9956       /* if this is remateriazable */
9957       if (AOP_TYPE (left) == AOP_IMMD)
9958         {
9959           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9960         }
9961       else
9962         {
9963           /* we need to get it byte by byte */
9964           _startLazyDPSEvaluation ();
9965           if (AOP_TYPE (left) != AOP_DPTR)
9966             {
9967               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9968               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9969               if (options.model == MODEL_FLAT24)
9970                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9971             }
9972           else
9973             {
9974               /* We need to generate a load to DPTR indirect through DPTR. */
9975               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9976               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9977               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9978               if (options.model == MODEL_FLAT24)
9979                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9980               emitcode ("pop", "dph");
9981               emitcode ("pop", "dpl");
9982               dopi =0;
9983             }
9984           _endLazyDPSEvaluation ();
9985         }
9986     }
9987   /* so dptr know contains the address */
9988   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9989
9990   /* if bit then unpack */
9991   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9992       if (AOP_INDPTRn(left)) {
9993           genSetDPTR(AOP(left)->aopu.dptr);
9994       }
9995       genUnpackBits (result, "dptr", FPOINTER);
9996       if (AOP_INDPTRn(left)) {
9997           genSetDPTR(0);
9998       }
9999   } else
10000     {
10001       size = AOP_SIZE (result);
10002       offset = 0;
10003
10004       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10005           while (size--) {
10006               genSetDPTR(AOP(left)->aopu.dptr);
10007               emitcode ("movx", "a,@dptr");
10008               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10009                   emitcode ("inc", "dptr");
10010               genSetDPTR (0);
10011               aopPut (AOP (result), "a", offset++);
10012           }
10013       } else {
10014           _startLazyDPSEvaluation ();
10015           while (size--) {
10016               if (AOP_INDPTRn(left)) {
10017                   genSetDPTR(AOP(left)->aopu.dptr);
10018               } else {
10019                   genSetDPTR (0);
10020               }
10021               _flushLazyDPS ();
10022
10023               emitcode ("movx", "a,@dptr");
10024               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10025                   emitcode ("inc", "dptr");
10026
10027               aopPut (AOP (result), "a", offset++);
10028           }
10029           _endLazyDPSEvaluation ();
10030       }
10031     }
10032   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10033       if (!AOP_INDPTRn(left)) {
10034           _startLazyDPSEvaluation ();
10035           aopPut ( AOP (left), "dpl", 0);
10036           aopPut ( AOP (left), "dph", 1);
10037           if (options.model == MODEL_FLAT24)
10038               aopPut ( AOP (left), "dpx", 2);
10039           _endLazyDPSEvaluation ();
10040       }
10041     pi->generated = 1;
10042   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10043              AOP_SIZE(result) > 1 &&
10044              IS_SYMOP(left) &&
10045              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10046
10047       size = AOP_SIZE (result) - 1;
10048       if (AOP_INDPTRn(left)) {
10049           genSetDPTR(AOP(left)->aopu.dptr);
10050       }
10051       while (size--) emitcode ("lcall","__decdptr");
10052       if (AOP_INDPTRn(left)) {
10053           genSetDPTR(0);
10054       }
10055   }
10056
10057   freeAsmop (left, NULL, ic, TRUE);
10058   freeAsmop (result, NULL, ic, TRUE);
10059 }
10060
10061 /*-----------------------------------------------------------------*/
10062 /* genCodePointerGet - get value from code space                  */
10063 /*-----------------------------------------------------------------*/
10064 static void
10065 genCodePointerGet (operand * left,
10066                     operand * result, iCode * ic, iCode *pi)
10067 {
10068   int size, offset, dopi=1;
10069   sym_link *retype = getSpec (operandType (result));
10070
10071   aopOp (left, ic, FALSE, FALSE);
10072
10073   /* if the operand is already in dptr
10074      then we do nothing else we move the value to dptr */
10075   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10076     {
10077       /* if this is remateriazable */
10078       if (AOP_TYPE (left) == AOP_IMMD)
10079         {
10080           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10081         }
10082       else
10083         {                       /* we need to get it byte by byte */
10084           _startLazyDPSEvaluation ();
10085           if (AOP_TYPE (left) != AOP_DPTR)
10086             {
10087               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10088               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10089               if (options.model == MODEL_FLAT24)
10090                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10091             }
10092           else
10093             {
10094               /* We need to generate a load to DPTR indirect through DPTR. */
10095               D (emitcode (";", "gencodePointerGet -- indirection special case."););
10096               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10097               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10098               if (options.model == MODEL_FLAT24)
10099                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10100               emitcode ("pop", "dph");
10101               emitcode ("pop", "dpl");
10102               dopi=0;
10103             }
10104           _endLazyDPSEvaluation ();
10105         }
10106     }
10107   /* so dptr know contains the address */
10108   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10109
10110   /* if bit then unpack */
10111   if (IS_BITFIELD (retype)) {
10112       if (AOP_INDPTRn(left)) {
10113           genSetDPTR(AOP(left)->aopu.dptr);
10114       }
10115       genUnpackBits (result, "dptr", CPOINTER);
10116       if (AOP_INDPTRn(left)) {
10117           genSetDPTR(0);
10118       }
10119   } else
10120     {
10121       size = AOP_SIZE (result);
10122       offset = 0;
10123       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10124           while (size--) {
10125               genSetDPTR(AOP(left)->aopu.dptr);
10126               emitcode ("clr", "a");
10127               emitcode ("movc", "a,@a+dptr");
10128               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10129                   emitcode ("inc", "dptr");
10130               genSetDPTR (0);
10131               aopPut (AOP (result), "a", offset++);
10132           }
10133       } else {
10134           _startLazyDPSEvaluation ();
10135           while (size--)
10136               {
10137                   if (AOP_INDPTRn(left)) {
10138                       genSetDPTR(AOP(left)->aopu.dptr);
10139                   } else {
10140                       genSetDPTR (0);
10141                   }
10142                   _flushLazyDPS ();
10143
10144                   emitcode ("clr", "a");
10145                   emitcode ("movc", "a,@a+dptr");
10146                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10147                       emitcode ("inc", "dptr");
10148                   aopPut (AOP (result), "a", offset++);
10149               }
10150           _endLazyDPSEvaluation ();
10151       }
10152     }
10153   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10154       if (!AOP_INDPTRn(left)) {
10155           _startLazyDPSEvaluation ();
10156
10157           aopPut ( AOP (left), "dpl", 0);
10158           aopPut ( AOP (left), "dph", 1);
10159           if (options.model == MODEL_FLAT24)
10160               aopPut ( AOP (left), "dpx", 2);
10161
10162           _endLazyDPSEvaluation ();
10163       }
10164       pi->generated = 1;
10165   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10166              AOP_SIZE(result) > 1 &&
10167              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10168
10169       size = AOP_SIZE (result) - 1;
10170       if (AOP_INDPTRn(left)) {
10171           genSetDPTR(AOP(left)->aopu.dptr);
10172       }
10173       while (size--) emitcode ("lcall","__decdptr");
10174       if (AOP_INDPTRn(left)) {
10175           genSetDPTR(0);
10176       }
10177   }
10178
10179   freeAsmop (left, NULL, ic, TRUE);
10180   freeAsmop (result, NULL, ic, TRUE);
10181 }
10182
10183 /*-----------------------------------------------------------------*/
10184 /* genGenPointerGet - gget value from generic pointer space        */
10185 /*-----------------------------------------------------------------*/
10186 static void
10187 genGenPointerGet (operand * left,
10188                   operand * result, iCode * ic, iCode * pi)
10189 {
10190   int size, offset;
10191   sym_link *retype = getSpec (operandType (result));
10192   sym_link *letype = getSpec (operandType (left));
10193
10194   D (emitcode (";", "genGenPointerGet "); );
10195
10196   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10197
10198   /* if the operand is already in dptr
10199      then we do nothing else we move the value to dptr */
10200   if (AOP_TYPE (left) != AOP_STR)
10201     {
10202       /* if this is rematerializable */
10203       if (AOP_TYPE (left) == AOP_IMMD)
10204         {
10205           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10206           if (AOP(left)->aopu.aop_immd.from_cast_remat)
10207             {
10208               MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10209             }
10210           else
10211             {
10212               emitcode ("mov", "b,#%d", pointerCode (retype));
10213             }
10214         }
10215       else
10216         {                       /* we need to get it byte by byte */
10217           _startLazyDPSEvaluation ();
10218           emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10219           emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10220           if (options.model == MODEL_FLAT24) {
10221               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10222               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10223           } else {
10224               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10225           }
10226           _endLazyDPSEvaluation ();
10227         }
10228     }
10229
10230   /* so dptr-b now contains the address */
10231   _G.bInUse++;
10232   aopOp (result, ic, FALSE, TRUE);
10233   _G.bInUse--;
10234
10235   /* if bit then unpack */
10236   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10237   {
10238     genUnpackBits (result, "dptr", GPOINTER);
10239   }
10240   else
10241     {
10242         size = AOP_SIZE (result);
10243         offset = 0;
10244
10245         while (size--)
10246         {
10247             if (size)
10248             {
10249                 // Get two bytes at a time, results in _AP & A.
10250                 // dptr will be incremented ONCE by __gptrgetWord.
10251                 //
10252                 // Note: any change here must be coordinated
10253                 // with the implementation of __gptrgetWord
10254                 // in device/lib/_gptrget.c
10255                 emitcode ("lcall", "__gptrgetWord");
10256                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10257                 aopPut (AOP (result), "a", offset++);
10258                 size--;
10259             }
10260             else
10261             {
10262                 // Only one byte to get.
10263                 emitcode ("lcall", "__gptrget");
10264                 aopPut (AOP (result), "a", offset++);
10265             }
10266
10267             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10268             {
10269                 emitcode ("inc", "dptr");
10270             }
10271         }
10272     }
10273
10274   if (pi && AOP_TYPE (left) != AOP_IMMD) {
10275     _startLazyDPSEvaluation ();
10276
10277     aopPut ( AOP (left), "dpl", 0);
10278     aopPut ( AOP (left), "dph", 1);
10279     if (options.model == MODEL_FLAT24) {
10280         aopPut ( AOP (left), "dpx", 2);
10281         aopPut ( AOP (left), "b", 3);
10282     } else  aopPut ( AOP (left), "b", 2);
10283
10284     _endLazyDPSEvaluation ();
10285
10286     pi->generated = 1;
10287   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10288              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10289
10290       size = AOP_SIZE (result) - 1;
10291       while (size--) emitcode ("lcall","__decdptr");
10292   }
10293
10294   freeAsmop (left, NULL, ic, TRUE);
10295   freeAsmop (result, NULL, ic, TRUE);
10296 }
10297
10298 /*-----------------------------------------------------------------*/
10299 /* genPointerGet - generate code for pointer get                   */
10300 /*-----------------------------------------------------------------*/
10301 static void
10302 genPointerGet (iCode * ic, iCode *pi)
10303 {
10304   operand *left, *result;
10305   sym_link *type, *etype;
10306   int p_type;
10307
10308   D (emitcode (";", "genPointerGet ");
10309     );
10310
10311   left = IC_LEFT (ic);
10312   result = IC_RESULT (ic);
10313
10314   /* depending on the type of pointer we need to
10315      move it to the correct pointer register */
10316   type = operandType (left);
10317   etype = getSpec (type);
10318   /* if left is of type of pointer then it is simple */
10319   if (IS_PTR (type) && !IS_FUNC (type->next))
10320     p_type = DCL_TYPE (type);
10321   else
10322     {
10323       /* we have to go by the storage class */
10324       p_type = PTR_TYPE (SPEC_OCLS (etype));
10325     }
10326   /* special case when cast remat */
10327   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10328       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10329     {
10330       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10331       type = operandType (left);
10332       p_type = DCL_TYPE (type);
10333     }
10334   /* now that we have the pointer type we assign
10335      the pointer values */
10336   switch (p_type)
10337     {
10338
10339     case POINTER:
10340     case IPOINTER:
10341       genNearPointerGet (left, result, ic, pi);
10342       break;
10343
10344     case PPOINTER:
10345       genPagedPointerGet (left, result, ic, pi);
10346       break;
10347
10348     case FPOINTER:
10349       genFarPointerGet (left, result, ic, pi);
10350       break;
10351
10352     case CPOINTER:
10353       genCodePointerGet (left, result, ic, pi);
10354       break;
10355
10356     case GPOINTER:
10357       genGenPointerGet (left, result, ic, pi);
10358       break;
10359     }
10360
10361 }
10362
10363 /*-----------------------------------------------------------------*/
10364 /* genPackBits - generates code for packed bit storage             */
10365 /*-----------------------------------------------------------------*/
10366 static void
10367 genPackBits (sym_link * etype,
10368              operand * right,
10369              char *rname, int p_type)
10370 {
10371   int offset = 0;       /* source byte offset */
10372   int rlen = 0;         /* remaining bitfield length */
10373   int blen;             /* bitfield length */
10374   int bstr;             /* bitfield starting bit within byte */
10375   int litval;           /* source literal value (if AOP_LIT) */
10376   unsigned char mask;   /* bitmask within current byte */
10377
10378   D(emitcode (";     genPackBits",""));
10379
10380   blen = SPEC_BLEN (etype);
10381   bstr = SPEC_BSTR (etype);
10382
10383   /* If the bitfield length is less than a byte */
10384   if (blen < 8)
10385     {
10386       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10387               (unsigned char) (0xFF >> (8 - bstr)));
10388
10389       if (AOP_TYPE (right) == AOP_LIT)
10390         {
10391           /* Case with a bitfield length <8 and literal source
10392           */
10393           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10394           litval <<= bstr;
10395           litval &= (~mask) & 0xff;
10396           emitPtrByteGet (rname, p_type, FALSE);
10397           if ((mask|litval)!=0xff)
10398             emitcode ("anl","a,#!constbyte", mask);
10399           if (litval)
10400             emitcode ("orl","a,#!constbyte", litval);
10401         }
10402       else
10403         {
10404           if ((blen==1) && (p_type!=GPOINTER))
10405             {
10406               /* Case with a bitfield length == 1 and no generic pointer
10407               */
10408               if (AOP_TYPE (right) == AOP_CRY)
10409                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10410               else
10411                 {
10412                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10413                   emitcode ("rrc","a");
10414                 }
10415               emitPtrByteGet (rname, p_type, FALSE);
10416               emitcode ("mov","acc.%d,c",bstr);
10417             }
10418           else
10419             {
10420               /* Case with a bitfield length < 8 and arbitrary source
10421               */
10422               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10423               /* shift and mask source value */
10424               AccLsh (bstr);
10425               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10426
10427               /* transfer A to B and get next byte */
10428               emitPtrByteGet (rname, p_type, TRUE);
10429
10430               emitcode ("anl", "a,#!constbyte", mask);
10431               emitcode ("orl", "a,b");
10432               if (p_type == GPOINTER)
10433                 emitcode ("pop", "b");
10434            }
10435         }
10436
10437       emitPtrByteSet (rname, p_type, "a");
10438       return;
10439     }
10440
10441   /* Bit length is greater than 7 bits. In this case, copy  */
10442   /* all except the partial byte at the end                 */
10443   for (rlen=blen;rlen>=8;rlen-=8)
10444     {
10445       emitPtrByteSet (rname, p_type,
10446                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10447       if (rlen>8)
10448         emitcode ("inc", "%s", rname);
10449     }
10450
10451   /* If there was a partial byte at the end */
10452   if (rlen)
10453     {
10454       mask = (((unsigned char) -1 << rlen) & 0xff);
10455
10456       if (AOP_TYPE (right) == AOP_LIT)
10457         {
10458           /* Case with partial byte and literal source
10459           */
10460           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10461           litval >>= (blen-rlen);
10462           litval &= (~mask) & 0xff;
10463           emitPtrByteGet (rname, p_type, FALSE);
10464           if ((mask|litval)!=0xff)
10465             emitcode ("anl","a,#!constbyte", mask);
10466           if (litval)
10467             emitcode ("orl","a,#!constbyte", litval);
10468         }
10469       else
10470         {
10471           /* Case with partial byte and arbitrary source
10472           */
10473           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10474           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10475
10476           /* transfer A to B and get next byte */
10477           emitPtrByteGet (rname, p_type, TRUE);
10478
10479           emitcode ("anl", "a,#!constbyte", mask);
10480           emitcode ("orl", "a,b");
10481           if (p_type == GPOINTER)
10482             emitcode ("pop", "b");
10483         }
10484       emitPtrByteSet (rname, p_type, "a");
10485     }
10486
10487 }
10488
10489
10490 /*-----------------------------------------------------------------*/
10491 /* genDataPointerSet - remat pointer to data space                 */
10492 /*-----------------------------------------------------------------*/
10493 static void
10494 genDataPointerSet (operand * right,
10495                    operand * result,
10496                    iCode * ic)
10497 {
10498   int size, offset = 0;
10499   char *l, buff[256];
10500
10501   aopOp (right, ic, FALSE, FALSE);
10502
10503   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10504   size = AOP_SIZE (right);
10505   while (size--)
10506     {
10507       if (offset)
10508         {
10509             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10510         }
10511       else
10512         {
10513             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10514         }
10515
10516       emitcode ("mov", "%s,%s", buff,
10517                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10518     }
10519
10520   freeAsmop (right, NULL, ic, TRUE);
10521   freeAsmop (result, NULL, ic, TRUE);
10522 }
10523
10524 /*-----------------------------------------------------------------*/
10525 /* genNearPointerSet - emitcode for near pointer put                */
10526 /*-----------------------------------------------------------------*/
10527 static void
10528 genNearPointerSet (operand * right,
10529                    operand * result,
10530                    iCode * ic,
10531                    iCode * pi)
10532 {
10533   asmop *aop = NULL;
10534   char *rname, *l;
10535   sym_link *retype, *letype;
10536   sym_link *ptype = operandType (result);
10537
10538   retype = getSpec (operandType (right));
10539   letype = getSpec (ptype);
10540
10541   aopOp (result, ic, FALSE, FALSE);
10542
10543   /* if the result is rematerializable &
10544      in data space & not a bit variable */
10545   if (AOP_TYPE (result) == AOP_IMMD &&
10546       DCL_TYPE (ptype) == POINTER &&
10547       !IS_BITVAR (retype) &&
10548       !IS_BITVAR (letype))
10549     {
10550       genDataPointerSet (right, result, ic);
10551       return;
10552     }
10553
10554   /* if the value is already in a pointer register
10555      then don't need anything more */
10556   if (!AOP_INPREG (AOP (result)))
10557     {
10558       /* otherwise get a free pointer register */
10559       regs *preg;
10560
10561       aop = newAsmop (0);
10562       preg = getFreePtr (ic, &aop, FALSE);
10563       emitcode ("mov", "%s,%s",
10564                 preg->name,
10565                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10566       rname = preg->name;
10567     }
10568   else
10569     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10570
10571   aopOp (right, ic, FALSE, FALSE);
10572
10573   /* if bitfield then unpack the bits */
10574   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10575     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10576   else
10577     {
10578       /* we have can just get the values */
10579       int size = AOP_SIZE (right);
10580       int offset = 0;
10581
10582       while (size--)
10583         {
10584           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10585           if (*l == '@')
10586             {
10587               MOVA (l);
10588               emitcode ("mov", "@%s,a", rname);
10589             }
10590           else
10591             emitcode ("mov", "@%s,%s", rname, l);
10592           if (size || pi)
10593             emitcode ("inc", "%s", rname);
10594           offset++;
10595         }
10596     }
10597
10598   /* now some housekeeping stuff */
10599   if (aop)
10600     {
10601       /* we had to allocate for this iCode */
10602       if (pi) aopPut (AOP (result),rname,0);
10603       freeAsmop (NULL, aop, ic, TRUE);
10604     }
10605   else
10606     {
10607       /* we did not allocate which means left
10608          already in a pointer register, then
10609          if size > 0 && this could be used again
10610          we have to point it back to where it
10611          belongs */
10612       if (AOP_SIZE (right) > 1 &&
10613           !OP_SYMBOL (result)->remat &&
10614           (OP_SYMBOL (result)->liveTo > ic->seq ||
10615            ic->depth) &&
10616           !pi)
10617         {
10618           int size = AOP_SIZE (right) - 1;
10619           while (size--)
10620             emitcode ("dec", "%s", rname);
10621         }
10622     }
10623
10624   /* done */
10625   if (pi) pi->generated = 1;
10626   freeAsmop (result, NULL, ic, TRUE);
10627   freeAsmop (right, NULL, ic, TRUE);
10628
10629
10630 }
10631
10632 /*-----------------------------------------------------------------*/
10633 /* genPagedPointerSet - emitcode for Paged pointer put             */
10634 /*-----------------------------------------------------------------*/
10635 static void
10636 genPagedPointerSet (operand * right,
10637                     operand * result,
10638                     iCode * ic,
10639                     iCode *pi)
10640 {
10641   asmop *aop = NULL;
10642   char *rname;
10643   sym_link *retype, *letype;
10644
10645   retype = getSpec (operandType (right));
10646   letype = getSpec (operandType (result));
10647
10648   aopOp (result, ic, FALSE, FALSE);
10649
10650   /* if the value is already in a pointer register
10651      then don't need anything more */
10652   if (!AOP_INPREG (AOP (result)))
10653     {
10654       /* otherwise get a free pointer register */
10655       regs *preg;
10656
10657       aop = newAsmop (0);
10658       preg = getFreePtr (ic, &aop, FALSE);
10659       emitcode ("mov", "%s,%s",
10660                 preg->name,
10661                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10662       rname = preg->name;
10663     }
10664   else
10665     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10666
10667   aopOp (right, ic, FALSE, FALSE);
10668
10669   /* if bitfield then unpack the bits */
10670   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10671     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10672   else
10673     {
10674       /* we have can just get the values */
10675       int size = AOP_SIZE (right);
10676       int offset = 0;
10677
10678       while (size--)
10679         {
10680           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10681
10682           emitcode ("movx", "@%s,a", rname);
10683
10684           if (size || pi)
10685             emitcode ("inc", "%s", rname);
10686
10687           offset++;
10688         }
10689     }
10690
10691   /* now some housekeeping stuff */
10692   if (aop)
10693     {
10694       if (pi) aopPut (AOP (result),rname,0);
10695       /* we had to allocate for this iCode */
10696       freeAsmop (NULL, aop, ic, TRUE);
10697     }
10698   else
10699     {
10700       /* we did not allocate which means left
10701          already in a pointer register, then
10702          if size > 0 && this could be used again
10703          we have to point it back to where it
10704          belongs */
10705       if (AOP_SIZE (right) > 1 &&
10706           !OP_SYMBOL (result)->remat &&
10707           (OP_SYMBOL (result)->liveTo > ic->seq ||
10708            ic->depth) &&
10709           !pi)
10710         {
10711           int size = AOP_SIZE (right) - 1;
10712           while (size--)
10713             emitcode ("dec", "%s", rname);
10714         }
10715     }
10716
10717   /* done */
10718   if (pi) pi->generated = 1;
10719   freeAsmop (result, NULL, ic, TRUE);
10720   freeAsmop (right, NULL, ic, TRUE);
10721
10722
10723 }
10724
10725 /*-----------------------------------------------------------------*/
10726 /* genFarPointerSet - set value from far space                     */
10727 /*-----------------------------------------------------------------*/
10728 static void
10729 genFarPointerSet (operand * right,
10730                   operand * result, iCode * ic, iCode *pi)
10731 {
10732   int size, offset, dopi=1;
10733   sym_link *retype = getSpec (operandType (right));
10734   sym_link *letype = getSpec (operandType (result));
10735
10736   aopOp (result, ic, FALSE, FALSE);
10737
10738   /* if the operand is already in dptr
10739      then we do nothing else we move the value to dptr */
10740   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10741     {
10742       /* if this is remateriazable */
10743       if (AOP_TYPE (result) == AOP_IMMD)
10744         emitcode ("mov", "dptr,%s",
10745                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10746       else
10747         {
10748           /* we need to get it byte by byte */
10749           _startLazyDPSEvaluation ();
10750           if (AOP_TYPE (result) != AOP_DPTR)
10751             {
10752               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10753               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10754               if (options.model == MODEL_FLAT24)
10755                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10756             }
10757           else
10758             {
10759               /* We need to generate a load to DPTR indirect through DPTR. */
10760               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10761
10762               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10763               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10764               if (options.model == MODEL_FLAT24)
10765                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10766               emitcode ("pop", "dph");
10767               emitcode ("pop", "dpl");
10768               dopi=0;
10769             }
10770           _endLazyDPSEvaluation ();
10771         }
10772     }
10773   /* so dptr know contains the address */
10774   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10775
10776   /* if bit then unpack */
10777   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10778       if (AOP_INDPTRn(result)) {
10779           genSetDPTR(AOP(result)->aopu.dptr);
10780       }
10781       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10782       if (AOP_INDPTRn(result)) {
10783           genSetDPTR(0);
10784       }
10785   } else {
10786       size = AOP_SIZE (right);
10787       offset = 0;
10788       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10789           while (size--) {
10790               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10791
10792               genSetDPTR(AOP(result)->aopu.dptr);
10793               emitcode ("movx", "@dptr,a");
10794               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10795                   emitcode ("inc", "dptr");
10796               genSetDPTR (0);
10797           }
10798       } else {
10799           _startLazyDPSEvaluation ();
10800           while (size--) {
10801               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10802
10803               if (AOP_INDPTRn(result)) {
10804                   genSetDPTR(AOP(result)->aopu.dptr);
10805               } else {
10806                   genSetDPTR (0);
10807               }
10808               _flushLazyDPS ();
10809
10810               emitcode ("movx", "@dptr,a");
10811               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10812                   emitcode ("inc", "dptr");
10813           }
10814           _endLazyDPSEvaluation ();
10815       }
10816   }
10817
10818   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10819       if (!AOP_INDPTRn(result)) {
10820           _startLazyDPSEvaluation ();
10821
10822           aopPut (AOP(result),"dpl",0);
10823           aopPut (AOP(result),"dph",1);
10824           if (options.model == MODEL_FLAT24)
10825               aopPut (AOP(result),"dpx",2);
10826
10827           _endLazyDPSEvaluation ();
10828       }
10829       pi->generated=1;
10830   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10831              AOP_SIZE(right) > 1 &&
10832              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10833
10834       size = AOP_SIZE (right) - 1;
10835       if (AOP_INDPTRn(result)) {
10836           genSetDPTR(AOP(result)->aopu.dptr);
10837       }
10838       while (size--) emitcode ("lcall","__decdptr");
10839       if (AOP_INDPTRn(result)) {
10840           genSetDPTR(0);
10841       }
10842   }
10843   freeAsmop (result, NULL, ic, TRUE);
10844   freeAsmop (right, NULL, ic, TRUE);
10845 }
10846
10847 /*-----------------------------------------------------------------*/
10848 /* genGenPointerSet - set value from generic pointer space         */
10849 /*-----------------------------------------------------------------*/
10850 static void
10851 genGenPointerSet (operand * right,
10852                   operand * result, iCode * ic, iCode *pi)
10853 {
10854   int size, offset;
10855   sym_link *retype = getSpec (operandType (right));
10856   sym_link *letype = getSpec (operandType (result));
10857
10858   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10859
10860   /* if the operand is already in dptr
10861      then we do nothing else we move the value to dptr */
10862   if (AOP_TYPE (result) != AOP_STR)
10863     {
10864       _startLazyDPSEvaluation ();
10865       /* if this is remateriazable */
10866       if (AOP_TYPE (result) == AOP_IMMD)
10867         {
10868           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10869           if (AOP(result)->aopu.aop_immd.from_cast_remat)
10870           {
10871               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10872           }
10873           else
10874           {
10875               emitcode ("mov",
10876                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10877           }
10878         }
10879       else
10880         {                       /* we need to get it byte by byte */
10881           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10882           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10883           if (options.model == MODEL_FLAT24) {
10884             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10885             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10886           } else {
10887             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10888           }
10889         }
10890       _endLazyDPSEvaluation ();
10891     }
10892   /* so dptr + b now contains the address */
10893   _G.bInUse++;
10894   aopOp (right, ic, FALSE, TRUE);
10895   _G.bInUse--;
10896
10897
10898   /* if bit then unpack */
10899   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10900     {
10901         genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10902     }
10903   else
10904     {
10905         size = AOP_SIZE (right);
10906         offset = 0;
10907
10908         _startLazyDPSEvaluation ();
10909         while (size--)
10910         {
10911             if (size)
10912             {
10913                 // Set two bytes at a time, passed in _AP & A.
10914                 // dptr will be incremented ONCE by __gptrputWord.
10915                 //
10916                 // Note: any change here must be coordinated
10917                 // with the implementation of __gptrputWord
10918                 // in device/lib/_gptrput.c
10919                 emitcode("mov", "_ap, %s",
10920                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10921                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10922
10923                 genSetDPTR (0);
10924                 _flushLazyDPS ();
10925                 emitcode ("lcall", "__gptrputWord");
10926                 size--;
10927             }
10928             else
10929             {
10930                 // Only one byte to put.
10931                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10932
10933                 genSetDPTR (0);
10934                 _flushLazyDPS ();
10935                 emitcode ("lcall", "__gptrput");
10936             }
10937
10938             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10939             {
10940                 emitcode ("inc", "dptr");
10941             }
10942         }
10943         _endLazyDPSEvaluation ();
10944     }
10945
10946   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10947       _startLazyDPSEvaluation ();
10948
10949       aopPut (AOP(result),"dpl",0);
10950       aopPut (AOP(result),"dph",1);
10951       if (options.model == MODEL_FLAT24) {
10952           aopPut (AOP(result),"dpx",2);
10953           aopPut (AOP(result),"b",3);
10954       } else {
10955           aopPut (AOP(result),"b",2);
10956       }
10957       _endLazyDPSEvaluation ();
10958
10959       pi->generated=1;
10960   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10961              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10962
10963       size = AOP_SIZE (right) - 1;
10964       while (size--) emitcode ("lcall","__decdptr");
10965   }
10966   freeAsmop (result, NULL, ic, TRUE);
10967   freeAsmop (right, NULL, ic, TRUE);
10968 }
10969
10970 /*-----------------------------------------------------------------*/
10971 /* genPointerSet - stores the value into a pointer location        */
10972 /*-----------------------------------------------------------------*/
10973 static void
10974 genPointerSet (iCode * ic, iCode *pi)
10975 {
10976   operand *right, *result;
10977   sym_link *type, *etype;
10978   int p_type;
10979
10980   D (emitcode (";", "genPointerSet "););
10981
10982   right = IC_RIGHT (ic);
10983   result = IC_RESULT (ic);
10984
10985   /* depending on the type of pointer we need to
10986      move it to the correct pointer register */
10987   type = operandType (result);
10988   etype = getSpec (type);
10989   /* if left is of type of pointer then it is simple */
10990   if (IS_PTR (type) && !IS_FUNC (type->next))
10991     {
10992       p_type = DCL_TYPE (type);
10993     }
10994   else
10995     {
10996       /* we have to go by the storage class */
10997       p_type = PTR_TYPE (SPEC_OCLS (etype));
10998     }
10999   /* special case when cast remat */
11000   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11001       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11002           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11003           type = operandType (result);
11004           p_type = DCL_TYPE (type);
11005   }
11006
11007   /* now that we have the pointer type we assign
11008      the pointer values */
11009   switch (p_type)
11010     {
11011
11012     case POINTER:
11013     case IPOINTER:
11014       genNearPointerSet (right, result, ic, pi);
11015       break;
11016
11017     case PPOINTER:
11018       genPagedPointerSet (right, result, ic, pi);
11019       break;
11020
11021     case FPOINTER:
11022       genFarPointerSet (right, result, ic, pi);
11023       break;
11024
11025     case GPOINTER:
11026       genGenPointerSet (right, result, ic, pi);
11027       break;
11028
11029     default:
11030       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11031               "genPointerSet: illegal pointer type");
11032     }
11033
11034 }
11035
11036 /*-----------------------------------------------------------------*/
11037 /* genIfx - generate code for Ifx statement                        */
11038 /*-----------------------------------------------------------------*/
11039 static void
11040 genIfx (iCode * ic, iCode * popIc)
11041 {
11042   operand *cond = IC_COND (ic);
11043   int isbit = 0;
11044
11045   D (emitcode (";", "genIfx "););
11046
11047   aopOp (cond, ic, FALSE, FALSE);
11048
11049   /* get the value into acc */
11050   if (AOP_TYPE (cond) != AOP_CRY)
11051     {
11052         toBoolean (cond);
11053     }
11054   else
11055     {
11056         isbit = 1;
11057     }
11058
11059   /* the result is now in the accumulator */
11060   freeAsmop (cond, NULL, ic, TRUE);
11061
11062   /* if there was something to be popped then do it */
11063   if (popIc)
11064     genIpop (popIc);
11065
11066   /* if the condition is  a bit variable */
11067   if (isbit && IS_ITEMP (cond) &&
11068       SPIL_LOC (cond))
11069     {
11070         genIfxJump (ic, SPIL_LOC (cond)->rname);
11071     }
11072   else if (isbit && !IS_ITEMP (cond))
11073     {
11074         genIfxJump (ic, OP_SYMBOL (cond)->rname);
11075     }
11076   else
11077     {
11078         genIfxJump (ic, "a");
11079     }
11080
11081   ic->generated = 1;
11082 }
11083
11084 /*-----------------------------------------------------------------*/
11085 /* genAddrOf - generates code for address of                       */
11086 /*-----------------------------------------------------------------*/
11087 static void
11088 genAddrOf (iCode * ic)
11089 {
11090   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11091   int size, offset;
11092
11093   D (emitcode (";", "genAddrOf ");
11094     );
11095
11096   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11097
11098   /* if the operand is on the stack then we
11099      need to get the stack offset of this
11100      variable */
11101   if (sym->onStack) {
11102
11103       /* if 10 bit stack */
11104       if (options.stack10bit) {
11105           char buff[10];
11106           int  offset;
11107
11108           tsprintf(buff, sizeof(buff),
11109                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
11110           /* if it has an offset then we need to compute it */
11111 /*        emitcode ("subb", "a,#!constbyte", */
11112 /*                  -((sym->stack < 0) ? */
11113 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
11114 /*                    ((short) sym->stack)) & 0xff); */
11115 /*        emitcode ("mov","b,a"); */
11116 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11117 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
11118 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
11119           if (sym->stack) {
11120               emitcode ("mov", "a,_bpx");
11121               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11122                                              ((char) (sym->stack - _G.nRegsSaved)) :
11123                                              ((char) sym->stack )) & 0xff);
11124               emitcode ("mov", "b,a");
11125               emitcode ("mov", "a,_bpx+1");
11126
11127               offset = (((sym->stack < 0) ?
11128                          ((short) (sym->stack - _G.nRegsSaved)) :
11129                          ((short) sym->stack )) >> 8) & 0xff;
11130
11131               emitcode ("addc","a,#!constbyte", offset);
11132
11133               aopPut (AOP (IC_RESULT (ic)), "b", 0);
11134               aopPut (AOP (IC_RESULT (ic)), "a", 1);
11135               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11136           } else {
11137               /* we can just move _bp */
11138               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11139               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11140               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11141           }
11142       } else {
11143           /* if it has an offset then we need to compute it */
11144           if (sym->stack) {
11145               emitcode ("mov", "a,_bp");
11146               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11147               aopPut (AOP (IC_RESULT (ic)), "a", 0);
11148           } else {
11149               /* we can just move _bp */
11150               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11151           }
11152           /* fill the result with zero */
11153           size = AOP_SIZE (IC_RESULT (ic)) - 1;
11154
11155
11156           if (options.stack10bit && size < (FPTRSIZE - 1)) {
11157               fprintf (stderr,
11158                        "*** warning: pointer to stack var truncated.\n");
11159           }
11160
11161           offset = 1;
11162           while (size--) {
11163               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11164           }
11165       }
11166       goto release;
11167   }
11168
11169   /* object not on stack then we need the name */
11170   size = AOP_SIZE (IC_RESULT (ic));
11171   offset = 0;
11172
11173   while (size--)
11174     {
11175       char s[SDCC_NAME_MAX];
11176       if (offset) {
11177           switch (offset) {
11178           case 1:
11179               tsprintf(s, sizeof(s), "#!his",sym->rname);
11180               break;
11181           case 2:
11182               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11183               break;
11184           case 3:
11185               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11186               break;
11187           default: /* should not need this (just in case) */
11188               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11189                        sym->rname,
11190                        offset * 8);
11191           }
11192       }
11193       else
11194       {
11195           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11196       }
11197
11198       aopPut (AOP (IC_RESULT (ic)), s, offset++);
11199     }
11200
11201 release:
11202   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11203
11204 }
11205
11206 #if 0 // obsolete, and buggy for != xdata
11207 /*-----------------------------------------------------------------*/
11208 /* genArrayInit - generates code for address of                       */
11209 /*-----------------------------------------------------------------*/
11210 static void
11211 genArrayInit (iCode * ic)
11212 {
11213     literalList *iLoop;
11214     int         ix, count;
11215     int         elementSize = 0, eIndex;
11216     unsigned    val, lastVal;
11217     sym_link    *type;
11218     operand     *left=IC_LEFT(ic);
11219
11220     D (emitcode (";", "genArrayInit "););
11221
11222     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11223
11224     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11225     {
11226         // Load immediate value into DPTR.
11227         emitcode("mov", "dptr, %s",
11228              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11229     }
11230     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11231     {
11232 #if 0
11233       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11234               "Unexpected operand to genArrayInit.\n");
11235       exit(1);
11236 #else
11237       // a regression because of SDCCcse.c:1.52
11238       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11239       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11240       if (options.model == MODEL_FLAT24)
11241         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11242 #endif
11243     }
11244
11245     type = operandType(IC_LEFT(ic));
11246
11247     if (type && type->next)
11248     {
11249         elementSize = getSize(type->next);
11250     }
11251     else
11252     {
11253         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11254                                 "can't determine element size in genArrayInit.\n");
11255         exit(1);
11256     }
11257
11258     iLoop = IC_ARRAYILIST(ic);
11259     lastVal = 0xffff;
11260
11261     while (iLoop)
11262     {
11263         bool firstpass = TRUE;
11264
11265         emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11266                  iLoop->count, (int)iLoop->literalValue, elementSize);
11267
11268         ix = iLoop->count;
11269
11270         while (ix)
11271         {
11272             symbol *tlbl = NULL;
11273
11274             count = ix > 256 ? 256 : ix;
11275
11276             if (count > 1)
11277             {
11278                 tlbl = newiTempLabel (NULL);
11279                 if (firstpass || (count & 0xff))
11280                 {
11281                     emitcode("mov", "b, #!constbyte", count & 0xff);
11282                 }
11283
11284                 emitcode ("", "!tlabeldef", tlbl->key + 100);
11285             }
11286
11287             firstpass = FALSE;
11288
11289             for (eIndex = 0; eIndex < elementSize; eIndex++)
11290             {
11291                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11292                 if (val != lastVal)
11293                 {
11294                     emitcode("mov", "a, #!constbyte", val);
11295                     lastVal = val;
11296                 }
11297
11298                 emitcode("movx", "@dptr, a");
11299                 emitcode("inc", "dptr");
11300             }
11301
11302             if (count > 1)
11303             {
11304                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11305             }
11306
11307             ix -= count;
11308         }
11309
11310         iLoop = iLoop->next;
11311     }
11312
11313     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11314 }
11315 #endif
11316
11317 /*-----------------------------------------------------------------*/
11318 /* genFarFarAssign - assignment when both are in far space         */
11319 /*-----------------------------------------------------------------*/
11320 static void
11321 genFarFarAssign (operand * result, operand * right, iCode * ic)
11322 {
11323   int size = AOP_SIZE (right);
11324   int offset = 0;
11325   symbol *rSym = NULL;
11326
11327   if (size == 1)
11328   {
11329       /* quick & easy case. */
11330       D(emitcode(";","genFarFarAssign (1 byte case)"););
11331       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11332       freeAsmop (right, NULL, ic, FALSE);
11333       /* now assign DPTR to result */
11334       _G.accInUse++;
11335       aopOp(result, ic, FALSE, FALSE);
11336       _G.accInUse--;
11337       aopPut(AOP(result), "a", 0);
11338       freeAsmop(result, NULL, ic, FALSE);
11339       return;
11340   }
11341
11342   /* See if we've got an underlying symbol to abuse. */
11343   if (IS_SYMOP(result) && OP_SYMBOL(result))
11344   {
11345       if (IS_TRUE_SYMOP(result))
11346       {
11347           rSym = OP_SYMBOL(result);
11348       }
11349       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11350       {
11351           rSym = OP_SYMBOL(result)->usl.spillLoc;
11352       }
11353   }
11354
11355   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11356   {
11357       /* We can use the '390 auto-toggle feature to good effect here. */
11358
11359       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11360       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
11361       emitcode ("mov", "dptr,#%s", rSym->rname);
11362       /* DP2 = result, DP1 = right, DP1 is current. */
11363       while (size)
11364       {
11365           emitcode("movx", "a,@dptr");
11366           emitcode("movx", "@dptr,a");
11367           if (--size)
11368           {
11369                emitcode("inc", "dptr");
11370                emitcode("inc", "dptr");
11371           }
11372       }
11373       emitcode("mov", "dps,#0");
11374       freeAsmop (right, NULL, ic, FALSE);
11375 #if 0
11376 some alternative code for processors without auto-toggle
11377 no time to test now, so later well put in...kpb
11378         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11379         emitcode("mov", "dps,#1");      /* Select DPTR2. */
11380         emitcode ("mov", "dptr,#%s", rSym->rname);
11381         /* DP2 = result, DP1 = right, DP1 is current. */
11382         while (size)
11383         {
11384           --size;
11385           emitcode("movx", "a,@dptr");
11386           if (size)
11387             emitcode("inc", "dptr");
11388           emitcode("inc", "dps");
11389           emitcode("movx", "@dptr,a");
11390           if (size)
11391             emitcode("inc", "dptr");
11392           emitcode("inc", "dps");
11393         }
11394         emitcode("mov", "dps,#0");
11395         freeAsmop (right, NULL, ic, FALSE);
11396 #endif
11397   }
11398   else
11399   {
11400       D (emitcode (";", "genFarFarAssign"););
11401       aopOp (result, ic, TRUE, TRUE);
11402
11403       _startLazyDPSEvaluation ();
11404
11405       while (size--)
11406         {
11407           aopPut (AOP (result),
11408                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11409           offset++;
11410         }
11411       _endLazyDPSEvaluation ();
11412       freeAsmop (result, NULL, ic, FALSE);
11413       freeAsmop (right, NULL, ic, FALSE);
11414   }
11415 }
11416
11417 /*-----------------------------------------------------------------*/
11418 /* genAssign - generate code for assignment                        */
11419 /*-----------------------------------------------------------------*/
11420 static void
11421 genAssign (iCode * ic)
11422 {
11423   operand *result, *right;
11424   int size, offset;
11425   unsigned long lit = 0L;
11426
11427   D (emitcode (";", "genAssign ");
11428     );
11429
11430   result = IC_RESULT (ic);
11431   right = IC_RIGHT (ic);
11432
11433   /* if they are the same */
11434   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11435     return;
11436
11437   aopOp (right, ic, FALSE, FALSE);
11438
11439   emitcode (";", "genAssign: resultIsFar = %s",
11440             isOperandInFarSpace (result) ?
11441             "TRUE" : "FALSE");
11442
11443   /* special case both in far space */
11444   if ((AOP_TYPE (right) == AOP_DPTR ||
11445        AOP_TYPE (right) == AOP_DPTR2) &&
11446   /* IS_TRUE_SYMOP(result)       && */
11447       isOperandInFarSpace (result))
11448     {
11449       genFarFarAssign (result, right, ic);
11450       return;
11451     }
11452
11453   aopOp (result, ic, TRUE, FALSE);
11454
11455   /* if they are the same registers */
11456   if (sameRegs (AOP (right), AOP (result)))
11457     goto release;
11458
11459   /* if the result is a bit */
11460   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11461     {
11462       /* if the right size is a literal then
11463          we know what the value is */
11464       if (AOP_TYPE (right) == AOP_LIT)
11465         {
11466           if (((int) operandLitValue (right)))
11467             aopPut (AOP (result), one, 0);
11468           else
11469             aopPut (AOP (result), zero, 0);
11470           goto release;
11471         }
11472
11473       /* the right is also a bit variable */
11474       if (AOP_TYPE (right) == AOP_CRY)
11475         {
11476           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11477           aopPut (AOP (result), "c", 0);
11478           goto release;
11479         }
11480
11481       /* we need to or */
11482       toBoolean (right);
11483       aopPut (AOP (result), "a", 0);
11484       goto release;
11485     }
11486
11487   /* bit variables done */
11488   /* general case */
11489   size = AOP_SIZE (result);
11490   offset = 0;
11491   if (AOP_TYPE (right) == AOP_LIT)
11492     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11493
11494   if ((size > 1) &&
11495       (AOP_TYPE (result) != AOP_REG) &&
11496       (AOP_TYPE (right) == AOP_LIT) &&
11497       !IS_FLOAT (operandType (right)))
11498     {
11499       _startLazyDPSEvaluation ();
11500       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11501         {
11502           aopPut (AOP (result),
11503                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11504                   offset);
11505           offset++;
11506           size--;
11507         }
11508       /* And now fill the rest with zeros. */
11509       if (size)
11510         {
11511           emitcode ("clr", "a");
11512         }
11513       while (size--)
11514         {
11515           aopPut (AOP (result), "a", offset++);
11516         }
11517       _endLazyDPSEvaluation ();
11518     }
11519   else
11520     {
11521       _startLazyDPSEvaluation ();
11522       while (size--)
11523         {
11524           aopPut (AOP (result),
11525                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11526                   offset);
11527           offset++;
11528         }
11529       _endLazyDPSEvaluation ();
11530     }
11531
11532 release:
11533   freeAsmop (right, NULL, ic, FALSE);
11534   freeAsmop (result, NULL, ic, TRUE);
11535 }
11536
11537 /*-----------------------------------------------------------------*/
11538 /* genJumpTab - generates code for jump table                      */
11539 /*-----------------------------------------------------------------*/
11540 static void
11541 genJumpTab (iCode * ic)
11542 {
11543   symbol *jtab;
11544   char *l;
11545
11546   D (emitcode (";", "genJumpTab ");
11547     );
11548
11549   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11550   /* get the condition into accumulator */
11551   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11552   MOVA (l);
11553   /* multiply by four! */
11554   emitcode ("add", "a,acc");
11555   emitcode ("add", "a,acc");
11556   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11557
11558   jtab = newiTempLabel (NULL);
11559   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11560   emitcode ("jmp", "@a+dptr");
11561   emitcode ("", "!tlabeldef", jtab->key + 100);
11562   /* now generate the jump labels */
11563   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11564        jtab = setNextItem (IC_JTLABELS (ic)))
11565     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11566
11567 }
11568
11569 /*-----------------------------------------------------------------*/
11570 /* genCast - gen code for casting                                  */
11571 /*-----------------------------------------------------------------*/
11572 static void
11573 genCast (iCode * ic)
11574 {
11575   operand *result = IC_RESULT (ic);
11576   sym_link *ctype = operandType (IC_LEFT (ic));
11577   sym_link *rtype = operandType (IC_RIGHT (ic));
11578   operand *right = IC_RIGHT (ic);
11579   int size, offset;
11580
11581   D (emitcode (";", "genCast "););
11582
11583   /* if they are equivalent then do nothing */
11584   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11585     return;
11586
11587   aopOp (right, ic, FALSE, AOP_IS_STR (result));
11588   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11589
11590   /* if the result is a bit */
11591   if (IS_BITVAR (OP_SYMBOL (result)->type)
11592       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11593     {
11594       /* if the right size is a literal then
11595          we know what the value is */
11596       if (AOP_TYPE (right) == AOP_LIT)
11597         {
11598           if (((int) operandLitValue (right)))
11599             aopPut (AOP (result), one, 0);
11600           else
11601             aopPut (AOP (result), zero, 0);
11602
11603           goto release;
11604         }
11605
11606       /* the right is also a bit variable */
11607       if (AOP_TYPE (right) == AOP_CRY)
11608         {
11609           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11610           aopPut (AOP (result), "c", 0);
11611           goto release;
11612         }
11613
11614       /* we need to or */
11615       toBoolean (right);
11616       aopPut (AOP (result), "a", 0);
11617       goto release;
11618     }
11619
11620   /* if they are the same size : or less */
11621   if (AOP_SIZE (result) <= AOP_SIZE (right))
11622     {
11623
11624       /* if they are in the same place */
11625       if (sameRegs (AOP (right), AOP (result)))
11626         goto release;
11627
11628       /* if they in different places then copy */
11629       size = AOP_SIZE (result);
11630       offset = 0;
11631       _startLazyDPSEvaluation ();
11632       while (size--)
11633         {
11634           aopPut (AOP (result),
11635                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11636                   offset);
11637           offset++;
11638         }
11639       _endLazyDPSEvaluation ();
11640       goto release;
11641     }
11642
11643
11644   /* if the result is of type pointer */
11645   if (IS_PTR (ctype))
11646     {
11647
11648       int p_type;
11649       sym_link *type = operandType (right);
11650
11651       /* pointer to generic pointer */
11652       if (IS_GENPTR (ctype))
11653         {
11654           if (IS_PTR (type))
11655             {
11656               p_type = DCL_TYPE (type);
11657             }
11658           else
11659             {
11660 #if OLD_CAST_BEHAVIOR
11661               /* KV: we are converting a non-pointer type to
11662                * a generic pointer. This (ifdef'd out) code
11663                * says that the resulting generic pointer
11664                * should have the same class as the storage
11665                * location of the non-pointer variable.
11666                *
11667                * For example, converting an int (which happens
11668                * to be stored in DATA space) to a pointer results
11669                * in a DATA generic pointer; if the original int
11670                * in XDATA space, so will be the resulting pointer.
11671                *
11672                * I don't like that behavior, and thus this change:
11673                * all such conversions will be forced to XDATA and
11674                * throw a warning. If you want some non-XDATA
11675                * type, or you want to suppress the warning, you
11676                * must go through an intermediate cast, like so:
11677                *
11678                * char _generic *gp = (char _xdata *)(intVar);
11679                */
11680               sym_link *etype = getSpec (type);
11681
11682               /* we have to go by the storage class */
11683               if (SPEC_OCLS (etype) != generic)
11684                 {
11685                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11686                 }
11687               else
11688 #endif
11689                 {
11690                   /* Converting unknown class (i.e. register variable)
11691                    * to generic pointer. This is not good, but
11692                    * we'll make a guess (and throw a warning).
11693                    */
11694                   p_type = FPOINTER;
11695                   werror (W_INT_TO_GEN_PTR_CAST);
11696                 }
11697             }
11698
11699           /* the first two bytes are known */
11700           size = GPTRSIZE - 1;
11701           offset = 0;
11702           _startLazyDPSEvaluation ();
11703           while (size--)
11704             {
11705               aopPut (AOP (result),
11706                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11707                       offset);
11708               offset++;
11709             }
11710           _endLazyDPSEvaluation ();
11711
11712           /* the last byte depending on type */
11713             {
11714                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11715                 char gpValStr[10];
11716
11717                 if (gpVal == -1)
11718                 {
11719                     // pointerTypeToGPByte will have bitched.
11720                     exit(1);
11721                 }
11722
11723                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
11724                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11725             }
11726           goto release;
11727         }
11728
11729       /* just copy the pointers */
11730       size = AOP_SIZE (result);
11731       offset = 0;
11732       _startLazyDPSEvaluation ();
11733       while (size--)
11734         {
11735           aopPut (AOP (result),
11736                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11737                   offset);
11738           offset++;
11739         }
11740       _endLazyDPSEvaluation ();
11741       goto release;
11742     }
11743
11744   /* so we now know that the size of destination is greater
11745      than the size of the source */
11746   /* we move to result for the size of source */
11747   size = AOP_SIZE (right);
11748   offset = 0;
11749   _startLazyDPSEvaluation ();
11750   while (size--)
11751     {
11752       aopPut (AOP (result),
11753               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11754               offset);
11755       offset++;
11756     }
11757   _endLazyDPSEvaluation ();
11758
11759   /* now depending on the sign of the source && destination */
11760   size = AOP_SIZE (result) - AOP_SIZE (right);
11761   /* if unsigned or not an integral type */
11762   /* also, if the source is a bit, we don't need to sign extend, because
11763    * it can't possibly have set the sign bit.
11764    */
11765   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11766     {
11767       while (size--)
11768         {
11769           aopPut (AOP (result), zero, offset++);
11770         }
11771     }
11772   else
11773     {
11774       /* we need to extend the sign :{ */
11775       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11776                         FALSE, FALSE, NULL));
11777       emitcode ("rlc", "a");
11778       emitcode ("subb", "a,acc");
11779       while (size--)
11780         aopPut (AOP (result), "a", offset++);
11781     }
11782
11783   /* we are done hurray !!!! */
11784
11785 release:
11786   freeAsmop (right, NULL, ic, TRUE);
11787   freeAsmop (result, NULL, ic, TRUE);
11788
11789 }
11790
11791 /*-----------------------------------------------------------------*/
11792 /* genDjnz - generate decrement & jump if not zero instrucion      */
11793 /*-----------------------------------------------------------------*/
11794 static int
11795 genDjnz (iCode * ic, iCode * ifx)
11796 {
11797   symbol *lbl, *lbl1;
11798   if (!ifx)
11799     return 0;
11800
11801   /* if the if condition has a false label
11802      then we cannot save */
11803   if (IC_FALSE (ifx))
11804     return 0;
11805
11806   /* if the minus is not of the form
11807      a = a - 1 */
11808   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11809       !IS_OP_LITERAL (IC_RIGHT (ic)))
11810     return 0;
11811
11812   if (operandLitValue (IC_RIGHT (ic)) != 1)
11813     return 0;
11814
11815   /* if the size of this greater than one then no
11816      saving */
11817   if (getSize (operandType (IC_RESULT (ic))) > 1)
11818     return 0;
11819
11820   /* otherwise we can save BIG */
11821   D(emitcode(";", "genDjnz"););
11822
11823   lbl = newiTempLabel (NULL);
11824   lbl1 = newiTempLabel (NULL);
11825
11826   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11827
11828   if (AOP_NEEDSACC(IC_RESULT(ic)))
11829   {
11830       /* If the result is accessed indirectly via
11831        * the accumulator, we must explicitly write
11832        * it back after the decrement.
11833        */
11834       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11835
11836       if (strcmp(rByte, "a"))
11837       {
11838            /* Something is hopelessly wrong */
11839            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11840                    __FILE__, __LINE__);
11841            /* We can just give up; the generated code will be inefficient,
11842             * but what the hey.
11843             */
11844            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11845            return 0;
11846       }
11847       emitcode ("dec", "%s", rByte);
11848       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11849       emitcode ("jnz", "!tlabel", lbl->key + 100);
11850   }
11851   else if (IS_AOP_PREG (IC_RESULT (ic)))
11852     {
11853       emitcode ("dec", "%s",
11854                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11855       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11856       emitcode ("jnz", "!tlabel", lbl->key + 100);
11857     }
11858   else
11859     {
11860       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11861                 lbl->key + 100);
11862     }
11863   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11864   emitcode ("", "!tlabeldef", lbl->key + 100);
11865   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11866   emitcode ("", "!tlabeldef", lbl1->key + 100);
11867
11868   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11869   ifx->generated = 1;
11870   return 1;
11871 }
11872
11873 /*-----------------------------------------------------------------*/
11874 /* genReceive - generate code for a receive iCode                  */
11875 /*-----------------------------------------------------------------*/
11876 static void
11877 genReceive (iCode * ic)
11878 {
11879     int size = getSize (operandType (IC_RESULT (ic)));
11880     int offset = 0;
11881     int rb1off ;
11882
11883     D (emitcode (";", "genReceive "););
11884
11885     if (ic->argreg == 1)
11886     {
11887         /* first parameter */
11888         if (AOP_IS_STR(IC_RESULT(ic)))
11889         {
11890             /* Nothing to do: it's already in the proper place. */
11891             return;
11892         }
11893         else
11894         {
11895             bool useDp2;
11896
11897             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11898                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11899                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11900
11901             _G.accInUse++;
11902             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11903             _G.accInUse--;
11904
11905             /* Sanity checking... */
11906             if (AOP_USESDPTR(IC_RESULT(ic)))
11907             {
11908                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11909                         "genReceive got unexpected DPTR.");
11910             }
11911             assignResultValue (IC_RESULT (ic));
11912         }
11913     }
11914     else
11915     {
11916         /* second receive onwards */
11917         /* this gets a little tricky since unused recevies will be
11918          eliminated, we have saved the reg in the type field . and
11919          we use that to figure out which register to use */
11920         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11921         rb1off = ic->argreg;
11922         while (size--)
11923         {
11924             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11925         }
11926     }
11927     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11928 }
11929
11930 /*-----------------------------------------------------------------*/
11931 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11932 /*-----------------------------------------------------------------*/
11933 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11934 {
11935     operand *from , *to , *count;
11936     symbol *lbl;
11937     bitVect *rsave;
11938     int i;
11939
11940     /* we know it has to be 3 parameters */
11941     assert (nparms == 3);
11942
11943     rsave = newBitVect(16);
11944     /* save DPTR if it needs to be saved */
11945     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11946             if (bitVectBitValue(ic->rMask,i))
11947                     rsave = bitVectSetBit(rsave,i);
11948     }
11949     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11950                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11951     savermask(rsave);
11952
11953     to = parms[0];
11954     from = parms[1];
11955     count = parms[2];
11956
11957     aopOp (from, ic->next, FALSE, FALSE);
11958
11959     /* get from into DPTR1 */
11960     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11961     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11962     if (options.model == MODEL_FLAT24) {
11963         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11964     }
11965
11966     freeAsmop (from, NULL, ic, FALSE);
11967     aopOp (to, ic, FALSE, FALSE);
11968     /* get "to" into DPTR */
11969     /* if the operand is already in dptr
11970        then we do nothing else we move the value to dptr */
11971     if (AOP_TYPE (to) != AOP_STR) {
11972         /* if already in DPTR then we need to push */
11973         if (AOP_TYPE(to) == AOP_DPTR) {
11974             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11975             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11976             if (options.model == MODEL_FLAT24)
11977                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11978             emitcode ("pop", "dph");
11979             emitcode ("pop", "dpl");
11980         } else {
11981             _startLazyDPSEvaluation ();
11982             /* if this is remateriazable */
11983             if (AOP_TYPE (to) == AOP_IMMD) {
11984                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11985             } else {                    /* we need to get it byte by byte */
11986                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11987                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11988                 if (options.model == MODEL_FLAT24) {
11989                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11990                 }
11991             }
11992             _endLazyDPSEvaluation ();
11993         }
11994     }
11995     freeAsmop (to, NULL, ic, FALSE);
11996     _G.dptrInUse = _G.dptr1InUse = 1;
11997     aopOp (count, ic->next->next, FALSE,FALSE);
11998     lbl =newiTempLabel(NULL);
11999
12000     /* now for the actual copy */
12001     if (AOP_TYPE(count) == AOP_LIT &&
12002         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12003         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12004         if (fromc) {
12005             emitcode ("lcall","__bi_memcpyc2x_s");
12006         } else {
12007             emitcode ("lcall","__bi_memcpyx2x_s");
12008         }
12009         freeAsmop (count, NULL, ic, FALSE);
12010     } else {
12011         symbol *lbl1 = newiTempLabel(NULL);
12012
12013         emitcode (";"," Auto increment but no djnz");
12014         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12015         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12016         freeAsmop (count, NULL, ic, FALSE);
12017         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12018         emitcode ("","!tlabeldef",lbl->key+100);
12019         if (fromc) {
12020             emitcode ("clr","a");
12021             emitcode ("movc", "a,@a+dptr");
12022         } else
12023             emitcode ("movx", "a,@dptr");
12024         emitcode ("movx", "@dptr,a");
12025         emitcode ("inc", "dptr");
12026         emitcode ("inc", "dptr");
12027         emitcode ("mov","a,b");
12028         emitcode ("orl","a,_ap");
12029         emitcode ("jz","!tlabel",lbl1->key+100);
12030         emitcode ("mov","a,_ap");
12031         emitcode ("add","a,#!constbyte",0xFF);
12032         emitcode ("mov","_ap,a");
12033         emitcode ("mov","a,b");
12034         emitcode ("addc","a,#!constbyte",0xFF);
12035         emitcode ("mov","b,a");
12036         emitcode ("sjmp","!tlabel",lbl->key+100);
12037         emitcode ("","!tlabeldef",lbl1->key+100);
12038     }
12039     emitcode ("mov", "dps,#0");
12040     _G.dptrInUse = _G.dptr1InUse = 0;
12041     unsavermask(rsave);
12042
12043 }
12044
12045 /*-----------------------------------------------------------------*/
12046 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
12047 /*-----------------------------------------------------------------*/
12048 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12049 {
12050     operand *from , *to , *count;
12051     symbol *lbl,*lbl2;
12052     bitVect *rsave;
12053     int i;
12054
12055     /* we know it has to be 3 parameters */
12056     assert (nparms == 3);
12057
12058     rsave = newBitVect(16);
12059     /* save DPTR if it needs to be saved */
12060     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12061             if (bitVectBitValue(ic->rMask,i))
12062                     rsave = bitVectSetBit(rsave,i);
12063     }
12064     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12065                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12066     savermask(rsave);
12067
12068     to = parms[0];
12069     from = parms[1];
12070     count = parms[2];
12071
12072     aopOp (from, ic->next, FALSE, FALSE);
12073
12074     /* get from into DPTR1 */
12075     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12076     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12077     if (options.model == MODEL_FLAT24) {
12078         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12079     }
12080
12081     freeAsmop (from, NULL, ic, FALSE);
12082     aopOp (to, ic, FALSE, FALSE);
12083     /* get "to" into DPTR */
12084     /* if the operand is already in dptr
12085        then we do nothing else we move the value to dptr */
12086     if (AOP_TYPE (to) != AOP_STR) {
12087         /* if already in DPTR then we need to push */
12088         if (AOP_TYPE(to) == AOP_DPTR) {
12089             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12090             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12091             if (options.model == MODEL_FLAT24)
12092                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12093             emitcode ("pop", "dph");
12094             emitcode ("pop", "dpl");
12095         } else {
12096             _startLazyDPSEvaluation ();
12097             /* if this is remateriazable */
12098             if (AOP_TYPE (to) == AOP_IMMD) {
12099                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12100             } else {                    /* we need to get it byte by byte */
12101                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12102                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12103                 if (options.model == MODEL_FLAT24) {
12104                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12105                 }
12106             }
12107             _endLazyDPSEvaluation ();
12108         }
12109     }
12110     freeAsmop (to, NULL, ic, FALSE);
12111     _G.dptrInUse = _G.dptr1InUse = 1;
12112     aopOp (count, ic->next->next, FALSE,FALSE);
12113     lbl =newiTempLabel(NULL);
12114     lbl2 =newiTempLabel(NULL);
12115
12116     /* now for the actual compare */
12117     if (AOP_TYPE(count) == AOP_LIT &&
12118         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12119         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12120         if (fromc)
12121             emitcode("lcall","__bi_memcmpc2x_s");
12122         else
12123             emitcode("lcall","__bi_memcmpx2x_s");
12124         freeAsmop (count, NULL, ic, FALSE);
12125         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12126         aopPut(AOP(IC_RESULT(ic)),"a",0);
12127         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12128     } else {
12129         symbol *lbl1 = newiTempLabel(NULL);
12130
12131         emitcode("push","ar0");
12132         emitcode (";"," Auto increment but no djnz");
12133         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12134         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12135         freeAsmop (count, NULL, ic, FALSE);
12136         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12137         emitcode ("","!tlabeldef",lbl->key+100);
12138         if (fromc) {
12139             emitcode ("clr","a");
12140             emitcode ("movc", "a,@a+dptr");
12141         } else
12142             emitcode ("movx", "a,@dptr");
12143         emitcode ("mov","r0,a");
12144         emitcode ("movx", "a,@dptr");
12145         emitcode ("clr","c");
12146         emitcode ("subb","a,r0");
12147         emitcode ("jnz","!tlabel",lbl2->key+100);
12148         emitcode ("inc", "dptr");
12149         emitcode ("inc", "dptr");
12150         emitcode ("mov","a,b");
12151         emitcode ("orl","a,_ap");
12152         emitcode ("jz","!tlabel",lbl1->key+100);
12153         emitcode ("mov","a,_ap");
12154         emitcode ("add","a,#!constbyte",0xFF);
12155         emitcode ("mov","_ap,a");
12156         emitcode ("mov","a,b");
12157         emitcode ("addc","a,#!constbyte",0xFF);
12158         emitcode ("mov","b,a");
12159         emitcode ("sjmp","!tlabel",lbl->key+100);
12160         emitcode ("","!tlabeldef",lbl1->key+100);
12161         emitcode ("clr","a");
12162         emitcode ("","!tlabeldef",lbl2->key+100);
12163         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12164         aopPut(AOP(IC_RESULT(ic)),"a",0);
12165         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12166         emitcode("pop","ar0");
12167         emitcode ("mov", "dps,#0");
12168     }
12169     _G.dptrInUse = _G.dptr1InUse = 0;
12170     unsavermask(rsave);
12171
12172 }
12173
12174 /*-----------------------------------------------------------------*/
12175 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12176 /* port, first parameter output area second parameter pointer to   */
12177 /* port third parameter count                                      */
12178 /*-----------------------------------------------------------------*/
12179 static void genInp( iCode *ic, int nparms, operand **parms)
12180 {
12181     operand *from , *to , *count;
12182     symbol *lbl;
12183     bitVect *rsave;
12184     int i;
12185
12186     /* we know it has to be 3 parameters */
12187     assert (nparms == 3);
12188
12189     rsave = newBitVect(16);
12190     /* save DPTR if it needs to be saved */
12191     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12192             if (bitVectBitValue(ic->rMask,i))
12193                     rsave = bitVectSetBit(rsave,i);
12194     }
12195     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12196                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12197     savermask(rsave);
12198
12199     to = parms[0];
12200     from = parms[1];
12201     count = parms[2];
12202
12203     aopOp (from, ic->next, FALSE, FALSE);
12204
12205     /* get from into DPTR1 */
12206     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12207     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12208     if (options.model == MODEL_FLAT24) {
12209         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12210     }
12211
12212     freeAsmop (from, NULL, ic, FALSE);
12213     aopOp (to, ic, FALSE, FALSE);
12214     /* get "to" into DPTR */
12215     /* if the operand is already in dptr
12216        then we do nothing else we move the value to dptr */
12217     if (AOP_TYPE (to) != AOP_STR) {
12218         /* if already in DPTR then we need to push */
12219         if (AOP_TYPE(to) == AOP_DPTR) {
12220             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12221             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12222             if (options.model == MODEL_FLAT24)
12223                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12224             emitcode ("pop", "dph");
12225             emitcode ("pop", "dpl");
12226         } else {
12227             _startLazyDPSEvaluation ();
12228             /* if this is remateriazable */
12229             if (AOP_TYPE (to) == AOP_IMMD) {
12230                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12231             } else {                    /* we need to get it byte by byte */
12232                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12233                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12234                 if (options.model == MODEL_FLAT24) {
12235                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12236                 }
12237             }
12238             _endLazyDPSEvaluation ();
12239         }
12240     }
12241     freeAsmop (to, NULL, ic, FALSE);
12242
12243     _G.dptrInUse = _G.dptr1InUse = 1;
12244     aopOp (count, ic->next->next, FALSE,FALSE);
12245     lbl =newiTempLabel(NULL);
12246
12247     /* now for the actual copy */
12248     if (AOP_TYPE(count) == AOP_LIT &&
12249         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12250         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12251         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12252         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12253         freeAsmop (count, NULL, ic, FALSE);
12254         emitcode ("","!tlabeldef",lbl->key+100);
12255         emitcode ("movx", "a,@dptr");   /* read data from port */
12256         emitcode ("dec","dps");         /* switch to DPTR */
12257         emitcode ("movx", "@dptr,a");   /* save into location */
12258         emitcode ("inc", "dptr");       /* point to next area */
12259         emitcode ("inc","dps");         /* switch to DPTR2 */
12260         emitcode ("djnz","b,!tlabel",lbl->key+100);
12261     } else {
12262         symbol *lbl1 = newiTempLabel(NULL);
12263
12264         emitcode (";"," Auto increment but no djnz");
12265         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12266         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12267         freeAsmop (count, NULL, ic, FALSE);
12268         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12269         emitcode ("","!tlabeldef",lbl->key+100);
12270         emitcode ("movx", "a,@dptr");
12271         emitcode ("dec","dps");         /* switch to DPTR */
12272         emitcode ("movx", "@dptr,a");
12273         emitcode ("inc", "dptr");
12274         emitcode ("inc","dps");         /* switch to DPTR2 */
12275 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
12276 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12277         emitcode ("mov","a,b");
12278         emitcode ("orl","a,_ap");
12279         emitcode ("jz","!tlabel",lbl1->key+100);
12280         emitcode ("mov","a,_ap");
12281         emitcode ("add","a,#!constbyte",0xFF);
12282         emitcode ("mov","_ap,a");
12283         emitcode ("mov","a,b");
12284         emitcode ("addc","a,#!constbyte",0xFF);
12285         emitcode ("mov","b,a");
12286         emitcode ("sjmp","!tlabel",lbl->key+100);
12287         emitcode ("","!tlabeldef",lbl1->key+100);
12288     }
12289     emitcode ("mov", "dps,#0");
12290     _G.dptrInUse = _G.dptr1InUse = 0;
12291     unsavermask(rsave);
12292
12293 }
12294
12295 /*-----------------------------------------------------------------*/
12296 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12297 /* port, first parameter output area second parameter pointer to   */
12298 /* port third parameter count                                      */
12299 /*-----------------------------------------------------------------*/
12300 static void genOutp( iCode *ic, int nparms, operand **parms)
12301 {
12302     operand *from , *to , *count;
12303     symbol *lbl;
12304     bitVect *rsave;
12305     int i;
12306
12307     /* we know it has to be 3 parameters */
12308     assert (nparms == 3);
12309
12310     rsave = newBitVect(16);
12311     /* save DPTR if it needs to be saved */
12312     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12313             if (bitVectBitValue(ic->rMask,i))
12314                     rsave = bitVectSetBit(rsave,i);
12315     }
12316     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12317                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12318     savermask(rsave);
12319
12320     to = parms[0];
12321     from = parms[1];
12322     count = parms[2];
12323
12324     aopOp (from, ic->next, FALSE, FALSE);
12325
12326     /* get from into DPTR1 */
12327     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12328     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12329     if (options.model == MODEL_FLAT24) {
12330         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12331     }
12332
12333     freeAsmop (from, NULL, ic, FALSE);
12334     aopOp (to, ic, FALSE, FALSE);
12335     /* get "to" into DPTR */
12336     /* if the operand is already in dptr
12337        then we do nothing else we move the value to dptr */
12338     if (AOP_TYPE (to) != AOP_STR) {
12339         /* if already in DPTR then we need to push */
12340         if (AOP_TYPE(to) == AOP_DPTR) {
12341             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12342             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12343             if (options.model == MODEL_FLAT24)
12344                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12345             emitcode ("pop", "dph");
12346             emitcode ("pop", "dpl");
12347         } else {
12348             _startLazyDPSEvaluation ();
12349             /* if this is remateriazable */
12350             if (AOP_TYPE (to) == AOP_IMMD) {
12351                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12352             } else {                    /* we need to get it byte by byte */
12353                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12354                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12355                 if (options.model == MODEL_FLAT24) {
12356                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12357                 }
12358             }
12359             _endLazyDPSEvaluation ();
12360         }
12361     }
12362     freeAsmop (to, NULL, ic, FALSE);
12363
12364     _G.dptrInUse = _G.dptr1InUse = 1;
12365     aopOp (count, ic->next->next, FALSE,FALSE);
12366     lbl =newiTempLabel(NULL);
12367
12368     /* now for the actual copy */
12369     if (AOP_TYPE(count) == AOP_LIT &&
12370         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12371         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12372         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12373         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12374         emitcode ("","!tlabeldef",lbl->key+100);
12375         emitcode ("movx", "a,@dptr");   /* read data from port */
12376         emitcode ("inc","dps");         /* switch to DPTR2 */
12377         emitcode ("movx", "@dptr,a");   /* save into location */
12378         emitcode ("inc", "dptr");       /* point to next area */
12379         emitcode ("dec","dps");         /* switch to DPTR */
12380         emitcode ("djnz","b,!tlabel",lbl->key+100);
12381         freeAsmop (count, NULL, ic, FALSE);
12382     } else {
12383         symbol *lbl1 = newiTempLabel(NULL);
12384
12385         emitcode (";"," Auto increment but no djnz");
12386         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12387         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12388         freeAsmop (count, NULL, ic, FALSE);
12389         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12390         emitcode ("","!tlabeldef",lbl->key+100);
12391         emitcode ("movx", "a,@dptr");
12392         emitcode ("inc", "dptr");
12393         emitcode ("inc","dps");         /* switch to DPTR2 */
12394         emitcode ("movx", "@dptr,a");
12395         emitcode ("dec","dps");         /* switch to DPTR */
12396         emitcode ("mov","a,b");
12397         emitcode ("orl","a,_ap");
12398         emitcode ("jz","!tlabel",lbl1->key+100);
12399         emitcode ("mov","a,_ap");
12400         emitcode ("add","a,#!constbyte",0xFF);
12401         emitcode ("mov","_ap,a");
12402         emitcode ("mov","a,b");
12403         emitcode ("addc","a,#!constbyte",0xFF);
12404         emitcode ("mov","b,a");
12405         emitcode ("sjmp","!tlabel",lbl->key+100);
12406         emitcode ("","!tlabeldef",lbl1->key+100);
12407     }
12408     emitcode ("mov", "dps,#0");
12409     _G.dptrInUse = _G.dptr1InUse = 0;
12410     unsavermask(rsave);
12411
12412 }
12413
12414 /*-----------------------------------------------------------------*/
12415 /* genSwapW - swap lower & high order bytes                        */
12416 /*-----------------------------------------------------------------*/
12417 static void genSwapW(iCode *ic, int nparms, operand **parms)
12418 {
12419     operand *dest;
12420     operand *src;
12421     assert (nparms==1);
12422
12423     src = parms[0];
12424     dest=IC_RESULT(ic);
12425
12426     assert(getSize(operandType(src))==2);
12427
12428     aopOp (src, ic, FALSE, FALSE);
12429     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12430     _G.accInUse++;
12431     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12432     _G.accInUse--;
12433     freeAsmop (src, NULL, ic, FALSE);
12434
12435     aopOp (dest,ic, FALSE, FALSE);
12436     aopPut(AOP(dest),"b",0);
12437     aopPut(AOP(dest),"a",1);
12438     freeAsmop (dest, NULL, ic, FALSE);
12439 }
12440
12441 /*-----------------------------------------------------------------*/
12442 /* genMemsetX - gencode for memSetX data                           */
12443 /*-----------------------------------------------------------------*/
12444 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12445 {
12446     operand *to , *val , *count;
12447     symbol *lbl;
12448     char *l;
12449     int i;
12450     bitVect *rsave;
12451
12452     /* we know it has to be 3 parameters */
12453     assert (nparms == 3);
12454
12455     to = parms[0];
12456     val = parms[1];
12457     count = parms[2];
12458
12459     /* save DPTR if it needs to be saved */
12460     rsave = newBitVect(16);
12461     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12462             if (bitVectBitValue(ic->rMask,i))
12463                     rsave = bitVectSetBit(rsave,i);
12464     }
12465     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12466                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12467     savermask(rsave);
12468
12469     aopOp (to, ic, FALSE, FALSE);
12470     /* get "to" into DPTR */
12471     /* if the operand is already in dptr
12472        then we do nothing else we move the value to dptr */
12473     if (AOP_TYPE (to) != AOP_STR) {
12474         /* if already in DPTR then we need to push */
12475         if (AOP_TYPE(to) == AOP_DPTR) {
12476             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12477             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12478             if (options.model == MODEL_FLAT24)
12479                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12480             emitcode ("pop", "dph");
12481             emitcode ("pop", "dpl");
12482         } else {
12483             _startLazyDPSEvaluation ();
12484             /* if this is remateriazable */
12485             if (AOP_TYPE (to) == AOP_IMMD) {
12486                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12487             } else {                    /* we need to get it byte by byte */
12488                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12489                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12490                 if (options.model == MODEL_FLAT24) {
12491                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12492                 }
12493             }
12494             _endLazyDPSEvaluation ();
12495         }
12496     }
12497     freeAsmop (to, NULL, ic, FALSE);
12498
12499     aopOp (val, ic->next->next, FALSE,FALSE);
12500     aopOp (count, ic->next->next, FALSE,FALSE);
12501     lbl =newiTempLabel(NULL);
12502     /* now for the actual copy */
12503     if (AOP_TYPE(count) == AOP_LIT &&
12504         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12505         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12506         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12507         MOVA(l);
12508         emitcode ("","!tlabeldef",lbl->key+100);
12509         emitcode ("movx", "@dptr,a");
12510         emitcode ("inc", "dptr");
12511         emitcode ("djnz","b,!tlabel",lbl->key+100);
12512     } else {
12513         symbol *lbl1 = newiTempLabel(NULL);
12514
12515         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12516         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12517         emitcode ("","!tlabeldef",lbl->key+100);
12518         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12519         emitcode ("movx", "@dptr,a");
12520         emitcode ("inc", "dptr");
12521         emitcode ("mov","a,b");
12522         emitcode ("orl","a,_ap");
12523         emitcode ("jz","!tlabel",lbl1->key+100);
12524         emitcode ("mov","a,_ap");
12525         emitcode ("add","a,#!constbyte",0xFF);
12526         emitcode ("mov","_ap,a");
12527         emitcode ("mov","a,b");
12528         emitcode ("addc","a,#!constbyte",0xFF);
12529         emitcode ("mov","b,a");
12530         emitcode ("sjmp","!tlabel",lbl->key+100);
12531         emitcode ("","!tlabeldef",lbl1->key+100);
12532     }
12533     freeAsmop (count, NULL, ic, FALSE);
12534     unsavermask(rsave);
12535 }
12536
12537 /*-----------------------------------------------------------------*/
12538 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12539 /*-----------------------------------------------------------------*/
12540 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12541 {
12542         bitVect *rsave ;
12543         operand *pnum, *result;
12544         int i;
12545
12546         assert (nparms==1);
12547         /* save registers that need to be saved */
12548         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12549                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12550
12551         pnum = parms[0];
12552         aopOp (pnum, ic, FALSE, FALSE);
12553         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12554         freeAsmop (pnum, NULL, ic, FALSE);
12555         emitcode ("lcall","NatLib_LoadPrimitive");
12556         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12557         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12558             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12559                 for (i = (size-1) ; i >= 0 ; i-- ) {
12560                         emitcode ("push","a%s",javaRet[i]);
12561                 }
12562                 for (i=0; i < size ; i++ ) {
12563                         emitcode ("pop","a%s",
12564                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12565                 }
12566         } else {
12567                 for (i = 0 ; i < size ; i++ ) {
12568                         aopPut(AOP(result),javaRet[i],i);
12569                 }
12570         }
12571         freeAsmop (result, NULL, ic, FALSE);
12572         unsavermask(rsave);
12573 }
12574
12575 /*-----------------------------------------------------------------*/
12576 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12577 /*-----------------------------------------------------------------*/
12578 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12579 {
12580         bitVect *rsave ;
12581         operand *pnum, *result;
12582         int size = 3;
12583         int i;
12584
12585         assert (nparms==1);
12586         /* save registers that need to be saved */
12587         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12588                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12589
12590         pnum = parms[0];
12591         aopOp (pnum, ic, FALSE, FALSE);
12592         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12593         freeAsmop (pnum, NULL, ic, FALSE);
12594         emitcode ("lcall","NatLib_LoadPointer");
12595         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12596         if (AOP_TYPE(result)!=AOP_STR) {
12597                 for (i = 0 ; i < size ; i++ ) {
12598                         aopPut(AOP(result),fReturn[i],i);
12599                 }
12600         }
12601         freeAsmop (result, NULL, ic, FALSE);
12602         unsavermask(rsave);
12603 }
12604
12605 /*-----------------------------------------------------------------*/
12606 /* genNatLibInstallStateBlock -                                    */
12607 /*-----------------------------------------------------------------*/
12608 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12609                                        operand **parms, const char *name)
12610 {
12611         bitVect *rsave ;
12612         operand *psb, *handle;
12613         assert (nparms==2);
12614
12615         /* save registers that need to be saved */
12616         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12617                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12618         psb = parms[0];
12619         handle = parms[1];
12620
12621         /* put pointer to state block into DPTR1 */
12622         aopOp (psb, ic, FALSE, FALSE);
12623         if (AOP_TYPE (psb) == AOP_IMMD) {
12624                 emitcode ("mov","dps,#1");
12625                 emitcode ("mov", "dptr,%s",
12626                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12627                 emitcode ("mov","dps,#0");
12628         } else {
12629                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12630                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12631                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12632         }
12633         freeAsmop (psb, NULL, ic, FALSE);
12634
12635         /* put libraryID into DPTR */
12636         emitcode ("mov","dptr,#LibraryID");
12637
12638         /* put handle into r3:r2 */
12639         aopOp (handle, ic, FALSE, FALSE);
12640         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12641                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12642                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12643                 emitcode ("pop","ar3");
12644                 emitcode ("pop","ar2");
12645         } else {
12646                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12647                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12648         }
12649         freeAsmop (psb, NULL, ic, FALSE);
12650
12651         /* make the call */
12652         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12653
12654         /* put return value into place*/
12655         _G.accInUse++;
12656         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12657         _G.accInUse--;
12658         aopPut(AOP(IC_RESULT(ic)),"a",0);
12659         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12660         unsavermask(rsave);
12661 }
12662
12663 /*-----------------------------------------------------------------*/
12664 /* genNatLibRemoveStateBlock -                                     */
12665 /*-----------------------------------------------------------------*/
12666 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12667 {
12668         bitVect *rsave ;
12669
12670         assert(nparms==0);
12671
12672         /* save registers that need to be saved */
12673         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12674                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12675
12676         /* put libraryID into DPTR */
12677         emitcode ("mov","dptr,#LibraryID");
12678         /* make the call */
12679         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12680         unsavermask(rsave);
12681 }
12682
12683 /*-----------------------------------------------------------------*/
12684 /* genNatLibGetStateBlock -                                        */
12685 /*-----------------------------------------------------------------*/
12686 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12687                                    operand **parms,const char *name)
12688 {
12689         bitVect *rsave ;
12690         symbol *lbl = newiTempLabel(NULL);
12691
12692         assert(nparms==0);
12693         /* save registers that need to be saved */
12694         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12695                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12696
12697         /* put libraryID into DPTR */
12698         emitcode ("mov","dptr,#LibraryID");
12699         /* make the call */
12700         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12701         emitcode ("jnz","!tlabel",lbl->key+100);
12702
12703         /* put return value into place */
12704         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12705         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12706                 emitcode ("push","ar3");
12707                 emitcode ("push","ar2");
12708                 emitcode ("pop","%s",
12709                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12710                 emitcode ("pop","%s",
12711                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12712         } else {
12713                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12714                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12715         }
12716         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12717         emitcode ("","!tlabeldef",lbl->key+100);
12718         unsavermask(rsave);
12719 }
12720
12721 /*-----------------------------------------------------------------*/
12722 /* genMMMalloc -                                                   */
12723 /*-----------------------------------------------------------------*/
12724 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12725                          int size, const char *name)
12726 {
12727         bitVect *rsave ;
12728         operand *bsize;
12729         symbol *rsym;
12730         symbol *lbl = newiTempLabel(NULL);
12731
12732         assert (nparms == 1);
12733         /* save registers that need to be saved */
12734         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12735                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12736
12737         bsize=parms[0];
12738         aopOp (bsize,ic,FALSE,FALSE);
12739
12740         /* put the size in R4-R2 */
12741         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12742                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12743                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12744                 if (size==3) {
12745                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12746                         emitcode("pop","ar4");
12747                 }
12748                 emitcode("pop","ar3");
12749                 emitcode("pop","ar2");
12750         } else {
12751                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12752                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12753                 if (size==3) {
12754                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12755                 }
12756         }
12757         freeAsmop (bsize, NULL, ic, FALSE);
12758
12759         /* make the call */
12760         emitcode ("lcall","MM_%s",name);
12761         emitcode ("jz","!tlabel",lbl->key+100);
12762         emitcode ("mov","r2,#!constbyte",0xff);
12763         emitcode ("mov","r3,#!constbyte",0xff);
12764         emitcode ("","!tlabeldef",lbl->key+100);
12765         /* we don't care about the pointer : we just save the handle */
12766         rsym = OP_SYMBOL(IC_RESULT(ic));
12767         if (rsym->liveFrom != rsym->liveTo) {
12768                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12769                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12770                         emitcode ("push","ar3");
12771                         emitcode ("push","ar2");
12772                         emitcode ("pop","%s",
12773                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12774                         emitcode ("pop","%s",
12775                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12776                 } else {
12777                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12778                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12779                 }
12780                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12781         }
12782         unsavermask(rsave);
12783 }
12784
12785 /*-----------------------------------------------------------------*/
12786 /* genMMDeref -                                                    */
12787 /*-----------------------------------------------------------------*/
12788 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12789 {
12790         bitVect *rsave ;
12791         operand *handle;
12792
12793         assert (nparms == 1);
12794         /* save registers that need to be saved */
12795         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12796                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12797
12798         handle=parms[0];
12799         aopOp (handle,ic,FALSE,FALSE);
12800
12801         /* put the size in R4-R2 */
12802         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12803                 emitcode("push","%s",
12804                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12805                 emitcode("push","%s",
12806                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12807                 emitcode("pop","ar3");
12808                 emitcode("pop","ar2");
12809         } else {
12810                 emitcode ("mov","r2,%s",
12811                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12812                 emitcode ("mov","r3,%s",
12813                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12814         }
12815         freeAsmop (handle, NULL, ic, FALSE);
12816
12817         /* make the call */
12818         emitcode ("lcall","MM_Deref");
12819
12820         {
12821                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12822                 if (rsym->liveFrom != rsym->liveTo) {
12823                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12824                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12825                             _startLazyDPSEvaluation ();
12826
12827                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12828                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12829                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12830
12831                             _endLazyDPSEvaluation ();
12832
12833                         }
12834                 }
12835         }
12836         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12837         unsavermask(rsave);
12838 }
12839
12840 /*-----------------------------------------------------------------*/
12841 /* genMMUnrestrictedPersist -                                      */
12842 /*-----------------------------------------------------------------*/
12843 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12844 {
12845         bitVect *rsave ;
12846         operand *handle;
12847
12848         assert (nparms == 1);
12849         /* save registers that need to be saved */
12850         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12851                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12852
12853         handle=parms[0];
12854         aopOp (handle,ic,FALSE,FALSE);
12855
12856         /* put the size in R3-R2 */
12857         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12858                 emitcode("push","%s",
12859                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12860                 emitcode("push","%s",
12861                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12862                 emitcode("pop","ar3");
12863                 emitcode("pop","ar2");
12864         } else {
12865                 emitcode ("mov","r2,%s",
12866                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12867                 emitcode ("mov","r3,%s",
12868                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12869         }
12870         freeAsmop (handle, NULL, ic, FALSE);
12871
12872         /* make the call */
12873         emitcode ("lcall","MM_UnrestrictedPersist");
12874
12875         {
12876                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12877                 if (rsym->liveFrom != rsym->liveTo) {
12878                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12879                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12880                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12881                 }
12882         }
12883         unsavermask(rsave);
12884 }
12885
12886 /*-----------------------------------------------------------------*/
12887 /* genSystemExecJavaProcess -                                      */
12888 /*-----------------------------------------------------------------*/
12889 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12890 {
12891         bitVect *rsave ;
12892         operand *handle, *pp;
12893
12894         assert (nparms==2);
12895         /* save registers that need to be saved */
12896         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12897                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12898
12899         pp = parms[0];
12900         handle = parms[1];
12901
12902         /* put the handle in R3-R2 */
12903         aopOp (handle,ic,FALSE,FALSE);
12904         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12905                 emitcode("push","%s",
12906                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12907                 emitcode("push","%s",
12908                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12909                 emitcode("pop","ar3");
12910                 emitcode("pop","ar2");
12911         } else {
12912                 emitcode ("mov","r2,%s",
12913                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12914                 emitcode ("mov","r3,%s",
12915                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12916         }
12917         freeAsmop (handle, NULL, ic, FALSE);
12918
12919         /* put pointer in DPTR */
12920         aopOp (pp,ic,FALSE,FALSE);
12921         if (AOP_TYPE(pp) == AOP_IMMD) {
12922                 emitcode ("mov", "dptr,%s",
12923                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12924         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12925                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12926                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12927                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12928         }
12929         freeAsmop (handle, NULL, ic, FALSE);
12930
12931         /* make the call */
12932         emitcode ("lcall","System_ExecJavaProcess");
12933
12934         /* put result in place */
12935         {
12936                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12937                 if (rsym->liveFrom != rsym->liveTo) {
12938                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12939                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12940                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12941                 }
12942         }
12943
12944         unsavermask(rsave);
12945 }
12946
12947 /*-----------------------------------------------------------------*/
12948 /* genSystemRTCRegisters -                                         */
12949 /*-----------------------------------------------------------------*/
12950 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12951                                   char *name)
12952 {
12953         bitVect *rsave ;
12954         operand *pp;
12955
12956         assert (nparms==1);
12957         /* save registers that need to be saved */
12958         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12959                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12960
12961         pp=parms[0];
12962         /* put pointer in DPTR */
12963         aopOp (pp,ic,FALSE,FALSE);
12964         if (AOP_TYPE (pp) == AOP_IMMD) {
12965                 emitcode ("mov","dps,#1");
12966                 emitcode ("mov", "dptr,%s",
12967                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12968                 emitcode ("mov","dps,#0");
12969         } else {
12970                 emitcode ("mov","dpl1,%s",
12971                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12972                 emitcode ("mov","dph1,%s",
12973                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12974                 emitcode ("mov","dpx1,%s",
12975                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12976         }
12977         freeAsmop (pp, NULL, ic, FALSE);
12978
12979         /* make the call */
12980         emitcode ("lcall","System_%sRTCRegisters",name);
12981
12982         unsavermask(rsave);
12983 }
12984
12985 /*-----------------------------------------------------------------*/
12986 /* genSystemThreadSleep -                                          */
12987 /*-----------------------------------------------------------------*/
12988 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12989 {
12990         bitVect *rsave ;
12991         operand *to, *s;
12992
12993         assert (nparms==1);
12994         /* save registers that need to be saved */
12995         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12996                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12997
12998         to = parms[0];
12999         aopOp(to,ic,FALSE,FALSE);
13000         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13001             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13002                 emitcode ("push","%s",
13003                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13004                 emitcode ("push","%s",
13005                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13006                 emitcode ("push","%s",
13007                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13008                 emitcode ("push","%s",
13009                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13010                 emitcode ("pop","ar3");
13011                 emitcode ("pop","ar2");
13012                 emitcode ("pop","ar1");
13013                 emitcode ("pop","ar0");
13014         } else {
13015                 emitcode ("mov","r0,%s",
13016                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13017                 emitcode ("mov","r1,%s",
13018                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13019                 emitcode ("mov","r2,%s",
13020                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13021                 emitcode ("mov","r3,%s",
13022                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13023         }
13024         freeAsmop (to, NULL, ic, FALSE);
13025
13026         /* suspend in acc */
13027         s = parms[1];
13028         aopOp(s,ic,FALSE,FALSE);
13029         emitcode ("mov","a,%s",
13030                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
13031         freeAsmop (s, NULL, ic, FALSE);
13032
13033         /* make the call */
13034         emitcode ("lcall","System_%s",name);
13035
13036         unsavermask(rsave);
13037 }
13038
13039 /*-----------------------------------------------------------------*/
13040 /* genSystemThreadResume -                                         */
13041 /*-----------------------------------------------------------------*/
13042 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13043 {
13044         bitVect *rsave ;
13045         operand *tid,*pid;
13046
13047         assert (nparms==2);
13048         /* save registers that need to be saved */
13049         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13050                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13051
13052         tid = parms[0];
13053         pid = parms[1];
13054
13055         /* PID in R0 */
13056         aopOp(pid,ic,FALSE,FALSE);
13057         emitcode ("mov","r0,%s",
13058                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13059         freeAsmop (pid, NULL, ic, FALSE);
13060
13061         /* tid into ACC */
13062         aopOp(tid,ic,FALSE,FALSE);
13063         emitcode ("mov","a,%s",
13064                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13065         freeAsmop (tid, NULL, ic, FALSE);
13066
13067         emitcode ("lcall","System_ThreadResume");
13068
13069         /* put result into place */
13070         {
13071                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13072                 if (rsym->liveFrom != rsym->liveTo) {
13073                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13074                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13075                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13076                 }
13077         }
13078         unsavermask(rsave);
13079 }
13080
13081 /*-----------------------------------------------------------------*/
13082 /* genSystemProcessResume -                                        */
13083 /*-----------------------------------------------------------------*/
13084 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13085 {
13086         bitVect *rsave ;
13087         operand *pid;
13088
13089         assert (nparms==1);
13090         /* save registers that need to be saved */
13091         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13092                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13093
13094         pid = parms[0];
13095
13096         /* pid into ACC */
13097         aopOp(pid,ic,FALSE,FALSE);
13098         emitcode ("mov","a,%s",
13099                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13100         freeAsmop (pid, NULL, ic, FALSE);
13101
13102         emitcode ("lcall","System_ProcessResume");
13103
13104         unsavermask(rsave);
13105 }
13106
13107 /*-----------------------------------------------------------------*/
13108 /* genSystem -                                                     */
13109 /*-----------------------------------------------------------------*/
13110 static void genSystem (iCode *ic,int nparms,char *name)
13111 {
13112         assert(nparms == 0);
13113
13114         emitcode ("lcall","System_%s",name);
13115 }
13116
13117 /*-----------------------------------------------------------------*/
13118 /* genSystemPoll -                                                  */
13119 /*-----------------------------------------------------------------*/
13120 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13121 {
13122         bitVect *rsave ;
13123         operand *fp;
13124
13125         assert (nparms==1);
13126         /* save registers that need to be saved */
13127         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13128                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13129
13130         fp = parms[0];
13131         aopOp (fp,ic,FALSE,FALSE);
13132         if (AOP_TYPE (fp) == AOP_IMMD) {
13133                 emitcode ("mov", "dptr,%s",
13134                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13135         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13136                 emitcode ("mov","dpl,%s",
13137                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13138                 emitcode ("mov","dph,%s",
13139                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13140                 emitcode ("mov","dpx,%s",
13141                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13142         }
13143         freeAsmop (fp, NULL, ic, FALSE);
13144
13145         emitcode ("lcall","System_%sPoll",name);
13146
13147         /* put result into place */
13148         {
13149                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13150                 if (rsym->liveFrom != rsym->liveTo) {
13151                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13152                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13153                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13154                 }
13155         }
13156         unsavermask(rsave);
13157 }
13158
13159 /*-----------------------------------------------------------------*/
13160 /* genSystemGetCurrentID -                                         */
13161 /*-----------------------------------------------------------------*/
13162 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13163 {
13164         assert (nparms==0);
13165
13166         emitcode ("lcall","System_GetCurrent%sId",name);
13167         /* put result into place */
13168         {
13169                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13170                 if (rsym->liveFrom != rsym->liveTo) {
13171                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13172                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13173                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13174                 }
13175         }
13176 }
13177
13178 /*-----------------------------------------------------------------*/
13179 /* genDummyRead - generate code for dummy read of volatiles        */
13180 /*-----------------------------------------------------------------*/
13181 static void
13182 genDummyRead (iCode * ic)
13183 {
13184   operand *op;
13185   int size, offset;
13186
13187   D(emitcode(";     genDummyRead",""));
13188
13189   op = IC_RIGHT (ic);
13190   if (op && IS_SYMOP (op))
13191     {
13192       aopOp (op, ic, FALSE, FALSE);
13193
13194       /* if the result is a bit */
13195       if (AOP_TYPE (op) == AOP_CRY)
13196         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13197       else
13198         {
13199           /* bit variables done */
13200           /* general case */
13201           size = AOP_SIZE (op);
13202           offset = 0;
13203           while (size--)
13204           {
13205             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13206             offset++;
13207           }
13208         }
13209
13210       freeAsmop (op, NULL, ic, TRUE);
13211     }
13212
13213   op = IC_LEFT (ic);
13214   if (op && IS_SYMOP (op))
13215     {
13216       aopOp (op, ic, FALSE, FALSE);
13217
13218       /* if the result is a bit */
13219       if (AOP_TYPE (op) == AOP_CRY)
13220         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13221       else
13222         {
13223           /* bit variables done */
13224           /* general case */
13225           size = AOP_SIZE (op);
13226           offset = 0;
13227           while (size--)
13228           {
13229             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13230             offset++;
13231           }
13232         }
13233
13234       freeAsmop (op, NULL, ic, TRUE);
13235     }
13236
13237 }
13238
13239 /*-----------------------------------------------------------------*/
13240 /* genCritical - generate code for start of a critical sequence    */
13241 /*-----------------------------------------------------------------*/
13242 static void
13243 genCritical (iCode *ic)
13244 {
13245   symbol *tlbl = newiTempLabel (NULL);
13246
13247   D(emitcode(";     genCritical",""));
13248
13249   if (IC_RESULT (ic))
13250     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13251
13252   emitcode ("setb", "c");
13253   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13254   emitcode ("clr", "c");
13255   emitcode ("", "%05d$:", (tlbl->key + 100));
13256
13257   if (IC_RESULT (ic))
13258     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13259   else
13260     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13261
13262   if (IC_RESULT (ic))
13263     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13264 }
13265
13266 /*-----------------------------------------------------------------*/
13267 /* genEndCritical - generate code for end of a critical sequence   */
13268 /*-----------------------------------------------------------------*/
13269 static void
13270 genEndCritical (iCode *ic)
13271 {
13272   D(emitcode(";     genEndCritical",""));
13273
13274   if (IC_RIGHT (ic))
13275     {
13276       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13277       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13278         {
13279           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13280           emitcode ("mov", "ea,c");
13281         }
13282       else
13283         {
13284           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13285           emitcode ("rrc", "a");
13286           emitcode ("mov", "ea,c");
13287         }
13288       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13289     }
13290   else
13291     {
13292       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13293       emitcode ("mov", "ea,c");
13294     }
13295 }
13296
13297
13298
13299 /*-----------------------------------------------------------------*/
13300 /* genBuiltIn - calls the appropriate function to  generating code */
13301 /* for a built in function                                         */
13302 /*-----------------------------------------------------------------*/
13303 static void genBuiltIn (iCode *ic)
13304 {
13305         operand *bi_parms[MAX_BUILTIN_ARGS];
13306         int nbi_parms;
13307         iCode *bi_iCode;
13308         symbol *bif;
13309
13310         /* get all the arguments for a built in function */
13311         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13312
13313         /* which function is it */
13314         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13315         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13316                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13317         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13318                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13319         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13320                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13321         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13322                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13323         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13324                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13325         } else if (strcmp(bif->name,"__builtin_inp")==0) {
13326                 genInp(bi_iCode,nbi_parms,bi_parms);
13327         } else if (strcmp(bif->name,"__builtin_outp")==0) {
13328                 genOutp(bi_iCode,nbi_parms,bi_parms);
13329         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13330                 genSwapW(bi_iCode,nbi_parms,bi_parms);
13331                 /* JavaNative builtIns */
13332         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13333                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13334         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13335                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13336         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13337                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13338         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13339                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13340         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13341                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13342         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13343                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13344         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13345                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13346         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13347                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13348         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13349                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13350         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13351                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13352         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13353                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13354         } else if (strcmp(bif->name,"MM_Malloc")==0) {
13355                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13356         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13357                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13358         } else if (strcmp(bif->name,"MM_Free")==0) {
13359                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13360         } else if (strcmp(bif->name,"MM_Deref")==0) {
13361                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13362         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13363                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13364         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13365                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13366         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13367                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13368         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13369                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13370         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13371                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13372         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13373                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13374         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13375                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13376         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13377                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13378         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13379                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13380         } else if (strcmp(bif->name,"System_SaveThread")==0) {
13381                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13382         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13383                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13384         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13385                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13386         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13387                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13388         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13389                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13390         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13391                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13392         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13393                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13394         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13395                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13396         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13397                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13398         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13399                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13400         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13401                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13402         } else {
13403                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13404                 return ;
13405         }
13406         return ;
13407 }
13408
13409 /*-----------------------------------------------------------------*/
13410 /* gen390Code - generate code for Dallas 390 based controllers     */
13411 /*-----------------------------------------------------------------*/
13412 void
13413 gen390Code (iCode * lic)
13414 {
13415   iCode *ic;
13416   int cln = 0;
13417
13418   lineHead = lineCurr = NULL;
13419   dptrn[1][0] = "dpl1";
13420   dptrn[1][1] = "dph1";
13421   dptrn[1][2] = "dpx1";
13422
13423   if (options.model == MODEL_FLAT24) {
13424     fReturnSizeDS390 = 5;
13425     fReturn = fReturn24;
13426   } else {
13427     fReturnSizeDS390 = 4;
13428     fReturn = fReturn16;
13429     options.stack10bit=0;
13430   }
13431 #if 1
13432   /* print the allocation information */
13433   if (allocInfo && currFunc)
13434     printAllocInfo (currFunc, codeOutFile);
13435 #endif
13436   /* if debug information required */
13437   if (options.debug && currFunc)
13438     {
13439       debugFile->writeFunction (currFunc, lic);
13440     }
13441   /* stack pointer name */
13442   if (options.useXstack)
13443     spname = "_spx";
13444   else
13445     spname = "sp";
13446
13447
13448   for (ic = lic; ic; ic = ic->next)
13449     {
13450       _G.current_iCode = ic;
13451
13452       if (ic->lineno && cln != ic->lineno)
13453         {
13454           if (options.debug)
13455             {
13456               debugFile->writeCLine (ic);
13457             }
13458           if (!options.noCcodeInAsm) {
13459             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13460                       printCLine(ic->filename, ic->lineno));
13461           }
13462           cln = ic->lineno;
13463         }
13464       if (options.iCodeInAsm) {
13465         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13466       }
13467       /* if the result is marked as
13468          spilt and rematerializable or code for
13469          this has already been generated then
13470          do nothing */
13471       if (resultRemat (ic) || ic->generated)
13472         continue;
13473
13474       /* depending on the operation */
13475       switch (ic->op)
13476         {
13477         case '!':
13478           genNot (ic);
13479           break;
13480
13481         case '~':
13482           genCpl (ic);
13483           break;
13484
13485         case UNARYMINUS:
13486           genUminus (ic);
13487           break;
13488
13489         case IPUSH:
13490           genIpush (ic);
13491           break;
13492
13493         case IPOP:
13494           /* IPOP happens only when trying to restore a
13495              spilt live range, if there is an ifx statement
13496              following this pop then the if statement might
13497              be using some of the registers being popped which
13498              would destory the contents of the register so
13499              we need to check for this condition and handle it */
13500           if (ic->next &&
13501               ic->next->op == IFX &&
13502               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13503             genIfx (ic->next, ic);
13504           else
13505             genIpop (ic);
13506           break;
13507
13508         case CALL:
13509           genCall (ic);
13510           break;
13511
13512         case PCALL:
13513           genPcall (ic);
13514           break;
13515
13516         case FUNCTION:
13517           genFunction (ic);
13518           break;
13519
13520         case ENDFUNCTION:
13521           genEndFunction (ic);
13522           break;
13523
13524         case RETURN:
13525           genRet (ic);
13526           break;
13527
13528         case LABEL:
13529           genLabel (ic);
13530           break;
13531
13532         case GOTO:
13533           genGoto (ic);
13534           break;
13535
13536         case '+':
13537           genPlus (ic);
13538           break;
13539
13540         case '-':
13541           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13542             genMinus (ic);
13543           break;
13544
13545         case '*':
13546           genMult (ic);
13547           break;
13548
13549         case '/':
13550           genDiv (ic);
13551           break;
13552
13553         case '%':
13554           genMod (ic);
13555           break;
13556
13557         case '>':
13558           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13559           break;
13560
13561         case '<':
13562           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13563           break;
13564
13565         case LE_OP:
13566         case GE_OP:
13567         case NE_OP:
13568
13569           /* note these two are xlated by algebraic equivalence
13570              during parsing SDCC.y */
13571           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13572                   "got '>=' or '<=' shouldn't have come here");
13573           break;
13574
13575         case EQ_OP:
13576           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13577           break;
13578
13579         case AND_OP:
13580           genAndOp (ic);
13581           break;
13582
13583         case OR_OP:
13584           genOrOp (ic);
13585           break;
13586
13587         case '^':
13588           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13589           break;
13590
13591         case '|':
13592           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13593           break;
13594
13595         case BITWISEAND:
13596           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13597           break;
13598
13599         case INLINEASM:
13600           genInline (ic);
13601           break;
13602
13603         case RRC:
13604           genRRC (ic);
13605           break;
13606
13607         case RLC:
13608           genRLC (ic);
13609           break;
13610
13611         case GETHBIT:
13612           genGetHbit (ic);
13613           break;
13614
13615         case LEFT_OP:
13616           genLeftShift (ic);
13617           break;
13618
13619         case RIGHT_OP:
13620           genRightShift (ic);
13621           break;
13622
13623         case GET_VALUE_AT_ADDRESS:
13624           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13625           break;
13626
13627         case '=':
13628           if (POINTER_SET (ic))
13629             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13630           else
13631             genAssign (ic);
13632           break;
13633
13634         case IFX:
13635           genIfx (ic, NULL);
13636           break;
13637
13638         case ADDRESS_OF:
13639           genAddrOf (ic);
13640           break;
13641
13642         case JUMPTABLE:
13643           genJumpTab (ic);
13644           break;
13645
13646         case CAST:
13647           genCast (ic);
13648           break;
13649
13650         case RECEIVE:
13651           genReceive (ic);
13652           break;
13653
13654         case SEND:
13655           if (ic->builtinSEND) genBuiltIn(ic);
13656           else addSet (&_G.sendSet, ic);
13657           break;
13658
13659         case DUMMY_READ_VOLATILE:
13660           genDummyRead (ic);
13661           break;
13662
13663         case CRITICAL:
13664           genCritical (ic);
13665           break;
13666
13667         case ENDCRITICAL:
13668           genEndCritical (ic);
13669           break;
13670
13671         case SWAP:
13672           genSwap (ic);
13673           break;
13674
13675 #if 0 // obsolete, and buggy for != xdata
13676         case ARRAYINIT:
13677             genArrayInit(ic);
13678             break;
13679 #endif
13680
13681         default:
13682           ic = ic;
13683         }
13684     }
13685
13686
13687   /* now we are ready to call the
13688      peep hole optimizer */
13689   if (!options.nopeep)
13690     peepHole (&lineHead);
13691
13692   /* now do the actual printing */
13693   printLine (lineHead, codeOutFile);
13694   return;
13695 }