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