* src/SDCCcse.c (ReplaceOpWithCheaperOp): minor fix for debugging only
[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       AccRol (8 - bstr);
9662       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9663       if (!SPEC_USIGN (etype))
9664         {
9665           /* signed bitfield */
9666           symbol *tlbl = newiTempLabel (NULL);
9667
9668           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9669           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9670           emitcode ("", "%05d$:", tlbl->key + 100);
9671         }
9672       aopPut (AOP (result), "a", offset++);
9673       goto finish;
9674     }
9675
9676   /* Bit field did not fit in a byte. Copy all
9677      but the partial byte at the end.  */
9678   for (rlen=blen;rlen>=8;rlen-=8)
9679     {
9680       emitPtrByteGet (rname, ptype, FALSE);
9681       aopPut (AOP (result), "a", offset++);
9682       if (rlen>8)
9683         emitcode ("inc", "%s", rname);
9684     }
9685
9686   /* Handle the partial byte at the end */
9687   if (rlen)
9688     {
9689       emitPtrByteGet (rname, ptype, FALSE);
9690       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9691       if (!SPEC_USIGN (etype))
9692         {
9693           /* signed bitfield */
9694           symbol *tlbl = newiTempLabel (NULL);
9695
9696           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9697           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9698           emitcode ("", "%05d$:", tlbl->key + 100);
9699         }
9700       aopPut (AOP (result), "a", offset++);
9701     }
9702
9703 finish:
9704   if (offset < rsize)
9705     {
9706       char *source;
9707
9708       if (SPEC_USIGN (etype))
9709         source = zero;
9710       else
9711         {
9712           /* signed bitfield: sign extension with 0x00 or 0xff */
9713           emitcode ("rlc", "a");
9714           emitcode ("subb", "a,acc");
9715
9716           source = "a";
9717         }
9718       rsize -= offset;
9719       while (rsize--)
9720         aopPut (AOP (result), source, offset++);
9721     }
9722 }
9723
9724
9725 /*-----------------------------------------------------------------*/
9726 /* genDataPointerGet - generates code when ptr offset is known     */
9727 /*-----------------------------------------------------------------*/
9728 static void
9729 genDataPointerGet (operand * left,
9730                    operand * result,
9731                    iCode * ic)
9732 {
9733   char *l;
9734   char buff[256];
9735   int size, offset = 0;
9736   aopOp (result, ic, TRUE, FALSE);
9737
9738   /* get the string representation of the name */
9739   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9740   size = AOP_SIZE (result);
9741   _startLazyDPSEvaluation ();
9742   while (size--)
9743     {
9744         if (offset)
9745         {
9746             SNPRINTF (buff, sizeof(buff),
9747                       "(%s + %d)", l + 1, offset);
9748         }
9749         else
9750         {
9751             SNPRINTF (buff, sizeof(buff),
9752                       "%s", l + 1);
9753         }
9754       aopPut (AOP (result), buff, offset++);
9755     }
9756   _endLazyDPSEvaluation ();
9757
9758   freeAsmop (left, NULL, ic, TRUE);
9759   freeAsmop (result, NULL, ic, TRUE);
9760 }
9761
9762 /*-----------------------------------------------------------------*/
9763 /* genNearPointerGet - emitcode for near pointer fetch             */
9764 /*-----------------------------------------------------------------*/
9765 static void
9766 genNearPointerGet (operand * left,
9767                    operand * result,
9768                    iCode * ic,
9769                    iCode *pi)
9770 {
9771   asmop *aop = NULL;
9772   regs *preg;
9773   char *rname;
9774   sym_link *rtype, *retype, *letype;
9775   sym_link *ltype = operandType (left);
9776   char buff[80];
9777
9778   rtype = operandType (result);
9779   retype = getSpec (rtype);
9780   letype = getSpec (ltype);
9781
9782   aopOp (left, ic, FALSE, FALSE);
9783
9784   /* if left is rematerialisable and
9785      result is not bitfield variable type and
9786      the left is pointer to data space i.e
9787      lower 128 bytes of space */
9788   if (AOP_TYPE (left) == AOP_IMMD &&
9789       !IS_BITFIELD (retype) &&
9790       !IS_BITFIELD (letype) &&
9791       DCL_TYPE (ltype) == POINTER)
9792     {
9793       genDataPointerGet (left, result, ic);
9794       return;
9795     }
9796
9797   /* if the value is already in a pointer register
9798      then don't need anything more */
9799   if (!AOP_INPREG (AOP (left)))
9800     {
9801       /* otherwise get a free pointer register */
9802       aop = newAsmop (0);
9803       preg = getFreePtr (ic, &aop, FALSE);
9804       emitcode ("mov", "%s,%s",
9805                 preg->name,
9806                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9807       rname = preg->name;
9808     }
9809   else
9810     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9811
9812   freeAsmop (left, NULL, ic, TRUE);
9813   aopOp (result, ic, FALSE, FALSE);
9814
9815   /* if bitfield then unpack the bits */
9816   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9817     genUnpackBits (result, rname, POINTER);
9818   else
9819     {
9820       /* we have can just get the values */
9821       int size = AOP_SIZE (result);
9822       int offset = 0;
9823
9824       while (size--)
9825         {
9826           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9827             {
9828
9829               emitcode ("mov", "a,@%s", rname);
9830               aopPut (AOP (result), "a", offset);
9831             }
9832           else
9833             {
9834               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9835               aopPut (AOP (result), buff, offset);
9836             }
9837           offset++;
9838           if (size || pi)
9839             {
9840                 emitcode ("inc", "%s", rname);
9841             }
9842         }
9843     }
9844
9845   /* now some housekeeping stuff */
9846   if (aop)
9847     {
9848       /* we had to allocate for this iCode */
9849       if (pi) { /* post increment present */
9850         aopPut(AOP ( left ),rname,0);
9851       }
9852       freeAsmop (NULL, aop, ic, TRUE);
9853     }
9854   else
9855     {
9856       /* we did not allocate which means left
9857          already in a pointer register, then
9858          if size > 0 && this could be used again
9859          we have to point it back to where it
9860          belongs */
9861       if (AOP_SIZE (result) > 1 &&
9862           !OP_SYMBOL (left)->remat &&
9863           (OP_SYMBOL (left)->liveTo > ic->seq ||
9864            ic->depth) &&
9865           !pi)
9866         {
9867           int size = AOP_SIZE (result) - 1;
9868           while (size--)
9869             emitcode ("dec", "%s", rname);
9870         }
9871     }
9872
9873   /* done */
9874   freeAsmop (result, NULL, ic, TRUE);
9875   if (pi) pi->generated = 1;
9876 }
9877
9878 /*-----------------------------------------------------------------*/
9879 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9880 /*-----------------------------------------------------------------*/
9881 static void
9882 genPagedPointerGet (operand * left,
9883                     operand * result,
9884                     iCode * ic,
9885                     iCode * pi)
9886 {
9887   asmop *aop = NULL;
9888   regs *preg;
9889   char *rname;
9890   sym_link *rtype, *retype, *letype;
9891
9892   rtype = operandType (result);
9893   retype = getSpec (rtype);
9894   letype = getSpec (operandType (left));
9895   aopOp (left, ic, FALSE, FALSE);
9896
9897   /* if the value is already in a pointer register
9898      then don't need anything more */
9899   if (!AOP_INPREG (AOP (left)))
9900     {
9901       /* otherwise get a free pointer register */
9902       aop = newAsmop (0);
9903       preg = getFreePtr (ic, &aop, FALSE);
9904       emitcode ("mov", "%s,%s",
9905                 preg->name,
9906                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9907       rname = preg->name;
9908     }
9909   else
9910     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9911
9912   freeAsmop (left, NULL, ic, TRUE);
9913   aopOp (result, ic, FALSE, FALSE);
9914
9915   /* if bitfield then unpack the bits */
9916   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9917     genUnpackBits (result, rname, PPOINTER);
9918   else
9919     {
9920       /* we have can just get the values */
9921       int size = AOP_SIZE (result);
9922       int offset = 0;
9923
9924       while (size--)
9925         {
9926
9927           emitcode ("movx", "a,@%s", rname);
9928           aopPut (AOP (result), "a", offset);
9929
9930           offset++;
9931
9932           if (size || pi)
9933             emitcode ("inc", "%s", rname);
9934         }
9935     }
9936
9937   /* now some housekeeping stuff */
9938   if (aop)
9939     {
9940       /* we had to allocate for this iCode */
9941       if (pi) aopPut ( AOP (left), rname, 0);
9942       freeAsmop (NULL, aop, ic, TRUE);
9943     }
9944   else
9945     {
9946       /* we did not allocate which means left
9947          already in a pointer register, then
9948          if size > 0 && this could be used again
9949          we have to point it back to where it
9950          belongs */
9951       if (AOP_SIZE (result) > 1 &&
9952           !OP_SYMBOL (left)->remat &&
9953           (OP_SYMBOL (left)->liveTo > ic->seq ||
9954            ic->depth) &&
9955           !pi)
9956         {
9957           int size = AOP_SIZE (result) - 1;
9958           while (size--)
9959             emitcode ("dec", "%s", rname);
9960         }
9961     }
9962
9963   /* done */
9964   freeAsmop (result, NULL, ic, TRUE);
9965   if (pi) pi->generated = 1;
9966 }
9967
9968 /*-----------------------------------------------------------------*/
9969 /* genFarPointerGet - gget value from far space                    */
9970 /*-----------------------------------------------------------------*/
9971 static void
9972 genFarPointerGet (operand * left,
9973                   operand * result, iCode * ic, iCode *pi)
9974 {
9975     int size, offset, dopi=1;
9976   sym_link *retype = getSpec (operandType (result));
9977   sym_link *letype = getSpec (operandType (left));
9978   D (emitcode (";", "genFarPointerGet"););
9979
9980   aopOp (left, ic, FALSE, FALSE);
9981
9982   /* if the operand is already in dptr
9983      then we do nothing else we move the value to dptr */
9984   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9985     {
9986       /* if this is remateriazable */
9987       if (AOP_TYPE (left) == AOP_IMMD)
9988         {
9989           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9990         }
9991       else
9992         {
9993           /* we need to get it byte by byte */
9994           _startLazyDPSEvaluation ();
9995           if (AOP_TYPE (left) != AOP_DPTR)
9996             {
9997               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9998               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9999               if (options.model == MODEL_FLAT24)
10000                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10001             }
10002           else
10003             {
10004               /* We need to generate a load to DPTR indirect through DPTR. */
10005               D (emitcode (";", "genFarPointerGet -- indirection special case."););
10006               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10007               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10008               if (options.model == MODEL_FLAT24)
10009                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10010               emitcode ("pop", "dph");
10011               emitcode ("pop", "dpl");
10012               dopi =0;
10013             }
10014           _endLazyDPSEvaluation ();
10015         }
10016     }
10017   /* so dptr know contains the address */
10018   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10019
10020   /* if bit then unpack */
10021   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10022       if (AOP_INDPTRn(left)) {
10023           genSetDPTR(AOP(left)->aopu.dptr);
10024       }
10025       genUnpackBits (result, "dptr", FPOINTER);
10026       if (AOP_INDPTRn(left)) {
10027           genSetDPTR(0);
10028       }
10029   } else
10030     {
10031       size = AOP_SIZE (result);
10032       offset = 0;
10033
10034       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10035           while (size--) {
10036               genSetDPTR(AOP(left)->aopu.dptr);
10037               emitcode ("movx", "a,@dptr");
10038               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10039                   emitcode ("inc", "dptr");
10040               genSetDPTR (0);
10041               aopPut (AOP (result), "a", offset++);
10042           }
10043       } else {
10044           _startLazyDPSEvaluation ();
10045           while (size--) {
10046               if (AOP_INDPTRn(left)) {
10047                   genSetDPTR(AOP(left)->aopu.dptr);
10048               } else {
10049                   genSetDPTR (0);
10050               }
10051               _flushLazyDPS ();
10052
10053               emitcode ("movx", "a,@dptr");
10054               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10055                   emitcode ("inc", "dptr");
10056
10057               aopPut (AOP (result), "a", offset++);
10058           }
10059           _endLazyDPSEvaluation ();
10060       }
10061     }
10062   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10063       if (!AOP_INDPTRn(left)) {
10064           _startLazyDPSEvaluation ();
10065           aopPut ( AOP (left), "dpl", 0);
10066           aopPut ( AOP (left), "dph", 1);
10067           if (options.model == MODEL_FLAT24)
10068               aopPut ( AOP (left), "dpx", 2);
10069           _endLazyDPSEvaluation ();
10070       }
10071     pi->generated = 1;
10072   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10073              AOP_SIZE(result) > 1 &&
10074              IS_SYMOP(left) &&
10075              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10076
10077       size = AOP_SIZE (result) - 1;
10078       if (AOP_INDPTRn(left)) {
10079           genSetDPTR(AOP(left)->aopu.dptr);
10080       }
10081       while (size--) emitcode ("lcall","__decdptr");
10082       if (AOP_INDPTRn(left)) {
10083           genSetDPTR(0);
10084       }
10085   }
10086
10087   freeAsmop (left, NULL, ic, TRUE);
10088   freeAsmop (result, NULL, ic, TRUE);
10089 }
10090
10091 /*-----------------------------------------------------------------*/
10092 /* genCodePointerGet - get value from code space                  */
10093 /*-----------------------------------------------------------------*/
10094 static void
10095 genCodePointerGet (operand * left,
10096                     operand * result, iCode * ic, iCode *pi)
10097 {
10098   int size, offset, dopi=1;
10099   sym_link *retype = getSpec (operandType (result));
10100
10101   aopOp (left, ic, FALSE, FALSE);
10102
10103   /* if the operand is already in dptr
10104      then we do nothing else we move the value to dptr */
10105   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10106     {
10107       /* if this is remateriazable */
10108       if (AOP_TYPE (left) == AOP_IMMD)
10109         {
10110           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10111         }
10112       else
10113         {                       /* we need to get it byte by byte */
10114           _startLazyDPSEvaluation ();
10115           if (AOP_TYPE (left) != AOP_DPTR)
10116             {
10117               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10118               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10119               if (options.model == MODEL_FLAT24)
10120                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10121             }
10122           else
10123             {
10124               /* We need to generate a load to DPTR indirect through DPTR. */
10125               D (emitcode (";", "gencodePointerGet -- indirection special case."););
10126               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10127               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10128               if (options.model == MODEL_FLAT24)
10129                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10130               emitcode ("pop", "dph");
10131               emitcode ("pop", "dpl");
10132               dopi=0;
10133             }
10134           _endLazyDPSEvaluation ();
10135         }
10136     }
10137   /* so dptr know contains the address */
10138   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10139
10140   /* if bit then unpack */
10141   if (IS_BITFIELD (retype)) {
10142       if (AOP_INDPTRn(left)) {
10143           genSetDPTR(AOP(left)->aopu.dptr);
10144       }
10145       genUnpackBits (result, "dptr", CPOINTER);
10146       if (AOP_INDPTRn(left)) {
10147           genSetDPTR(0);
10148       }
10149   } else
10150     {
10151       size = AOP_SIZE (result);
10152       offset = 0;
10153       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10154           while (size--) {
10155               genSetDPTR(AOP(left)->aopu.dptr);
10156               emitcode ("clr", "a");
10157               emitcode ("movc", "a,@a+dptr");
10158               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10159                   emitcode ("inc", "dptr");
10160               genSetDPTR (0);
10161               aopPut (AOP (result), "a", offset++);
10162           }
10163       } else {
10164           _startLazyDPSEvaluation ();
10165           while (size--)
10166               {
10167                   if (AOP_INDPTRn(left)) {
10168                       genSetDPTR(AOP(left)->aopu.dptr);
10169                   } else {
10170                       genSetDPTR (0);
10171                   }
10172                   _flushLazyDPS ();
10173
10174                   emitcode ("clr", "a");
10175                   emitcode ("movc", "a,@a+dptr");
10176                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10177                       emitcode ("inc", "dptr");
10178                   aopPut (AOP (result), "a", offset++);
10179               }
10180           _endLazyDPSEvaluation ();
10181       }
10182     }
10183   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10184       if (!AOP_INDPTRn(left)) {
10185           _startLazyDPSEvaluation ();
10186
10187           aopPut ( AOP (left), "dpl", 0);
10188           aopPut ( AOP (left), "dph", 1);
10189           if (options.model == MODEL_FLAT24)
10190               aopPut ( AOP (left), "dpx", 2);
10191
10192           _endLazyDPSEvaluation ();
10193       }
10194       pi->generated = 1;
10195   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10196              AOP_SIZE(result) > 1 &&
10197              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10198
10199       size = AOP_SIZE (result) - 1;
10200       if (AOP_INDPTRn(left)) {
10201           genSetDPTR(AOP(left)->aopu.dptr);
10202       }
10203       while (size--) emitcode ("lcall","__decdptr");
10204       if (AOP_INDPTRn(left)) {
10205           genSetDPTR(0);
10206       }
10207   }
10208
10209   freeAsmop (left, NULL, ic, TRUE);
10210   freeAsmop (result, NULL, ic, TRUE);
10211 }
10212
10213 /*-----------------------------------------------------------------*/
10214 /* genGenPointerGet - gget value from generic pointer space        */
10215 /*-----------------------------------------------------------------*/
10216 static void
10217 genGenPointerGet (operand * left,
10218                   operand * result, iCode * ic, iCode * pi)
10219 {
10220   int size, offset;
10221   sym_link *retype = getSpec (operandType (result));
10222   sym_link *letype = getSpec (operandType (left));
10223
10224   D (emitcode (";", "genGenPointerGet "); );
10225
10226   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10227
10228   /* if the operand is already in dptr
10229      then we do nothing else we move the value to dptr */
10230   if (AOP_TYPE (left) != AOP_STR)
10231     {
10232       /* if this is rematerializable */
10233       if (AOP_TYPE (left) == AOP_IMMD)
10234         {
10235           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10236           if (AOP(left)->aopu.aop_immd.from_cast_remat)
10237             {
10238               MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10239             }
10240           else
10241             {
10242               emitcode ("mov", "b,#%d", pointerCode (retype));
10243             }
10244         }
10245       else
10246         {                       /* we need to get it byte by byte */
10247           _startLazyDPSEvaluation ();
10248           emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10249           emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10250           if (options.model == MODEL_FLAT24) {
10251               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10252               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10253           } else {
10254               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10255           }
10256           _endLazyDPSEvaluation ();
10257         }
10258     }
10259
10260   /* so dptr-b now contains the address */
10261   _G.bInUse++;
10262   aopOp (result, ic, FALSE, TRUE);
10263   _G.bInUse--;
10264
10265   /* if bit then unpack */
10266   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10267   {
10268     genUnpackBits (result, "dptr", GPOINTER);
10269   }
10270   else
10271     {
10272         size = AOP_SIZE (result);
10273         offset = 0;
10274
10275         while (size--)
10276         {
10277             if (size)
10278             {
10279                 // Get two bytes at a time, results in _AP & A.
10280                 // dptr will be incremented ONCE by __gptrgetWord.
10281                 //
10282                 // Note: any change here must be coordinated
10283                 // with the implementation of __gptrgetWord
10284                 // in device/lib/_gptrget.c
10285                 emitcode ("lcall", "__gptrgetWord");
10286                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10287                 aopPut (AOP (result), "a", offset++);
10288                 size--;
10289             }
10290             else
10291             {
10292                 // Only one byte to get.
10293                 emitcode ("lcall", "__gptrget");
10294                 aopPut (AOP (result), "a", offset++);
10295             }
10296
10297             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10298             {
10299                 emitcode ("inc", "dptr");
10300             }
10301         }
10302     }
10303
10304   if (pi && AOP_TYPE (left) != AOP_IMMD) {
10305     _startLazyDPSEvaluation ();
10306
10307     aopPut ( AOP (left), "dpl", 0);
10308     aopPut ( AOP (left), "dph", 1);
10309     if (options.model == MODEL_FLAT24) {
10310         aopPut ( AOP (left), "dpx", 2);
10311         aopPut ( AOP (left), "b", 3);
10312     } else  aopPut ( AOP (left), "b", 2);
10313
10314     _endLazyDPSEvaluation ();
10315
10316     pi->generated = 1;
10317   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10318              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10319
10320       size = AOP_SIZE (result) - 1;
10321       while (size--) emitcode ("lcall","__decdptr");
10322   }
10323
10324   freeAsmop (left, NULL, ic, TRUE);
10325   freeAsmop (result, NULL, ic, TRUE);
10326 }
10327
10328 /*-----------------------------------------------------------------*/
10329 /* genPointerGet - generate code for pointer get                   */
10330 /*-----------------------------------------------------------------*/
10331 static void
10332 genPointerGet (iCode * ic, iCode *pi)
10333 {
10334   operand *left, *result;
10335   sym_link *type, *etype;
10336   int p_type;
10337
10338   D (emitcode (";", "genPointerGet ");
10339     );
10340
10341   left = IC_LEFT (ic);
10342   result = IC_RESULT (ic);
10343
10344   /* depending on the type of pointer we need to
10345      move it to the correct pointer register */
10346   type = operandType (left);
10347   etype = getSpec (type);
10348   /* if left is of type of pointer then it is simple */
10349   if (IS_PTR (type) && !IS_FUNC (type->next))
10350     p_type = DCL_TYPE (type);
10351   else
10352     {
10353       /* we have to go by the storage class */
10354       p_type = PTR_TYPE (SPEC_OCLS (etype));
10355     }
10356   /* special case when cast remat */
10357   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10358       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10359     {
10360       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10361       type = operandType (left);
10362       p_type = DCL_TYPE (type);
10363     }
10364   /* now that we have the pointer type we assign
10365      the pointer values */
10366   switch (p_type)
10367     {
10368
10369     case POINTER:
10370     case IPOINTER:
10371       genNearPointerGet (left, result, ic, pi);
10372       break;
10373
10374     case PPOINTER:
10375       genPagedPointerGet (left, result, ic, pi);
10376       break;
10377
10378     case FPOINTER:
10379       genFarPointerGet (left, result, ic, pi);
10380       break;
10381
10382     case CPOINTER:
10383       genCodePointerGet (left, result, ic, pi);
10384       break;
10385
10386     case GPOINTER:
10387       genGenPointerGet (left, result, ic, pi);
10388       break;
10389     }
10390
10391 }
10392
10393 /*-----------------------------------------------------------------*/
10394 /* genPackBits - generates code for packed bit storage             */
10395 /*-----------------------------------------------------------------*/
10396 static void
10397 genPackBits (sym_link * etype,
10398              operand * right,
10399              char *rname, int p_type)
10400 {
10401   int offset = 0;       /* source byte offset */
10402   int rlen = 0;         /* remaining bitfield length */
10403   int blen;             /* bitfield length */
10404   int bstr;             /* bitfield starting bit within byte */
10405   int litval;           /* source literal value (if AOP_LIT) */
10406   unsigned char mask;   /* bitmask within current byte */
10407
10408   D(emitcode (";     genPackBits",""));
10409
10410   blen = SPEC_BLEN (etype);
10411   bstr = SPEC_BSTR (etype);
10412
10413   /* If the bitfield length is less than a byte */
10414   if (blen < 8)
10415     {
10416       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10417               (unsigned char) (0xFF >> (8 - bstr)));
10418
10419       if (AOP_TYPE (right) == AOP_LIT)
10420         {
10421           /* Case with a bitfield length <8 and literal source
10422           */
10423           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10424           litval <<= bstr;
10425           litval &= (~mask) & 0xff;
10426           emitPtrByteGet (rname, p_type, FALSE);
10427           if ((mask|litval)!=0xff)
10428             emitcode ("anl","a,#!constbyte", mask);
10429           if (litval)
10430             emitcode ("orl","a,#!constbyte", litval);
10431         }
10432       else
10433         {
10434           if ((blen==1) && (p_type!=GPOINTER))
10435             {
10436               /* Case with a bitfield length == 1 and no generic pointer
10437               */
10438               if (AOP_TYPE (right) == AOP_CRY)
10439                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10440               else
10441                 {
10442                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10443                   emitcode ("rrc","a");
10444                 }
10445               emitPtrByteGet (rname, p_type, FALSE);
10446               emitcode ("mov","acc.%d,c",bstr);
10447             }
10448           else
10449             {
10450               /* Case with a bitfield length < 8 and arbitrary source
10451               */
10452               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10453               /* shift and mask source value */
10454               AccLsh (bstr);
10455               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10456
10457               /* transfer A to B and get next byte */
10458               emitPtrByteGet (rname, p_type, TRUE);
10459
10460               emitcode ("anl", "a,#!constbyte", mask);
10461               emitcode ("orl", "a,b");
10462               if (p_type == GPOINTER)
10463                 emitcode ("pop", "b");
10464            }
10465         }
10466
10467       emitPtrByteSet (rname, p_type, "a");
10468       return;
10469     }
10470
10471   /* Bit length is greater than 7 bits. In this case, copy  */
10472   /* all except the partial byte at the end                 */
10473   for (rlen=blen;rlen>=8;rlen-=8)
10474     {
10475       emitPtrByteSet (rname, p_type,
10476                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10477       if (rlen>8)
10478         emitcode ("inc", "%s", rname);
10479     }
10480
10481   /* If there was a partial byte at the end */
10482   if (rlen)
10483     {
10484       mask = (((unsigned char) -1 << rlen) & 0xff);
10485
10486       if (AOP_TYPE (right) == AOP_LIT)
10487         {
10488           /* Case with partial byte and literal source
10489           */
10490           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10491           litval >>= (blen-rlen);
10492           litval &= (~mask) & 0xff;
10493           emitPtrByteGet (rname, p_type, FALSE);
10494           if ((mask|litval)!=0xff)
10495             emitcode ("anl","a,#!constbyte", mask);
10496           if (litval)
10497             emitcode ("orl","a,#!constbyte", litval);
10498         }
10499       else
10500         {
10501           /* Case with partial byte and arbitrary source
10502           */
10503           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10504           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10505
10506           /* transfer A to B and get next byte */
10507           emitPtrByteGet (rname, p_type, TRUE);
10508
10509           emitcode ("anl", "a,#!constbyte", mask);
10510           emitcode ("orl", "a,b");
10511           if (p_type == GPOINTER)
10512             emitcode ("pop", "b");
10513         }
10514       emitPtrByteSet (rname, p_type, "a");
10515     }
10516
10517 }
10518
10519
10520 /*-----------------------------------------------------------------*/
10521 /* genDataPointerSet - remat pointer to data space                 */
10522 /*-----------------------------------------------------------------*/
10523 static void
10524 genDataPointerSet (operand * right,
10525                    operand * result,
10526                    iCode * ic)
10527 {
10528   int size, offset = 0;
10529   char *l, buff[256];
10530
10531   aopOp (right, ic, FALSE, FALSE);
10532
10533   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10534   size = AOP_SIZE (right);
10535   while (size--)
10536     {
10537       if (offset)
10538         {
10539             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10540         }
10541       else
10542         {
10543             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10544         }
10545
10546       emitcode ("mov", "%s,%s", buff,
10547                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10548     }
10549
10550   freeAsmop (right, NULL, ic, TRUE);
10551   freeAsmop (result, NULL, ic, TRUE);
10552 }
10553
10554 /*-----------------------------------------------------------------*/
10555 /* genNearPointerSet - emitcode for near pointer put                */
10556 /*-----------------------------------------------------------------*/
10557 static void
10558 genNearPointerSet (operand * right,
10559                    operand * result,
10560                    iCode * ic,
10561                    iCode * pi)
10562 {
10563   asmop *aop = NULL;
10564   char *rname, *l;
10565   sym_link *retype, *letype;
10566   sym_link *ptype = operandType (result);
10567
10568   retype = getSpec (operandType (right));
10569   letype = getSpec (ptype);
10570
10571   aopOp (result, ic, FALSE, FALSE);
10572
10573   /* if the result is rematerializable &
10574      in data space & not a bit variable */
10575   if (AOP_TYPE (result) == AOP_IMMD &&
10576       DCL_TYPE (ptype) == POINTER &&
10577       !IS_BITVAR (retype) &&
10578       !IS_BITVAR (letype))
10579     {
10580       genDataPointerSet (right, result, ic);
10581       return;
10582     }
10583
10584   /* if the value is already in a pointer register
10585      then don't need anything more */
10586   if (!AOP_INPREG (AOP (result)))
10587     {
10588       /* otherwise get a free pointer register */
10589       regs *preg;
10590
10591       aop = newAsmop (0);
10592       preg = getFreePtr (ic, &aop, FALSE);
10593       emitcode ("mov", "%s,%s",
10594                 preg->name,
10595                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10596       rname = preg->name;
10597     }
10598   else
10599     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10600
10601   aopOp (right, ic, FALSE, FALSE);
10602
10603   /* if bitfield then unpack the bits */
10604   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10605     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10606   else
10607     {
10608       /* we have can just get the values */
10609       int size = AOP_SIZE (right);
10610       int offset = 0;
10611
10612       while (size--)
10613         {
10614           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10615           if (*l == '@')
10616             {
10617               MOVA (l);
10618               emitcode ("mov", "@%s,a", rname);
10619             }
10620           else
10621             emitcode ("mov", "@%s,%s", rname, l);
10622           if (size || pi)
10623             emitcode ("inc", "%s", rname);
10624           offset++;
10625         }
10626     }
10627
10628   /* now some housekeeping stuff */
10629   if (aop)
10630     {
10631       /* we had to allocate for this iCode */
10632       if (pi) aopPut (AOP (result),rname,0);
10633       freeAsmop (NULL, aop, ic, TRUE);
10634     }
10635   else
10636     {
10637       /* we did not allocate which means left
10638          already in a pointer register, then
10639          if size > 0 && this could be used again
10640          we have to point it back to where it
10641          belongs */
10642       if (AOP_SIZE (right) > 1 &&
10643           !OP_SYMBOL (result)->remat &&
10644           (OP_SYMBOL (result)->liveTo > ic->seq ||
10645            ic->depth) &&
10646           !pi)
10647         {
10648           int size = AOP_SIZE (right) - 1;
10649           while (size--)
10650             emitcode ("dec", "%s", rname);
10651         }
10652     }
10653
10654   /* done */
10655   if (pi) pi->generated = 1;
10656   freeAsmop (result, NULL, ic, TRUE);
10657   freeAsmop (right, NULL, ic, TRUE);
10658
10659
10660 }
10661
10662 /*-----------------------------------------------------------------*/
10663 /* genPagedPointerSet - emitcode for Paged pointer put             */
10664 /*-----------------------------------------------------------------*/
10665 static void
10666 genPagedPointerSet (operand * right,
10667                     operand * result,
10668                     iCode * ic,
10669                     iCode *pi)
10670 {
10671   asmop *aop = NULL;
10672   char *rname;
10673   sym_link *retype, *letype;
10674
10675   retype = getSpec (operandType (right));
10676   letype = getSpec (operandType (result));
10677
10678   aopOp (result, ic, FALSE, FALSE);
10679
10680   /* if the value is already in a pointer register
10681      then don't need anything more */
10682   if (!AOP_INPREG (AOP (result)))
10683     {
10684       /* otherwise get a free pointer register */
10685       regs *preg;
10686
10687       aop = newAsmop (0);
10688       preg = getFreePtr (ic, &aop, FALSE);
10689       emitcode ("mov", "%s,%s",
10690                 preg->name,
10691                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10692       rname = preg->name;
10693     }
10694   else
10695     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10696
10697   aopOp (right, ic, FALSE, FALSE);
10698
10699   /* if bitfield then unpack the bits */
10700   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10701     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10702   else
10703     {
10704       /* we have can just get the values */
10705       int size = AOP_SIZE (right);
10706       int offset = 0;
10707
10708       while (size--)
10709         {
10710           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10711
10712           emitcode ("movx", "@%s,a", rname);
10713
10714           if (size || pi)
10715             emitcode ("inc", "%s", rname);
10716
10717           offset++;
10718         }
10719     }
10720
10721   /* now some housekeeping stuff */
10722   if (aop)
10723     {
10724       if (pi) aopPut (AOP (result),rname,0);
10725       /* we had to allocate for this iCode */
10726       freeAsmop (NULL, aop, ic, TRUE);
10727     }
10728   else
10729     {
10730       /* we did not allocate which means left
10731          already in a pointer register, then
10732          if size > 0 && this could be used again
10733          we have to point it back to where it
10734          belongs */
10735       if (AOP_SIZE (right) > 1 &&
10736           !OP_SYMBOL (result)->remat &&
10737           (OP_SYMBOL (result)->liveTo > ic->seq ||
10738            ic->depth) &&
10739           !pi)
10740         {
10741           int size = AOP_SIZE (right) - 1;
10742           while (size--)
10743             emitcode ("dec", "%s", rname);
10744         }
10745     }
10746
10747   /* done */
10748   if (pi) pi->generated = 1;
10749   freeAsmop (result, NULL, ic, TRUE);
10750   freeAsmop (right, NULL, ic, TRUE);
10751
10752
10753 }
10754
10755 /*-----------------------------------------------------------------*/
10756 /* genFarPointerSet - set value from far space                     */
10757 /*-----------------------------------------------------------------*/
10758 static void
10759 genFarPointerSet (operand * right,
10760                   operand * result, iCode * ic, iCode *pi)
10761 {
10762   int size, offset, dopi=1;
10763   sym_link *retype = getSpec (operandType (right));
10764   sym_link *letype = getSpec (operandType (result));
10765
10766   aopOp (result, ic, FALSE, FALSE);
10767
10768   /* if the operand is already in dptr
10769      then we do nothing else we move the value to dptr */
10770   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10771     {
10772       /* if this is remateriazable */
10773       if (AOP_TYPE (result) == AOP_IMMD)
10774         emitcode ("mov", "dptr,%s",
10775                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10776       else
10777         {
10778           /* we need to get it byte by byte */
10779           _startLazyDPSEvaluation ();
10780           if (AOP_TYPE (result) != AOP_DPTR)
10781             {
10782               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10783               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10784               if (options.model == MODEL_FLAT24)
10785                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10786             }
10787           else
10788             {
10789               /* We need to generate a load to DPTR indirect through DPTR. */
10790               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10791
10792               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10793               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10794               if (options.model == MODEL_FLAT24)
10795                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10796               emitcode ("pop", "dph");
10797               emitcode ("pop", "dpl");
10798               dopi=0;
10799             }
10800           _endLazyDPSEvaluation ();
10801         }
10802     }
10803   /* so dptr know contains the address */
10804   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10805
10806   /* if bit then unpack */
10807   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10808       if (AOP_INDPTRn(result)) {
10809           genSetDPTR(AOP(result)->aopu.dptr);
10810       }
10811       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10812       if (AOP_INDPTRn(result)) {
10813           genSetDPTR(0);
10814       }
10815   } else {
10816       size = AOP_SIZE (right);
10817       offset = 0;
10818       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10819           while (size--) {
10820               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10821
10822               genSetDPTR(AOP(result)->aopu.dptr);
10823               emitcode ("movx", "@dptr,a");
10824               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10825                   emitcode ("inc", "dptr");
10826               genSetDPTR (0);
10827           }
10828       } else {
10829           _startLazyDPSEvaluation ();
10830           while (size--) {
10831               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10832
10833               if (AOP_INDPTRn(result)) {
10834                   genSetDPTR(AOP(result)->aopu.dptr);
10835               } else {
10836                   genSetDPTR (0);
10837               }
10838               _flushLazyDPS ();
10839
10840               emitcode ("movx", "@dptr,a");
10841               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10842                   emitcode ("inc", "dptr");
10843           }
10844           _endLazyDPSEvaluation ();
10845       }
10846   }
10847
10848   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10849       if (!AOP_INDPTRn(result)) {
10850           _startLazyDPSEvaluation ();
10851
10852           aopPut (AOP(result),"dpl",0);
10853           aopPut (AOP(result),"dph",1);
10854           if (options.model == MODEL_FLAT24)
10855               aopPut (AOP(result),"dpx",2);
10856
10857           _endLazyDPSEvaluation ();
10858       }
10859       pi->generated=1;
10860   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10861              AOP_SIZE(right) > 1 &&
10862              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10863
10864       size = AOP_SIZE (right) - 1;
10865       if (AOP_INDPTRn(result)) {
10866           genSetDPTR(AOP(result)->aopu.dptr);
10867       }
10868       while (size--) emitcode ("lcall","__decdptr");
10869       if (AOP_INDPTRn(result)) {
10870           genSetDPTR(0);
10871       }
10872   }
10873   freeAsmop (result, NULL, ic, TRUE);
10874   freeAsmop (right, NULL, ic, TRUE);
10875 }
10876
10877 /*-----------------------------------------------------------------*/
10878 /* genGenPointerSet - set value from generic pointer space         */
10879 /*-----------------------------------------------------------------*/
10880 static void
10881 genGenPointerSet (operand * right,
10882                   operand * result, iCode * ic, iCode *pi)
10883 {
10884   int size, offset;
10885   sym_link *retype = getSpec (operandType (right));
10886   sym_link *letype = getSpec (operandType (result));
10887
10888   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10889
10890   /* if the operand is already in dptr
10891      then we do nothing else we move the value to dptr */
10892   if (AOP_TYPE (result) != AOP_STR)
10893     {
10894       _startLazyDPSEvaluation ();
10895       /* if this is remateriazable */
10896       if (AOP_TYPE (result) == AOP_IMMD)
10897         {
10898           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10899           if (AOP(result)->aopu.aop_immd.from_cast_remat)
10900           {
10901               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10902           }
10903           else
10904           {
10905               emitcode ("mov",
10906                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10907           }
10908         }
10909       else
10910         {                       /* we need to get it byte by byte */
10911           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10912           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10913           if (options.model == MODEL_FLAT24) {
10914             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10915             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10916           } else {
10917             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10918           }
10919         }
10920       _endLazyDPSEvaluation ();
10921     }
10922   /* so dptr + b now contains the address */
10923   _G.bInUse++;
10924   aopOp (right, ic, FALSE, TRUE);
10925   _G.bInUse--;
10926
10927
10928   /* if bit then unpack */
10929   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10930     {
10931         genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10932     }
10933   else
10934     {
10935         size = AOP_SIZE (right);
10936         offset = 0;
10937
10938         _startLazyDPSEvaluation ();
10939         while (size--)
10940         {
10941             if (size)
10942             {
10943                 // Set two bytes at a time, passed in _AP & A.
10944                 // dptr will be incremented ONCE by __gptrputWord.
10945                 //
10946                 // Note: any change here must be coordinated
10947                 // with the implementation of __gptrputWord
10948                 // in device/lib/_gptrput.c
10949                 emitcode("mov", "_ap, %s",
10950                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10951                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10952
10953                 genSetDPTR (0);
10954                 _flushLazyDPS ();
10955                 emitcode ("lcall", "__gptrputWord");
10956                 size--;
10957             }
10958             else
10959             {
10960                 // Only one byte to put.
10961                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10962
10963                 genSetDPTR (0);
10964                 _flushLazyDPS ();
10965                 emitcode ("lcall", "__gptrput");
10966             }
10967
10968             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10969             {
10970                 emitcode ("inc", "dptr");
10971             }
10972         }
10973         _endLazyDPSEvaluation ();
10974     }
10975
10976   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10977       _startLazyDPSEvaluation ();
10978
10979       aopPut (AOP(result),"dpl",0);
10980       aopPut (AOP(result),"dph",1);
10981       if (options.model == MODEL_FLAT24) {
10982           aopPut (AOP(result),"dpx",2);
10983           aopPut (AOP(result),"b",3);
10984       } else {
10985           aopPut (AOP(result),"b",2);
10986       }
10987       _endLazyDPSEvaluation ();
10988
10989       pi->generated=1;
10990   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10991              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10992
10993       size = AOP_SIZE (right) - 1;
10994       while (size--) emitcode ("lcall","__decdptr");
10995   }
10996   freeAsmop (result, NULL, ic, TRUE);
10997   freeAsmop (right, NULL, ic, TRUE);
10998 }
10999
11000 /*-----------------------------------------------------------------*/
11001 /* genPointerSet - stores the value into a pointer location        */
11002 /*-----------------------------------------------------------------*/
11003 static void
11004 genPointerSet (iCode * ic, iCode *pi)
11005 {
11006   operand *right, *result;
11007   sym_link *type, *etype;
11008   int p_type;
11009
11010   D (emitcode (";", "genPointerSet "););
11011
11012   right = IC_RIGHT (ic);
11013   result = IC_RESULT (ic);
11014
11015   /* depending on the type of pointer we need to
11016      move it to the correct pointer register */
11017   type = operandType (result);
11018   etype = getSpec (type);
11019   /* if left is of type of pointer then it is simple */
11020   if (IS_PTR (type) && !IS_FUNC (type->next))
11021     {
11022       p_type = DCL_TYPE (type);
11023     }
11024   else
11025     {
11026       /* we have to go by the storage class */
11027       p_type = PTR_TYPE (SPEC_OCLS (etype));
11028     }
11029   /* special case when cast remat */
11030   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11031       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11032           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11033           type = operandType (result);
11034           p_type = DCL_TYPE (type);
11035   }
11036
11037   /* now that we have the pointer type we assign
11038      the pointer values */
11039   switch (p_type)
11040     {
11041
11042     case POINTER:
11043     case IPOINTER:
11044       genNearPointerSet (right, result, ic, pi);
11045       break;
11046
11047     case PPOINTER:
11048       genPagedPointerSet (right, result, ic, pi);
11049       break;
11050
11051     case FPOINTER:
11052       genFarPointerSet (right, result, ic, pi);
11053       break;
11054
11055     case GPOINTER:
11056       genGenPointerSet (right, result, ic, pi);
11057       break;
11058
11059     default:
11060       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11061               "genPointerSet: illegal pointer type");
11062     }
11063
11064 }
11065
11066 /*-----------------------------------------------------------------*/
11067 /* genIfx - generate code for Ifx statement                        */
11068 /*-----------------------------------------------------------------*/
11069 static void
11070 genIfx (iCode * ic, iCode * popIc)
11071 {
11072   operand *cond = IC_COND (ic);
11073   int isbit = 0;
11074
11075   D (emitcode (";", "genIfx "););
11076
11077   aopOp (cond, ic, FALSE, FALSE);
11078
11079   /* get the value into acc */
11080   if (AOP_TYPE (cond) != AOP_CRY)
11081     {
11082         toBoolean (cond);
11083     }
11084   else
11085     {
11086         isbit = 1;
11087     }
11088
11089   /* the result is now in the accumulator */
11090   freeAsmop (cond, NULL, ic, TRUE);
11091
11092   /* if there was something to be popped then do it */
11093   if (popIc)
11094     genIpop (popIc);
11095
11096   /* if the condition is  a bit variable */
11097   if (isbit && IS_ITEMP (cond) &&
11098       SPIL_LOC (cond))
11099     {
11100         genIfxJump (ic, SPIL_LOC (cond)->rname);
11101     }
11102   else if (isbit && !IS_ITEMP (cond))
11103     {
11104         genIfxJump (ic, OP_SYMBOL (cond)->rname);
11105     }
11106   else
11107     {
11108         genIfxJump (ic, "a");
11109     }
11110
11111   ic->generated = 1;
11112 }
11113
11114 /*-----------------------------------------------------------------*/
11115 /* genAddrOf - generates code for address of                       */
11116 /*-----------------------------------------------------------------*/
11117 static void
11118 genAddrOf (iCode * ic)
11119 {
11120   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11121   int size, offset;
11122
11123   D (emitcode (";", "genAddrOf ");
11124     );
11125
11126   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11127
11128   /* if the operand is on the stack then we
11129      need to get the stack offset of this
11130      variable */
11131   if (sym->onStack) {
11132
11133       /* if 10 bit stack */
11134       if (options.stack10bit) {
11135           char buff[10];
11136           int  offset;
11137
11138           tsprintf(buff, sizeof(buff),
11139                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
11140           /* if it has an offset then we need to compute it */
11141 /*        emitcode ("subb", "a,#!constbyte", */
11142 /*                  -((sym->stack < 0) ? */
11143 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
11144 /*                    ((short) sym->stack)) & 0xff); */
11145 /*        emitcode ("mov","b,a"); */
11146 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11147 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
11148 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
11149           if (sym->stack) {
11150               emitcode ("mov", "a,_bpx");
11151               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11152                                              ((char) (sym->stack - _G.nRegsSaved)) :
11153                                              ((char) sym->stack )) & 0xff);
11154               emitcode ("mov", "b,a");
11155               emitcode ("mov", "a,_bpx+1");
11156
11157               offset = (((sym->stack < 0) ?
11158                          ((short) (sym->stack - _G.nRegsSaved)) :
11159                          ((short) sym->stack )) >> 8) & 0xff;
11160
11161               emitcode ("addc","a,#!constbyte", offset);
11162
11163               aopPut (AOP (IC_RESULT (ic)), "b", 0);
11164               aopPut (AOP (IC_RESULT (ic)), "a", 1);
11165               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11166           } else {
11167               /* we can just move _bp */
11168               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11169               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11170               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11171           }
11172       } else {
11173           /* if it has an offset then we need to compute it */
11174           if (sym->stack) {
11175               emitcode ("mov", "a,_bp");
11176               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11177               aopPut (AOP (IC_RESULT (ic)), "a", 0);
11178           } else {
11179               /* we can just move _bp */
11180               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11181           }
11182           /* fill the result with zero */
11183           size = AOP_SIZE (IC_RESULT (ic)) - 1;
11184
11185
11186           if (options.stack10bit && size < (FPTRSIZE - 1)) {
11187               fprintf (stderr,
11188                        "*** warning: pointer to stack var truncated.\n");
11189           }
11190
11191           offset = 1;
11192           while (size--) {
11193               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11194           }
11195       }
11196       goto release;
11197   }
11198
11199   /* object not on stack then we need the name */
11200   size = AOP_SIZE (IC_RESULT (ic));
11201   offset = 0;
11202
11203   while (size--)
11204     {
11205       char s[SDCC_NAME_MAX];
11206       if (offset) {
11207           switch (offset) {
11208           case 1:
11209               tsprintf(s, sizeof(s), "#!his",sym->rname);
11210               break;
11211           case 2:
11212               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11213               break;
11214           case 3:
11215               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11216               break;
11217           default: /* should not need this (just in case) */
11218               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11219                        sym->rname,
11220                        offset * 8);
11221           }
11222       }
11223       else
11224       {
11225           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11226       }
11227
11228       aopPut (AOP (IC_RESULT (ic)), s, offset++);
11229     }
11230
11231 release:
11232   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11233
11234 }
11235
11236 #if 0 // obsolete, and buggy for != xdata
11237 /*-----------------------------------------------------------------*/
11238 /* genArrayInit - generates code for address of                       */
11239 /*-----------------------------------------------------------------*/
11240 static void
11241 genArrayInit (iCode * ic)
11242 {
11243     literalList *iLoop;
11244     int         ix, count;
11245     int         elementSize = 0, eIndex;
11246     unsigned    val, lastVal;
11247     sym_link    *type;
11248     operand     *left=IC_LEFT(ic);
11249
11250     D (emitcode (";", "genArrayInit "););
11251
11252     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11253
11254     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11255     {
11256         // Load immediate value into DPTR.
11257         emitcode("mov", "dptr, %s",
11258              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11259     }
11260     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11261     {
11262 #if 0
11263       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11264               "Unexpected operand to genArrayInit.\n");
11265       exit(1);
11266 #else
11267       // a regression because of SDCCcse.c:1.52
11268       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11269       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11270       if (options.model == MODEL_FLAT24)
11271         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11272 #endif
11273     }
11274
11275     type = operandType(IC_LEFT(ic));
11276
11277     if (type && type->next)
11278     {
11279         elementSize = getSize(type->next);
11280     }
11281     else
11282     {
11283         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11284                                 "can't determine element size in genArrayInit.\n");
11285         exit(1);
11286     }
11287
11288     iLoop = IC_ARRAYILIST(ic);
11289     lastVal = 0xffff;
11290
11291     while (iLoop)
11292     {
11293         bool firstpass = TRUE;
11294
11295         emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11296                  iLoop->count, (int)iLoop->literalValue, elementSize);
11297
11298         ix = iLoop->count;
11299
11300         while (ix)
11301         {
11302             symbol *tlbl = NULL;
11303
11304             count = ix > 256 ? 256 : ix;
11305
11306             if (count > 1)
11307             {
11308                 tlbl = newiTempLabel (NULL);
11309                 if (firstpass || (count & 0xff))
11310                 {
11311                     emitcode("mov", "b, #!constbyte", count & 0xff);
11312                 }
11313
11314                 emitcode ("", "!tlabeldef", tlbl->key + 100);
11315             }
11316
11317             firstpass = FALSE;
11318
11319             for (eIndex = 0; eIndex < elementSize; eIndex++)
11320             {
11321                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11322                 if (val != lastVal)
11323                 {
11324                     emitcode("mov", "a, #!constbyte", val);
11325                     lastVal = val;
11326                 }
11327
11328                 emitcode("movx", "@dptr, a");
11329                 emitcode("inc", "dptr");
11330             }
11331
11332             if (count > 1)
11333             {
11334                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11335             }
11336
11337             ix -= count;
11338         }
11339
11340         iLoop = iLoop->next;
11341     }
11342
11343     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11344 }
11345 #endif
11346
11347 /*-----------------------------------------------------------------*/
11348 /* genFarFarAssign - assignment when both are in far space         */
11349 /*-----------------------------------------------------------------*/
11350 static void
11351 genFarFarAssign (operand * result, operand * right, iCode * ic)
11352 {
11353   int size = AOP_SIZE (right);
11354   int offset = 0;
11355   symbol *rSym = NULL;
11356
11357   if (size == 1)
11358   {
11359       /* quick & easy case. */
11360       D(emitcode(";","genFarFarAssign (1 byte case)"););
11361       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11362       freeAsmop (right, NULL, ic, FALSE);
11363       /* now assign DPTR to result */
11364       _G.accInUse++;
11365       aopOp(result, ic, FALSE, FALSE);
11366       _G.accInUse--;
11367       aopPut(AOP(result), "a", 0);
11368       freeAsmop(result, NULL, ic, FALSE);
11369       return;
11370   }
11371
11372   /* See if we've got an underlying symbol to abuse. */
11373   if (IS_SYMOP(result) && OP_SYMBOL(result))
11374   {
11375       if (IS_TRUE_SYMOP(result))
11376       {
11377           rSym = OP_SYMBOL(result);
11378       }
11379       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11380       {
11381           rSym = OP_SYMBOL(result)->usl.spillLoc;
11382       }
11383   }
11384
11385   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11386   {
11387       /* We can use the '390 auto-toggle feature to good effect here. */
11388
11389       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11390       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
11391       emitcode ("mov", "dptr,#%s", rSym->rname);
11392       /* DP2 = result, DP1 = right, DP1 is current. */
11393       while (size)
11394       {
11395           emitcode("movx", "a,@dptr");
11396           emitcode("movx", "@dptr,a");
11397           if (--size)
11398           {
11399                emitcode("inc", "dptr");
11400                emitcode("inc", "dptr");
11401           }
11402       }
11403       emitcode("mov", "dps,#0");
11404       freeAsmop (right, NULL, ic, FALSE);
11405 #if 0
11406 some alternative code for processors without auto-toggle
11407 no time to test now, so later well put in...kpb
11408         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11409         emitcode("mov", "dps,#1");      /* Select DPTR2. */
11410         emitcode ("mov", "dptr,#%s", rSym->rname);
11411         /* DP2 = result, DP1 = right, DP1 is current. */
11412         while (size)
11413         {
11414           --size;
11415           emitcode("movx", "a,@dptr");
11416           if (size)
11417             emitcode("inc", "dptr");
11418           emitcode("inc", "dps");
11419           emitcode("movx", "@dptr,a");
11420           if (size)
11421             emitcode("inc", "dptr");
11422           emitcode("inc", "dps");
11423         }
11424         emitcode("mov", "dps,#0");
11425         freeAsmop (right, NULL, ic, FALSE);
11426 #endif
11427   }
11428   else
11429   {
11430       D (emitcode (";", "genFarFarAssign"););
11431       aopOp (result, ic, TRUE, TRUE);
11432
11433       _startLazyDPSEvaluation ();
11434
11435       while (size--)
11436         {
11437           aopPut (AOP (result),
11438                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11439           offset++;
11440         }
11441       _endLazyDPSEvaluation ();
11442       freeAsmop (result, NULL, ic, FALSE);
11443       freeAsmop (right, NULL, ic, FALSE);
11444   }
11445 }
11446
11447 /*-----------------------------------------------------------------*/
11448 /* genAssign - generate code for assignment                        */
11449 /*-----------------------------------------------------------------*/
11450 static void
11451 genAssign (iCode * ic)
11452 {
11453   operand *result, *right;
11454   int size, offset;
11455   unsigned long lit = 0L;
11456
11457   D (emitcode (";", "genAssign ");
11458     );
11459
11460   result = IC_RESULT (ic);
11461   right = IC_RIGHT (ic);
11462
11463   /* if they are the same */
11464   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11465     return;
11466
11467   aopOp (right, ic, FALSE, FALSE);
11468
11469   emitcode (";", "genAssign: resultIsFar = %s",
11470             isOperandInFarSpace (result) ?
11471             "TRUE" : "FALSE");
11472
11473   /* special case both in far space */
11474   if ((AOP_TYPE (right) == AOP_DPTR ||
11475        AOP_TYPE (right) == AOP_DPTR2) &&
11476   /* IS_TRUE_SYMOP(result)       && */
11477       isOperandInFarSpace (result))
11478     {
11479       genFarFarAssign (result, right, ic);
11480       return;
11481     }
11482
11483   aopOp (result, ic, TRUE, FALSE);
11484
11485   /* if they are the same registers */
11486   if (sameRegs (AOP (right), AOP (result)))
11487     goto release;
11488
11489   /* if the result is a bit */
11490   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11491     {
11492       /* if the right size is a literal then
11493          we know what the value is */
11494       if (AOP_TYPE (right) == AOP_LIT)
11495         {
11496           if (((int) operandLitValue (right)))
11497             aopPut (AOP (result), one, 0);
11498           else
11499             aopPut (AOP (result), zero, 0);
11500           goto release;
11501         }
11502
11503       /* the right is also a bit variable */
11504       if (AOP_TYPE (right) == AOP_CRY)
11505         {
11506           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11507           aopPut (AOP (result), "c", 0);
11508           goto release;
11509         }
11510
11511       /* we need to or */
11512       toBoolean (right);
11513       aopPut (AOP (result), "a", 0);
11514       goto release;
11515     }
11516
11517   /* bit variables done */
11518   /* general case */
11519   size = AOP_SIZE (result);
11520   offset = 0;
11521   if (AOP_TYPE (right) == AOP_LIT)
11522     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11523
11524   if ((size > 1) &&
11525       (AOP_TYPE (result) != AOP_REG) &&
11526       (AOP_TYPE (right) == AOP_LIT) &&
11527       !IS_FLOAT (operandType (right)))
11528     {
11529       _startLazyDPSEvaluation ();
11530       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11531         {
11532           aopPut (AOP (result),
11533                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11534                   offset);
11535           offset++;
11536           size--;
11537         }
11538       /* And now fill the rest with zeros. */
11539       if (size)
11540         {
11541           emitcode ("clr", "a");
11542         }
11543       while (size--)
11544         {
11545           aopPut (AOP (result), "a", offset++);
11546         }
11547       _endLazyDPSEvaluation ();
11548     }
11549   else
11550     {
11551       _startLazyDPSEvaluation ();
11552       while (size--)
11553         {
11554           aopPut (AOP (result),
11555                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11556                   offset);
11557           offset++;
11558         }
11559       _endLazyDPSEvaluation ();
11560     }
11561
11562 release:
11563   freeAsmop (right, NULL, ic, FALSE);
11564   freeAsmop (result, NULL, ic, TRUE);
11565 }
11566
11567 /*-----------------------------------------------------------------*/
11568 /* genJumpTab - generates code for jump table                      */
11569 /*-----------------------------------------------------------------*/
11570 static void
11571 genJumpTab (iCode * ic)
11572 {
11573   symbol *jtab;
11574   char *l;
11575
11576   D (emitcode (";", "genJumpTab ");
11577     );
11578
11579   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11580   /* get the condition into accumulator */
11581   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11582   MOVA (l);
11583   /* multiply by four! */
11584   emitcode ("add", "a,acc");
11585   emitcode ("add", "a,acc");
11586   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11587
11588   jtab = newiTempLabel (NULL);
11589   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11590   emitcode ("jmp", "@a+dptr");
11591   emitcode ("", "!tlabeldef", jtab->key + 100);
11592   /* now generate the jump labels */
11593   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11594        jtab = setNextItem (IC_JTLABELS (ic)))
11595     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11596
11597 }
11598
11599 /*-----------------------------------------------------------------*/
11600 /* genCast - gen code for casting                                  */
11601 /*-----------------------------------------------------------------*/
11602 static void
11603 genCast (iCode * ic)
11604 {
11605   operand *result = IC_RESULT (ic);
11606   sym_link *ctype = operandType (IC_LEFT (ic));
11607   sym_link *rtype = operandType (IC_RIGHT (ic));
11608   operand *right = IC_RIGHT (ic);
11609   int size, offset;
11610
11611   D (emitcode (";", "genCast "););
11612
11613   /* if they are equivalent then do nothing */
11614   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11615     return;
11616
11617   aopOp (right, ic, FALSE, AOP_IS_STR (result));
11618   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11619
11620   /* if the result is a bit */
11621   if (IS_BITVAR (OP_SYMBOL (result)->type)
11622       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11623     {
11624       /* if the right size is a literal then
11625          we know what the value is */
11626       if (AOP_TYPE (right) == AOP_LIT)
11627         {
11628           if (((int) operandLitValue (right)))
11629             aopPut (AOP (result), one, 0);
11630           else
11631             aopPut (AOP (result), zero, 0);
11632
11633           goto release;
11634         }
11635
11636       /* the right is also a bit variable */
11637       if (AOP_TYPE (right) == AOP_CRY)
11638         {
11639           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11640           aopPut (AOP (result), "c", 0);
11641           goto release;
11642         }
11643
11644       /* we need to or */
11645       toBoolean (right);
11646       aopPut (AOP (result), "a", 0);
11647       goto release;
11648     }
11649
11650   /* if they are the same size : or less */
11651   if (AOP_SIZE (result) <= AOP_SIZE (right))
11652     {
11653
11654       /* if they are in the same place */
11655       if (sameRegs (AOP (right), AOP (result)))
11656         goto release;
11657
11658       /* if they in different places then copy */
11659       size = AOP_SIZE (result);
11660       offset = 0;
11661       _startLazyDPSEvaluation ();
11662       while (size--)
11663         {
11664           aopPut (AOP (result),
11665                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11666                   offset);
11667           offset++;
11668         }
11669       _endLazyDPSEvaluation ();
11670       goto release;
11671     }
11672
11673
11674   /* if the result is of type pointer */
11675   if (IS_PTR (ctype))
11676     {
11677
11678       int p_type;
11679       sym_link *type = operandType (right);
11680
11681       /* pointer to generic pointer */
11682       if (IS_GENPTR (ctype))
11683         {
11684           if (IS_PTR (type))
11685             {
11686               p_type = DCL_TYPE (type);
11687             }
11688           else
11689             {
11690 #if OLD_CAST_BEHAVIOR
11691               /* KV: we are converting a non-pointer type to
11692                * a generic pointer. This (ifdef'd out) code
11693                * says that the resulting generic pointer
11694                * should have the same class as the storage
11695                * location of the non-pointer variable.
11696                *
11697                * For example, converting an int (which happens
11698                * to be stored in DATA space) to a pointer results
11699                * in a DATA generic pointer; if the original int
11700                * in XDATA space, so will be the resulting pointer.
11701                *
11702                * I don't like that behavior, and thus this change:
11703                * all such conversions will be forced to XDATA and
11704                * throw a warning. If you want some non-XDATA
11705                * type, or you want to suppress the warning, you
11706                * must go through an intermediate cast, like so:
11707                *
11708                * char _generic *gp = (char _xdata *)(intVar);
11709                */
11710               sym_link *etype = getSpec (type);
11711
11712               /* we have to go by the storage class */
11713               if (SPEC_OCLS (etype) != generic)
11714                 {
11715                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11716                 }
11717               else
11718 #endif
11719                 {
11720                   /* Converting unknown class (i.e. register variable)
11721                    * to generic pointer. This is not good, but
11722                    * we'll make a guess (and throw a warning).
11723                    */
11724                   p_type = FPOINTER;
11725                   werror (W_INT_TO_GEN_PTR_CAST);
11726                 }
11727             }
11728
11729           /* the first two bytes are known */
11730           size = GPTRSIZE - 1;
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
11742           /* the last byte depending on type */
11743             {
11744                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11745                 char gpValStr[10];
11746
11747                 if (gpVal == -1)
11748                 {
11749                     // pointerTypeToGPByte will have bitched.
11750                     exit(1);
11751                 }
11752
11753                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
11754                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11755             }
11756           goto release;
11757         }
11758
11759       /* just copy the pointers */
11760       size = AOP_SIZE (result);
11761       offset = 0;
11762       _startLazyDPSEvaluation ();
11763       while (size--)
11764         {
11765           aopPut (AOP (result),
11766                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11767                   offset);
11768           offset++;
11769         }
11770       _endLazyDPSEvaluation ();
11771       goto release;
11772     }
11773
11774   /* so we now know that the size of destination is greater
11775      than the size of the source */
11776   /* we move to result for the size of source */
11777   size = AOP_SIZE (right);
11778   offset = 0;
11779   _startLazyDPSEvaluation ();
11780   while (size--)
11781     {
11782       aopPut (AOP (result),
11783               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11784               offset);
11785       offset++;
11786     }
11787   _endLazyDPSEvaluation ();
11788
11789   /* now depending on the sign of the source && destination */
11790   size = AOP_SIZE (result) - AOP_SIZE (right);
11791   /* if unsigned or not an integral type */
11792   /* also, if the source is a bit, we don't need to sign extend, because
11793    * it can't possibly have set the sign bit.
11794    */
11795   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11796     {
11797       while (size--)
11798         {
11799           aopPut (AOP (result), zero, offset++);
11800         }
11801     }
11802   else
11803     {
11804       /* we need to extend the sign :{ */
11805       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11806                         FALSE, FALSE, NULL));
11807       emitcode ("rlc", "a");
11808       emitcode ("subb", "a,acc");
11809       while (size--)
11810         aopPut (AOP (result), "a", offset++);
11811     }
11812
11813   /* we are done hurray !!!! */
11814
11815 release:
11816   freeAsmop (right, NULL, ic, TRUE);
11817   freeAsmop (result, NULL, ic, TRUE);
11818
11819 }
11820
11821 /*-----------------------------------------------------------------*/
11822 /* genDjnz - generate decrement & jump if not zero instrucion      */
11823 /*-----------------------------------------------------------------*/
11824 static int
11825 genDjnz (iCode * ic, iCode * ifx)
11826 {
11827   symbol *lbl, *lbl1;
11828   if (!ifx)
11829     return 0;
11830
11831   /* if the if condition has a false label
11832      then we cannot save */
11833   if (IC_FALSE (ifx))
11834     return 0;
11835
11836   /* if the minus is not of the form
11837      a = a - 1 */
11838   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11839       !IS_OP_LITERAL (IC_RIGHT (ic)))
11840     return 0;
11841
11842   if (operandLitValue (IC_RIGHT (ic)) != 1)
11843     return 0;
11844
11845   /* if the size of this greater than one then no
11846      saving */
11847   if (getSize (operandType (IC_RESULT (ic))) > 1)
11848     return 0;
11849
11850   /* otherwise we can save BIG */
11851   D(emitcode(";", "genDjnz"););
11852
11853   lbl = newiTempLabel (NULL);
11854   lbl1 = newiTempLabel (NULL);
11855
11856   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11857
11858   if (AOP_NEEDSACC(IC_RESULT(ic)))
11859   {
11860       /* If the result is accessed indirectly via
11861        * the accumulator, we must explicitly write
11862        * it back after the decrement.
11863        */
11864       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11865
11866       if (strcmp(rByte, "a"))
11867       {
11868            /* Something is hopelessly wrong */
11869            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11870                    __FILE__, __LINE__);
11871            /* We can just give up; the generated code will be inefficient,
11872             * but what the hey.
11873             */
11874            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11875            return 0;
11876       }
11877       emitcode ("dec", "%s", rByte);
11878       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11879       emitcode ("jnz", "!tlabel", lbl->key + 100);
11880   }
11881   else if (IS_AOP_PREG (IC_RESULT (ic)))
11882     {
11883       emitcode ("dec", "%s",
11884                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11885       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11886       emitcode ("jnz", "!tlabel", lbl->key + 100);
11887     }
11888   else
11889     {
11890       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11891                 lbl->key + 100);
11892     }
11893   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11894   emitcode ("", "!tlabeldef", lbl->key + 100);
11895   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11896   emitcode ("", "!tlabeldef", lbl1->key + 100);
11897
11898   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11899   ifx->generated = 1;
11900   return 1;
11901 }
11902
11903 /*-----------------------------------------------------------------*/
11904 /* genReceive - generate code for a receive iCode                  */
11905 /*-----------------------------------------------------------------*/
11906 static void
11907 genReceive (iCode * ic)
11908 {
11909     int size = getSize (operandType (IC_RESULT (ic)));
11910     int offset = 0;
11911     int rb1off ;
11912
11913     D (emitcode (";", "genReceive "););
11914
11915     if (ic->argreg == 1)
11916     {
11917         /* first parameter */
11918         if (AOP_IS_STR(IC_RESULT(ic)))
11919         {
11920             /* Nothing to do: it's already in the proper place. */
11921             return;
11922         }
11923         else
11924         {
11925             bool useDp2;
11926
11927             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11928                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11929                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11930
11931             _G.accInUse++;
11932             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11933             _G.accInUse--;
11934
11935             /* Sanity checking... */
11936             if (AOP_USESDPTR(IC_RESULT(ic)))
11937             {
11938                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11939                         "genReceive got unexpected DPTR.");
11940             }
11941             assignResultValue (IC_RESULT (ic));
11942         }
11943     }
11944     else
11945     {
11946         /* second receive onwards */
11947         /* this gets a little tricky since unused recevies will be
11948          eliminated, we have saved the reg in the type field . and
11949          we use that to figure out which register to use */
11950         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11951         rb1off = ic->argreg;
11952         while (size--)
11953         {
11954             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11955         }
11956     }
11957     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11958 }
11959
11960 /*-----------------------------------------------------------------*/
11961 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11962 /*-----------------------------------------------------------------*/
11963 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11964 {
11965     operand *from , *to , *count;
11966     symbol *lbl;
11967     bitVect *rsave;
11968     int i;
11969
11970     /* we know it has to be 3 parameters */
11971     assert (nparms == 3);
11972
11973     rsave = newBitVect(16);
11974     /* save DPTR if it needs to be saved */
11975     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11976             if (bitVectBitValue(ic->rMask,i))
11977                     rsave = bitVectSetBit(rsave,i);
11978     }
11979     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11980                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11981     savermask(rsave);
11982
11983     to = parms[0];
11984     from = parms[1];
11985     count = parms[2];
11986
11987     aopOp (from, ic->next, FALSE, FALSE);
11988
11989     /* get from into DPTR1 */
11990     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11991     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11992     if (options.model == MODEL_FLAT24) {
11993         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11994     }
11995
11996     freeAsmop (from, NULL, ic, FALSE);
11997     aopOp (to, ic, FALSE, FALSE);
11998     /* get "to" into DPTR */
11999     /* if the operand is already in dptr
12000        then we do nothing else we move the value to dptr */
12001     if (AOP_TYPE (to) != AOP_STR) {
12002         /* if already in DPTR then we need to push */
12003         if (AOP_TYPE(to) == AOP_DPTR) {
12004             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12005             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12006             if (options.model == MODEL_FLAT24)
12007                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12008             emitcode ("pop", "dph");
12009             emitcode ("pop", "dpl");
12010         } else {
12011             _startLazyDPSEvaluation ();
12012             /* if this is remateriazable */
12013             if (AOP_TYPE (to) == AOP_IMMD) {
12014                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12015             } else {                    /* we need to get it byte by byte */
12016                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12017                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12018                 if (options.model == MODEL_FLAT24) {
12019                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12020                 }
12021             }
12022             _endLazyDPSEvaluation ();
12023         }
12024     }
12025     freeAsmop (to, NULL, ic, FALSE);
12026     _G.dptrInUse = _G.dptr1InUse = 1;
12027     aopOp (count, ic->next->next, FALSE,FALSE);
12028     lbl =newiTempLabel(NULL);
12029
12030     /* now for the actual copy */
12031     if (AOP_TYPE(count) == AOP_LIT &&
12032         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12033         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12034         if (fromc) {
12035             emitcode ("lcall","__bi_memcpyc2x_s");
12036         } else {
12037             emitcode ("lcall","__bi_memcpyx2x_s");
12038         }
12039         freeAsmop (count, NULL, ic, FALSE);
12040     } else {
12041         symbol *lbl1 = newiTempLabel(NULL);
12042
12043         emitcode (";"," Auto increment but no djnz");
12044         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12045         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12046         freeAsmop (count, NULL, ic, FALSE);
12047         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12048         emitcode ("","!tlabeldef",lbl->key+100);
12049         if (fromc) {
12050             emitcode ("clr","a");
12051             emitcode ("movc", "a,@a+dptr");
12052         } else
12053             emitcode ("movx", "a,@dptr");
12054         emitcode ("movx", "@dptr,a");
12055         emitcode ("inc", "dptr");
12056         emitcode ("inc", "dptr");
12057         emitcode ("mov","a,b");
12058         emitcode ("orl","a,_ap");
12059         emitcode ("jz","!tlabel",lbl1->key+100);
12060         emitcode ("mov","a,_ap");
12061         emitcode ("add","a,#!constbyte",0xFF);
12062         emitcode ("mov","_ap,a");
12063         emitcode ("mov","a,b");
12064         emitcode ("addc","a,#!constbyte",0xFF);
12065         emitcode ("mov","b,a");
12066         emitcode ("sjmp","!tlabel",lbl->key+100);
12067         emitcode ("","!tlabeldef",lbl1->key+100);
12068     }
12069     emitcode ("mov", "dps,#0");
12070     _G.dptrInUse = _G.dptr1InUse = 0;
12071     unsavermask(rsave);
12072
12073 }
12074
12075 /*-----------------------------------------------------------------*/
12076 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
12077 /*-----------------------------------------------------------------*/
12078 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12079 {
12080     operand *from , *to , *count;
12081     symbol *lbl,*lbl2;
12082     bitVect *rsave;
12083     int i;
12084
12085     /* we know it has to be 3 parameters */
12086     assert (nparms == 3);
12087
12088     rsave = newBitVect(16);
12089     /* save DPTR if it needs to be saved */
12090     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12091             if (bitVectBitValue(ic->rMask,i))
12092                     rsave = bitVectSetBit(rsave,i);
12093     }
12094     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12095                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12096     savermask(rsave);
12097
12098     to = parms[0];
12099     from = parms[1];
12100     count = parms[2];
12101
12102     aopOp (from, ic->next, FALSE, FALSE);
12103
12104     /* get from into DPTR1 */
12105     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12106     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12107     if (options.model == MODEL_FLAT24) {
12108         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12109     }
12110
12111     freeAsmop (from, NULL, ic, FALSE);
12112     aopOp (to, ic, FALSE, FALSE);
12113     /* get "to" into DPTR */
12114     /* if the operand is already in dptr
12115        then we do nothing else we move the value to dptr */
12116     if (AOP_TYPE (to) != AOP_STR) {
12117         /* if already in DPTR then we need to push */
12118         if (AOP_TYPE(to) == AOP_DPTR) {
12119             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12120             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12121             if (options.model == MODEL_FLAT24)
12122                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12123             emitcode ("pop", "dph");
12124             emitcode ("pop", "dpl");
12125         } else {
12126             _startLazyDPSEvaluation ();
12127             /* if this is remateriazable */
12128             if (AOP_TYPE (to) == AOP_IMMD) {
12129                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12130             } else {                    /* we need to get it byte by byte */
12131                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12132                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12133                 if (options.model == MODEL_FLAT24) {
12134                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12135                 }
12136             }
12137             _endLazyDPSEvaluation ();
12138         }
12139     }
12140     freeAsmop (to, NULL, ic, FALSE);
12141     _G.dptrInUse = _G.dptr1InUse = 1;
12142     aopOp (count, ic->next->next, FALSE,FALSE);
12143     lbl =newiTempLabel(NULL);
12144     lbl2 =newiTempLabel(NULL);
12145
12146     /* now for the actual compare */
12147     if (AOP_TYPE(count) == AOP_LIT &&
12148         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12149         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12150         if (fromc)
12151             emitcode("lcall","__bi_memcmpc2x_s");
12152         else
12153             emitcode("lcall","__bi_memcmpx2x_s");
12154         freeAsmop (count, NULL, ic, FALSE);
12155         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12156         aopPut(AOP(IC_RESULT(ic)),"a",0);
12157         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12158     } else {
12159         symbol *lbl1 = newiTempLabel(NULL);
12160
12161         emitcode("push","ar0");
12162         emitcode (";"," Auto increment but no djnz");
12163         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12164         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12165         freeAsmop (count, NULL, ic, FALSE);
12166         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12167         emitcode ("","!tlabeldef",lbl->key+100);
12168         if (fromc) {
12169             emitcode ("clr","a");
12170             emitcode ("movc", "a,@a+dptr");
12171         } else
12172             emitcode ("movx", "a,@dptr");
12173         emitcode ("mov","r0,a");
12174         emitcode ("movx", "a,@dptr");
12175         emitcode ("clr","c");
12176         emitcode ("subb","a,r0");
12177         emitcode ("jnz","!tlabel",lbl2->key+100);
12178         emitcode ("inc", "dptr");
12179         emitcode ("inc", "dptr");
12180         emitcode ("mov","a,b");
12181         emitcode ("orl","a,_ap");
12182         emitcode ("jz","!tlabel",lbl1->key+100);
12183         emitcode ("mov","a,_ap");
12184         emitcode ("add","a,#!constbyte",0xFF);
12185         emitcode ("mov","_ap,a");
12186         emitcode ("mov","a,b");
12187         emitcode ("addc","a,#!constbyte",0xFF);
12188         emitcode ("mov","b,a");
12189         emitcode ("sjmp","!tlabel",lbl->key+100);
12190         emitcode ("","!tlabeldef",lbl1->key+100);
12191         emitcode ("clr","a");
12192         emitcode ("","!tlabeldef",lbl2->key+100);
12193         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12194         aopPut(AOP(IC_RESULT(ic)),"a",0);
12195         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12196         emitcode("pop","ar0");
12197         emitcode ("mov", "dps,#0");
12198     }
12199     _G.dptrInUse = _G.dptr1InUse = 0;
12200     unsavermask(rsave);
12201
12202 }
12203
12204 /*-----------------------------------------------------------------*/
12205 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12206 /* port, first parameter output area second parameter pointer to   */
12207 /* port third parameter count                                      */
12208 /*-----------------------------------------------------------------*/
12209 static void genInp( iCode *ic, int nparms, operand **parms)
12210 {
12211     operand *from , *to , *count;
12212     symbol *lbl;
12213     bitVect *rsave;
12214     int i;
12215
12216     /* we know it has to be 3 parameters */
12217     assert (nparms == 3);
12218
12219     rsave = newBitVect(16);
12220     /* save DPTR if it needs to be saved */
12221     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12222             if (bitVectBitValue(ic->rMask,i))
12223                     rsave = bitVectSetBit(rsave,i);
12224     }
12225     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12226                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12227     savermask(rsave);
12228
12229     to = parms[0];
12230     from = parms[1];
12231     count = parms[2];
12232
12233     aopOp (from, ic->next, FALSE, FALSE);
12234
12235     /* get from into DPTR1 */
12236     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12237     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12238     if (options.model == MODEL_FLAT24) {
12239         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12240     }
12241
12242     freeAsmop (from, NULL, ic, FALSE);
12243     aopOp (to, ic, FALSE, FALSE);
12244     /* get "to" into DPTR */
12245     /* if the operand is already in dptr
12246        then we do nothing else we move the value to dptr */
12247     if (AOP_TYPE (to) != AOP_STR) {
12248         /* if already in DPTR then we need to push */
12249         if (AOP_TYPE(to) == AOP_DPTR) {
12250             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12251             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12252             if (options.model == MODEL_FLAT24)
12253                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12254             emitcode ("pop", "dph");
12255             emitcode ("pop", "dpl");
12256         } else {
12257             _startLazyDPSEvaluation ();
12258             /* if this is remateriazable */
12259             if (AOP_TYPE (to) == AOP_IMMD) {
12260                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12261             } else {                    /* we need to get it byte by byte */
12262                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12263                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12264                 if (options.model == MODEL_FLAT24) {
12265                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12266                 }
12267             }
12268             _endLazyDPSEvaluation ();
12269         }
12270     }
12271     freeAsmop (to, NULL, ic, FALSE);
12272
12273     _G.dptrInUse = _G.dptr1InUse = 1;
12274     aopOp (count, ic->next->next, FALSE,FALSE);
12275     lbl =newiTempLabel(NULL);
12276
12277     /* now for the actual copy */
12278     if (AOP_TYPE(count) == AOP_LIT &&
12279         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12280         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12281         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12282         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12283         freeAsmop (count, NULL, ic, FALSE);
12284         emitcode ("","!tlabeldef",lbl->key+100);
12285         emitcode ("movx", "a,@dptr");   /* read data from port */
12286         emitcode ("dec","dps");         /* switch to DPTR */
12287         emitcode ("movx", "@dptr,a");   /* save into location */
12288         emitcode ("inc", "dptr");       /* point to next area */
12289         emitcode ("inc","dps");         /* switch to DPTR2 */
12290         emitcode ("djnz","b,!tlabel",lbl->key+100);
12291     } else {
12292         symbol *lbl1 = newiTempLabel(NULL);
12293
12294         emitcode (";"," Auto increment but no djnz");
12295         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12296         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12297         freeAsmop (count, NULL, ic, FALSE);
12298         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12299         emitcode ("","!tlabeldef",lbl->key+100);
12300         emitcode ("movx", "a,@dptr");
12301         emitcode ("dec","dps");         /* switch to DPTR */
12302         emitcode ("movx", "@dptr,a");
12303         emitcode ("inc", "dptr");
12304         emitcode ("inc","dps");         /* switch to DPTR2 */
12305 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
12306 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12307         emitcode ("mov","a,b");
12308         emitcode ("orl","a,_ap");
12309         emitcode ("jz","!tlabel",lbl1->key+100);
12310         emitcode ("mov","a,_ap");
12311         emitcode ("add","a,#!constbyte",0xFF);
12312         emitcode ("mov","_ap,a");
12313         emitcode ("mov","a,b");
12314         emitcode ("addc","a,#!constbyte",0xFF);
12315         emitcode ("mov","b,a");
12316         emitcode ("sjmp","!tlabel",lbl->key+100);
12317         emitcode ("","!tlabeldef",lbl1->key+100);
12318     }
12319     emitcode ("mov", "dps,#0");
12320     _G.dptrInUse = _G.dptr1InUse = 0;
12321     unsavermask(rsave);
12322
12323 }
12324
12325 /*-----------------------------------------------------------------*/
12326 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12327 /* port, first parameter output area second parameter pointer to   */
12328 /* port third parameter count                                      */
12329 /*-----------------------------------------------------------------*/
12330 static void genOutp( iCode *ic, int nparms, operand **parms)
12331 {
12332     operand *from , *to , *count;
12333     symbol *lbl;
12334     bitVect *rsave;
12335     int i;
12336
12337     /* we know it has to be 3 parameters */
12338     assert (nparms == 3);
12339
12340     rsave = newBitVect(16);
12341     /* save DPTR if it needs to be saved */
12342     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12343             if (bitVectBitValue(ic->rMask,i))
12344                     rsave = bitVectSetBit(rsave,i);
12345     }
12346     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12347                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12348     savermask(rsave);
12349
12350     to = parms[0];
12351     from = parms[1];
12352     count = parms[2];
12353
12354     aopOp (from, ic->next, FALSE, FALSE);
12355
12356     /* get from into DPTR1 */
12357     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12358     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12359     if (options.model == MODEL_FLAT24) {
12360         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12361     }
12362
12363     freeAsmop (from, NULL, ic, FALSE);
12364     aopOp (to, ic, FALSE, FALSE);
12365     /* get "to" into DPTR */
12366     /* if the operand is already in dptr
12367        then we do nothing else we move the value to dptr */
12368     if (AOP_TYPE (to) != AOP_STR) {
12369         /* if already in DPTR then we need to push */
12370         if (AOP_TYPE(to) == AOP_DPTR) {
12371             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12372             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12373             if (options.model == MODEL_FLAT24)
12374                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12375             emitcode ("pop", "dph");
12376             emitcode ("pop", "dpl");
12377         } else {
12378             _startLazyDPSEvaluation ();
12379             /* if this is remateriazable */
12380             if (AOP_TYPE (to) == AOP_IMMD) {
12381                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12382             } else {                    /* we need to get it byte by byte */
12383                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12384                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12385                 if (options.model == MODEL_FLAT24) {
12386                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12387                 }
12388             }
12389             _endLazyDPSEvaluation ();
12390         }
12391     }
12392     freeAsmop (to, NULL, ic, FALSE);
12393
12394     _G.dptrInUse = _G.dptr1InUse = 1;
12395     aopOp (count, ic->next->next, FALSE,FALSE);
12396     lbl =newiTempLabel(NULL);
12397
12398     /* now for the actual copy */
12399     if (AOP_TYPE(count) == AOP_LIT &&
12400         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12401         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12402         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12403         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12404         emitcode ("","!tlabeldef",lbl->key+100);
12405         emitcode ("movx", "a,@dptr");   /* read data from port */
12406         emitcode ("inc","dps");         /* switch to DPTR2 */
12407         emitcode ("movx", "@dptr,a");   /* save into location */
12408         emitcode ("inc", "dptr");       /* point to next area */
12409         emitcode ("dec","dps");         /* switch to DPTR */
12410         emitcode ("djnz","b,!tlabel",lbl->key+100);
12411         freeAsmop (count, NULL, ic, FALSE);
12412     } else {
12413         symbol *lbl1 = newiTempLabel(NULL);
12414
12415         emitcode (";"," Auto increment but no djnz");
12416         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12417         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12418         freeAsmop (count, NULL, ic, FALSE);
12419         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12420         emitcode ("","!tlabeldef",lbl->key+100);
12421         emitcode ("movx", "a,@dptr");
12422         emitcode ("inc", "dptr");
12423         emitcode ("inc","dps");         /* switch to DPTR2 */
12424         emitcode ("movx", "@dptr,a");
12425         emitcode ("dec","dps");         /* switch to DPTR */
12426         emitcode ("mov","a,b");
12427         emitcode ("orl","a,_ap");
12428         emitcode ("jz","!tlabel",lbl1->key+100);
12429         emitcode ("mov","a,_ap");
12430         emitcode ("add","a,#!constbyte",0xFF);
12431         emitcode ("mov","_ap,a");
12432         emitcode ("mov","a,b");
12433         emitcode ("addc","a,#!constbyte",0xFF);
12434         emitcode ("mov","b,a");
12435         emitcode ("sjmp","!tlabel",lbl->key+100);
12436         emitcode ("","!tlabeldef",lbl1->key+100);
12437     }
12438     emitcode ("mov", "dps,#0");
12439     _G.dptrInUse = _G.dptr1InUse = 0;
12440     unsavermask(rsave);
12441
12442 }
12443
12444 /*-----------------------------------------------------------------*/
12445 /* genSwapW - swap lower & high order bytes                        */
12446 /*-----------------------------------------------------------------*/
12447 static void genSwapW(iCode *ic, int nparms, operand **parms)
12448 {
12449     operand *dest;
12450     operand *src;
12451     assert (nparms==1);
12452
12453     src = parms[0];
12454     dest=IC_RESULT(ic);
12455
12456     assert(getSize(operandType(src))==2);
12457
12458     aopOp (src, ic, FALSE, FALSE);
12459     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12460     _G.accInUse++;
12461     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12462     _G.accInUse--;
12463     freeAsmop (src, NULL, ic, FALSE);
12464
12465     aopOp (dest,ic, FALSE, FALSE);
12466     aopPut(AOP(dest),"b",0);
12467     aopPut(AOP(dest),"a",1);
12468     freeAsmop (dest, NULL, ic, FALSE);
12469 }
12470
12471 /*-----------------------------------------------------------------*/
12472 /* genMemsetX - gencode for memSetX data                           */
12473 /*-----------------------------------------------------------------*/
12474 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12475 {
12476     operand *to , *val , *count;
12477     symbol *lbl;
12478     char *l;
12479     int i;
12480     bitVect *rsave;
12481
12482     /* we know it has to be 3 parameters */
12483     assert (nparms == 3);
12484
12485     to = parms[0];
12486     val = parms[1];
12487     count = parms[2];
12488
12489     /* save DPTR if it needs to be saved */
12490     rsave = newBitVect(16);
12491     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12492             if (bitVectBitValue(ic->rMask,i))
12493                     rsave = bitVectSetBit(rsave,i);
12494     }
12495     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12496                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12497     savermask(rsave);
12498
12499     aopOp (to, ic, FALSE, FALSE);
12500     /* get "to" into DPTR */
12501     /* if the operand is already in dptr
12502        then we do nothing else we move the value to dptr */
12503     if (AOP_TYPE (to) != AOP_STR) {
12504         /* if already in DPTR then we need to push */
12505         if (AOP_TYPE(to) == AOP_DPTR) {
12506             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12507             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12508             if (options.model == MODEL_FLAT24)
12509                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12510             emitcode ("pop", "dph");
12511             emitcode ("pop", "dpl");
12512         } else {
12513             _startLazyDPSEvaluation ();
12514             /* if this is remateriazable */
12515             if (AOP_TYPE (to) == AOP_IMMD) {
12516                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12517             } else {                    /* we need to get it byte by byte */
12518                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12519                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12520                 if (options.model == MODEL_FLAT24) {
12521                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12522                 }
12523             }
12524             _endLazyDPSEvaluation ();
12525         }
12526     }
12527     freeAsmop (to, NULL, ic, FALSE);
12528
12529     aopOp (val, ic->next->next, FALSE,FALSE);
12530     aopOp (count, ic->next->next, FALSE,FALSE);
12531     lbl =newiTempLabel(NULL);
12532     /* now for the actual copy */
12533     if (AOP_TYPE(count) == AOP_LIT &&
12534         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12535         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12536         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12537         MOVA(l);
12538         emitcode ("","!tlabeldef",lbl->key+100);
12539         emitcode ("movx", "@dptr,a");
12540         emitcode ("inc", "dptr");
12541         emitcode ("djnz","b,!tlabel",lbl->key+100);
12542     } else {
12543         symbol *lbl1 = newiTempLabel(NULL);
12544
12545         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12546         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12547         emitcode ("","!tlabeldef",lbl->key+100);
12548         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12549         emitcode ("movx", "@dptr,a");
12550         emitcode ("inc", "dptr");
12551         emitcode ("mov","a,b");
12552         emitcode ("orl","a,_ap");
12553         emitcode ("jz","!tlabel",lbl1->key+100);
12554         emitcode ("mov","a,_ap");
12555         emitcode ("add","a,#!constbyte",0xFF);
12556         emitcode ("mov","_ap,a");
12557         emitcode ("mov","a,b");
12558         emitcode ("addc","a,#!constbyte",0xFF);
12559         emitcode ("mov","b,a");
12560         emitcode ("sjmp","!tlabel",lbl->key+100);
12561         emitcode ("","!tlabeldef",lbl1->key+100);
12562     }
12563     freeAsmop (count, NULL, ic, FALSE);
12564     unsavermask(rsave);
12565 }
12566
12567 /*-----------------------------------------------------------------*/
12568 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12569 /*-----------------------------------------------------------------*/
12570 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12571 {
12572         bitVect *rsave ;
12573         operand *pnum, *result;
12574         int i;
12575
12576         assert (nparms==1);
12577         /* save registers that need to be saved */
12578         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12579                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12580
12581         pnum = parms[0];
12582         aopOp (pnum, ic, FALSE, FALSE);
12583         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12584         freeAsmop (pnum, NULL, ic, FALSE);
12585         emitcode ("lcall","NatLib_LoadPrimitive");
12586         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12587         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12588             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12589                 for (i = (size-1) ; i >= 0 ; i-- ) {
12590                         emitcode ("push","a%s",javaRet[i]);
12591                 }
12592                 for (i=0; i < size ; i++ ) {
12593                         emitcode ("pop","a%s",
12594                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12595                 }
12596         } else {
12597                 for (i = 0 ; i < size ; i++ ) {
12598                         aopPut(AOP(result),javaRet[i],i);
12599                 }
12600         }
12601         freeAsmop (result, NULL, ic, FALSE);
12602         unsavermask(rsave);
12603 }
12604
12605 /*-----------------------------------------------------------------*/
12606 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12607 /*-----------------------------------------------------------------*/
12608 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12609 {
12610         bitVect *rsave ;
12611         operand *pnum, *result;
12612         int size = 3;
12613         int i;
12614
12615         assert (nparms==1);
12616         /* save registers that need to be saved */
12617         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12618                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12619
12620         pnum = parms[0];
12621         aopOp (pnum, ic, FALSE, FALSE);
12622         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12623         freeAsmop (pnum, NULL, ic, FALSE);
12624         emitcode ("lcall","NatLib_LoadPointer");
12625         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12626         if (AOP_TYPE(result)!=AOP_STR) {
12627                 for (i = 0 ; i < size ; i++ ) {
12628                         aopPut(AOP(result),fReturn[i],i);
12629                 }
12630         }
12631         freeAsmop (result, NULL, ic, FALSE);
12632         unsavermask(rsave);
12633 }
12634
12635 /*-----------------------------------------------------------------*/
12636 /* genNatLibInstallStateBlock -                                    */
12637 /*-----------------------------------------------------------------*/
12638 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12639                                        operand **parms, const char *name)
12640 {
12641         bitVect *rsave ;
12642         operand *psb, *handle;
12643         assert (nparms==2);
12644
12645         /* save registers that need to be saved */
12646         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12647                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12648         psb = parms[0];
12649         handle = parms[1];
12650
12651         /* put pointer to state block into DPTR1 */
12652         aopOp (psb, ic, FALSE, FALSE);
12653         if (AOP_TYPE (psb) == AOP_IMMD) {
12654                 emitcode ("mov","dps,#1");
12655                 emitcode ("mov", "dptr,%s",
12656                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12657                 emitcode ("mov","dps,#0");
12658         } else {
12659                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12660                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12661                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12662         }
12663         freeAsmop (psb, NULL, ic, FALSE);
12664
12665         /* put libraryID into DPTR */
12666         emitcode ("mov","dptr,#LibraryID");
12667
12668         /* put handle into r3:r2 */
12669         aopOp (handle, ic, FALSE, FALSE);
12670         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12671                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12672                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12673                 emitcode ("pop","ar3");
12674                 emitcode ("pop","ar2");
12675         } else {
12676                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12677                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12678         }
12679         freeAsmop (psb, NULL, ic, FALSE);
12680
12681         /* make the call */
12682         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12683
12684         /* put return value into place*/
12685         _G.accInUse++;
12686         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12687         _G.accInUse--;
12688         aopPut(AOP(IC_RESULT(ic)),"a",0);
12689         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12690         unsavermask(rsave);
12691 }
12692
12693 /*-----------------------------------------------------------------*/
12694 /* genNatLibRemoveStateBlock -                                     */
12695 /*-----------------------------------------------------------------*/
12696 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12697 {
12698         bitVect *rsave ;
12699
12700         assert(nparms==0);
12701
12702         /* save registers that need to be saved */
12703         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12704                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12705
12706         /* put libraryID into DPTR */
12707         emitcode ("mov","dptr,#LibraryID");
12708         /* make the call */
12709         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12710         unsavermask(rsave);
12711 }
12712
12713 /*-----------------------------------------------------------------*/
12714 /* genNatLibGetStateBlock -                                        */
12715 /*-----------------------------------------------------------------*/
12716 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12717                                    operand **parms,const char *name)
12718 {
12719         bitVect *rsave ;
12720         symbol *lbl = newiTempLabel(NULL);
12721
12722         assert(nparms==0);
12723         /* save registers that need to be saved */
12724         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12725                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12726
12727         /* put libraryID into DPTR */
12728         emitcode ("mov","dptr,#LibraryID");
12729         /* make the call */
12730         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12731         emitcode ("jnz","!tlabel",lbl->key+100);
12732
12733         /* put return value into place */
12734         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12735         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12736                 emitcode ("push","ar3");
12737                 emitcode ("push","ar2");
12738                 emitcode ("pop","%s",
12739                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12740                 emitcode ("pop","%s",
12741                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12742         } else {
12743                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12744                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12745         }
12746         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12747         emitcode ("","!tlabeldef",lbl->key+100);
12748         unsavermask(rsave);
12749 }
12750
12751 /*-----------------------------------------------------------------*/
12752 /* genMMMalloc -                                                   */
12753 /*-----------------------------------------------------------------*/
12754 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12755                          int size, const char *name)
12756 {
12757         bitVect *rsave ;
12758         operand *bsize;
12759         symbol *rsym;
12760         symbol *lbl = newiTempLabel(NULL);
12761
12762         assert (nparms == 1);
12763         /* save registers that need to be saved */
12764         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12765                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12766
12767         bsize=parms[0];
12768         aopOp (bsize,ic,FALSE,FALSE);
12769
12770         /* put the size in R4-R2 */
12771         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12772                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12773                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12774                 if (size==3) {
12775                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12776                         emitcode("pop","ar4");
12777                 }
12778                 emitcode("pop","ar3");
12779                 emitcode("pop","ar2");
12780         } else {
12781                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12782                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12783                 if (size==3) {
12784                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12785                 }
12786         }
12787         freeAsmop (bsize, NULL, ic, FALSE);
12788
12789         /* make the call */
12790         emitcode ("lcall","MM_%s",name);
12791         emitcode ("jz","!tlabel",lbl->key+100);
12792         emitcode ("mov","r2,#!constbyte",0xff);
12793         emitcode ("mov","r3,#!constbyte",0xff);
12794         emitcode ("","!tlabeldef",lbl->key+100);
12795         /* we don't care about the pointer : we just save the handle */
12796         rsym = OP_SYMBOL(IC_RESULT(ic));
12797         if (rsym->liveFrom != rsym->liveTo) {
12798                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12799                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12800                         emitcode ("push","ar3");
12801                         emitcode ("push","ar2");
12802                         emitcode ("pop","%s",
12803                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12804                         emitcode ("pop","%s",
12805                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12806                 } else {
12807                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12808                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12809                 }
12810                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12811         }
12812         unsavermask(rsave);
12813 }
12814
12815 /*-----------------------------------------------------------------*/
12816 /* genMMDeref -                                                    */
12817 /*-----------------------------------------------------------------*/
12818 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12819 {
12820         bitVect *rsave ;
12821         operand *handle;
12822
12823         assert (nparms == 1);
12824         /* save registers that need to be saved */
12825         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12826                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12827
12828         handle=parms[0];
12829         aopOp (handle,ic,FALSE,FALSE);
12830
12831         /* put the size in R4-R2 */
12832         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12833                 emitcode("push","%s",
12834                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12835                 emitcode("push","%s",
12836                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12837                 emitcode("pop","ar3");
12838                 emitcode("pop","ar2");
12839         } else {
12840                 emitcode ("mov","r2,%s",
12841                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12842                 emitcode ("mov","r3,%s",
12843                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12844         }
12845         freeAsmop (handle, NULL, ic, FALSE);
12846
12847         /* make the call */
12848         emitcode ("lcall","MM_Deref");
12849
12850         {
12851                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12852                 if (rsym->liveFrom != rsym->liveTo) {
12853                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12854                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12855                             _startLazyDPSEvaluation ();
12856
12857                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12858                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12859                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12860
12861                             _endLazyDPSEvaluation ();
12862
12863                         }
12864                 }
12865         }
12866         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12867         unsavermask(rsave);
12868 }
12869
12870 /*-----------------------------------------------------------------*/
12871 /* genMMUnrestrictedPersist -                                      */
12872 /*-----------------------------------------------------------------*/
12873 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12874 {
12875         bitVect *rsave ;
12876         operand *handle;
12877
12878         assert (nparms == 1);
12879         /* save registers that need to be saved */
12880         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12881                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12882
12883         handle=parms[0];
12884         aopOp (handle,ic,FALSE,FALSE);
12885
12886         /* put the size in R3-R2 */
12887         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12888                 emitcode("push","%s",
12889                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12890                 emitcode("push","%s",
12891                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12892                 emitcode("pop","ar3");
12893                 emitcode("pop","ar2");
12894         } else {
12895                 emitcode ("mov","r2,%s",
12896                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12897                 emitcode ("mov","r3,%s",
12898                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12899         }
12900         freeAsmop (handle, NULL, ic, FALSE);
12901
12902         /* make the call */
12903         emitcode ("lcall","MM_UnrestrictedPersist");
12904
12905         {
12906                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12907                 if (rsym->liveFrom != rsym->liveTo) {
12908                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12909                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12910                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12911                 }
12912         }
12913         unsavermask(rsave);
12914 }
12915
12916 /*-----------------------------------------------------------------*/
12917 /* genSystemExecJavaProcess -                                      */
12918 /*-----------------------------------------------------------------*/
12919 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12920 {
12921         bitVect *rsave ;
12922         operand *handle, *pp;
12923
12924         assert (nparms==2);
12925         /* save registers that need to be saved */
12926         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12927                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12928
12929         pp = parms[0];
12930         handle = parms[1];
12931
12932         /* put the handle in R3-R2 */
12933         aopOp (handle,ic,FALSE,FALSE);
12934         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12935                 emitcode("push","%s",
12936                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12937                 emitcode("push","%s",
12938                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12939                 emitcode("pop","ar3");
12940                 emitcode("pop","ar2");
12941         } else {
12942                 emitcode ("mov","r2,%s",
12943                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12944                 emitcode ("mov","r3,%s",
12945                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12946         }
12947         freeAsmop (handle, NULL, ic, FALSE);
12948
12949         /* put pointer in DPTR */
12950         aopOp (pp,ic,FALSE,FALSE);
12951         if (AOP_TYPE(pp) == AOP_IMMD) {
12952                 emitcode ("mov", "dptr,%s",
12953                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12954         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12955                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12956                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12957                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12958         }
12959         freeAsmop (handle, NULL, ic, FALSE);
12960
12961         /* make the call */
12962         emitcode ("lcall","System_ExecJavaProcess");
12963
12964         /* put result in place */
12965         {
12966                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12967                 if (rsym->liveFrom != rsym->liveTo) {
12968                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12969                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12970                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12971                 }
12972         }
12973
12974         unsavermask(rsave);
12975 }
12976
12977 /*-----------------------------------------------------------------*/
12978 /* genSystemRTCRegisters -                                         */
12979 /*-----------------------------------------------------------------*/
12980 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12981                                   char *name)
12982 {
12983         bitVect *rsave ;
12984         operand *pp;
12985
12986         assert (nparms==1);
12987         /* save registers that need to be saved */
12988         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12989                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12990
12991         pp=parms[0];
12992         /* put pointer in DPTR */
12993         aopOp (pp,ic,FALSE,FALSE);
12994         if (AOP_TYPE (pp) == AOP_IMMD) {
12995                 emitcode ("mov","dps,#1");
12996                 emitcode ("mov", "dptr,%s",
12997                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12998                 emitcode ("mov","dps,#0");
12999         } else {
13000                 emitcode ("mov","dpl1,%s",
13001                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
13002                 emitcode ("mov","dph1,%s",
13003                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
13004                 emitcode ("mov","dpx1,%s",
13005                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
13006         }
13007         freeAsmop (pp, NULL, ic, FALSE);
13008
13009         /* make the call */
13010         emitcode ("lcall","System_%sRTCRegisters",name);
13011
13012         unsavermask(rsave);
13013 }
13014
13015 /*-----------------------------------------------------------------*/
13016 /* genSystemThreadSleep -                                          */
13017 /*-----------------------------------------------------------------*/
13018 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13019 {
13020         bitVect *rsave ;
13021         operand *to, *s;
13022
13023         assert (nparms==1);
13024         /* save registers that need to be saved */
13025         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13026                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13027
13028         to = parms[0];
13029         aopOp(to,ic,FALSE,FALSE);
13030         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13031             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13032                 emitcode ("push","%s",
13033                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13034                 emitcode ("push","%s",
13035                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13036                 emitcode ("push","%s",
13037                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13038                 emitcode ("push","%s",
13039                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13040                 emitcode ("pop","ar3");
13041                 emitcode ("pop","ar2");
13042                 emitcode ("pop","ar1");
13043                 emitcode ("pop","ar0");
13044         } else {
13045                 emitcode ("mov","r0,%s",
13046                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13047                 emitcode ("mov","r1,%s",
13048                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13049                 emitcode ("mov","r2,%s",
13050                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13051                 emitcode ("mov","r3,%s",
13052                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13053         }
13054         freeAsmop (to, NULL, ic, FALSE);
13055
13056         /* suspend in acc */
13057         s = parms[1];
13058         aopOp(s,ic,FALSE,FALSE);
13059         emitcode ("mov","a,%s",
13060                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
13061         freeAsmop (s, NULL, ic, FALSE);
13062
13063         /* make the call */
13064         emitcode ("lcall","System_%s",name);
13065
13066         unsavermask(rsave);
13067 }
13068
13069 /*-----------------------------------------------------------------*/
13070 /* genSystemThreadResume -                                         */
13071 /*-----------------------------------------------------------------*/
13072 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13073 {
13074         bitVect *rsave ;
13075         operand *tid,*pid;
13076
13077         assert (nparms==2);
13078         /* save registers that need to be saved */
13079         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13080                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13081
13082         tid = parms[0];
13083         pid = parms[1];
13084
13085         /* PID in R0 */
13086         aopOp(pid,ic,FALSE,FALSE);
13087         emitcode ("mov","r0,%s",
13088                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13089         freeAsmop (pid, NULL, ic, FALSE);
13090
13091         /* tid into ACC */
13092         aopOp(tid,ic,FALSE,FALSE);
13093         emitcode ("mov","a,%s",
13094                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13095         freeAsmop (tid, NULL, ic, FALSE);
13096
13097         emitcode ("lcall","System_ThreadResume");
13098
13099         /* put result into place */
13100         {
13101                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13102                 if (rsym->liveFrom != rsym->liveTo) {
13103                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13104                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13105                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13106                 }
13107         }
13108         unsavermask(rsave);
13109 }
13110
13111 /*-----------------------------------------------------------------*/
13112 /* genSystemProcessResume -                                        */
13113 /*-----------------------------------------------------------------*/
13114 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13115 {
13116         bitVect *rsave ;
13117         operand *pid;
13118
13119         assert (nparms==1);
13120         /* save registers that need to be saved */
13121         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13122                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13123
13124         pid = parms[0];
13125
13126         /* pid into ACC */
13127         aopOp(pid,ic,FALSE,FALSE);
13128         emitcode ("mov","a,%s",
13129                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13130         freeAsmop (pid, NULL, ic, FALSE);
13131
13132         emitcode ("lcall","System_ProcessResume");
13133
13134         unsavermask(rsave);
13135 }
13136
13137 /*-----------------------------------------------------------------*/
13138 /* genSystem -                                                     */
13139 /*-----------------------------------------------------------------*/
13140 static void genSystem (iCode *ic,int nparms,char *name)
13141 {
13142         assert(nparms == 0);
13143
13144         emitcode ("lcall","System_%s",name);
13145 }
13146
13147 /*-----------------------------------------------------------------*/
13148 /* genSystemPoll -                                                  */
13149 /*-----------------------------------------------------------------*/
13150 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13151 {
13152         bitVect *rsave ;
13153         operand *fp;
13154
13155         assert (nparms==1);
13156         /* save registers that need to be saved */
13157         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13158                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13159
13160         fp = parms[0];
13161         aopOp (fp,ic,FALSE,FALSE);
13162         if (AOP_TYPE (fp) == AOP_IMMD) {
13163                 emitcode ("mov", "dptr,%s",
13164                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13165         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13166                 emitcode ("mov","dpl,%s",
13167                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13168                 emitcode ("mov","dph,%s",
13169                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13170                 emitcode ("mov","dpx,%s",
13171                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13172         }
13173         freeAsmop (fp, NULL, ic, FALSE);
13174
13175         emitcode ("lcall","System_%sPoll",name);
13176
13177         /* put result into place */
13178         {
13179                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13180                 if (rsym->liveFrom != rsym->liveTo) {
13181                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13182                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13183                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13184                 }
13185         }
13186         unsavermask(rsave);
13187 }
13188
13189 /*-----------------------------------------------------------------*/
13190 /* genSystemGetCurrentID -                                         */
13191 /*-----------------------------------------------------------------*/
13192 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13193 {
13194         assert (nparms==0);
13195
13196         emitcode ("lcall","System_GetCurrent%sId",name);
13197         /* put result into place */
13198         {
13199                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13200                 if (rsym->liveFrom != rsym->liveTo) {
13201                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13202                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13203                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13204                 }
13205         }
13206 }
13207
13208 /*-----------------------------------------------------------------*/
13209 /* genDummyRead - generate code for dummy read of volatiles        */
13210 /*-----------------------------------------------------------------*/
13211 static void
13212 genDummyRead (iCode * ic)
13213 {
13214   operand *op;
13215   int size, offset;
13216
13217   D(emitcode(";     genDummyRead",""));
13218
13219   op = IC_RIGHT (ic);
13220   if (op && IS_SYMOP (op))
13221     {
13222       aopOp (op, ic, FALSE, FALSE);
13223
13224       /* if the result is a bit */
13225       if (AOP_TYPE (op) == AOP_CRY)
13226         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13227       else
13228         {
13229           /* bit variables done */
13230           /* general case */
13231           size = AOP_SIZE (op);
13232           offset = 0;
13233           while (size--)
13234           {
13235             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13236             offset++;
13237           }
13238         }
13239
13240       freeAsmop (op, NULL, ic, TRUE);
13241     }
13242
13243   op = IC_LEFT (ic);
13244   if (op && IS_SYMOP (op))
13245     {
13246       aopOp (op, ic, FALSE, FALSE);
13247
13248       /* if the result is a bit */
13249       if (AOP_TYPE (op) == AOP_CRY)
13250         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13251       else
13252         {
13253           /* bit variables done */
13254           /* general case */
13255           size = AOP_SIZE (op);
13256           offset = 0;
13257           while (size--)
13258           {
13259             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13260             offset++;
13261           }
13262         }
13263
13264       freeAsmop (op, NULL, ic, TRUE);
13265     }
13266
13267 }
13268
13269 /*-----------------------------------------------------------------*/
13270 /* genCritical - generate code for start of a critical sequence    */
13271 /*-----------------------------------------------------------------*/
13272 static void
13273 genCritical (iCode *ic)
13274 {
13275   symbol *tlbl = newiTempLabel (NULL);
13276
13277   D(emitcode(";     genCritical",""));
13278
13279   if (IC_RESULT (ic))
13280     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13281
13282   emitcode ("setb", "c");
13283   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13284   emitcode ("clr", "c");
13285   emitcode ("", "%05d$:", (tlbl->key + 100));
13286
13287   if (IC_RESULT (ic))
13288     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13289   else
13290     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13291
13292   if (IC_RESULT (ic))
13293     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13294 }
13295
13296 /*-----------------------------------------------------------------*/
13297 /* genEndCritical - generate code for end of a critical sequence   */
13298 /*-----------------------------------------------------------------*/
13299 static void
13300 genEndCritical (iCode *ic)
13301 {
13302   D(emitcode(";     genEndCritical",""));
13303
13304   if (IC_RIGHT (ic))
13305     {
13306       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13307       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13308         {
13309           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13310           emitcode ("mov", "ea,c");
13311         }
13312       else
13313         {
13314           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13315           emitcode ("rrc", "a");
13316           emitcode ("mov", "ea,c");
13317         }
13318       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13319     }
13320   else
13321     {
13322       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13323       emitcode ("mov", "ea,c");
13324     }
13325 }
13326
13327
13328
13329 /*-----------------------------------------------------------------*/
13330 /* genBuiltIn - calls the appropriate function to  generating code */
13331 /* for a built in function                                         */
13332 /*-----------------------------------------------------------------*/
13333 static void genBuiltIn (iCode *ic)
13334 {
13335         operand *bi_parms[MAX_BUILTIN_ARGS];
13336         int nbi_parms;
13337         iCode *bi_iCode;
13338         symbol *bif;
13339
13340         /* get all the arguments for a built in function */
13341         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13342
13343         /* which function is it */
13344         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13345         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13346                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13347         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13348                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13349         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13350                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13351         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13352                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13353         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13354                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13355         } else if (strcmp(bif->name,"__builtin_inp")==0) {
13356                 genInp(bi_iCode,nbi_parms,bi_parms);
13357         } else if (strcmp(bif->name,"__builtin_outp")==0) {
13358                 genOutp(bi_iCode,nbi_parms,bi_parms);
13359         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13360                 genSwapW(bi_iCode,nbi_parms,bi_parms);
13361                 /* JavaNative builtIns */
13362         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13363                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13364         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13365                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13366         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13367                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13368         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13369                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13370         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13371                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13372         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13373                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13374         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13375                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13376         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13377                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13378         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13379                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13380         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13381                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13382         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13383                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13384         } else if (strcmp(bif->name,"MM_Malloc")==0) {
13385                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13386         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13387                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13388         } else if (strcmp(bif->name,"MM_Free")==0) {
13389                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13390         } else if (strcmp(bif->name,"MM_Deref")==0) {
13391                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13392         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13393                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13394         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13395                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13396         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13397                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13398         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13399                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13400         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13401                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13402         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13403                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13404         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13405                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13406         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13407                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13408         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13409                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13410         } else if (strcmp(bif->name,"System_SaveThread")==0) {
13411                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13412         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13413                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13414         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13415                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13416         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13417                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13418         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13419                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13420         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13421                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13422         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13423                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13424         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13425                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13426         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13427                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13428         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13429                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13430         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13431                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13432         } else {
13433                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13434                 return ;
13435         }
13436         return ;
13437 }
13438
13439 /*-----------------------------------------------------------------*/
13440 /* gen390Code - generate code for Dallas 390 based controllers     */
13441 /*-----------------------------------------------------------------*/
13442 void
13443 gen390Code (iCode * lic)
13444 {
13445   iCode *ic;
13446   int cln = 0;
13447
13448   lineHead = lineCurr = NULL;
13449   dptrn[1][0] = "dpl1";
13450   dptrn[1][1] = "dph1";
13451   dptrn[1][2] = "dpx1";
13452
13453   if (options.model == MODEL_FLAT24) {
13454     fReturnSizeDS390 = 5;
13455     fReturn = fReturn24;
13456   } else {
13457     fReturnSizeDS390 = 4;
13458     fReturn = fReturn16;
13459     options.stack10bit=0;
13460   }
13461 #if 1
13462   /* print the allocation information */
13463   if (allocInfo && currFunc)
13464     printAllocInfo (currFunc, codeOutFile);
13465 #endif
13466   /* if debug information required */
13467   if (options.debug && currFunc)
13468     {
13469       debugFile->writeFunction (currFunc, lic);
13470     }
13471   /* stack pointer name */
13472   if (options.useXstack)
13473     spname = "_spx";
13474   else
13475     spname = "sp";
13476
13477
13478   for (ic = lic; ic; ic = ic->next)
13479     {
13480       _G.current_iCode = ic;
13481
13482       if (ic->lineno && cln != ic->lineno)
13483         {
13484           if (options.debug)
13485             {
13486               debugFile->writeCLine (ic);
13487             }
13488           if (!options.noCcodeInAsm) {
13489             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13490                       printCLine(ic->filename, ic->lineno));
13491           }
13492           cln = ic->lineno;
13493         }
13494       if (options.iCodeInAsm) {
13495         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13496       }
13497       /* if the result is marked as
13498          spilt and rematerializable or code for
13499          this has already been generated then
13500          do nothing */
13501       if (resultRemat (ic) || ic->generated)
13502         continue;
13503
13504       /* depending on the operation */
13505       switch (ic->op)
13506         {
13507         case '!':
13508           genNot (ic);
13509           break;
13510
13511         case '~':
13512           genCpl (ic);
13513           break;
13514
13515         case UNARYMINUS:
13516           genUminus (ic);
13517           break;
13518
13519         case IPUSH:
13520           genIpush (ic);
13521           break;
13522
13523         case IPOP:
13524           /* IPOP happens only when trying to restore a
13525              spilt live range, if there is an ifx statement
13526              following this pop then the if statement might
13527              be using some of the registers being popped which
13528              would destory the contents of the register so
13529              we need to check for this condition and handle it */
13530           if (ic->next &&
13531               ic->next->op == IFX &&
13532               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13533             genIfx (ic->next, ic);
13534           else
13535             genIpop (ic);
13536           break;
13537
13538         case CALL:
13539           genCall (ic);
13540           break;
13541
13542         case PCALL:
13543           genPcall (ic);
13544           break;
13545
13546         case FUNCTION:
13547           genFunction (ic);
13548           break;
13549
13550         case ENDFUNCTION:
13551           genEndFunction (ic);
13552           break;
13553
13554         case RETURN:
13555           genRet (ic);
13556           break;
13557
13558         case LABEL:
13559           genLabel (ic);
13560           break;
13561
13562         case GOTO:
13563           genGoto (ic);
13564           break;
13565
13566         case '+':
13567           genPlus (ic);
13568           break;
13569
13570         case '-':
13571           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13572             genMinus (ic);
13573           break;
13574
13575         case '*':
13576           genMult (ic);
13577           break;
13578
13579         case '/':
13580           genDiv (ic);
13581           break;
13582
13583         case '%':
13584           genMod (ic);
13585           break;
13586
13587         case '>':
13588           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13589           break;
13590
13591         case '<':
13592           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13593           break;
13594
13595         case LE_OP:
13596         case GE_OP:
13597         case NE_OP:
13598
13599           /* note these two are xlated by algebraic equivalence
13600              during parsing SDCC.y */
13601           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13602                   "got '>=' or '<=' shouldn't have come here");
13603           break;
13604
13605         case EQ_OP:
13606           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13607           break;
13608
13609         case AND_OP:
13610           genAndOp (ic);
13611           break;
13612
13613         case OR_OP:
13614           genOrOp (ic);
13615           break;
13616
13617         case '^':
13618           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13619           break;
13620
13621         case '|':
13622           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13623           break;
13624
13625         case BITWISEAND:
13626           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13627           break;
13628
13629         case INLINEASM:
13630           genInline (ic);
13631           break;
13632
13633         case RRC:
13634           genRRC (ic);
13635           break;
13636
13637         case RLC:
13638           genRLC (ic);
13639           break;
13640
13641         case GETHBIT:
13642           genGetHbit (ic);
13643           break;
13644
13645         case LEFT_OP:
13646           genLeftShift (ic);
13647           break;
13648
13649         case RIGHT_OP:
13650           genRightShift (ic);
13651           break;
13652
13653         case GET_VALUE_AT_ADDRESS:
13654           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13655           break;
13656
13657         case '=':
13658           if (POINTER_SET (ic))
13659             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13660           else
13661             genAssign (ic);
13662           break;
13663
13664         case IFX:
13665           genIfx (ic, NULL);
13666           break;
13667
13668         case ADDRESS_OF:
13669           genAddrOf (ic);
13670           break;
13671
13672         case JUMPTABLE:
13673           genJumpTab (ic);
13674           break;
13675
13676         case CAST:
13677           genCast (ic);
13678           break;
13679
13680         case RECEIVE:
13681           genReceive (ic);
13682           break;
13683
13684         case SEND:
13685           if (ic->builtinSEND) genBuiltIn(ic);
13686           else addSet (&_G.sendSet, ic);
13687           break;
13688
13689         case DUMMY_READ_VOLATILE:
13690           genDummyRead (ic);
13691           break;
13692
13693         case CRITICAL:
13694           genCritical (ic);
13695           break;
13696
13697         case ENDCRITICAL:
13698           genEndCritical (ic);
13699           break;
13700
13701         case SWAP:
13702           genSwap (ic);
13703           break;
13704
13705 #if 0 // obsolete, and buggy for != xdata
13706         case ARRAYINIT:
13707             genArrayInit(ic);
13708             break;
13709 #endif
13710
13711         default:
13712           ic = ic;
13713         }
13714     }
13715
13716
13717   /* now we are ready to call the
13718      peep hole optimizer */
13719   if (!options.nopeep)
13720     peepHole (&lineHead);
13721
13722   /* now do the actual printing */
13723   printLine (lineHead, codeOutFile);
13724   return;
13725 }