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