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