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