fix genMinus aopPut out-of-range bug
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for 8051
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   
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12   
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17   
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21   
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25   
26   Notes:
27   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
28                 Made everything static
29 -------------------------------------------------------------------------*/
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "SDCCglobl.h"
36
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
39 #else
40 #ifdef HAVE_ENDIAN_H
41 #include <endian.h>
42 #else
43 #ifndef __BORLANDC__
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
46 #endif
47 #endif
48 #endif
49
50 #include "common.h"
51 #include "SDCCpeeph.h"
52 #include "ralloc.h"
53 #include "gen.h"
54
55 char *aopLiteral (value *val, int offset);
56 extern int allocInfo;
57
58 /* this is the down and dirty file with all kinds of 
59    kludgy & hacky stuff. This is what it is all about
60    CODE GENERATION for a specific MCU . some of the
61    routines may be reusable, will have to see */
62
63 static char *zero = "#0x00";
64 static char *one  = "#0x01";
65 static char *spname ;
66
67 #define D(x) x
68
69 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
70 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
71 static char *accUse[] = {"a","b"};
72
73 static short rbank = -1;
74
75 static struct {
76     short r0Pushed;
77     short r1Pushed;
78     short accInUse;
79     short inLine;
80     short debugLine;
81     short nRegsSaved;
82     set *sendSet;
83 } _G;
84
85 extern int ds390_ptrRegReq ;
86 extern int ds390_nRegs;
87 extern FILE *codeOutFile;
88 static void saverbank (int, iCode *,bool);
89 #define RESULTONSTACK(x) \
90                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
91                          IC_RESULT(x)->aop->type == AOP_STK )
92
93 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
94 #define MOVA(x) { char *_mova_tmp = strdup(x); \
95                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
96                  { \
97                     emitcode("mov","a,%s",_mova_tmp); \
98                  } \
99                  free(_mova_tmp); \
100                 }
101 #define CLRC    emitcode("clr","c")
102 #define SETC    emitcode("setb","c")
103
104 static lineNode *lineHead = NULL;
105 static lineNode *lineCurr = NULL;
106
107 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
108 0xE0, 0xC0, 0x80, 0x00};
109 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
110 0x07, 0x03, 0x01, 0x00};
111
112 #define LSB     0
113 #define MSB16   1
114 #define MSB24   2
115 #define MSB32   3
116
117 /*-----------------------------------------------------------------*/
118 /* emitcode - writes the code into a file : for now it is simple    */
119 /*-----------------------------------------------------------------*/
120 static void emitcode (char *inst,char *fmt, ...)
121 {
122     va_list ap;
123     char lb[MAX_INLINEASM];  
124     char *lbp = lb;
125
126     va_start(ap,fmt);   
127
128     if (inst && *inst) {
129         if (fmt && *fmt)
130             sprintf(lb,"%s\t",inst);
131         else
132             sprintf(lb,"%s",inst);
133         vsprintf(lb+(strlen(lb)),fmt,ap);
134     }  else
135         vsprintf(lb,fmt,ap);
136
137     while (isspace(*lbp)) lbp++;
138
139     if (lbp && *lbp) 
140         lineCurr = (lineCurr ?
141                     connectLine(lineCurr,newLineNode(lb)) :
142                     (lineHead = newLineNode(lb)));
143     lineCurr->isInline = _G.inLine;
144     lineCurr->isDebug  = _G.debugLine;
145     va_end(ap);
146 }
147
148 /*-----------------------------------------------------------------*/
149 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
150 /*-----------------------------------------------------------------*/
151 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
152 {
153     bool r0iu = FALSE , r1iu = FALSE;
154     bool r0ou = FALSE , r1ou = FALSE;
155
156     /* the logic: if r0 & r1 used in the instruction
157     then we are in trouble otherwise */
158
159     /* first check if r0 & r1 are used by this
160     instruction, in which case we are in trouble */
161     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
162         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
163     {
164         goto endOfWorld;      
165     }
166
167     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
168     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
169
170     /* if no usage of r0 then return it */
171     if (!r0iu && !r0ou) {
172         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
173         (*aopp)->type = AOP_R0;
174         
175         return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
176     }
177
178     /* if no usage of r1 then return it */
179     if (!r1iu && !r1ou) {
180         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
181         (*aopp)->type = AOP_R1;
182
183         return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
184     }    
185
186     /* now we know they both have usage */
187     /* if r0 not used in this instruction */
188     if (!r0iu) {
189         /* push it if not already pushed */
190         if (!_G.r0Pushed) {
191             emitcode ("push","%s",
192                       ds390_regWithIdx(R0_IDX)->dname);
193             _G.r0Pushed++ ;
194         }
195         
196         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
197         (*aopp)->type = AOP_R0;
198
199         return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
200     }
201
202     /* if r1 not used then */
203
204     if (!r1iu) {
205         /* push it if not already pushed */
206         if (!_G.r1Pushed) {
207             emitcode ("push","%s",
208                       ds390_regWithIdx(R1_IDX)->dname);
209             _G.r1Pushed++ ;
210         }
211         
212         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
213         (*aopp)->type = AOP_R1;
214         return ds390_regWithIdx(R1_IDX);
215     }
216
217 endOfWorld :
218     /* I said end of world but not quite end of world yet */
219     /* if this is a result then we can push it on the stack*/
220     if (result) {
221         (*aopp)->type = AOP_STK;    
222         return NULL;
223     }
224
225     piCode(ic,stdout);
226     /* other wise this is true end of the world */
227     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
228            "getFreePtr should never reach here");
229     exit(1);
230 }
231
232 /*-----------------------------------------------------------------*/
233 /* newAsmop - creates a new asmOp                                  */
234 /*-----------------------------------------------------------------*/
235 static asmop *newAsmop (short type)
236 {
237     asmop *aop;
238
239     ALLOC(aop,sizeof(asmop));
240     aop->type = type;
241     return aop;
242 }
243
244 static void genSetDPTR(int n)
245 {
246     if (!n)
247     {
248         emitcode("mov", "dps, #0x00");
249     }
250     else
251     {
252         emitcode("mov", "dps, #0x01");
253     }
254 }
255
256 /*-----------------------------------------------------------------*/
257 /* pointerCode - returns the code for a pointer type               */
258 /*-----------------------------------------------------------------*/
259 static int pointerCode (link *etype)
260 {
261
262     return PTR_TYPE(SPEC_OCLS(etype));
263
264 }
265
266 /*-----------------------------------------------------------------*/
267 /* aopForSym - for a true symbol                                   */
268 /*-----------------------------------------------------------------*/
269 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
270 {
271     asmop *aop;
272     memmap *space= SPEC_OCLS(sym->etype);
273
274     /* if already has one */
275     if (sym->aop)
276         return sym->aop;
277
278     /* assign depending on the storage class */
279     /* if it is on the stack or indirectly addressable */
280     /* space we need to assign either r0 or r1 to it   */    
281     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
282         sym->aop = aop = newAsmop(0);
283         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
284         aop->size = getSize(sym->type);
285
286         /* now assign the address of the variable to 
287         the pointer register */
288         if (aop->type != AOP_STK) {
289
290             if (sym->onStack) {
291                     if ( _G.accInUse )
292                         emitcode("push","acc");
293
294                     emitcode("mov","a,_bp");
295                     emitcode("add","a,#0x%02x",
296                              ((sym->stack < 0) ?
297                               ((char)(sym->stack - _G.nRegsSaved )) :
298                               ((char)sym->stack)) & 0xff);
299                     emitcode("mov","%s,a",
300                              aop->aopu.aop_ptr->name);
301
302                     if ( _G.accInUse )
303                         emitcode("pop","acc");
304             } else
305                 emitcode("mov","%s,#%s",
306                          aop->aopu.aop_ptr->name,
307                          sym->rname);
308             aop->paged = space->paged;
309         } else
310             aop->aopu.aop_stk = sym->stack;
311         return aop;
312     }
313     
314     if (sym->onStack && options.stack10bit)
315     {
316         /* It's on the 10 bit stack, which is located in
317          * far data space.
318          */
319          
320         if ( _G.accInUse )
321                 emitcode("push","acc");
322
323         emitcode("mov","a,_bp");
324         emitcode("add","a,#0x%02x",
325                  ((sym->stack < 0) ?
326                    ((char)(sym->stack - _G.nRegsSaved )) :
327                    ((char)sym->stack)) & 0xff);
328         
329         if (useDP2)
330         {        
331         genSetDPTR(1);
332         emitcode ("mov","dpx1,#0x40");
333         emitcode ("mov","dph1,#0x00");
334         emitcode ("mov","dpl1, a");
335         genSetDPTR(0);
336         }
337         else
338         {
339             emitcode ("mov","dpx,#0x40");
340             emitcode ("mov","dph,#0x00");
341             emitcode ("mov","dpl, a");           
342         }
343         
344         if ( _G.accInUse )
345             emitcode("pop","acc");
346             
347         sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
348         aop->size = getSize(sym->type); 
349         return aop;
350     }
351
352     /* if in bit space */
353     if (IN_BITSPACE(space)) {
354         sym->aop = aop = newAsmop (AOP_CRY);
355         aop->aopu.aop_dir = sym->rname ;
356         aop->size = getSize(sym->type);
357         return aop;
358     }
359     /* if it is in direct space */
360     if (IN_DIRSPACE(space)) {
361         sym->aop = aop = newAsmop (AOP_DIR);
362         aop->aopu.aop_dir = sym->rname ;
363         aop->size = getSize(sym->type);
364         return aop;
365     }
366
367     /* special case for a function */
368     if (IS_FUNC(sym->type)) {   
369         sym->aop = aop = newAsmop(AOP_IMMD);    
370         ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
371         strcpy(aop->aopu.aop_immd,sym->rname);
372         aop->size = FPTRSIZE; 
373         return aop;
374     }
375
376     /* only remaining is far space */
377     /* in which case DPTR gets the address */
378     sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
379     if (useDP2)
380     {        
381         genSetDPTR(1);
382     emitcode ("mov","dptr,#%s", sym->rname);
383         genSetDPTR(0);
384     }    
385     else
386     {
387         emitcode ("mov","dptr,#%s", sym->rname);
388     }
389     aop->size = getSize(sym->type);
390
391     /* if it is in code space */
392     if (IN_CODESPACE(space))
393         aop->code = 1;
394
395     return aop;     
396 }
397
398 /*-----------------------------------------------------------------*/
399 /* aopForRemat - rematerialzes an object                           */
400 /*-----------------------------------------------------------------*/
401 static asmop *aopForRemat (symbol *sym)
402 {
403     iCode *ic = sym->rematiCode;
404     asmop *aop = newAsmop(AOP_IMMD);
405
406     int val = 0;
407
408     for (;;) {
409         if (ic->op == '+')
410             val += operandLitValue(IC_RIGHT(ic));
411         else if (ic->op == '-')
412             val -= operandLitValue(IC_RIGHT(ic));
413         else
414             break;
415         
416         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
417     }
418
419     if (val)
420         sprintf(buffer,"(%s %c 0x%04x)",
421                 OP_SYMBOL(IC_LEFT(ic))->rname, 
422                 val >= 0 ? '+' : '-',
423                 abs(val) & 0xffff);
424     else
425         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
426
427     ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
428     strcpy(aop->aopu.aop_immd,buffer);    
429     return aop;        
430 }
431
432 /*-----------------------------------------------------------------*/
433 /* regsInCommon - two operands have some registers in common       */
434 /*-----------------------------------------------------------------*/
435 static bool regsInCommon (operand *op1, operand *op2)
436 {
437     symbol *sym1, *sym2;
438     int i;
439
440     /* if they have registers in common */
441     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
442         return FALSE ;
443
444     sym1 = OP_SYMBOL(op1);
445     sym2 = OP_SYMBOL(op2);
446
447     if (sym1->nRegs == 0 || sym2->nRegs == 0)
448         return FALSE ;
449
450     for (i = 0 ; i < sym1->nRegs ; i++) {
451         int j;
452         if (!sym1->regs[i])
453             continue ;
454
455         for (j = 0 ; j < sym2->nRegs ;j++ ) {
456             if (!sym2->regs[j])
457                 continue ;
458
459             if (sym2->regs[j] == sym1->regs[i])
460                 return TRUE ;
461         }
462     }
463
464     return FALSE ;
465 }
466
467 /*-----------------------------------------------------------------*/
468 /* operandsEqu - equivalent                                        */
469 /*-----------------------------------------------------------------*/
470 static bool operandsEqu ( operand *op1, operand *op2)
471 {
472     symbol *sym1, *sym2;
473
474     /* if they not symbols */
475     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
476         return FALSE;
477
478     sym1 = OP_SYMBOL(op1);
479     sym2 = OP_SYMBOL(op2);
480
481     /* if both are itemps & one is spilt
482        and the other is not then false */
483     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
484         sym1->isspilt != sym2->isspilt )
485         return FALSE ;
486
487     /* if they are the same */
488     if (sym1 == sym2)
489         return TRUE ;
490
491     if (strcmp(sym1->rname,sym2->rname) == 0)
492         return TRUE;
493
494
495     /* if left is a tmp & right is not */
496     if (IS_ITEMP(op1)  && 
497         !IS_ITEMP(op2) &&
498         sym1->isspilt  &&
499         (sym1->usl.spillLoc == sym2))
500         return TRUE;
501
502     if (IS_ITEMP(op2)  && 
503         !IS_ITEMP(op1) &&
504         sym2->isspilt  &&
505         sym1->level > 0 &&
506         (sym2->usl.spillLoc == sym1))
507         return TRUE ;
508
509     return FALSE ;
510 }
511
512 /*-----------------------------------------------------------------*/
513 /* sameRegs - two asmops have the same registers                   */
514 /*-----------------------------------------------------------------*/
515 static bool sameRegs (asmop *aop1, asmop *aop2 )
516 {
517     int i;
518
519     if (aop1 == aop2)
520     {
521         if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
522         {
523             return FALSE;
524         }
525         return TRUE ;
526     }
527
528     if (aop1->type != AOP_REG ||
529         aop2->type != AOP_REG )
530         return FALSE ;
531
532     if (aop1->size != aop2->size )
533         return FALSE ;
534
535     for (i = 0 ; i < aop1->size ; i++ )
536         if (aop1->aopu.aop_reg[i] !=
537             aop2->aopu.aop_reg[i] )
538             return FALSE ;
539
540     return TRUE ;
541 }
542
543 /*-----------------------------------------------------------------*/
544 /* aopOp - allocates an asmop for an operand  :                    */
545 /*-----------------------------------------------------------------*/
546 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
547 {
548     asmop *aop;
549     symbol *sym;
550     int i;
551
552     if (!op)
553         return ;
554
555     /* if this a literal */
556     if (IS_OP_LITERAL(op)) {
557         op->aop = aop = newAsmop(AOP_LIT);
558         aop->aopu.aop_lit = op->operand.valOperand;
559         aop->size = getSize(operandType(op));
560         return;
561     }
562
563     /* if already has a asmop then continue */
564     if (op->aop)
565         return ;
566
567     /* if the underlying symbol has a aop */
568     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
569         op->aop = OP_SYMBOL(op)->aop;
570         return;
571     }
572
573     /* if this is a true symbol */
574     if (IS_TRUE_SYMOP(op)) {    
575         op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
576         return ;
577     }
578
579     /* this is a temporary : this has
580     only four choices :
581     a) register
582     b) spillocation
583     c) rematerialize 
584     d) conditional   
585     e) can be a return use only */
586
587     sym = OP_SYMBOL(op);
588
589
590     /* if the type is a conditional */
591     if (sym->regType == REG_CND) {
592         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
593         aop->size = 0;
594         return;
595     }
596
597     /* if it is spilt then two situations
598     a) is rematerialize 
599     b) has a spill location */
600     if (sym->isspilt || sym->nRegs == 0) {
601
602         /* rematerialize it NOW */
603         if (sym->remat) {
604             sym->aop = op->aop = aop =
605                                       aopForRemat (sym);
606             aop->size = getSize(sym->type);
607             return;
608         }
609
610         if (sym->accuse) {
611             int i;
612             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
613             aop->size = getSize(sym->type);
614             for ( i = 0 ; i < 2 ; i++ )
615                 aop->aopu.aop_str[i] = accUse[i];
616             return;  
617         }
618
619         if (sym->ruonly ) {
620             int i;
621             aop = op->aop = sym->aop = newAsmop(AOP_STR);
622             aop->size = getSize(sym->type);
623             for ( i = 0 ; i < fReturnSize_390 ; i++ )
624                 aop->aopu.aop_str[i] = fReturn[i];
625             return;
626         }
627
628         /* else spill location  */
629         sym->aop = op->aop = aop = 
630                 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
631         aop->size = getSize(sym->type);
632         return;
633     }
634
635     /* must be in a register */
636     sym->aop = op->aop = aop = newAsmop(AOP_REG);
637     aop->size = sym->nRegs;
638     for ( i = 0 ; i < sym->nRegs ;i++)
639         aop->aopu.aop_reg[i] = sym->regs[i];
640 }
641
642 /*-----------------------------------------------------------------*/
643 /* freeAsmop - free up the asmop given to an operand               */
644 /*----------------------------------------------------------------*/
645 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
646 {   
647     asmop *aop ;
648
649     if (!op)
650         aop = aaop;
651     else 
652         aop = op->aop;
653
654     if (!aop)
655         return ;
656
657     if (aop->freed)
658         goto dealloc; 
659
660     aop->freed = 1;
661
662     /* depending on the asmop type only three cases need work AOP_RO
663        , AOP_R1 && AOP_STK */
664     switch (aop->type) {
665         case AOP_R0 :
666             if (_G.r0Pushed ) {
667                 if (pop) {
668                     emitcode ("pop","ar0");     
669                     _G.r0Pushed--;
670                 }
671             }
672             bitVectUnSetBit(ic->rUsed,R0_IDX);
673             break;
674
675         case AOP_R1 :
676             if (_G.r1Pushed ) {
677                 if (pop) {
678                     emitcode ("pop","ar1");
679                     _G.r1Pushed--;
680                 }
681             }
682             bitVectUnSetBit(ic->rUsed,R1_IDX);          
683             break;
684
685         case AOP_STK :
686         {
687             int sz = aop->size;    
688             int stk = aop->aopu.aop_stk + aop->size;
689             bitVectUnSetBit(ic->rUsed,R0_IDX);
690             bitVectUnSetBit(ic->rUsed,R1_IDX);          
691
692             getFreePtr(ic,&aop,FALSE);
693             
694             if (options.stack10bit)
695             {
696                 /* I'm not sure what to do here yet... */
697                 /* #STUB */
698                 fprintf(stderr, 
699                         "*** Warning: probably generating bad code for "
700                         "10 bit stack mode.\n");
701             }
702             
703             if (stk) {
704                 emitcode ("mov","a,_bp");
705                 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
706                 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
707             } else {
708                 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
709             }
710
711             while (sz--) {
712                 emitcode("pop","acc");
713                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
714                 if (!sz) break;
715                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
716             }
717             op->aop = aop;
718             freeAsmop(op,NULL,ic,TRUE);
719             if (_G.r0Pushed) {
720                 emitcode("pop","ar0");
721                 _G.r0Pushed--;
722             }
723
724             if (_G.r1Pushed) {
725                 emitcode("pop","ar1");
726                 _G.r1Pushed--;
727             }       
728         }
729     }
730
731 dealloc:
732     /* all other cases just dealloc */
733     if (op ) {
734         op->aop = NULL;
735         if (IS_SYMOP(op)) {
736             OP_SYMBOL(op)->aop = NULL;    
737             /* if the symbol has a spill */
738             if (SPIL_LOC(op))
739                 SPIL_LOC(op)->aop = NULL;
740         }
741     }
742 }
743
744 /*------------------------------------------------------------------*/
745 /* aopGet - for fetching value of the aop                           */
746 /*                                                                  */
747 /* Set canClobberACC if you are aure it is OK to clobber the value  */
748 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
749 /* just less efficient.                                             */
750 /*------------------------------------------------------------------*/
751
752 static char *aopGet (asmop *aop, 
753                      int offset, 
754                      bool bit16,
755                      bool dname,
756                      bool canClobberACC)
757 {
758     char *s = buffer ;
759     char *rs;
760
761     /* offset is greater than
762     size then zero */
763     if (offset > (aop->size - 1) &&
764         aop->type != AOP_LIT)
765         return zero;
766
767     /* depending on type */
768     switch (aop->type) {
769         
770     case AOP_R0:
771     case AOP_R1:
772         /* if we need to increment it */       
773         while (offset > aop->coff) {        
774             emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
775             aop->coff++;
776         }
777         
778         while (offset < aop->coff) {
779             emitcode("dec","%s",aop->aopu.aop_ptr->name);
780             aop->coff--;
781         }
782         
783         aop->coff = offset ;
784         if (aop->paged) {
785             emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
786             return (dname ? "acc" : "a");
787         }       
788         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
789         ALLOC_ATOMIC(rs,strlen(s)+1);
790         strcpy(rs,s);   
791         return rs;
792         
793     case AOP_DPTR:
794     case AOP_DPTR2:
795     
796     if (aop->type == AOP_DPTR2)
797     {
798         genSetDPTR(1);
799         
800 #ifndef KEVIN_BROKE_IT        
801         if (!canClobberACC)
802 #endif        
803         {
804             emitcode("xch", "a, ap");
805         }
806     }
807     
808         while (offset > aop->coff) {
809             emitcode ("inc","dptr");
810             aop->coff++;
811         }
812         
813         while (offset < aop->coff) {        
814             emitcode("lcall","__decdptr");
815             aop->coff--;
816         }
817         
818         aop->coff = offset;
819         if (aop->code) {
820             emitcode("clr","a");
821             emitcode("movc","a,@a+dptr");
822         }
823     else {
824             emitcode("movx","a,@dptr");
825     }
826             
827     if (aop->type == AOP_DPTR2)
828     {
829         genSetDPTR(0);
830
831 #ifndef KEVIN_BROKE_IT        
832         if (!canClobberACC)
833 #endif        
834         {
835             emitcode("xch", "a, ap");
836             return "ap";
837         }
838     }
839             
840     return (dname ? "acc" : "a");
841         
842         
843     case AOP_IMMD:
844         if (bit16) 
845             sprintf (s,"#%s",aop->aopu.aop_immd);
846         else
847             if (offset) 
848                 sprintf(s,"#(%s >> %d)",
849                         aop->aopu.aop_immd,
850                         offset*8);
851             else
852                 sprintf(s,"#%s",
853                         aop->aopu.aop_immd);
854         ALLOC_ATOMIC(rs,strlen(s)+1);
855         strcpy(rs,s);   
856         return rs;
857         
858     case AOP_DIR:
859         if (offset)
860             sprintf(s,"(%s + %d)",
861                     aop->aopu.aop_dir,
862                     offset);
863         else
864             sprintf(s,"%s",aop->aopu.aop_dir);
865         ALLOC_ATOMIC(rs,strlen(s)+1);
866         strcpy(rs,s);   
867         return rs;
868         
869     case AOP_REG:
870         if (dname) 
871             return aop->aopu.aop_reg[offset]->dname;
872         else
873             return aop->aopu.aop_reg[offset]->name;
874         
875     case AOP_CRY:
876         emitcode("clr","a");
877         emitcode("mov","c,%s",aop->aopu.aop_dir);
878         emitcode("rlc","a") ;
879         return (dname ? "acc" : "a");
880         
881     case AOP_ACC:
882         if (!offset && dname)
883             return "acc";
884         return aop->aopu.aop_str[offset];
885
886     case AOP_LIT:
887         return aopLiteral (aop->aopu.aop_lit,offset);
888         
889     case AOP_STR:
890         aop->coff = offset ;
891         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
892             dname)
893             return "acc";
894         
895         return aop->aopu.aop_str[offset];
896         
897     }
898
899     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
900            "aopget got unsupported aop->type");
901     exit(1);
902 }
903 /*-----------------------------------------------------------------*/
904 /* aopPut - puts a string for a aop                                */
905 /*-----------------------------------------------------------------*/
906 static void aopPut (asmop *aop, char *s, int offset)
907 {
908     char *d = buffer ;
909     symbol *lbl ;
910
911     if (aop->size && offset > ( aop->size - 1)) {
912         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
913                "aopPut got offset > aop->size");
914         exit(1);
915     }
916
917     /* will assign value to value */
918     /* depending on where it is ofcourse */
919     switch (aop->type) {
920     case AOP_DIR:
921         if (offset)
922             sprintf(d,"(%s + %d)",
923                     aop->aopu.aop_dir,offset);
924         else
925             sprintf(d,"%s",aop->aopu.aop_dir);
926         
927         if (strcmp(d,s))
928             emitcode("mov","%s,%s",d,s);
929         
930         break;
931         
932     case AOP_REG:
933         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
934             strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
935             if (*s == '@'           ||
936                 strcmp(s,"r0") == 0 ||
937                 strcmp(s,"r1") == 0 ||
938                 strcmp(s,"r2") == 0 ||
939                 strcmp(s,"r3") == 0 ||
940                 strcmp(s,"r4") == 0 ||
941                 strcmp(s,"r5") == 0 ||
942                 strcmp(s,"r6") == 0 || 
943                 strcmp(s,"r7") == 0 )
944                 emitcode("mov","%s,%s",
945                          aop->aopu.aop_reg[offset]->dname,s);
946             else
947                 emitcode("mov","%s,%s",
948                          aop->aopu.aop_reg[offset]->name,s);
949         }
950         break;
951         
952     case AOP_DPTR:
953     case AOP_DPTR2:
954     
955     if (aop->type == AOP_DPTR2)
956     {
957         genSetDPTR(1);
958     }
959     
960         if (aop->code) {
961             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
962                    "aopPut writting to code space");
963             exit(1);
964         }
965         
966         while (offset > aop->coff) {
967             aop->coff++;
968             emitcode ("inc","dptr");
969         }
970         
971         while (offset < aop->coff) {
972             aop->coff-- ;
973             emitcode("lcall","__decdptr");
974         }
975         
976         aop->coff = offset;
977         
978         /* if not in accumulater */
979         MOVA(s);        
980         
981         emitcode ("movx","@dptr,a");
982         
983     if (aop->type == AOP_DPTR2)
984     {
985         genSetDPTR(0);
986     }
987         break;
988         
989     case AOP_R0:
990     case AOP_R1:
991         while (offset > aop->coff) {
992             aop->coff++;
993             emitcode("inc","%s",aop->aopu.aop_ptr->name);
994         }
995         while (offset < aop->coff) {
996             aop->coff-- ;
997             emitcode ("dec","%s",aop->aopu.aop_ptr->name);
998         }
999         aop->coff = offset;
1000         
1001         if (aop->paged) {
1002             MOVA(s);           
1003             emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1004             
1005         } else
1006             if (*s == '@') {
1007                 MOVA(s);
1008                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1009             } else
1010                 if (strcmp(s,"r0") == 0 ||
1011                     strcmp(s,"r1") == 0 ||
1012                     strcmp(s,"r2") == 0 ||
1013                     strcmp(s,"r3") == 0 ||
1014                     strcmp(s,"r4") == 0 ||
1015                     strcmp(s,"r5") == 0 ||
1016                     strcmp(s,"r6") == 0 || 
1017                     strcmp(s,"r7") == 0 ) {
1018                     char buffer[10];
1019                     sprintf(buffer,"a%s",s);
1020                     emitcode("mov","@%s,%s",
1021                              aop->aopu.aop_ptr->name,buffer);
1022                 } else
1023                     emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1024         
1025         break;
1026         
1027     case AOP_STK:
1028         if (strcmp(s,"a") == 0)
1029             emitcode("push","acc");
1030         else
1031             emitcode("push","%s",s);
1032         
1033         break;
1034         
1035     case AOP_CRY:
1036         /* if bit variable */
1037         if (!aop->aopu.aop_dir) {
1038             emitcode("clr","a");
1039             emitcode("rlc","a");
1040         } else {
1041             if (s == zero) 
1042                 emitcode("clr","%s",aop->aopu.aop_dir);
1043             else
1044                 if (s == one)
1045                     emitcode("setb","%s",aop->aopu.aop_dir);
1046                 else
1047                     if (!strcmp(s,"c"))
1048                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1049                     else {
1050                         lbl = newiTempLabel(NULL);
1051                         
1052                         if (strcmp(s,"a")) {
1053                             MOVA(s);
1054                         }
1055                         emitcode("clr","c");
1056                         emitcode("jz","%05d$",lbl->key+100);
1057                         emitcode("cpl","c");
1058                         emitcode("","%05d$:",lbl->key+100);
1059                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1060                     }
1061         }
1062         break;
1063         
1064     case AOP_STR:
1065         aop->coff = offset;
1066         if (strcmp(aop->aopu.aop_str[offset],s))
1067             emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1068         break;
1069         
1070     case AOP_ACC:
1071         aop->coff = offset;
1072         if (!offset && (strcmp(s,"acc") == 0))
1073             break;
1074         
1075         if (strcmp(aop->aopu.aop_str[offset],s))
1076             emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1077         break;
1078
1079     default :
1080         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1081                "aopPut got unsupported aop->type");
1082         exit(1);    
1083     }    
1084
1085 }
1086
1087
1088 #if 0
1089 /*-----------------------------------------------------------------*/
1090 /* pointToEnd :- points to the last byte of the operand            */
1091 /*-----------------------------------------------------------------*/
1092 static void pointToEnd (asmop *aop)
1093 {
1094     int count ;
1095     if (!aop)
1096         return ;
1097
1098     aop->coff = count = (aop->size - 1);
1099     switch (aop->type) {
1100         case AOP_R0 :
1101         case AOP_R1 :
1102             while (count--)
1103                 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1104             break;
1105         case AOP_DPTR :
1106             while (count--)
1107                 emitcode("inc","dptr");
1108             break;
1109     }
1110
1111 }
1112 #endif
1113
1114 /*-----------------------------------------------------------------*/
1115 /* reAdjustPreg - points a register back to where it should        */
1116 /*-----------------------------------------------------------------*/
1117 static void reAdjustPreg (asmop *aop)
1118 {
1119     int size ;
1120
1121     aop->coff = 0;
1122     if ((size = aop->size) <= 1)
1123         return ;
1124     size-- ;
1125     switch (aop->type) {
1126         case AOP_R0 :
1127         case AOP_R1 :
1128             while (size--)
1129                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1130             break;          
1131         case AOP_DPTR :
1132         case AOP_DPTR2:
1133             if (aop->type == AOP_DPTR2)
1134             {
1135                 genSetDPTR(1);
1136             } 
1137             while (size--)
1138             {
1139                 emitcode("lcall","__decdptr");
1140             }
1141                 
1142             if (aop->type == AOP_DPTR2)
1143             {
1144                 genSetDPTR(0);
1145             }                
1146             break;  
1147
1148     }   
1149
1150 }
1151
1152 #define AOP(op) op->aop
1153 #define AOP_TYPE(op) AOP(op)->type
1154 #define AOP_SIZE(op) AOP(op)->size
1155 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1156                        AOP_TYPE(x) == AOP_R0))
1157
1158 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1159                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1160                          AOP(x)->paged)) 
1161
1162 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1163                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1164                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1165
1166 /* Workaround for DS80C390 bug: div ab may return bogus results
1167  * if A is accessed in instruction immediately before the div.
1168  *
1169  * Will be fixed in B4 rev of processor, Dallas claims.
1170  */
1171  
1172 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)                         \
1173     if (!AOP_NEEDSACC(RIGHT))                                   \
1174     {                                                           \
1175         /* We can load A first, then B, since                   \
1176          * B (the RIGHT operand) won't clobber A,               \
1177          * thus avoiding touching A right before the div.       \
1178          */                                                     \
1179         D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1180         L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);               \
1181         MOVA(L);                                                \
1182         emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1183     }                                                           \
1184     else                                                        \
1185     {                                                           \
1186         /* Just stuff in a nop after loading A. */              \
1187         emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1188         L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);               \
1189         MOVA(L);                                                \
1190         emitcode("nop", "; workaround for DS80C390 div bug.");  \
1191     }
1192
1193 /*-----------------------------------------------------------------*/
1194 /* genNotFloat - generates not for float operations              */
1195 /*-----------------------------------------------------------------*/
1196 static void genNotFloat (operand *op, operand *res)
1197 {
1198     int size, offset;
1199     char *l;
1200     symbol *tlbl ;
1201
1202     D(emitcode(";", "genNotFloat "););
1203
1204     /* we will put 127 in the first byte of 
1205     the result */
1206     aopPut(AOP(res),"#127",0);
1207     size = AOP_SIZE(op) - 1;
1208     offset = 1;
1209
1210     l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1211     MOVA(l);    
1212
1213     while(size--) {
1214         emitcode("orl","a,%s",
1215                  aopGet(op->aop,
1216                         offset++,FALSE,FALSE,FALSE));
1217     }
1218     tlbl = newiTempLabel(NULL);
1219
1220     tlbl = newiTempLabel(NULL);
1221     aopPut(res->aop,one,1);
1222     emitcode("jz","%05d$",(tlbl->key+100));
1223     aopPut(res->aop,zero,1);
1224     emitcode("","%05d$:",(tlbl->key+100));
1225
1226     size = res->aop->size - 2;
1227     offset = 2;    
1228     /* put zeros in the rest */
1229     while (size--) 
1230         aopPut(res->aop,zero,offset++);
1231 }
1232
1233 /*-----------------------------------------------------------------*/
1234 /* opIsGptr: returns non-zero if the passed operand is             */   
1235 /* a generic pointer type.                                         */
1236 /*-----------------------------------------------------------------*/ 
1237 static int opIsGptr(operand *op)
1238 {
1239     link *type = operandType(op);
1240     
1241     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1242     {
1243         return 1;
1244     }
1245     return 0;        
1246 }
1247
1248 /*-----------------------------------------------------------------*/
1249 /* getDataSize - get the operand data size                         */
1250 /*-----------------------------------------------------------------*/
1251 static int getDataSize(operand *op)
1252 {
1253     int size;
1254     size = AOP_SIZE(op);
1255     if (size == GPTRSIZE)
1256     {
1257         link *type = operandType(op);
1258         if (IS_GENPTR(type))
1259         {
1260             /* generic pointer; arithmetic operations
1261              * should ignore the high byte (pointer type).
1262              */
1263             size--;
1264         }
1265     }
1266     return size;
1267 }
1268
1269 /*-----------------------------------------------------------------*/
1270 /* outAcc - output Acc                                             */
1271 /*-----------------------------------------------------------------*/
1272 static void outAcc(operand *result)
1273 {
1274     int size, offset;
1275     size = getDataSize(result);
1276     if(size){
1277         aopPut(AOP(result),"a",0);
1278         size--;
1279         offset = 1;
1280         /* unsigned or positive */
1281         while(size--){
1282             aopPut(AOP(result),zero,offset++);
1283         }
1284     }
1285 }
1286
1287 /*-----------------------------------------------------------------*/
1288 /* outBitC - output a bit C                                        */
1289 /*-----------------------------------------------------------------*/
1290 static void outBitC(operand *result)
1291 {
1292     /* if the result is bit */
1293     if (AOP_TYPE(result) == AOP_CRY) 
1294         aopPut(AOP(result),"c",0);
1295     else {
1296         emitcode("clr","a");
1297         emitcode("rlc","a");
1298         outAcc(result);
1299     }
1300 }
1301
1302 /*-----------------------------------------------------------------*/
1303 /* toBoolean - emit code for orl a,operator(sizeop)                */
1304 /*-----------------------------------------------------------------*/
1305 static void toBoolean(operand *oper)
1306 {
1307     int size = AOP_SIZE(oper) - 1;
1308     int offset = 1;
1309
1310     if (AOP_NEEDSACC(oper))
1311     {
1312         emitcode("push", "b");
1313         emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1314     }
1315     else
1316     {
1317         MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1318     }
1319     while (size--) 
1320     {
1321         if (AOP_NEEDSACC(oper))
1322         {
1323             emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1324         }
1325         else
1326         {
1327         emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1328 }
1329     }
1330     
1331     if (AOP_NEEDSACC(oper))
1332     {
1333         emitcode("mov", "a,b");
1334         emitcode("pop", "b");
1335     }
1336 }
1337
1338
1339 /*-----------------------------------------------------------------*/
1340 /* genNot - generate code for ! operation                          */
1341 /*-----------------------------------------------------------------*/
1342 static void genNot (iCode *ic)
1343 {
1344     symbol *tlbl;
1345     link *optype = operandType(IC_LEFT(ic));
1346
1347     D(emitcode(";", "genNot "););
1348
1349     /* assign asmOps to operand & result */
1350     aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1351     aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1352
1353     /* if in bit space then a special case */
1354     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1355         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1356         emitcode("cpl","c"); 
1357         outBitC(IC_RESULT(ic));
1358         goto release;
1359     }
1360
1361     /* if type float then do float */
1362     if (IS_FLOAT(optype)) {
1363         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1364         goto release;
1365     }
1366
1367     toBoolean(IC_LEFT(ic));
1368
1369     tlbl = newiTempLabel(NULL);
1370     emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1371     emitcode("","%05d$:",tlbl->key+100);
1372     outBitC(IC_RESULT(ic));
1373
1374 release:    
1375     /* release the aops */
1376     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1377     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1378 }
1379
1380
1381 /*-----------------------------------------------------------------*/
1382 /* genCpl - generate code for complement                           */
1383 /*-----------------------------------------------------------------*/
1384 static void genCpl (iCode *ic)
1385 {
1386     int offset = 0;
1387     int size ;
1388
1389     D(emitcode(";", "genCpl "););
1390
1391
1392     /* assign asmOps to operand & result */
1393     aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1394     aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1395
1396     /* if both are in bit space then 
1397     a special case */
1398     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1399         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1400
1401         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1402         emitcode("cpl","c"); 
1403         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1404         goto release; 
1405     } 
1406
1407     size = AOP_SIZE(IC_RESULT(ic));
1408     while (size--) {
1409         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1410         MOVA(l);       
1411         emitcode("cpl","a");
1412         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1413     }
1414
1415
1416 release:
1417     /* release the aops */
1418     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1419     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1420 }
1421
1422 /*-----------------------------------------------------------------*/
1423 /* genUminusFloat - unary minus for floating points                */
1424 /*-----------------------------------------------------------------*/
1425 static void genUminusFloat(operand *op,operand *result)
1426 {
1427     int size ,offset =0 ;
1428     char *l;
1429     /* for this we just need to flip the 
1430     first it then copy the rest in place */
1431     D(emitcode(";", "genUminusFloat"););
1432     
1433     size = AOP_SIZE(op) - 1;
1434     l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1435     MOVA(l);    
1436
1437     emitcode("cpl","acc.7");
1438     aopPut(AOP(result),"a",3);    
1439
1440     while(size--) {
1441         aopPut(AOP(result),
1442                aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1443                offset);
1444         offset++;
1445     }          
1446 }
1447
1448 /*-----------------------------------------------------------------*/
1449 /* genUminus - unary minus code generation                         */
1450 /*-----------------------------------------------------------------*/
1451 static void genUminus (iCode *ic)
1452 {
1453     int offset ,size ;
1454     link *optype, *rtype;
1455
1456     D(emitcode(";", "genUminus "););
1457
1458
1459     /* assign asmops */
1460     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1461     aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1462
1463     /* if both in bit space then special
1464     case */
1465     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1466         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1467
1468         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1469         emitcode("cpl","c"); 
1470         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1471         goto release; 
1472     } 
1473
1474     optype = operandType(IC_LEFT(ic));
1475     rtype = operandType(IC_RESULT(ic));
1476
1477     /* if float then do float stuff */
1478     if (IS_FLOAT(optype)) {
1479         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1480         goto release;
1481     }
1482
1483     /* otherwise subtract from zero */
1484     size = AOP_SIZE(IC_LEFT(ic));
1485     offset = 0 ;
1486     //CLRC ;
1487     while(size--) {
1488         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1489         if (!strcmp(l,"a")) {
1490           if (offset==0)
1491             SETC;
1492           emitcode("cpl","a");
1493           emitcode("addc", "a,#0");
1494         } else {
1495           if (offset==0)
1496             CLRC;
1497           emitcode("clr","a");
1498           emitcode("subb","a,%s",l);
1499         }       
1500         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1501     }
1502
1503     /* if any remaining bytes in the result */
1504     /* we just need to propagate the sign   */
1505     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1506         emitcode("rlc","a");
1507         emitcode("subb","a,acc");
1508         while (size--) 
1509             aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1510     }       
1511
1512 release:
1513     /* release the aops */
1514     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1515     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1516 }
1517
1518 /*-----------------------------------------------------------------*/
1519 /* saveRegisters - will look for a call and save the registers     */
1520 /*-----------------------------------------------------------------*/
1521 static void saveRegisters(iCode *lic) 
1522 {
1523     int i;
1524     iCode *ic;
1525     bitVect *rsave;
1526     link *detype;
1527
1528     /* look for call */
1529     for (ic = lic ; ic ; ic = ic->next) 
1530         if (ic->op == CALL || ic->op == PCALL)
1531             break;
1532
1533     if (!ic) {
1534         fprintf(stderr,"found parameter push with no function call\n");
1535         return ;
1536     }
1537
1538     /* if the registers have been saved already then
1539     do nothing */
1540     if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1541         return ;
1542
1543     /* find the registers in use at this time 
1544     and push them away to safety */
1545     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1546                           ic->rUsed);
1547
1548     ic->regsSaved = 1;
1549     if (options.useXstack) {
1550         if (bitVectBitValue(rsave,R0_IDX))
1551             emitcode("mov","b,r0");
1552         emitcode("mov","r0,%s",spname);
1553         for (i = 0 ; i < ds390_nRegs ; i++) {
1554             if (bitVectBitValue(rsave,i)) {
1555                 if (i == R0_IDX)
1556                     emitcode("mov","a,b");
1557                 else
1558                     emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1559                 emitcode("movx","@r0,a");
1560                 emitcode("inc","r0");
1561             }
1562         }
1563         emitcode("mov","%s,r0",spname);
1564         if (bitVectBitValue(rsave,R0_IDX))
1565             emitcode("mov","r0,b");         
1566     } else
1567         for (i = 0 ; i < ds390_nRegs ; i++) {
1568             if (bitVectBitValue(rsave,i))
1569                 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1570         }
1571
1572     detype = getSpec(operandType(IC_LEFT(ic)));
1573     if (detype        && 
1574         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1575         IS_ISR(currFunc->etype) &&
1576         !ic->bankSaved) 
1577
1578         saverbank(SPEC_BANK(detype),ic,TRUE);
1579
1580 }
1581 /*-----------------------------------------------------------------*/
1582 /* unsaveRegisters - pop the pushed registers                      */
1583 /*-----------------------------------------------------------------*/
1584 static void unsaveRegisters (iCode *ic)
1585 {
1586     int i;
1587     bitVect *rsave;
1588     /* find the registers in use at this time 
1589     and push them away to safety */
1590     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1591                           ic->rUsed);
1592     
1593     if (options.useXstack) {
1594         emitcode("mov","r0,%s",spname); 
1595         for (i =  ds390_nRegs ; i >= 0 ; i--) {
1596             if (bitVectBitValue(rsave,i)) {
1597                 emitcode("dec","r0");
1598                 emitcode("movx","a,@r0");
1599                 if (i == R0_IDX)
1600                     emitcode("mov","b,a");
1601                 else
1602                     emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1603             }       
1604
1605         }
1606         emitcode("mov","%s,r0",spname);
1607         if (bitVectBitValue(rsave,R0_IDX))
1608             emitcode("mov","r0,b");
1609     } else
1610         for (i =  ds390_nRegs ; i >= 0 ; i--) {
1611             if (bitVectBitValue(rsave,i))
1612                 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1613         }
1614
1615 }  
1616
1617
1618 /*-----------------------------------------------------------------*/
1619 /* pushSide -                                                      */
1620 /*-----------------------------------------------------------------*/
1621 static void pushSide(operand * oper, int size)
1622 {
1623         int offset = 0;
1624         while (size--) {
1625                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1626                 if (AOP_TYPE(oper) != AOP_REG &&
1627                     AOP_TYPE(oper) != AOP_DIR &&
1628                     strcmp(l,"a") ) {
1629                         emitcode("mov","a,%s",l);
1630                         emitcode("push","acc");
1631                 } else
1632                         emitcode("push","%s",l);
1633         }
1634 }
1635
1636 /*-----------------------------------------------------------------*/
1637 /* assignResultValue -                                             */
1638 /*-----------------------------------------------------------------*/
1639 static void assignResultValue(operand * oper)
1640 {
1641         int offset = 0;
1642         int size = AOP_SIZE(oper);
1643         while (size--) {
1644                 aopPut(AOP(oper),fReturn[offset],offset);
1645                 offset++;
1646         }
1647 }
1648
1649
1650 /*-----------------------------------------------------------------*/
1651 /* genXpush - pushes onto the external stack                       */
1652 /*-----------------------------------------------------------------*/
1653 static void genXpush (iCode *ic)
1654 {
1655     asmop *aop = newAsmop(0);
1656     regs *r ;
1657     int size,offset = 0;
1658
1659     D(emitcode(";", "genXpush "););
1660
1661     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1662     r = getFreePtr(ic,&aop,FALSE);
1663
1664     
1665     emitcode("mov","%s,_spx",r->name);
1666
1667     size = AOP_SIZE(IC_LEFT(ic));
1668     while(size--) {
1669
1670         char *l = aopGet(AOP(IC_LEFT(ic)),
1671                          offset++,FALSE,FALSE,TRUE);    
1672         MOVA(l);            
1673         emitcode("movx","@%s,a",r->name);       
1674         emitcode("inc","%s",r->name);
1675
1676     }
1677
1678         
1679     emitcode("mov","_spx,%s",r->name);
1680
1681     freeAsmop(NULL,aop,ic,TRUE);
1682     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1683 }
1684
1685 /*-----------------------------------------------------------------*/
1686 /* genIpush - genrate code for pushing this gets a little complex  */
1687 /*-----------------------------------------------------------------*/
1688 static void genIpush (iCode *ic)
1689 {
1690     int size, offset = 0 ;
1691     char *l;
1692
1693     D(emitcode(";", "genIpush "););
1694
1695
1696     /* if this is not a parm push : ie. it is spill push 
1697     and spill push is always done on the local stack */
1698     if (!ic->parmPush) {
1699
1700         /* and the item is spilt then do nothing */
1701         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1702             return ;
1703
1704         aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1705         size = AOP_SIZE(IC_LEFT(ic));
1706         /* push it on the stack */
1707         while(size--) {
1708             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1709             if (*l == '#') {
1710                 MOVA(l);
1711                 l = "acc";
1712             }
1713             emitcode("push","%s",l);
1714         }
1715         return ;        
1716     }
1717
1718     /* this is a paramter push: in this case we call
1719     the routine to find the call and save those
1720     registers that need to be saved */   
1721     saveRegisters(ic);
1722
1723     /* if use external stack then call the external
1724     stack pushing routine */
1725     if (options.useXstack) {
1726         genXpush(ic);
1727         return ;
1728     }
1729
1730     /* then do the push */
1731     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1732
1733
1734         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1735     size = AOP_SIZE(IC_LEFT(ic));
1736
1737     while (size--) {
1738         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1739         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
1740             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1741             strcmp(l,"a") ) {
1742             emitcode("mov","a,%s",l);
1743             emitcode("push","acc");
1744         } else
1745             emitcode("push","%s",l);
1746     }       
1747
1748     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1749 }
1750
1751 /*-----------------------------------------------------------------*/
1752 /* genIpop - recover the registers: can happen only for spilling   */
1753 /*-----------------------------------------------------------------*/
1754 static void genIpop (iCode *ic)
1755 {
1756     int size,offset ;
1757
1758     D(emitcode(";", "genIpop "););
1759
1760
1761     /* if the temp was not pushed then */
1762     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1763         return ;
1764
1765     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1766     size = AOP_SIZE(IC_LEFT(ic));
1767     offset = (size-1);
1768     while (size--) 
1769         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1770                                    FALSE,TRUE,TRUE));
1771
1772     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1773 }
1774
1775 /*-----------------------------------------------------------------*/
1776 /* unsaverbank - restores the resgister bank from stack            */
1777 /*-----------------------------------------------------------------*/
1778 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1779 {
1780     int i;
1781     asmop *aop ;
1782     regs *r = NULL;
1783
1784     if (popPsw) {
1785         if (options.useXstack) {
1786             aop = newAsmop(0);
1787             r = getFreePtr(ic,&aop,FALSE);
1788             
1789             
1790             emitcode("mov","%s,_spx",r->name);
1791             emitcode("movx","a,@%s",r->name);
1792             emitcode("mov","psw,a");
1793             emitcode("dec","%s",r->name);
1794             
1795         }else
1796             emitcode ("pop","psw");
1797     }
1798
1799     for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1800         if (options.useXstack) {       
1801             emitcode("movx","a,@%s",r->name);
1802             emitcode("mov","(%s+%d),a",
1803                      regs390[i].base,8*bank+regs390[i].offset);
1804             emitcode("dec","%s",r->name);
1805
1806         } else 
1807             emitcode("pop","(%s+%d)",
1808                      regs390[i].base,8*bank+regs390[i].offset);
1809     }
1810
1811     if (options.useXstack) {
1812
1813         emitcode("mov","_spx,%s",r->name);
1814         freeAsmop(NULL,aop,ic,TRUE);
1815
1816     } 
1817 }
1818
1819 /*-----------------------------------------------------------------*/
1820 /* saverbank - saves an entire register bank on the stack          */
1821 /*-----------------------------------------------------------------*/
1822 static void saverbank (int bank, iCode *ic, bool pushPsw)
1823 {
1824     int i;
1825     asmop *aop ;
1826     regs *r = NULL;
1827
1828     if (options.useXstack) {
1829
1830         aop = newAsmop(0);
1831         r = getFreePtr(ic,&aop,FALSE);  
1832         emitcode("mov","%s,_spx",r->name);
1833
1834     }
1835
1836     for (i = 0 ; i < ds390_nRegs ;i++) {
1837         if (options.useXstack) {
1838             emitcode("inc","%s",r->name);
1839             emitcode("mov","a,(%s+%d)",
1840                      regs390[i].base,8*bank+regs390[i].offset);
1841             emitcode("movx","@%s,a",r->name);           
1842         } else 
1843             emitcode("push","(%s+%d)",
1844                      regs390[i].base,8*bank+regs390[i].offset);
1845     }
1846     
1847     if (pushPsw) {
1848         if (options.useXstack) {
1849             emitcode("mov","a,psw");
1850             emitcode("movx","@%s,a",r->name);   
1851             emitcode("inc","%s",r->name);
1852             emitcode("mov","_spx,%s",r->name);       
1853             freeAsmop (NULL,aop,ic,TRUE);
1854             
1855         } else
1856             emitcode("push","psw");
1857         
1858         emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1859     }
1860     ic->bankSaved = 1;
1861
1862 }
1863
1864 /*-----------------------------------------------------------------*/
1865 /* genCall - generates a call statement                            */
1866 /*-----------------------------------------------------------------*/
1867 static void genCall (iCode *ic)
1868 {
1869     link *detype;   
1870
1871     D(emitcode(";", "genCall "););
1872
1873     /* if caller saves & we have not saved then */
1874     if (!ic->regsSaved)
1875         saveRegisters(ic);
1876
1877     /* if we are calling a function that is not using
1878     the same register bank then we need to save the
1879     destination registers on the stack */
1880     detype = getSpec(operandType(IC_LEFT(ic)));
1881     if (detype        && 
1882         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1883         IS_ISR(currFunc->etype) &&
1884         !ic->bankSaved) 
1885
1886         saverbank(SPEC_BANK(detype),ic,TRUE);
1887
1888     /* if send set is not empty the assign */
1889     if (_G.sendSet) {
1890         iCode *sic ;
1891
1892         for (sic = setFirstItem(_G.sendSet) ; sic ; 
1893              sic = setNextItem(_G.sendSet)) {
1894             int size, offset = 0;
1895         aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
1896             size = AOP_SIZE(IC_LEFT(sic));
1897             while (size--) {
1898                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1899                                 FALSE, FALSE, FALSE);
1900                 if (strcmp(l,fReturn[offset]))
1901                     emitcode("mov","%s,%s",
1902                              fReturn[offset],
1903                              l);
1904                 offset++;
1905             }
1906             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1907         }
1908         _G.sendSet = NULL;
1909     }
1910     /* make the call */
1911     emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1912                            OP_SYMBOL(IC_LEFT(ic))->rname :
1913                            OP_SYMBOL(IC_LEFT(ic))->name));
1914
1915     /* if we need assign a result value */
1916     if ((IS_ITEMP(IC_RESULT(ic)) && 
1917          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1918           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1919         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1920
1921         if (!isOperandInFarSpace(IC_RESULT(ic)))
1922         {
1923         _G.accInUse++;
1924             aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1925         _G.accInUse--;
1926
1927         assignResultValue(IC_RESULT(ic));
1928                 
1929         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1930     }
1931         else
1932         {
1933             /* Result is in far space, and requires DPTR to access
1934              * it. Push the result onto the stack and restore from
1935              * there.
1936              */
1937             int size = getSize(operandType(IC_RESULT(ic)));
1938             int offset = size - 1;
1939             char *l;
1940             
1941             emitcode(";", "Kevin function call abuse #1");
1942
1943             /* first push the right side on to the stack */
1944             /* NB: this relies on the fact that "a" is the last
1945              * register in fReturn. If it were not, the MOVA
1946              * would potentially clobber a returned byte in A.
1947              */
1948             while (size--) {
1949                 l = fReturn[offset--];
1950                 MOVA(l);
1951                 emitcode ("push","acc");
1952             }
1953     
1954             /* now assign DPTR to result */
1955             aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1956             size = AOP_SIZE(IC_RESULT(ic));
1957             aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
1958             while (size--) {
1959                 emitcode ("pop","acc");
1960                 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
1961             }
1962             freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1963         }
1964     }
1965
1966     /* adjust the stack for parameters if 
1967     required */
1968     if (IC_LEFT(ic)->parmBytes) {
1969         int i;
1970         if (IC_LEFT(ic)->parmBytes > 3) {
1971             emitcode("mov","a,%s",spname);
1972             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1973             emitcode("mov","%s,a",spname);
1974         } else 
1975             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
1976                 emitcode("dec","%s",spname);
1977
1978     }
1979
1980     /* if register bank was saved then pop them */
1981     if (ic->bankSaved)
1982         unsaverbank(SPEC_BANK(detype),ic,TRUE);
1983
1984     /* if we hade saved some registers then unsave them */
1985     if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1986         unsaveRegisters (ic);
1987
1988
1989 }
1990
1991 /*-----------------------------------------------------------------*/
1992 /* genPcall - generates a call by pointer statement                */
1993 /*-----------------------------------------------------------------*/
1994 static void genPcall (iCode *ic)
1995 {
1996     link *detype;
1997     symbol *rlbl = newiTempLabel(NULL);
1998
1999     D(emitcode(";", "genPcall "););
2000
2001
2002     /* if caller saves & we have not saved then */
2003     if (!ic->regsSaved)
2004         saveRegisters(ic);
2005
2006     /* if we are calling a function that is not using
2007     the same register bank then we need to save the
2008     destination registers on the stack */
2009     detype = getSpec(operandType(IC_LEFT(ic)));
2010     if (detype        && 
2011         IS_ISR(currFunc->etype) &&
2012         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2013         saverbank(SPEC_BANK(detype),ic,TRUE);
2014
2015
2016     /* push the return address on to the stack */
2017     emitcode("mov","a,#%05d$",(rlbl->key+100));
2018     emitcode("push","acc");    
2019     emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2020     emitcode("push","acc");
2021     
2022     if (options.model == MODEL_FLAT24)
2023     {
2024         emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2025         emitcode("push","acc");    
2026     }
2027
2028     /* now push the calling address */
2029     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2030
2031     pushSide(IC_LEFT(ic), FPTRSIZE);
2032
2033     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2034
2035     /* if send set is not empty the assign */
2036     if (_G.sendSet) {
2037         iCode *sic ;
2038
2039         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2040              sic = setNextItem(_G.sendSet)) {
2041             int size, offset = 0;
2042             aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2043             size = AOP_SIZE(IC_LEFT(sic));
2044             while (size--) {
2045                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2046                                 FALSE,FALSE,FALSE);
2047                 if (strcmp(l,fReturn[offset]))
2048                     emitcode("mov","%s,%s",
2049                              fReturn[offset],
2050                              l);
2051                 offset++;
2052             }
2053             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2054         }
2055         _G.sendSet = NULL;
2056     }
2057
2058     emitcode("ret","");
2059     emitcode("","%05d$:",(rlbl->key+100));
2060
2061
2062     /* if we need assign a result value */
2063     if ((IS_ITEMP(IC_RESULT(ic)) &&
2064          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2065           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2066         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2067
2068         _G.accInUse++;
2069         aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2070         _G.accInUse--;
2071         
2072         assignResultValue(IC_RESULT(ic));
2073
2074         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2075     }
2076
2077     /* adjust the stack for parameters if 
2078     required */
2079     if (IC_LEFT(ic)->parmBytes) {
2080         int i;
2081         if (IC_LEFT(ic)->parmBytes > 3) {
2082             emitcode("mov","a,%s",spname);
2083             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2084             emitcode("mov","%s,a",spname);
2085         } else 
2086             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
2087                 emitcode("dec","%s",spname);
2088
2089     }
2090
2091     /* if register bank was saved then unsave them */
2092     if (detype        && 
2093         (SPEC_BANK(currFunc->etype) != 
2094          SPEC_BANK(detype)))
2095         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2096
2097     /* if we hade saved some registers then
2098     unsave them */
2099     if (ic->regsSaved)
2100         unsaveRegisters (ic);
2101
2102 }
2103
2104 /*-----------------------------------------------------------------*/
2105 /* resultRemat - result  is rematerializable                       */
2106 /*-----------------------------------------------------------------*/
2107 static int resultRemat (iCode *ic)
2108 {
2109     if (SKIP_IC(ic) || ic->op == IFX)
2110         return 0;
2111
2112     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2113         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2114         if (sym->remat && !POINTER_SET(ic)) 
2115             return 1;
2116     }
2117
2118     return 0;
2119 }
2120
2121 #ifdef __BORLANDC__
2122 #define STRCASECMP stricmp
2123 #else
2124 #define STRCASECMP strcasecmp
2125 #endif
2126
2127 /*-----------------------------------------------------------------*/
2128 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2129 /*-----------------------------------------------------------------*/
2130 static bool inExcludeList(char *s)
2131 {
2132     int i =0;
2133     
2134     if (options.excludeRegs[i] &&
2135     STRCASECMP(options.excludeRegs[i],"none") == 0)
2136         return FALSE ;
2137
2138     for ( i = 0 ; options.excludeRegs[i]; i++) {
2139         if (options.excludeRegs[i] &&
2140         STRCASECMP(s,options.excludeRegs[i]) == 0)
2141             return TRUE;
2142     }
2143     return FALSE ;
2144 }
2145
2146 /*-----------------------------------------------------------------*/
2147 /* genFunction - generated code for function entry                 */
2148 /*-----------------------------------------------------------------*/
2149 static void genFunction (iCode *ic)
2150 {
2151     symbol *sym;
2152     link *fetype;
2153
2154     D(emitcode(";", "genFunction "););
2155
2156     _G.nRegsSaved = 0;
2157     /* create the function header */
2158     emitcode(";","-----------------------------------------");
2159     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2160     emitcode(";","-----------------------------------------");
2161
2162     emitcode("","%s:",sym->rname);
2163     fetype = getSpec(operandType(IC_LEFT(ic)));
2164
2165     /* if critical function then turn interrupts off */
2166     if (SPEC_CRTCL(fetype))
2167         emitcode("clr","ea");
2168
2169     /* here we need to generate the equates for the
2170        register bank if required */
2171     if (SPEC_BANK(fetype) != rbank) {
2172         int i ;
2173
2174         rbank = SPEC_BANK(fetype);
2175         for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2176             if (strcmp(regs390[i].base,"0") == 0)
2177                 emitcode("","%s = 0x%02x",
2178                          regs390[i].dname,
2179                          8*rbank+regs390[i].offset);
2180             else
2181                 emitcode ("","%s = %s + 0x%02x",
2182                           regs390[i].dname,
2183                           regs390[i].base,
2184                           8*rbank+regs390[i].offset);
2185         }
2186     }
2187
2188     /* if this is an interrupt service routine then
2189     save acc, b, dpl, dph  */
2190     if (IS_ISR(sym->etype)) {
2191         
2192         if (!inExcludeList("acc"))          
2193             emitcode ("push","acc");    
2194         if (!inExcludeList("b"))
2195             emitcode ("push","b");
2196         if (!inExcludeList("dpl"))
2197             emitcode ("push","dpl");
2198         if (!inExcludeList("dph"))
2199             emitcode ("push","dph");
2200         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2201         {
2202             emitcode ("push", "dpx");
2203             /* Make sure we're using standard DPTR */
2204             emitcode ("push", "dps");
2205             emitcode ("mov", "dps, #0x00");
2206             if (options.stack10bit)
2207             {   
2208                 /* This ISR could conceivably use DPTR2. Better save it. */
2209                 emitcode ("push", "dpl1");
2210                 emitcode ("push", "dph1");
2211                 emitcode ("push", "dpx1");
2212             emitcode ("push", "ap");
2213             }
2214         }
2215         /* if this isr has no bank i.e. is going to
2216            run with bank 0 , then we need to save more
2217            registers :-) */
2218         if (!SPEC_BANK(sym->etype)) {
2219
2220             /* if this function does not call any other
2221                function then we can be economical and
2222                save only those registers that are used */
2223             if (! sym->hasFcall) {
2224                 int i;
2225
2226                 /* if any registers used */
2227                 if (sym->regsUsed) {
2228                     /* save the registers used */
2229                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2230                         if (bitVectBitValue(sym->regsUsed,i) ||
2231                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2232                             emitcode("push","%s",ds390_regWithIdx(i)->dname);                       
2233                     }
2234                 }
2235                 
2236             } else {
2237                 /* this function has  a function call cannot
2238                    determines register usage so we will have the
2239                    entire bank */
2240                 saverbank(0,ic,FALSE);
2241             }       
2242         }
2243     } else {
2244         /* if callee-save to be used for this function
2245            then save the registers being used in this function */
2246         if (sym->calleeSave) {
2247             int i;
2248             
2249             /* if any registers used */
2250             if (sym->regsUsed) {
2251                 /* save the registers used */
2252                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2253                     if (bitVectBitValue(sym->regsUsed,i) ||
2254                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2255                         emitcode("push","%s",ds390_regWithIdx(i)->dname);
2256                         _G.nRegsSaved++;
2257                     }
2258                 }
2259             }
2260         }
2261     }
2262
2263     /* set the register bank to the desired value */
2264     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2265         emitcode("push","psw");
2266         emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);   
2267     }
2268
2269     if (IS_RENT(sym->etype) || options.stackAuto) {
2270
2271         if (options.useXstack) {
2272             emitcode("mov","r0,%s",spname);
2273             emitcode("mov","a,_bp");
2274             emitcode("movx","@r0,a");
2275             emitcode("inc","%s",spname);
2276         }
2277         else
2278         {
2279             /* set up the stack */
2280             emitcode ("push","_bp");     /* save the callers stack  */
2281         }
2282         emitcode ("mov","_bp,%s",spname);
2283     }
2284
2285     /* adjust the stack for the function */
2286     if (sym->stack) {
2287
2288         int i = sym->stack;
2289         if (i > 256 ) 
2290             werror(W_STACK_OVERFLOW,sym->name);
2291
2292         if (i > 3 && sym->recvSize < 4) {              
2293
2294             emitcode ("mov","a,sp");
2295             emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2296             emitcode ("mov","sp,a");
2297            
2298         }
2299         else
2300             while(i--)
2301                 emitcode("inc","sp");
2302     }
2303
2304      if (sym->xstack) {
2305
2306         emitcode ("mov","a,_spx");
2307         emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2308         emitcode ("mov","_spx,a");
2309     }    
2310
2311 }
2312
2313 /*-----------------------------------------------------------------*/
2314 /* genEndFunction - generates epilogue for functions               */
2315 /*-----------------------------------------------------------------*/
2316 static void genEndFunction (iCode *ic)
2317 {
2318     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2319
2320     D(emitcode(";", "genEndFunction "););
2321
2322     if (IS_RENT(sym->etype) || options.stackAuto)
2323     {
2324         emitcode ("mov","%s,_bp",spname);
2325     }
2326
2327     /* if use external stack but some variables were
2328     added to the local stack then decrement the
2329     local stack */
2330     if (options.useXstack && sym->stack) {      
2331         emitcode("mov","a,sp");
2332         emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2333         emitcode("mov","sp,a");
2334     }
2335
2336
2337     if ((IS_RENT(sym->etype) || options.stackAuto)) {
2338         if (options.useXstack) {
2339             emitcode("mov","r0,%s",spname);
2340             emitcode("movx","a,@r0");
2341             emitcode("mov","_bp,a");
2342             emitcode("dec","%s",spname);
2343         }
2344         else
2345         {
2346             emitcode ("pop","_bp");
2347         }
2348     }
2349
2350     /* restore the register bank  */    
2351     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2352         emitcode ("pop","psw");
2353
2354     if (IS_ISR(sym->etype)) {
2355
2356         /* now we need to restore the registers */
2357         /* if this isr has no bank i.e. is going to
2358            run with bank 0 , then we need to save more
2359            registers :-) */
2360         if (!SPEC_BANK(sym->etype)) {
2361             
2362             /* if this function does not call any other
2363                function then we can be economical and
2364                save only those registers that are used */
2365             if (! sym->hasFcall) {
2366                 int i;
2367                 
2368                 /* if any registers used */
2369                 if (sym->regsUsed) {
2370                     /* save the registers used */
2371                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2372                         if (bitVectBitValue(sym->regsUsed,i) ||
2373                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2374                             emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2375                     }
2376                 }
2377                 
2378             } else {
2379                 /* this function has  a function call cannot
2380                    determines register usage so we will have the
2381                    entire bank */
2382                 unsaverbank(0,ic,FALSE);
2383             }       
2384         }
2385
2386         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2387         {
2388             if (options.stack10bit)
2389             {
2390             emitcode ("pop", "ap");
2391                 emitcode ("pop", "dpx1");
2392                 emitcode ("pop", "dph1");
2393                 emitcode ("pop", "dpl1");
2394             }   
2395             emitcode ("pop", "dps");
2396             emitcode ("pop", "dpx");
2397         }
2398         if (!inExcludeList("dph"))
2399             emitcode ("pop","dph");
2400         if (!inExcludeList("dpl"))
2401             emitcode ("pop","dpl");
2402         if (!inExcludeList("b"))
2403             emitcode ("pop","b");
2404         if (!inExcludeList("acc"))
2405             emitcode ("pop","acc");
2406
2407         if (SPEC_CRTCL(sym->etype))
2408             emitcode("setb","ea");
2409
2410         /* if debug then send end of function */
2411 /*      if (options.debug && currFunc) { */
2412         if (currFunc) {
2413             _G.debugLine = 1;
2414             emitcode("","C$%s$%d$%d$%d ==.",
2415                      ic->filename,currFunc->lastLine,
2416                      ic->level,ic->block); 
2417             if (IS_STATIC(currFunc->etype))         
2418                 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2419             else
2420                 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2421             _G.debugLine = 0;
2422         }
2423         
2424         emitcode ("reti","");
2425     }
2426     else {
2427         if (SPEC_CRTCL(sym->etype))
2428             emitcode("setb","ea");
2429         
2430         if (sym->calleeSave) {
2431             int i;
2432             
2433             /* if any registers used */
2434             if (sym->regsUsed) {
2435                 /* save the registers used */
2436                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2437                     if (bitVectBitValue(sym->regsUsed,i) ||
2438                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2439                         emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2440                 }
2441             }
2442             
2443         }
2444
2445         /* if debug then send end of function */
2446         if (currFunc) {
2447             _G.debugLine = 1;
2448             emitcode("","C$%s$%d$%d$%d ==.",
2449                      ic->filename,currFunc->lastLine,
2450                      ic->level,ic->block); 
2451             if (IS_STATIC(currFunc->etype))         
2452                 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2453             else
2454                 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2455             _G.debugLine = 0;
2456         }
2457
2458         emitcode ("ret","");
2459     }
2460
2461 }
2462
2463 /*-----------------------------------------------------------------*/
2464 /* genRet - generate code for return statement                     */
2465 /*-----------------------------------------------------------------*/
2466 static void genRet (iCode *ic)
2467 {
2468     int size,offset = 0 , pushed = 0;
2469     
2470     D(emitcode(";", "genRet "););
2471
2472     /* if we have no return value then
2473        just generate the "ret" */
2474     if (!IC_LEFT(ic)) 
2475         goto jumpret;       
2476     
2477     /* we have something to return then
2478        move the return value into place */
2479     aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2480     size = AOP_SIZE(IC_LEFT(ic));
2481     
2482     while (size--) {
2483             char *l ;
2484             if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2485                     l = aopGet(AOP(IC_LEFT(ic)),offset++,
2486                            FALSE,TRUE,FALSE);
2487                     emitcode("push","%s",l);
2488                     pushed++;
2489             } else {
2490                     l = aopGet(AOP(IC_LEFT(ic)),offset,
2491                                FALSE,FALSE,FALSE);
2492                     if (strcmp(fReturn[offset],l))
2493                             emitcode("mov","%s,%s",fReturn[offset++],l);
2494             }
2495     }    
2496
2497     if (pushed) {
2498         while(pushed) {
2499             pushed--;
2500             if (strcmp(fReturn[pushed],"a"))
2501                 emitcode("pop",fReturn[pushed]);
2502             else
2503                 emitcode("pop","acc");
2504         }
2505     }
2506     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2507     
2508  jumpret:
2509         /* generate a jump to the return label
2510            if the next is not the return statement */
2511     if (!(ic->next && ic->next->op == LABEL &&
2512           IC_LABEL(ic->next) == returnLabel))
2513         
2514         emitcode("ljmp","%05d$",(returnLabel->key+100));
2515     
2516 }
2517
2518 /*-----------------------------------------------------------------*/
2519 /* genLabel - generates a label                                    */
2520 /*-----------------------------------------------------------------*/
2521 static void genLabel (iCode *ic)
2522 {
2523     /* special case never generate */
2524     if (IC_LABEL(ic) == entryLabel)
2525         return ;
2526
2527     D(emitcode(";", "genLabel "););
2528
2529     emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2530 }
2531
2532 /*-----------------------------------------------------------------*/
2533 /* genGoto - generates a ljmp                                      */
2534 /*-----------------------------------------------------------------*/
2535 static void genGoto (iCode *ic)
2536 {
2537     D(emitcode(";", "genGoto "););
2538     emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2539 }
2540
2541 /*-----------------------------------------------------------------*/
2542 /* findLabelBackwards: walks back through the iCode chain looking  */
2543 /* for the given label. Returns number of iCode instructions       */
2544 /* between that label and given ic.                                */
2545 /* Returns zero if label not found.                                */
2546 /*-----------------------------------------------------------------*/
2547 static int findLabelBackwards(iCode *ic, int key)
2548 {
2549     int count = 0;
2550     
2551     while (ic->prev)
2552     {
2553         ic = ic->prev;
2554         count++;
2555         
2556         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2557         {
2558             /* printf("findLabelBackwards = %d\n", count); */
2559             return count;
2560         }
2561     }
2562     
2563     return 0;
2564 }
2565
2566 /*-----------------------------------------------------------------*/
2567 /* genPlusIncr :- does addition with increment if possible         */
2568 /*-----------------------------------------------------------------*/
2569 static bool genPlusIncr (iCode *ic)
2570 {
2571     unsigned int icount ;
2572     unsigned int size = getDataSize(IC_RESULT(ic));
2573     
2574     /* will try to generate an increment */
2575     /* if the right side is not a literal 
2576        we cannot */
2577     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2578         return FALSE ;
2579     
2580     /* if the literal value of the right hand side
2581        is greater than 4 then it is not worth it */
2582     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2583         return FALSE ;
2584     
2585     /* if increment 16 bits in register */
2586     if (
2587         AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2588         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2589         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2590         (size > 1) &&
2591         (icount == 1)) {
2592         symbol *tlbl;
2593         int emitTlbl;
2594         int labelRange;
2595
2596         /* If the next instruction is a goto and the goto target
2597          * is <= 5 instructions previous to this, we can generate
2598          * jumps straight to that target.
2599          */
2600         if (ic->next && ic->next->op == GOTO
2601             && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2602             && labelRange <= 5 )
2603         {
2604            emitcode(";", "tail increment optimized (range %d)", labelRange);
2605            tlbl = IC_LABEL(ic->next);
2606            emitTlbl = 0;
2607         }
2608         else
2609         {
2610             tlbl = newiTempLabel(NULL);
2611             emitTlbl = 1;
2612         }
2613         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2614         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2615            IS_AOP_PREG(IC_RESULT(ic)))
2616             emitcode("cjne","%s,#0x00,%05d$"
2617                      ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2618                      ,tlbl->key+100);
2619         else {
2620             emitcode("clr","a");
2621             emitcode("cjne","a,%s,%05d$"
2622                      ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2623                      ,tlbl->key+100);
2624         }
2625     
2626         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2627         if (size > 2)
2628         {
2629             if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2630                IS_AOP_PREG(IC_RESULT(ic)))
2631                 emitcode("cjne","%s,#0x00,%05d$"
2632                          ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2633                          ,tlbl->key+100);
2634             else
2635                 emitcode("cjne","a,%s,%05d$"
2636                          ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2637                          ,tlbl->key+100);
2638             
2639             emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2640        }
2641        if (size > 3)
2642        {
2643             if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2644                IS_AOP_PREG(IC_RESULT(ic)))
2645                 emitcode("cjne","%s,#0x00,%05d$"
2646                          ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2647                          ,tlbl->key+100);
2648             else{
2649                 emitcode("cjne","a,%s,%05d$"
2650                          ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2651                          ,tlbl->key+100);
2652             }
2653             emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2654         }
2655         
2656         if (emitTlbl)
2657         {
2658             emitcode("","%05d$:",tlbl->key+100);
2659         }
2660         return TRUE;
2661     }
2662     
2663     /* if the sizes are greater than 1 then we cannot */
2664     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2665         AOP_SIZE(IC_LEFT(ic)) > 1   )
2666         return FALSE ;
2667     
2668     /* we can if the aops of the left & result match or
2669        if they are in registers and the registers are the
2670        same */
2671     if (
2672         AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2673         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2674         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2675         
2676         if (icount > 3) {
2677             MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2678             emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2679             aopPut(AOP(IC_RESULT(ic)),"a",0);
2680         } else {
2681             
2682             while (icount--) 
2683                 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2684         }
2685         
2686         return TRUE ;
2687     }
2688     
2689     return FALSE ;
2690 }
2691
2692 /*-----------------------------------------------------------------*/
2693 /* outBitAcc - output a bit in acc                                 */
2694 /*-----------------------------------------------------------------*/
2695 static void outBitAcc(operand *result)
2696 {
2697     symbol *tlbl = newiTempLabel(NULL);
2698     /* if the result is a bit */
2699     if (AOP_TYPE(result) == AOP_CRY){
2700         aopPut(AOP(result),"a",0);
2701     }
2702     else {
2703         emitcode("jz","%05d$",tlbl->key+100);
2704         emitcode("mov","a,%s",one);
2705         emitcode("","%05d$:",tlbl->key+100);
2706         outAcc(result);
2707     }
2708 }
2709
2710 /*-----------------------------------------------------------------*/
2711 /* genPlusBits - generates code for addition of two bits           */
2712 /*-----------------------------------------------------------------*/
2713 static void genPlusBits (iCode *ic)
2714 {
2715     D(emitcode(";", "genPlusBits "););
2716     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2717         symbol *lbl = newiTempLabel(NULL);
2718         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2719         emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2720         emitcode("cpl","c");
2721         emitcode("","%05d$:",(lbl->key+100));
2722         outBitC(IC_RESULT(ic));
2723     }
2724     else{
2725         emitcode("clr","a");
2726         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2727         emitcode("rlc","a");
2728         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2729         emitcode("addc","a,#0x00");
2730         outAcc(IC_RESULT(ic));
2731     }
2732 }
2733
2734 static void adjustArithmeticResult(iCode *ic)
2735 {
2736     if (opIsGptr(IC_RESULT(ic)) &&
2737         opIsGptr(IC_LEFT(ic))   &&
2738         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2739     {
2740         aopPut(AOP(IC_RESULT(ic)),
2741                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2742                GPTRSIZE - 1);
2743     }
2744
2745     if (opIsGptr(IC_RESULT(ic)) &&
2746         opIsGptr(IC_RIGHT(ic))   &&
2747         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2748     {
2749         aopPut(AOP(IC_RESULT(ic)),
2750                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2751                GPTRSIZE - 1);
2752     }
2753
2754     if (opIsGptr(IC_RESULT(ic))            &&
2755         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
2756         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
2757          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2758          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2759          char buffer[5];
2760          sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2761          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2762      }
2763 }
2764
2765 #define AOP_OP_3(ic) \
2766     aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2767     aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2768     aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2769     if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2770         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2771     { \
2772         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2773         fprintf(stderr,                                  \
2774                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
2775     }
2776
2777 #define AOP_SET_LOCALS(ic) \
2778     left = IC_LEFT(ic); \
2779     right = IC_RIGHT(ic); \
2780     result = IC_RESULT(ic);
2781
2782 /*-----------------------------------------------------------------*/
2783 /* genPlus - generates code for addition                           */
2784 /*-----------------------------------------------------------------*/
2785 static void genPlus (iCode *ic)
2786 {
2787     int size, offset = 0;
2788     bool pushResult = FALSE;
2789
2790     D(emitcode(";", "genPlus "););
2791
2792     /* special cases :- */
2793
2794     aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2795     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2796     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2797         (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2798     {
2799         pushResult = TRUE;
2800     }
2801     else
2802     {
2803         aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
2804
2805     /* if literal, literal on the right or
2806        if left requires ACC or right is already
2807        in ACC */
2808     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2809         (AOP_NEEDSACC(IC_LEFT(ic))) ||
2810         AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2811         operand *t = IC_RIGHT(ic);
2812         IC_RIGHT(ic) = IC_LEFT(ic);
2813         IC_LEFT(ic) = t;
2814     }
2815
2816     /* if both left & right are in bit
2817     space */
2818     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2819         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2820         genPlusBits (ic);
2821         goto release ;
2822     }
2823
2824     /* if left in bit space & right literal */
2825     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2826         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2827         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2828         /* if result in bit space */
2829         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2830             if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2831                 emitcode("cpl","c");
2832             outBitC(IC_RESULT(ic));
2833         } else {
2834             size = getDataSize(IC_RESULT(ic));
2835             while (size--) {
2836                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2837                 emitcode("addc","a,#00");
2838                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2839             }
2840         }
2841         goto release ;
2842     }
2843
2844     /* if I can do an increment instead
2845     of add then GOOD for ME */
2846     if (genPlusIncr (ic) == TRUE)
2847         goto release;   
2848
2849     }
2850     size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
2851
2852     while(size--){
2853         if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2854             MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
2855             if(offset == 0)
2856                 emitcode("add","a,%s",
2857                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
2858             else
2859                 emitcode("addc","a,%s",
2860                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
2861         } else {
2862             MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2863             if(offset == 0)
2864                 emitcode("add","a,%s",
2865                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
2866             else
2867                 emitcode("addc","a,%s",
2868                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
2869         }
2870         if (!pushResult)
2871         {
2872             aopPut(AOP(IC_RESULT(ic)),"a",offset);
2873         }
2874         else
2875         {
2876             emitcode("push", "acc");
2877         }
2878         offset++;
2879     }
2880
2881     if (pushResult)
2882     {
2883         aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2884
2885         size = getDataSize(IC_LEFT(ic));
2886
2887         while(size--)
2888         {
2889             emitcode("pop", "acc");
2890             aopPut(AOP(IC_RESULT(ic)), "a", --offset);
2891         }
2892     }
2893
2894     adjustArithmeticResult(ic);
2895
2896 release:
2897     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2898     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2899     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2900 }
2901
2902 /*-----------------------------------------------------------------*/
2903 /* genMinusDec :- does subtraction with deccrement if possible     */
2904 /*-----------------------------------------------------------------*/
2905 static bool genMinusDec (iCode *ic)
2906 {
2907     unsigned int icount ;
2908     unsigned int size = getDataSize(IC_RESULT(ic));
2909
2910     /* will try to generate an increment */
2911     /* if the right side is not a literal 
2912     we cannot */
2913     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2914         return FALSE ;
2915
2916     /* if the literal value of the right hand side
2917     is greater than 4 then it is not worth it */
2918     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2919         return FALSE ;
2920
2921     /* if decrement 16 bits in register */
2922     if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2923         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2924         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2925         (size > 1) &&
2926         (icount == 1)) {
2927             symbol *tlbl;
2928             int emitTlbl;
2929             int labelRange;
2930
2931             /* If the next instruction is a goto and the goto target
2932          * is <= 5 instructions previous to this, we can generate
2933              * jumps straight to that target.
2934              */
2935             if (ic->next && ic->next->op == GOTO
2936                 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2937                 && labelRange <= 5 )
2938             {        
2939                emitcode(";", "tail decrement optimized (range %d)", labelRange);
2940                tlbl = IC_LABEL(ic->next);
2941                emitTlbl = 0;
2942             }
2943             else
2944             {
2945                 tlbl = newiTempLabel(NULL);
2946                 emitTlbl = 1;
2947             }
2948         
2949                 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2950                 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2951                    AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2952                    IS_AOP_PREG(IC_RESULT(ic)))
2953                         emitcode("cjne","%s,#0xff,%05d$"
2954                                          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2955                                          ,tlbl->key+100);
2956                 else{
2957                         emitcode("mov","a,#0xff");
2958                         emitcode("cjne","a,%s,%05d$"
2959                                          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2960                                          ,tlbl->key+100);
2961                 }
2962                 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2963                 if (size > 2)
2964                 {
2965                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2966                            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2967                            IS_AOP_PREG(IC_RESULT(ic)))
2968                                 emitcode("cjne","%s,#0xff,%05d$"
2969                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2970                                                  ,tlbl->key+100);
2971                         else{
2972                                 emitcode("cjne","a,%s,%05d$"
2973                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2974                                                  ,tlbl->key+100);
2975                         }
2976                         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2977                 }
2978                 if (size > 3)
2979                 {
2980                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2981                            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2982                            IS_AOP_PREG(IC_RESULT(ic)))
2983                                 emitcode("cjne","%s,#0xff,%05d$"
2984                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2985                                                  ,tlbl->key+100);
2986                         else{
2987                                 emitcode("cjne","a,%s,%05d$"
2988                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2989                                                  ,tlbl->key+100);
2990                         }
2991                         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2992                 }
2993                 if (emitTlbl)
2994                 {
2995                     emitcode("","%05d$:",tlbl->key+100);
2996                 }
2997         return TRUE;
2998     }
2999
3000     /* if the sizes are greater than 1 then we cannot */
3001     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3002         AOP_SIZE(IC_LEFT(ic)) > 1   )
3003         return FALSE ;
3004
3005     /* we can if the aops of the left & result match or
3006     if they are in registers and the registers are the
3007     same */
3008     if (
3009         AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3010         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3011         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3012
3013         while (icount--) 
3014             emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3015
3016         return TRUE ;
3017     }
3018
3019     return FALSE ;
3020 }
3021
3022 /*-----------------------------------------------------------------*/
3023 /* addSign - complete with sign                                    */
3024 /*-----------------------------------------------------------------*/
3025 static void addSign(operand *result, int offset, int sign)
3026 {
3027     int size = (getDataSize(result) - offset);
3028     if(size > 0){
3029         if(sign){
3030             emitcode("rlc","a");
3031             emitcode("subb","a,acc");
3032             while(size--)
3033                 aopPut(AOP(result),"a",offset++); 
3034         } else
3035             while(size--)
3036                 aopPut(AOP(result),zero,offset++);
3037     }
3038 }
3039
3040 /*-----------------------------------------------------------------*/
3041 /* genMinusBits - generates code for subtraction  of two bits      */
3042 /*-----------------------------------------------------------------*/
3043 static void genMinusBits (iCode *ic)
3044 {
3045     symbol *lbl = newiTempLabel(NULL);
3046     
3047     D(emitcode(";", "genMinusBits "););    
3048
3049     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3050         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3051         emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3052         emitcode("cpl","c");
3053         emitcode("","%05d$:",(lbl->key+100));
3054         outBitC(IC_RESULT(ic));
3055     }
3056     else{
3057         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3058         emitcode("subb","a,acc");
3059         emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3060         emitcode("inc","a");
3061         emitcode("","%05d$:",(lbl->key+100));
3062         aopPut(AOP(IC_RESULT(ic)),"a",0);
3063         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3064     }
3065 }
3066
3067 /*-----------------------------------------------------------------*/
3068 /* genMinus - generates code for subtraction                       */
3069 /*-----------------------------------------------------------------*/
3070 static void genMinus (iCode *ic)
3071 {
3072     int size, offset = 0;
3073     unsigned long lit = 0L;
3074     bool pushResult = FALSE;
3075
3076     D(emitcode(";", "genMinus "););
3077
3078     aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3079     aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3080     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3081         (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3082     {
3083         pushResult = TRUE;
3084     }
3085     else
3086     {
3087         aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3088
3089     /* special cases :- */
3090     /* if both left & right are in bit space */
3091     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3092         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3093         genMinusBits (ic);
3094         goto release ;
3095     }
3096
3097     /* if I can do an decrement instead
3098     of subtract then GOOD for ME */
3099     if (genMinusDec (ic) == TRUE)
3100         goto release;
3101
3102     }
3103
3104     size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3105
3106     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3107         CLRC;
3108     }
3109     else{
3110         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3111         lit = - (long)lit;
3112     }
3113
3114
3115     /* if literal, add a,#-lit, else normal subb */
3116     while (size--) {
3117         MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3118         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
3119             emitcode("subb","a,%s",
3120                      aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3121         else{
3122             /* first add without previous c */
3123             if(!offset)
3124                 emitcode("add","a,#0x%02x",
3125                          (unsigned int)(lit & 0x0FFL));
3126             else
3127                 emitcode("addc","a,#0x%02x",
3128                          (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3129         }
3130
3131         if (pushResult)
3132         {
3133             emitcode("push", "acc");
3134         }
3135         else
3136         {
3137             aopPut(AOP(IC_RESULT(ic)),"a",offset);
3138         }
3139         offset++;
3140     }
3141
3142     if (pushResult)
3143     {
3144         aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3145
3146         size = getDataSize(IC_LEFT(ic));
3147
3148         /* If the pushed data is bigger than the result,
3149          * simply discard unused bytes. Icky, but works.
3150          *
3151          * Should we throw a warning here? We're losing data...
3152          */
3153         while (size > getDataSize(IC_RESULT(ic)))
3154         {
3155            emitcode(";", "discarding unused result byte.");
3156            emitcode("pop", "acc");
3157            size--;
3158            offset--; 
3159         }
3160
3161         while(size--)
3162         {
3163             emitcode("pop", "acc");
3164             aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3165         }
3166     }
3167
3168     adjustArithmeticResult(ic);
3169         
3170 release:
3171     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3172     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3173     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3174 }
3175
3176
3177 /*-----------------------------------------------------------------*/
3178 /* genMultbits :- multiplication of bits                           */
3179 /*-----------------------------------------------------------------*/
3180 static void genMultbits (operand *left, 
3181                          operand *right, 
3182                          operand *result)
3183 {
3184     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3185     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3186     outBitC(result);
3187 }
3188
3189
3190 /*-----------------------------------------------------------------*/
3191 /* genMultOneByte : 8 bit multiplication & division                */
3192 /*-----------------------------------------------------------------*/
3193 static void genMultOneByte (operand *left,
3194                             operand *right,
3195                             operand *result)
3196 {
3197     link *opetype = operandType(result);
3198     char *l ;
3199     symbol *lbl ;
3200     int size,offset;
3201
3202     /* (if two literals, the value is computed before) */
3203     /* if one literal, literal on the right */
3204     if (AOP_TYPE(left) == AOP_LIT){
3205         operand *t = right;
3206         right = left;
3207         left = t;
3208     }
3209
3210     size = AOP_SIZE(result);
3211     /* signed or unsigned */
3212     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3213     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3214     MOVA(l);       
3215     emitcode("mul","ab");
3216     /* if result size = 1, mul signed = mul unsigned */
3217     aopPut(AOP(result),"a",0);
3218     if (size > 1){
3219         if (SPEC_USIGN(opetype)){
3220             aopPut(AOP(result),"b",1);
3221             if (size > 2)
3222                 /* for filling the MSBs */
3223                 emitcode("clr","a");
3224         }
3225         else{
3226             emitcode("mov","a,b");
3227
3228             /* adjust the MSB if left or right neg */
3229
3230             /* if one literal */
3231             if (AOP_TYPE(right) == AOP_LIT){
3232                 /* AND literal negative */
3233                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3234                     /* adjust MSB (c==0 after mul) */
3235                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3236                 }
3237             }
3238             else{
3239                 lbl = newiTempLabel(NULL);
3240                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3241                 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3242                 emitcode("","%05d$:",(lbl->key+100));
3243                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3244                 lbl = newiTempLabel(NULL);      
3245                 emitcode("jc","%05d$",(lbl->key+100));          
3246                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3247                 emitcode("","%05d$:",(lbl->key+100));
3248             }
3249
3250             lbl = newiTempLabel(NULL);
3251             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3252             emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3253             emitcode("","%05d$:",(lbl->key+100));
3254             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3255             lbl = newiTempLabel(NULL);      
3256             emitcode("jc","%05d$",(lbl->key+100));          
3257             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3258             emitcode("","%05d$:",(lbl->key+100));
3259
3260             aopPut(AOP(result),"a",1);
3261             if(size > 2){
3262                 /* get the sign */
3263                 emitcode("rlc","a");
3264                 emitcode("subb","a,acc");
3265             }
3266         }
3267         size -= 2;   
3268         offset = 2;
3269         if (size > 0)
3270             while (size--)
3271                 aopPut(AOP(result),"a",offset++);
3272     }
3273 }
3274
3275 /*-----------------------------------------------------------------*/
3276 /* genMult - generates code for multiplication                     */
3277 /*-----------------------------------------------------------------*/
3278 static void genMult (iCode *ic)
3279 {
3280     operand *left = IC_LEFT(ic);
3281     operand *right = IC_RIGHT(ic);
3282     operand *result= IC_RESULT(ic);   
3283
3284     D(emitcode(";", "genMult "););
3285
3286     /* assign the amsops */
3287     AOP_OP_3(ic);
3288 #if 0
3289     aopOp (left,ic,FALSE, FALSE);
3290     aopOp (right,ic,FALSE, TRUE);
3291     aopOp (result,ic,TRUE, FALSE);
3292 #endif
3293
3294     /* special cases first */
3295     /* both are bits */
3296     if (AOP_TYPE(left) == AOP_CRY &&
3297         AOP_TYPE(right)== AOP_CRY) {
3298         genMultbits(left,right,result);
3299         goto release ;
3300     }
3301
3302     /* if both are of size == 1 */
3303     if (AOP_SIZE(left) == 1 &&
3304         AOP_SIZE(right) == 1 ) {
3305         genMultOneByte(left,right,result);
3306         goto release ;
3307     }
3308
3309     /* should have been converted to function call */       
3310     assert(1) ;
3311
3312 release :
3313     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3314     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3315     freeAsmop(result,NULL,ic,TRUE); 
3316 }
3317
3318 /*-----------------------------------------------------------------*/
3319 /* genDivbits :- division of bits                                  */
3320 /*-----------------------------------------------------------------*/
3321 static void genDivbits (operand *left, 
3322                         operand *right, 
3323                         operand *result)
3324 {
3325
3326     char *l;
3327
3328     /* the result must be bit */
3329     LOAD_AB_FOR_DIV(left, right, l);
3330     emitcode("div","ab");
3331     emitcode("rrc","a");
3332     aopPut(AOP(result),"c",0);
3333 }
3334
3335 /*-----------------------------------------------------------------*/
3336 /* genDivOneByte : 8 bit division                                  */
3337 /*-----------------------------------------------------------------*/
3338 static void genDivOneByte (operand *left,
3339                            operand *right,
3340                            operand *result)
3341 {
3342     link *opetype = operandType(result);
3343     char *l ;
3344     symbol *lbl ;
3345     int size,offset;
3346
3347     size = AOP_SIZE(result) - 1;
3348     offset = 1;
3349     /* signed or unsigned */
3350     if (SPEC_USIGN(opetype)) {
3351         /* unsigned is easy */
3352         LOAD_AB_FOR_DIV(left, right, l);
3353         emitcode("div","ab");
3354         aopPut(AOP(result),"a",0);
3355         while (size--)
3356             aopPut(AOP(result),zero,offset++);
3357         return ;
3358     }
3359
3360     /* signed is a little bit more difficult */
3361
3362     /* save the signs of the operands */
3363     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);    
3364     MOVA(l);    
3365     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3366     emitcode("push","acc"); /* save it on the stack */
3367
3368     /* now sign adjust for both left & right */
3369     l =  aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3370     MOVA(l);       
3371     lbl = newiTempLabel(NULL);
3372     emitcode("jnb","acc.7,%05d$",(lbl->key+100));   
3373     emitcode("cpl","a");   
3374     emitcode("inc","a");
3375     emitcode("","%05d$:",(lbl->key+100));
3376     emitcode("mov","b,a");
3377
3378     /* sign adjust left side */
3379     l =  aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3380     MOVA(l);
3381
3382     lbl = newiTempLabel(NULL);
3383     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3384     emitcode("cpl","a");
3385     emitcode("inc","a");
3386     emitcode("","%05d$:",(lbl->key+100));
3387
3388     /* now the division */
3389     emitcode("nop", "; workaround for DS80C390 div bug.");
3390     emitcode("div","ab");
3391     /* we are interested in the lower order
3392     only */
3393     emitcode("mov","b,a");
3394     lbl = newiTempLabel(NULL);
3395     emitcode("pop","acc");   
3396     /* if there was an over flow we don't 
3397     adjust the sign of the result */
3398     emitcode("jb","ov,%05d$",(lbl->key+100));
3399     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3400     CLRC;
3401     emitcode("clr","a");
3402     emitcode("subb","a,b");
3403     emitcode("mov","b,a");
3404     emitcode("","%05d$:",(lbl->key+100));
3405
3406     /* now we are done */
3407     aopPut(AOP(result),"b",0);
3408     if(size > 0){
3409         emitcode("mov","c,b.7");
3410         emitcode("subb","a,acc");   
3411     }
3412     while (size--)
3413         aopPut(AOP(result),"a",offset++);
3414
3415 }
3416
3417 /*-----------------------------------------------------------------*/
3418 /* genDiv - generates code for division                            */
3419 /*-----------------------------------------------------------------*/
3420 static void genDiv (iCode *ic)
3421 {
3422     operand *left = IC_LEFT(ic);
3423     operand *right = IC_RIGHT(ic);
3424     operand *result= IC_RESULT(ic);   
3425
3426     D(emitcode(";", "genDiv "););
3427
3428     /* assign the amsops */
3429     AOP_OP_3(ic);
3430 #if 0
3431     aopOp (left,ic,FALSE, FALSE);
3432     aopOp (right,ic,FALSE, TRUE);
3433     aopOp (result,ic,TRUE, FALSE);
3434 #endif
3435
3436     /* special cases first */
3437     /* both are bits */
3438     if (AOP_TYPE(left) == AOP_CRY &&
3439         AOP_TYPE(right)== AOP_CRY) {
3440         genDivbits(left,right,result);
3441         goto release ;
3442     }
3443
3444     /* if both are of size == 1 */
3445     if (AOP_SIZE(left) == 1 &&
3446         AOP_SIZE(right) == 1 ) {
3447         genDivOneByte(left,right,result);
3448         goto release ;
3449     }
3450
3451     /* should have been converted to function call */
3452     assert(1);
3453 release :
3454     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3455     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3456     freeAsmop(result,NULL,ic,TRUE); 
3457 }
3458
3459 /*-----------------------------------------------------------------*/
3460 /* genModbits :- modulus of bits                                   */
3461 /*-----------------------------------------------------------------*/
3462 static void genModbits (operand *left, 
3463                         operand *right, 
3464                         operand *result)
3465 {
3466
3467     char *l;
3468
3469     /* the result must be bit */    
3470     LOAD_AB_FOR_DIV(left, right, l);
3471     emitcode("div","ab");
3472     emitcode("mov","a,b");
3473     emitcode("rrc","a");
3474     aopPut(AOP(result),"c",0);
3475 }
3476
3477 /*-----------------------------------------------------------------*/
3478 /* genModOneByte : 8 bit modulus                                   */
3479 /*-----------------------------------------------------------------*/
3480 static void genModOneByte (operand *left,
3481                            operand *right,
3482                            operand *result)
3483 {
3484     link *opetype = operandType(result);
3485     char *l ;
3486     symbol *lbl ;
3487
3488     /* signed or unsigned */
3489     if (SPEC_USIGN(opetype)) {
3490         /* unsigned is easy */
3491         LOAD_AB_FOR_DIV(left, right, l);
3492         emitcode("div","ab");
3493         aopPut(AOP(result),"b",0);
3494         return ;
3495     }
3496
3497     /* signed is a little bit more difficult */
3498
3499     /* save the signs of the operands */
3500     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3501     MOVA(l);
3502
3503     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3504     emitcode("push","acc"); /* save it on the stack */
3505
3506     /* now sign adjust for both left & right */
3507     l =  aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3508     MOVA(l);
3509
3510     lbl = newiTempLabel(NULL);
3511     emitcode("jnb","acc.7,%05d$",(lbl->key+100));  
3512     emitcode("cpl","a");   
3513     emitcode("inc","a");
3514     emitcode("","%05d$:",(lbl->key+100));
3515     emitcode("mov","b,a"); 
3516
3517     /* sign adjust left side */
3518     l =  aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3519     MOVA(l);
3520
3521     lbl = newiTempLabel(NULL);
3522     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3523     emitcode("cpl","a");   
3524     emitcode("inc","a");
3525     emitcode("","%05d$:",(lbl->key+100));
3526
3527     /* now the multiplication */
3528     emitcode("nop", "; workaround for DS80C390 div bug.");
3529     emitcode("div","ab");
3530     /* we are interested in the lower order
3531     only */
3532     lbl = newiTempLabel(NULL);
3533     emitcode("pop","acc");   
3534     /* if there was an over flow we don't 
3535     adjust the sign of the result */
3536     emitcode("jb","ov,%05d$",(lbl->key+100));
3537     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3538     CLRC ;
3539     emitcode("clr","a");
3540     emitcode("subb","a,b");
3541     emitcode("mov","b,a");
3542     emitcode("","%05d$:",(lbl->key+100));
3543
3544     /* now we are done */
3545     aopPut(AOP(result),"b",0);
3546
3547 }
3548
3549 /*-----------------------------------------------------------------*/
3550 /* genMod - generates code for division                            */
3551 /*-----------------------------------------------------------------*/
3552 static void genMod (iCode *ic)
3553 {
3554     operand *left = IC_LEFT(ic);
3555     operand *right = IC_RIGHT(ic);
3556     operand *result= IC_RESULT(ic);  
3557
3558     D(emitcode(";", "genMod "););
3559
3560     /* assign the amsops */
3561     AOP_OP_3(ic);
3562 #if 0
3563     aopOp (left,ic,FALSE, FALSE);
3564     aopOp (right,ic,FALSE, TRUE);
3565     aopOp (result,ic,TRUE, FALSE);
3566 #endif
3567
3568     /* special cases first */
3569     /* both are bits */
3570     if (AOP_TYPE(left) == AOP_CRY &&
3571         AOP_TYPE(right)== AOP_CRY) {
3572         genModbits(left,right,result);
3573         goto release ;
3574     }
3575
3576     /* if both are of size == 1 */
3577     if (AOP_SIZE(left) == 1 &&
3578         AOP_SIZE(right) == 1 ) {
3579         genModOneByte(left,right,result);
3580         goto release ;
3581     }
3582
3583     /* should have been converted to function call */
3584     assert(1);
3585
3586 release :
3587     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3588     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3589     freeAsmop(result,NULL,ic,TRUE); 
3590 }
3591
3592 /*-----------------------------------------------------------------*/
3593 /* genIfxJump :- will create a jump depending on the ifx           */
3594 /*-----------------------------------------------------------------*/
3595 static void genIfxJump (iCode *ic, char *jval)
3596 {
3597     symbol *jlbl ;
3598     symbol *tlbl = newiTempLabel(NULL);
3599     char *inst;
3600
3601     D(emitcode(";", "genIfxJump "););
3602
3603     /* if true label then we jump if condition
3604     supplied is true */
3605     if ( IC_TRUE(ic) ) {
3606         jlbl = IC_TRUE(ic);
3607         inst = ((strcmp(jval,"a") == 0 ? "jz" :
3608                  (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3609     }
3610     else {
3611         /* false label is present */
3612         jlbl = IC_FALSE(ic) ;
3613         inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3614                  (strcmp(jval,"c") == 0 ? "jc" : "jb" )));              
3615     }
3616     if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0) 
3617         emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3618     else
3619         emitcode(inst,"%05d$",tlbl->key+100);
3620     emitcode("ljmp","%05d$",jlbl->key+100);
3621     emitcode("","%05d$:",tlbl->key+100);                
3622
3623     /* mark the icode as generated */
3624     ic->generated = 1;
3625 }
3626
3627 /*-----------------------------------------------------------------*/
3628 /* genCmp :- greater or less than comparison                       */
3629 /*-----------------------------------------------------------------*/
3630 static void genCmp (operand *left,operand *right,
3631                     operand *result, iCode *ifx, int sign)
3632 {
3633     int size, offset = 0 ;
3634     unsigned long lit = 0L;
3635     bool swappedOps = FALSE;
3636
3637     D(emitcode(";", "genCmp"););
3638
3639 #if 0
3640     /* If left if lit and right isn't, swap 'em. */
3641     if (AOP_TYPE(left) == AOP_LIT &&
3642         AOP_TYPE(right) != AOP_LIT)
3643     {
3644         operand *tmp = left;
3645         left = right;
3646         right = tmp;
3647         D(emitcode(";", "kevin literal hack"););
3648         swappedOps = !swappedOps;
3649     }
3650
3651     if (AOP_NEEDSACC(right))
3652     {
3653         if (AOP_NEEDSACC(left))
3654         {
3655             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3656                    "both CMP operands need ACC!");
3657             exit(1);
3658         }
3659         else
3660         {
3661             operand *tmp = left;
3662             left = right;
3663             right = tmp;
3664             D(emitcode(";", "kevin ACC hack"););
3665             swappedOps = !swappedOps;
3666         }
3667     }
3668 #endif
3669
3670     /* if left & right are bit variables */
3671     if (AOP_TYPE(left) == AOP_CRY &&
3672         AOP_TYPE(right) == AOP_CRY ) {
3673         emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3674         emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3675     } else {
3676         /* subtract right from left if at the
3677         end the carry flag is set then we know that
3678         left is greater than right */
3679         size = max(AOP_SIZE(left),AOP_SIZE(right));
3680
3681         /* if unsigned char cmp with lit, do cjne left,#right,zz */
3682         if((size == 1) && !sign &&
3683            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3684             symbol *lbl  = newiTempLabel(NULL);
3685             emitcode("cjne","%s,%s,%05d$",
3686                      aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3687                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3688                      lbl->key+100);
3689             emitcode("","%05d$:",lbl->key+100);
3690         } else {
3691             if(AOP_TYPE(right) == AOP_LIT){
3692                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3693                 /* optimize if(x < 0) or if(x >= 0) */
3694                 if(lit == 0L){
3695                     if(!sign){
3696                         CLRC;
3697                     }
3698                     else{
3699                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3700                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3701                             genIfxJump (ifx,"acc.7");
3702                             return;
3703                         }
3704                         else    
3705                             emitcode("rlc","a");
3706                     }
3707                     goto release;
3708                 }
3709             }
3710             CLRC;
3711             while (size--)
3712             {
3713                 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3714                 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3715                 emitcode(";", "genCmp #2");
3716                 if (sign && (size == 0))
3717                 {
3718                     emitcode(";", "genCmp #3");
3719                     emitcode("xrl","a,#0x80");
3720                     if (AOP_TYPE(right) == AOP_LIT)
3721                     {
3722                         unsigned long lit = (unsigned long)
3723                             floatFromVal(AOP(right)->aopu.aop_lit);
3724                         emitcode(";", "genCmp #3.1");
3725                         emitcode("subb","a,#0x%02x",
3726                             0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3727                     }
3728                     else
3729                     {
3730                         emitcode(";", "genCmp #3.2");
3731                         if (AOP_NEEDSACC(right))
3732                         {
3733                             emitcode("push", "acc");
3734                         }
3735                         emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3736                                   FALSE,FALSE,FALSE));
3737                         emitcode("xrl","b,#0x80");
3738                         if (AOP_NEEDSACC(right))
3739                         {
3740                             emitcode("pop", "acc");
3741                         }
3742                         emitcode("subb","a,b");
3743                     }
3744                 }
3745                 else
3746                 {
3747                     const char *s;
3748
3749                     emitcode(";", "genCmp #4");
3750                     if (AOP_NEEDSACC(right))
3751                     {
3752                         /* Yuck!! */
3753                         emitcode(";", "genCmp #4.1");
3754                         emitcode("xch", "a, b");
3755                         MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3756                         emitcode("xch", "a, b");
3757                         s = "b";
3758                     }
3759                     else
3760                     {
3761                         emitcode(";", "genCmp #4.2");
3762                         s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3763                     }
3764
3765                     emitcode("subb","a,%s",s);
3766                 }
3767             }
3768         }
3769     }
3770
3771 release:
3772     if (swappedOps)
3773     {
3774         D(emitcode(";","kevHack: flip carry."););
3775         emitcode("cpl", "c");
3776     }
3777
3778     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3779         outBitC(result);
3780     } else {
3781         /* if the result is used in the next
3782         ifx conditional branch then generate
3783         code a little differently */
3784         if (ifx )
3785             genIfxJump (ifx,"c");
3786         else
3787             outBitC(result);
3788         /* leave the result in acc */
3789     }
3790 }
3791
3792 /*-----------------------------------------------------------------*/
3793 /* genCmpGt :- greater than comparison                             */
3794 /*-----------------------------------------------------------------*/
3795 static void genCmpGt (iCode *ic, iCode *ifx)
3796 {
3797     operand *left, *right, *result;
3798     link *letype , *retype;
3799     int sign ;
3800
3801     D(emitcode(";", "genCmpGt "););
3802
3803     left = IC_LEFT(ic);
3804     right= IC_RIGHT(ic);
3805     result = IC_RESULT(ic);
3806
3807     letype = getSpec(operandType(left));
3808     retype =getSpec(operandType(right));
3809     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3810     /* assign the amsops */
3811     AOP_OP_3(ic);
3812 #if 0
3813     aopOp (left,ic,FALSE, TRUE);
3814     aopOp (right,ic,FALSE, FALSE);
3815     aopOp (result,ic,TRUE, FALSE);
3816 #endif
3817
3818     genCmp(right, left, result, ifx, sign);
3819
3820     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3821     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3822     freeAsmop(result,NULL,ic,TRUE); 
3823 }
3824
3825 /*-----------------------------------------------------------------*/
3826 /* genCmpLt - less than comparisons                                */
3827 /*-----------------------------------------------------------------*/
3828 static void genCmpLt (iCode *ic, iCode *ifx)
3829 {
3830     operand *left, *right, *result;
3831     link *letype , *retype;
3832     int sign ;
3833
3834     D(emitcode(";", "genCmpLt "););
3835
3836     left = IC_LEFT(ic);
3837     right= IC_RIGHT(ic);
3838     result = IC_RESULT(ic);
3839
3840     letype = getSpec(operandType(left));
3841     retype =getSpec(operandType(right));
3842     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3843
3844     /* assign the amsops */
3845     AOP_OP_3(ic);
3846 #if 0
3847     aopOp (left,ic,FALSE, FALSE);
3848     aopOp (right,ic,FALSE, TRUE);
3849     aopOp (result,ic,TRUE, FALSE);
3850 #endif
3851
3852     genCmp(left, right, result, ifx, sign);
3853
3854     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3855     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3856     freeAsmop(result,NULL,ic,TRUE); 
3857 }
3858
3859 /*-----------------------------------------------------------------*/
3860 /* gencjneshort - compare and jump if not equal                    */
3861 /*-----------------------------------------------------------------*/
3862 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3863 {
3864     int size = max(AOP_SIZE(left),AOP_SIZE(right));
3865     int offset = 0;
3866     unsigned long lit = 0L;
3867
3868     D(emitcode(";", "gencjneshort"););
3869
3870     /* if the left side is a literal or 
3871     if the right is in a pointer register and left 
3872     is not */
3873     if ((AOP_TYPE(left) == AOP_LIT) || 
3874         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3875         operand *t = right;
3876         right = left;
3877         left = t;
3878     }
3879     if(AOP_TYPE(right) == AOP_LIT)
3880         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3881
3882     /* if the right side is a literal then anything goes */
3883     if (AOP_TYPE(right) == AOP_LIT &&
3884         AOP_TYPE(left) != AOP_DIR ) {
3885         while (size--) {
3886             char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
3887             MOVA(l);
3888             emitcode("cjne","a,%s,%05d$",
3889                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3890                      lbl->key+100);
3891             offset++;
3892         }
3893     }
3894
3895     /* if the right side is in a register or in direct space or
3896     if the left is a pointer register & right is not */    
3897     else if (AOP_TYPE(right) == AOP_REG ||
3898              AOP_TYPE(right) == AOP_DIR || 
3899              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3900              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3901         while (size--) {
3902             MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3903             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3904                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3905                 emitcode("jnz","%05d$",lbl->key+100);
3906             else
3907                 emitcode("cjne","a,%s,%05d$",
3908                          aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
3909                          lbl->key+100);
3910             offset++;
3911         }
3912     } else {
3913         /* right is a pointer reg need both a & b */
3914         while(size--) {
3915             char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
3916             if(strcmp(l,"b"))
3917                 emitcode("mov","b,%s",l);
3918             MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
3919             emitcode("cjne","a,b,%05d$",lbl->key+100);    
3920             offset++;
3921         }
3922     }
3923 }
3924
3925 /*-----------------------------------------------------------------*/
3926 /* gencjne - compare and jump if not equal                         */
3927 /*-----------------------------------------------------------------*/
3928 static void gencjne(operand *left, operand *right, symbol *lbl)
3929 {
3930     symbol *tlbl  = newiTempLabel(NULL);
3931
3932     D(emitcode(";", "gencjne"););
3933
3934     gencjneshort(left, right, lbl);
3935
3936     emitcode("mov","a,%s",one);
3937     emitcode("sjmp","%05d$",tlbl->key+100);
3938     emitcode("","%05d$:",lbl->key+100);
3939     emitcode("clr","a");
3940     emitcode("","%05d$:",tlbl->key+100);
3941 }
3942
3943 /*-----------------------------------------------------------------*/
3944 /* genCmpEq - generates code for equal to                          */
3945 /*-----------------------------------------------------------------*/
3946 static void genCmpEq (iCode *ic, iCode *ifx)
3947 {
3948     operand *left, *right, *result;
3949
3950     D(emitcode(";", "genCmpEq "););
3951
3952     AOP_OP_3(ic);
3953     AOP_SET_LOCALS(ic);
3954 #if 0
3955     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
3956     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3957     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3958 #endif
3959
3960     /* if literal, literal on the right or 
3961     if the right is in a pointer register and left 
3962     is not */
3963     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
3964         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3965         operand *t = IC_RIGHT(ic);
3966         IC_RIGHT(ic) = IC_LEFT(ic);
3967         IC_LEFT(ic) = t;
3968     }
3969
3970     if(ifx && !AOP_SIZE(result)){
3971         symbol *tlbl;
3972         /* if they are both bit variables */
3973         if (AOP_TYPE(left) == AOP_CRY &&
3974             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3975             if(AOP_TYPE(right) == AOP_LIT){
3976                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3977                 if(lit == 0L){
3978                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3979                     emitcode("cpl","c");
3980                 } else if(lit == 1L) {
3981                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3982                 } else {
3983                     emitcode("clr","c");
3984                 }
3985                 /* AOP_TYPE(right) == AOP_CRY */
3986             } else {
3987                 symbol *lbl = newiTempLabel(NULL);
3988                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3989                 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3990                 emitcode("cpl","c");
3991                 emitcode("","%05d$:",(lbl->key+100));
3992             }
3993             /* if true label then we jump if condition
3994             supplied is true */
3995             tlbl = newiTempLabel(NULL);
3996             if ( IC_TRUE(ifx) ) {
3997                 emitcode("jnc","%05d$",tlbl->key+100);
3998                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3999             } else {
4000                 emitcode("jc","%05d$",tlbl->key+100);
4001                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4002             }
4003             emitcode("","%05d$:",tlbl->key+100);                
4004         } else {
4005             tlbl = newiTempLabel(NULL);
4006             gencjneshort(left, right, tlbl);
4007             if ( IC_TRUE(ifx) ) {
4008                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4009                 emitcode("","%05d$:",tlbl->key+100);                
4010             } else {
4011                 symbol *lbl = newiTempLabel(NULL);
4012                 emitcode("sjmp","%05d$",lbl->key+100);
4013                 emitcode("","%05d$:",tlbl->key+100);                
4014                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4015                 emitcode("","%05d$:",lbl->key+100);             
4016             }
4017         }
4018         /* mark the icode as generated */
4019         ifx->generated = 1;
4020         goto release ;
4021     }
4022
4023     /* if they are both bit variables */
4024     if (AOP_TYPE(left) == AOP_CRY &&
4025         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4026         if(AOP_TYPE(right) == AOP_LIT){
4027             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4028             if(lit == 0L){
4029                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4030                 emitcode("cpl","c");
4031             } else if(lit == 1L) {
4032                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4033             } else {
4034                 emitcode("clr","c");
4035             }
4036             /* AOP_TYPE(right) == AOP_CRY */
4037         } else {
4038             symbol *lbl = newiTempLabel(NULL);
4039             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4040             emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4041             emitcode("cpl","c");
4042             emitcode("","%05d$:",(lbl->key+100));
4043         }
4044         /* c = 1 if egal */
4045         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4046             outBitC(result);
4047             goto release ;
4048         }
4049         if (ifx) {
4050             genIfxJump (ifx,"c");
4051             goto release ;
4052         }
4053         /* if the result is used in an arithmetic operation
4054         then put the result in place */
4055         outBitC(result);
4056     } else {
4057         gencjne(left,right,newiTempLabel(NULL));    
4058         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4059             aopPut(AOP(result),"a",0);
4060             goto release ;
4061         }
4062         if (ifx) {
4063             genIfxJump (ifx,"a");
4064             goto release ;
4065         }
4066         /* if the result is used in an arithmetic operation
4067         then put the result in place */
4068         if (AOP_TYPE(result) != AOP_CRY) 
4069             outAcc(result);
4070         /* leave the result in acc */
4071     }
4072
4073 release:
4074     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4075     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4076     freeAsmop(result,NULL,ic,TRUE);
4077 }
4078
4079 /*-----------------------------------------------------------------*/
4080 /* ifxForOp - returns the icode containing the ifx for operand     */
4081 /*-----------------------------------------------------------------*/
4082 static iCode *ifxForOp ( operand *op, iCode *ic )
4083 {
4084     /* if true symbol then needs to be assigned */
4085     if (IS_TRUE_SYMOP(op))
4086         return NULL ;
4087
4088     /* if this has register type condition and
4089     the next instruction is ifx with the same operand
4090     and live to of the operand is upto the ifx only then */
4091     if (ic->next &&
4092         ic->next->op == IFX &&
4093         IC_COND(ic->next)->key == op->key &&
4094         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4095         return ic->next;
4096
4097     return NULL;
4098 }
4099 /*-----------------------------------------------------------------*/
4100 /* genAndOp - for && operation                                     */
4101 /*-----------------------------------------------------------------*/
4102 static void genAndOp (iCode *ic)
4103 {
4104     operand *left,*right, *result;
4105     symbol *tlbl;
4106
4107     D(emitcode(";", "genAndOp "););
4108
4109     /* note here that && operations that are in an
4110     if statement are taken away by backPatchLabels
4111     only those used in arthmetic operations remain */
4112     AOP_OP_3(ic);
4113     AOP_SET_LOCALS(ic);
4114 #if 0
4115     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4116     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4117     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4118 #endif
4119
4120     /* if both are bit variables */
4121     if (AOP_TYPE(left) == AOP_CRY &&
4122         AOP_TYPE(right) == AOP_CRY ) {
4123         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4124         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4125         outBitC(result);
4126     } else {
4127         tlbl = newiTempLabel(NULL);
4128         toBoolean(left);    
4129         emitcode("jz","%05d$",tlbl->key+100);
4130         toBoolean(right);
4131         emitcode("","%05d$:",tlbl->key+100);
4132         outBitAcc(result);
4133     }
4134
4135     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4136     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4137     freeAsmop(result,NULL,ic,TRUE);
4138 }
4139
4140
4141 /*-----------------------------------------------------------------*/
4142 /* genOrOp - for || operation                                      */
4143 /*-----------------------------------------------------------------*/
4144 static void genOrOp (iCode *ic)
4145 {
4146     operand *left,*right, *result;
4147     symbol *tlbl;
4148
4149     D(emitcode(";", "genOrOp "););
4150
4151     /* note here that || operations that are in an
4152     if statement are taken away by backPatchLabels
4153     only those used in arthmetic operations remain */
4154     AOP_OP_3(ic);
4155     AOP_SET_LOCALS(ic);
4156 #if 0
4157     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4158     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4159     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4160 #endif
4161
4162     /* if both are bit variables */
4163     if (AOP_TYPE(left) == AOP_CRY &&
4164         AOP_TYPE(right) == AOP_CRY ) {
4165         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4166         emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4167         outBitC(result);
4168     } else {
4169         tlbl = newiTempLabel(NULL);
4170         toBoolean(left);
4171         emitcode("jnz","%05d$",tlbl->key+100);
4172         toBoolean(right);
4173         emitcode("","%05d$:",tlbl->key+100);
4174         outBitAcc(result);
4175     }
4176
4177     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4178     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4179     freeAsmop(result,NULL,ic,TRUE);            
4180 }
4181
4182 /*-----------------------------------------------------------------*/
4183 /* isLiteralBit - test if lit == 2^n                               */
4184 /*-----------------------------------------------------------------*/
4185 static int isLiteralBit(unsigned long lit)
4186 {
4187     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4188     0x100L,0x200L,0x400L,0x800L,
4189     0x1000L,0x2000L,0x4000L,0x8000L,
4190     0x10000L,0x20000L,0x40000L,0x80000L,
4191     0x100000L,0x200000L,0x400000L,0x800000L,
4192     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4193     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4194     int idx;
4195     
4196     for(idx = 0; idx < 32; idx++)
4197         if(lit == pw[idx])
4198             return idx+1;
4199     return 0;
4200 }
4201
4202 /*-----------------------------------------------------------------*/
4203 /* continueIfTrue -                                                */
4204 /*-----------------------------------------------------------------*/
4205 static void continueIfTrue (iCode *ic)
4206 {
4207     if(IC_TRUE(ic))
4208         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4209     ic->generated = 1;
4210 }
4211
4212 /*-----------------------------------------------------------------*/
4213 /* jmpIfTrue -                                                     */
4214 /*-----------------------------------------------------------------*/
4215 static void jumpIfTrue (iCode *ic)
4216 {
4217     if(!IC_TRUE(ic))
4218         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4219     ic->generated = 1;
4220 }
4221
4222 /*-----------------------------------------------------------------*/
4223 /* jmpTrueOrFalse -                                                */
4224 /*-----------------------------------------------------------------*/
4225 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4226 {
4227     // ugly but optimized by peephole
4228     if(IC_TRUE(ic)){
4229         symbol *nlbl = newiTempLabel(NULL);
4230         emitcode("sjmp","%05d$",nlbl->key+100);                 
4231         emitcode("","%05d$:",tlbl->key+100);
4232         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4233         emitcode("","%05d$:",nlbl->key+100);
4234     }
4235     else{
4236         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4237         emitcode("","%05d$:",tlbl->key+100);
4238     }
4239     ic->generated = 1;
4240 }
4241
4242 /*-----------------------------------------------------------------*/
4243 /* genAnd  - code for and                                          */
4244 /*-----------------------------------------------------------------*/
4245 static void genAnd (iCode *ic, iCode *ifx)
4246 {
4247     operand *left, *right, *result;
4248     int size, offset=0;  
4249     unsigned long lit = 0L;
4250     int bytelit = 0;
4251     char buffer[10];
4252
4253     D(emitcode(";", "genAnd "););
4254
4255     AOP_OP_3(ic);
4256     AOP_SET_LOCALS(ic);
4257 #if 0
4258     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4259     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4260     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4261 #endif
4262
4263 #ifdef DEBUG_TYPE
4264     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4265              AOP_TYPE(result),
4266              AOP_TYPE(left), AOP_TYPE(right));
4267     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4268              AOP_SIZE(result),
4269              AOP_SIZE(left), AOP_SIZE(right));
4270 #endif
4271
4272     /* if left is a literal & right is not then exchange them */
4273     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4274         AOP_NEEDSACC(left)) {
4275         operand *tmp = right ;
4276         right = left;
4277         left = tmp;
4278     }
4279
4280     /* if result = right then exchange them */
4281     if(sameRegs(AOP(result),AOP(right))){
4282         operand *tmp = right ;
4283         right = left;
4284         left = tmp;
4285     }
4286
4287     /* if right is bit then exchange them */
4288     if (AOP_TYPE(right) == AOP_CRY &&
4289         AOP_TYPE(left) != AOP_CRY){
4290         operand *tmp = right ;
4291         right = left;
4292         left = tmp;
4293     }
4294     if(AOP_TYPE(right) == AOP_LIT)
4295         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4296
4297     size = AOP_SIZE(result);
4298
4299     // if(bit & yy)
4300     // result = bit & yy;
4301     if (AOP_TYPE(left) == AOP_CRY){
4302         // c = bit & literal;
4303         if(AOP_TYPE(right) == AOP_LIT){
4304             if(lit & 1) {
4305                 if(size && sameRegs(AOP(result),AOP(left)))
4306                     // no change
4307                     goto release;
4308                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4309             } else {
4310                 // bit(result) = 0;
4311                 if(size && (AOP_TYPE(result) == AOP_CRY)){
4312                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4313                     goto release;
4314                 }
4315                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4316                     jumpIfTrue(ifx);
4317                     goto release;
4318                 }
4319                 emitcode("clr","c");
4320             }
4321         } else {
4322             if (AOP_TYPE(right) == AOP_CRY){
4323                 // c = bit & bit;
4324                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4325                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4326             } else {
4327                 // c = bit & val;
4328                 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4329                 // c = lsb
4330                 emitcode("rrc","a");
4331                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4332             }
4333         }
4334         // bit = c
4335         // val = c
4336         if(size)
4337             outBitC(result);
4338         // if(bit & ...)
4339         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4340             genIfxJump(ifx, "c");           
4341         goto release ;
4342     }
4343
4344     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4345     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4346     if((AOP_TYPE(right) == AOP_LIT) &&
4347        (AOP_TYPE(result) == AOP_CRY) &&
4348        (AOP_TYPE(left) != AOP_CRY)){
4349         int posbit = isLiteralBit(lit);
4350         /* left &  2^n */
4351         if(posbit){
4352             posbit--;
4353             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4354             // bit = left & 2^n
4355             if(size)
4356                 emitcode("mov","c,acc.%d",posbit&0x07);
4357             // if(left &  2^n)
4358             else{
4359                 if(ifx){
4360                     sprintf(buffer,"acc.%d",posbit&0x07);
4361                     genIfxJump(ifx, buffer);
4362                 }
4363                 goto release;
4364             }
4365         } else {
4366             symbol *tlbl = newiTempLabel(NULL);
4367             int sizel = AOP_SIZE(left);
4368             if(size)
4369                 emitcode("setb","c");
4370             while(sizel--){
4371                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4372                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4373                     // byte ==  2^n ?
4374                     if((posbit = isLiteralBit(bytelit)) != 0)
4375                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4376                     else{
4377                         if(bytelit != 0x0FFL)
4378                             emitcode("anl","a,%s",
4379                                      aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4380                         emitcode("jnz","%05d$",tlbl->key+100);
4381                     }
4382                 }
4383                 offset++;
4384             }
4385             // bit = left & literal
4386             if(size){
4387                 emitcode("clr","c");
4388                 emitcode("","%05d$:",tlbl->key+100);
4389             }
4390             // if(left & literal)
4391             else{
4392                 if(ifx)
4393                     jmpTrueOrFalse(ifx, tlbl);
4394                 goto release ;
4395             }
4396         }
4397         outBitC(result);
4398         goto release ;
4399     }
4400
4401     /* if left is same as result */
4402     if(sameRegs(AOP(result),AOP(left))){
4403         for(;size--; offset++) {
4404             if(AOP_TYPE(right) == AOP_LIT){
4405                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4406                     continue;
4407                 else 
4408                     if (bytelit == 0)
4409                         aopPut(AOP(result),zero,offset);
4410                     else 
4411                         if (IS_AOP_PREG(result)) {
4412                             MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4413                             emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4414                             aopPut(AOP(result),"a",offset);
4415                         } else
4416                             emitcode("anl","%s,%s",
4417                                      aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4418                                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4419             } else {
4420                 if (AOP_TYPE(left) == AOP_ACC)
4421                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4422                 else {
4423                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4424                     if (IS_AOP_PREG(result)) {
4425                         emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4426                         aopPut(AOP(result),"a",offset);
4427
4428                     } else
4429                         emitcode("anl","%s,a",
4430                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4431                 }
4432             }
4433         }
4434     } else {
4435         // left & result in different registers
4436         if(AOP_TYPE(result) == AOP_CRY){
4437             // result = bit
4438             // if(size), result in bit
4439             // if(!size && ifx), conditional oper: if(left & right)
4440             symbol *tlbl = newiTempLabel(NULL);
4441             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4442             if(size)
4443                 emitcode("setb","c");
4444             while(sizer--){
4445                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4446                 emitcode("anl","a,%s",
4447                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4448                 emitcode("jnz","%05d$",tlbl->key+100);
4449                 offset++;
4450             }
4451             if(size){
4452                 CLRC;
4453                 emitcode("","%05d$:",tlbl->key+100);
4454                 outBitC(result);
4455             } else if(ifx)
4456                 jmpTrueOrFalse(ifx, tlbl);
4457         } else {
4458             for(;(size--);offset++) {
4459                 // normal case
4460                 // result = left & right
4461                 if(AOP_TYPE(right) == AOP_LIT){
4462                     if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4463                         aopPut(AOP(result),
4464                                aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4465                                offset);
4466                         continue;
4467                     } else if(bytelit == 0){
4468                         aopPut(AOP(result),zero,offset);
4469                         continue;
4470                     }
4471                 }
4472                 // faster than result <- left, anl result,right
4473                 // and better if result is SFR
4474                 if (AOP_TYPE(left) == AOP_ACC) 
4475                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4476                 else {
4477                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4478                     emitcode("anl","a,%s",
4479                              aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4480                 }
4481                 aopPut(AOP(result),"a",offset);
4482             }
4483         }
4484     }
4485
4486 release :
4487     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4489     freeAsmop(result,NULL,ic,TRUE);     
4490 }
4491
4492 /*-----------------------------------------------------------------*/
4493 /* genOr  - code for or                                            */
4494 /*-----------------------------------------------------------------*/
4495 static void genOr (iCode *ic, iCode *ifx)
4496 {
4497     operand *left, *right, *result;
4498     int size, offset=0;
4499     unsigned long lit = 0L;
4500
4501     D(emitcode(";", "genOr "););
4502
4503     AOP_OP_3(ic);
4504     AOP_SET_LOCALS(ic);
4505     #if 0
4506     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4507     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4508     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4509     #endif
4510
4511 #ifdef DEBUG_TYPE
4512     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4513              AOP_TYPE(result),
4514              AOP_TYPE(left), AOP_TYPE(right));
4515     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4516              AOP_SIZE(result),
4517              AOP_SIZE(left), AOP_SIZE(right));
4518 #endif
4519
4520     /* if left is a literal & right is not then exchange them */
4521     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4522         AOP_NEEDSACC(left)) {
4523         operand *tmp = right ;
4524         right = left;
4525         left = tmp;
4526     }
4527
4528     /* if result = right then exchange them */
4529     if(sameRegs(AOP(result),AOP(right))){
4530         operand *tmp = right ;
4531         right = left;
4532         left = tmp;
4533     }
4534
4535     /* if right is bit then exchange them */
4536     if (AOP_TYPE(right) == AOP_CRY &&
4537         AOP_TYPE(left) != AOP_CRY){
4538         operand *tmp = right ;
4539         right = left;
4540         left = tmp;
4541     }
4542     if(AOP_TYPE(right) == AOP_LIT)
4543         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4544
4545     size = AOP_SIZE(result);
4546
4547     // if(bit | yy)
4548     // xx = bit | yy;
4549     if (AOP_TYPE(left) == AOP_CRY){
4550         if(AOP_TYPE(right) == AOP_LIT){
4551             // c = bit & literal;
4552             if(lit){
4553                 // lit != 0 => result = 1
4554                 if(AOP_TYPE(result) == AOP_CRY){
4555                     if(size)
4556                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4557                     else if(ifx)
4558                         continueIfTrue(ifx);
4559                     goto release;
4560                 }
4561                 emitcode("setb","c");
4562             } else {
4563                 // lit == 0 => result = left
4564                 if(size && sameRegs(AOP(result),AOP(left)))
4565                     goto release;
4566                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4567             }
4568         } else {
4569             if (AOP_TYPE(right) == AOP_CRY){
4570                 // c = bit | bit;
4571                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4572                 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4573             }
4574             else{
4575                 // c = bit | val;
4576                 symbol *tlbl = newiTempLabel(NULL);
4577                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4578                     emitcode("setb","c");
4579                 emitcode("jb","%s,%05d$",
4580                          AOP(left)->aopu.aop_dir,tlbl->key+100);
4581                 toBoolean(right);
4582                 emitcode("jnz","%05d$",tlbl->key+100);
4583                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4584                     jmpTrueOrFalse(ifx, tlbl);
4585                     goto release;
4586                 } else {
4587                     CLRC;
4588                     emitcode("","%05d$:",tlbl->key+100);
4589                 }
4590             }
4591         }
4592         // bit = c
4593         // val = c
4594         if(size)
4595             outBitC(result);
4596         // if(bit | ...)
4597         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4598             genIfxJump(ifx, "c");           
4599         goto release ;
4600     }
4601
4602     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4603     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4604     if((AOP_TYPE(right) == AOP_LIT) &&
4605        (AOP_TYPE(result) == AOP_CRY) &&
4606        (AOP_TYPE(left) != AOP_CRY)){
4607         if(lit){
4608             // result = 1
4609             if(size)
4610                 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4611             else 
4612                 continueIfTrue(ifx);
4613             goto release;
4614         } else {
4615             // lit = 0, result = boolean(left)
4616             if(size)
4617                 emitcode("setb","c");
4618             toBoolean(right);
4619             if(size){
4620                 symbol *tlbl = newiTempLabel(NULL);
4621                 emitcode("jnz","%05d$",tlbl->key+100);
4622                 CLRC;
4623                 emitcode("","%05d$:",tlbl->key+100);
4624             } else {
4625                 genIfxJump (ifx,"a");
4626                 goto release;
4627             }
4628         }
4629         outBitC(result);
4630         goto release ;
4631     }
4632
4633     /* if left is same as result */
4634     if(sameRegs(AOP(result),AOP(left))){
4635         for(;size--; offset++) {
4636             if(AOP_TYPE(right) == AOP_LIT){
4637                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4638                     continue;
4639                 else 
4640                     if (IS_AOP_PREG(left)) {
4641                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4642                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4643                         aopPut(AOP(result),"a",offset);
4644                     } else
4645                         emitcode("orl","%s,%s",
4646                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4647                                  aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4648             } else {
4649                 if (AOP_TYPE(left) == AOP_ACC) 
4650                     emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4651                 else {              
4652                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4653                     if (IS_AOP_PREG(left)) {
4654                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4655                         aopPut(AOP(result),"a",offset);
4656                     } else
4657                         emitcode("orl","%s,a",
4658                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4659                 }
4660             }
4661         }
4662     } else {
4663         // left & result in different registers
4664         if(AOP_TYPE(result) == AOP_CRY){
4665             // result = bit
4666             // if(size), result in bit
4667             // if(!size && ifx), conditional oper: if(left | right)
4668             symbol *tlbl = newiTempLabel(NULL);
4669             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4670             if(size)
4671                 emitcode("setb","c");
4672             while(sizer--){
4673                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4674                 emitcode("orl","a,%s",
4675                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4676                 emitcode("jnz","%05d$",tlbl->key+100);
4677                 offset++;
4678             }
4679             if(size){
4680                 CLRC;
4681                 emitcode("","%05d$:",tlbl->key+100);
4682                 outBitC(result);
4683             } else if(ifx)
4684                 jmpTrueOrFalse(ifx, tlbl);
4685         } else for(;(size--);offset++){
4686             // normal case
4687             // result = left & right
4688             if(AOP_TYPE(right) == AOP_LIT){
4689                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4690                     aopPut(AOP(result),
4691                            aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4692                            offset);
4693                     continue;
4694                 }
4695             }
4696             // faster than result <- left, anl result,right
4697             // and better if result is SFR
4698             if (AOP_TYPE(left) == AOP_ACC) 
4699                 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4700             else {
4701                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4702                 emitcode("orl","a,%s",
4703                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4704             }
4705             aopPut(AOP(result),"a",offset);                     
4706         }
4707     }
4708
4709 release :
4710     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4711     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4712     freeAsmop(result,NULL,ic,TRUE);     
4713 }
4714
4715 /*-----------------------------------------------------------------*/
4716 /* genXor - code for xclusive or                                   */
4717 /*-----------------------------------------------------------------*/
4718 static void genXor (iCode *ic, iCode *ifx)
4719 {
4720     operand *left, *right, *result;
4721     int size, offset=0;
4722     unsigned long lit = 0L;
4723
4724     D(emitcode(";", "genXor "););
4725
4726     AOP_OP_3(ic);
4727     AOP_SET_LOCALS(ic);
4728 #if 0
4729     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4730     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4731     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4732 #endif
4733
4734 #ifdef DEBUG_TYPE
4735     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4736              AOP_TYPE(result),
4737              AOP_TYPE(left), AOP_TYPE(right));
4738     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4739              AOP_SIZE(result),
4740              AOP_SIZE(left), AOP_SIZE(right));
4741 #endif
4742
4743     /* if left is a literal & right is not ||
4744        if left needs acc & right does not */
4745     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4746         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4747         operand *tmp = right ;
4748         right = left;
4749         left = tmp;
4750     }
4751
4752     /* if result = right then exchange them */
4753     if(sameRegs(AOP(result),AOP(right))){
4754         operand *tmp = right ;
4755         right = left;
4756         left = tmp;
4757     }
4758
4759     /* if right is bit then exchange them */
4760     if (AOP_TYPE(right) == AOP_CRY &&
4761         AOP_TYPE(left) != AOP_CRY){
4762         operand *tmp = right ;
4763         right = left;
4764         left = tmp;
4765     }
4766     if(AOP_TYPE(right) == AOP_LIT)
4767         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4768
4769     size = AOP_SIZE(result);
4770
4771     // if(bit ^ yy)
4772     // xx = bit ^ yy;
4773     if (AOP_TYPE(left) == AOP_CRY){
4774         if(AOP_TYPE(right) == AOP_LIT){
4775             // c = bit & literal;
4776             if(lit>>1){
4777                 // lit>>1  != 0 => result = 1
4778                 if(AOP_TYPE(result) == AOP_CRY){
4779                     if(size)
4780                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4781                     else if(ifx)
4782                         continueIfTrue(ifx);
4783                     goto release;
4784                 }
4785                 emitcode("setb","c");
4786             } else{
4787                 // lit == (0 or 1)
4788                 if(lit == 0){
4789                     // lit == 0, result = left
4790                     if(size && sameRegs(AOP(result),AOP(left)))
4791                         goto release;
4792                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4793                 } else{
4794                     // lit == 1, result = not(left)
4795                     if(size && sameRegs(AOP(result),AOP(left))){
4796                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4797                         goto release;
4798                     } else {
4799                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4800                         emitcode("cpl","c");
4801                     }
4802                 }
4803             }
4804
4805         } else {
4806             // right != literal
4807             symbol *tlbl = newiTempLabel(NULL);
4808             if (AOP_TYPE(right) == AOP_CRY){
4809                 // c = bit ^ bit;
4810                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4811             }
4812             else{
4813                 int sizer = AOP_SIZE(right);
4814                 // c = bit ^ val
4815                 // if val>>1 != 0, result = 1
4816                 emitcode("setb","c");
4817                 while(sizer){
4818                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
4819                     if(sizer == 1)
4820                         // test the msb of the lsb
4821                         emitcode("anl","a,#0xfe");
4822                     emitcode("jnz","%05d$",tlbl->key+100);
4823                     sizer--;
4824                 }
4825                 // val = (0,1)
4826                 emitcode("rrc","a");
4827             }
4828             emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4829             emitcode("cpl","c");
4830             emitcode("","%05d$:",(tlbl->key+100));
4831         }
4832         // bit = c
4833         // val = c
4834         if(size)
4835             outBitC(result);
4836         // if(bit | ...)
4837         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4838             genIfxJump(ifx, "c");           
4839         goto release ;
4840     }
4841
4842     if(sameRegs(AOP(result),AOP(left))){
4843         /* if left is same as result */
4844         for(;size--; offset++) {
4845             if(AOP_TYPE(right) == AOP_LIT){
4846                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4847                     continue;
4848                 else
4849                     if (IS_AOP_PREG(left)) {
4850                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4851                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4852                         aopPut(AOP(result),"a",offset);
4853                     } else 
4854                         emitcode("xrl","%s,%s",
4855                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4856                                  aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4857             } else {
4858                 if (AOP_TYPE(left) == AOP_ACC)
4859                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4860                 else {
4861                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4862                     if (IS_AOP_PREG(left)) {
4863                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4864                         aopPut(AOP(result),"a",offset);
4865                     } else
4866                         emitcode("xrl","%s,a",
4867                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4868                 }
4869             }
4870         }
4871     } else {
4872         // left & result in different registers
4873         if(AOP_TYPE(result) == AOP_CRY){
4874             // result = bit
4875             // if(size), result in bit
4876             // if(!size && ifx), conditional oper: if(left ^ right)
4877             symbol *tlbl = newiTempLabel(NULL);
4878             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4879             if(size)
4880                 emitcode("setb","c");
4881             while(sizer--){
4882                 if((AOP_TYPE(right) == AOP_LIT) &&
4883                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4884                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4885                 } else {
4886                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4887                     emitcode("xrl","a,%s",
4888                              aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4889                 }
4890                 emitcode("jnz","%05d$",tlbl->key+100);
4891                 offset++;
4892             }
4893             if(size){
4894                 CLRC;
4895                 emitcode("","%05d$:",tlbl->key+100);
4896                 outBitC(result);
4897             } else if(ifx)
4898                 jmpTrueOrFalse(ifx, tlbl);
4899         } else for(;(size--);offset++){
4900             // normal case
4901             // result = left & right
4902             if(AOP_TYPE(right) == AOP_LIT){
4903                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4904                     aopPut(AOP(result),
4905                            aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4906                            offset);
4907                     continue;
4908                 }
4909             }
4910             // faster than result <- left, anl result,right
4911             // and better if result is SFR
4912             if (AOP_TYPE(left) == AOP_ACC)
4913                 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4914             else {
4915                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4916                 emitcode("xrl","a,%s",
4917                          aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4918             }
4919             aopPut(AOP(result),"a",offset);
4920         }
4921     }
4922
4923 release :
4924     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4925     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4926     freeAsmop(result,NULL,ic,TRUE);     
4927 }
4928
4929 /*-----------------------------------------------------------------*/
4930 /* genInline - write the inline code out                           */
4931 /*-----------------------------------------------------------------*/
4932 static void genInline (iCode *ic)
4933 {
4934     char buffer[MAX_INLINEASM];
4935     char *bp = buffer;
4936     char *bp1= buffer;
4937     
4938     D(emitcode(";", "genInline "););
4939
4940     _G.inLine += (!options.asmpeep);
4941     strcpy(buffer,IC_INLINE(ic));
4942
4943     /* emit each line as a code */
4944     while (*bp) {
4945         if (*bp == '\n') {
4946             *bp++ = '\0';
4947             emitcode(bp1,"");
4948             bp1 = bp;
4949         } else {
4950             if (*bp == ':') {
4951                 bp++;
4952                 *bp = '\0';
4953                 bp++;
4954                 emitcode(bp1,"");
4955                 bp1 = bp;
4956             } else
4957                 bp++;
4958         }
4959     }
4960     if (bp1 != bp)
4961         emitcode(bp1,"");
4962     /*     emitcode("",buffer); */
4963     _G.inLine -= (!options.asmpeep);
4964 }
4965
4966 /*-----------------------------------------------------------------*/
4967 /* genRRC - rotate right with carry                                */
4968 /*-----------------------------------------------------------------*/
4969 static void genRRC (iCode *ic)
4970 {
4971     operand *left , *result ;
4972     int size, offset = 0;
4973     char *l;    
4974
4975     D(emitcode(";", "genRRC "););
4976
4977     /* rotate right with carry */
4978     left = IC_LEFT(ic);
4979     result=IC_RESULT(ic);
4980     aopOp (left,ic,FALSE, FALSE);
4981     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
4982
4983     /* move it to the result */
4984     size = AOP_SIZE(result);    
4985     offset = size - 1 ;
4986     CLRC;
4987     while (size--) {
4988         l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4989         MOVA(l);
4990         emitcode("rrc","a");
4991         if (AOP_SIZE(result) > 1)
4992             aopPut(AOP(result),"a",offset--);
4993     }
4994     /* now we need to put the carry into the
4995     highest order byte of the result */
4996     if (AOP_SIZE(result) > 1) {
4997         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
4998         MOVA(l);
4999     }
5000     emitcode("mov","acc.7,c");
5001     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5002     freeAsmop(left,NULL,ic,TRUE);
5003     freeAsmop(result,NULL,ic,TRUE);
5004 }
5005
5006 /*-----------------------------------------------------------------*/
5007 /* genRLC - generate code for rotate left with carry               */
5008 /*-----------------------------------------------------------------*/
5009 static void genRLC (iCode *ic)
5010 {    
5011     operand *left , *result ;
5012     int size, offset = 0;
5013     char *l;    
5014
5015     D(emitcode(";", "genRLC "););
5016
5017     /* rotate right with carry */
5018     left = IC_LEFT(ic);
5019     result=IC_RESULT(ic);
5020     aopOp (left,ic,FALSE, FALSE);
5021     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5022
5023     /* move it to the result */
5024     size = AOP_SIZE(result);    
5025     offset = 0 ;
5026     if (size--) {
5027         l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5028         MOVA(l);
5029         emitcode("add","a,acc");
5030         if (AOP_SIZE(result) > 1)
5031             aopPut(AOP(result),"a",offset++);
5032         while (size--) {
5033             l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5034             MOVA(l);
5035             emitcode("rlc","a");
5036             if (AOP_SIZE(result) > 1)
5037                 aopPut(AOP(result),"a",offset++);
5038         }
5039     }
5040     /* now we need to put the carry into the
5041     highest order byte of the result */
5042     if (AOP_SIZE(result) > 1) {
5043         l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5044         MOVA(l);
5045     }
5046     emitcode("mov","acc.0,c");
5047     aopPut(AOP(result),"a",0);
5048     freeAsmop(left,NULL,ic,TRUE);
5049     freeAsmop(result,NULL,ic,TRUE);
5050 }
5051
5052 /*-----------------------------------------------------------------*/
5053 /* genGetHbit - generates code get highest order bit               */
5054 /*-----------------------------------------------------------------*/
5055 static void genGetHbit (iCode *ic)
5056 {
5057     operand *left, *result;
5058     left = IC_LEFT(ic);
5059     result=IC_RESULT(ic);
5060     aopOp (left,ic,FALSE, FALSE);
5061     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5062
5063     D(emitcode(";", "genGetHbit "););
5064
5065     /* get the highest order byte into a */
5066     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5067     if(AOP_TYPE(result) == AOP_CRY){
5068         emitcode("rlc","a");
5069         outBitC(result);
5070     }
5071     else{
5072         emitcode("rl","a");
5073         emitcode("anl","a,#0x01");
5074         outAcc(result);
5075     }
5076
5077
5078     freeAsmop(left,NULL,ic,TRUE);
5079     freeAsmop(result,NULL,ic,TRUE);
5080 }
5081
5082 /*-----------------------------------------------------------------*/
5083 /* AccRol - rotate left accumulator by known count                 */
5084 /*-----------------------------------------------------------------*/
5085 static void AccRol (int shCount)
5086 {
5087     shCount &= 0x0007;              // shCount : 0..7
5088     switch(shCount){
5089         case 0 :
5090             break;
5091         case 1 :
5092             emitcode("rl","a");
5093             break;
5094         case 2 :
5095             emitcode("rl","a");
5096             emitcode("rl","a");
5097             break;
5098         case 3 :
5099             emitcode("swap","a");
5100             emitcode("rr","a");
5101             break;
5102         case 4 :
5103             emitcode("swap","a");
5104             break;
5105         case 5 :
5106             emitcode("swap","a");
5107             emitcode("rl","a");
5108             break;
5109         case 6 :
5110             emitcode("rr","a");
5111             emitcode("rr","a");
5112             break;
5113         case 7 :
5114             emitcode("rr","a");
5115             break;
5116     }
5117 }
5118
5119 /*-----------------------------------------------------------------*/
5120 /* AccLsh - left shift accumulator by known count                  */
5121 /*-----------------------------------------------------------------*/
5122 static void AccLsh (int shCount)
5123 {
5124     if(shCount != 0){
5125         if(shCount == 1)
5126             emitcode("add","a,acc");
5127         else 
5128             if(shCount == 2) {
5129             emitcode("add","a,acc");
5130             emitcode("add","a,acc");
5131         } else {
5132             /* rotate left accumulator */
5133             AccRol(shCount);
5134             /* and kill the lower order bits */
5135             emitcode("anl","a,#0x%02x", SLMask[shCount]);
5136         }
5137     }
5138 }
5139
5140 /*-----------------------------------------------------------------*/
5141 /* AccRsh - right shift accumulator by known count                 */
5142 /*-----------------------------------------------------------------*/
5143 static void AccRsh (int shCount)
5144 {
5145     if(shCount != 0){
5146         if(shCount == 1){
5147             CLRC;
5148             emitcode("rrc","a");
5149         } else {
5150             /* rotate right accumulator */
5151             AccRol(8 - shCount);
5152             /* and kill the higher order bits */
5153             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5154         }
5155     }
5156 }
5157
5158 /*-----------------------------------------------------------------*/
5159 /* AccSRsh - signed right shift accumulator by known count                 */
5160 /*-----------------------------------------------------------------*/
5161 static void AccSRsh (int shCount)
5162 {
5163     symbol *tlbl ;
5164     if(shCount != 0){
5165         if(shCount == 1){
5166             emitcode("mov","c,acc.7");
5167             emitcode("rrc","a");
5168         } else if(shCount == 2){
5169             emitcode("mov","c,acc.7");
5170             emitcode("rrc","a");
5171             emitcode("mov","c,acc.7");
5172             emitcode("rrc","a");
5173         } else {
5174             tlbl = newiTempLabel(NULL);
5175             /* rotate right accumulator */
5176             AccRol(8 - shCount);
5177             /* and kill the higher order bits */
5178             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5179             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5180             emitcode("orl","a,#0x%02x",
5181                      (unsigned char)~SRMask[shCount]);
5182             emitcode("","%05d$:",tlbl->key+100);
5183         }
5184     }
5185 }
5186
5187 /*-----------------------------------------------------------------*/
5188 /* shiftR1Left2Result - shift right one byte from left to result   */
5189 /*-----------------------------------------------------------------*/
5190 static void shiftR1Left2Result (operand *left, int offl,
5191                                 operand *result, int offr,
5192                                 int shCount, int sign)
5193 {
5194     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5195     /* shift right accumulator */
5196     if(sign)
5197         AccSRsh(shCount);
5198     else
5199         AccRsh(shCount);
5200     aopPut(AOP(result),"a",offr);
5201 }
5202
5203 /*-----------------------------------------------------------------*/
5204 /* shiftL1Left2Result - shift left one byte from left to result    */
5205 /*-----------------------------------------------------------------*/
5206 static void shiftL1Left2Result (operand *left, int offl,
5207                                 operand *result, int offr, int shCount)
5208 {
5209     char *l;
5210     l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5211     MOVA(l);
5212     /* shift left accumulator */
5213     AccLsh(shCount);
5214     aopPut(AOP(result),"a",offr);
5215 }
5216
5217 /*-----------------------------------------------------------------*/
5218 /* movLeft2Result - move byte from left to result                  */
5219 /*-----------------------------------------------------------------*/
5220 static void movLeft2Result (operand *left, int offl,
5221                             operand *result, int offr, int sign)
5222 {
5223     char *l;
5224     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5225         l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5226
5227         if (*l == '@' && (IS_AOP_PREG(result))) {
5228             emitcode("mov","a,%s",l);
5229             aopPut(AOP(result),"a",offr);
5230         } else {
5231             if(!sign)
5232                 aopPut(AOP(result),l,offr);
5233             else{
5234                 /* MSB sign in acc.7 ! */
5235                 if(getDataSize(left) == offl+1){
5236                     emitcode("mov","a,%s",l);
5237                     aopPut(AOP(result),"a",offr);
5238                 }
5239             }
5240         }
5241     }
5242 }
5243
5244 /*-----------------------------------------------------------------*/
5245 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5246 /*-----------------------------------------------------------------*/
5247 static void AccAXRrl1 (char *x)
5248 {
5249     emitcode("rrc","a");
5250     emitcode("xch","a,%s", x);
5251     emitcode("rrc","a");
5252     emitcode("xch","a,%s", x);
5253 }
5254
5255 /*-----------------------------------------------------------------*/
5256 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5257 /*-----------------------------------------------------------------*/
5258 static void AccAXLrl1 (char *x)
5259 {
5260     emitcode("xch","a,%s",x);
5261     emitcode("rlc","a");
5262     emitcode("xch","a,%s",x);
5263     emitcode("rlc","a");
5264 }
5265
5266 /*-----------------------------------------------------------------*/
5267 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5268 /*-----------------------------------------------------------------*/
5269 static void AccAXLsh1 (char *x)
5270 {
5271     emitcode("xch","a,%s",x);
5272     emitcode("add","a,acc");
5273     emitcode("xch","a,%s",x);
5274     emitcode("rlc","a");
5275 }
5276
5277 /*-----------------------------------------------------------------*/
5278 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5279 /*-----------------------------------------------------------------*/
5280 static void AccAXLsh (char *x, int shCount)
5281 {
5282     switch(shCount){
5283         case 0 :
5284             break;
5285         case 1 :
5286             AccAXLsh1(x);
5287             break;
5288         case 2 :
5289             AccAXLsh1(x);
5290             AccAXLsh1(x);
5291             break;
5292         case 3 :
5293         case 4 :
5294         case 5 :                        // AAAAABBB:CCCCCDDD
5295             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
5296             emitcode("anl","a,#0x%02x",
5297                      SLMask[shCount]);  // BBB00000:CCCCCDDD
5298             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
5299             AccRol(shCount);            // DDDCCCCC:BBB00000
5300             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
5301             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
5302             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
5303             emitcode("anl","a,#0x%02x",
5304                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
5305             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
5306             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
5307             break;
5308         case 6 :                        // AAAAAABB:CCCCCCDD
5309             emitcode("anl","a,#0x%02x",
5310                      SRMask[shCount]);  // 000000BB:CCCCCCDD
5311             emitcode("mov","c,acc.0");  // c = B
5312             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
5313             AccAXRrl1(x);               // BCCCCCCD:D000000B
5314             AccAXRrl1(x);               // BBCCCCCC:DD000000
5315             break;
5316         case 7 :                        // a:x <<= 7
5317             emitcode("anl","a,#0x%02x",
5318                      SRMask[shCount]);  // 0000000B:CCCCCCCD
5319             emitcode("mov","c,acc.0");  // c = B
5320             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
5321             AccAXRrl1(x);               // BCCCCCCC:D0000000
5322             break;
5323         default :
5324             break;
5325     }
5326 }
5327
5328 /*-----------------------------------------------------------------*/
5329 /* AccAXRsh - right shift a:x known count (0..7)                   */
5330 /*-----------------------------------------------------------------*/
5331 static void AccAXRsh (char *x, int shCount)
5332 {   
5333     switch(shCount){
5334         case 0 :
5335             break;
5336         case 1 :
5337             CLRC;
5338             AccAXRrl1(x);               // 0->a:x
5339             break;
5340         case 2 :
5341             CLRC;
5342             AccAXRrl1(x);               // 0->a:x
5343             CLRC;
5344             AccAXRrl1(x);               // 0->a:x
5345             break;
5346         case 3 :
5347         case 4 :
5348         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5349             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
5350             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5351             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5352             emitcode("anl","a,#0x%02x",
5353                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5354             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5355             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5356             emitcode("anl","a,#0x%02x",
5357                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5358             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5359             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5360             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
5361             break;
5362         case 6 :                        // AABBBBBB:CCDDDDDD
5363             emitcode("mov","c,acc.7");
5364             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5365             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5366             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5367             emitcode("anl","a,#0x%02x",
5368                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5369             break;
5370         case 7 :                        // ABBBBBBB:CDDDDDDD
5371             emitcode("mov","c,acc.7");  // c = A
5372             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5373             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5374             emitcode("anl","a,#0x%02x",
5375                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5376             break;
5377         default :
5378             break;
5379     }
5380 }
5381
5382 /*-----------------------------------------------------------------*/
5383 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5384 /*-----------------------------------------------------------------*/
5385 static void AccAXRshS (char *x, int shCount)
5386 {   
5387     symbol *tlbl ;
5388     switch(shCount){
5389         case 0 :
5390             break;
5391         case 1 :
5392             emitcode("mov","c,acc.7");
5393             AccAXRrl1(x);               // s->a:x
5394             break;
5395         case 2 :
5396             emitcode("mov","c,acc.7");
5397             AccAXRrl1(x);               // s->a:x
5398             emitcode("mov","c,acc.7");
5399             AccAXRrl1(x);               // s->a:x
5400             break;
5401         case 3 :
5402         case 4 :
5403         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5404             tlbl = newiTempLabel(NULL);
5405             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
5406             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5407             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5408             emitcode("anl","a,#0x%02x",
5409                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5410             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5411             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5412             emitcode("anl","a,#0x%02x",
5413                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5414             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5415             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5416             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
5417             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5418             emitcode("orl","a,#0x%02x",
5419                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
5420             emitcode("","%05d$:",tlbl->key+100);
5421             break;                      // SSSSAAAA:BBBCCCCC
5422         case 6 :                        // AABBBBBB:CCDDDDDD
5423             tlbl = newiTempLabel(NULL);
5424             emitcode("mov","c,acc.7");
5425             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5426             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5427             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5428             emitcode("anl","a,#0x%02x",
5429                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5430             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5431             emitcode("orl","a,#0x%02x",
5432                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
5433             emitcode("","%05d$:",tlbl->key+100);
5434             break;
5435         case 7 :                        // ABBBBBBB:CDDDDDDD
5436             tlbl = newiTempLabel(NULL);
5437             emitcode("mov","c,acc.7");  // c = A
5438             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5439             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5440             emitcode("anl","a,#0x%02x",
5441                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5442             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5443             emitcode("orl","a,#0x%02x",
5444                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
5445             emitcode("","%05d$:",tlbl->key+100);
5446             break;
5447         default :
5448             break;
5449     }
5450 }
5451
5452 /*-----------------------------------------------------------------*/
5453 /* shiftL2Left2Result - shift left two bytes from left to result   */
5454 /*-----------------------------------------------------------------*/
5455 static void shiftL2Left2Result (operand *left, int offl,
5456                                 operand *result, int offr, int shCount)
5457 {
5458     if(sameRegs(AOP(result), AOP(left)) &&
5459        ((offl + MSB16) == offr)){
5460         /* don't crash result[offr] */
5461         MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5462         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5463     } else {
5464         movLeft2Result(left,offl, result, offr, 0);
5465         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5466     }
5467     /* ax << shCount (x = lsb(result))*/
5468     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5469     aopPut(AOP(result),"a",offr+MSB16);
5470 }
5471
5472
5473 /*-----------------------------------------------------------------*/
5474 /* shiftR2Left2Result - shift right two bytes from left to result  */
5475 /*-----------------------------------------------------------------*/
5476 static void shiftR2Left2Result (operand *left, int offl,
5477                                 operand *result, int offr,
5478                                 int shCount, int sign)
5479 {
5480     if(sameRegs(AOP(result), AOP(left)) &&
5481        ((offl + MSB16) == offr)){
5482         /* don't crash result[offr] */
5483         MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5484         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5485     } else {
5486         movLeft2Result(left,offl, result, offr, 0);
5487         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5488     }
5489     /* a:x >> shCount (x = lsb(result))*/
5490     if(sign)
5491         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5492     else
5493         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5494     if(getDataSize(result) > 1)
5495         aopPut(AOP(result),"a",offr+MSB16);
5496 }
5497
5498 /*-----------------------------------------------------------------*/
5499 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5500 /*-----------------------------------------------------------------*/
5501 static void shiftLLeftOrResult (operand *left, int offl,
5502                                 operand *result, int offr, int shCount)
5503 {
5504     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5505     /* shift left accumulator */
5506     AccLsh(shCount);
5507     /* or with result */
5508     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5509     /* back to result */
5510     aopPut(AOP(result),"a",offr);
5511 }
5512
5513 /*-----------------------------------------------------------------*/
5514 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5515 /*-----------------------------------------------------------------*/
5516 static void shiftRLeftOrResult (operand *left, int offl,
5517                                 operand *result, int offr, int shCount)
5518 {
5519     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5520     /* shift right accumulator */
5521     AccRsh(shCount);
5522     /* or with result */
5523     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5524     /* back to result */
5525     aopPut(AOP(result),"a",offr);
5526 }
5527
5528 /*-----------------------------------------------------------------*/
5529 /* genlshOne - left shift a one byte quantity by known count       */
5530 /*-----------------------------------------------------------------*/
5531 static void genlshOne (operand *result, operand *left, int shCount)
5532 {       
5533     D(emitcode(";", "genlshOne "););
5534     shiftL1Left2Result(left, LSB, result, LSB, shCount);
5535 }
5536
5537 /*-----------------------------------------------------------------*/
5538 /* genlshTwo - left shift two bytes by known amount != 0           */
5539 /*-----------------------------------------------------------------*/
5540 static void genlshTwo (operand *result,operand *left, int shCount)
5541 {
5542     int size;
5543     
5544     D(emitcode(";", "genlshTwo "););
5545
5546     size = getDataSize(result);
5547
5548     /* if shCount >= 8 */
5549     if (shCount >= 8) {
5550         shCount -= 8 ;
5551
5552         if (size > 1){
5553             if (shCount)
5554                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5555             else 
5556                 movLeft2Result(left, LSB, result, MSB16, 0);
5557         }
5558         aopPut(AOP(result),zero,LSB);   
5559     }
5560
5561     /*  1 <= shCount <= 7 */
5562     else {  
5563         if(size == 1)
5564             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
5565         else 
5566             shiftL2Left2Result(left, LSB, result, LSB, shCount);
5567     }
5568 }
5569
5570 /*-----------------------------------------------------------------*/
5571 /* shiftLLong - shift left one long from left to result            */
5572 /* offl = LSB or MSB16                                             */
5573 /*-----------------------------------------------------------------*/
5574 static void shiftLLong (operand *left, operand *result, int offr )
5575 {
5576     char *l;
5577     int size = AOP_SIZE(result);
5578
5579     if(size >= LSB+offr){
5580         l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5581         MOVA(l);
5582         emitcode("add","a,acc");
5583         if (sameRegs(AOP(left),AOP(result)) && 
5584             size >= MSB16+offr && offr != LSB )
5585             emitcode("xch","a,%s",
5586                      aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5587         else        
5588             aopPut(AOP(result),"a",LSB+offr);
5589     }
5590
5591     if(size >= MSB16+offr){
5592         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5593             l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5594             MOVA(l);
5595         }
5596         emitcode("rlc","a");
5597         if (sameRegs(AOP(left),AOP(result)) && 
5598             size >= MSB24+offr && offr != LSB)
5599             emitcode("xch","a,%s",
5600                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5601         else        
5602             aopPut(AOP(result),"a",MSB16+offr);
5603     }
5604
5605     if(size >= MSB24+offr){
5606         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5607             l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5608             MOVA(l);
5609         }
5610         emitcode("rlc","a");
5611         if (sameRegs(AOP(left),AOP(result)) && 
5612             size >= MSB32+offr && offr != LSB )
5613             emitcode("xch","a,%s",
5614                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5615         else        
5616             aopPut(AOP(result),"a",MSB24+offr);
5617     }
5618
5619     if(size > MSB32+offr){
5620         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5621             l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5622             MOVA(l);    
5623         }
5624         emitcode("rlc","a");
5625         aopPut(AOP(result),"a",MSB32+offr);
5626     }
5627     if(offr != LSB)
5628         aopPut(AOP(result),zero,LSB);       
5629 }
5630
5631 /*-----------------------------------------------------------------*/
5632 /* genlshFour - shift four byte by a known amount != 0             */
5633 /*-----------------------------------------------------------------*/
5634 static void genlshFour (operand *result, operand *left, int shCount)
5635 {
5636     int size;
5637
5638     D(emitcode(";", "genlshFour "););
5639
5640     size = AOP_SIZE(result);
5641
5642     /* if shifting more that 3 bytes */
5643     if (shCount >= 24 ) {
5644         shCount -= 24;
5645         if (shCount)
5646             /* lowest order of left goes to the highest
5647             order of the destination */
5648             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5649         else
5650             movLeft2Result(left, LSB, result, MSB32, 0);
5651         aopPut(AOP(result),zero,LSB);
5652         aopPut(AOP(result),zero,MSB16);
5653         aopPut(AOP(result),zero,MSB32);
5654         return;
5655     }
5656
5657     /* more than two bytes */
5658     else if ( shCount >= 16 ) {
5659         /* lower order two bytes goes to higher order two bytes */
5660         shCount -= 16;
5661         /* if some more remaining */
5662         if (shCount)
5663             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5664         else {
5665             movLeft2Result(left, MSB16, result, MSB32, 0);
5666             movLeft2Result(left, LSB, result, MSB24, 0);
5667         }
5668         aopPut(AOP(result),zero,MSB16);
5669         aopPut(AOP(result),zero,LSB);
5670         return;
5671     }    
5672
5673     /* if more than 1 byte */
5674     else if ( shCount >= 8 ) {
5675         /* lower order three bytes goes to higher order  three bytes */
5676         shCount -= 8;
5677         if(size == 2){
5678             if(shCount)
5679                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5680             else
5681                 movLeft2Result(left, LSB, result, MSB16, 0);
5682         }
5683         else{   /* size = 4 */
5684             if(shCount == 0){
5685                 movLeft2Result(left, MSB24, result, MSB32, 0);
5686                 movLeft2Result(left, MSB16, result, MSB24, 0);
5687                 movLeft2Result(left, LSB, result, MSB16, 0);
5688                 aopPut(AOP(result),zero,LSB);
5689             }
5690             else if(shCount == 1)
5691                 shiftLLong(left, result, MSB16);
5692             else{
5693                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5694                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5695                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5696                 aopPut(AOP(result),zero,LSB);
5697             }
5698         }
5699     }
5700
5701     /* 1 <= shCount <= 7 */
5702     else if(shCount <= 2){
5703         shiftLLong(left, result, LSB);
5704         if(shCount == 2)
5705             shiftLLong(result, result, LSB);
5706     }
5707     /* 3 <= shCount <= 7, optimize */
5708     else{
5709         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5710         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5711         shiftL2Left2Result(left, LSB, result, LSB, shCount);
5712     }
5713 }
5714
5715 /*-----------------------------------------------------------------*/
5716 /* genLeftShiftLiteral - left shifting by known count              */
5717 /*-----------------------------------------------------------------*/
5718 static void genLeftShiftLiteral (operand *left,
5719                                  operand *right,
5720                                  operand *result,
5721                                  iCode *ic)
5722 {    
5723     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5724     int size;
5725
5726     D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5727
5728     freeAsmop(right,NULL,ic,TRUE);
5729
5730     aopOp(left,ic,FALSE, FALSE);
5731     aopOp(result,ic,FALSE, TRUE);
5732
5733     size = getSize(operandType(result));
5734
5735 #if VIEW_SIZE
5736     emitcode("; shift left ","result %d, left %d",size,
5737              AOP_SIZE(left));
5738 #endif
5739
5740     /* I suppose that the left size >= result size */
5741     if(shCount == 0){
5742         while(size--){
5743             movLeft2Result(left, size, result, size, 0);
5744         }
5745     }
5746
5747     else if(shCount >= (size * 8))
5748         while(size--)
5749             aopPut(AOP(result),zero,size);
5750     else{
5751         switch (size) {
5752             case 1:
5753                 genlshOne (result,left,shCount);
5754                 break;
5755
5756             case 2:
5757             case 3: /* bug: this is for generic pointers, I bet. */
5758                 genlshTwo (result,left,shCount);
5759                 break;
5760
5761             case 4:
5762                 genlshFour (result,left,shCount);
5763                 break;
5764         }
5765     }
5766     freeAsmop(left,NULL,ic,TRUE);
5767     freeAsmop(result,NULL,ic,TRUE);
5768 }
5769
5770 /*-----------------------------------------------------------------*/
5771 /* genLeftShift - generates code for left shifting                 */
5772 /*-----------------------------------------------------------------*/
5773 static void genLeftShift (iCode *ic)
5774 {
5775     operand *left,*right, *result;
5776     int size, offset;
5777     char *l;
5778     symbol *tlbl , *tlbl1;
5779
5780     D(emitcode(";", "genLeftShift "););
5781
5782     right = IC_RIGHT(ic);
5783     left  = IC_LEFT(ic);
5784     result = IC_RESULT(ic);
5785
5786     aopOp(right,ic,FALSE, FALSE);
5787
5788     #if 0
5789     /* if the shift count is known then do it 
5790     as efficiently as possible */
5791     if (AOP_TYPE(right) == AOP_LIT) {
5792         genLeftShiftLiteral (left,right,result,ic);
5793         return ;
5794     }
5795     #endif
5796
5797     /* shift count is unknown then we have to form 
5798     a loop get the loop count in B : Note: we take
5799     only the lower order byte since shifting
5800     more that 32 bits make no sense anyway, ( the
5801     largest size of an object can be only 32 bits ) */  
5802
5803     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
5804     emitcode("inc","b");
5805     freeAsmop (right,NULL,ic,TRUE);
5806     aopOp(left,ic,FALSE, FALSE);
5807     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5808
5809     /* now move the left to the result if they are not the
5810     same */
5811     if (!sameRegs(AOP(left),AOP(result)) && 
5812         AOP_SIZE(result) > 1) {
5813
5814         size = AOP_SIZE(result);
5815         offset=0;
5816         while (size--) {
5817             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
5818             if (*l == '@' && (IS_AOP_PREG(result))) {
5819
5820                 emitcode("mov","a,%s",l);
5821                 aopPut(AOP(result),"a",offset);
5822             } else
5823                 aopPut(AOP(result),l,offset);
5824             offset++;
5825         }
5826     }
5827
5828     tlbl = newiTempLabel(NULL);
5829     size = AOP_SIZE(result);
5830     offset = 0 ;   
5831     tlbl1 = newiTempLabel(NULL);
5832
5833     /* if it is only one byte then */
5834     if (size == 1) {
5835         symbol *tlbl1 = newiTempLabel(NULL);
5836
5837         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
5838         MOVA(l);
5839         emitcode("sjmp","%05d$",tlbl1->key+100); 
5840         emitcode("","%05d$:",tlbl->key+100);
5841         emitcode("add","a,acc");
5842         emitcode("","%05d$:",tlbl1->key+100);
5843         emitcode("djnz","b,%05d$",tlbl->key+100);      
5844         aopPut(AOP(result),"a",0);
5845         goto release ;
5846     }
5847     
5848     reAdjustPreg(AOP(result));    
5849     
5850     emitcode("sjmp","%05d$",tlbl1->key+100); 
5851     emitcode("","%05d$:",tlbl->key+100);    
5852     l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5853     MOVA(l);
5854     emitcode("add","a,acc");         
5855     aopPut(AOP(result),"a",offset++);
5856     while (--size) {
5857         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5858         MOVA(l);
5859         emitcode("rlc","a");         
5860         aopPut(AOP(result),"a",offset++);
5861     }
5862     reAdjustPreg(AOP(result));
5863
5864     emitcode("","%05d$:",tlbl1->key+100);
5865     emitcode("djnz","b,%05d$",tlbl->key+100);
5866 release:
5867     freeAsmop(left,NULL,ic,TRUE);
5868     freeAsmop(result,NULL,ic,TRUE);
5869 }
5870
5871 /*-----------------------------------------------------------------*/
5872 /* genrshOne - right shift a one byte quantity by known count      */
5873 /*-----------------------------------------------------------------*/
5874 static void genrshOne (operand *result, operand *left,
5875                        int shCount, int sign)
5876 {
5877     D(emitcode(";", "genrshOne"););
5878     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5879 }
5880
5881 /*-----------------------------------------------------------------*/
5882 /* genrshTwo - right shift two bytes by known amount != 0          */
5883 /*-----------------------------------------------------------------*/
5884 static void genrshTwo (operand *result,operand *left,
5885                        int shCount, int sign)
5886 {
5887     D(emitcode(";", "genrshTwo"););
5888
5889     /* if shCount >= 8 */
5890     if (shCount >= 8) {
5891         shCount -= 8 ;
5892         if (shCount)
5893             shiftR1Left2Result(left, MSB16, result, LSB,
5894                                shCount, sign);
5895         else 
5896             movLeft2Result(left, MSB16, result, LSB, sign);
5897         addSign(result, MSB16, sign);
5898     }
5899
5900     /*  1 <= shCount <= 7 */
5901     else
5902         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
5903 }
5904
5905 /*-----------------------------------------------------------------*/
5906 /* shiftRLong - shift right one long from left to result           */
5907 /* offl = LSB or MSB16                                             */
5908 /*-----------------------------------------------------------------*/
5909 static void shiftRLong (operand *left, int offl,
5910                         operand *result, int sign)
5911 {
5912     if(!sign)
5913         emitcode("clr","c");
5914     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
5915     if(sign)
5916         emitcode("mov","c,acc.7");
5917     emitcode("rrc","a");
5918     aopPut(AOP(result),"a",MSB32-offl);
5919     if(offl == MSB16)
5920         /* add sign of "a" */
5921         addSign(result, MSB32, sign);
5922
5923     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
5924     emitcode("rrc","a");
5925     aopPut(AOP(result),"a",MSB24-offl);
5926
5927     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
5928     emitcode("rrc","a");
5929     aopPut(AOP(result),"a",MSB16-offl);
5930
5931     if(offl == LSB){
5932         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
5933         emitcode("rrc","a");
5934         aopPut(AOP(result),"a",LSB);
5935     }
5936 }
5937
5938 /*-----------------------------------------------------------------*/
5939 /* genrshFour - shift four byte by a known amount != 0             */
5940 /*-----------------------------------------------------------------*/
5941 static void genrshFour (operand *result, operand *left,
5942                         int shCount, int sign)
5943 {
5944     D(emitcode(";", "genrshFour"););
5945     
5946     /* if shifting more that 3 bytes */
5947     if(shCount >= 24 ) {
5948         shCount -= 24;
5949         if(shCount)
5950             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5951         else
5952             movLeft2Result(left, MSB32, result, LSB, sign);
5953         addSign(result, MSB16, sign);
5954     }
5955     else if(shCount >= 16){
5956         shCount -= 16;
5957         if(shCount)
5958             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5959         else{
5960             movLeft2Result(left, MSB24, result, LSB, 0);
5961             movLeft2Result(left, MSB32, result, MSB16, sign);
5962         }
5963         addSign(result, MSB24, sign);
5964     }
5965     else if(shCount >= 8){
5966         shCount -= 8;
5967         if(shCount == 1)
5968             shiftRLong(left, MSB16, result, sign);
5969         else if(shCount == 0){
5970             movLeft2Result(left, MSB16, result, LSB, 0);
5971             movLeft2Result(left, MSB24, result, MSB16, 0);
5972             movLeft2Result(left, MSB32, result, MSB24, sign);
5973             addSign(result, MSB32, sign);
5974         }
5975         else{
5976             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5977             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5978             /* the last shift is signed */
5979             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5980             addSign(result, MSB32, sign);
5981         }
5982     }
5983     else{   /* 1 <= shCount <= 7 */
5984         if(shCount <= 2){
5985             shiftRLong(left, LSB, result, sign);
5986             if(shCount == 2)
5987                 shiftRLong(result, LSB, result, sign);
5988         }
5989         else{
5990             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5991             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5992             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5993         }
5994     }
5995 }
5996
5997 /*-----------------------------------------------------------------*/
5998 /* genRightShiftLiteral - right shifting by known count            */
5999 /*-----------------------------------------------------------------*/
6000 static void genRightShiftLiteral (operand *left,
6001                                   operand *right,
6002                                   operand *result,
6003                                   iCode *ic,
6004                                   int sign)
6005 {    
6006     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6007     int size;
6008
6009     D(emitcode(";", "genRightShiftLiteral"););
6010
6011     freeAsmop(right,NULL,ic,TRUE);
6012
6013     aopOp(left,ic,FALSE, FALSE);
6014     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6015
6016 #if VIEW_SIZE
6017     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6018              AOP_SIZE(left));
6019 #endif
6020
6021     size = getDataSize(left);
6022     /* test the LEFT size !!! */
6023
6024     /* I suppose that the left size >= result size */
6025     if(shCount == 0){
6026         size = getDataSize(result);
6027         while(size--)
6028             movLeft2Result(left, size, result, size, 0);
6029     }
6030
6031     else if(shCount >= (size * 8)){
6032         if(sign)
6033             /* get sign in acc.7 */
6034             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6035         addSign(result, LSB, sign);
6036     } else{
6037         switch (size) {
6038             case 1:
6039                 genrshOne (result,left,shCount,sign);
6040                 break;
6041
6042             case 2:
6043                 genrshTwo (result,left,shCount,sign);
6044                 break;
6045
6046             case 4:
6047                 genrshFour (result,left,shCount,sign);
6048                 break;
6049             default :
6050                 break;
6051         }
6052
6053         freeAsmop(left,NULL,ic,TRUE);
6054         freeAsmop(result,NULL,ic,TRUE);
6055     }
6056 }
6057
6058 /*-----------------------------------------------------------------*/
6059 /* genSignedRightShift - right shift of signed number              */
6060 /*-----------------------------------------------------------------*/
6061 static void genSignedRightShift (iCode *ic)
6062 {
6063     operand *right, *left, *result;
6064     int size, offset;
6065     char *l;
6066     symbol *tlbl, *tlbl1 ;
6067
6068     D(emitcode(";", "genSignedRightShift "););
6069
6070     /* we do it the hard way put the shift count in b
6071     and loop thru preserving the sign */
6072
6073     right = IC_RIGHT(ic);
6074     left  = IC_LEFT(ic);
6075     result = IC_RESULT(ic);
6076
6077     aopOp(right,ic,FALSE, FALSE);
6078
6079     #if 0
6080     if ( AOP_TYPE(right) == AOP_LIT) {
6081         genRightShiftLiteral (left,right,result,ic,1);
6082         return ;
6083     }
6084     #endif
6085         /* shift count is unknown then we have to form 
6086        a loop get the loop count in B : Note: we take
6087        only the lower order byte since shifting
6088        more that 32 bits make no sense anyway, ( the
6089        largest size of an object can be only 32 bits ) */  
6090
6091     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6092     emitcode("inc","b");
6093     freeAsmop (right,NULL,ic,TRUE);
6094     aopOp(left,ic,FALSE, FALSE);
6095     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6096
6097     /* now move the left to the result if they are not the
6098     same */
6099     if (!sameRegs(AOP(left),AOP(result)) && 
6100         AOP_SIZE(result) > 1) {
6101
6102         size = AOP_SIZE(result);
6103         offset=0;
6104         while (size--) {
6105             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6106             if (*l == '@' && IS_AOP_PREG(result)) {
6107
6108                 emitcode("mov","a,%s",l);
6109                 aopPut(AOP(result),"a",offset);
6110             } else
6111                 aopPut(AOP(result),l,offset);
6112             offset++;
6113         }
6114     }
6115
6116     /* mov the highest order bit to OVR */    
6117     tlbl = newiTempLabel(NULL);
6118     tlbl1= newiTempLabel(NULL);
6119
6120     size = AOP_SIZE(result);
6121     offset = size - 1;
6122     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6123     emitcode("rlc","a");
6124     emitcode("mov","ov,c");
6125     /* if it is only one byte then */
6126     if (size == 1) {
6127         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6128         MOVA(l);
6129         emitcode("sjmp","%05d$",tlbl1->key+100);
6130         emitcode("","%05d$:",tlbl->key+100);
6131         emitcode("mov","c,ov");
6132         emitcode("rrc","a");
6133         emitcode("","%05d$:",tlbl1->key+100);
6134         emitcode("djnz","b,%05d$",tlbl->key+100);
6135         aopPut(AOP(result),"a",0);
6136         goto release ;
6137     }
6138
6139     reAdjustPreg(AOP(result));
6140     emitcode("sjmp","%05d$",tlbl1->key+100);
6141     emitcode("","%05d$:",tlbl->key+100);    
6142     emitcode("mov","c,ov");
6143     while (size--) {
6144         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6145         MOVA(l);
6146         emitcode("rrc","a");         
6147         aopPut(AOP(result),"a",offset--);
6148     }
6149     reAdjustPreg(AOP(result));
6150     emitcode("","%05d$:",tlbl1->key+100);
6151     emitcode("djnz","b,%05d$",tlbl->key+100);
6152
6153 release:
6154     freeAsmop(left,NULL,ic,TRUE);
6155     freeAsmop(result,NULL,ic,TRUE);
6156 }
6157
6158 /*-----------------------------------------------------------------*/
6159 /* genRightShift - generate code for right shifting                */
6160 /*-----------------------------------------------------------------*/
6161 static void genRightShift (iCode *ic)
6162 {
6163     operand *right, *left, *result;
6164     link *retype ;
6165     int size, offset;
6166     char *l;
6167     symbol *tlbl, *tlbl1 ;
6168
6169     D(emitcode(";", "genRightShift "););
6170
6171     /* if signed then we do it the hard way preserve the
6172     sign bit moving it inwards */
6173     retype = getSpec(operandType(IC_RESULT(ic)));
6174
6175     if (!SPEC_USIGN(retype)) {
6176         genSignedRightShift (ic);
6177         return ;
6178     }
6179
6180     /* signed & unsigned types are treated the same : i.e. the
6181     signed is NOT propagated inwards : quoting from the
6182     ANSI - standard : "for E1 >> E2, is equivalent to division
6183     by 2**E2 if unsigned or if it has a non-negative value,
6184     otherwise the result is implementation defined ", MY definition
6185     is that the sign does not get propagated */
6186
6187     right = IC_RIGHT(ic);
6188     left  = IC_LEFT(ic);
6189     result = IC_RESULT(ic);
6190
6191     aopOp(right,ic,FALSE, FALSE);
6192
6193     #if 0
6194     /* if the shift count is known then do it 
6195     as efficiently as possible */
6196     if (AOP_TYPE(right) == AOP_LIT) {
6197         genRightShiftLiteral (left,right,result,ic, 0);
6198         return ;
6199     }
6200     #endif
6201
6202     /* shift count is unknown then we have to form 
6203     a loop get the loop count in B : Note: we take
6204     only the lower order byte since shifting
6205     more that 32 bits make no sense anyway, ( the
6206     largest size of an object can be only 32 bits ) */  
6207
6208     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6209     emitcode("inc","b");
6210     freeAsmop (right,NULL,ic,TRUE);
6211     aopOp(left,ic,FALSE, FALSE);
6212     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6213
6214     /* now move the left to the result if they are not the
6215     same */
6216     if (!sameRegs(AOP(left),AOP(result)) && 
6217         AOP_SIZE(result) > 1) {
6218
6219         size = AOP_SIZE(result);
6220         offset=0;
6221         while (size--) {
6222             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6223             if (*l == '@' && IS_AOP_PREG(result)) {
6224
6225                 emitcode("mov","a,%s",l);
6226                 aopPut(AOP(result),"a",offset);
6227             } else
6228                 aopPut(AOP(result),l,offset);
6229             offset++;
6230         }
6231     }
6232
6233     tlbl = newiTempLabel(NULL);
6234     tlbl1= newiTempLabel(NULL);
6235     size = AOP_SIZE(result);
6236     offset = size - 1;
6237
6238     /* if it is only one byte then */
6239     if (size == 1) {
6240         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6241         MOVA(l);
6242         emitcode("sjmp","%05d$",tlbl1->key+100);
6243         emitcode("","%05d$:",tlbl->key+100);
6244         CLRC;
6245         emitcode("rrc","a");
6246         emitcode("","%05d$:",tlbl1->key+100);
6247         emitcode("djnz","b,%05d$",tlbl->key+100);
6248         aopPut(AOP(result),"a",0);
6249         goto release ;
6250     }
6251
6252     reAdjustPreg(AOP(result));
6253     emitcode("sjmp","%05d$",tlbl1->key+100);
6254     emitcode("","%05d$:",tlbl->key+100);    
6255     CLRC;
6256     while (size--) {
6257         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6258         MOVA(l);
6259         emitcode("rrc","a");         
6260         aopPut(AOP(result),"a",offset--);
6261     }
6262     reAdjustPreg(AOP(result));
6263
6264     emitcode("","%05d$:",tlbl1->key+100);
6265     emitcode("djnz","b,%05d$",tlbl->key+100);
6266
6267 release:
6268     freeAsmop(left,NULL,ic,TRUE);
6269     freeAsmop(result,NULL,ic,TRUE);
6270 }
6271
6272 /*-----------------------------------------------------------------*/
6273 /* genUnpackBits - generates code for unpacking bits               */
6274 /*-----------------------------------------------------------------*/
6275 static void genUnpackBits (operand *result, char *rname, int ptype)
6276 {    
6277     int shCnt ;
6278     int rlen = 0 ;
6279     link *etype;
6280     int offset = 0 ;
6281
6282     D(emitcode(";", "genUnpackBits "););
6283
6284     etype = getSpec(operandType(result));
6285
6286     /* read the first byte  */
6287     switch (ptype) {
6288
6289     case POINTER:
6290     case IPOINTER:
6291         emitcode("mov","a,@%s",rname);
6292         break;
6293         
6294     case PPOINTER:
6295         emitcode("movx","a,@%s",rname);
6296         break;
6297         
6298     case FPOINTER:
6299         emitcode("movx","a,@dptr");
6300         break;
6301
6302     case CPOINTER:
6303         emitcode("clr","a");
6304         emitcode("movc","a","@a+dptr");
6305         break;
6306
6307     case GPOINTER:
6308         emitcode("lcall","__gptrget");
6309         break;
6310     }
6311
6312     /* if we have bitdisplacement then it fits   */
6313     /* into this byte completely or if length is */
6314     /* less than a byte                          */
6315     if ((shCnt = SPEC_BSTR(etype)) || 
6316         (SPEC_BLEN(etype) <= 8))  {
6317
6318         /* shift right acc */
6319         AccRsh(shCnt);
6320
6321         emitcode("anl","a,#0x%02x",
6322                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6323         aopPut(AOP(result),"a",offset);
6324         return ;
6325     }
6326
6327     /* bit field did not fit in a byte  */
6328     rlen = SPEC_BLEN(etype) - 8;
6329     aopPut(AOP(result),"a",offset++);
6330
6331     while (1)  {
6332
6333         switch (ptype) {
6334         case POINTER:
6335         case IPOINTER:
6336             emitcode("inc","%s",rname);
6337             emitcode("mov","a,@%s",rname);
6338             break;
6339             
6340         case PPOINTER:
6341             emitcode("inc","%s",rname);
6342             emitcode("movx","a,@%s",rname);
6343             break;
6344
6345         case FPOINTER:
6346             emitcode("inc","dptr");
6347             emitcode("movx","a,@dptr");
6348             break;
6349             
6350         case CPOINTER:
6351             emitcode("clr","a");
6352             emitcode("inc","dptr");
6353             emitcode("movc","a","@a+dptr");
6354             break;
6355             
6356         case GPOINTER:
6357             emitcode("inc","dptr");
6358             emitcode("lcall","__gptrget");
6359             break;
6360         }
6361
6362         rlen -= 8;            
6363         /* if we are done */
6364         if ( rlen <= 0 )
6365             break ;
6366         
6367         aopPut(AOP(result),"a",offset++);
6368                               
6369     }
6370     
6371     if (rlen) {
6372         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6373         aopPut(AOP(result),"a",offset);        
6374     }
6375     
6376     return ;
6377 }
6378
6379
6380 /*-----------------------------------------------------------------*/
6381 /* genDataPointerGet - generates code when ptr offset is known     */
6382 /*-----------------------------------------------------------------*/
6383 static void genDataPointerGet (operand *left, 
6384                                operand *result, 
6385                                iCode *ic)
6386 {
6387     char *l;
6388     char buffer[256];
6389     int size , offset = 0;
6390     aopOp(result,ic,TRUE, FALSE);
6391
6392     /* get the string representation of the name */
6393     l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6394     size = AOP_SIZE(result);
6395     while (size--) {
6396         if (offset)
6397             sprintf(buffer,"(%s + %d)",l+1,offset);
6398         else
6399             sprintf(buffer,"%s",l+1);
6400         aopPut(AOP(result),buffer,offset++);
6401     }
6402
6403     freeAsmop(left,NULL,ic,TRUE);
6404     freeAsmop(result,NULL,ic,TRUE);
6405 }
6406
6407 /*-----------------------------------------------------------------*/
6408 /* genNearPointerGet - emitcode for near pointer fetch             */
6409 /*-----------------------------------------------------------------*/
6410 static void genNearPointerGet (operand *left, 
6411                                operand *result, 
6412                                iCode *ic)
6413 {
6414     asmop *aop = NULL;
6415     regs *preg = NULL ;
6416     char *rname ;
6417     link *rtype, *retype;
6418     link *ltype = operandType(left);    
6419     char buffer[80];
6420
6421     rtype = operandType(result);
6422     retype= getSpec(rtype);
6423     
6424     aopOp(left,ic,FALSE, FALSE);
6425     
6426     /* if left is rematerialisable and
6427        result is not bit variable type and
6428        the left is pointer to data space i.e
6429        lower 128 bytes of space */
6430     if (AOP_TYPE(left) == AOP_IMMD &&
6431         !IS_BITVAR(retype)         &&
6432         DCL_TYPE(ltype) == POINTER) {
6433         genDataPointerGet (left,result,ic);
6434         return ;
6435     }
6436     
6437         /* if the value is already in a pointer register
6438        then don't need anything more */
6439     if (!AOP_INPREG(AOP(left))) {
6440         /* otherwise get a free pointer register */
6441         aop = newAsmop(0);
6442         preg = getFreePtr(ic,&aop,FALSE);
6443         emitcode("mov","%s,%s",
6444                 preg->name,
6445                 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6446         rname = preg->name ;
6447     } else
6448         rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6449     
6450     freeAsmop(left,NULL,ic,TRUE);
6451     aopOp (result,ic,FALSE, FALSE);
6452     
6453       /* if bitfield then unpack the bits */
6454     if (IS_BITVAR(retype)) 
6455         genUnpackBits (result,rname,POINTER);
6456     else {
6457         /* we have can just get the values */
6458         int size = AOP_SIZE(result);
6459         int offset = 0 ;        
6460         
6461         while (size--) {
6462             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6463
6464                 emitcode("mov","a,@%s",rname);
6465                 aopPut(AOP(result),"a",offset);
6466             } else {
6467                 sprintf(buffer,"@%s",rname);
6468                 aopPut(AOP(result),buffer,offset);
6469             }
6470             offset++ ;
6471             if (size)
6472                 emitcode("inc","%s",rname);
6473         }
6474     }
6475
6476     /* now some housekeeping stuff */
6477     if (aop) {
6478         /* we had to allocate for this iCode */
6479         freeAsmop(NULL,aop,ic,TRUE);
6480     } else { 
6481         /* we did not allocate which means left
6482            already in a pointer register, then
6483            if size > 0 && this could be used again
6484            we have to point it back to where it 
6485            belongs */
6486         if (AOP_SIZE(result) > 1 &&
6487             !OP_SYMBOL(left)->remat &&
6488             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6489               ic->depth )) {
6490             int size = AOP_SIZE(result) - 1;
6491             while (size--)
6492                 emitcode("dec","%s",rname);
6493         }
6494     }
6495
6496     /* done */
6497     freeAsmop(result,NULL,ic,TRUE);
6498      
6499 }
6500
6501 /*-----------------------------------------------------------------*/
6502 /* genPagedPointerGet - emitcode for paged pointer fetch           */
6503 /*-----------------------------------------------------------------*/
6504 static void genPagedPointerGet (operand *left, 
6505                                operand *result, 
6506                                iCode *ic)
6507 {
6508     asmop *aop = NULL;
6509     regs *preg = NULL ;
6510     char *rname ;
6511     link *rtype, *retype;    
6512
6513     rtype = operandType(result);
6514     retype= getSpec(rtype);
6515     
6516     aopOp(left,ic,FALSE, FALSE);
6517
6518   /* if the value is already in a pointer register
6519        then don't need anything more */
6520     if (!AOP_INPREG(AOP(left))) {
6521         /* otherwise get a free pointer register */
6522         aop = newAsmop(0);
6523         preg = getFreePtr(ic,&aop,FALSE);
6524         emitcode("mov","%s,%s",
6525                 preg->name,
6526                 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6527         rname = preg->name ;
6528     } else
6529         rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6530     
6531     freeAsmop(left,NULL,ic,TRUE);
6532     aopOp (result,ic,FALSE, FALSE);
6533
6534     /* if bitfield then unpack the bits */
6535     if (IS_BITVAR(retype)) 
6536         genUnpackBits (result,rname,PPOINTER);
6537     else {
6538         /* we have can just get the values */
6539         int size = AOP_SIZE(result);
6540         int offset = 0 ;        
6541         
6542         while (size--) {
6543             
6544             emitcode("movx","a,@%s",rname);
6545             aopPut(AOP(result),"a",offset);
6546             
6547             offset++ ;
6548             
6549             if (size)
6550                 emitcode("inc","%s",rname);
6551         }
6552     }
6553
6554     /* now some housekeeping stuff */
6555     if (aop) {
6556         /* we had to allocate for this iCode */
6557         freeAsmop(NULL,aop,ic,TRUE);
6558     } else { 
6559         /* we did not allocate which means left
6560            already in a pointer register, then
6561            if size > 0 && this could be used again
6562            we have to point it back to where it 
6563            belongs */
6564         if (AOP_SIZE(result) > 1 &&
6565             !OP_SYMBOL(left)->remat &&
6566             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6567               ic->depth )) {
6568             int size = AOP_SIZE(result) - 1;
6569             while (size--)
6570                 emitcode("dec","%s",rname);
6571         }
6572     }
6573
6574     /* done */
6575     freeAsmop(result,NULL,ic,TRUE);
6576     
6577         
6578 }
6579
6580 /*-----------------------------------------------------------------*/
6581 /* genFarPointerGet - gget value from far space                    */
6582 /*-----------------------------------------------------------------*/
6583 static void genFarPointerGet (operand *left,
6584                               operand *result, iCode *ic)
6585 {
6586     int size, offset ;
6587     link *retype = getSpec(operandType(result));
6588
6589     D(emitcode(";", "genFarPointerGet"););
6590
6591     aopOp(left,ic,FALSE, FALSE);
6592
6593     /* if the operand is already in dptr 
6594     then we do nothing else we move the value to dptr */
6595     if (AOP_TYPE(left) != AOP_STR) {
6596         /* if this is remateriazable */
6597         if (AOP_TYPE(left) == AOP_IMMD)
6598         {
6599             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6600         }
6601         else 
6602         { 
6603             /* we need to get it byte by byte */
6604             if (AOP_TYPE(left) != AOP_DPTR)
6605             {
6606                 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6607                 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6608                 if (options.model == MODEL_FLAT24)
6609                 {
6610                     emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6611                 }
6612             }
6613             else
6614             {
6615                  /* We need to generate a load to DPTR indirect through DPTR. */
6616                  D(emitcode(";", "genFarPointerGet -- indirection special case."););
6617                  emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6618                  emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6619                  emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6620                  emitcode("pop", "dph");
6621                  emitcode("pop", "dpl");
6622             }
6623         }
6624     }
6625     /* so dptr know contains the address */
6626     freeAsmop(left,NULL,ic,TRUE);
6627     aopOp(result,ic,FALSE, TRUE);
6628
6629     /* if bit then unpack */
6630     if (IS_BITVAR(retype)) 
6631         genUnpackBits(result,"dptr",FPOINTER);
6632     else {
6633         size = AOP_SIZE(result);
6634         offset = 0 ;
6635
6636         while (size--) {
6637             emitcode("movx","a,@dptr");
6638             aopPut(AOP(result),"a",offset++);
6639             if (size)
6640                 emitcode("inc","dptr");
6641         }
6642     }
6643
6644     freeAsmop(result,NULL,ic,TRUE);
6645 }
6646
6647 /*-----------------------------------------------------------------*/
6648 /* emitcodePointerGet - gget value from code space                  */
6649 /*-----------------------------------------------------------------*/
6650 static void emitcodePointerGet (operand *left,
6651                                 operand *result, iCode *ic)
6652 {
6653     int size, offset ;
6654     link *retype = getSpec(operandType(result));
6655
6656     aopOp(left,ic,FALSE, FALSE);
6657
6658     /* if the operand is already in dptr 
6659     then we do nothing else we move the value to dptr */
6660     if (AOP_TYPE(left) != AOP_STR) {
6661         /* if this is remateriazable */
6662         if (AOP_TYPE(left) == AOP_IMMD)
6663             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6664         else { /* we need to get it byte by byte */
6665             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6666             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6667             if (options.model == MODEL_FLAT24)
6668             {
6669                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6670             }
6671         }
6672     }
6673     /* so dptr know contains the address */
6674     freeAsmop(left,NULL,ic,TRUE);
6675     aopOp(result,ic,FALSE, FALSE);
6676
6677     /* if bit then unpack */
6678     if (IS_BITVAR(retype)) 
6679         genUnpackBits(result,"dptr",CPOINTER);
6680     else {
6681         size = AOP_SIZE(result);
6682         offset = 0 ;
6683
6684         while (size--) {
6685             emitcode("clr","a");
6686             emitcode("movc","a,@a+dptr");
6687             aopPut(AOP(result),"a",offset++);
6688             if (size)
6689                 emitcode("inc","dptr");
6690         }
6691     }
6692
6693     freeAsmop(result,NULL,ic,TRUE);
6694 }
6695
6696 /*-----------------------------------------------------------------*/
6697 /* genGenPointerGet - gget value from generic pointer space        */
6698 /*-----------------------------------------------------------------*/
6699 static void genGenPointerGet (operand *left,
6700                               operand *result, iCode *ic)
6701 {
6702     int size, offset ;
6703     link *retype = getSpec(operandType(result));
6704
6705     aopOp(left,ic,FALSE, TRUE);
6706
6707     /* if the operand is already in dptr 
6708     then we do nothing else we move the value to dptr */
6709     if (AOP_TYPE(left) != AOP_STR) {
6710         /* if this is remateriazable */
6711         if (AOP_TYPE(left) == AOP_IMMD) {
6712             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6713             emitcode("mov","b,#%d",pointerCode(retype));
6714         }
6715         else { /* we need to get it byte by byte */
6716             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6717             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6718             if (options.model == MODEL_FLAT24)
6719             {
6720                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6721                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
6722             }
6723             else
6724             {
6725                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6726             }
6727         }
6728     }
6729     /* so dptr know contains the address */
6730     freeAsmop(left,NULL,ic,TRUE);
6731     aopOp(result,ic,FALSE, TRUE);
6732
6733     /* if bit then unpack */
6734     if (IS_BITVAR(retype)) 
6735         genUnpackBits(result,"dptr",GPOINTER);
6736     else {
6737         size = AOP_SIZE(result);
6738         offset = 0 ;
6739
6740         while (size--) {
6741             emitcode("lcall","__gptrget");
6742             aopPut(AOP(result),"a",offset++);
6743             if (size)
6744                 emitcode("inc","dptr");
6745         }
6746     }
6747
6748     freeAsmop(result,NULL,ic,TRUE);
6749 }
6750
6751 /*-----------------------------------------------------------------*/
6752 /* genPointerGet - generate code for pointer get                   */
6753 /*-----------------------------------------------------------------*/
6754 static void genPointerGet (iCode *ic)
6755 {
6756     operand *left, *result ;
6757     link *type, *etype;
6758     int p_type;
6759
6760     D(emitcode(";", "genPointerGet "););
6761
6762     left = IC_LEFT(ic);
6763     result = IC_RESULT(ic) ;
6764
6765     /* depending on the type of pointer we need to
6766     move it to the correct pointer register */
6767     type = operandType(left);
6768     etype = getSpec(type);
6769     /* if left is of type of pointer then it is simple */
6770     if (IS_PTR(type) && !IS_FUNC(type->next)) 
6771         p_type = DCL_TYPE(type);
6772     else {
6773         /* we have to go by the storage class */
6774         p_type = PTR_TYPE(SPEC_OCLS(etype));
6775
6776 /*      if (SPEC_OCLS(etype)->codesp ) { */
6777 /*          p_type = CPOINTER ;  */
6778 /*      } */
6779 /*      else */
6780 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6781 /*              p_type = FPOINTER ; */
6782 /*          else */
6783 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6784 /*                  p_type = PPOINTER; */
6785 /*              else */
6786 /*                  if (SPEC_OCLS(etype) == idata ) */
6787 /*                      p_type = IPOINTER; */
6788 /*                  else */
6789 /*                      p_type = POINTER ; */
6790     }
6791
6792     /* now that we have the pointer type we assign
6793     the pointer values */
6794     switch (p_type) {
6795
6796     case POINTER:       
6797     case IPOINTER:
6798         genNearPointerGet (left,result,ic);
6799         break;
6800
6801     case PPOINTER:
6802         genPagedPointerGet(left,result,ic);
6803         break;
6804
6805     case FPOINTER:
6806         genFarPointerGet (left,result,ic);
6807         break;
6808
6809     case CPOINTER:
6810         emitcodePointerGet (left,result,ic);
6811         break;
6812
6813     case GPOINTER:
6814         genGenPointerGet (left,result,ic);
6815         break;
6816     }
6817
6818 }
6819
6820 /*-----------------------------------------------------------------*/
6821 /* genPackBits - generates code for packed bit storage             */
6822 /*-----------------------------------------------------------------*/
6823 static void genPackBits (link    *etype ,
6824                          operand *right ,
6825                          char *rname, int p_type)
6826 {
6827     int shCount = 0 ;
6828     int offset = 0  ;
6829     int rLen = 0 ;
6830     int blen, bstr ;   
6831     char *l ;
6832
6833     blen = SPEC_BLEN(etype);
6834     bstr = SPEC_BSTR(etype);
6835
6836     l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
6837     MOVA(l);   
6838
6839     /* if the bit lenth is less than or    */
6840     /* it exactly fits a byte then         */
6841     if (SPEC_BLEN(etype) <= 8 )  {
6842         shCount = SPEC_BSTR(etype) ;
6843
6844         /* shift left acc */
6845         AccLsh(shCount);
6846
6847         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6848
6849
6850             switch (p_type) {
6851                 case POINTER:
6852                     emitcode ("mov","b,a");
6853                     emitcode("mov","a,@%s",rname);
6854                     break;
6855
6856                 case FPOINTER:
6857                     emitcode ("mov","b,a");
6858                     emitcode("movx","a,@dptr");
6859                     break;
6860
6861                 case GPOINTER:
6862                     emitcode ("push","b");
6863                     emitcode ("push","acc");
6864                     emitcode ("lcall","__gptrget");
6865                     emitcode ("pop","b");
6866                     break;
6867             }
6868
6869             emitcode ("anl","a,#0x%02x",(unsigned char)
6870                       ((unsigned char)(0xFF << (blen+bstr)) | 
6871                        (unsigned char)(0xFF >> (8-bstr)) ) );
6872             emitcode ("orl","a,b");
6873             if (p_type == GPOINTER)
6874                 emitcode("pop","b");
6875         }
6876     }
6877
6878     switch (p_type) {
6879         case POINTER:
6880             emitcode("mov","@%s,a",rname);
6881             break;
6882
6883         case FPOINTER:
6884             emitcode("movx","@dptr,a");
6885             break;
6886
6887         case GPOINTER:
6888             emitcode("lcall","__gptrput");
6889             break;
6890     }
6891
6892     /* if we r done */
6893     if ( SPEC_BLEN(etype) <= 8 )
6894         return ;
6895
6896     emitcode("inc","%s",rname);
6897     rLen = SPEC_BLEN(etype) ;     
6898
6899     /* now generate for lengths greater than one byte */
6900     while (1) {
6901
6902         l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
6903
6904         rLen -= 8 ;
6905         if (rLen <= 0 )
6906             break ;
6907
6908         switch (p_type) {
6909             case POINTER:
6910                 if (*l == '@') {
6911                     MOVA(l);
6912                     emitcode("mov","@%s,a",rname);
6913                 } else
6914                     emitcode("mov","@%s,%s",rname,l);
6915                 break;
6916
6917             case FPOINTER:
6918                 MOVA(l);
6919                 emitcode("movx","@dptr,a");
6920                 break;
6921
6922             case GPOINTER:
6923                 MOVA(l);
6924                 emitcode("lcall","__gptrput");
6925                 break;  
6926         }   
6927         emitcode ("inc","%s",rname);
6928     }
6929
6930     MOVA(l);
6931
6932     /* last last was not complete */
6933     if (rLen)   {
6934         /* save the byte & read byte */
6935         switch (p_type) {
6936             case POINTER:
6937                 emitcode ("mov","b,a");
6938                 emitcode("mov","a,@%s",rname);
6939                 break;
6940
6941             case FPOINTER:
6942                 emitcode ("mov","b,a");
6943                 emitcode("movx","a,@dptr");
6944                 break;
6945
6946             case GPOINTER:
6947                 emitcode ("push","b");
6948                 emitcode ("push","acc");
6949                 emitcode ("lcall","__gptrget");
6950                 emitcode ("pop","b");
6951                 break;
6952         }
6953
6954         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6955         emitcode ("orl","a,b");
6956     }
6957
6958     if (p_type == GPOINTER)
6959         emitcode("pop","b");
6960
6961     switch (p_type) {
6962
6963     case POINTER:
6964         emitcode("mov","@%s,a",rname);
6965         break;
6966         
6967     case FPOINTER:
6968         emitcode("movx","@dptr,a");
6969         break;
6970         
6971     case GPOINTER:
6972         emitcode("lcall","__gptrput");
6973         break;                  
6974     }
6975 }
6976 /*-----------------------------------------------------------------*/
6977 /* genDataPointerSet - remat pointer to data space                 */
6978 /*-----------------------------------------------------------------*/
6979 static void genDataPointerSet(operand *right,
6980                               operand *result,
6981                               iCode *ic)
6982 {
6983     int size, offset = 0 ;
6984     char *l, buffer[256];
6985
6986     aopOp(right,ic,FALSE, FALSE);
6987     
6988     l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
6989     size = AOP_SIZE(right);
6990     while (size--) {
6991         if (offset)
6992             sprintf(buffer,"(%s + %d)",l+1,offset);
6993         else
6994             sprintf(buffer,"%s",l+1);
6995         emitcode("mov","%s,%s",buffer,
6996                  aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
6997     }
6998
6999     freeAsmop(right,NULL,ic,TRUE);
7000     freeAsmop(result,NULL,ic,TRUE);
7001 }
7002
7003 /*-----------------------------------------------------------------*/
7004 /* genNearPointerSet - emitcode for near pointer put                */
7005 /*-----------------------------------------------------------------*/
7006 static void genNearPointerSet (operand *right,
7007                                operand *result, 
7008                                iCode *ic)
7009 {
7010     asmop *aop = NULL;
7011     regs *preg = NULL ;
7012     char *rname , *l;
7013     link *retype;
7014     link *ptype = operandType(result);
7015     
7016     retype= getSpec(operandType(right));
7017
7018     aopOp(result,ic,FALSE, FALSE);
7019     
7020     /* if the result is rematerializable &
7021        in data space & not a bit variable */
7022     if (AOP_TYPE(result) == AOP_IMMD &&
7023         DCL_TYPE(ptype) == POINTER   &&
7024         !IS_BITVAR(retype)) {
7025         genDataPointerSet (right,result,ic);
7026         return;
7027     }
7028
7029     /* if the value is already in a pointer register
7030     then don't need anything more */
7031     if (!AOP_INPREG(AOP(result))) {
7032         /* otherwise get a free pointer register */
7033         aop = newAsmop(0);
7034         preg = getFreePtr(ic,&aop,FALSE);
7035         emitcode("mov","%s,%s",
7036                  preg->name,
7037                  aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7038         rname = preg->name ;
7039     } else
7040         rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7041
7042     freeAsmop(result,NULL,ic,TRUE);
7043     aopOp (right,ic,FALSE, FALSE);
7044
7045     /* if bitfield then unpack the bits */
7046     if (IS_BITVAR(retype)) 
7047         genPackBits (retype,right,rname,POINTER);
7048     else {
7049         /* we have can just get the values */
7050         int size = AOP_SIZE(right);
7051         int offset = 0 ;    
7052
7053         while (size--) {
7054             l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7055             if (*l == '@' ) {
7056                 MOVA(l);
7057                 emitcode("mov","@%s,a",rname);
7058             } else
7059                 emitcode("mov","@%s,%s",rname,l);
7060             if (size)
7061                 emitcode("inc","%s",rname);
7062             offset++;
7063         }
7064     }
7065
7066     /* now some housekeeping stuff */
7067     if (aop) {
7068         /* we had to allocate for this iCode */
7069         freeAsmop(NULL,aop,ic,TRUE);
7070     } else { 
7071         /* we did not allocate which means left
7072         already in a pointer register, then
7073         if size > 0 && this could be used again
7074         we have to point it back to where it 
7075         belongs */
7076         if (AOP_SIZE(right) > 1 &&
7077             !OP_SYMBOL(result)->remat &&
7078             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7079               ic->depth )) {
7080             int size = AOP_SIZE(right) - 1;
7081             while (size--)
7082                 emitcode("dec","%s",rname);
7083         }
7084     }
7085
7086     /* done */
7087     freeAsmop(right,NULL,ic,TRUE);
7088
7089
7090 }
7091
7092 /*-----------------------------------------------------------------*/
7093 /* genPagedPointerSet - emitcode for Paged pointer put             */
7094 /*-----------------------------------------------------------------*/
7095 static void genPagedPointerSet (operand *right,
7096                                operand *result, 
7097                                iCode *ic)
7098 {
7099     asmop *aop = NULL;
7100     regs *preg = NULL ;
7101     char *rname , *l;
7102     link *retype;
7103        
7104     retype= getSpec(operandType(right));
7105     
7106     aopOp(result,ic,FALSE, FALSE);
7107     
7108     /* if the value is already in a pointer register
7109        then don't need anything more */
7110     if (!AOP_INPREG(AOP(result))) {
7111         /* otherwise get a free pointer register */
7112         aop = newAsmop(0);
7113         preg = getFreePtr(ic,&aop,FALSE);
7114         emitcode("mov","%s,%s",
7115                 preg->name,
7116                 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7117         rname = preg->name ;
7118     } else
7119         rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7120     
7121     freeAsmop(result,NULL,ic,TRUE);
7122     aopOp (right,ic,FALSE, FALSE);
7123
7124     /* if bitfield then unpack the bits */
7125     if (IS_BITVAR(retype)) 
7126         genPackBits (retype,right,rname,PPOINTER);
7127     else {
7128         /* we have can just get the values */
7129         int size = AOP_SIZE(right);
7130         int offset = 0 ;        
7131         
7132         while (size--) {
7133             l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7134             
7135             MOVA(l);
7136             emitcode("movx","@%s,a",rname);
7137
7138             if (size)
7139                 emitcode("inc","%s",rname);
7140
7141             offset++;
7142         }
7143     }
7144     
7145     /* now some housekeeping stuff */
7146     if (aop) {
7147         /* we had to allocate for this iCode */
7148         freeAsmop(NULL,aop,ic,TRUE);
7149     } else { 
7150         /* we did not allocate which means left
7151            already in a pointer register, then
7152            if size > 0 && this could be used again
7153            we have to point it back to where it 
7154            belongs */
7155         if (AOP_SIZE(right) > 1 &&
7156             !OP_SYMBOL(result)->remat &&
7157             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7158               ic->depth )) {
7159             int size = AOP_SIZE(right) - 1;
7160             while (size--)
7161                 emitcode("dec","%s",rname);
7162         }
7163     }
7164
7165     /* done */
7166     freeAsmop(right,NULL,ic,TRUE);
7167     
7168         
7169 }
7170
7171 /*-----------------------------------------------------------------*/
7172 /* genFarPointerSet - set value from far space                     */
7173 /*-----------------------------------------------------------------*/
7174 static void genFarPointerSet (operand *right,
7175                               operand *result, iCode *ic)
7176 {
7177     int size, offset ;
7178     link *retype = getSpec(operandType(right));
7179
7180     aopOp(result,ic,FALSE, FALSE);
7181
7182     /* if the operand is already in dptr 
7183     then we do nothing else we move the value to dptr */
7184     if (AOP_TYPE(result) != AOP_STR) {
7185         /* if this is remateriazable */
7186         if (AOP_TYPE(result) == AOP_IMMD)
7187             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7188         else 
7189         {
7190             /* we need to get it byte by byte */
7191             if (AOP_TYPE(result) != AOP_DPTR)
7192             {
7193                 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7194                 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7195                 if (options.model == MODEL_FLAT24)
7196                 {
7197                     emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7198                 }
7199             }
7200             else
7201             {
7202                  /* We need to generate a load to DPTR indirect through DPTR. */
7203                  D(emitcode(";", "genFarPointerSet -- indirection special case."););
7204                  emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7205                  emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7206                  emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7207                  emitcode("pop", "dph");
7208                  emitcode("pop", "dpl");
7209             }
7210         }
7211     }
7212     /* so dptr know contains the address */
7213     freeAsmop(result,NULL,ic,TRUE);
7214     aopOp(right,ic,FALSE, TRUE);
7215
7216     /* if bit then unpack */
7217     if (IS_BITVAR(retype)) 
7218         genPackBits(retype,right,"dptr",FPOINTER);
7219     else {
7220         size = AOP_SIZE(right);
7221         offset = 0 ;
7222
7223         while (size--) {
7224             char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7225             MOVA(l);
7226             emitcode("movx","@dptr,a");
7227             if (size)
7228                 emitcode("inc","dptr");
7229         }
7230     }
7231
7232     freeAsmop(right,NULL,ic,TRUE);
7233 }
7234
7235 /*-----------------------------------------------------------------*/
7236 /* genGenPointerSet - set value from generic pointer space         */
7237 /*-----------------------------------------------------------------*/
7238 static void genGenPointerSet (operand *right,
7239                               operand *result, iCode *ic)
7240 {
7241     int size, offset ;
7242     link *retype = getSpec(operandType(right));
7243
7244     aopOp(result,ic,FALSE, TRUE);
7245
7246     /* if the operand is already in dptr 
7247     then we do nothing else we move the value to dptr */
7248     if (AOP_TYPE(result) != AOP_STR) {
7249         /* if this is remateriazable */
7250         if (AOP_TYPE(result) == AOP_IMMD) {
7251             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7252             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7253         }
7254         else { /* we need to get it byte by byte */
7255             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7256             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7257             if (options.model == MODEL_FLAT24)
7258             {
7259                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7260                emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7261             }
7262             else
7263             {
7264                 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7265             }
7266         }
7267     }
7268     /* so dptr know contains the address */
7269     freeAsmop(result,NULL,ic,TRUE);
7270     aopOp(right,ic,FALSE, TRUE);
7271
7272     /* if bit then unpack */
7273     if (IS_BITVAR(retype)) 
7274         genPackBits(retype,right,"dptr",GPOINTER);
7275     else {
7276         size = AOP_SIZE(right);
7277         offset = 0 ;
7278
7279         while (size--) {
7280             char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7281             MOVA(l);
7282             emitcode("lcall","__gptrput");
7283             if (size)
7284                 emitcode("inc","dptr");
7285         }
7286     }
7287
7288     freeAsmop(right,NULL,ic,TRUE);
7289 }
7290
7291 /*-----------------------------------------------------------------*/
7292 /* genPointerSet - stores the value into a pointer location        */
7293 /*-----------------------------------------------------------------*/
7294 static void genPointerSet (iCode *ic)
7295 {    
7296     operand *right, *result ;
7297     link *type, *etype;
7298     int p_type;
7299
7300     D(emitcode(";", "genPointerSet "););
7301
7302     right = IC_RIGHT(ic);
7303     result = IC_RESULT(ic) ;
7304
7305     /* depending on the type of pointer we need to
7306     move it to the correct pointer register */
7307     type = operandType(result);
7308     etype = getSpec(type);
7309     /* if left is of type of pointer then it is simple */
7310     if (IS_PTR(type) && !IS_FUNC(type->next)) {
7311         p_type = DCL_TYPE(type);
7312     }
7313     else {
7314         /* we have to go by the storage class */
7315         p_type = PTR_TYPE(SPEC_OCLS(etype));
7316
7317 /*      if (SPEC_OCLS(etype)->codesp ) { */
7318 /*          p_type = CPOINTER ;  */
7319 /*      } */
7320 /*      else */
7321 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7322 /*              p_type = FPOINTER ; */
7323 /*          else */
7324 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7325 /*                  p_type = PPOINTER ; */
7326 /*              else */
7327 /*                  if (SPEC_OCLS(etype) == idata ) */
7328 /*                      p_type = IPOINTER ; */
7329 /*                  else */
7330 /*                      p_type = POINTER ; */
7331     }
7332
7333     /* now that we have the pointer type we assign
7334     the pointer values */
7335     switch (p_type) {
7336
7337     case POINTER:
7338     case IPOINTER:
7339         genNearPointerSet (right,result,ic);
7340         break;
7341
7342     case PPOINTER:
7343         genPagedPointerSet (right,result,ic);
7344         break;
7345
7346     case FPOINTER:
7347         genFarPointerSet (right,result,ic);
7348         break;
7349
7350     case GPOINTER:
7351         genGenPointerSet (right,result,ic);
7352         break;
7353     }
7354
7355 }
7356
7357 /*-----------------------------------------------------------------*/
7358 /* genIfx - generate code for Ifx statement                        */
7359 /*-----------------------------------------------------------------*/
7360 static void genIfx (iCode *ic, iCode *popIc)
7361 {
7362     operand *cond = IC_COND(ic);
7363     int isbit =0;
7364
7365     D(emitcode(";", "genIfx "););
7366
7367     aopOp(cond,ic,FALSE, FALSE);
7368
7369     /* get the value into acc */
7370     if (AOP_TYPE(cond) != AOP_CRY)
7371         toBoolean(cond);
7372     else
7373         isbit = 1;
7374     /* the result is now in the accumulator */
7375     freeAsmop(cond,NULL,ic,TRUE);
7376
7377     /* if there was something to be popped then do it */
7378     if (popIc)
7379         genIpop(popIc);
7380
7381     /* if the condition is  a bit variable */
7382     if (isbit && IS_ITEMP(cond) && 
7383         SPIL_LOC(cond))
7384         genIfxJump(ic,SPIL_LOC(cond)->rname);
7385     else
7386         if (isbit && !IS_ITEMP(cond))
7387             genIfxJump(ic,OP_SYMBOL(cond)->rname);
7388         else
7389             genIfxJump(ic,"a");
7390
7391     ic->generated = 1;
7392 }
7393
7394 /*-----------------------------------------------------------------*/
7395 /* genAddrOf - generates code for address of                       */
7396 /*-----------------------------------------------------------------*/
7397 static void genAddrOf (iCode *ic)
7398 {
7399     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7400     int size, offset ;
7401
7402     D(emitcode(";", "genAddrOf "););
7403
7404     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7405
7406     /* if the operand is on the stack then we 
7407     need to get the stack offset of this
7408     variable */
7409     if (sym->onStack) {
7410         /* if it has an offset then we need to compute
7411         it */
7412         if (sym->stack) {
7413             emitcode("mov","a,_bp");
7414             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7415             aopPut(AOP(IC_RESULT(ic)),"a",0);       
7416         } else {
7417             /* we can just move _bp */
7418             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7419         }
7420         /* fill the result with zero */
7421         size = AOP_SIZE(IC_RESULT(ic)) - 1;
7422         
7423         
7424         if (options.stack10bit && size < (FPTRSIZE - 1))
7425         {
7426             fprintf(stderr, 
7427                     "*** warning: pointer to stack var truncated.\n");
7428         }
7429         
7430         offset = 1;
7431         while (size--)
7432         {
7433             /* Yuck! */
7434             if (options.stack10bit && offset == 2)
7435             {
7436                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7437             }
7438             else
7439             {
7440                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7441             }
7442         }
7443
7444         goto release;
7445     }
7446
7447     /* object not on stack then we need the name */
7448     size = AOP_SIZE(IC_RESULT(ic));
7449     offset = 0;
7450
7451     while (size--) {
7452         char s[SDCC_NAME_MAX];
7453         if (offset) 
7454             sprintf(s,"#(%s >> %d)",
7455                     sym->rname,
7456                     offset*8);
7457         else
7458             sprintf(s,"#%s",sym->rname);
7459         aopPut(AOP(IC_RESULT(ic)),s,offset++);
7460     }
7461
7462 release:
7463     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7464
7465 }
7466
7467 /*-----------------------------------------------------------------*/
7468 /* genFarFarAssign - assignment when both are in far space         */
7469 /*-----------------------------------------------------------------*/
7470 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7471 {
7472     int size = AOP_SIZE(right);
7473     int offset = 0;
7474     char *l ;
7475     /* first push the right side on to the stack */
7476     while (size--) {
7477         l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7478         MOVA(l);
7479         emitcode ("push","acc");
7480     }
7481     
7482     D(emitcode(";", "genFarFarAssign "););
7483
7484     freeAsmop(right,NULL,ic,FALSE);
7485     /* now assign DPTR to result */
7486     aopOp(result,ic,FALSE, FALSE);
7487     size = AOP_SIZE(result);
7488     while (size--) {
7489         emitcode ("pop","acc");
7490         aopPut(AOP(result),"a",--offset);
7491     }
7492     freeAsmop(result,NULL,ic,FALSE);
7493         
7494 }
7495
7496 /*-----------------------------------------------------------------*/
7497 /* genAssign - generate code for assignment                        */
7498 /*-----------------------------------------------------------------*/
7499 static void genAssign (iCode *ic)
7500 {
7501     operand *result, *right;
7502     int size, offset ;
7503         unsigned long lit = 0L;
7504
7505     D(emitcode(";", "genAssign "););
7506
7507     result = IC_RESULT(ic);
7508     right  = IC_RIGHT(ic) ;
7509
7510     /* if they are the same */
7511     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7512         return ;
7513
7514     aopOp(right,ic,FALSE, FALSE);
7515     
7516     emitcode(";", "genAssign: resultIsFar = %s",
7517              isOperandInFarSpace(result) ?
7518              "TRUE" : "FALSE");
7519
7520     /* special case both in far space */
7521     if ((AOP_TYPE(right) == AOP_DPTR ||
7522          AOP_TYPE(right) == AOP_DPTR2) &&
7523     /* IS_TRUE_SYMOP(result)       && */
7524     isOperandInFarSpace(result)) {
7525         
7526         genFarFarAssign (result,right,ic);
7527         return ;
7528     }
7529
7530     aopOp(result,ic,TRUE, FALSE);
7531
7532     /* if they are the same registers */
7533     if (sameRegs(AOP(right),AOP(result)))
7534         goto release;
7535
7536     /* if the result is a bit */
7537     if (AOP_TYPE(result) == AOP_CRY) {
7538
7539         /* if the right size is a literal then
7540         we know what the value is */
7541         if (AOP_TYPE(right) == AOP_LIT) {
7542             if (((int) operandLitValue(right))) 
7543                 aopPut(AOP(result),one,0);
7544             else
7545                 aopPut(AOP(result),zero,0);
7546             goto release;
7547         }
7548
7549         /* the right is also a bit variable */
7550         if (AOP_TYPE(right) == AOP_CRY) {
7551             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7552             aopPut(AOP(result),"c",0);
7553             goto release ;
7554         }
7555
7556         /* we need to or */
7557         toBoolean(right);
7558         aopPut(AOP(result),"a",0);
7559         goto release ;
7560     }
7561
7562     /* bit variables done */
7563     /* general case */
7564     size = AOP_SIZE(result);
7565     offset = 0 ;
7566     if(AOP_TYPE(right) == AOP_LIT)
7567         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7568     if((size > 1) &&
7569        (AOP_TYPE(result) != AOP_REG) &&
7570        (AOP_TYPE(right) == AOP_LIT) &&
7571        !IS_FLOAT(operandType(right)) &&
7572        (lit < 256L)){
7573         emitcode("clr","a");
7574         while (size--) {
7575             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7576                 aopPut(AOP(result),"a",size);
7577             else
7578                 aopPut(AOP(result),
7579                        aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7580                        size);
7581         }
7582     } else {
7583         while (size--) {
7584             aopPut(AOP(result),
7585                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7586                    offset);
7587             offset++;
7588         }
7589     }
7590     
7591 release:
7592     freeAsmop (right,NULL,ic,FALSE);
7593     freeAsmop (result,NULL,ic,TRUE);
7594 }   
7595
7596 /*-----------------------------------------------------------------*/
7597 /* genJumpTab - genrates code for jump table                       */
7598 /*-----------------------------------------------------------------*/
7599 static void genJumpTab (iCode *ic)
7600 {
7601     symbol *jtab;
7602     char *l;
7603
7604     D(emitcode(";", "genJumpTab "););
7605
7606     aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7607     /* get the condition into accumulator */
7608     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7609     MOVA(l);
7610     /* multiply by four! */
7611     emitcode("add","a,acc");
7612     emitcode("add","a,acc");
7613     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7614
7615     jtab = newiTempLabel(NULL);
7616     emitcode("mov","dptr,#%05d$",jtab->key+100);
7617     emitcode("jmp","@a+dptr");
7618     emitcode("","%05d$:",jtab->key+100);
7619     /* now generate the jump labels */
7620     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7621          jtab = setNextItem(IC_JTLABELS(ic)))
7622         emitcode("ljmp","%05d$",jtab->key+100);
7623
7624 }
7625
7626 /*-----------------------------------------------------------------*/
7627 /* genCast - gen code for casting                                  */
7628 /*-----------------------------------------------------------------*/
7629 static void genCast (iCode *ic)
7630 {
7631     operand *result = IC_RESULT(ic);
7632     link *ctype = operandType(IC_LEFT(ic));
7633     link *rtype = operandType(IC_RIGHT(ic));
7634     operand *right = IC_RIGHT(ic);
7635     int size, offset ;
7636
7637     D(emitcode(";", "genCast "););
7638
7639     /* if they are equivalent then do nothing */
7640     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7641         return ;
7642
7643     aopOp(right,ic,FALSE, FALSE) ;
7644     aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7645
7646     /* if the result is a bit */
7647     if (AOP_TYPE(result) == AOP_CRY) {
7648         /* if the right size is a literal then
7649         we know what the value is */
7650         if (AOP_TYPE(right) == AOP_LIT) {
7651             if (((int) operandLitValue(right))) 
7652                 aopPut(AOP(result),one,0);
7653             else
7654                 aopPut(AOP(result),zero,0);
7655
7656             goto release;
7657         }
7658
7659         /* the right is also a bit variable */
7660         if (AOP_TYPE(right) == AOP_CRY) {
7661             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7662             aopPut(AOP(result),"c",0);
7663             goto release ;
7664         }
7665
7666         /* we need to or */
7667         toBoolean(right);
7668         aopPut(AOP(result),"a",0);
7669         goto release ;
7670     }
7671
7672     /* if they are the same size : or less */
7673     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7674
7675         /* if they are in the same place */
7676         if (sameRegs(AOP(right),AOP(result)))
7677             goto release;
7678
7679         /* if they in different places then copy */
7680         size = AOP_SIZE(result);
7681         offset = 0 ;
7682         while (size--) {
7683             aopPut(AOP(result),
7684                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7685                    offset);
7686             offset++;
7687         }
7688         goto release;
7689     }
7690
7691
7692     /* if the result is of type pointer */
7693     if (IS_PTR(ctype)) {
7694
7695         int p_type;
7696         link *type = operandType(right);
7697
7698         /* pointer to generic pointer */
7699         if (IS_GENPTR(ctype)) {
7700             char *l = zero;
7701             
7702             if (IS_PTR(type)) 
7703             {
7704                 p_type = DCL_TYPE(type);
7705             }
7706             else 
7707             {
7708 #if OLD_CAST_BEHAVIOR
7709                 /* KV: we are converting a non-pointer type to
7710                  * a generic pointer. This (ifdef'd out) code
7711                  * says that the resulting generic pointer 
7712                  * should have the same class as the storage
7713                  * location of the non-pointer variable.
7714                  * 
7715                  * For example, converting an int (which happens
7716                  * to be stored in DATA space) to a pointer results
7717                  * in a DATA generic pointer; if the original int
7718                  * in XDATA space, so will be the resulting pointer.
7719                  *
7720                  * I don't like that behavior, and thus this change:
7721                  * all such conversions will be forced to XDATA and
7722                  * throw a warning. If you want some non-XDATA
7723                  * type, or you want to suppress the warning, you
7724                  * must go through an intermediate cast, like so:
7725                  *
7726                  * char _generic *gp = (char _xdata *)(intVar);
7727                  */
7728                 link *etype = getSpec(type);             
7729
7730                 /* we have to go by the storage class */
7731                 if (SPEC_OCLS(etype) != generic)
7732                 {
7733                     p_type = PTR_TYPE(SPEC_OCLS(etype));
7734                 }
7735                 else
7736 #endif          
7737                 {
7738                     /* Converting unknown class (i.e. register variable)
7739                      * to generic pointer. This is not good, but
7740                      * we'll make a guess (and throw a warning).
7741                      */
7742                     p_type = FPOINTER;
7743                     werror(W_INT_TO_GEN_PTR_CAST);           
7744                 }
7745             }
7746                 
7747             /* the first two bytes are known */
7748             size = GPTRSIZE - 1; 
7749             offset = 0 ;
7750             while (size--) {
7751                 aopPut(AOP(result),
7752                        aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7753                        offset);
7754                 offset++;
7755             }
7756             
7757             /* the last byte depending on type */
7758             switch (p_type) {
7759             case IPOINTER:
7760             case POINTER:
7761                 l = zero;
7762                 break;
7763             case FPOINTER:
7764                 l = one;
7765                 break;
7766             case CPOINTER:
7767                 l = "#0x02";
7768                 break;                          
7769             case PPOINTER:
7770                 l = "#0x03";
7771                 break;
7772                 
7773             default:
7774                 /* this should never happen */
7775                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7776                        "got unknown pointer type");
7777                 exit(1);
7778             }
7779             aopPut(AOP(result),l, GPTRSIZE - 1);            
7780             goto release ;
7781         }
7782         
7783         /* just copy the pointers */
7784         size = AOP_SIZE(result);
7785         offset = 0 ;
7786         while (size--) {
7787             aopPut(AOP(result),
7788                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7789                    offset);
7790             offset++;
7791         }
7792         goto release ;
7793     }
7794     
7795     /* so we now know that the size of destination is greater
7796     than the size of the source */
7797     /* we move to result for the size of source */
7798     size = AOP_SIZE(right);
7799     offset = 0 ;
7800     while (size--) {
7801         aopPut(AOP(result),
7802                aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7803                offset);
7804         offset++;
7805     }
7806
7807     /* now depending on the sign of the source && destination */
7808     size = AOP_SIZE(result) - AOP_SIZE(right);
7809     /* if unsigned or not an integral type */
7810     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7811         while (size--)
7812             aopPut(AOP(result),zero,offset++);
7813     } else {
7814         /* we need to extend the sign :{ */
7815         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7816                          FALSE,FALSE,TRUE);
7817         MOVA(l);
7818         emitcode("rlc","a");
7819         emitcode("subb","a,acc");
7820         while (size--)
7821             aopPut(AOP(result),"a",offset++);   
7822     }
7823
7824     /* we are done hurray !!!! */
7825
7826 release:
7827     freeAsmop(right,NULL,ic,TRUE);
7828     freeAsmop(result,NULL,ic,TRUE);
7829
7830 }
7831
7832 /*-----------------------------------------------------------------*/
7833 /* genDjnz - generate decrement & jump if not zero instrucion      */
7834 /*-----------------------------------------------------------------*/
7835 static int genDjnz (iCode *ic, iCode *ifx)
7836 {
7837     symbol *lbl, *lbl1;
7838     if (!ifx)
7839         return 0;
7840     
7841     /* if the if condition has a false label
7842        then we cannot save */
7843     if (IC_FALSE(ifx))
7844         return 0;
7845
7846     /* if the minus is not of the form 
7847        a = a - 1 */
7848     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7849         !IS_OP_LITERAL(IC_RIGHT(ic)))
7850         return 0;
7851
7852     if (operandLitValue(IC_RIGHT(ic)) != 1)
7853         return 0;
7854
7855     /* if the size of this greater than one then no
7856        saving */
7857     if (getSize(operandType(IC_RESULT(ic))) > 1)
7858         return 0;
7859
7860     /* otherwise we can save BIG */
7861     lbl = newiTempLabel(NULL);
7862     lbl1= newiTempLabel(NULL);
7863
7864     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7865     
7866     if (IS_AOP_PREG(IC_RESULT(ic))) {
7867         emitcode("dec","%s",
7868                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7869         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7870         emitcode("jnz","%05d$",lbl->key+100);
7871     } else {    
7872         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
7873                   lbl->key+100);
7874     }
7875     emitcode ("sjmp","%05d$",lbl1->key+100);
7876     emitcode ("","%05d$:",lbl->key+100);
7877     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7878     emitcode ("","%05d$:",lbl1->key+100);
7879     
7880     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7881     ifx->generated = 1;
7882     return 1;
7883 }
7884
7885 /*-----------------------------------------------------------------*/
7886 /* genReceive - generate code for a receive iCode                  */
7887 /*-----------------------------------------------------------------*/
7888 static void genReceive (iCode *ic)
7889 {    
7890
7891     D(emitcode(";", "genReceive "););
7892
7893     if (isOperandInFarSpace(IC_RESULT(ic)) && 
7894         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7895           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7896         int size = getSize(operandType(IC_RESULT(ic)));
7897         int offset =  fReturnSize_390 - size;
7898         while (size--) {
7899             emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7900                                     fReturn[fReturnSize_390 - offset - 1] : "acc"));
7901             offset++;
7902         }
7903         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7904         size = AOP_SIZE(IC_RESULT(ic));
7905         offset = 0;
7906         while (size--) {
7907             emitcode ("pop","acc");
7908             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7909         }
7910         
7911     } else {
7912         _G.accInUse++;
7913         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);  
7914         _G.accInUse--;
7915         assignResultValue(IC_RESULT(ic));       
7916     }
7917
7918     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7919 }
7920
7921 /*-----------------------------------------------------------------*/
7922 /* gen390Code - generate code for 8051 based controllers            */
7923 /*-----------------------------------------------------------------*/
7924 void gen390Code (iCode *lic)
7925 {
7926     iCode *ic;
7927     int cln = 0;
7928
7929     lineHead = lineCurr = NULL;
7930
7931     /* print the allocation information */
7932     if (allocInfo)
7933         printAllocInfo( currFunc, codeOutFile);
7934     /* if debug information required */
7935 /*     if (options.debug && currFunc) { */
7936     if (currFunc) {
7937         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7938         _G.debugLine = 1;
7939         if (IS_STATIC(currFunc->etype))
7940             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
7941         else
7942             emitcode("","G$%s$0$0 ==.",currFunc->name);
7943         _G.debugLine = 0;
7944     }
7945     /* stack pointer name */
7946     if (options.useXstack)
7947         spname = "_spx";
7948     else
7949         spname = "sp";
7950     
7951  
7952     for (ic = lic ; ic ; ic = ic->next ) {
7953         
7954         if ( cln != ic->lineno ) {
7955             if ( options.debug ) {
7956                 _G.debugLine = 1;
7957                 emitcode("","C$%s$%d$%d$%d ==.",
7958                          ic->filename,ic->lineno,
7959                          ic->level,ic->block);
7960                 _G.debugLine = 0;
7961             }
7962             emitcode(";","%s %d",ic->filename,ic->lineno);
7963             cln = ic->lineno ;
7964         }
7965         /* if the result is marked as
7966            spilt and rematerializable or code for
7967            this has already been generated then
7968            do nothing */
7969         if (resultRemat(ic) || ic->generated ) 
7970             continue ;
7971         
7972         /* depending on the operation */
7973         switch (ic->op) {
7974         case '!' :
7975             genNot(ic);
7976             break;
7977             
7978         case '~' :
7979             genCpl(ic);
7980             break;
7981             
7982         case UNARYMINUS:
7983             genUminus (ic);
7984             break;
7985             
7986         case IPUSH:
7987             genIpush (ic);
7988             break;
7989             
7990         case IPOP:
7991             /* IPOP happens only when trying to restore a 
7992                spilt live range, if there is an ifx statement
7993                following this pop then the if statement might
7994                be using some of the registers being popped which
7995                would destory the contents of the register so
7996                we need to check for this condition and handle it */
7997             if (ic->next            && 
7998                 ic->next->op == IFX &&
7999                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
8000                 genIfx (ic->next,ic);
8001             else
8002                 genIpop (ic);
8003             break; 
8004             
8005         case CALL:
8006             genCall (ic);
8007             break;
8008             
8009         case PCALL:
8010             genPcall (ic);
8011             break;
8012             
8013         case FUNCTION:
8014             genFunction (ic);
8015             break;
8016             
8017         case ENDFUNCTION:
8018             genEndFunction (ic);
8019             break;
8020             
8021         case RETURN:
8022             genRet (ic);
8023             break;
8024             
8025         case LABEL:
8026             genLabel (ic);
8027             break;
8028             
8029         case GOTO:
8030             genGoto (ic);
8031             break;
8032             
8033         case '+' :
8034             genPlus (ic) ;
8035             break;
8036             
8037         case '-' :
8038             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8039                 genMinus (ic);
8040             break;
8041             
8042         case '*' :
8043             genMult (ic);
8044             break;
8045             
8046         case '/' :
8047             genDiv (ic) ;
8048             break;
8049             
8050         case '%' :
8051             genMod (ic);
8052             break;
8053             
8054         case '>' :
8055             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
8056             break;
8057             
8058         case '<' :
8059             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8060             break;
8061             
8062         case LE_OP:
8063         case GE_OP:
8064         case NE_OP:
8065             
8066             /* note these two are xlated by algebraic equivalence
8067                during parsing SDCC.y */
8068             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8069                    "got '>=' or '<=' shouldn't have come here");
8070             break;      
8071             
8072         case EQ_OP:
8073             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8074             break;          
8075             
8076         case AND_OP:
8077             genAndOp (ic);
8078             break;
8079             
8080         case OR_OP:
8081             genOrOp (ic);
8082             break;
8083             
8084         case '^' :
8085             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8086             break;
8087             
8088         case '|' :
8089                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8090             break;
8091             
8092         case BITWISEAND:
8093             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8094             break;
8095             
8096         case INLINEASM:
8097             genInline (ic);
8098             break;
8099             
8100         case RRC:
8101             genRRC (ic);
8102             break;
8103             
8104         case RLC:
8105             genRLC (ic);
8106             break;
8107             
8108         case GETHBIT:
8109             genGetHbit (ic);
8110             break;
8111             
8112         case LEFT_OP:
8113             genLeftShift (ic);
8114             break;
8115             
8116         case RIGHT_OP:
8117             genRightShift (ic);
8118             break;
8119             
8120         case GET_VALUE_AT_ADDRESS:
8121             genPointerGet(ic);
8122             break;
8123             
8124         case '=' :
8125             if (POINTER_SET(ic))
8126                 genPointerSet(ic);
8127             else
8128                 genAssign(ic);
8129             break;
8130             
8131         case IFX:
8132             genIfx (ic,NULL);
8133             break;
8134             
8135         case ADDRESS_OF:
8136             genAddrOf (ic);
8137             break;
8138             
8139         case JUMPTABLE:
8140             genJumpTab (ic);
8141             break;
8142             
8143         case CAST:
8144             genCast (ic);
8145             break;
8146             
8147         case RECEIVE:
8148             genReceive(ic);
8149             break;
8150             
8151         case SEND:
8152             addSet(&_G.sendSet,ic);
8153             break;
8154
8155         default :
8156             ic = ic;
8157             /*      piCode(ic,stdout); */
8158             
8159         }
8160     }
8161     
8162
8163     /* now we are ready to call the 
8164        peep hole optimizer */
8165     if (!options.nopeep)
8166         peepHole (&lineHead);
8167
8168     /* now do the actual printing */
8169     printLine (lineHead,codeOutFile);    
8170     return;
8171 }