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