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