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