make integer -> generic pointer casts default to XDATA and throw a awrning
[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(0);
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(0);
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(0);
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(0);
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(0);    
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         while(size--)
3149         {
3150             emitcode("pop", "acc");
3151             aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3152         }
3153     }
3154
3155     adjustArithmeticResult(ic);
3156         
3157 release:
3158     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3159     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3160     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3161 }
3162
3163
3164 /*-----------------------------------------------------------------*/
3165 /* genMultbits :- multiplication of bits                           */
3166 /*-----------------------------------------------------------------*/
3167 static void genMultbits (operand *left, 
3168                          operand *right, 
3169                          operand *result)
3170 {
3171     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3172     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3173     outBitC(result);
3174 }
3175
3176
3177 /*-----------------------------------------------------------------*/
3178 /* genMultOneByte : 8 bit multiplication & division                */
3179 /*-----------------------------------------------------------------*/
3180 static void genMultOneByte (operand *left,
3181                             operand *right,
3182                             operand *result)
3183 {
3184     link *opetype = operandType(result);
3185     char *l ;
3186     symbol *lbl ;
3187     int size,offset;
3188
3189     /* (if two literals, the value is computed before) */
3190     /* if one literal, literal on the right */
3191     if (AOP_TYPE(left) == AOP_LIT){
3192         operand *t = right;
3193         right = left;
3194         left = t;
3195     }
3196
3197     size = AOP_SIZE(result);
3198     /* signed or unsigned */
3199     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3200     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3201     MOVA(l);       
3202     emitcode("mul","ab");
3203     /* if result size = 1, mul signed = mul unsigned */
3204     aopPut(AOP(result),"a",0);
3205     if (size > 1){
3206         if (SPEC_USIGN(opetype)){
3207             aopPut(AOP(result),"b",1);
3208             if (size > 2)
3209                 /* for filling the MSBs */
3210                 emitcode("clr","a");
3211         }
3212         else{
3213             emitcode("mov","a,b");
3214
3215             /* adjust the MSB if left or right neg */
3216
3217             /* if one literal */
3218             if (AOP_TYPE(right) == AOP_LIT){
3219                 /* AND literal negative */
3220                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3221                     /* adjust MSB (c==0 after mul) */
3222                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3223                 }
3224             }
3225             else{
3226                 lbl = newiTempLabel(NULL);
3227                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3228                 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3229                 emitcode("","%05d$:",(lbl->key+100));
3230                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3231                 lbl = newiTempLabel(NULL);      
3232                 emitcode("jc","%05d$",(lbl->key+100));          
3233                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3234                 emitcode("","%05d$:",(lbl->key+100));
3235             }
3236
3237             lbl = newiTempLabel(NULL);
3238             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3239             emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3240             emitcode("","%05d$:",(lbl->key+100));
3241             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3242             lbl = newiTempLabel(NULL);      
3243             emitcode("jc","%05d$",(lbl->key+100));          
3244             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3245             emitcode("","%05d$:",(lbl->key+100));
3246
3247             aopPut(AOP(result),"a",1);
3248             if(size > 2){
3249                 /* get the sign */
3250                 emitcode("rlc","a");
3251                 emitcode("subb","a,acc");
3252             }
3253         }
3254         size -= 2;   
3255         offset = 2;
3256         if (size > 0)
3257             while (size--)
3258                 aopPut(AOP(result),"a",offset++);
3259     }
3260 }
3261
3262 /*-----------------------------------------------------------------*/
3263 /* genMult - generates code for multiplication                     */
3264 /*-----------------------------------------------------------------*/
3265 static void genMult (iCode *ic)
3266 {
3267     operand *left = IC_LEFT(ic);
3268     operand *right = IC_RIGHT(ic);
3269     operand *result= IC_RESULT(ic);   
3270
3271     D(emitcode(";", "genMult "););
3272
3273     /* assign the amsops */
3274     AOP_OP_3(ic);
3275 #if 0
3276     aopOp (left,ic,FALSE, FALSE);
3277     aopOp (right,ic,FALSE, TRUE);
3278     aopOp (result,ic,TRUE, FALSE);
3279 #endif
3280
3281     /* special cases first */
3282     /* both are bits */
3283     if (AOP_TYPE(left) == AOP_CRY &&
3284         AOP_TYPE(right)== AOP_CRY) {
3285         genMultbits(left,right,result);
3286         goto release ;
3287     }
3288
3289     /* if both are of size == 1 */
3290     if (AOP_SIZE(left) == 1 &&
3291         AOP_SIZE(right) == 1 ) {
3292         genMultOneByte(left,right,result);
3293         goto release ;
3294     }
3295
3296     /* should have been converted to function call */       
3297     assert(1) ;
3298
3299 release :
3300     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3301     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3302     freeAsmop(result,NULL,ic,TRUE); 
3303 }
3304
3305 /*-----------------------------------------------------------------*/
3306 /* genDivbits :- division of bits                                  */
3307 /*-----------------------------------------------------------------*/
3308 static void genDivbits (operand *left, 
3309                         operand *right, 
3310                         operand *result)
3311 {
3312
3313     char *l;
3314
3315     /* the result must be bit */
3316     LOAD_AB_FOR_DIV(left, right, l);
3317     emitcode("div","ab");
3318     emitcode("rrc","a");
3319     aopPut(AOP(result),"c",0);
3320 }
3321
3322 /*-----------------------------------------------------------------*/
3323 /* genDivOneByte : 8 bit division                                  */
3324 /*-----------------------------------------------------------------*/
3325 static void genDivOneByte (operand *left,
3326                            operand *right,
3327                            operand *result)
3328 {
3329     link *opetype = operandType(result);
3330     char *l ;
3331     symbol *lbl ;
3332     int size,offset;
3333
3334     size = AOP_SIZE(result) - 1;
3335     offset = 1;
3336     /* signed or unsigned */
3337     if (SPEC_USIGN(opetype)) {
3338         /* unsigned is easy */
3339         LOAD_AB_FOR_DIV(left, right, l);
3340         emitcode("div","ab");
3341         aopPut(AOP(result),"a",0);
3342         while (size--)
3343             aopPut(AOP(result),zero,offset++);
3344         return ;
3345     }
3346
3347     /* signed is a little bit more difficult */
3348
3349     /* save the signs of the operands */
3350     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);    
3351     MOVA(l);    
3352     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3353     emitcode("push","acc"); /* save it on the stack */
3354
3355     /* now sign adjust for both left & right */
3356     l =  aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3357     MOVA(l);       
3358     lbl = newiTempLabel(NULL);
3359     emitcode("jnb","acc.7,%05d$",(lbl->key+100));   
3360     emitcode("cpl","a");   
3361     emitcode("inc","a");
3362     emitcode("","%05d$:",(lbl->key+100));
3363     emitcode("mov","b,a");
3364
3365     /* sign adjust left side */
3366     l =  aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3367     MOVA(l);
3368
3369     lbl = newiTempLabel(NULL);
3370     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3371     emitcode("cpl","a");
3372     emitcode("inc","a");
3373     emitcode("","%05d$:",(lbl->key+100));
3374
3375     /* now the division */
3376     emitcode("nop", "; workaround for DS80C390 div bug.");
3377     emitcode("div","ab");
3378     /* we are interested in the lower order
3379     only */
3380     emitcode("mov","b,a");
3381     lbl = newiTempLabel(NULL);
3382     emitcode("pop","acc");   
3383     /* if there was an over flow we don't 
3384     adjust the sign of the result */
3385     emitcode("jb","ov,%05d$",(lbl->key+100));
3386     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3387     CLRC;
3388     emitcode("clr","a");
3389     emitcode("subb","a,b");
3390     emitcode("mov","b,a");
3391     emitcode("","%05d$:",(lbl->key+100));
3392
3393     /* now we are done */
3394     aopPut(AOP(result),"b",0);
3395     if(size > 0){
3396         emitcode("mov","c,b.7");
3397         emitcode("subb","a,acc");   
3398     }
3399     while (size--)
3400         aopPut(AOP(result),"a",offset++);
3401
3402 }
3403
3404 /*-----------------------------------------------------------------*/
3405 /* genDiv - generates code for division                            */
3406 /*-----------------------------------------------------------------*/
3407 static void genDiv (iCode *ic)
3408 {
3409     operand *left = IC_LEFT(ic);
3410     operand *right = IC_RIGHT(ic);
3411     operand *result= IC_RESULT(ic);   
3412
3413     D(emitcode(";", "genDiv "););
3414
3415     /* assign the amsops */
3416     AOP_OP_3(ic);
3417 #if 0
3418     aopOp (left,ic,FALSE, FALSE);
3419     aopOp (right,ic,FALSE, TRUE);
3420     aopOp (result,ic,TRUE, FALSE);
3421 #endif
3422
3423     /* special cases first */
3424     /* both are bits */
3425     if (AOP_TYPE(left) == AOP_CRY &&
3426         AOP_TYPE(right)== AOP_CRY) {
3427         genDivbits(left,right,result);
3428         goto release ;
3429     }
3430
3431     /* if both are of size == 1 */
3432     if (AOP_SIZE(left) == 1 &&
3433         AOP_SIZE(right) == 1 ) {
3434         genDivOneByte(left,right,result);
3435         goto release ;
3436     }
3437
3438     /* should have been converted to function call */
3439     assert(1);
3440 release :
3441     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3442     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3443     freeAsmop(result,NULL,ic,TRUE); 
3444 }
3445
3446 /*-----------------------------------------------------------------*/
3447 /* genModbits :- modulus of bits                                   */
3448 /*-----------------------------------------------------------------*/
3449 static void genModbits (operand *left, 
3450                         operand *right, 
3451                         operand *result)
3452 {
3453
3454     char *l;
3455
3456     /* the result must be bit */    
3457     LOAD_AB_FOR_DIV(left, right, l);
3458     emitcode("div","ab");
3459     emitcode("mov","a,b");
3460     emitcode("rrc","a");
3461     aopPut(AOP(result),"c",0);
3462 }
3463
3464 /*-----------------------------------------------------------------*/
3465 /* genModOneByte : 8 bit modulus                                   */
3466 /*-----------------------------------------------------------------*/
3467 static void genModOneByte (operand *left,
3468                            operand *right,
3469                            operand *result)
3470 {
3471     link *opetype = operandType(result);
3472     char *l ;
3473     symbol *lbl ;
3474
3475     /* signed or unsigned */
3476     if (SPEC_USIGN(opetype)) {
3477         /* unsigned is easy */
3478         LOAD_AB_FOR_DIV(left, right, l);
3479         emitcode("div","ab");
3480         aopPut(AOP(result),"b",0);
3481         return ;
3482     }
3483
3484     /* signed is a little bit more difficult */
3485
3486     /* save the signs of the operands */
3487     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3488     MOVA(l);
3489
3490     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3491     emitcode("push","acc"); /* save it on the stack */
3492
3493     /* now sign adjust for both left & right */
3494     l =  aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3495     MOVA(l);
3496
3497     lbl = newiTempLabel(NULL);
3498     emitcode("jnb","acc.7,%05d$",(lbl->key+100));  
3499     emitcode("cpl","a");   
3500     emitcode("inc","a");
3501     emitcode("","%05d$:",(lbl->key+100));
3502     emitcode("mov","b,a"); 
3503
3504     /* sign adjust left side */
3505     l =  aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3506     MOVA(l);
3507
3508     lbl = newiTempLabel(NULL);
3509     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3510     emitcode("cpl","a");   
3511     emitcode("inc","a");
3512     emitcode("","%05d$:",(lbl->key+100));
3513
3514     /* now the multiplication */
3515     emitcode("nop", "; workaround for DS80C390 div bug.");
3516     emitcode("div","ab");
3517     /* we are interested in the lower order
3518     only */
3519     lbl = newiTempLabel(NULL);
3520     emitcode("pop","acc");   
3521     /* if there was an over flow we don't 
3522     adjust the sign of the result */
3523     emitcode("jb","ov,%05d$",(lbl->key+100));
3524     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3525     CLRC ;
3526     emitcode("clr","a");
3527     emitcode("subb","a,b");
3528     emitcode("mov","b,a");
3529     emitcode("","%05d$:",(lbl->key+100));
3530
3531     /* now we are done */
3532     aopPut(AOP(result),"b",0);
3533
3534 }
3535
3536 /*-----------------------------------------------------------------*/
3537 /* genMod - generates code for division                            */
3538 /*-----------------------------------------------------------------*/
3539 static void genMod (iCode *ic)
3540 {
3541     operand *left = IC_LEFT(ic);
3542     operand *right = IC_RIGHT(ic);
3543     operand *result= IC_RESULT(ic);  
3544
3545     D(emitcode(";", "genMod "););
3546
3547     /* assign the amsops */
3548     AOP_OP_3(ic);
3549 #if 0
3550     aopOp (left,ic,FALSE, FALSE);
3551     aopOp (right,ic,FALSE, TRUE);
3552     aopOp (result,ic,TRUE, FALSE);
3553 #endif
3554
3555     /* special cases first */
3556     /* both are bits */
3557     if (AOP_TYPE(left) == AOP_CRY &&
3558         AOP_TYPE(right)== AOP_CRY) {
3559         genModbits(left,right,result);
3560         goto release ;
3561     }
3562
3563     /* if both are of size == 1 */
3564     if (AOP_SIZE(left) == 1 &&
3565         AOP_SIZE(right) == 1 ) {
3566         genModOneByte(left,right,result);
3567         goto release ;
3568     }
3569
3570     /* should have been converted to function call */
3571     assert(1);
3572
3573 release :
3574     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3575     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3576     freeAsmop(result,NULL,ic,TRUE); 
3577 }
3578
3579 /*-----------------------------------------------------------------*/
3580 /* genIfxJump :- will create a jump depending on the ifx           */
3581 /*-----------------------------------------------------------------*/
3582 static void genIfxJump (iCode *ic, char *jval)
3583 {
3584     symbol *jlbl ;
3585     symbol *tlbl = newiTempLabel(NULL);
3586     char *inst;
3587
3588     D(emitcode(";", "genIfxJump "););
3589
3590     /* if true label then we jump if condition
3591     supplied is true */
3592     if ( IC_TRUE(ic) ) {
3593         jlbl = IC_TRUE(ic);
3594         inst = ((strcmp(jval,"a") == 0 ? "jz" :
3595                  (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3596     }
3597     else {
3598         /* false label is present */
3599         jlbl = IC_FALSE(ic) ;
3600         inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3601                  (strcmp(jval,"c") == 0 ? "jc" : "jb" )));              
3602     }
3603     if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0) 
3604         emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3605     else
3606         emitcode(inst,"%05d$",tlbl->key+100);
3607     emitcode("ljmp","%05d$",jlbl->key+100);
3608     emitcode("","%05d$:",tlbl->key+100);                
3609
3610     /* mark the icode as generated */
3611     ic->generated = 1;
3612 }
3613
3614 /*-----------------------------------------------------------------*/
3615 /* genCmp :- greater or less than comparison                       */
3616 /*-----------------------------------------------------------------*/
3617 static void genCmp (operand *left,operand *right,
3618                     operand *result, iCode *ifx, int sign)
3619 {
3620     int size, offset = 0 ;
3621     unsigned long lit = 0L;
3622     bool swappedOps = FALSE;
3623
3624     D(emitcode(";", "genCmp"););
3625
3626 #if 0
3627     /* If left if lit and right isn't, swap 'em. */
3628     if (AOP_TYPE(left) == AOP_LIT &&
3629         AOP_TYPE(right) != AOP_LIT)
3630     {
3631         operand *tmp = left;
3632         left = right;
3633         right = tmp;
3634         D(emitcode(";", "kevin literal hack"););
3635         swappedOps = !swappedOps;
3636     }
3637
3638     if (AOP_NEEDSACC(right))
3639     {
3640         if (AOP_NEEDSACC(left))
3641         {
3642             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3643                    "both CMP operands need ACC!");
3644             exit(-1);
3645         }
3646         else
3647         {
3648             operand *tmp = left;
3649             left = right;
3650             right = tmp;
3651             D(emitcode(";", "kevin ACC hack"););
3652             swappedOps = !swappedOps;
3653         }
3654     }
3655 #endif
3656
3657     /* if left & right are bit variables */
3658     if (AOP_TYPE(left) == AOP_CRY &&
3659         AOP_TYPE(right) == AOP_CRY ) {
3660         emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3661         emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3662     } else {
3663         /* subtract right from left if at the
3664         end the carry flag is set then we know that
3665         left is greater than right */
3666         size = max(AOP_SIZE(left),AOP_SIZE(right));
3667
3668         /* if unsigned char cmp with lit, do cjne left,#right,zz */
3669         if((size == 1) && !sign &&
3670            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3671             symbol *lbl  = newiTempLabel(NULL);
3672             emitcode("cjne","%s,%s,%05d$",
3673                      aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3674                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3675                      lbl->key+100);
3676             emitcode("","%05d$:",lbl->key+100);
3677         } else {
3678             if(AOP_TYPE(right) == AOP_LIT){
3679                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3680                 /* optimize if(x < 0) or if(x >= 0) */
3681                 if(lit == 0L){
3682                     if(!sign){
3683                         CLRC;
3684                     }
3685                     else{
3686                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3687                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3688                             genIfxJump (ifx,"acc.7");
3689                             return;
3690                         }
3691                         else    
3692                             emitcode("rlc","a");
3693                     }
3694                     goto release;
3695                 }
3696             }
3697             CLRC;
3698             while (size--)
3699             {
3700                 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3701                 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3702                 emitcode(";", "genCmp #2");
3703                 if (sign && (size == 0))
3704                 {
3705                     emitcode(";", "genCmp #3");
3706                     emitcode("xrl","a,#0x80");
3707                     if (AOP_TYPE(right) == AOP_LIT)
3708                     {
3709                         unsigned long lit = (unsigned long)
3710                             floatFromVal(AOP(right)->aopu.aop_lit);
3711                         emitcode(";", "genCmp #3.1");
3712                         emitcode("subb","a,#0x%02x",
3713                             0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3714                     }
3715                     else
3716                     {
3717                         emitcode(";", "genCmp #3.2");
3718                         if (AOP_NEEDSACC(right))
3719                         {
3720                             emitcode("push", "acc");
3721                         }
3722                         emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3723                                   FALSE,FALSE,FALSE));
3724                         emitcode("xrl","b,#0x80");
3725                         if (AOP_NEEDSACC(right))
3726                         {
3727                             emitcode("pop", "acc");
3728                         }
3729                         emitcode("subb","a,b");
3730                     }
3731                 }
3732                 else
3733                 {
3734                     const char *s;
3735
3736                     emitcode(";", "genCmp #4");
3737                     if (AOP_NEEDSACC(right))
3738                     {
3739                         /* Yuck!! */
3740                         emitcode(";", "genCmp #4.1");
3741                         emitcode("xch", "a, b");
3742                         MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3743                         emitcode("xch", "a, b");
3744                         s = "b";
3745                     }
3746                     else
3747                     {
3748                         emitcode(";", "genCmp #4.2");
3749                         s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3750                     }
3751
3752                     emitcode("subb","a,%s",s);
3753                 }
3754             }
3755         }
3756     }
3757
3758 release:
3759     if (swappedOps)
3760     {
3761         D(emitcode(";","kevHack: flip carry."););
3762         emitcode("cpl", "c");
3763     }
3764
3765     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3766         outBitC(result);
3767     } else {
3768         /* if the result is used in the next
3769         ifx conditional branch then generate
3770         code a little differently */
3771         if (ifx )
3772             genIfxJump (ifx,"c");
3773         else
3774             outBitC(result);
3775         /* leave the result in acc */
3776     }
3777 }
3778
3779 /*-----------------------------------------------------------------*/
3780 /* genCmpGt :- greater than comparison                             */
3781 /*-----------------------------------------------------------------*/
3782 static void genCmpGt (iCode *ic, iCode *ifx)
3783 {
3784     operand *left, *right, *result;
3785     link *letype , *retype;
3786     int sign ;
3787
3788     D(emitcode(";", "genCmpGt "););
3789
3790     left = IC_LEFT(ic);
3791     right= IC_RIGHT(ic);
3792     result = IC_RESULT(ic);
3793
3794     letype = getSpec(operandType(left));
3795     retype =getSpec(operandType(right));
3796     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3797     /* assign the amsops */
3798     AOP_OP_3(ic);
3799 #if 0
3800     aopOp (left,ic,FALSE, TRUE);
3801     aopOp (right,ic,FALSE, FALSE);
3802     aopOp (result,ic,TRUE, FALSE);
3803 #endif
3804
3805     genCmp(right, left, result, ifx, sign);
3806
3807     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3808     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3809     freeAsmop(result,NULL,ic,TRUE); 
3810 }
3811
3812 /*-----------------------------------------------------------------*/
3813 /* genCmpLt - less than comparisons                                */
3814 /*-----------------------------------------------------------------*/
3815 static void genCmpLt (iCode *ic, iCode *ifx)
3816 {
3817     operand *left, *right, *result;
3818     link *letype , *retype;
3819     int sign ;
3820
3821     D(emitcode(";", "genCmpLt "););
3822
3823     left = IC_LEFT(ic);
3824     right= IC_RIGHT(ic);
3825     result = IC_RESULT(ic);
3826
3827     letype = getSpec(operandType(left));
3828     retype =getSpec(operandType(right));
3829     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3830
3831     /* assign the amsops */
3832     AOP_OP_3(ic);
3833 #if 0
3834     aopOp (left,ic,FALSE, FALSE);
3835     aopOp (right,ic,FALSE, TRUE);
3836     aopOp (result,ic,TRUE, FALSE);
3837 #endif
3838
3839     genCmp(left, right, result, ifx, sign);
3840
3841     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3842     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3843     freeAsmop(result,NULL,ic,TRUE); 
3844 }
3845
3846 /*-----------------------------------------------------------------*/
3847 /* gencjneshort - compare and jump if not equal                    */
3848 /*-----------------------------------------------------------------*/
3849 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3850 {
3851     int size = max(AOP_SIZE(left),AOP_SIZE(right));
3852     int offset = 0;
3853     unsigned long lit = 0L;
3854
3855     D(emitcode(";", "gencjneshort"););
3856
3857     /* if the left side is a literal or 
3858     if the right is in a pointer register and left 
3859     is not */
3860     if ((AOP_TYPE(left) == AOP_LIT) || 
3861         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3862         operand *t = right;
3863         right = left;
3864         left = t;
3865     }
3866     if(AOP_TYPE(right) == AOP_LIT)
3867         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3868
3869     /* if the right side is a literal then anything goes */
3870     if (AOP_TYPE(right) == AOP_LIT &&
3871         AOP_TYPE(left) != AOP_DIR ) {
3872         while (size--) {
3873             char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
3874             MOVA(l);
3875             emitcode("cjne","a,%s,%05d$",
3876                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3877                      lbl->key+100);
3878             offset++;
3879         }
3880     }
3881
3882     /* if the right side is in a register or in direct space or
3883     if the left is a pointer register & right is not */    
3884     else if (AOP_TYPE(right) == AOP_REG ||
3885              AOP_TYPE(right) == AOP_DIR || 
3886              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3887              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3888         while (size--) {
3889             MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3890             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3891                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3892                 emitcode("jnz","%05d$",lbl->key+100);
3893             else
3894                 emitcode("cjne","a,%s,%05d$",
3895                          aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
3896                          lbl->key+100);
3897             offset++;
3898         }
3899     } else {
3900         /* right is a pointer reg need both a & b */
3901         while(size--) {
3902             char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
3903             if(strcmp(l,"b"))
3904                 emitcode("mov","b,%s",l);
3905             MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
3906             emitcode("cjne","a,b,%05d$",lbl->key+100);    
3907             offset++;
3908         }
3909     }
3910 }
3911
3912 /*-----------------------------------------------------------------*/
3913 /* gencjne - compare and jump if not equal                         */
3914 /*-----------------------------------------------------------------*/
3915 static void gencjne(operand *left, operand *right, symbol *lbl)
3916 {
3917     symbol *tlbl  = newiTempLabel(NULL);
3918
3919     D(emitcode(";", "gencjne"););
3920
3921     gencjneshort(left, right, lbl);
3922
3923     emitcode("mov","a,%s",one);
3924     emitcode("sjmp","%05d$",tlbl->key+100);
3925     emitcode("","%05d$:",lbl->key+100);
3926     emitcode("clr","a");
3927     emitcode("","%05d$:",tlbl->key+100);
3928 }
3929
3930 /*-----------------------------------------------------------------*/
3931 /* genCmpEq - generates code for equal to                          */
3932 /*-----------------------------------------------------------------*/
3933 static void genCmpEq (iCode *ic, iCode *ifx)
3934 {
3935     operand *left, *right, *result;
3936
3937     D(emitcode(";", "genCmpEq "););
3938
3939     AOP_OP_3(ic);
3940     AOP_SET_LOCALS(ic);
3941 #if 0
3942     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
3943     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3944     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3945 #endif
3946
3947     /* if literal, literal on the right or 
3948     if the right is in a pointer register and left 
3949     is not */
3950     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
3951         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3952         operand *t = IC_RIGHT(ic);
3953         IC_RIGHT(ic) = IC_LEFT(ic);
3954         IC_LEFT(ic) = t;
3955     }
3956
3957     if(ifx && !AOP_SIZE(result)){
3958         symbol *tlbl;
3959         /* if they are both bit variables */
3960         if (AOP_TYPE(left) == AOP_CRY &&
3961             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3962             if(AOP_TYPE(right) == AOP_LIT){
3963                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3964                 if(lit == 0L){
3965                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3966                     emitcode("cpl","c");
3967                 } else if(lit == 1L) {
3968                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3969                 } else {
3970                     emitcode("clr","c");
3971                 }
3972                 /* AOP_TYPE(right) == AOP_CRY */
3973             } else {
3974                 symbol *lbl = newiTempLabel(NULL);
3975                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3976                 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3977                 emitcode("cpl","c");
3978                 emitcode("","%05d$:",(lbl->key+100));
3979             }
3980             /* if true label then we jump if condition
3981             supplied is true */
3982             tlbl = newiTempLabel(NULL);
3983             if ( IC_TRUE(ifx) ) {
3984                 emitcode("jnc","%05d$",tlbl->key+100);
3985                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3986             } else {
3987                 emitcode("jc","%05d$",tlbl->key+100);
3988                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3989             }
3990             emitcode("","%05d$:",tlbl->key+100);                
3991         } else {
3992             tlbl = newiTempLabel(NULL);
3993             gencjneshort(left, right, tlbl);
3994             if ( IC_TRUE(ifx) ) {
3995                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3996                 emitcode("","%05d$:",tlbl->key+100);                
3997             } else {
3998                 symbol *lbl = newiTempLabel(NULL);
3999                 emitcode("sjmp","%05d$",lbl->key+100);
4000                 emitcode("","%05d$:",tlbl->key+100);                
4001                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4002                 emitcode("","%05d$:",lbl->key+100);             
4003             }
4004         }
4005         /* mark the icode as generated */
4006         ifx->generated = 1;
4007         goto release ;
4008     }
4009
4010     /* if they are both bit variables */
4011     if (AOP_TYPE(left) == AOP_CRY &&
4012         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4013         if(AOP_TYPE(right) == AOP_LIT){
4014             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4015             if(lit == 0L){
4016                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4017                 emitcode("cpl","c");
4018             } else if(lit == 1L) {
4019                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4020             } else {
4021                 emitcode("clr","c");
4022             }
4023             /* AOP_TYPE(right) == AOP_CRY */
4024         } else {
4025             symbol *lbl = newiTempLabel(NULL);
4026             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4027             emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4028             emitcode("cpl","c");
4029             emitcode("","%05d$:",(lbl->key+100));
4030         }
4031         /* c = 1 if egal */
4032         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4033             outBitC(result);
4034             goto release ;
4035         }
4036         if (ifx) {
4037             genIfxJump (ifx,"c");
4038             goto release ;
4039         }
4040         /* if the result is used in an arithmetic operation
4041         then put the result in place */
4042         outBitC(result);
4043     } else {
4044         gencjne(left,right,newiTempLabel(NULL));    
4045         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4046             aopPut(AOP(result),"a",0);
4047             goto release ;
4048         }
4049         if (ifx) {
4050             genIfxJump (ifx,"a");
4051             goto release ;
4052         }
4053         /* if the result is used in an arithmetic operation
4054         then put the result in place */
4055         if (AOP_TYPE(result) != AOP_CRY) 
4056             outAcc(result);
4057         /* leave the result in acc */
4058     }
4059
4060 release:
4061     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4062     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4063     freeAsmop(result,NULL,ic,TRUE);
4064 }
4065
4066 /*-----------------------------------------------------------------*/
4067 /* ifxForOp - returns the icode containing the ifx for operand     */
4068 /*-----------------------------------------------------------------*/
4069 static iCode *ifxForOp ( operand *op, iCode *ic )
4070 {
4071     /* if true symbol then needs to be assigned */
4072     if (IS_TRUE_SYMOP(op))
4073         return NULL ;
4074
4075     /* if this has register type condition and
4076     the next instruction is ifx with the same operand
4077     and live to of the operand is upto the ifx only then */
4078     if (ic->next &&
4079         ic->next->op == IFX &&
4080         IC_COND(ic->next)->key == op->key &&
4081         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4082         return ic->next;
4083
4084     return NULL;
4085 }
4086 /*-----------------------------------------------------------------*/
4087 /* genAndOp - for && operation                                     */
4088 /*-----------------------------------------------------------------*/
4089 static void genAndOp (iCode *ic)
4090 {
4091     operand *left,*right, *result;
4092     symbol *tlbl;
4093
4094     D(emitcode(";", "genAndOp "););
4095
4096     /* note here that && operations that are in an
4097     if statement are taken away by backPatchLabels
4098     only those used in arthmetic operations remain */
4099     AOP_OP_3(ic);
4100     AOP_SET_LOCALS(ic);
4101 #if 0
4102     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4103     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4104     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4105 #endif
4106
4107     /* if both are bit variables */
4108     if (AOP_TYPE(left) == AOP_CRY &&
4109         AOP_TYPE(right) == AOP_CRY ) {
4110         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4111         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4112         outBitC(result);
4113     } else {
4114         tlbl = newiTempLabel(NULL);
4115         toBoolean(left);    
4116         emitcode("jz","%05d$",tlbl->key+100);
4117         toBoolean(right);
4118         emitcode("","%05d$:",tlbl->key+100);
4119         outBitAcc(result);
4120     }
4121
4122     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4123     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4124     freeAsmop(result,NULL,ic,TRUE);
4125 }
4126
4127
4128 /*-----------------------------------------------------------------*/
4129 /* genOrOp - for || operation                                      */
4130 /*-----------------------------------------------------------------*/
4131 static void genOrOp (iCode *ic)
4132 {
4133     operand *left,*right, *result;
4134     symbol *tlbl;
4135
4136     D(emitcode(";", "genOrOp "););
4137
4138     /* note here that || operations that are in an
4139     if statement are taken away by backPatchLabels
4140     only those used in arthmetic operations remain */
4141     AOP_OP_3(ic);
4142     AOP_SET_LOCALS(ic);
4143 #if 0
4144     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4145     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4146     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4147 #endif
4148
4149     /* if both are bit variables */
4150     if (AOP_TYPE(left) == AOP_CRY &&
4151         AOP_TYPE(right) == AOP_CRY ) {
4152         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4153         emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4154         outBitC(result);
4155     } else {
4156         tlbl = newiTempLabel(NULL);
4157         toBoolean(left);
4158         emitcode("jnz","%05d$",tlbl->key+100);
4159         toBoolean(right);
4160         emitcode("","%05d$:",tlbl->key+100);
4161         outBitAcc(result);
4162     }
4163
4164     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4165     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4166     freeAsmop(result,NULL,ic,TRUE);            
4167 }
4168
4169 /*-----------------------------------------------------------------*/
4170 /* isLiteralBit - test if lit == 2^n                               */
4171 /*-----------------------------------------------------------------*/
4172 static int isLiteralBit(unsigned long lit)
4173 {
4174     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4175     0x100L,0x200L,0x400L,0x800L,
4176     0x1000L,0x2000L,0x4000L,0x8000L,
4177     0x10000L,0x20000L,0x40000L,0x80000L,
4178     0x100000L,0x200000L,0x400000L,0x800000L,
4179     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4180     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4181     int idx;
4182     
4183     for(idx = 0; idx < 32; idx++)
4184         if(lit == pw[idx])
4185             return idx+1;
4186     return 0;
4187 }
4188
4189 /*-----------------------------------------------------------------*/
4190 /* continueIfTrue -                                                */
4191 /*-----------------------------------------------------------------*/
4192 static void continueIfTrue (iCode *ic)
4193 {
4194     if(IC_TRUE(ic))
4195         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4196     ic->generated = 1;
4197 }
4198
4199 /*-----------------------------------------------------------------*/
4200 /* jmpIfTrue -                                                     */
4201 /*-----------------------------------------------------------------*/
4202 static void jumpIfTrue (iCode *ic)
4203 {
4204     if(!IC_TRUE(ic))
4205         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4206     ic->generated = 1;
4207 }
4208
4209 /*-----------------------------------------------------------------*/
4210 /* jmpTrueOrFalse -                                                */
4211 /*-----------------------------------------------------------------*/
4212 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4213 {
4214     // ugly but optimized by peephole
4215     if(IC_TRUE(ic)){
4216         symbol *nlbl = newiTempLabel(NULL);
4217         emitcode("sjmp","%05d$",nlbl->key+100);                 
4218         emitcode("","%05d$:",tlbl->key+100);
4219         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4220         emitcode("","%05d$:",nlbl->key+100);
4221     }
4222     else{
4223         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4224         emitcode("","%05d$:",tlbl->key+100);
4225     }
4226     ic->generated = 1;
4227 }
4228
4229 /*-----------------------------------------------------------------*/
4230 /* genAnd  - code for and                                          */
4231 /*-----------------------------------------------------------------*/
4232 static void genAnd (iCode *ic, iCode *ifx)
4233 {
4234     operand *left, *right, *result;
4235     int size, offset=0;  
4236     unsigned long lit = 0L;
4237     int bytelit = 0;
4238     char buffer[10];
4239
4240     D(emitcode(";", "genAnd "););
4241
4242     AOP_OP_3(ic);
4243     AOP_SET_LOCALS(ic);
4244 #if 0
4245     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4246     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4247     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4248 #endif
4249
4250 #ifdef DEBUG_TYPE
4251     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4252              AOP_TYPE(result),
4253              AOP_TYPE(left), AOP_TYPE(right));
4254     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4255              AOP_SIZE(result),
4256              AOP_SIZE(left), AOP_SIZE(right));
4257 #endif
4258
4259     /* if left is a literal & right is not then exchange them */
4260     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4261         AOP_NEEDSACC(left)) {
4262         operand *tmp = right ;
4263         right = left;
4264         left = tmp;
4265     }
4266
4267     /* if result = right then exchange them */
4268     if(sameRegs(AOP(result),AOP(right))){
4269         operand *tmp = right ;
4270         right = left;
4271         left = tmp;
4272     }
4273
4274     /* if right is bit then exchange them */
4275     if (AOP_TYPE(right) == AOP_CRY &&
4276         AOP_TYPE(left) != AOP_CRY){
4277         operand *tmp = right ;
4278         right = left;
4279         left = tmp;
4280     }
4281     if(AOP_TYPE(right) == AOP_LIT)
4282         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4283
4284     size = AOP_SIZE(result);
4285
4286     // if(bit & yy)
4287     // result = bit & yy;
4288     if (AOP_TYPE(left) == AOP_CRY){
4289         // c = bit & literal;
4290         if(AOP_TYPE(right) == AOP_LIT){
4291             if(lit & 1) {
4292                 if(size && sameRegs(AOP(result),AOP(left)))
4293                     // no change
4294                     goto release;
4295                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4296             } else {
4297                 // bit(result) = 0;
4298                 if(size && (AOP_TYPE(result) == AOP_CRY)){
4299                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4300                     goto release;
4301                 }
4302                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4303                     jumpIfTrue(ifx);
4304                     goto release;
4305                 }
4306                 emitcode("clr","c");
4307             }
4308         } else {
4309             if (AOP_TYPE(right) == AOP_CRY){
4310                 // c = bit & bit;
4311                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4312                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4313             } else {
4314                 // c = bit & val;
4315                 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4316                 // c = lsb
4317                 emitcode("rrc","a");
4318                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4319             }
4320         }
4321         // bit = c
4322         // val = c
4323         if(size)
4324             outBitC(result);
4325         // if(bit & ...)
4326         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4327             genIfxJump(ifx, "c");           
4328         goto release ;
4329     }
4330
4331     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4332     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4333     if((AOP_TYPE(right) == AOP_LIT) &&
4334        (AOP_TYPE(result) == AOP_CRY) &&
4335        (AOP_TYPE(left) != AOP_CRY)){
4336         int posbit = isLiteralBit(lit);
4337         /* left &  2^n */
4338         if(posbit){
4339             posbit--;
4340             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4341             // bit = left & 2^n
4342             if(size)
4343                 emitcode("mov","c,acc.%d",posbit&0x07);
4344             // if(left &  2^n)
4345             else{
4346                 if(ifx){
4347                     sprintf(buffer,"acc.%d",posbit&0x07);
4348                     genIfxJump(ifx, buffer);
4349                 }
4350                 goto release;
4351             }
4352         } else {
4353             symbol *tlbl = newiTempLabel(NULL);
4354             int sizel = AOP_SIZE(left);
4355             if(size)
4356                 emitcode("setb","c");
4357             while(sizel--){
4358                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4359                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4360                     // byte ==  2^n ?
4361                     if((posbit = isLiteralBit(bytelit)) != 0)
4362                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4363                     else{
4364                         if(bytelit != 0x0FFL)
4365                             emitcode("anl","a,%s",
4366                                      aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4367                         emitcode("jnz","%05d$",tlbl->key+100);
4368                     }
4369                 }
4370                 offset++;
4371             }
4372             // bit = left & literal
4373             if(size){
4374                 emitcode("clr","c");
4375                 emitcode("","%05d$:",tlbl->key+100);
4376             }
4377             // if(left & literal)
4378             else{
4379                 if(ifx)
4380                     jmpTrueOrFalse(ifx, tlbl);
4381                 goto release ;
4382             }
4383         }
4384         outBitC(result);
4385         goto release ;
4386     }
4387
4388     /* if left is same as result */
4389     if(sameRegs(AOP(result),AOP(left))){
4390         for(;size--; offset++) {
4391             if(AOP_TYPE(right) == AOP_LIT){
4392                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4393                     continue;
4394                 else 
4395                     if (bytelit == 0)
4396                         aopPut(AOP(result),zero,offset);
4397                     else 
4398                         if (IS_AOP_PREG(result)) {
4399                             MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4400                             emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4401                             aopPut(AOP(result),"a",offset);
4402                         } else
4403                             emitcode("anl","%s,%s",
4404                                      aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4405                                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4406             } else {
4407                 if (AOP_TYPE(left) == AOP_ACC)
4408                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4409                 else {
4410                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4411                     if (IS_AOP_PREG(result)) {
4412                         emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4413                         aopPut(AOP(result),"a",offset);
4414
4415                     } else
4416                         emitcode("anl","%s,a",
4417                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4418                 }
4419             }
4420         }
4421     } else {
4422         // left & result in different registers
4423         if(AOP_TYPE(result) == AOP_CRY){
4424             // result = bit
4425             // if(size), result in bit
4426             // if(!size && ifx), conditional oper: if(left & right)
4427             symbol *tlbl = newiTempLabel(NULL);
4428             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4429             if(size)
4430                 emitcode("setb","c");
4431             while(sizer--){
4432                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4433                 emitcode("anl","a,%s",
4434                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4435                 emitcode("jnz","%05d$",tlbl->key+100);
4436                 offset++;
4437             }
4438             if(size){
4439                 CLRC;
4440                 emitcode("","%05d$:",tlbl->key+100);
4441                 outBitC(result);
4442             } else if(ifx)
4443                 jmpTrueOrFalse(ifx, tlbl);
4444         } else {
4445             for(;(size--);offset++) {
4446                 // normal case
4447                 // result = left & right
4448                 if(AOP_TYPE(right) == AOP_LIT){
4449                     if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4450                         aopPut(AOP(result),
4451                                aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4452                                offset);
4453                         continue;
4454                     } else if(bytelit == 0){
4455                         aopPut(AOP(result),zero,offset);
4456                         continue;
4457                     }
4458                 }
4459                 // faster than result <- left, anl result,right
4460                 // and better if result is SFR
4461                 if (AOP_TYPE(left) == AOP_ACC) 
4462                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4463                 else {
4464                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4465                     emitcode("anl","a,%s",
4466                              aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4467                 }
4468                 aopPut(AOP(result),"a",offset);
4469             }
4470         }
4471     }
4472
4473 release :
4474     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4475     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4476     freeAsmop(result,NULL,ic,TRUE);     
4477 }
4478
4479 /*-----------------------------------------------------------------*/
4480 /* genOr  - code for or                                            */
4481 /*-----------------------------------------------------------------*/
4482 static void genOr (iCode *ic, iCode *ifx)
4483 {
4484     operand *left, *right, *result;
4485     int size, offset=0;
4486     unsigned long lit = 0L;
4487
4488     D(emitcode(";", "genOr "););
4489
4490     AOP_OP_3(ic);
4491     AOP_SET_LOCALS(ic);
4492     #if 0
4493     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4494     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4495     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4496     #endif
4497
4498 #ifdef DEBUG_TYPE
4499     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4500              AOP_TYPE(result),
4501              AOP_TYPE(left), AOP_TYPE(right));
4502     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4503              AOP_SIZE(result),
4504              AOP_SIZE(left), AOP_SIZE(right));
4505 #endif
4506
4507     /* if left is a literal & right is not then exchange them */
4508     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4509         AOP_NEEDSACC(left)) {
4510         operand *tmp = right ;
4511         right = left;
4512         left = tmp;
4513     }
4514
4515     /* if result = right then exchange them */
4516     if(sameRegs(AOP(result),AOP(right))){
4517         operand *tmp = right ;
4518         right = left;
4519         left = tmp;
4520     }
4521
4522     /* if right is bit then exchange them */
4523     if (AOP_TYPE(right) == AOP_CRY &&
4524         AOP_TYPE(left) != AOP_CRY){
4525         operand *tmp = right ;
4526         right = left;
4527         left = tmp;
4528     }
4529     if(AOP_TYPE(right) == AOP_LIT)
4530         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4531
4532     size = AOP_SIZE(result);
4533
4534     // if(bit | yy)
4535     // xx = bit | yy;
4536     if (AOP_TYPE(left) == AOP_CRY){
4537         if(AOP_TYPE(right) == AOP_LIT){
4538             // c = bit & literal;
4539             if(lit){
4540                 // lit != 0 => result = 1
4541                 if(AOP_TYPE(result) == AOP_CRY){
4542                     if(size)
4543                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4544                     else if(ifx)
4545                         continueIfTrue(ifx);
4546                     goto release;
4547                 }
4548                 emitcode("setb","c");
4549             } else {
4550                 // lit == 0 => result = left
4551                 if(size && sameRegs(AOP(result),AOP(left)))
4552                     goto release;
4553                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4554             }
4555         } else {
4556             if (AOP_TYPE(right) == AOP_CRY){
4557                 // c = bit | bit;
4558                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4559                 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4560             }
4561             else{
4562                 // c = bit | val;
4563                 symbol *tlbl = newiTempLabel(NULL);
4564                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4565                     emitcode("setb","c");
4566                 emitcode("jb","%s,%05d$",
4567                          AOP(left)->aopu.aop_dir,tlbl->key+100);
4568                 toBoolean(right);
4569                 emitcode("jnz","%05d$",tlbl->key+100);
4570                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4571                     jmpTrueOrFalse(ifx, tlbl);
4572                     goto release;
4573                 } else {
4574                     CLRC;
4575                     emitcode("","%05d$:",tlbl->key+100);
4576                 }
4577             }
4578         }
4579         // bit = c
4580         // val = c
4581         if(size)
4582             outBitC(result);
4583         // if(bit | ...)
4584         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4585             genIfxJump(ifx, "c");           
4586         goto release ;
4587     }
4588
4589     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4590     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4591     if((AOP_TYPE(right) == AOP_LIT) &&
4592        (AOP_TYPE(result) == AOP_CRY) &&
4593        (AOP_TYPE(left) != AOP_CRY)){
4594         if(lit){
4595             // result = 1
4596             if(size)
4597                 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4598             else 
4599                 continueIfTrue(ifx);
4600             goto release;
4601         } else {
4602             // lit = 0, result = boolean(left)
4603             if(size)
4604                 emitcode("setb","c");
4605             toBoolean(right);
4606             if(size){
4607                 symbol *tlbl = newiTempLabel(NULL);
4608                 emitcode("jnz","%05d$",tlbl->key+100);
4609                 CLRC;
4610                 emitcode("","%05d$:",tlbl->key+100);
4611             } else {
4612                 genIfxJump (ifx,"a");
4613                 goto release;
4614             }
4615         }
4616         outBitC(result);
4617         goto release ;
4618     }
4619
4620     /* if left is same as result */
4621     if(sameRegs(AOP(result),AOP(left))){
4622         for(;size--; offset++) {
4623             if(AOP_TYPE(right) == AOP_LIT){
4624                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4625                     continue;
4626                 else 
4627                     if (IS_AOP_PREG(left)) {
4628                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4629                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4630                         aopPut(AOP(result),"a",offset);
4631                     } else
4632                         emitcode("orl","%s,%s",
4633                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4634                                  aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4635             } else {
4636                 if (AOP_TYPE(left) == AOP_ACC) 
4637                     emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4638                 else {              
4639                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4640                     if (IS_AOP_PREG(left)) {
4641                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4642                         aopPut(AOP(result),"a",offset);
4643                     } else
4644                         emitcode("orl","%s,a",
4645                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4646                 }
4647             }
4648         }
4649     } else {
4650         // left & result in different registers
4651         if(AOP_TYPE(result) == AOP_CRY){
4652             // result = bit
4653             // if(size), result in bit
4654             // if(!size && ifx), conditional oper: if(left | right)
4655             symbol *tlbl = newiTempLabel(NULL);
4656             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4657             if(size)
4658                 emitcode("setb","c");
4659             while(sizer--){
4660                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4661                 emitcode("orl","a,%s",
4662                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4663                 emitcode("jnz","%05d$",tlbl->key+100);
4664                 offset++;
4665             }
4666             if(size){
4667                 CLRC;
4668                 emitcode("","%05d$:",tlbl->key+100);
4669                 outBitC(result);
4670             } else if(ifx)
4671                 jmpTrueOrFalse(ifx, tlbl);
4672         } else for(;(size--);offset++){
4673             // normal case
4674             // result = left & right
4675             if(AOP_TYPE(right) == AOP_LIT){
4676                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4677                     aopPut(AOP(result),
4678                            aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4679                            offset);
4680                     continue;
4681                 }
4682             }
4683             // faster than result <- left, anl result,right
4684             // and better if result is SFR
4685             if (AOP_TYPE(left) == AOP_ACC) 
4686                 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4687             else {
4688                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4689                 emitcode("orl","a,%s",
4690                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4691             }
4692             aopPut(AOP(result),"a",offset);                     
4693         }
4694     }
4695
4696 release :
4697     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4698     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4699     freeAsmop(result,NULL,ic,TRUE);     
4700 }
4701
4702 /*-----------------------------------------------------------------*/
4703 /* genXor - code for xclusive or                                   */
4704 /*-----------------------------------------------------------------*/
4705 static void genXor (iCode *ic, iCode *ifx)
4706 {
4707     operand *left, *right, *result;
4708     int size, offset=0;
4709     unsigned long lit = 0L;
4710
4711     D(emitcode(";", "genXor "););
4712
4713     AOP_OP_3(ic);
4714     AOP_SET_LOCALS(ic);
4715 #if 0
4716     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4717     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4718     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4719 #endif
4720
4721 #ifdef DEBUG_TYPE
4722     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4723              AOP_TYPE(result),
4724              AOP_TYPE(left), AOP_TYPE(right));
4725     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4726              AOP_SIZE(result),
4727              AOP_SIZE(left), AOP_SIZE(right));
4728 #endif
4729
4730     /* if left is a literal & right is not ||
4731        if left needs acc & right does not */
4732     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4733         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4734         operand *tmp = right ;
4735         right = left;
4736         left = tmp;
4737     }
4738
4739     /* if result = right then exchange them */
4740     if(sameRegs(AOP(result),AOP(right))){
4741         operand *tmp = right ;
4742         right = left;
4743         left = tmp;
4744     }
4745
4746     /* if right is bit then exchange them */
4747     if (AOP_TYPE(right) == AOP_CRY &&
4748         AOP_TYPE(left) != AOP_CRY){
4749         operand *tmp = right ;
4750         right = left;
4751         left = tmp;
4752     }
4753     if(AOP_TYPE(right) == AOP_LIT)
4754         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4755
4756     size = AOP_SIZE(result);
4757
4758     // if(bit ^ yy)
4759     // xx = bit ^ yy;
4760     if (AOP_TYPE(left) == AOP_CRY){
4761         if(AOP_TYPE(right) == AOP_LIT){
4762             // c = bit & literal;
4763             if(lit>>1){
4764                 // lit>>1  != 0 => result = 1
4765                 if(AOP_TYPE(result) == AOP_CRY){
4766                     if(size)
4767                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4768                     else if(ifx)
4769                         continueIfTrue(ifx);
4770                     goto release;
4771                 }
4772                 emitcode("setb","c");
4773             } else{
4774                 // lit == (0 or 1)
4775                 if(lit == 0){
4776                     // lit == 0, result = left
4777                     if(size && sameRegs(AOP(result),AOP(left)))
4778                         goto release;
4779                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4780                 } else{
4781                     // lit == 1, result = not(left)
4782                     if(size && sameRegs(AOP(result),AOP(left))){
4783                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4784                         goto release;
4785                     } else {
4786                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4787                         emitcode("cpl","c");
4788                     }
4789                 }
4790             }
4791
4792         } else {
4793             // right != literal
4794             symbol *tlbl = newiTempLabel(NULL);
4795             if (AOP_TYPE(right) == AOP_CRY){
4796                 // c = bit ^ bit;
4797                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4798             }
4799             else{
4800                 int sizer = AOP_SIZE(right);
4801                 // c = bit ^ val
4802                 // if val>>1 != 0, result = 1
4803                 emitcode("setb","c");
4804                 while(sizer){
4805                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
4806                     if(sizer == 1)
4807                         // test the msb of the lsb
4808                         emitcode("anl","a,#0xfe");
4809                     emitcode("jnz","%05d$",tlbl->key+100);
4810                     sizer--;
4811                 }
4812                 // val = (0,1)
4813                 emitcode("rrc","a");
4814             }
4815             emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4816             emitcode("cpl","c");
4817             emitcode("","%05d$:",(tlbl->key+100));
4818         }
4819         // bit = c
4820         // val = c
4821         if(size)
4822             outBitC(result);
4823         // if(bit | ...)
4824         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4825             genIfxJump(ifx, "c");           
4826         goto release ;
4827     }
4828
4829     if(sameRegs(AOP(result),AOP(left))){
4830         /* if left is same as result */
4831         for(;size--; offset++) {
4832             if(AOP_TYPE(right) == AOP_LIT){
4833                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4834                     continue;
4835                 else
4836                     if (IS_AOP_PREG(left)) {
4837                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4838                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4839                         aopPut(AOP(result),"a",offset);
4840                     } else 
4841                         emitcode("xrl","%s,%s",
4842                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4843                                  aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4844             } else {
4845                 if (AOP_TYPE(left) == AOP_ACC)
4846                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4847                 else {
4848                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4849                     if (IS_AOP_PREG(left)) {
4850                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4851                         aopPut(AOP(result),"a",offset);
4852                     } else
4853                         emitcode("xrl","%s,a",
4854                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4855                 }
4856             }
4857         }
4858     } else {
4859         // left & result in different registers
4860         if(AOP_TYPE(result) == AOP_CRY){
4861             // result = bit
4862             // if(size), result in bit
4863             // if(!size && ifx), conditional oper: if(left ^ right)
4864             symbol *tlbl = newiTempLabel(NULL);
4865             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4866             if(size)
4867                 emitcode("setb","c");
4868             while(sizer--){
4869                 if((AOP_TYPE(right) == AOP_LIT) &&
4870                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4871                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4872                 } else {
4873                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4874                     emitcode("xrl","a,%s",
4875                              aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4876                 }
4877                 emitcode("jnz","%05d$",tlbl->key+100);
4878                 offset++;
4879             }
4880             if(size){
4881                 CLRC;
4882                 emitcode("","%05d$:",tlbl->key+100);
4883                 outBitC(result);
4884             } else if(ifx)
4885                 jmpTrueOrFalse(ifx, tlbl);
4886         } else for(;(size--);offset++){
4887             // normal case
4888             // result = left & right
4889             if(AOP_TYPE(right) == AOP_LIT){
4890                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4891                     aopPut(AOP(result),
4892                            aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4893                            offset);
4894                     continue;
4895                 }
4896             }
4897             // faster than result <- left, anl result,right
4898             // and better if result is SFR
4899             if (AOP_TYPE(left) == AOP_ACC)
4900                 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4901             else {
4902                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4903                 emitcode("xrl","a,%s",
4904                          aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4905             }
4906             aopPut(AOP(result),"a",offset);
4907         }
4908     }
4909
4910 release :
4911     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4912     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4913     freeAsmop(result,NULL,ic,TRUE);     
4914 }
4915
4916 /*-----------------------------------------------------------------*/
4917 /* genInline - write the inline code out                           */
4918 /*-----------------------------------------------------------------*/
4919 static void genInline (iCode *ic)
4920 {
4921     char buffer[MAX_INLINEASM];
4922     char *bp = buffer;
4923     char *bp1= buffer;
4924     
4925     D(emitcode(";", "genInline "););
4926
4927     _G.inLine += (!options.asmpeep);
4928     strcpy(buffer,IC_INLINE(ic));
4929
4930     /* emit each line as a code */
4931     while (*bp) {
4932         if (*bp == '\n') {
4933             *bp++ = '\0';
4934             emitcode(bp1,"");
4935             bp1 = bp;
4936         } else {
4937             if (*bp == ':') {
4938                 bp++;
4939                 *bp = '\0';
4940                 bp++;
4941                 emitcode(bp1,"");
4942                 bp1 = bp;
4943             } else
4944                 bp++;
4945         }
4946     }
4947     if (bp1 != bp)
4948         emitcode(bp1,"");
4949     /*     emitcode("",buffer); */
4950     _G.inLine -= (!options.asmpeep);
4951 }
4952
4953 /*-----------------------------------------------------------------*/
4954 /* genRRC - rotate right with carry                                */
4955 /*-----------------------------------------------------------------*/
4956 static void genRRC (iCode *ic)
4957 {
4958     operand *left , *result ;
4959     int size, offset = 0;
4960     char *l;    
4961
4962     D(emitcode(";", "genRRC "););
4963
4964     /* rotate right with carry */
4965     left = IC_LEFT(ic);
4966     result=IC_RESULT(ic);
4967     aopOp (left,ic,FALSE, FALSE);
4968     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
4969
4970     /* move it to the result */
4971     size = AOP_SIZE(result);    
4972     offset = size - 1 ;
4973     CLRC;
4974     while (size--) {
4975         l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4976         MOVA(l);
4977         emitcode("rrc","a");
4978         if (AOP_SIZE(result) > 1)
4979             aopPut(AOP(result),"a",offset--);
4980     }
4981     /* now we need to put the carry into the
4982     highest order byte of the result */
4983     if (AOP_SIZE(result) > 1) {
4984         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
4985         MOVA(l);
4986     }
4987     emitcode("mov","acc.7,c");
4988     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4989     freeAsmop(left,NULL,ic,TRUE);
4990     freeAsmop(result,NULL,ic,TRUE);
4991 }
4992
4993 /*-----------------------------------------------------------------*/
4994 /* genRLC - generate code for rotate left with carry               */
4995 /*-----------------------------------------------------------------*/
4996 static void genRLC (iCode *ic)
4997 {    
4998     operand *left , *result ;
4999     int size, offset = 0;
5000     char *l;    
5001
5002     D(emitcode(";", "genRLC "););
5003
5004     /* rotate right with carry */
5005     left = IC_LEFT(ic);
5006     result=IC_RESULT(ic);
5007     aopOp (left,ic,FALSE, FALSE);
5008     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5009
5010     /* move it to the result */
5011     size = AOP_SIZE(result);    
5012     offset = 0 ;
5013     if (size--) {
5014         l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5015         MOVA(l);
5016         emitcode("add","a,acc");
5017         if (AOP_SIZE(result) > 1)
5018             aopPut(AOP(result),"a",offset++);
5019         while (size--) {
5020             l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5021             MOVA(l);
5022             emitcode("rlc","a");
5023             if (AOP_SIZE(result) > 1)
5024                 aopPut(AOP(result),"a",offset++);
5025         }
5026     }
5027     /* now we need to put the carry into the
5028     highest order byte of the result */
5029     if (AOP_SIZE(result) > 1) {
5030         l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5031         MOVA(l);
5032     }
5033     emitcode("mov","acc.0,c");
5034     aopPut(AOP(result),"a",0);
5035     freeAsmop(left,NULL,ic,TRUE);
5036     freeAsmop(result,NULL,ic,TRUE);
5037 }
5038
5039 /*-----------------------------------------------------------------*/
5040 /* genGetHbit - generates code get highest order bit               */
5041 /*-----------------------------------------------------------------*/
5042 static void genGetHbit (iCode *ic)
5043 {
5044     operand *left, *result;
5045     left = IC_LEFT(ic);
5046     result=IC_RESULT(ic);
5047     aopOp (left,ic,FALSE, FALSE);
5048     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5049
5050     D(emitcode(";", "genGetHbit "););
5051
5052     /* get the highest order byte into a */
5053     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5054     if(AOP_TYPE(result) == AOP_CRY){
5055         emitcode("rlc","a");
5056         outBitC(result);
5057     }
5058     else{
5059         emitcode("rl","a");
5060         emitcode("anl","a,#0x01");
5061         outAcc(result);
5062     }
5063
5064
5065     freeAsmop(left,NULL,ic,TRUE);
5066     freeAsmop(result,NULL,ic,TRUE);
5067 }
5068
5069 /*-----------------------------------------------------------------*/
5070 /* AccRol - rotate left accumulator by known count                 */
5071 /*-----------------------------------------------------------------*/
5072 static void AccRol (int shCount)
5073 {
5074     shCount &= 0x0007;              // shCount : 0..7
5075     switch(shCount){
5076         case 0 :
5077             break;
5078         case 1 :
5079             emitcode("rl","a");
5080             break;
5081         case 2 :
5082             emitcode("rl","a");
5083             emitcode("rl","a");
5084             break;
5085         case 3 :
5086             emitcode("swap","a");
5087             emitcode("rr","a");
5088             break;
5089         case 4 :
5090             emitcode("swap","a");
5091             break;
5092         case 5 :
5093             emitcode("swap","a");
5094             emitcode("rl","a");
5095             break;
5096         case 6 :
5097             emitcode("rr","a");
5098             emitcode("rr","a");
5099             break;
5100         case 7 :
5101             emitcode("rr","a");
5102             break;
5103     }
5104 }
5105
5106 /*-----------------------------------------------------------------*/
5107 /* AccLsh - left shift accumulator by known count                  */
5108 /*-----------------------------------------------------------------*/
5109 static void AccLsh (int shCount)
5110 {
5111     if(shCount != 0){
5112         if(shCount == 1)
5113             emitcode("add","a,acc");
5114         else 
5115             if(shCount == 2) {
5116             emitcode("add","a,acc");
5117             emitcode("add","a,acc");
5118         } else {
5119             /* rotate left accumulator */
5120             AccRol(shCount);
5121             /* and kill the lower order bits */
5122             emitcode("anl","a,#0x%02x", SLMask[shCount]);
5123         }
5124     }
5125 }
5126
5127 /*-----------------------------------------------------------------*/
5128 /* AccRsh - right shift accumulator by known count                 */
5129 /*-----------------------------------------------------------------*/
5130 static void AccRsh (int shCount)
5131 {
5132     if(shCount != 0){
5133         if(shCount == 1){
5134             CLRC;
5135             emitcode("rrc","a");
5136         } else {
5137             /* rotate right accumulator */
5138             AccRol(8 - shCount);
5139             /* and kill the higher order bits */
5140             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5141         }
5142     }
5143 }
5144
5145 /*-----------------------------------------------------------------*/
5146 /* AccSRsh - signed right shift accumulator by known count                 */
5147 /*-----------------------------------------------------------------*/
5148 static void AccSRsh (int shCount)
5149 {
5150     symbol *tlbl ;
5151     if(shCount != 0){
5152         if(shCount == 1){
5153             emitcode("mov","c,acc.7");
5154             emitcode("rrc","a");
5155         } else if(shCount == 2){
5156             emitcode("mov","c,acc.7");
5157             emitcode("rrc","a");
5158             emitcode("mov","c,acc.7");
5159             emitcode("rrc","a");
5160         } else {
5161             tlbl = newiTempLabel(NULL);
5162             /* rotate right accumulator */
5163             AccRol(8 - shCount);
5164             /* and kill the higher order bits */
5165             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5166             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5167             emitcode("orl","a,#0x%02x",
5168                      (unsigned char)~SRMask[shCount]);
5169             emitcode("","%05d$:",tlbl->key+100);
5170         }
5171     }
5172 }
5173
5174 /*-----------------------------------------------------------------*/
5175 /* shiftR1Left2Result - shift right one byte from left to result   */
5176 /*-----------------------------------------------------------------*/
5177 static void shiftR1Left2Result (operand *left, int offl,
5178                                 operand *result, int offr,
5179                                 int shCount, int sign)
5180 {
5181     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5182     /* shift right accumulator */
5183     if(sign)
5184         AccSRsh(shCount);
5185     else
5186         AccRsh(shCount);
5187     aopPut(AOP(result),"a",offr);
5188 }
5189
5190 /*-----------------------------------------------------------------*/
5191 /* shiftL1Left2Result - shift left one byte from left to result    */
5192 /*-----------------------------------------------------------------*/
5193 static void shiftL1Left2Result (operand *left, int offl,
5194                                 operand *result, int offr, int shCount)
5195 {
5196     char *l;
5197     l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5198     MOVA(l);
5199     /* shift left accumulator */
5200     AccLsh(shCount);
5201     aopPut(AOP(result),"a",offr);
5202 }
5203
5204 /*-----------------------------------------------------------------*/
5205 /* movLeft2Result - move byte from left to result                  */
5206 /*-----------------------------------------------------------------*/
5207 static void movLeft2Result (operand *left, int offl,
5208                             operand *result, int offr, int sign)
5209 {
5210     char *l;
5211     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5212         l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5213
5214         if (*l == '@' && (IS_AOP_PREG(result))) {
5215             emitcode("mov","a,%s",l);
5216             aopPut(AOP(result),"a",offr);
5217         } else {
5218             if(!sign)
5219                 aopPut(AOP(result),l,offr);
5220             else{
5221                 /* MSB sign in acc.7 ! */
5222                 if(getDataSize(left) == offl+1){
5223                     emitcode("mov","a,%s",l);
5224                     aopPut(AOP(result),"a",offr);
5225                 }
5226             }
5227         }
5228     }
5229 }
5230
5231 /*-----------------------------------------------------------------*/
5232 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5233 /*-----------------------------------------------------------------*/
5234 static void AccAXRrl1 (char *x)
5235 {
5236     emitcode("rrc","a");
5237     emitcode("xch","a,%s", x);
5238     emitcode("rrc","a");
5239     emitcode("xch","a,%s", x);
5240 }
5241
5242 /*-----------------------------------------------------------------*/
5243 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5244 /*-----------------------------------------------------------------*/
5245 static void AccAXLrl1 (char *x)
5246 {
5247     emitcode("xch","a,%s",x);
5248     emitcode("rlc","a");
5249     emitcode("xch","a,%s",x);
5250     emitcode("rlc","a");
5251 }
5252
5253 /*-----------------------------------------------------------------*/
5254 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5255 /*-----------------------------------------------------------------*/
5256 static void AccAXLsh1 (char *x)
5257 {
5258     emitcode("xch","a,%s",x);
5259     emitcode("add","a,acc");
5260     emitcode("xch","a,%s",x);
5261     emitcode("rlc","a");
5262 }
5263
5264 /*-----------------------------------------------------------------*/
5265 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5266 /*-----------------------------------------------------------------*/
5267 static void AccAXLsh (char *x, int shCount)
5268 {
5269     switch(shCount){
5270         case 0 :
5271             break;
5272         case 1 :
5273             AccAXLsh1(x);
5274             break;
5275         case 2 :
5276             AccAXLsh1(x);
5277             AccAXLsh1(x);
5278             break;
5279         case 3 :
5280         case 4 :
5281         case 5 :                        // AAAAABBB:CCCCCDDD
5282             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
5283             emitcode("anl","a,#0x%02x",
5284                      SLMask[shCount]);  // BBB00000:CCCCCDDD
5285             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
5286             AccRol(shCount);            // DDDCCCCC:BBB00000
5287             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
5288             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
5289             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
5290             emitcode("anl","a,#0x%02x",
5291                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
5292             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
5293             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
5294             break;
5295         case 6 :                        // AAAAAABB:CCCCCCDD
5296             emitcode("anl","a,#0x%02x",
5297                      SRMask[shCount]);  // 000000BB:CCCCCCDD
5298             emitcode("mov","c,acc.0");  // c = B
5299             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
5300             AccAXRrl1(x);               // BCCCCCCD:D000000B
5301             AccAXRrl1(x);               // BBCCCCCC:DD000000
5302             break;
5303         case 7 :                        // a:x <<= 7
5304             emitcode("anl","a,#0x%02x",
5305                      SRMask[shCount]);  // 0000000B:CCCCCCCD
5306             emitcode("mov","c,acc.0");  // c = B
5307             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
5308             AccAXRrl1(x);               // BCCCCCCC:D0000000
5309             break;
5310         default :
5311             break;
5312     }
5313 }
5314
5315 /*-----------------------------------------------------------------*/
5316 /* AccAXRsh - right shift a:x known count (0..7)                   */
5317 /*-----------------------------------------------------------------*/
5318 static void AccAXRsh (char *x, int shCount)
5319 {   
5320     switch(shCount){
5321         case 0 :
5322             break;
5323         case 1 :
5324             CLRC;
5325             AccAXRrl1(x);               // 0->a:x
5326             break;
5327         case 2 :
5328             CLRC;
5329             AccAXRrl1(x);               // 0->a:x
5330             CLRC;
5331             AccAXRrl1(x);               // 0->a:x
5332             break;
5333         case 3 :
5334         case 4 :
5335         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5336             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
5337             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5338             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5339             emitcode("anl","a,#0x%02x",
5340                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5341             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5342             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5343             emitcode("anl","a,#0x%02x",
5344                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5345             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5346             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5347             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
5348             break;
5349         case 6 :                        // AABBBBBB:CCDDDDDD
5350             emitcode("mov","c,acc.7");
5351             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5352             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5353             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5354             emitcode("anl","a,#0x%02x",
5355                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5356             break;
5357         case 7 :                        // ABBBBBBB:CDDDDDDD
5358             emitcode("mov","c,acc.7");  // c = A
5359             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5360             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5361             emitcode("anl","a,#0x%02x",
5362                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5363             break;
5364         default :
5365             break;
5366     }
5367 }
5368
5369 /*-----------------------------------------------------------------*/
5370 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5371 /*-----------------------------------------------------------------*/
5372 static void AccAXRshS (char *x, int shCount)
5373 {   
5374     symbol *tlbl ;
5375     switch(shCount){
5376         case 0 :
5377             break;
5378         case 1 :
5379             emitcode("mov","c,acc.7");
5380             AccAXRrl1(x);               // s->a:x
5381             break;
5382         case 2 :
5383             emitcode("mov","c,acc.7");
5384             AccAXRrl1(x);               // s->a:x
5385             emitcode("mov","c,acc.7");
5386             AccAXRrl1(x);               // s->a:x
5387             break;
5388         case 3 :
5389         case 4 :
5390         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5391             tlbl = newiTempLabel(NULL);
5392             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
5393             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5394             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5395             emitcode("anl","a,#0x%02x",
5396                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5397             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5398             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5399             emitcode("anl","a,#0x%02x",
5400                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5401             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5402             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5403             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
5404             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5405             emitcode("orl","a,#0x%02x",
5406                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
5407             emitcode("","%05d$:",tlbl->key+100);
5408             break;                      // SSSSAAAA:BBBCCCCC
5409         case 6 :                        // AABBBBBB:CCDDDDDD
5410             tlbl = newiTempLabel(NULL);
5411             emitcode("mov","c,acc.7");
5412             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5413             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5414             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5415             emitcode("anl","a,#0x%02x",
5416                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5417             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5418             emitcode("orl","a,#0x%02x",
5419                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
5420             emitcode("","%05d$:",tlbl->key+100);
5421             break;
5422         case 7 :                        // ABBBBBBB:CDDDDDDD
5423             tlbl = newiTempLabel(NULL);
5424             emitcode("mov","c,acc.7");  // c = A
5425             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5426             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5427             emitcode("anl","a,#0x%02x",
5428                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5429             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5430             emitcode("orl","a,#0x%02x",
5431                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
5432             emitcode("","%05d$:",tlbl->key+100);
5433             break;
5434         default :
5435             break;
5436     }
5437 }
5438
5439 /*-----------------------------------------------------------------*/
5440 /* shiftL2Left2Result - shift left two bytes from left to result   */
5441 /*-----------------------------------------------------------------*/
5442 static void shiftL2Left2Result (operand *left, int offl,
5443                                 operand *result, int offr, int shCount)
5444 {
5445     if(sameRegs(AOP(result), AOP(left)) &&
5446        ((offl + MSB16) == offr)){
5447         /* don't crash result[offr] */
5448         MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5449         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5450     } else {
5451         movLeft2Result(left,offl, result, offr, 0);
5452         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5453     }
5454     /* ax << shCount (x = lsb(result))*/
5455     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5456     aopPut(AOP(result),"a",offr+MSB16);
5457 }
5458
5459
5460 /*-----------------------------------------------------------------*/
5461 /* shiftR2Left2Result - shift right two bytes from left to result  */
5462 /*-----------------------------------------------------------------*/
5463 static void shiftR2Left2Result (operand *left, int offl,
5464                                 operand *result, int offr,
5465                                 int shCount, int sign)
5466 {
5467     if(sameRegs(AOP(result), AOP(left)) &&
5468        ((offl + MSB16) == offr)){
5469         /* don't crash result[offr] */
5470         MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5471         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5472     } else {
5473         movLeft2Result(left,offl, result, offr, 0);
5474         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5475     }
5476     /* a:x >> shCount (x = lsb(result))*/
5477     if(sign)
5478         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5479     else
5480         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5481     if(getDataSize(result) > 1)
5482         aopPut(AOP(result),"a",offr+MSB16);
5483 }
5484
5485 /*-----------------------------------------------------------------*/
5486 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5487 /*-----------------------------------------------------------------*/
5488 static void shiftLLeftOrResult (operand *left, int offl,
5489                                 operand *result, int offr, int shCount)
5490 {
5491     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5492     /* shift left accumulator */
5493     AccLsh(shCount);
5494     /* or with result */
5495     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5496     /* back to result */
5497     aopPut(AOP(result),"a",offr);
5498 }
5499
5500 /*-----------------------------------------------------------------*/
5501 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5502 /*-----------------------------------------------------------------*/
5503 static void shiftRLeftOrResult (operand *left, int offl,
5504                                 operand *result, int offr, int shCount)
5505 {
5506     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5507     /* shift right accumulator */
5508     AccRsh(shCount);
5509     /* or with result */
5510     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5511     /* back to result */
5512     aopPut(AOP(result),"a",offr);
5513 }
5514
5515 /*-----------------------------------------------------------------*/
5516 /* genlshOne - left shift a one byte quantity by known count       */
5517 /*-----------------------------------------------------------------*/
5518 static void genlshOne (operand *result, operand *left, int shCount)
5519 {       
5520     D(emitcode(";", "genlshOne "););
5521     shiftL1Left2Result(left, LSB, result, LSB, shCount);
5522 }
5523
5524 /*-----------------------------------------------------------------*/
5525 /* genlshTwo - left shift two bytes by known amount != 0           */
5526 /*-----------------------------------------------------------------*/
5527 static void genlshTwo (operand *result,operand *left, int shCount)
5528 {
5529     int size;
5530     
5531     D(emitcode(";", "genlshTwo "););
5532
5533     size = getDataSize(result);
5534
5535     /* if shCount >= 8 */
5536     if (shCount >= 8) {
5537         shCount -= 8 ;
5538
5539         if (size > 1){
5540             if (shCount)
5541                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5542             else 
5543                 movLeft2Result(left, LSB, result, MSB16, 0);
5544         }
5545         aopPut(AOP(result),zero,LSB);   
5546     }
5547
5548     /*  1 <= shCount <= 7 */
5549     else {  
5550         if(size == 1)
5551             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
5552         else 
5553             shiftL2Left2Result(left, LSB, result, LSB, shCount);
5554     }
5555 }
5556
5557 /*-----------------------------------------------------------------*/
5558 /* shiftLLong - shift left one long from left to result            */
5559 /* offl = LSB or MSB16                                             */
5560 /*-----------------------------------------------------------------*/
5561 static void shiftLLong (operand *left, operand *result, int offr )
5562 {
5563     char *l;
5564     int size = AOP_SIZE(result);
5565
5566     if(size >= LSB+offr){
5567         l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5568         MOVA(l);
5569         emitcode("add","a,acc");
5570         if (sameRegs(AOP(left),AOP(result)) && 
5571             size >= MSB16+offr && offr != LSB )
5572             emitcode("xch","a,%s",
5573                      aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5574         else        
5575             aopPut(AOP(result),"a",LSB+offr);
5576     }
5577
5578     if(size >= MSB16+offr){
5579         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5580             l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5581             MOVA(l);
5582         }
5583         emitcode("rlc","a");
5584         if (sameRegs(AOP(left),AOP(result)) && 
5585             size >= MSB24+offr && offr != LSB)
5586             emitcode("xch","a,%s",
5587                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5588         else        
5589             aopPut(AOP(result),"a",MSB16+offr);
5590     }
5591
5592     if(size >= MSB24+offr){
5593         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5594             l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5595             MOVA(l);
5596         }
5597         emitcode("rlc","a");
5598         if (sameRegs(AOP(left),AOP(result)) && 
5599             size >= MSB32+offr && offr != LSB )
5600             emitcode("xch","a,%s",
5601                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5602         else        
5603             aopPut(AOP(result),"a",MSB24+offr);
5604     }
5605
5606     if(size > MSB32+offr){
5607         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5608             l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5609             MOVA(l);    
5610         }
5611         emitcode("rlc","a");
5612         aopPut(AOP(result),"a",MSB32+offr);
5613     }
5614     if(offr != LSB)
5615         aopPut(AOP(result),zero,LSB);       
5616 }
5617
5618 /*-----------------------------------------------------------------*/
5619 /* genlshFour - shift four byte by a known amount != 0             */
5620 /*-----------------------------------------------------------------*/
5621 static void genlshFour (operand *result, operand *left, int shCount)
5622 {
5623     int size;
5624
5625     D(emitcode(";", "genlshFour "););
5626
5627     size = AOP_SIZE(result);
5628
5629     /* if shifting more that 3 bytes */
5630     if (shCount >= 24 ) {
5631         shCount -= 24;
5632         if (shCount)
5633             /* lowest order of left goes to the highest
5634             order of the destination */
5635             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5636         else
5637             movLeft2Result(left, LSB, result, MSB32, 0);
5638         aopPut(AOP(result),zero,LSB);
5639         aopPut(AOP(result),zero,MSB16);
5640         aopPut(AOP(result),zero,MSB32);
5641         return;
5642     }
5643
5644     /* more than two bytes */
5645     else if ( shCount >= 16 ) {
5646         /* lower order two bytes goes to higher order two bytes */
5647         shCount -= 16;
5648         /* if some more remaining */
5649         if (shCount)
5650             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5651         else {
5652             movLeft2Result(left, MSB16, result, MSB32, 0);
5653             movLeft2Result(left, LSB, result, MSB24, 0);
5654         }
5655         aopPut(AOP(result),zero,MSB16);
5656         aopPut(AOP(result),zero,LSB);
5657         return;
5658     }    
5659
5660     /* if more than 1 byte */
5661     else if ( shCount >= 8 ) {
5662         /* lower order three bytes goes to higher order  three bytes */
5663         shCount -= 8;
5664         if(size == 2){
5665             if(shCount)
5666                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5667             else
5668                 movLeft2Result(left, LSB, result, MSB16, 0);
5669         }
5670         else{   /* size = 4 */
5671             if(shCount == 0){
5672                 movLeft2Result(left, MSB24, result, MSB32, 0);
5673                 movLeft2Result(left, MSB16, result, MSB24, 0);
5674                 movLeft2Result(left, LSB, result, MSB16, 0);
5675                 aopPut(AOP(result),zero,LSB);
5676             }
5677             else if(shCount == 1)
5678                 shiftLLong(left, result, MSB16);
5679             else{
5680                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5681                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5682                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5683                 aopPut(AOP(result),zero,LSB);
5684             }
5685         }
5686     }
5687
5688     /* 1 <= shCount <= 7 */
5689     else if(shCount <= 2){
5690         shiftLLong(left, result, LSB);
5691         if(shCount == 2)
5692             shiftLLong(result, result, LSB);
5693     }
5694     /* 3 <= shCount <= 7, optimize */
5695     else{
5696         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5697         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5698         shiftL2Left2Result(left, LSB, result, LSB, shCount);
5699     }
5700 }
5701
5702 /*-----------------------------------------------------------------*/
5703 /* genLeftShiftLiteral - left shifting by known count              */
5704 /*-----------------------------------------------------------------*/
5705 static void genLeftShiftLiteral (operand *left,
5706                                  operand *right,
5707                                  operand *result,
5708                                  iCode *ic)
5709 {    
5710     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5711     int size;
5712
5713     D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5714
5715     freeAsmop(right,NULL,ic,TRUE);
5716
5717     aopOp(left,ic,FALSE, FALSE);
5718     aopOp(result,ic,FALSE, TRUE);
5719
5720     size = getSize(operandType(result));
5721
5722 #if VIEW_SIZE
5723     emitcode("; shift left ","result %d, left %d",size,
5724              AOP_SIZE(left));
5725 #endif
5726
5727     /* I suppose that the left size >= result size */
5728     if(shCount == 0){
5729         while(size--){
5730             movLeft2Result(left, size, result, size, 0);
5731         }
5732     }
5733
5734     else if(shCount >= (size * 8))
5735         while(size--)
5736             aopPut(AOP(result),zero,size);
5737     else{
5738         switch (size) {
5739             case 1:
5740                 genlshOne (result,left,shCount);
5741                 break;
5742
5743             case 2:
5744             case 3: /* bug: this is for generic pointers, I bet. */
5745                 genlshTwo (result,left,shCount);
5746                 break;
5747
5748             case 4:
5749                 genlshFour (result,left,shCount);
5750                 break;
5751         }
5752     }
5753     freeAsmop(left,NULL,ic,TRUE);
5754     freeAsmop(result,NULL,ic,TRUE);
5755 }
5756
5757 /*-----------------------------------------------------------------*/
5758 /* genLeftShift - generates code for left shifting                 */
5759 /*-----------------------------------------------------------------*/
5760 static void genLeftShift (iCode *ic)
5761 {
5762     operand *left,*right, *result;
5763     int size, offset;
5764     char *l;
5765     symbol *tlbl , *tlbl1;
5766
5767     D(emitcode(";", "genLeftShift "););
5768
5769     right = IC_RIGHT(ic);
5770     left  = IC_LEFT(ic);
5771     result = IC_RESULT(ic);
5772
5773     aopOp(right,ic,FALSE, FALSE);
5774
5775     #if 0
5776     /* if the shift count is known then do it 
5777     as efficiently as possible */
5778     if (AOP_TYPE(right) == AOP_LIT) {
5779         genLeftShiftLiteral (left,right,result,ic);
5780         return ;
5781     }
5782     #endif
5783
5784     /* shift count is unknown then we have to form 
5785     a loop get the loop count in B : Note: we take
5786     only the lower order byte since shifting
5787     more that 32 bits make no sense anyway, ( the
5788     largest size of an object can be only 32 bits ) */  
5789
5790     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
5791     emitcode("inc","b");
5792     freeAsmop (right,NULL,ic,TRUE);
5793     aopOp(left,ic,FALSE, FALSE);
5794     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5795
5796     /* now move the left to the result if they are not the
5797     same */
5798     if (!sameRegs(AOP(left),AOP(result)) && 
5799         AOP_SIZE(result) > 1) {
5800
5801         size = AOP_SIZE(result);
5802         offset=0;
5803         while (size--) {
5804             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
5805             if (*l == '@' && (IS_AOP_PREG(result))) {
5806
5807                 emitcode("mov","a,%s",l);
5808                 aopPut(AOP(result),"a",offset);
5809             } else
5810                 aopPut(AOP(result),l,offset);
5811             offset++;
5812         }
5813     }
5814
5815     tlbl = newiTempLabel(NULL);
5816     size = AOP_SIZE(result);
5817     offset = 0 ;   
5818     tlbl1 = newiTempLabel(NULL);
5819
5820     /* if it is only one byte then */
5821     if (size == 1) {
5822         symbol *tlbl1 = newiTempLabel(NULL);
5823
5824         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
5825         MOVA(l);
5826         emitcode("sjmp","%05d$",tlbl1->key+100); 
5827         emitcode("","%05d$:",tlbl->key+100);
5828         emitcode("add","a,acc");
5829         emitcode("","%05d$:",tlbl1->key+100);
5830         emitcode("djnz","b,%05d$",tlbl->key+100);      
5831         aopPut(AOP(result),"a",0);
5832         goto release ;
5833     }
5834     
5835     reAdjustPreg(AOP(result));    
5836     
5837     emitcode("sjmp","%05d$",tlbl1->key+100); 
5838     emitcode("","%05d$:",tlbl->key+100);    
5839     l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5840     MOVA(l);
5841     emitcode("add","a,acc");         
5842     aopPut(AOP(result),"a",offset++);
5843     while (--size) {
5844         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5845         MOVA(l);
5846         emitcode("rlc","a");         
5847         aopPut(AOP(result),"a",offset++);
5848     }
5849     reAdjustPreg(AOP(result));
5850
5851     emitcode("","%05d$:",tlbl1->key+100);
5852     emitcode("djnz","b,%05d$",tlbl->key+100);
5853 release:
5854     freeAsmop(left,NULL,ic,TRUE);
5855     freeAsmop(result,NULL,ic,TRUE);
5856 }
5857
5858 /*-----------------------------------------------------------------*/
5859 /* genrshOne - right shift a one byte quantity by known count      */
5860 /*-----------------------------------------------------------------*/
5861 static void genrshOne (operand *result, operand *left,
5862                        int shCount, int sign)
5863 {
5864     D(emitcode(";", "genrshOne"););
5865     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5866 }
5867
5868 /*-----------------------------------------------------------------*/
5869 /* genrshTwo - right shift two bytes by known amount != 0          */
5870 /*-----------------------------------------------------------------*/
5871 static void genrshTwo (operand *result,operand *left,
5872                        int shCount, int sign)
5873 {
5874     D(emitcode(";", "genrshTwo"););
5875
5876     /* if shCount >= 8 */
5877     if (shCount >= 8) {
5878         shCount -= 8 ;
5879         if (shCount)
5880             shiftR1Left2Result(left, MSB16, result, LSB,
5881                                shCount, sign);
5882         else 
5883             movLeft2Result(left, MSB16, result, LSB, sign);
5884         addSign(result, MSB16, sign);
5885     }
5886
5887     /*  1 <= shCount <= 7 */
5888     else
5889         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
5890 }
5891
5892 /*-----------------------------------------------------------------*/
5893 /* shiftRLong - shift right one long from left to result           */
5894 /* offl = LSB or MSB16                                             */
5895 /*-----------------------------------------------------------------*/
5896 static void shiftRLong (operand *left, int offl,
5897                         operand *result, int sign)
5898 {
5899     if(!sign)
5900         emitcode("clr","c");
5901     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
5902     if(sign)
5903         emitcode("mov","c,acc.7");
5904     emitcode("rrc","a");
5905     aopPut(AOP(result),"a",MSB32-offl);
5906     if(offl == MSB16)
5907         /* add sign of "a" */
5908         addSign(result, MSB32, sign);
5909
5910     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
5911     emitcode("rrc","a");
5912     aopPut(AOP(result),"a",MSB24-offl);
5913
5914     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
5915     emitcode("rrc","a");
5916     aopPut(AOP(result),"a",MSB16-offl);
5917
5918     if(offl == LSB){
5919         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
5920         emitcode("rrc","a");
5921         aopPut(AOP(result),"a",LSB);
5922     }
5923 }
5924
5925 /*-----------------------------------------------------------------*/
5926 /* genrshFour - shift four byte by a known amount != 0             */
5927 /*-----------------------------------------------------------------*/
5928 static void genrshFour (operand *result, operand *left,
5929                         int shCount, int sign)
5930 {
5931     D(emitcode(";", "genrshFour"););
5932     
5933     /* if shifting more that 3 bytes */
5934     if(shCount >= 24 ) {
5935         shCount -= 24;
5936         if(shCount)
5937             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5938         else
5939             movLeft2Result(left, MSB32, result, LSB, sign);
5940         addSign(result, MSB16, sign);
5941     }
5942     else if(shCount >= 16){
5943         shCount -= 16;
5944         if(shCount)
5945             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5946         else{
5947             movLeft2Result(left, MSB24, result, LSB, 0);
5948             movLeft2Result(left, MSB32, result, MSB16, sign);
5949         }
5950         addSign(result, MSB24, sign);
5951     }
5952     else if(shCount >= 8){
5953         shCount -= 8;
5954         if(shCount == 1)
5955             shiftRLong(left, MSB16, result, sign);
5956         else if(shCount == 0){
5957             movLeft2Result(left, MSB16, result, LSB, 0);
5958             movLeft2Result(left, MSB24, result, MSB16, 0);
5959             movLeft2Result(left, MSB32, result, MSB24, sign);
5960             addSign(result, MSB32, sign);
5961         }
5962         else{
5963             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5964             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5965             /* the last shift is signed */
5966             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5967             addSign(result, MSB32, sign);
5968         }
5969     }
5970     else{   /* 1 <= shCount <= 7 */
5971         if(shCount <= 2){
5972             shiftRLong(left, LSB, result, sign);
5973             if(shCount == 2)
5974                 shiftRLong(result, LSB, result, sign);
5975         }
5976         else{
5977             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5978             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5979             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5980         }
5981     }
5982 }
5983
5984 /*-----------------------------------------------------------------*/
5985 /* genRightShiftLiteral - right shifting by known count            */
5986 /*-----------------------------------------------------------------*/
5987 static void genRightShiftLiteral (operand *left,
5988                                   operand *right,
5989                                   operand *result,
5990                                   iCode *ic,
5991                                   int sign)
5992 {    
5993     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5994     int size;
5995
5996     D(emitcode(";", "genRightShiftLiteral"););
5997
5998     freeAsmop(right,NULL,ic,TRUE);
5999
6000     aopOp(left,ic,FALSE, FALSE);
6001     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6002
6003 #if VIEW_SIZE
6004     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6005              AOP_SIZE(left));
6006 #endif
6007
6008     size = getDataSize(left);
6009     /* test the LEFT size !!! */
6010
6011     /* I suppose that the left size >= result size */
6012     if(shCount == 0){
6013         size = getDataSize(result);
6014         while(size--)
6015             movLeft2Result(left, size, result, size, 0);
6016     }
6017
6018     else if(shCount >= (size * 8)){
6019         if(sign)
6020             /* get sign in acc.7 */
6021             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6022         addSign(result, LSB, sign);
6023     } else{
6024         switch (size) {
6025             case 1:
6026                 genrshOne (result,left,shCount,sign);
6027                 break;
6028
6029             case 2:
6030                 genrshTwo (result,left,shCount,sign);
6031                 break;
6032
6033             case 4:
6034                 genrshFour (result,left,shCount,sign);
6035                 break;
6036             default :
6037                 break;
6038         }
6039
6040         freeAsmop(left,NULL,ic,TRUE);
6041         freeAsmop(result,NULL,ic,TRUE);
6042     }
6043 }
6044
6045 /*-----------------------------------------------------------------*/
6046 /* genSignedRightShift - right shift of signed number              */
6047 /*-----------------------------------------------------------------*/
6048 static void genSignedRightShift (iCode *ic)
6049 {
6050     operand *right, *left, *result;
6051     int size, offset;
6052     char *l;
6053     symbol *tlbl, *tlbl1 ;
6054
6055     D(emitcode(";", "genSignedRightShift "););
6056
6057     /* we do it the hard way put the shift count in b
6058     and loop thru preserving the sign */
6059
6060     right = IC_RIGHT(ic);
6061     left  = IC_LEFT(ic);
6062     result = IC_RESULT(ic);
6063
6064     aopOp(right,ic,FALSE, FALSE);
6065
6066     #if 0
6067     if ( AOP_TYPE(right) == AOP_LIT) {
6068         genRightShiftLiteral (left,right,result,ic,1);
6069         return ;
6070     }
6071     #endif
6072         /* shift count is unknown then we have to form 
6073        a loop get the loop count in B : Note: we take
6074        only the lower order byte since shifting
6075        more that 32 bits make no sense anyway, ( the
6076        largest size of an object can be only 32 bits ) */  
6077
6078     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6079     emitcode("inc","b");
6080     freeAsmop (right,NULL,ic,TRUE);
6081     aopOp(left,ic,FALSE, FALSE);
6082     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6083
6084     /* now move the left to the result if they are not the
6085     same */
6086     if (!sameRegs(AOP(left),AOP(result)) && 
6087         AOP_SIZE(result) > 1) {
6088
6089         size = AOP_SIZE(result);
6090         offset=0;
6091         while (size--) {
6092             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6093             if (*l == '@' && IS_AOP_PREG(result)) {
6094
6095                 emitcode("mov","a,%s",l);
6096                 aopPut(AOP(result),"a",offset);
6097             } else
6098                 aopPut(AOP(result),l,offset);
6099             offset++;
6100         }
6101     }
6102
6103     /* mov the highest order bit to OVR */    
6104     tlbl = newiTempLabel(NULL);
6105     tlbl1= newiTempLabel(NULL);
6106
6107     size = AOP_SIZE(result);
6108     offset = size - 1;
6109     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6110     emitcode("rlc","a");
6111     emitcode("mov","ov,c");
6112     /* if it is only one byte then */
6113     if (size == 1) {
6114         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6115         MOVA(l);
6116         emitcode("sjmp","%05d$",tlbl1->key+100);
6117         emitcode("","%05d$:",tlbl->key+100);
6118         emitcode("mov","c,ov");
6119         emitcode("rrc","a");
6120         emitcode("","%05d$:",tlbl1->key+100);
6121         emitcode("djnz","b,%05d$",tlbl->key+100);
6122         aopPut(AOP(result),"a",0);
6123         goto release ;
6124     }
6125
6126     reAdjustPreg(AOP(result));
6127     emitcode("sjmp","%05d$",tlbl1->key+100);
6128     emitcode("","%05d$:",tlbl->key+100);    
6129     emitcode("mov","c,ov");
6130     while (size--) {
6131         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6132         MOVA(l);
6133         emitcode("rrc","a");         
6134         aopPut(AOP(result),"a",offset--);
6135     }
6136     reAdjustPreg(AOP(result));
6137     emitcode("","%05d$:",tlbl1->key+100);
6138     emitcode("djnz","b,%05d$",tlbl->key+100);
6139
6140 release:
6141     freeAsmop(left,NULL,ic,TRUE);
6142     freeAsmop(result,NULL,ic,TRUE);
6143 }
6144
6145 /*-----------------------------------------------------------------*/
6146 /* genRightShift - generate code for right shifting                */
6147 /*-----------------------------------------------------------------*/
6148 static void genRightShift (iCode *ic)
6149 {
6150     operand *right, *left, *result;
6151     link *retype ;
6152     int size, offset;
6153     char *l;
6154     symbol *tlbl, *tlbl1 ;
6155
6156     D(emitcode(";", "genRightShift "););
6157
6158     /* if signed then we do it the hard way preserve the
6159     sign bit moving it inwards */
6160     retype = getSpec(operandType(IC_RESULT(ic)));
6161
6162     if (!SPEC_USIGN(retype)) {
6163         genSignedRightShift (ic);
6164         return ;
6165     }
6166
6167     /* signed & unsigned types are treated the same : i.e. the
6168     signed is NOT propagated inwards : quoting from the
6169     ANSI - standard : "for E1 >> E2, is equivalent to division
6170     by 2**E2 if unsigned or if it has a non-negative value,
6171     otherwise the result is implementation defined ", MY definition
6172     is that the sign does not get propagated */
6173
6174     right = IC_RIGHT(ic);
6175     left  = IC_LEFT(ic);
6176     result = IC_RESULT(ic);
6177
6178     aopOp(right,ic,FALSE, FALSE);
6179
6180     #if 0
6181     /* if the shift count is known then do it 
6182     as efficiently as possible */
6183     if (AOP_TYPE(right) == AOP_LIT) {
6184         genRightShiftLiteral (left,right,result,ic, 0);
6185         return ;
6186     }
6187     #endif
6188
6189     /* shift count is unknown then we have to form 
6190     a loop get the loop count in B : Note: we take
6191     only the lower order byte since shifting
6192     more that 32 bits make no sense anyway, ( the
6193     largest size of an object can be only 32 bits ) */  
6194
6195     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6196     emitcode("inc","b");
6197     freeAsmop (right,NULL,ic,TRUE);
6198     aopOp(left,ic,FALSE, FALSE);
6199     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6200
6201     /* now move the left to the result if they are not the
6202     same */
6203     if (!sameRegs(AOP(left),AOP(result)) && 
6204         AOP_SIZE(result) > 1) {
6205
6206         size = AOP_SIZE(result);
6207         offset=0;
6208         while (size--) {
6209             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6210             if (*l == '@' && IS_AOP_PREG(result)) {
6211
6212                 emitcode("mov","a,%s",l);
6213                 aopPut(AOP(result),"a",offset);
6214             } else
6215                 aopPut(AOP(result),l,offset);
6216             offset++;
6217         }
6218     }
6219
6220     tlbl = newiTempLabel(NULL);
6221     tlbl1= newiTempLabel(NULL);
6222     size = AOP_SIZE(result);
6223     offset = size - 1;
6224
6225     /* if it is only one byte then */
6226     if (size == 1) {
6227         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6228         MOVA(l);
6229         emitcode("sjmp","%05d$",tlbl1->key+100);
6230         emitcode("","%05d$:",tlbl->key+100);
6231         CLRC;
6232         emitcode("rrc","a");
6233         emitcode("","%05d$:",tlbl1->key+100);
6234         emitcode("djnz","b,%05d$",tlbl->key+100);
6235         aopPut(AOP(result),"a",0);
6236         goto release ;
6237     }
6238
6239     reAdjustPreg(AOP(result));
6240     emitcode("sjmp","%05d$",tlbl1->key+100);
6241     emitcode("","%05d$:",tlbl->key+100);    
6242     CLRC;
6243     while (size--) {
6244         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6245         MOVA(l);
6246         emitcode("rrc","a");         
6247         aopPut(AOP(result),"a",offset--);
6248     }
6249     reAdjustPreg(AOP(result));
6250
6251     emitcode("","%05d$:",tlbl1->key+100);
6252     emitcode("djnz","b,%05d$",tlbl->key+100);
6253
6254 release:
6255     freeAsmop(left,NULL,ic,TRUE);
6256     freeAsmop(result,NULL,ic,TRUE);
6257 }
6258
6259 /*-----------------------------------------------------------------*/
6260 /* genUnpackBits - generates code for unpacking bits               */
6261 /*-----------------------------------------------------------------*/
6262 static void genUnpackBits (operand *result, char *rname, int ptype)
6263 {    
6264     int shCnt ;
6265     int rlen = 0 ;
6266     link *etype;
6267     int offset = 0 ;
6268
6269     D(emitcode(";", "genUnpackBits "););
6270
6271     etype = getSpec(operandType(result));
6272
6273     /* read the first byte  */
6274     switch (ptype) {
6275
6276     case POINTER:
6277     case IPOINTER:
6278         emitcode("mov","a,@%s",rname);
6279         break;
6280         
6281     case PPOINTER:
6282         emitcode("movx","a,@%s",rname);
6283         break;
6284         
6285     case FPOINTER:
6286         emitcode("movx","a,@dptr");
6287         break;
6288
6289     case CPOINTER:
6290         emitcode("clr","a");
6291         emitcode("movc","a","@a+dptr");
6292         break;
6293
6294     case GPOINTER:
6295         emitcode("lcall","__gptrget");
6296         break;
6297     }
6298
6299     /* if we have bitdisplacement then it fits   */
6300     /* into this byte completely or if length is */
6301     /* less than a byte                          */
6302     if ((shCnt = SPEC_BSTR(etype)) || 
6303         (SPEC_BLEN(etype) <= 8))  {
6304
6305         /* shift right acc */
6306         AccRsh(shCnt);
6307
6308         emitcode("anl","a,#0x%02x",
6309                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6310         aopPut(AOP(result),"a",offset);
6311         return ;
6312     }
6313
6314     /* bit field did not fit in a byte  */
6315     rlen = SPEC_BLEN(etype) - 8;
6316     aopPut(AOP(result),"a",offset++);
6317
6318     while (1)  {
6319
6320         switch (ptype) {
6321         case POINTER:
6322         case IPOINTER:
6323             emitcode("inc","%s",rname);
6324             emitcode("mov","a,@%s",rname);
6325             break;
6326             
6327         case PPOINTER:
6328             emitcode("inc","%s",rname);
6329             emitcode("movx","a,@%s",rname);
6330             break;
6331
6332         case FPOINTER:
6333             emitcode("inc","dptr");
6334             emitcode("movx","a,@dptr");
6335             break;
6336             
6337         case CPOINTER:
6338             emitcode("clr","a");
6339             emitcode("inc","dptr");
6340             emitcode("movc","a","@a+dptr");
6341             break;
6342             
6343         case GPOINTER:
6344             emitcode("inc","dptr");
6345             emitcode("lcall","__gptrget");
6346             break;
6347         }
6348
6349         rlen -= 8;            
6350         /* if we are done */
6351         if ( rlen <= 0 )
6352             break ;
6353         
6354         aopPut(AOP(result),"a",offset++);
6355                               
6356     }
6357     
6358     if (rlen) {
6359         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6360         aopPut(AOP(result),"a",offset);        
6361     }
6362     
6363     return ;
6364 }
6365
6366
6367 /*-----------------------------------------------------------------*/
6368 /* genDataPointerGet - generates code when ptr offset is known     */
6369 /*-----------------------------------------------------------------*/
6370 static void genDataPointerGet (operand *left, 
6371                                operand *result, 
6372                                iCode *ic)
6373 {
6374     char *l;
6375     char buffer[256];
6376     int size , offset = 0;
6377     aopOp(result,ic,TRUE, FALSE);
6378
6379     /* get the string representation of the name */
6380     l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6381     size = AOP_SIZE(result);
6382     while (size--) {
6383         if (offset)
6384             sprintf(buffer,"(%s + %d)",l+1,offset);
6385         else
6386             sprintf(buffer,"%s",l+1);
6387         aopPut(AOP(result),buffer,offset++);
6388     }
6389
6390     freeAsmop(left,NULL,ic,TRUE);
6391     freeAsmop(result,NULL,ic,TRUE);
6392 }
6393
6394 /*-----------------------------------------------------------------*/
6395 /* genNearPointerGet - emitcode for near pointer fetch             */
6396 /*-----------------------------------------------------------------*/
6397 static void genNearPointerGet (operand *left, 
6398                                operand *result, 
6399                                iCode *ic)
6400 {
6401     asmop *aop = NULL;
6402     regs *preg = NULL ;
6403     char *rname ;
6404     link *rtype, *retype;
6405     link *ltype = operandType(left);    
6406     char buffer[80];
6407
6408     rtype = operandType(result);
6409     retype= getSpec(rtype);
6410     
6411     aopOp(left,ic,FALSE, FALSE);
6412     
6413     /* if left is rematerialisable and
6414        result is not bit variable type and
6415        the left is pointer to data space i.e
6416        lower 128 bytes of space */
6417     if (AOP_TYPE(left) == AOP_IMMD &&
6418         !IS_BITVAR(retype)         &&
6419         DCL_TYPE(ltype) == POINTER) {
6420         genDataPointerGet (left,result,ic);
6421         return ;
6422     }
6423     
6424         /* if the value is already in a pointer register
6425        then don't need anything more */
6426     if (!AOP_INPREG(AOP(left))) {
6427         /* otherwise get a free pointer register */
6428         aop = newAsmop(0);
6429         preg = getFreePtr(ic,&aop,FALSE);
6430         emitcode("mov","%s,%s",
6431                 preg->name,
6432                 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6433         rname = preg->name ;
6434     } else
6435         rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6436     
6437     freeAsmop(left,NULL,ic,TRUE);
6438     aopOp (result,ic,FALSE, FALSE);
6439     
6440       /* if bitfield then unpack the bits */
6441     if (IS_BITVAR(retype)) 
6442         genUnpackBits (result,rname,POINTER);
6443     else {
6444         /* we have can just get the values */
6445         int size = AOP_SIZE(result);
6446         int offset = 0 ;        
6447         
6448         while (size--) {
6449             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6450
6451                 emitcode("mov","a,@%s",rname);
6452                 aopPut(AOP(result),"a",offset);
6453             } else {
6454                 sprintf(buffer,"@%s",rname);
6455                 aopPut(AOP(result),buffer,offset);
6456             }
6457             offset++ ;
6458             if (size)
6459                 emitcode("inc","%s",rname);
6460         }
6461     }
6462
6463     /* now some housekeeping stuff */
6464     if (aop) {
6465         /* we had to allocate for this iCode */
6466         freeAsmop(NULL,aop,ic,TRUE);
6467     } else { 
6468         /* we did not allocate which means left
6469            already in a pointer register, then
6470            if size > 0 && this could be used again
6471            we have to point it back to where it 
6472            belongs */
6473         if (AOP_SIZE(result) > 1 &&
6474             !OP_SYMBOL(left)->remat &&
6475             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6476               ic->depth )) {
6477             int size = AOP_SIZE(result) - 1;
6478             while (size--)
6479                 emitcode("dec","%s",rname);
6480         }
6481     }
6482
6483     /* done */
6484     freeAsmop(result,NULL,ic,TRUE);
6485      
6486 }
6487
6488 /*-----------------------------------------------------------------*/
6489 /* genPagedPointerGet - emitcode for paged pointer fetch           */
6490 /*-----------------------------------------------------------------*/
6491 static void genPagedPointerGet (operand *left, 
6492                                operand *result, 
6493                                iCode *ic)
6494 {
6495     asmop *aop = NULL;
6496     regs *preg = NULL ;
6497     char *rname ;
6498     link *rtype, *retype;    
6499
6500     rtype = operandType(result);
6501     retype= getSpec(rtype);
6502     
6503     aopOp(left,ic,FALSE, FALSE);
6504
6505   /* if the value is already in a pointer register
6506        then don't need anything more */
6507     if (!AOP_INPREG(AOP(left))) {
6508         /* otherwise get a free pointer register */
6509         aop = newAsmop(0);
6510         preg = getFreePtr(ic,&aop,FALSE);
6511         emitcode("mov","%s,%s",
6512                 preg->name,
6513                 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6514         rname = preg->name ;
6515     } else
6516         rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6517     
6518     freeAsmop(left,NULL,ic,TRUE);
6519     aopOp (result,ic,FALSE, FALSE);
6520
6521     /* if bitfield then unpack the bits */
6522     if (IS_BITVAR(retype)) 
6523         genUnpackBits (result,rname,PPOINTER);
6524     else {
6525         /* we have can just get the values */
6526         int size = AOP_SIZE(result);
6527         int offset = 0 ;        
6528         
6529         while (size--) {
6530             
6531             emitcode("movx","a,@%s",rname);
6532             aopPut(AOP(result),"a",offset);
6533             
6534             offset++ ;
6535             
6536             if (size)
6537                 emitcode("inc","%s",rname);
6538         }
6539     }
6540
6541     /* now some housekeeping stuff */
6542     if (aop) {
6543         /* we had to allocate for this iCode */
6544         freeAsmop(NULL,aop,ic,TRUE);
6545     } else { 
6546         /* we did not allocate which means left
6547            already in a pointer register, then
6548            if size > 0 && this could be used again
6549            we have to point it back to where it 
6550            belongs */
6551         if (AOP_SIZE(result) > 1 &&
6552             !OP_SYMBOL(left)->remat &&
6553             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6554               ic->depth )) {
6555             int size = AOP_SIZE(result) - 1;
6556             while (size--)
6557                 emitcode("dec","%s",rname);
6558         }
6559     }
6560
6561     /* done */
6562     freeAsmop(result,NULL,ic,TRUE);
6563     
6564         
6565 }
6566
6567 /*-----------------------------------------------------------------*/
6568 /* genFarPointerGet - gget value from far space                    */
6569 /*-----------------------------------------------------------------*/
6570 static void genFarPointerGet (operand *left,
6571                               operand *result, iCode *ic)
6572 {
6573     int size, offset ;
6574     link *retype = getSpec(operandType(result));
6575
6576     D(emitcode(";", "genFarPointerGet"););
6577
6578     aopOp(left,ic,FALSE, FALSE);
6579
6580     /* if the operand is already in dptr 
6581     then we do nothing else we move the value to dptr */
6582     if (AOP_TYPE(left) != AOP_STR) {
6583         /* if this is remateriazable */
6584         if (AOP_TYPE(left) == AOP_IMMD)
6585         {
6586             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6587         }
6588         else 
6589         { 
6590             /* we need to get it byte by byte */
6591             if (AOP_TYPE(left) != AOP_DPTR)
6592             {
6593                 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6594                 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6595                 if (options.model == MODEL_FLAT24)
6596                 {
6597                     emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6598                 }
6599             }
6600             else
6601             {
6602                  /* We need to generate a load to DPTR indirect through DPTR. */
6603                  D(emitcode(";", "genFarPointerGet -- indirection special case."););
6604                  emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6605                  emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6606                  emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6607                  emitcode("pop", "dph");
6608                  emitcode("pop", "dpl");
6609             }
6610         }
6611     }
6612     /* so dptr know contains the address */
6613     freeAsmop(left,NULL,ic,TRUE);
6614     aopOp(result,ic,FALSE, TRUE);
6615
6616     /* if bit then unpack */
6617     if (IS_BITVAR(retype)) 
6618         genUnpackBits(result,"dptr",FPOINTER);
6619     else {
6620         size = AOP_SIZE(result);
6621         offset = 0 ;
6622
6623         while (size--) {
6624             emitcode("movx","a,@dptr");
6625             aopPut(AOP(result),"a",offset++);
6626             if (size)
6627                 emitcode("inc","dptr");
6628         }
6629     }
6630
6631     freeAsmop(result,NULL,ic,TRUE);
6632 }
6633
6634 /*-----------------------------------------------------------------*/
6635 /* emitcodePointerGet - gget value from code space                  */
6636 /*-----------------------------------------------------------------*/
6637 static void emitcodePointerGet (operand *left,
6638                                 operand *result, iCode *ic)
6639 {
6640     int size, offset ;
6641     link *retype = getSpec(operandType(result));
6642
6643     aopOp(left,ic,FALSE, FALSE);
6644
6645     /* if the operand is already in dptr 
6646     then we do nothing else we move the value to dptr */
6647     if (AOP_TYPE(left) != AOP_STR) {
6648         /* if this is remateriazable */
6649         if (AOP_TYPE(left) == AOP_IMMD)
6650             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6651         else { /* we need to get it byte by byte */
6652             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6653             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6654             if (options.model == MODEL_FLAT24)
6655             {
6656                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6657             }
6658         }
6659     }
6660     /* so dptr know contains the address */
6661     freeAsmop(left,NULL,ic,TRUE);
6662     aopOp(result,ic,FALSE, FALSE);
6663
6664     /* if bit then unpack */
6665     if (IS_BITVAR(retype)) 
6666         genUnpackBits(result,"dptr",CPOINTER);
6667     else {
6668         size = AOP_SIZE(result);
6669         offset = 0 ;
6670
6671         while (size--) {
6672             emitcode("clr","a");
6673             emitcode("movc","a,@a+dptr");
6674             aopPut(AOP(result),"a",offset++);
6675             if (size)
6676                 emitcode("inc","dptr");
6677         }
6678     }
6679
6680     freeAsmop(result,NULL,ic,TRUE);
6681 }
6682
6683 /*-----------------------------------------------------------------*/
6684 /* genGenPointerGet - gget value from generic pointer space        */
6685 /*-----------------------------------------------------------------*/
6686 static void genGenPointerGet (operand *left,
6687                               operand *result, iCode *ic)
6688 {
6689     int size, offset ;
6690     link *retype = getSpec(operandType(result));
6691
6692     aopOp(left,ic,FALSE, TRUE);
6693
6694     /* if the operand is already in dptr 
6695     then we do nothing else we move the value to dptr */
6696     if (AOP_TYPE(left) != AOP_STR) {
6697         /* if this is remateriazable */
6698         if (AOP_TYPE(left) == AOP_IMMD) {
6699             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6700             emitcode("mov","b,#%d",pointerCode(retype));
6701         }
6702         else { /* we need to get it byte by byte */
6703             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6704             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6705             if (options.model == MODEL_FLAT24)
6706             {
6707                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6708                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
6709             }
6710             else
6711             {
6712                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6713             }
6714         }
6715     }
6716     /* so dptr know contains the address */
6717     freeAsmop(left,NULL,ic,TRUE);
6718     aopOp(result,ic,FALSE, TRUE);
6719
6720     /* if bit then unpack */
6721     if (IS_BITVAR(retype)) 
6722         genUnpackBits(result,"dptr",GPOINTER);
6723     else {
6724         size = AOP_SIZE(result);
6725         offset = 0 ;
6726
6727         while (size--) {
6728             emitcode("lcall","__gptrget");
6729             aopPut(AOP(result),"a",offset++);
6730             if (size)
6731                 emitcode("inc","dptr");
6732         }
6733     }
6734
6735     freeAsmop(result,NULL,ic,TRUE);
6736 }
6737
6738 /*-----------------------------------------------------------------*/
6739 /* genPointerGet - generate code for pointer get                   */
6740 /*-----------------------------------------------------------------*/
6741 static void genPointerGet (iCode *ic)
6742 {
6743     operand *left, *result ;
6744     link *type, *etype;
6745     int p_type;
6746
6747     D(emitcode(";", "genPointerGet "););
6748
6749     left = IC_LEFT(ic);
6750     result = IC_RESULT(ic) ;
6751
6752     /* depending on the type of pointer we need to
6753     move it to the correct pointer register */
6754     type = operandType(left);
6755     etype = getSpec(type);
6756     /* if left is of type of pointer then it is simple */
6757     if (IS_PTR(type) && !IS_FUNC(type->next)) 
6758         p_type = DCL_TYPE(type);
6759     else {
6760         /* we have to go by the storage class */
6761         p_type = PTR_TYPE(SPEC_OCLS(etype));
6762
6763 /*      if (SPEC_OCLS(etype)->codesp ) { */
6764 /*          p_type = CPOINTER ;  */
6765 /*      } */
6766 /*      else */
6767 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6768 /*              p_type = FPOINTER ; */
6769 /*          else */
6770 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6771 /*                  p_type = PPOINTER; */
6772 /*              else */
6773 /*                  if (SPEC_OCLS(etype) == idata ) */
6774 /*                      p_type = IPOINTER; */
6775 /*                  else */
6776 /*                      p_type = POINTER ; */
6777     }
6778
6779     /* now that we have the pointer type we assign
6780     the pointer values */
6781     switch (p_type) {
6782
6783     case POINTER:       
6784     case IPOINTER:
6785         genNearPointerGet (left,result,ic);
6786         break;
6787
6788     case PPOINTER:
6789         genPagedPointerGet(left,result,ic);
6790         break;
6791
6792     case FPOINTER:
6793         genFarPointerGet (left,result,ic);
6794         break;
6795
6796     case CPOINTER:
6797         emitcodePointerGet (left,result,ic);
6798         break;
6799
6800     case GPOINTER:
6801         genGenPointerGet (left,result,ic);
6802         break;
6803     }
6804
6805 }
6806
6807 /*-----------------------------------------------------------------*/
6808 /* genPackBits - generates code for packed bit storage             */
6809 /*-----------------------------------------------------------------*/
6810 static void genPackBits (link    *etype ,
6811                          operand *right ,
6812                          char *rname, int p_type)
6813 {
6814     int shCount = 0 ;
6815     int offset = 0  ;
6816     int rLen = 0 ;
6817     int blen, bstr ;   
6818     char *l ;
6819
6820     blen = SPEC_BLEN(etype);
6821     bstr = SPEC_BSTR(etype);
6822
6823     l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
6824     MOVA(l);   
6825
6826     /* if the bit lenth is less than or    */
6827     /* it exactly fits a byte then         */
6828     if (SPEC_BLEN(etype) <= 8 )  {
6829         shCount = SPEC_BSTR(etype) ;
6830
6831         /* shift left acc */
6832         AccLsh(shCount);
6833
6834         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6835
6836
6837             switch (p_type) {
6838                 case POINTER:
6839                     emitcode ("mov","b,a");
6840                     emitcode("mov","a,@%s",rname);
6841                     break;
6842
6843                 case FPOINTER:
6844                     emitcode ("mov","b,a");
6845                     emitcode("movx","a,@dptr");
6846                     break;
6847
6848                 case GPOINTER:
6849                     emitcode ("push","b");
6850                     emitcode ("push","acc");
6851                     emitcode ("lcall","__gptrget");
6852                     emitcode ("pop","b");
6853                     break;
6854             }
6855
6856             emitcode ("anl","a,#0x%02x",(unsigned char)
6857                       ((unsigned char)(0xFF << (blen+bstr)) | 
6858                        (unsigned char)(0xFF >> (8-bstr)) ) );
6859             emitcode ("orl","a,b");
6860             if (p_type == GPOINTER)
6861                 emitcode("pop","b");
6862         }
6863     }
6864
6865     switch (p_type) {
6866         case POINTER:
6867             emitcode("mov","@%s,a",rname);
6868             break;
6869
6870         case FPOINTER:
6871             emitcode("movx","@dptr,a");
6872             break;
6873
6874         case GPOINTER:
6875             emitcode("lcall","__gptrput");
6876             break;
6877     }
6878
6879     /* if we r done */
6880     if ( SPEC_BLEN(etype) <= 8 )
6881         return ;
6882
6883     emitcode("inc","%s",rname);
6884     rLen = SPEC_BLEN(etype) ;     
6885
6886     /* now generate for lengths greater than one byte */
6887     while (1) {
6888
6889         l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
6890
6891         rLen -= 8 ;
6892         if (rLen <= 0 )
6893             break ;
6894
6895         switch (p_type) {
6896             case POINTER:
6897                 if (*l == '@') {
6898                     MOVA(l);
6899                     emitcode("mov","@%s,a",rname);
6900                 } else
6901                     emitcode("mov","@%s,%s",rname,l);
6902                 break;
6903
6904             case FPOINTER:
6905                 MOVA(l);
6906                 emitcode("movx","@dptr,a");
6907                 break;
6908
6909             case GPOINTER:
6910                 MOVA(l);
6911                 emitcode("lcall","__gptrput");
6912                 break;  
6913         }   
6914         emitcode ("inc","%s",rname);
6915     }
6916
6917     MOVA(l);
6918
6919     /* last last was not complete */
6920     if (rLen)   {
6921         /* save the byte & read byte */
6922         switch (p_type) {
6923             case POINTER:
6924                 emitcode ("mov","b,a");
6925                 emitcode("mov","a,@%s",rname);
6926                 break;
6927
6928             case FPOINTER:
6929                 emitcode ("mov","b,a");
6930                 emitcode("movx","a,@dptr");
6931                 break;
6932
6933             case GPOINTER:
6934                 emitcode ("push","b");
6935                 emitcode ("push","acc");
6936                 emitcode ("lcall","__gptrget");
6937                 emitcode ("pop","b");
6938                 break;
6939         }
6940
6941         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6942         emitcode ("orl","a,b");
6943     }
6944
6945     if (p_type == GPOINTER)
6946         emitcode("pop","b");
6947
6948     switch (p_type) {
6949
6950     case POINTER:
6951         emitcode("mov","@%s,a",rname);
6952         break;
6953         
6954     case FPOINTER:
6955         emitcode("movx","@dptr,a");
6956         break;
6957         
6958     case GPOINTER:
6959         emitcode("lcall","__gptrput");
6960         break;                  
6961     }
6962 }
6963 /*-----------------------------------------------------------------*/
6964 /* genDataPointerSet - remat pointer to data space                 */
6965 /*-----------------------------------------------------------------*/
6966 static void genDataPointerSet(operand *right,
6967                               operand *result,
6968                               iCode *ic)
6969 {
6970     int size, offset = 0 ;
6971     char *l, buffer[256];
6972
6973     aopOp(right,ic,FALSE, FALSE);
6974     
6975     l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
6976     size = AOP_SIZE(right);
6977     while (size--) {
6978         if (offset)
6979             sprintf(buffer,"(%s + %d)",l+1,offset);
6980         else
6981             sprintf(buffer,"%s",l+1);
6982         emitcode("mov","%s,%s",buffer,
6983                  aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
6984     }
6985
6986     freeAsmop(right,NULL,ic,TRUE);
6987     freeAsmop(result,NULL,ic,TRUE);
6988 }
6989
6990 /*-----------------------------------------------------------------*/
6991 /* genNearPointerSet - emitcode for near pointer put                */
6992 /*-----------------------------------------------------------------*/
6993 static void genNearPointerSet (operand *right,
6994                                operand *result, 
6995                                iCode *ic)
6996 {
6997     asmop *aop = NULL;
6998     regs *preg = NULL ;
6999     char *rname , *l;
7000     link *retype;
7001     link *ptype = operandType(result);
7002     
7003     retype= getSpec(operandType(right));
7004
7005     aopOp(result,ic,FALSE, FALSE);
7006     
7007     /* if the result is rematerializable &
7008        in data space & not a bit variable */
7009     if (AOP_TYPE(result) == AOP_IMMD &&
7010         DCL_TYPE(ptype) == POINTER   &&
7011         !IS_BITVAR(retype)) {
7012         genDataPointerSet (right,result,ic);
7013         return;
7014     }
7015
7016     /* if the value is already in a pointer register
7017     then don't need anything more */
7018     if (!AOP_INPREG(AOP(result))) {
7019         /* otherwise get a free pointer register */
7020         aop = newAsmop(0);
7021         preg = getFreePtr(ic,&aop,FALSE);
7022         emitcode("mov","%s,%s",
7023                  preg->name,
7024                  aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7025         rname = preg->name ;
7026     } else
7027         rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7028
7029     freeAsmop(result,NULL,ic,TRUE);
7030     aopOp (right,ic,FALSE, FALSE);
7031
7032     /* if bitfield then unpack the bits */
7033     if (IS_BITVAR(retype)) 
7034         genPackBits (retype,right,rname,POINTER);
7035     else {
7036         /* we have can just get the values */
7037         int size = AOP_SIZE(right);
7038         int offset = 0 ;    
7039
7040         while (size--) {
7041             l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7042             if (*l == '@' ) {
7043                 MOVA(l);
7044                 emitcode("mov","@%s,a",rname);
7045             } else
7046                 emitcode("mov","@%s,%s",rname,l);
7047             if (size)
7048                 emitcode("inc","%s",rname);
7049             offset++;
7050         }
7051     }
7052
7053     /* now some housekeeping stuff */
7054     if (aop) {
7055         /* we had to allocate for this iCode */
7056         freeAsmop(NULL,aop,ic,TRUE);
7057     } else { 
7058         /* we did not allocate which means left
7059         already in a pointer register, then
7060         if size > 0 && this could be used again
7061         we have to point it back to where it 
7062         belongs */
7063         if (AOP_SIZE(right) > 1 &&
7064             !OP_SYMBOL(result)->remat &&
7065             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7066               ic->depth )) {
7067             int size = AOP_SIZE(right) - 1;
7068             while (size--)
7069                 emitcode("dec","%s",rname);
7070         }
7071     }
7072
7073     /* done */
7074     freeAsmop(right,NULL,ic,TRUE);
7075
7076
7077 }
7078
7079 /*-----------------------------------------------------------------*/
7080 /* genPagedPointerSet - emitcode for Paged pointer put             */
7081 /*-----------------------------------------------------------------*/
7082 static void genPagedPointerSet (operand *right,
7083                                operand *result, 
7084                                iCode *ic)
7085 {
7086     asmop *aop = NULL;
7087     regs *preg = NULL ;
7088     char *rname , *l;
7089     link *retype;
7090        
7091     retype= getSpec(operandType(right));
7092     
7093     aopOp(result,ic,FALSE, FALSE);
7094     
7095     /* if the value is already in a pointer register
7096        then don't need anything more */
7097     if (!AOP_INPREG(AOP(result))) {
7098         /* otherwise get a free pointer register */
7099         aop = newAsmop(0);
7100         preg = getFreePtr(ic,&aop,FALSE);
7101         emitcode("mov","%s,%s",
7102                 preg->name,
7103                 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7104         rname = preg->name ;
7105     } else
7106         rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7107     
7108     freeAsmop(result,NULL,ic,TRUE);
7109     aopOp (right,ic,FALSE, FALSE);
7110
7111     /* if bitfield then unpack the bits */
7112     if (IS_BITVAR(retype)) 
7113         genPackBits (retype,right,rname,PPOINTER);
7114     else {
7115         /* we have can just get the values */
7116         int size = AOP_SIZE(right);
7117         int offset = 0 ;        
7118         
7119         while (size--) {
7120             l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7121             
7122             MOVA(l);
7123             emitcode("movx","@%s,a",rname);
7124
7125             if (size)
7126                 emitcode("inc","%s",rname);
7127
7128             offset++;
7129         }
7130     }
7131     
7132     /* now some housekeeping stuff */
7133     if (aop) {
7134         /* we had to allocate for this iCode */
7135         freeAsmop(NULL,aop,ic,TRUE);
7136     } else { 
7137         /* we did not allocate which means left
7138            already in a pointer register, then
7139            if size > 0 && this could be used again
7140            we have to point it back to where it 
7141            belongs */
7142         if (AOP_SIZE(right) > 1 &&
7143             !OP_SYMBOL(result)->remat &&
7144             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7145               ic->depth )) {
7146             int size = AOP_SIZE(right) - 1;
7147             while (size--)
7148                 emitcode("dec","%s",rname);
7149         }
7150     }
7151
7152     /* done */
7153     freeAsmop(right,NULL,ic,TRUE);
7154     
7155         
7156 }
7157
7158 /*-----------------------------------------------------------------*/
7159 /* genFarPointerSet - set value from far space                     */
7160 /*-----------------------------------------------------------------*/
7161 static void genFarPointerSet (operand *right,
7162                               operand *result, iCode *ic)
7163 {
7164     int size, offset ;
7165     link *retype = getSpec(operandType(right));
7166
7167     aopOp(result,ic,FALSE, FALSE);
7168
7169     /* if the operand is already in dptr 
7170     then we do nothing else we move the value to dptr */
7171     if (AOP_TYPE(result) != AOP_STR) {
7172         /* if this is remateriazable */
7173         if (AOP_TYPE(result) == AOP_IMMD)
7174             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7175         else 
7176         {
7177             /* we need to get it byte by byte */
7178             if (AOP_TYPE(result) != AOP_DPTR)
7179             {
7180                 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7181                 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7182                 if (options.model == MODEL_FLAT24)
7183                 {
7184                     emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7185                 }
7186             }
7187             else
7188             {
7189                  /* We need to generate a load to DPTR indirect through DPTR. */
7190                  D(emitcode(";", "genFarPointerSet -- indirection special case."););
7191                  emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7192                  emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7193                  emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7194                  emitcode("pop", "dph");
7195                  emitcode("pop", "dpl");
7196             }
7197         }
7198     }
7199     /* so dptr know contains the address */
7200     freeAsmop(result,NULL,ic,TRUE);
7201     aopOp(right,ic,FALSE, TRUE);
7202
7203     /* if bit then unpack */
7204     if (IS_BITVAR(retype)) 
7205         genPackBits(retype,right,"dptr",FPOINTER);
7206     else {
7207         size = AOP_SIZE(right);
7208         offset = 0 ;
7209
7210         while (size--) {
7211             char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7212             MOVA(l);
7213             emitcode("movx","@dptr,a");
7214             if (size)
7215                 emitcode("inc","dptr");
7216         }
7217     }
7218
7219     freeAsmop(right,NULL,ic,TRUE);
7220 }
7221
7222 /*-----------------------------------------------------------------*/
7223 /* genGenPointerSet - set value from generic pointer space         */
7224 /*-----------------------------------------------------------------*/
7225 static void genGenPointerSet (operand *right,
7226                               operand *result, iCode *ic)
7227 {
7228     int size, offset ;
7229     link *retype = getSpec(operandType(right));
7230
7231     aopOp(result,ic,FALSE, TRUE);
7232
7233     /* if the operand is already in dptr 
7234     then we do nothing else we move the value to dptr */
7235     if (AOP_TYPE(result) != AOP_STR) {
7236         /* if this is remateriazable */
7237         if (AOP_TYPE(result) == AOP_IMMD) {
7238             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7239             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7240         }
7241         else { /* we need to get it byte by byte */
7242             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7243             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7244             if (options.model == MODEL_FLAT24)
7245             {
7246                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7247                emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7248             }
7249             else
7250             {
7251                 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7252             }
7253         }
7254     }
7255     /* so dptr know contains the address */
7256     freeAsmop(result,NULL,ic,TRUE);
7257     aopOp(right,ic,FALSE, TRUE);
7258
7259     /* if bit then unpack */
7260     if (IS_BITVAR(retype)) 
7261         genPackBits(retype,right,"dptr",GPOINTER);
7262     else {
7263         size = AOP_SIZE(right);
7264         offset = 0 ;
7265
7266         while (size--) {
7267             char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7268             MOVA(l);
7269             emitcode("lcall","__gptrput");
7270             if (size)
7271                 emitcode("inc","dptr");
7272         }
7273     }
7274
7275     freeAsmop(right,NULL,ic,TRUE);
7276 }
7277
7278 /*-----------------------------------------------------------------*/
7279 /* genPointerSet - stores the value into a pointer location        */
7280 /*-----------------------------------------------------------------*/
7281 static void genPointerSet (iCode *ic)
7282 {    
7283     operand *right, *result ;
7284     link *type, *etype;
7285     int p_type;
7286
7287     D(emitcode(";", "genPointerSet "););
7288
7289     right = IC_RIGHT(ic);
7290     result = IC_RESULT(ic) ;
7291
7292     /* depending on the type of pointer we need to
7293     move it to the correct pointer register */
7294     type = operandType(result);
7295     etype = getSpec(type);
7296     /* if left is of type of pointer then it is simple */
7297     if (IS_PTR(type) && !IS_FUNC(type->next)) {
7298         p_type = DCL_TYPE(type);
7299     }
7300     else {
7301         /* we have to go by the storage class */
7302         p_type = PTR_TYPE(SPEC_OCLS(etype));
7303
7304 /*      if (SPEC_OCLS(etype)->codesp ) { */
7305 /*          p_type = CPOINTER ;  */
7306 /*      } */
7307 /*      else */
7308 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7309 /*              p_type = FPOINTER ; */
7310 /*          else */
7311 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7312 /*                  p_type = PPOINTER ; */
7313 /*              else */
7314 /*                  if (SPEC_OCLS(etype) == idata ) */
7315 /*                      p_type = IPOINTER ; */
7316 /*                  else */
7317 /*                      p_type = POINTER ; */
7318     }
7319
7320     /* now that we have the pointer type we assign
7321     the pointer values */
7322     switch (p_type) {
7323
7324     case POINTER:
7325     case IPOINTER:
7326         genNearPointerSet (right,result,ic);
7327         break;
7328
7329     case PPOINTER:
7330         genPagedPointerSet (right,result,ic);
7331         break;
7332
7333     case FPOINTER:
7334         genFarPointerSet (right,result,ic);
7335         break;
7336
7337     case GPOINTER:
7338         genGenPointerSet (right,result,ic);
7339         break;
7340     }
7341
7342 }
7343
7344 /*-----------------------------------------------------------------*/
7345 /* genIfx - generate code for Ifx statement                        */
7346 /*-----------------------------------------------------------------*/
7347 static void genIfx (iCode *ic, iCode *popIc)
7348 {
7349     operand *cond = IC_COND(ic);
7350     int isbit =0;
7351
7352     D(emitcode(";", "genIfx "););
7353
7354     aopOp(cond,ic,FALSE, FALSE);
7355
7356     /* get the value into acc */
7357     if (AOP_TYPE(cond) != AOP_CRY)
7358         toBoolean(cond);
7359     else
7360         isbit = 1;
7361     /* the result is now in the accumulator */
7362     freeAsmop(cond,NULL,ic,TRUE);
7363
7364     /* if there was something to be popped then do it */
7365     if (popIc)
7366         genIpop(popIc);
7367
7368     /* if the condition is  a bit variable */
7369     if (isbit && IS_ITEMP(cond) && 
7370         SPIL_LOC(cond))
7371         genIfxJump(ic,SPIL_LOC(cond)->rname);
7372     else
7373         if (isbit && !IS_ITEMP(cond))
7374             genIfxJump(ic,OP_SYMBOL(cond)->rname);
7375         else
7376             genIfxJump(ic,"a");
7377
7378     ic->generated = 1;
7379 }
7380
7381 /*-----------------------------------------------------------------*/
7382 /* genAddrOf - generates code for address of                       */
7383 /*-----------------------------------------------------------------*/
7384 static void genAddrOf (iCode *ic)
7385 {
7386     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7387     int size, offset ;
7388
7389     D(emitcode(";", "genAddrOf "););
7390
7391     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7392
7393     /* if the operand is on the stack then we 
7394     need to get the stack offset of this
7395     variable */
7396     if (sym->onStack) {
7397         /* if it has an offset then we need to compute
7398         it */
7399         if (sym->stack) {
7400             emitcode("mov","a,_bp");
7401             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7402             aopPut(AOP(IC_RESULT(ic)),"a",0);       
7403         } else {
7404             /* we can just move _bp */
7405             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7406         }
7407         /* fill the result with zero */
7408         size = AOP_SIZE(IC_RESULT(ic)) - 1;
7409         
7410         
7411         if (options.stack10bit && size < (FPTRSIZE - 1))
7412         {
7413             fprintf(stderr, 
7414                     "*** warning: pointer to stack var truncated.\n");
7415         }
7416         
7417         offset = 1;
7418         while (size--)
7419         {
7420             /* Yuck! */
7421             if (options.stack10bit && offset == 2)
7422             {
7423                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7424             }
7425             else
7426             {
7427                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7428             }
7429         }
7430
7431         goto release;
7432     }
7433
7434     /* object not on stack then we need the name */
7435     size = AOP_SIZE(IC_RESULT(ic));
7436     offset = 0;
7437
7438     while (size--) {
7439         char s[SDCC_NAME_MAX];
7440         if (offset) 
7441             sprintf(s,"#(%s >> %d)",
7442                     sym->rname,
7443                     offset*8);
7444         else
7445             sprintf(s,"#%s",sym->rname);
7446         aopPut(AOP(IC_RESULT(ic)),s,offset++);
7447     }
7448
7449 release:
7450     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7451
7452 }
7453
7454 /*-----------------------------------------------------------------*/
7455 /* genFarFarAssign - assignment when both are in far space         */
7456 /*-----------------------------------------------------------------*/
7457 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7458 {
7459     int size = AOP_SIZE(right);
7460     int offset = 0;
7461     char *l ;
7462     /* first push the right side on to the stack */
7463     while (size--) {
7464         l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7465         MOVA(l);
7466         emitcode ("push","acc");
7467     }
7468     
7469     D(emitcode(";", "genFarFarAssign "););
7470
7471     freeAsmop(right,NULL,ic,FALSE);
7472     /* now assign DPTR to result */
7473     aopOp(result,ic,FALSE, FALSE);
7474     size = AOP_SIZE(result);
7475     while (size--) {
7476         emitcode ("pop","acc");
7477         aopPut(AOP(result),"a",--offset);
7478     }
7479     freeAsmop(result,NULL,ic,FALSE);
7480         
7481 }
7482
7483 /*-----------------------------------------------------------------*/
7484 /* genAssign - generate code for assignment                        */
7485 /*-----------------------------------------------------------------*/
7486 static void genAssign (iCode *ic)
7487 {
7488     operand *result, *right;
7489     int size, offset ;
7490         unsigned long lit = 0L;
7491
7492     D(emitcode(";", "genAssign "););
7493
7494     result = IC_RESULT(ic);
7495     right  = IC_RIGHT(ic) ;
7496
7497     /* if they are the same */
7498     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7499         return ;
7500
7501     aopOp(right,ic,FALSE, FALSE);
7502     
7503     emitcode(";", "genAssign: resultIsFar = %s",
7504              isOperandInFarSpace(result) ?
7505              "TRUE" : "FALSE");
7506
7507     /* special case both in far space */
7508     if ((AOP_TYPE(right) == AOP_DPTR ||
7509          AOP_TYPE(right) == AOP_DPTR2) &&
7510     /* IS_TRUE_SYMOP(result)       && */
7511     isOperandInFarSpace(result)) {
7512         
7513         genFarFarAssign (result,right,ic);
7514         return ;
7515     }
7516
7517     aopOp(result,ic,TRUE, FALSE);
7518
7519     /* if they are the same registers */
7520     if (sameRegs(AOP(right),AOP(result)))
7521         goto release;
7522
7523     /* if the result is a bit */
7524     if (AOP_TYPE(result) == AOP_CRY) {
7525
7526         /* if the right size is a literal then
7527         we know what the value is */
7528         if (AOP_TYPE(right) == AOP_LIT) {
7529             if (((int) operandLitValue(right))) 
7530                 aopPut(AOP(result),one,0);
7531             else
7532                 aopPut(AOP(result),zero,0);
7533             goto release;
7534         }
7535
7536         /* the right is also a bit variable */
7537         if (AOP_TYPE(right) == AOP_CRY) {
7538             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7539             aopPut(AOP(result),"c",0);
7540             goto release ;
7541         }
7542
7543         /* we need to or */
7544         toBoolean(right);
7545         aopPut(AOP(result),"a",0);
7546         goto release ;
7547     }
7548
7549     /* bit variables done */
7550     /* general case */
7551     size = AOP_SIZE(result);
7552     offset = 0 ;
7553     if(AOP_TYPE(right) == AOP_LIT)
7554         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7555     if((size > 1) &&
7556        (AOP_TYPE(result) != AOP_REG) &&
7557        (AOP_TYPE(right) == AOP_LIT) &&
7558        !IS_FLOAT(operandType(right)) &&
7559        (lit < 256L)){
7560         emitcode("clr","a");
7561         while (size--) {
7562             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7563                 aopPut(AOP(result),"a",size);
7564             else
7565                 aopPut(AOP(result),
7566                        aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7567                        size);
7568         }
7569     } else {
7570         while (size--) {
7571             aopPut(AOP(result),
7572                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7573                    offset);
7574             offset++;
7575         }
7576     }
7577     
7578 release:
7579     freeAsmop (right,NULL,ic,FALSE);
7580     freeAsmop (result,NULL,ic,TRUE);
7581 }   
7582
7583 /*-----------------------------------------------------------------*/
7584 /* genJumpTab - genrates code for jump table                       */
7585 /*-----------------------------------------------------------------*/
7586 static void genJumpTab (iCode *ic)
7587 {
7588     symbol *jtab;
7589     char *l;
7590
7591     D(emitcode(";", "genJumpTab "););
7592
7593     aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7594     /* get the condition into accumulator */
7595     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7596     MOVA(l);
7597     /* multiply by four! */
7598     emitcode("add","a,acc");
7599     emitcode("add","a,acc");
7600     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7601
7602     jtab = newiTempLabel(NULL);
7603     emitcode("mov","dptr,#%05d$",jtab->key+100);
7604     emitcode("jmp","@a+dptr");
7605     emitcode("","%05d$:",jtab->key+100);
7606     /* now generate the jump labels */
7607     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7608          jtab = setNextItem(IC_JTLABELS(ic)))
7609         emitcode("ljmp","%05d$",jtab->key+100);
7610
7611 }
7612
7613 /*-----------------------------------------------------------------*/
7614 /* genCast - gen code for casting                                  */
7615 /*-----------------------------------------------------------------*/
7616 static void genCast (iCode *ic)
7617 {
7618     operand *result = IC_RESULT(ic);
7619     link *ctype = operandType(IC_LEFT(ic));
7620     link *rtype = operandType(IC_RIGHT(ic));
7621     operand *right = IC_RIGHT(ic);
7622     int size, offset ;
7623
7624     D(emitcode(";", "genCast "););
7625
7626     /* if they are equivalent then do nothing */
7627     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7628         return ;
7629
7630     aopOp(right,ic,FALSE, FALSE) ;
7631     aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7632
7633     /* if the result is a bit */
7634     if (AOP_TYPE(result) == AOP_CRY) {
7635         /* if the right size is a literal then
7636         we know what the value is */
7637         if (AOP_TYPE(right) == AOP_LIT) {
7638             if (((int) operandLitValue(right))) 
7639                 aopPut(AOP(result),one,0);
7640             else
7641                 aopPut(AOP(result),zero,0);
7642
7643             goto release;
7644         }
7645
7646         /* the right is also a bit variable */
7647         if (AOP_TYPE(right) == AOP_CRY) {
7648             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7649             aopPut(AOP(result),"c",0);
7650             goto release ;
7651         }
7652
7653         /* we need to or */
7654         toBoolean(right);
7655         aopPut(AOP(result),"a",0);
7656         goto release ;
7657     }
7658
7659     /* if they are the same size : or less */
7660     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7661
7662         /* if they are in the same place */
7663         if (sameRegs(AOP(right),AOP(result)))
7664             goto release;
7665
7666         /* if they in different places then copy */
7667         size = AOP_SIZE(result);
7668         offset = 0 ;
7669         while (size--) {
7670             aopPut(AOP(result),
7671                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7672                    offset);
7673             offset++;
7674         }
7675         goto release;
7676     }
7677
7678
7679     /* if the result is of type pointer */
7680     if (IS_PTR(ctype)) {
7681
7682         int p_type;
7683         link *type = operandType(right);
7684
7685         /* pointer to generic pointer */
7686         if (IS_GENPTR(ctype)) {
7687             char *l = zero;
7688             
7689             if (IS_PTR(type)) 
7690             {
7691                 p_type = DCL_TYPE(type);
7692             }
7693             else 
7694             {
7695 #if OLD_CAST_BEHAVIOR
7696                 /* KV: we are converting a non-pointer type to
7697                  * a generic pointer. This (ifdef'd out) code
7698                  * says that the resulting generic pointer 
7699                  * should have the same class as the storage
7700                  * location of the non-pointer variable.
7701                  * 
7702                  * For example, converting an int (which happens
7703                  * to be stored in DATA space) to a pointer results
7704                  * in a DATA generic pointer; if the original int
7705                  * in XDATA space, so will be the resulting pointer.
7706                  *
7707                  * I don't like that behavior, and thus this change:
7708                  * all such conversions will be forced to XDATA and
7709                  * throw a warning. If you want some non-XDATA
7710                  * type, or you want to suppress the warning, you
7711                  * must go through an intermediate cast, like so:
7712                  *
7713                  * char _generic *gp = (char _xdata *)(intVar);
7714                  */
7715                 link *etype = getSpec(type);             
7716
7717                 /* we have to go by the storage class */
7718                 if (SPEC_OCLS(etype) != generic)
7719                 {
7720                     p_type = PTR_TYPE(SPEC_OCLS(etype));
7721                 }
7722                 else
7723 #endif          
7724                 {
7725                     /* Converting unknown class (i.e. register variable)
7726                      * to generic pointer. This is not good, but
7727                      * we'll make a guess (and throw a warning).
7728                      */
7729                     p_type = FPOINTER;
7730                     werror(W_INT_TO_GEN_PTR_CAST);           
7731                 }
7732             }
7733                 
7734             /* the first two bytes are known */
7735             size = GPTRSIZE - 1; 
7736             offset = 0 ;
7737             while (size--) {
7738                 aopPut(AOP(result),
7739                        aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7740                        offset);
7741                 offset++;
7742             }
7743             
7744             /* the last byte depending on type */
7745             switch (p_type) {
7746             case IPOINTER:
7747             case POINTER:
7748                 l = zero;
7749                 break;
7750             case FPOINTER:
7751                 l = one;
7752                 break;
7753             case CPOINTER:
7754                 l = "#0x02";
7755                 break;                          
7756             case PPOINTER:
7757                 l = "#0x03";
7758                 break;
7759                 
7760             default:
7761                 /* this should never happen */
7762                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7763                        "got unknown pointer type");
7764                 exit(1);
7765             }
7766             aopPut(AOP(result),l, GPTRSIZE - 1);            
7767             goto release ;
7768         }
7769         
7770         /* just copy the pointers */
7771         size = AOP_SIZE(result);
7772         offset = 0 ;
7773         while (size--) {
7774             aopPut(AOP(result),
7775                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7776                    offset);
7777             offset++;
7778         }
7779         goto release ;
7780     }
7781     
7782     /* so we now know that the size of destination is greater
7783     than the size of the source */
7784     /* we move to result for the size of source */
7785     size = AOP_SIZE(right);
7786     offset = 0 ;
7787     while (size--) {
7788         aopPut(AOP(result),
7789                aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7790                offset);
7791         offset++;
7792     }
7793
7794     /* now depending on the sign of the source && destination */
7795     size = AOP_SIZE(result) - AOP_SIZE(right);
7796     /* if unsigned or not an integral type */
7797     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7798         while (size--)
7799             aopPut(AOP(result),zero,offset++);
7800     } else {
7801         /* we need to extend the sign :{ */
7802         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7803                          FALSE,FALSE,TRUE);
7804         MOVA(l);
7805         emitcode("rlc","a");
7806         emitcode("subb","a,acc");
7807         while (size--)
7808             aopPut(AOP(result),"a",offset++);   
7809     }
7810
7811     /* we are done hurray !!!! */
7812
7813 release:
7814     freeAsmop(right,NULL,ic,TRUE);
7815     freeAsmop(result,NULL,ic,TRUE);
7816
7817 }
7818
7819 /*-----------------------------------------------------------------*/
7820 /* genDjnz - generate decrement & jump if not zero instrucion      */
7821 /*-----------------------------------------------------------------*/
7822 static int genDjnz (iCode *ic, iCode *ifx)
7823 {
7824     symbol *lbl, *lbl1;
7825     if (!ifx)
7826         return 0;
7827     
7828     /* if the if condition has a false label
7829        then we cannot save */
7830     if (IC_FALSE(ifx))
7831         return 0;
7832
7833     /* if the minus is not of the form 
7834        a = a - 1 */
7835     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7836         !IS_OP_LITERAL(IC_RIGHT(ic)))
7837         return 0;
7838
7839     if (operandLitValue(IC_RIGHT(ic)) != 1)
7840         return 0;
7841
7842     /* if the size of this greater than one then no
7843        saving */
7844     if (getSize(operandType(IC_RESULT(ic))) > 1)
7845         return 0;
7846
7847     /* otherwise we can save BIG */
7848     lbl = newiTempLabel(NULL);
7849     lbl1= newiTempLabel(NULL);
7850
7851     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7852     
7853     if (IS_AOP_PREG(IC_RESULT(ic))) {
7854         emitcode("dec","%s",
7855                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7856         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7857         emitcode("jnz","%05d$",lbl->key+100);
7858     } else {    
7859         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
7860                   lbl->key+100);
7861     }
7862     emitcode ("sjmp","%05d$",lbl1->key+100);
7863     emitcode ("","%05d$:",lbl->key+100);
7864     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7865     emitcode ("","%05d$:",lbl1->key+100);
7866     
7867     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7868     ifx->generated = 1;
7869     return 1;
7870 }
7871
7872 /*-----------------------------------------------------------------*/
7873 /* genReceive - generate code for a receive iCode                  */
7874 /*-----------------------------------------------------------------*/
7875 static void genReceive (iCode *ic)
7876 {    
7877
7878     D(emitcode(";", "genReceive "););
7879
7880     if (isOperandInFarSpace(IC_RESULT(ic)) && 
7881         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7882           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7883         int size = getSize(operandType(IC_RESULT(ic)));
7884         int offset =  fReturnSize_390 - size;
7885         while (size--) {
7886             emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7887                                     fReturn[fReturnSize_390 - offset - 1] : "acc"));
7888             offset++;
7889         }
7890         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7891         size = AOP_SIZE(IC_RESULT(ic));
7892         offset = 0;
7893         while (size--) {
7894             emitcode ("pop","acc");
7895             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7896         }
7897         
7898     } else {
7899         _G.accInUse++;
7900         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);  
7901         _G.accInUse--;
7902         assignResultValue(IC_RESULT(ic));       
7903     }
7904
7905     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7906 }
7907
7908 /*-----------------------------------------------------------------*/
7909 /* gen390Code - generate code for 8051 based controllers            */
7910 /*-----------------------------------------------------------------*/
7911 void gen390Code (iCode *lic)
7912 {
7913     iCode *ic;
7914     int cln = 0;
7915
7916     lineHead = lineCurr = NULL;
7917
7918     /* print the allocation information */
7919     if (allocInfo)
7920         printAllocInfo( currFunc, codeOutFile);
7921     /* if debug information required */
7922 /*     if (options.debug && currFunc) { */
7923     if (currFunc) {
7924         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7925         _G.debugLine = 1;
7926         if (IS_STATIC(currFunc->etype))
7927             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
7928         else
7929             emitcode("","G$%s$0$0 ==.",currFunc->name);
7930         _G.debugLine = 0;
7931     }
7932     /* stack pointer name */
7933     if (options.useXstack)
7934         spname = "_spx";
7935     else
7936         spname = "sp";
7937     
7938  
7939     for (ic = lic ; ic ; ic = ic->next ) {
7940         
7941         if ( cln != ic->lineno ) {
7942             if ( options.debug ) {
7943                 _G.debugLine = 1;
7944                 emitcode("","C$%s$%d$%d$%d ==.",
7945                          ic->filename,ic->lineno,
7946                          ic->level,ic->block);
7947                 _G.debugLine = 0;
7948             }
7949             emitcode(";","%s %d",ic->filename,ic->lineno);
7950             cln = ic->lineno ;
7951         }
7952         /* if the result is marked as
7953            spilt and rematerializable or code for
7954            this has already been generated then
7955            do nothing */
7956         if (resultRemat(ic) || ic->generated ) 
7957             continue ;
7958         
7959         /* depending on the operation */
7960         switch (ic->op) {
7961         case '!' :
7962             genNot(ic);
7963             break;
7964             
7965         case '~' :
7966             genCpl(ic);
7967             break;
7968             
7969         case UNARYMINUS:
7970             genUminus (ic);
7971             break;
7972             
7973         case IPUSH:
7974             genIpush (ic);
7975             break;
7976             
7977         case IPOP:
7978             /* IPOP happens only when trying to restore a 
7979                spilt live range, if there is an ifx statement
7980                following this pop then the if statement might
7981                be using some of the registers being popped which
7982                would destory the contents of the register so
7983                we need to check for this condition and handle it */
7984             if (ic->next            && 
7985                 ic->next->op == IFX &&
7986                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
7987                 genIfx (ic->next,ic);
7988             else
7989                 genIpop (ic);
7990             break; 
7991             
7992         case CALL:
7993             genCall (ic);
7994             break;
7995             
7996         case PCALL:
7997             genPcall (ic);
7998             break;
7999             
8000         case FUNCTION:
8001             genFunction (ic);
8002             break;
8003             
8004         case ENDFUNCTION:
8005             genEndFunction (ic);
8006             break;
8007             
8008         case RETURN:
8009             genRet (ic);
8010             break;
8011             
8012         case LABEL:
8013             genLabel (ic);
8014             break;
8015             
8016         case GOTO:
8017             genGoto (ic);
8018             break;
8019             
8020         case '+' :
8021             genPlus (ic) ;
8022             break;
8023             
8024         case '-' :
8025             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8026                 genMinus (ic);
8027             break;
8028             
8029         case '*' :
8030             genMult (ic);
8031             break;
8032             
8033         case '/' :
8034             genDiv (ic) ;
8035             break;
8036             
8037         case '%' :
8038             genMod (ic);
8039             break;
8040             
8041         case '>' :
8042             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
8043             break;
8044             
8045         case '<' :
8046             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8047             break;
8048             
8049         case LE_OP:
8050         case GE_OP:
8051         case NE_OP:
8052             
8053             /* note these two are xlated by algebraic equivalence
8054                during parsing SDCC.y */
8055             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8056                    "got '>=' or '<=' shouldn't have come here");
8057             break;      
8058             
8059         case EQ_OP:
8060             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8061             break;          
8062             
8063         case AND_OP:
8064             genAndOp (ic);
8065             break;
8066             
8067         case OR_OP:
8068             genOrOp (ic);
8069             break;
8070             
8071         case '^' :
8072             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8073             break;
8074             
8075         case '|' :
8076                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8077             break;
8078             
8079         case BITWISEAND:
8080             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8081             break;
8082             
8083         case INLINEASM:
8084             genInline (ic);
8085             break;
8086             
8087         case RRC:
8088             genRRC (ic);
8089             break;
8090             
8091         case RLC:
8092             genRLC (ic);
8093             break;
8094             
8095         case GETHBIT:
8096             genGetHbit (ic);
8097             break;
8098             
8099         case LEFT_OP:
8100             genLeftShift (ic);
8101             break;
8102             
8103         case RIGHT_OP:
8104             genRightShift (ic);
8105             break;
8106             
8107         case GET_VALUE_AT_ADDRESS:
8108             genPointerGet(ic);
8109             break;
8110             
8111         case '=' :
8112             if (POINTER_SET(ic))
8113                 genPointerSet(ic);
8114             else
8115                 genAssign(ic);
8116             break;
8117             
8118         case IFX:
8119             genIfx (ic,NULL);
8120             break;
8121             
8122         case ADDRESS_OF:
8123             genAddrOf (ic);
8124             break;
8125             
8126         case JUMPTABLE:
8127             genJumpTab (ic);
8128             break;
8129             
8130         case CAST:
8131             genCast (ic);
8132             break;
8133             
8134         case RECEIVE:
8135             genReceive(ic);
8136             break;
8137             
8138         case SEND:
8139             addSet(&_G.sendSet,ic);
8140             break;
8141
8142         default :
8143             ic = ic;
8144             /*      piCode(ic,stdout); */
8145             
8146         }
8147     }
8148     
8149
8150     /* now we are ready to call the 
8151        peep hole optimizer */
8152     if (!options.nopeep)
8153         peepHole (&lineHead);
8154
8155     /* now do the actual printing */
8156     printLine (lineHead,codeOutFile);    
8157     return;
8158 }