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