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