* src/hc08/gen.c (genPackBitsImmed, genUnpackBitsImmed): fix offset
[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       transferAopAop (AOP (op), offset, AOP (result), offset);
2335       offset++;
2336     }
2337
2338   needpula = pushRegIfUsed (hc08_reg_a);
2339   loadRegFromAop (hc08_reg_a, AOP (op), offset);
2340   emitcode ("eor", "#0x80");
2341   hc08_useReg (hc08_reg_a);
2342   storeRegToAop (hc08_reg_a, AOP (result), offset);
2343   pullOrFreeReg (hc08_reg_a, needpula);
2344 }
2345
2346 /*-----------------------------------------------------------------*/
2347 /* genUminus - unary minus code generation                         */
2348 /*-----------------------------------------------------------------*/
2349 static void
2350 genUminus (iCode * ic)
2351 {
2352   int offset, size;
2353   sym_link *optype, *rtype;
2354   char *sub;
2355   bool needpula;
2356   asmop *result;
2357
2358   D(emitcode (";     genUminus",""));
2359
2360   /* assign asmops */
2361   aopOp (IC_LEFT (ic), ic, FALSE);
2362   aopOp (IC_RESULT (ic), ic, TRUE);
2363
2364   optype = operandType (IC_LEFT (ic));
2365   rtype = operandType (IC_RESULT (ic));
2366
2367   /* if float then do float stuff */
2368   if (IS_FLOAT (optype))
2369     {
2370       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2371       goto release;
2372     }
2373
2374   /* otherwise subtract from zero */
2375   size = AOP_SIZE (IC_LEFT (ic));
2376   offset = 0;
2377
2378   if (size == 1)
2379     {
2380       if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2381         needpula = pushRegIfUsed (hc08_reg_a);
2382       else
2383         needpula = FALSE;
2384       loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2385       emitcode ("nega", "");
2386       hc08_freeReg (hc08_reg_a);
2387       storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)), 
2388                          SPEC_USIGN (operandType (IC_LEFT (ic))));
2389       pullOrFreeReg (hc08_reg_a, needpula);
2390     }
2391   else
2392     {
2393       if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2394         result = forceStackedAop (AOP (IC_RESULT (ic)));
2395       else
2396         result = AOP (IC_RESULT (ic));
2397         
2398       needpula = pushRegIfUsed (hc08_reg_a);
2399       sub="sub";
2400       while (size--)
2401         {
2402           loadRegFromConst (hc08_reg_a, zero);
2403           accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2404           storeRegToAop (hc08_reg_a, result, offset++);
2405           sub = "sbc";
2406         }
2407         storeRegSignToUpperAop (hc08_reg_a, result, offset, 
2408                                 SPEC_USIGN (operandType (IC_LEFT (ic))));
2409       pullOrFreeReg (hc08_reg_a, needpula);
2410       
2411       if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2412         freeAsmop (NULL, result, ic, TRUE);
2413     }
2414
2415
2416
2417 release:
2418   /* release the aops */
2419   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2420   freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2421 }
2422
2423 /*-----------------------------------------------------------------*/
2424 /* saveRegisters - will look for a call and save the registers     */
2425 /*-----------------------------------------------------------------*/
2426 static void
2427 saveRegisters (iCode * lic)
2428 {
2429   int i;
2430   iCode *ic;
2431   bitVect *rsave;
2432
2433   /* look for call */
2434   for (ic = lic; ic; ic = ic->next)
2435     if (ic->op == CALL || ic->op == PCALL)
2436       break;
2437
2438   if (!ic)
2439     {
2440       fprintf (stderr, "found parameter push with no function call\n");
2441       return;
2442     }
2443
2444   /* if the registers have been saved already or don't need to be then
2445      do nothing */
2446   if (ic->regsSaved)
2447     return;
2448   if (IS_SYMOP(IC_LEFT(ic)) &&
2449       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2450        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2451     return;
2452   
2453   /* safe the registers in use at this time but skip the
2454      ones for the result */
2455   rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2456                          hc08_rUmaskForOp (IC_RESULT(ic)));
2457
2458   ic->regsSaved = 1;
2459   for (i = 0; i < hc08_nRegs; i++)
2460     {
2461       if (bitVectBitValue (rsave, i))
2462         pushReg ( hc08_regWithIdx (i), FALSE);
2463     }
2464 }
2465
2466 /*-----------------------------------------------------------------*/
2467 /* unsaveRegisters - pop the pushed registers                      */
2468 /*-----------------------------------------------------------------*/
2469 static void
2470 unsaveRegisters (iCode * ic)
2471 {
2472   int i;
2473   bitVect *rsave;
2474
2475   /* restore the registers in use at this time but skip the
2476      ones for the result */
2477   rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2478                          hc08_rUmaskForOp (IC_RESULT(ic)));
2479
2480   for (i = hc08_nRegs; i >= 0; i--)
2481     {
2482       if (bitVectBitValue (rsave, i))
2483         pullReg ( hc08_regWithIdx (i));
2484     }
2485
2486 }
2487
2488
2489 /*-----------------------------------------------------------------*/
2490 /* pushSide -                */
2491 /*-----------------------------------------------------------------*/
2492 static void
2493 pushSide (operand * oper, int size)
2494 {
2495   int offset = 0;
2496   while (size--)
2497     {
2498       loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2499       pushReg ( hc08_reg_a, TRUE);
2500     }
2501 }
2502
2503 /*-----------------------------------------------------------------*/
2504 /* assignResultValue -               */
2505 /*-----------------------------------------------------------------*/
2506 static void
2507 assignResultValue (operand * oper)
2508 {
2509   int size = AOP_SIZE (oper);
2510   int offset = 0;
2511   while (size--)
2512     {
2513       transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2514       if (hc08_aop_pass[offset]->type == AOP_REG)
2515         hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2516       offset++;
2517     }
2518 }
2519
2520
2521
2522 /*-----------------------------------------------------------------*/
2523 /* genIpush - genrate code for pushing this gets a little complex  */
2524 /*-----------------------------------------------------------------*/
2525 static void
2526 genIpush (iCode * ic)
2527 {
2528   int size, offset = 0;
2529 //  char *l;
2530
2531   D(emitcode (";     genIpush",""));
2532
2533   /* if this is not a parm push : ie. it is spill push
2534      and spill push is always done on the local stack */
2535   if (!ic->parmPush)
2536     {
2537
2538       /* and the item is spilt then do nothing */
2539       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2540         return;
2541
2542       aopOp (IC_LEFT (ic), ic, FALSE);
2543       size = AOP_SIZE (IC_LEFT (ic));
2544       offset = 0;
2545       /* push it on the stack */
2546       while (size--)
2547         {
2548           loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2549           pushReg ( hc08_reg_a, TRUE);
2550         }
2551
2552       return;
2553     }
2554
2555   /* this is a paramter push: in this case we call
2556      the routine to find the call and save those
2557      registers that need to be saved */
2558   saveRegisters (ic);
2559
2560   /* then do the push */
2561   aopOp (IC_LEFT (ic), ic, FALSE);
2562
2563
2564   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2565   size = AOP_SIZE (IC_LEFT (ic));
2566   offset = 0;
2567
2568 //  l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2569   if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2570     {
2571       if ((size==2) && hc08_reg_hx->isFree)
2572         {
2573           loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2574           pushReg (hc08_reg_hx, TRUE);
2575           goto release;
2576         }
2577     }
2578
2579   while (size--)
2580     {
2581 //      printf("loading %d\n", offset);
2582       loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2583 //      printf("pushing \n");
2584       pushReg (hc08_reg_a, TRUE);
2585     }
2586
2587 release:
2588   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2589 }
2590
2591 /*-----------------------------------------------------------------*/
2592 /* genIpop - recover the registers: can happen only for spilling   */
2593 /*-----------------------------------------------------------------*/
2594 static void
2595 genIpop (iCode * ic)
2596 {
2597   int size, offset;
2598
2599   D(emitcode (";     genIpop",""));
2600
2601   /* if the temp was not pushed then */
2602   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2603     return;
2604
2605   aopOp (IC_LEFT (ic), ic, FALSE);
2606   size = AOP_SIZE (IC_LEFT (ic));
2607   offset = size - 1;
2608   while (size--)
2609     {
2610       pullReg (hc08_reg_a);
2611       storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2612     }
2613   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2614 }
2615
2616
2617 /*-----------------------------------------------------------------*/
2618 /* genSend - gen code for SEND                                     */
2619 /*-----------------------------------------------------------------*/
2620 static void genSend(set *sendSet)
2621 {
2622     iCode *sic;
2623
2624     for (sic = setFirstItem (_G.sendSet); sic;
2625          sic = setNextItem (_G.sendSet)) {
2626           int size, offset = 0;
2627           aopOp (IC_LEFT (sic), sic, FALSE);
2628           size = AOP_SIZE (IC_LEFT (sic));
2629
2630           if (sic->argreg) {
2631               offset = size-1;
2632               while (size--) {
2633                   transferAopAop( AOP (IC_LEFT (sic)), offset,
2634                                   hc08_aop_pass[offset+(sic->argreg-1)], 0);
2635                   offset--;
2636               }
2637           }       
2638           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2639     }
2640 }
2641
2642 /*-----------------------------------------------------------------*/
2643 /* genCall - generates a call statement                            */
2644 /*-----------------------------------------------------------------*/
2645 static void
2646 genCall (iCode * ic)
2647 {
2648   sym_link *dtype;
2649 //  bool restoreBank = FALSE;
2650 //  bool swapBanks = FALSE;
2651
2652   D(emitcode(";     genCall",""));
2653
2654   dtype = operandType (IC_LEFT (ic));
2655   /* if send set is not empty the assign */
2656   if (_G.sendSet)
2657     {
2658         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2659             genSend(reverseSet(_G.sendSet));
2660         } else {
2661             genSend(_G.sendSet);
2662         }
2663
2664       _G.sendSet = NULL;
2665     }
2666
2667   /* if caller saves & we have not saved then */
2668   if (!ic->regsSaved)
2669       saveRegisters (ic);
2670
2671
2672   /* make the call */
2673   emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2674                           OP_SYMBOL (IC_LEFT (ic))->rname :
2675                           OP_SYMBOL (IC_LEFT (ic))->name));
2676
2677
2678   /* if we need assign a result value */
2679   if ((IS_ITEMP (IC_RESULT (ic)) &&
2680        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2681         OP_SYMBOL (IC_RESULT (ic))->accuse || 
2682         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2683       IS_TRUE_SYMOP (IC_RESULT (ic)))
2684     {
2685
2686       _G.accInUse++;
2687       aopOp (IC_RESULT (ic), ic, FALSE);
2688       _G.accInUse--;
2689
2690       assignResultValue (IC_RESULT (ic));
2691
2692       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2693     }
2694
2695   /* adjust the stack for parameters if
2696      required */
2697   if (ic->parmBytes)
2698     {
2699       pullNull (ic->parmBytes);
2700     }
2701
2702   /* if we had saved some registers then unsave them */
2703   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2704     unsaveRegisters (ic);
2705
2706 }
2707
2708 /*-----------------------------------------------------------------*/
2709 /* -10l - generates a call by pointer statement                */
2710 /*-----------------------------------------------------------------*/
2711 static void
2712 genPcall (iCode * ic)
2713 {
2714   sym_link *dtype;
2715   symbol *rlbl = newiTempLabel (NULL);
2716   symbol *tlbl = newiTempLabel (NULL);
2717 //  bool restoreBank=FALSE;
2718 //  bool swapBanks = FALSE;
2719
2720   D(emitcode(";     genPCall",""));
2721
2722   /* if caller saves & we have not saved then */
2723   if (!ic->regsSaved)
2724     saveRegisters (ic);
2725
2726   /* if we are calling a not _naked function that is not using
2727      the same register bank then we need to save the
2728      destination registers on the stack */
2729   dtype = operandType (IC_LEFT (ic))->next;
2730
2731   /* now push the calling address */
2732   emitBranch ("bsr", tlbl);
2733   emitBranch ("bra", rlbl);
2734   emitLabel (tlbl);
2735
2736   /* Push the function's address */
2737   aopOp (IC_LEFT (ic), ic, FALSE);
2738   pushSide (IC_LEFT (ic), FPTRSIZE);
2739   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2740
2741   /* if send set is not empty the assign */
2742   if (_G.sendSet)
2743     {
2744         genSend(reverseSet(_G.sendSet));
2745         _G.sendSet = NULL;
2746     }
2747
2748
2749   /* make the call */
2750   emitcode ("rts", "");
2751
2752   emitLabel (rlbl);
2753
2754
2755   /* if we need assign a result value */
2756   if ((IS_ITEMP (IC_RESULT (ic)) &&
2757        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2758         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2759       IS_TRUE_SYMOP (IC_RESULT (ic)))
2760     {
2761
2762       _G.accInUse++;
2763       aopOp (IC_RESULT (ic), ic, FALSE);
2764       _G.accInUse--;
2765
2766       assignResultValue (IC_RESULT (ic));
2767
2768       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2769     }
2770
2771   /* adjust the stack for parameters if
2772      required */
2773   if (ic->parmBytes)
2774     {
2775       pullNull (ic->parmBytes);
2776     }
2777
2778   /* if we hade saved some registers then
2779      unsave them */
2780   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2781     unsaveRegisters (ic);
2782 }
2783
2784 /*-----------------------------------------------------------------*/
2785 /* resultRemat - result  is rematerializable                       */
2786 /*-----------------------------------------------------------------*/
2787 static int
2788 resultRemat (iCode * ic)
2789 {
2790   if (SKIP_IC (ic) || ic->op == IFX)
2791     return 0;
2792
2793   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2794     {
2795       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2796       if (sym->remat && !POINTER_SET (ic))
2797         return 1;
2798     }
2799
2800   return 0;
2801 }
2802
2803 #if defined(__BORLANDC__) || defined(_MSC_VER)
2804 #define STRCASECMP stricmp
2805 #else
2806 #define STRCASECMP strcasecmp
2807 #endif
2808
2809 /*-----------------------------------------------------------------*/
2810 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2811 /*-----------------------------------------------------------------*/
2812 static int
2813 regsCmp(void *p1, void *p2)
2814 {
2815   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2816 }
2817
2818 static bool
2819 inExcludeList (char *s)
2820 {
2821   const char *p = setFirstItem(options.excludeRegsSet);
2822
2823   if (p == NULL || STRCASECMP(p, "none") == 0)
2824     return FALSE;
2825
2826
2827   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2828 }
2829
2830 /*-----------------------------------------------------------------*/
2831 /* genFunction - generated code for function entry                 */
2832 /*-----------------------------------------------------------------*/
2833 static void
2834 genFunction (iCode * ic)
2835 {
2836   symbol *sym;
2837   sym_link *ftype;
2838   int calleesaves_saved_register = -1;
2839
2840   _G.nRegsSaved = 0;
2841   _G.stackPushes = 0;
2842   /* create the function header */
2843   emitcode (";", "-----------------------------------------");
2844   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2845   emitcode (";", "-----------------------------------------");
2846
2847   emitcode ("", "%s:", sym->rname);
2848   ftype = operandType (IC_LEFT (ic));
2849   
2850   _G.stackOfs = 0;
2851   _G.stackPushes = 0;
2852   debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2853
2854   if (IFFUNC_ISNAKED(ftype))
2855   {
2856       emitcode(";", "naked function: no prologue.");
2857       return;
2858   }
2859
2860
2861
2862   /* if this is an interrupt service routine then
2863      save h  */
2864   if (IFFUNC_ISISR (sym->type))
2865     {
2866
2867       if (!inExcludeList ("h"))
2868         pushReg (hc08_reg_h, FALSE);
2869     }
2870   else
2871     {
2872       /* if callee-save to be used for this function
2873          then save the registers being used in this function */
2874       if (IFFUNC_CALLEESAVES(sym->type))
2875         {
2876           int i;
2877
2878           /* if any registers used */
2879           if (sym->regsUsed)
2880             {
2881               /* save the registers used */
2882               for (i = 0; i < sym->regsUsed->size; i++)
2883                 {
2884                   if (bitVectBitValue (sym->regsUsed, i))
2885                     {
2886                       /* remember one saved register for later usage */
2887                       if (calleesaves_saved_register < 0)
2888                         calleesaves_saved_register = i;
2889                       pushReg (hc08_regWithIdx (i), FALSE);
2890                       _G.nRegsSaved++;
2891                     }
2892                 }
2893             }
2894         }
2895     }
2896
2897   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2898     {
2899
2900     }
2901
2902   /* adjust the stack for the function */
2903   if (sym->stack)
2904     {
2905
2906       int i = sym->stack;
2907 //      if (i > 256)
2908 //      werror (W_STACK_OVERFLOW, sym->name);
2909
2910       adjustStack (-i);
2911     }
2912   _G.stackOfs = sym->stack;
2913   _G.stackPushes = 0;
2914   
2915   /* if critical function then turn interrupts off */
2916   if (IFFUNC_ISCRITICAL (ftype))
2917     {
2918       if (IFFUNC_ARGS (ftype))
2919         {
2920           /* Function was passed parameters, so make sure A is preserved */
2921           pushReg (hc08_reg_a, FALSE);
2922           pushReg (hc08_reg_a, FALSE);
2923           emitcode ("tpa", "");
2924           emitcode ("sta", "2,s");
2925           emitcode ("sei", "");
2926           pullReg (hc08_reg_a);
2927         }
2928       else
2929         {
2930           /* No passed parameters, so A can be freely modified */
2931           emitcode ("tpa", "");
2932           pushReg (hc08_reg_a, TRUE);
2933           emitcode ("sei", "");
2934         }
2935     }
2936
2937 }
2938
2939 /*-----------------------------------------------------------------*/
2940 /* genEndFunction - generates epilogue for functions               */
2941 /*-----------------------------------------------------------------*/
2942 static void
2943 genEndFunction (iCode * ic)
2944 {
2945   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2946
2947   if (IFFUNC_ISNAKED(sym->type))
2948   {
2949       emitcode(";", "naked function: no epilogue.");
2950       if (options.debug && currFunc)
2951         debugFile->writeEndFunction (currFunc, ic, 0);
2952       return;
2953   }
2954
2955   if (IFFUNC_ISCRITICAL (sym->type))
2956     {
2957       if (!IS_VOID(sym->type->next))
2958         {
2959           /* Function has return value, so make sure A is preserved */
2960           pushReg (hc08_reg_a, FALSE);
2961           emitcode ("lda", "2,s");
2962           emitcode ("tap", "");
2963           pullReg (hc08_reg_a);
2964           pullNull (1);
2965         }
2966       else
2967         {
2968           /* Function returns void, so A can be freely modified */
2969           pullReg (hc08_reg_a);
2970           emitcode ("tap", "");
2971         }
2972     }
2973
2974   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2975     {
2976     }
2977
2978   if (sym->stack)
2979     {
2980       _G.stackPushes += sym->stack;
2981       adjustStack (sym->stack);
2982     }
2983
2984
2985   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2986     {
2987     }
2988
2989   if (IFFUNC_ISISR (sym->type))
2990     {
2991
2992       if (!inExcludeList ("h"))
2993         pullReg (hc08_reg_h);
2994
2995
2996       /* if debug then send end of function */
2997       if (options.debug && currFunc)
2998         {
2999           debugFile->writeEndFunction (currFunc, ic, 1);
3000         }
3001
3002       emitcode ("rti", "");
3003     }
3004   else
3005     {
3006       if (IFFUNC_CALLEESAVES(sym->type))
3007         {
3008           int i;
3009
3010           /* if any registers used */
3011           if (sym->regsUsed)
3012             {
3013               /* save the registers used */
3014               for (i = sym->regsUsed->size; i >= 0; i--)
3015                 {
3016                   if (bitVectBitValue (sym->regsUsed, i) ||
3017                       (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3018                     emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3019                 }
3020             }
3021
3022         }
3023
3024       /* if debug then send end of function */
3025       if (options.debug && currFunc)
3026         {
3027           debugFile->writeEndFunction (currFunc, ic, 1);
3028         }
3029
3030       emitcode ("rts", "");
3031     }
3032
3033 }
3034
3035 /*-----------------------------------------------------------------*/
3036 /* genRet - generate code for return statement                     */
3037 /*-----------------------------------------------------------------*/
3038 static void
3039 genRet (iCode * ic)
3040 {
3041   int size, offset = 0;
3042 //  int pushed = 0;
3043
3044   D(emitcode (";     genRet",""));
3045
3046   /* if we have no return value then
3047      just generate the "ret" */
3048   if (!IC_LEFT (ic))
3049     goto jumpret;
3050
3051   /* we have something to return then
3052      move the return value into place */
3053   aopOp (IC_LEFT (ic), ic, FALSE);
3054   size = AOP_SIZE (IC_LEFT (ic));
3055
3056 #if 1
3057    offset = size - 1;
3058    while (size--)
3059      {
3060        transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3061        offset--;
3062      }
3063 #else
3064   switch (size)
3065     {
3066       case 4:
3067         /* 4 byte return: store value in the global return variable */
3068         offset = size-1;
3069         while (size--)
3070           {
3071             loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3072             STA (fReturn2[offset--], FALSE);
3073             hc08_freeReg (hc08_reg_a);
3074           }
3075         break;
3076       case 2:
3077         /* 2 byte return: store value in x:a */
3078         loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3079         hc08_freeReg (hc08_reg_xa);
3080         break;
3081       case 1:
3082         /* 1 byte return: store value in a */
3083         loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3084         hc08_freeReg (hc08_reg_a);
3085         break;
3086     }
3087 #endif
3088
3089   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3090
3091 jumpret:
3092   /* generate a jump to the return label
3093      if the next is not the return statement */
3094   if (!(ic->next && ic->next->op == LABEL &&
3095         IC_LABEL (ic->next) == returnLabel))
3096
3097     emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3098
3099 }
3100
3101 /*-----------------------------------------------------------------*/
3102 /* genLabel - generates a label                                    */
3103 /*-----------------------------------------------------------------*/
3104 static void
3105 genLabel (iCode * ic)
3106 {
3107   int i;
3108   regs *reg;
3109   
3110   /* For the high level labels we cannot depend on any */
3111   /* register's contents. Amnesia time.                */
3112   for (i=A_IDX;i<=XA_IDX;i++)
3113     {
3114       reg = hc08_regWithIdx(i);
3115       if (reg)
3116         reg->aop = NULL;
3117     }
3118
3119   /* special case never generate */
3120   if (IC_LABEL (ic) == entryLabel)
3121     return;
3122           
3123   debugFile->writeLabel(IC_LABEL (ic), ic);
3124
3125   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3126
3127 }
3128
3129 /*-----------------------------------------------------------------*/
3130 /* genGoto - generates a jmp                                      */
3131 /*-----------------------------------------------------------------*/
3132 static void
3133 genGoto (iCode * ic)
3134 {
3135   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3136 }
3137
3138 #if 0
3139 /*-----------------------------------------------------------------*/
3140 /* findLabelBackwards: walks back through the iCode chain looking  */
3141 /* for the given label. Returns number of iCode instructions     */
3142 /* between that label and given ic.          */
3143 /* Returns zero if label not found.          */
3144 /*-----------------------------------------------------------------*/
3145 static int
3146 findLabelBackwards (iCode * ic, int key)
3147 {
3148   int count = 0;
3149
3150   while (ic->prev)
3151     {
3152       ic = ic->prev;
3153       count++;
3154
3155       /* If we have any pushes or pops, we cannot predict the distance.
3156          I don't like this at all, this should be dealt with in the 
3157          back-end */
3158       if (ic->op == IPUSH || ic->op == IPOP) {
3159         return 0;
3160       }
3161
3162       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3163         {
3164           return count;
3165         }
3166     }
3167
3168   return 0;
3169 }
3170 #endif
3171
3172 /*-----------------------------------------------------------------*/
3173 /* genPlusIncr :- does addition with increment if possible         */
3174 /*-----------------------------------------------------------------*/
3175 static bool
3176 genPlusIncr (iCode * ic)
3177 {
3178   int icount;
3179   operand *left;
3180   operand *result;
3181   bool needpulx;
3182   bool needpulh;
3183   bool needpula;
3184   unsigned int size = getDataSize (IC_RESULT (ic));
3185   int offset;
3186   symbol *tlbl = NULL;
3187   
3188   left = IC_LEFT (ic);
3189   result = IC_RESULT (ic);
3190
3191   /* will try to generate an increment */
3192   /* if the right side is not a literal
3193      we cannot */
3194   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3195     return FALSE;
3196
3197   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3198
3199   D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3200   
3201   if ((IS_AOP_HX (AOP (left)) ||
3202        ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3203       )
3204       && (icount>=-128) && (icount<=127) && (size==2))
3205     {
3206       if (!IS_AOP_HX (AOP (left)))
3207         {
3208           needpulx = pushRegIfUsed (hc08_reg_x);
3209           needpulh = pushRegIfUsed (hc08_reg_h);
3210         }
3211       else
3212         {
3213           needpulx = FALSE;
3214           needpulh = FALSE;
3215         }
3216       loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3217       emitcode ("aix","#%d", icount);
3218       hc08_dirtyReg (hc08_reg_hx, FALSE);
3219       storeRegToAop (hc08_reg_hx, AOP(result), 0);
3220       pullOrFreeReg (hc08_reg_h, needpulh);
3221       pullOrFreeReg (hc08_reg_x, needpulx);
3222       return TRUE;
3223     }
3224
3225   D(emitcode ("", "; icount = %d, sameRegs=%d", icount, 
3226             sameRegs (AOP (left), AOP (result))));
3227   
3228   if ((icount > 255) || (icount<0))
3229     return FALSE;
3230
3231   if (!sameRegs (AOP (left), AOP (result)))
3232     return FALSE;
3233
3234   D(emitcode (";     genPlusIncr",""));
3235
3236   if (size>1)
3237     tlbl = newiTempLabel (NULL);
3238
3239   if (icount==1)
3240     {
3241       needpula = FALSE;
3242       rmwWithAop ("inc", AOP (result), 0);
3243       if (1<size)
3244         emitBranch ("bne", tlbl);
3245     }
3246   else
3247     {
3248       if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3249         needpula = pushRegIfUsed (hc08_reg_a);
3250       else
3251         needpula = FALSE;
3252       loadRegFromAop (hc08_reg_a, AOP (result), 0);
3253       accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3254       hc08_useReg (hc08_reg_a);
3255       storeRegToAop (hc08_reg_a, AOP (result), 0);
3256       hc08_freeReg (hc08_reg_a);
3257       if (1<size)
3258         emitBranch ("bcc", tlbl);
3259     }
3260   for (offset=1; offset<size; offset++)
3261     {
3262       rmwWithAop ("inc", AOP (result), offset);
3263       if ((offset+1)<size)
3264         emitBranch ("bne", tlbl);
3265     }
3266
3267   if (size>1)
3268     emitLabel (tlbl);
3269   
3270   pullOrFreeReg (hc08_reg_a, needpula);
3271       
3272   return TRUE;
3273 }
3274
3275
3276
3277 /*-----------------------------------------------------------------*/
3278 /* genPlus - generates code for addition                           */
3279 /*-----------------------------------------------------------------*/
3280 static void
3281 genPlus (iCode * ic)
3282 {
3283   int size, offset = 0;
3284   char *add;
3285   asmop *leftOp, *rightOp;
3286
3287   /* special cases :- */
3288
3289   D(emitcode (";     genPlus",""));
3290
3291   aopOp (IC_LEFT (ic), ic, FALSE);
3292   aopOp (IC_RIGHT (ic), ic, FALSE);
3293   aopOp (IC_RESULT (ic), ic, TRUE);
3294
3295   /* we want registers on the left and literals on the right */
3296   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3297       (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3298     {
3299       operand *t = IC_RIGHT (ic);
3300       IC_RIGHT (ic) = IC_LEFT (ic);
3301       IC_LEFT (ic) = t;
3302     }
3303
3304
3305   /* if I can do an increment instead
3306      of add then GOOD for ME */
3307   if (genPlusIncr (ic) == TRUE)
3308     goto release;
3309
3310   D(emitcode("",";  left size = %d", getDataSize (IC_LEFT(ic))));
3311   D(emitcode("",";  right size = %d", getDataSize (IC_RIGHT(ic))));
3312   D(emitcode("",";  result size = %d", getDataSize (IC_RESULT(ic))));
3313   
3314   size = getDataSize (IC_RESULT (ic));
3315
3316   leftOp = AOP(IC_LEFT(ic));
3317   rightOp = AOP(IC_RIGHT(ic));
3318   add = "add";
3319
3320   offset = 0;
3321   while (size--)
3322     {
3323       loadRegFromAop (hc08_reg_a, leftOp, offset);
3324       accopWithAop(add, rightOp, offset);
3325       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3326       hc08_freeReg (hc08_reg_a);
3327       add = "adc";  /* further adds must propagate carry */
3328     }
3329
3330
3331 //  adjustArithmeticResult (ic);
3332
3333 release:
3334   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3335   freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3336   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3337 }
3338
3339 /*-----------------------------------------------------------------*/
3340 /* genMinusDec :- does subtraction with deccrement if possible     */
3341 /*-----------------------------------------------------------------*/
3342 static bool
3343 genMinusDec (iCode * ic)
3344 {
3345   unsigned int icount;
3346   operand *left;
3347   operand *result;
3348   bool needpulx;
3349   bool needpulh;
3350   unsigned int size = getDataSize (IC_RESULT (ic));
3351 //  int offset;
3352 //  symbol *tlbl;
3353   
3354   left = IC_LEFT (ic);
3355   result = IC_RESULT (ic);
3356
3357   /* will try to generate an increment */
3358   /* if the right side is not a literal
3359      we cannot */
3360   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3361     return FALSE;
3362
3363   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3364
3365   if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3366       && (icount>=-127) && (icount<=128) && (size==2))
3367     {
3368       if (!IS_AOP_HX (AOP (left)))
3369         {
3370           needpulx = pushRegIfUsed (hc08_reg_x);
3371           needpulh = pushRegIfUsed (hc08_reg_h);
3372         }
3373       else
3374         {
3375           needpulx = FALSE;
3376           needpulh = FALSE;
3377         }
3378       loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3379       emitcode ("aix","#%d", -icount);
3380       hc08_dirtyReg (hc08_reg_hx, FALSE);
3381       storeRegToAop (hc08_reg_hx, AOP(result), 0);
3382       pullOrFreeReg (hc08_reg_h, needpulh);
3383       pullOrFreeReg (hc08_reg_x, needpulx);
3384       return TRUE;
3385     }
3386   
3387   if ((icount > 1) || (icount<0))
3388     return FALSE;
3389
3390   if (!sameRegs (AOP (left), AOP (result)))
3391     return FALSE;
3392
3393   if (size!=1)
3394     return FALSE;
3395
3396   D(emitcode (";     genMinusDec",""));
3397
3398   rmwWithAop ("dec", AOP (result), 0);
3399   
3400   return TRUE;
3401 }
3402
3403 /*-----------------------------------------------------------------*/
3404 /* addSign - complete with sign                                    */
3405 /*-----------------------------------------------------------------*/
3406 static void
3407 addSign (operand * result, int offset, int sign)
3408 {
3409   int size = (getDataSize (result) - offset);
3410   if (size > 0)
3411     {
3412       if (sign)
3413         {
3414           emitcode ("rola", "");
3415           emitcode ("clra", "");
3416           emitcode ("sbc", zero);
3417           while (size--)
3418             storeRegToAop (hc08_reg_a, AOP (result), offset++);
3419         }
3420       else
3421         while (size--)
3422           storeConstToAop (zero, AOP (result), offset++);
3423     }
3424 }
3425
3426
3427 /*-----------------------------------------------------------------*/
3428 /* genMinus - generates code for subtraction                       */
3429 /*-----------------------------------------------------------------*/
3430 static void
3431 genMinus (iCode * ic)
3432 {
3433   char *sub;
3434   int size, offset = 0;
3435   
3436   asmop *leftOp, *rightOp;
3437
3438   D(emitcode (";     genMinus",""));
3439
3440   aopOp (IC_LEFT (ic), ic, FALSE);
3441   aopOp (IC_RIGHT (ic), ic, FALSE);
3442   aopOp (IC_RESULT (ic), ic, TRUE);
3443
3444   /* special cases :- */
3445   /* if I can do an decrement instead
3446      of subtract then GOOD for ME */
3447   if (genMinusDec (ic) == TRUE)
3448     goto release;
3449
3450   size = getDataSize (IC_RESULT (ic));
3451
3452
3453   leftOp = AOP(IC_LEFT(ic));
3454   rightOp = AOP(IC_RIGHT(ic));
3455
3456   sub = "sub";
3457   offset = 0;
3458   while (size--)
3459     {
3460       loadRegFromAop ( hc08_reg_a, leftOp, offset);
3461       accopWithAop(sub, rightOp, offset);
3462       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3463       sub = "sbc";
3464     }
3465   
3466   
3467 //  adjustArithmeticResult (ic);
3468
3469 release:
3470   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3471   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3472   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3473 }
3474
3475
3476
3477 /*-----------------------------------------------------------------*/
3478 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3479 /*-----------------------------------------------------------------*/
3480 static void
3481 genMultOneByte (operand * left,
3482                 operand * right,
3483                 operand * result)
3484 {
3485   /* sym_link *opetype = operandType (result); */
3486   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3487   int size=AOP_SIZE(result);
3488   bool negLiteral = FALSE;
3489
3490   D(emitcode (";     genMultOneByte",""));
3491
3492   if (size<1 || size>2) {
3493     // this should never happen
3494       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3495                AOP_SIZE(result), __FILE__, lineno);
3496       exit (1);
3497   }
3498
3499   /* (if two literals: the value is computed before) */
3500   /* if one literal, literal on the right */
3501   if (AOP_TYPE (left) == AOP_LIT)
3502     {
3503       operand *t = right;
3504       right = left;
3505       left = t;
3506       //D(emitcode (";", "swapped left and right"));
3507     }
3508
3509   if (size == 1
3510       || (SPEC_USIGN(operandType(left)) &&
3511           SPEC_USIGN(operandType(right))))
3512     {
3513       // just an unsigned 8*8=8/16 multiply
3514       //D(emitcode (";","unsigned"));
3515
3516       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3517       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3518       emitcode ("mul", "");
3519       hc08_dirtyReg (hc08_reg_xa, FALSE);
3520       storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3521       hc08_freeReg (hc08_reg_xa);
3522       
3523       return;
3524     }
3525
3526   // we have to do a signed multiply
3527
3528
3529   //D(emitcode (";", "signed"));
3530   adjustStack (-1);
3531   emitcode ("clr", "1,s");
3532
3533   tlbl1 = newiTempLabel (NULL);
3534   loadRegFromAop (hc08_reg_a, AOP (left), 0);
3535   emitcode ("tsta","");
3536   emitBranch ("bpl", tlbl1);
3537   emitcode ("inc", "1,s");
3538   rmwWithReg ("neg", hc08_reg_a);
3539   emitLabel (tlbl1);
3540
3541   if (AOP_TYPE(right)==AOP_LIT)
3542     {
3543       signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3544       /* AND literal negative */
3545       if (val < 0) {
3546         emitcode ("ldx", "#0x%02x", -val);
3547         negLiteral = TRUE;
3548       } else {
3549         emitcode ("ldx", "#0x%02x", val);
3550       }
3551       hc08_useReg (hc08_reg_x);
3552     }
3553   else
3554     {
3555       tlbl2 = newiTempLabel (NULL);
3556       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3557       emitcode ("tstx", "");
3558       emitBranch ("bpl", tlbl2);
3559       emitcode ("inc", "1,s");
3560       rmwWithReg ("neg", hc08_reg_x);
3561       emitLabel (tlbl2);
3562     }
3563
3564   emitcode ("mul", "");
3565   hc08_dirtyReg (hc08_reg_xa, FALSE);
3566
3567   tlbl3 = newiTempLabel (NULL);
3568   emitcode ("dec", "1,s");
3569   if (negLiteral)
3570     emitBranch ("bne", tlbl3);
3571   else
3572     emitBranch ("beq", tlbl3);
3573
3574   rmwWithReg ("neg", hc08_reg_a);
3575   if (size>1)
3576     {
3577       tlbl4 = newiTempLabel (NULL);
3578       emitBranch ("bcc", tlbl4);
3579       rmwWithReg ("inc", hc08_reg_x);
3580       emitLabel (tlbl4);
3581       rmwWithReg ("neg", hc08_reg_x);
3582     }
3583
3584   emitLabel (tlbl3);
3585   adjustStack (1);
3586   storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3587   hc08_freeReg (hc08_reg_xa);
3588
3589 }
3590
3591 /*-----------------------------------------------------------------*/
3592 /* genMult - generates code for multiplication                     */
3593 /*-----------------------------------------------------------------*/
3594 static void
3595 genMult (iCode * ic)
3596 {
3597   operand *left = IC_LEFT (ic);
3598   operand *right = IC_RIGHT (ic);
3599   operand *result = IC_RESULT (ic);
3600
3601   D(emitcode (";     genMult",""));
3602
3603   /* assign the amsops */
3604   aopOp (left, ic, FALSE);
3605   aopOp (right, ic, FALSE);
3606   aopOp (result, ic, TRUE);
3607
3608   /* special cases first */
3609   /* if both are of size == 1 */
3610 //  if (getSize(operandType(left)) == 1 && 
3611 //      getSize(operandType(right)) == 1)
3612   if (AOP_SIZE (left) == 1 && 
3613       AOP_SIZE (right) == 1)
3614     {
3615       genMultOneByte (left, right, result);
3616       goto release;
3617     }
3618
3619   /* should have been converted to function call */
3620     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3621              getSize(OP_SYMBOL(right)->type));
3622     fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3623              AOP_SIZE (right));
3624   assert (0);
3625
3626 release:
3627   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3628   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3629   freeAsmop (result, NULL, ic, TRUE);
3630 }
3631
3632 /*-----------------------------------------------------------------*/
3633 /* genDivOneByte : 8 bit division                                  */
3634 /*-----------------------------------------------------------------*/
3635 static void
3636 genDivOneByte (operand * left,
3637                operand * right,
3638                operand * result)
3639 {
3640   sym_link *opetype = operandType (result);
3641 //  char *l;
3642   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3643   int size;
3644   bool negLiteral = FALSE;
3645
3646   D(emitcode (";     genDivOneByte",""));
3647
3648   size = AOP_SIZE (result);
3649   /* signed or unsigned */
3650   if (SPEC_USIGN (opetype))
3651     {
3652       /* unsigned is easy */
3653       loadRegFromAop (hc08_reg_h, AOP (left), 1);
3654       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3655       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3656       emitcode ("div", "");
3657       hc08_dirtyReg (hc08_reg_a, FALSE);
3658       hc08_dirtyReg (hc08_reg_h, FALSE);
3659       storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3660       hc08_freeReg (hc08_reg_a);
3661       hc08_freeReg (hc08_reg_x);
3662       hc08_freeReg (hc08_reg_h);
3663       return;
3664     }
3665
3666   /* signed is a little bit more difficult */
3667
3668   adjustStack (-1);
3669   emitcode ("clr", "1,s");
3670
3671   tlbl1 = newiTempLabel (NULL);
3672   tlbl2 = newiTempLabel (NULL);
3673   loadRegFromAop (hc08_reg_a, AOP (left), 0);
3674   loadRegFromAop (hc08_reg_x, AOP (left), 1);
3675   emitBranch ("bpl", tlbl1);
3676   emitcode ("inc", "1,s");
3677   rmwWithReg ("neg", hc08_reg_a);
3678   emitBranch ("bcc", tlbl2);
3679   rmwWithReg ("inc", hc08_reg_x);
3680   emitLabel (tlbl2);
3681   rmwWithReg ("neg", hc08_reg_x);
3682   transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3683   emitLabel (tlbl1);
3684
3685   if (AOP_TYPE(right)==AOP_LIT)
3686     {
3687       signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3688       /* AND literal negative */
3689       if (val < 0) {
3690         emitcode ("ldx", "#0x%02x", -val);
3691         negLiteral = TRUE;
3692       } else {
3693         emitcode ("ldx", "#0x%02x", val);
3694       }
3695       hc08_useReg (hc08_reg_x);
3696     }
3697   else
3698     {
3699       tlbl3 = newiTempLabel (NULL);
3700       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3701       emitBranch ("bpl", tlbl3);
3702       emitcode ("inc", "1,s");
3703       rmwWithReg ("neg", hc08_reg_x);
3704       emitLabel (tlbl3);
3705     }
3706
3707   emitcode ("div", "");
3708   hc08_dirtyReg (hc08_reg_x, FALSE);
3709   hc08_dirtyReg (hc08_reg_a, FALSE);
3710   hc08_dirtyReg (hc08_reg_h, FALSE);
3711
3712   tlbl4 = newiTempLabel (NULL);
3713   emitcode ("dec", "1,s");
3714   if (negLiteral)
3715     emitBranch ("bne", tlbl4);
3716   else
3717     emitBranch ("beq", tlbl4);
3718   rmwWithReg ("neg", hc08_reg_a);
3719
3720   emitLabel (tlbl4);
3721   adjustStack (1);
3722   storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3723   hc08_freeReg (hc08_reg_a);
3724   hc08_freeReg (hc08_reg_x);
3725   hc08_freeReg (hc08_reg_h);
3726
3727
3728 }
3729
3730 /*-----------------------------------------------------------------*/
3731 /* genDiv - generates code for division                            */
3732 /*-----------------------------------------------------------------*/
3733 static void
3734 genDiv (iCode * ic)
3735 {
3736   operand *left = IC_LEFT (ic);
3737   operand *right = IC_RIGHT (ic);
3738   operand *result = IC_RESULT (ic);
3739
3740   D(emitcode (";     genDiv",""));
3741
3742   /* assign the amsops */
3743   aopOp (left, ic, FALSE);
3744   aopOp (right, ic, FALSE);
3745   aopOp (result, ic, TRUE);
3746
3747   /* special cases first */
3748   /* if both are of size == 1 */
3749   if (AOP_SIZE (left) <= 2 &&
3750       AOP_SIZE (right) == 1)
3751     {
3752       genDivOneByte (left, right, result);
3753       goto release;
3754     }
3755
3756   /* should have been converted to function call */
3757   assert (0);
3758 release:
3759   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3760   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3761   freeAsmop (result, NULL, ic, TRUE);
3762 }
3763
3764 /*-----------------------------------------------------------------*/
3765 /* genModOneByte : 8 bit modulus                                   */
3766 /*-----------------------------------------------------------------*/
3767 static void
3768 genModOneByte (operand * left,
3769                operand * right,
3770                operand * result)
3771 {
3772   sym_link *opetype = operandType (result);
3773 //  symbol *lbl;
3774   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3775   int size;
3776   bool negLiteral = FALSE;
3777
3778   D(emitcode (";     genModOneByte",""));
3779
3780   size = AOP_SIZE (result);
3781   /* signed or unsigned */
3782   if (SPEC_USIGN (opetype))
3783     {
3784       /* unsigned is easy */
3785       loadRegFromAop (hc08_reg_h, AOP (left), 1);
3786       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3787       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3788       emitcode ("div", "");
3789       hc08_dirtyReg (hc08_reg_a, FALSE);
3790       hc08_dirtyReg (hc08_reg_h, FALSE);
3791       storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3792       hc08_freeReg (hc08_reg_a);
3793       hc08_freeReg (hc08_reg_x);
3794       hc08_freeReg (hc08_reg_h);
3795       return;
3796     }
3797
3798   /* signed is a little bit more difficult */
3799
3800   adjustStack (-1);
3801   emitcode ("clr", "1,s");
3802
3803   tlbl1 = newiTempLabel (NULL);
3804   tlbl2 = newiTempLabel (NULL);
3805   loadRegFromAop (hc08_reg_a, AOP (left), 0);
3806   loadRegFromAop (hc08_reg_x, AOP (left), 1);
3807   emitBranch ("bpl", tlbl1);
3808   emitcode ("inc", "1,s");
3809   rmwWithReg ("neg", hc08_reg_a);
3810   emitBranch ("bcc", tlbl2);
3811   rmwWithReg ("inc", hc08_reg_x);
3812   emitLabel (tlbl2);
3813   rmwWithReg ("neg", hc08_reg_x);
3814   transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3815   emitLabel (tlbl1);
3816
3817   if (AOP_TYPE(right)==AOP_LIT)
3818     {
3819       signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3820       /* AND literal negative */
3821       if (val < 0) {
3822         emitcode ("ldx", "#0x%02x", -val);
3823         negLiteral = TRUE;
3824       } else {
3825         emitcode ("ldx", "#0x%02x", val);
3826       }
3827       hc08_useReg (hc08_reg_x);
3828     }
3829   else
3830     {
3831       tlbl3 = newiTempLabel (NULL);
3832       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3833       emitBranch ("bpl", tlbl3);
3834       emitcode ("inc", "1,s");
3835       rmwWithReg ("neg", hc08_reg_x);
3836       emitLabel (tlbl3);
3837     }
3838
3839   emitcode ("div", "");
3840   hc08_dirtyReg (hc08_reg_x, FALSE);
3841   hc08_dirtyReg (hc08_reg_a, FALSE);
3842   hc08_dirtyReg (hc08_reg_h, FALSE);
3843
3844   tlbl4 = newiTempLabel (NULL);
3845   transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3846   emitcode ("dec", "1,s");
3847   if (negLiteral)
3848     emitBranch ("bne", tlbl4);
3849   else
3850     emitBranch ("beq", tlbl4);
3851   rmwWithReg ("neg", hc08_reg_a);
3852
3853   emitLabel (tlbl4);
3854   adjustStack (1);
3855   storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3856   hc08_freeReg (hc08_reg_a);
3857   hc08_freeReg (hc08_reg_x);
3858   hc08_freeReg (hc08_reg_h);
3859
3860 }
3861
3862 /*-----------------------------------------------------------------*/
3863 /* genMod - generates code for division                            */
3864 /*-----------------------------------------------------------------*/
3865 static void
3866 genMod (iCode * ic)
3867 {
3868   operand *left = IC_LEFT (ic);
3869   operand *right = IC_RIGHT (ic);
3870   operand *result = IC_RESULT (ic);
3871
3872   D(emitcode (";     genMod",""));
3873
3874   /* assign the amsops */
3875   aopOp (left, ic, FALSE);
3876   aopOp (right, ic, FALSE);
3877   aopOp (result, ic, TRUE);
3878
3879   /* special cases first */
3880   /* if both are of size == 1 */
3881   if (AOP_SIZE (left) <= 2 &&
3882       AOP_SIZE (right) == 1)
3883     {
3884       genModOneByte (left, right, result);
3885       goto release;
3886     }
3887
3888   /* should have been converted to function call */
3889   assert (0);
3890
3891 release:
3892   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3893   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3894   freeAsmop (result, NULL, ic, TRUE);
3895 }
3896
3897 /*-----------------------------------------------------------------*/
3898 /* genIfxJump :- will create a jump depending on the ifx           */
3899 /*-----------------------------------------------------------------*/
3900 static void
3901 genIfxJump (iCode * ic, char *jval)
3902 {
3903   symbol *jlbl;
3904   symbol *tlbl = newiTempLabel (NULL);
3905   char *inst;
3906
3907   D(emitcode (";     genIfxJump",""));
3908
3909   /* if true label then we jump if condition
3910      supplied is true */
3911   if (IC_TRUE (ic))
3912     {
3913       jlbl = IC_TRUE (ic);
3914       if (!strcmp (jval, "a"))
3915         inst = "beq";
3916       else if (!strcmp (jval, "c"))
3917         inst = "bcc";
3918       else
3919         inst = "bge";
3920     }
3921   else
3922     {
3923       /* false label is present */
3924       jlbl = IC_FALSE (ic);
3925       if (!strcmp (jval, "a"))
3926         inst = "bne";
3927       else if (!strcmp (jval, "c"))
3928         inst = "bcs";
3929       else
3930         inst = "blt";
3931     }
3932   emitBranch (inst, tlbl);
3933   emitBranch ("jmp", jlbl);
3934   emitLabel (tlbl);
3935
3936   /* mark the icode as generated */
3937   ic->generated = 1;
3938 }
3939
3940 /*-----------------------------------------------------------------*/
3941 /* genCmp :- greater or less than comparison                       */
3942 /*-----------------------------------------------------------------*/
3943 static void
3944 genCmp (operand * left, operand * right,
3945         operand * result, iCode * ifx, int sign, iCode *ic)
3946 {
3947   int size, offset = 0;
3948   unsigned long lit = 0L;
3949   char *sub;
3950   bool needpula = FALSE;
3951
3952   D(emitcode (";     genCmp",""));
3953
3954   /* subtract right from left if at the
3955      end the carry flag is set then we know that
3956      left is greater than right */
3957   size = max (AOP_SIZE (left), AOP_SIZE (right));
3958
3959   if (AOP_TYPE (right) == AOP_LIT)
3960     {
3961       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3962       /* optimize if(x < 0) or if(x >= 0) */
3963       if (lit == 0L)
3964         {
3965           if (!sign)
3966             {
3967               CLRC;
3968             }
3969           else
3970             {
3971               loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3972               emitcode ("rola", "");
3973               hc08_useReg (hc08_reg_a);
3974             }
3975           sign = 0;
3976           goto release;
3977         }
3978     }
3979
3980   if ((size==2)
3981       && ((AOP_TYPE (right) == AOP_LIT) || 
3982           ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3983       && hc08_reg_hx->isFree)
3984     {
3985       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3986       emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3987       hc08_freeReg (hc08_reg_hx);
3988       goto release;
3989     }
3990
3991   offset = 0;
3992   if (size==1)
3993     sub="cmp";
3994   else
3995     sub="sub";
3996   while (size--)
3997     {
3998       loadRegFromAop (hc08_reg_a, AOP (left), offset);
3999       accopWithAop (sub, AOP (right), offset);
4000       hc08_freeReg (hc08_reg_a);
4001       offset++;
4002       sub="sbc";
4003     }
4004
4005 release:
4006   freeAsmop (right, NULL, ic, TRUE);
4007   freeAsmop (left, NULL, ic, TRUE);
4008   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4009     {
4010       outBitC (result);
4011     }
4012   else
4013     {
4014       /* if the result is used in the next
4015          ifx conditional branch then generate
4016          code a little differently */
4017       if (ifx)
4018         {
4019           pullOrFreeReg(hc08_reg_a,needpula);
4020           genIfxJump (ifx, sign ? "s" : "c");
4021         }
4022       else
4023         if (!sign)
4024           outBitC (result);
4025         else
4026           outBitNV (result);
4027         pullOrFreeReg(hc08_reg_a,needpula);
4028     }
4029 }
4030
4031 /*-----------------------------------------------------------------*/
4032 /* genCmpGt :- greater than comparison                             */
4033 /*-----------------------------------------------------------------*/
4034 static void
4035 genCmpGt (iCode * ic, iCode * ifx)
4036 {
4037   operand *left, *right, *result;
4038   sym_link *letype, *retype;
4039   int sign;
4040
4041   D(emitcode (";     genCmpGt",""));
4042
4043   result = IC_RESULT (ic);
4044   left = IC_LEFT (ic);
4045   right = IC_RIGHT (ic);
4046
4047   letype = getSpec (operandType (left));
4048   retype = getSpec (operandType (right));
4049   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4050   /* assign the amsops */
4051   aopOp (left, ic, FALSE);
4052   aopOp (right, ic, FALSE);
4053   aopOp (result, ic, TRUE);
4054
4055   genCmp (right, left, result, ifx, sign,ic);
4056
4057   freeAsmop (result, NULL, ic, TRUE);
4058 }
4059
4060 /*-----------------------------------------------------------------*/
4061 /* genCmpLt - less than comparisons                                */
4062 /*-----------------------------------------------------------------*/
4063 static void
4064 genCmpLt (iCode * ic, iCode * ifx)
4065 {
4066   operand *left, *right, *result;
4067   sym_link *letype, *retype;
4068   int sign;
4069
4070   D(emitcode (";     genCmpLt",""));
4071
4072   result = IC_RESULT (ic);
4073   left = IC_LEFT (ic);
4074   right = IC_RIGHT (ic);
4075
4076   letype = getSpec (operandType (left));
4077   retype = getSpec (operandType (right));
4078   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4079
4080   /* assign the amsops */
4081   aopOp (left, ic, FALSE);
4082   aopOp (right, ic, FALSE);
4083   aopOp (result, ic, TRUE);
4084
4085   genCmp (left, right, result, ifx, sign,ic);
4086
4087   freeAsmop (result, NULL, ic, TRUE);
4088 }
4089
4090 /*-----------------------------------------------------------------*/
4091 /*  - compare and branch if not equal                    */
4092 /*-----------------------------------------------------------------*/
4093 static void
4094 gencbneshort (operand * left, operand * right, symbol * lbl)
4095 {
4096   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4097   int offset = 0;
4098   unsigned long lit = 0L;
4099
4100   /* if the left side is a literal or
4101      if the right is in a pointer register and left
4102      is not */
4103   if (AOP_TYPE (left) == AOP_LIT)
4104     {
4105       operand *t = right;
4106       right = left;
4107       left = t;
4108     }
4109   if (AOP_TYPE (right) == AOP_LIT)
4110     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4111
4112   while (size--)
4113     {
4114       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4115       accopWithAop ("cmp", AOP (right), offset);
4116       hc08_useReg (hc08_reg_a);
4117       hc08_freeReg (hc08_reg_a);
4118       emitBranch ("bne", lbl);
4119       offset++;
4120     }
4121
4122 }
4123
4124 /*-----------------------------------------------------------------*/
4125 /* gencjne - compare and jump if not equal                         */
4126 /*-----------------------------------------------------------------*/
4127 static void
4128 gencjne (operand * left, operand * right, symbol * lbl)
4129 {
4130   symbol *tlbl = newiTempLabel (NULL);
4131
4132   gencbneshort (left, right, lbl);
4133
4134   loadRegFromConst (hc08_reg_a, one);
4135   emitBranch ("bra", tlbl);
4136   emitLabel (lbl);
4137   loadRegFromConst (hc08_reg_a, zero);
4138   emitLabel (tlbl);
4139
4140   hc08_useReg(hc08_reg_a);
4141   hc08_freeReg(hc08_reg_a);
4142 }
4143
4144 /*-----------------------------------------------------------------*/
4145 /* genCmpEq - generates code for equal to                          */
4146 /*-----------------------------------------------------------------*/
4147 static void
4148 genCmpEq (iCode * ic, iCode * ifx)
4149 {
4150   operand *left, *right, *result;
4151
4152   D(emitcode (";     genCmpEq",""));
4153
4154   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4155   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4156   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4157
4158   /* if literal, literal on the right or
4159      if the right is in a pointer register and left
4160      is not */
4161   if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4162     {
4163       operand *t = IC_RIGHT (ic);
4164       IC_RIGHT (ic) = IC_LEFT (ic);
4165       IC_LEFT (ic) = t;
4166     }
4167
4168   if (ifx && !AOP_SIZE (result))
4169     {
4170       symbol *tlbl;
4171       tlbl = newiTempLabel (NULL);
4172       gencbneshort (left, right, tlbl);
4173       if (IC_TRUE (ifx))
4174         {
4175           emitBranch ("jmp", IC_TRUE (ifx));
4176           emitLabel (tlbl);
4177         }
4178       else
4179         {
4180           symbol *lbl = newiTempLabel (NULL);
4181           emitBranch ("bra", lbl);
4182           emitLabel (tlbl);
4183           emitBranch ("jmp", IC_FALSE (ifx));
4184           emitLabel (lbl);
4185         }
4186       
4187       /* mark the icode as generated */
4188       ifx->generated = 1;
4189       goto release;
4190     }
4191
4192   gencjne (left, right, newiTempLabel (NULL));
4193   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4194     {
4195       storeRegToAop (hc08_reg_a, AOP (result), 0);
4196       goto release;
4197     }
4198   if (ifx)
4199     {
4200       genIfxJump (ifx, "a");
4201       goto release;
4202     }
4203   /* if the result is used in an arithmetic operation
4204      then put the result in place */
4205   if (AOP_TYPE (result) != AOP_CRY)
4206     outAcc (result);
4207
4208 release:
4209   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4210   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4211   freeAsmop (result, NULL, ic, TRUE);
4212 }
4213
4214 /*-----------------------------------------------------------------*/
4215 /* ifxForOp - returns the icode containing the ifx for operand     */
4216 /*-----------------------------------------------------------------*/
4217 static iCode *
4218 ifxForOp (operand * op, iCode * ic)
4219 {
4220   /* if true symbol then needs to be assigned */
4221   if (IS_TRUE_SYMOP (op))
4222     return NULL;
4223
4224   /* if this has register type condition and
4225      the next instruction is ifx with the same operand
4226      and live to of the operand is upto the ifx only then */
4227   if (ic->next &&
4228       ic->next->op == IFX &&
4229       IC_COND (ic->next)->key == op->key &&
4230       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4231     return ic->next;
4232
4233   return NULL;
4234 }
4235
4236 static bool
4237 genPointerGetSetOfs (iCode *ic)
4238 {
4239   iCode *lic = ic->next;
4240   bool pset, pget;
4241   int offset, size;
4242   symbol *sym;
4243   asmop *derefaop;
4244
4245   /* Make sure we have a next iCode */
4246   D(emitcode("","; checking lic"));
4247   if (!lic)
4248     return FALSE;
4249
4250   /* Make sure the result of the addition is an iCode */
4251   D(emitcode("","; checking IS_ITEMP"));
4252   if (!IS_ITEMP (IC_RESULT (ic)))
4253     return FALSE;
4254
4255   /* Make sure the next iCode is a pointer set or get */
4256   pset = POINTER_SET(lic);
4257   pget = POINTER_GET(lic);
4258   D(emitcode("","; pset=%d, pget=%d",pset,pget));
4259   if (!pset && !pget)
4260     return FALSE;
4261
4262   /* Make sure this is the only use of the pointer */
4263   if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4264     return FALSE;
4265     
4266   D(emitcode("", "; checking pset operandsEqu"));
4267   if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4268     return FALSE;
4269
4270   D(emitcode("", "; checking pget operandsEqu"));
4271   if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4272     return FALSE;
4273
4274   D(emitcode("", "; checking IS_SYMOP"));
4275   if (!IS_SYMOP (IC_LEFT (ic)))
4276     return FALSE;
4277
4278   D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4279   if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4280     return FALSE;
4281
4282   sym = OP_SYMBOL (IC_LEFT (ic));
4283   
4284   D(emitcode("", "; checking remat"));
4285   if (!sym->remat)
4286     return FALSE;
4287     
4288   
4289   if (pget)
4290     {
4291       D(emitcode (";     genPointerGetOfs",""));
4292       aopOp (IC_LEFT(ic), ic, FALSE);
4293       derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4294       freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4295       
4296       aopOp (IC_RIGHT(ic), ic, FALSE);
4297       aopOp (IC_RESULT(lic), lic, FALSE);
4298
4299       if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4300         {
4301           if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4302             {
4303               loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4304               loadRegFromConst (hc08_reg_h, zero);
4305             }
4306           else
4307             {
4308               loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4309               transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4310               emitcode ("rola","");
4311               emitcode ("clra","");
4312               emitcode ("sbc", "#0");
4313               hc08_useReg (hc08_reg_a);
4314               transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4315            }
4316         }
4317       else
4318         loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4319       size = AOP_SIZE (IC_RESULT(lic));
4320       derefaop->size = size;
4321       offset=0;
4322       
4323       while (size--)
4324         {
4325           emitcode ("lda", "%s,x",
4326                     aopAdrStr (derefaop, offset, TRUE));
4327           hc08_useReg (hc08_reg_a);
4328           storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4329           hc08_freeReg (hc08_reg_a);
4330         }
4331
4332       lic->generated = 1;
4333       hc08_freeReg (hc08_reg_hx);
4334
4335       freeAsmop (NULL, derefaop, ic, TRUE);
4336       freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4337       freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4338       
4339       return TRUE;
4340     }
4341
4342   if (pset)
4343     {
4344       D(emitcode (";     genPointerSetOfs",""));
4345       aopOp (IC_LEFT(ic), ic, FALSE);
4346       derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4347       freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4348
4349       aopOp (IC_RIGHT(ic), ic, FALSE);
4350       aopOp (IC_RIGHT(lic), lic, FALSE);
4351       
4352       if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4353         {
4354           if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4355             {
4356               loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4357               loadRegFromConst (hc08_reg_h, zero);
4358             }
4359           else
4360             {
4361               loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4362               transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4363               emitcode ("rola","");
4364               emitcode ("clra","");
4365               emitcode ("sbc", "#0");
4366               hc08_useReg (hc08_reg_a);
4367               transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4368            }
4369         }
4370       else
4371         loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4372       size = AOP_SIZE (IC_RIGHT(lic));
4373       derefaop->size = size;
4374       offset=0;
4375       
4376       while (size--)
4377         {
4378           loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4379           emitcode ("sta", "%s,x",
4380                     aopAdrStr (derefaop, offset, TRUE));
4381           hc08_freeReg (hc08_reg_a);
4382           offset++;
4383         }
4384
4385       lic->generated = 1;
4386       hc08_freeReg (hc08_reg_hx);
4387
4388       freeAsmop (NULL, derefaop, ic, TRUE);
4389       freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4390       freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4391       
4392       return TRUE;
4393     }
4394     
4395   return FALSE;
4396 }
4397
4398
4399 /*-----------------------------------------------------------------*/
4400 /* hasInc - operand is incremented before any other use            */
4401 /*-----------------------------------------------------------------*/
4402 static iCode *
4403 hasInc (operand *op, iCode *ic,int osize)
4404 {
4405   sym_link *type = operandType(op);
4406   sym_link *retype = getSpec (type);
4407   iCode *lic = ic->next;
4408   int isize ;
4409   
4410   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4411   if (!IS_SYMOP(op)) return NULL;
4412
4413   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4414   if (IS_AGGREGATE(type->next)) return NULL;
4415   if (osize != (isize = getSize(type->next))) return NULL;
4416
4417   while (lic) {
4418     /* if operand of the form op = op + <sizeof *op> */
4419     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4420         isOperandEqual(IC_RESULT(lic),op) && 
4421         isOperandLiteral(IC_RIGHT(lic)) &&
4422         operandLitValue(IC_RIGHT(lic)) == isize) {
4423       return lic;
4424     }
4425     /* if the operand used or deffed */
4426     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4427       return NULL;
4428     }
4429     /* if GOTO or IFX */
4430     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4431     lic = lic->next;
4432   }
4433   return NULL;
4434 }
4435
4436 /*-----------------------------------------------------------------*/
4437 /* genAndOp - for && operation                                     */
4438 /*-----------------------------------------------------------------*/
4439 static void
4440 genAndOp (iCode * ic)
4441 {
4442   operand *left, *right, *result;
4443   symbol *tlbl, *tlbl0;
4444
4445   D(emitcode (";     genAndOp",""));
4446
4447   /* note here that && operations that are in an
4448      if statement are taken away by backPatchLabels
4449      only those used in arthmetic operations remain */
4450   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4451   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4452   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4453
4454   tlbl = newiTempLabel (NULL);
4455   tlbl0 = newiTempLabel (NULL);
4456   
4457   asmopToBool (AOP (left), FALSE);
4458   emitBranch ("beq", tlbl0);
4459   asmopToBool (AOP (right), FALSE);
4460   emitBranch ("beq", tlbl0);
4461   loadRegFromConst (hc08_reg_a,one);
4462   emitBranch ("bra", tlbl);
4463   emitLabel (tlbl0);
4464   loadRegFromConst (hc08_reg_a,zero);
4465   emitLabel (tlbl);
4466
4467   hc08_useReg (hc08_reg_a);
4468   hc08_freeReg (hc08_reg_a);
4469   
4470   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4471
4472   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4473   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4474   freeAsmop (result, NULL, ic, TRUE);
4475 }
4476
4477
4478 /*-----------------------------------------------------------------*/
4479 /* genOrOp - for || operation                                      */
4480 /*-----------------------------------------------------------------*/
4481 static void
4482 genOrOp (iCode * ic)
4483 {
4484   operand *left, *right, *result;
4485   symbol *tlbl, *tlbl0;
4486
4487   D(emitcode (";     genOrOp",""));
4488
4489   /* note here that || operations that are in an
4490      if statement are taken away by backPatchLabels
4491      only those used in arthmetic operations remain */
4492   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4493   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4494   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4495
4496   tlbl = newiTempLabel (NULL);
4497   tlbl0 = newiTempLabel (NULL);
4498   
4499   asmopToBool (AOP (left), FALSE);
4500   emitBranch ("bne", tlbl0);
4501   asmopToBool (AOP (right), FALSE);
4502   emitBranch ("bne", tlbl0);
4503   loadRegFromConst (hc08_reg_a,zero);
4504   emitBranch ("bra", tlbl);
4505   emitLabel (tlbl0);
4506   loadRegFromConst (hc08_reg_a,one);
4507   emitLabel (tlbl);
4508
4509   hc08_useReg (hc08_reg_a);
4510   hc08_freeReg (hc08_reg_a);
4511   
4512   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4513
4514
4515   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4517   freeAsmop (result, NULL, ic, TRUE);
4518 }
4519
4520 /*-----------------------------------------------------------------*/
4521 /* isLiteralBit - test if lit == 2^n                               */
4522 /*-----------------------------------------------------------------*/
4523 static int
4524 isLiteralBit (unsigned long lit)
4525 {
4526   unsigned long pw[32] =
4527   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4528    0x100L, 0x200L, 0x400L, 0x800L,
4529    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4530    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4531    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4532    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4533    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4534   int idx;
4535
4536   for (idx = 0; idx < 32; idx++)
4537     if (lit == pw[idx])
4538       return idx + 1;
4539   return 0;
4540 }
4541
4542 #if 0
4543 /*-----------------------------------------------------------------*/
4544 /* continueIfTrue -                                                */
4545 /*-----------------------------------------------------------------*/
4546 static void
4547 continueIfTrue (iCode * ic)
4548 {
4549   if (IC_TRUE (ic))
4550     emitBranch ("jmp", IC_TRUE (ic));
4551   ic->generated = 1;
4552 }
4553
4554 /*-----------------------------------------------------------------*/
4555 /* jmpIfTrue -                                                     */
4556 /*-----------------------------------------------------------------*/
4557 static void
4558 jumpIfTrue (iCode * ic)
4559 {
4560   if (!IC_TRUE (ic))
4561     emitBranch ("jmp", IC_FALSE (ic));
4562   ic->generated = 1;
4563 }
4564
4565 /*-----------------------------------------------------------------*/
4566 /* jmpTrueOrFalse -                                                */
4567 /*-----------------------------------------------------------------*/
4568 static void
4569 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4570 {
4571   // ugly but optimized by peephole
4572   if (IC_TRUE (ic))
4573     {
4574       symbol *nlbl = newiTempLabel (NULL);
4575       emitBranch ("bra", nlbl);
4576       emitLabel (tlbl);
4577       emitBranch ("jmp", IC_TRUE (ic));
4578       emitLabel (nlbl);
4579     }
4580   else
4581     {
4582       emitBranch ("jmp", IC_FALSE (ic));
4583       emitLabel (tlbl);
4584     }
4585   ic->generated = 1;
4586 }
4587 #endif
4588
4589 /*-----------------------------------------------------------------*/
4590 /* genAnd  - code for and                                          */
4591 /*-----------------------------------------------------------------*/
4592 static void
4593 genAnd (iCode * ic, iCode * ifx)
4594 {
4595   operand *left, *right, *result;
4596   int size, offset = 0;
4597   unsigned long lit = 0L;
4598   unsigned long litinv;
4599
4600   
4601 //  int bytelit = 0;
4602 //  char buffer[10];
4603
4604   D(emitcode (";     genAnd",""));
4605
4606   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4607   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4608   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4609
4610 #ifdef DEBUG_TYPE
4611   D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4612             AOP_TYPE (result),
4613             AOP_TYPE (left), AOP_TYPE (right)));
4614   D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4615             AOP_SIZE (result),
4616             AOP_SIZE (left), AOP_SIZE (right)));
4617 #endif
4618
4619   /* if left is a literal & right is not then exchange them */
4620   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4621     {
4622       operand *tmp = right;
4623       right = left;
4624       left = tmp;
4625     }
4626
4627   /* if left is accumulator & right is not then exchange them */
4628   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4629     {
4630       operand *tmp = right;
4631       right = left;
4632       left = tmp;
4633     }
4634
4635
4636   if (AOP_TYPE (result) == AOP_CRY)
4637     {
4638       symbol *tlbl;
4639       wassertl (ifx, "AOP_CPY result without ifx");
4640       
4641       tlbl = newiTempLabel (NULL);
4642       size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4643       offset = 0;
4644       while (size--)
4645         {
4646           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4647           if ((AOP_TYPE (right) == AOP_LIT)
4648               && (((lit >> (offset*8)) & 0xff) == 0xff))
4649             emitcode ("tsta","");
4650           else
4651             accopWithAop ("and", AOP (right), offset);
4652           hc08_freeReg( hc08_reg_a);      
4653           if (size)
4654             emitBranch ("bne", tlbl);
4655           else
4656             {
4657               emitLabel (tlbl);
4658               genIfxJump (ifx, "a");
4659             }
4660           offset++;
4661         }
4662     }
4663   
4664   size = AOP_SIZE (result);
4665
4666   if (AOP_TYPE (right) == AOP_LIT)
4667     {
4668       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4669       litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4670
4671       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4672           (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4673         {
4674           int bitpos = isLiteralBit(litinv)-1;
4675           emitcode ("bclr","#%d,%s",bitpos & 7,
4676                     aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4677           goto release;
4678         }
4679     }
4680     
4681   offset = 0;
4682   while (size--)
4683     {
4684       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4685       if ((AOP_TYPE (right) != AOP_LIT)
4686           || (((lit >> (offset*8)) & 0xff) != 0xff))
4687         accopWithAop ("and", AOP (right), offset);
4688       storeRegToAop (hc08_reg_a, AOP (result), offset++);
4689       hc08_freeReg( hc08_reg_a);      
4690     }
4691
4692 release:
4693   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4694   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4695   freeAsmop (result, NULL, ic, TRUE);
4696 }
4697
4698 /*-----------------------------------------------------------------*/
4699 /* genOr  - code for or                                            */
4700 /*-----------------------------------------------------------------*/
4701 static void
4702 genOr (iCode * ic, iCode * ifx)
4703 {
4704   operand *left, *right, *result;
4705   int size, offset = 0;
4706   unsigned long lit = 0L;
4707
4708   D(emitcode (";     genOr",""));
4709
4710   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4711   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4712   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4713
4714 #ifdef DEBUG_TYPE
4715   D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4716             AOP_TYPE (result),
4717             AOP_TYPE (left), AOP_TYPE (right)));
4718   D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4719             AOP_SIZE (result),
4720             AOP_SIZE (left), AOP_SIZE (right)));
4721 #endif
4722
4723   /* if left is a literal & right is not then exchange them */
4724   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4725     {
4726       operand *tmp = right;
4727       right = left;
4728       left = tmp;
4729     }
4730
4731   /* if left is accumulator & right is not then exchange them */
4732   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4733     {
4734       operand *tmp = right;
4735       right = left;
4736       left = tmp;
4737     }
4738
4739   if (AOP_TYPE (result) == AOP_CRY)
4740     {
4741       symbol *tlbl;
4742       wassertl (ifx, "AOP_CPY result without ifx");
4743       
4744       tlbl = newiTempLabel (NULL);
4745       size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4746       offset = 0;
4747       while (size--)
4748         {
4749           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4750           if ((AOP_TYPE (right) == AOP_LIT)
4751               && (((lit >> (offset*8)) & 0xff) == 0))
4752             emitcode ("tsta","");
4753           else
4754             accopWithAop ("ora", AOP (right), offset);
4755           hc08_freeReg( hc08_reg_a);      
4756           if (size)
4757             emitBranch ("bne", tlbl);
4758           else
4759             {
4760               emitLabel (tlbl);
4761               genIfxJump (ifx, "a");
4762             }
4763           offset++;
4764         }
4765     }
4766   
4767   if (AOP_TYPE (right) == AOP_LIT)
4768     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4769
4770   size = AOP_SIZE (result);
4771
4772   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4773       (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4774       (AOP_TYPE (left) == AOP_DIR))
4775     {
4776       int bitpos = isLiteralBit(lit)-1;
4777       emitcode ("bset","#%d,%s",bitpos & 7,
4778                 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4779       goto release;
4780     }
4781     
4782   offset = 0;
4783   while (size--)
4784     {
4785       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4786       accopWithAop ("ora", AOP (right), offset);
4787       storeRegToAop (hc08_reg_a, AOP (result), offset++);
4788       hc08_freeReg( hc08_reg_a);      
4789     }
4790
4791
4792 release:
4793   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4794   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4795   freeAsmop (result, NULL, ic, TRUE);
4796 }
4797
4798 /*-----------------------------------------------------------------*/
4799 /* genXor - code for xclusive or                                   */
4800 /*-----------------------------------------------------------------*/
4801 static void
4802 genXor (iCode * ic, iCode * ifx)
4803 {
4804   operand *left, *right, *result;
4805   int size, offset = 0;
4806   unsigned long lit = 0L;
4807
4808   D(emitcode (";     genXor",""));
4809
4810   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4811   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4812   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4813
4814 #ifdef DEBUG_TYPE
4815   D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4816             AOP_TYPE (result),
4817             AOP_TYPE (left), AOP_TYPE (right)));
4818   D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4819             AOP_SIZE (result),
4820             AOP_SIZE (left), AOP_SIZE (right)));
4821 #endif
4822
4823   /* if left is a literal & right is not ||
4824      if left needs acc & right does not */
4825   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4826     {
4827       operand *tmp = right;
4828       right = left;
4829       left = tmp;
4830     }
4831
4832   /* if left is accumulator & right is not then exchange them */
4833   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4834     {
4835       operand *tmp = right;
4836       right = left;
4837       left = tmp;
4838     }
4839
4840   if (AOP_TYPE (result) == AOP_CRY)
4841     {
4842       symbol *tlbl;
4843       wassertl (ifx, "AOP_CPY result without ifx");
4844       
4845       tlbl = newiTempLabel (NULL);
4846       size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4847       offset = 0;
4848       while (size--)
4849         {
4850           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4851           if ((AOP_TYPE (right) == AOP_LIT)
4852               && (((lit >> (offset*8)) & 0xff) == 0))
4853             emitcode ("tsta","");
4854           else
4855             accopWithAop ("eor", AOP (right), offset);
4856           hc08_freeReg( hc08_reg_a);      
4857           if (size)
4858             emitBranch ("bne", tlbl);
4859           else
4860             {
4861               emitLabel (tlbl);
4862               genIfxJump (ifx, "a");
4863             }
4864           offset++;
4865         }
4866     }
4867     
4868   if (AOP_TYPE (right) == AOP_LIT)
4869     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4870
4871   size = AOP_SIZE (result);
4872   offset = 0;
4873   while (size--)
4874     {
4875       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4876       accopWithAop ("eor", AOP (right), offset);
4877       storeRegToAop (hc08_reg_a, AOP (result), offset++);
4878       hc08_freeReg( hc08_reg_a);      
4879     }
4880
4881 //release:
4882   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4883   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4884   freeAsmop (result, NULL, ic, TRUE);
4885 }
4886
4887 static void
4888 emitinline (iCode * ic, char *inlin)
4889 {
4890   char buffer[512];
4891   char *symname;
4892   char c;
4893   char *bp=buffer;
4894   symbol *sym, *tempsym;
4895   asmop *aop;
4896   char *l;
4897   
4898   while (*inlin)
4899     {
4900       if (*inlin == '_')
4901         {
4902           symname = ++inlin;
4903           while (isalnum(*inlin) || (*inlin == '_'))
4904             inlin++;
4905           c = *inlin;
4906           *inlin = '\0';
4907           //printf("Found possible symbol '%s'\n",symname);
4908           tempsym = newSymbol (symname, ic->level);
4909           tempsym->block = ic->block;
4910           sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4911           *inlin = c;
4912           if (!sym)
4913             {
4914               *bp++ = '_';
4915               inlin = symname;
4916             }
4917           else
4918             {
4919               aop = aopForSym (ic, sym, FALSE);
4920               l = aopAdrStr (aop, aop->size - 1, TRUE);
4921               if (*l=='#')
4922                 l++;
4923               sym->isref = 1;
4924               if (!sym->allocreq && !sym->ismyparm)
4925                 {
4926                   werror (E_ID_UNDEF, sym->name);
4927                   werror (W_CONTINUE,
4928                           "  Add 'volatile' to the variable declaration so that it\n"
4929                           "  can be referenced within inline assembly");
4930                 }
4931               //printf("Replacing with '%s'\n",l);
4932               while (*l)
4933                 {
4934                   *bp++ = *l++;
4935                   if ((2+bp-buffer)>sizeof(buffer))
4936                     goto endofline;
4937                 }
4938             }
4939         }
4940       else
4941         {
4942           *bp++ = *inlin++;
4943         }
4944       if ((2+bp-buffer)>sizeof(buffer))
4945         goto endofline;
4946     }
4947
4948 endofline:
4949   *bp = '\0';
4950
4951   if ((2+bp-buffer)>sizeof(buffer))
4952     fprintf(stderr, "Inline assembly buffer overflow\n");
4953   
4954   //printf("%s\n",buffer);
4955   emitcode (buffer,"");
4956 }
4957
4958
4959 /*-----------------------------------------------------------------*/
4960 /* genInline - write the inline code out                           */
4961 /*-----------------------------------------------------------------*/
4962 static void
4963 genInline (iCode * ic)
4964 {
4965   char *buffer, *bp, *bp1;
4966
4967   D(emitcode (";     genInline",""));
4968
4969   _G.inLine += (!options.asmpeep);
4970
4971   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4972   strcpy (buffer, IC_INLINE (ic));
4973
4974   /* emit each line as a code */
4975   while (*bp)
4976     {
4977       if (*bp == '\n')
4978         {
4979           *bp++ = '\0';
4980           /* emitcode (bp1, ""); */
4981           emitinline (ic, bp1);
4982           bp1 = bp;
4983         }
4984       else
4985         {
4986           if (*bp == ':')
4987             {
4988               bp++;
4989               *bp = '\0';
4990               bp++;
4991               emitcode (bp1, "");
4992               bp1 = bp;
4993             }
4994           else
4995             bp++;
4996         }
4997     }
4998   if (bp1 != bp)
4999     {
5000       /* emitcode (bp1, ""); */
5001       emitinline (ic, bp1);
5002     }
5003   /*     emitcode("",buffer); */
5004   _G.inLine -= (!options.asmpeep);
5005 }
5006
5007 /*-----------------------------------------------------------------*/
5008 /* genRRC - rotate right with carry                                */
5009 /*-----------------------------------------------------------------*/
5010 static void
5011 genRRC (iCode * ic)
5012 {
5013   operand *left, *result;
5014   int size, offset = 0;
5015   bool needpula = FALSE;
5016   bool resultInA = FALSE;
5017   char *shift;
5018
5019   D(emitcode (";     genRRC",""));
5020
5021   /* rotate right with carry */
5022   left = IC_LEFT (ic);
5023   result = IC_RESULT (ic);
5024   aopOp (left, ic, FALSE);
5025   aopOp (result, ic, FALSE);
5026
5027   if ((AOP_TYPE (result) == AOP_REG)
5028       && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5029    resultInA = TRUE;
5030
5031   size = AOP_SIZE (result);
5032   offset = size-1;
5033
5034   shift="lsr";
5035   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5036     {
5037       while (size--)
5038         {
5039           rmwWithAop (shift, AOP (result), offset--);
5040           shift="ror";
5041         }
5042     }
5043   else
5044     {
5045       while (size--)
5046         {
5047           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5048           rmwWithReg (shift, hc08_reg_a);
5049           storeRegToAop (hc08_reg_a, AOP (result), offset--);
5050           hc08_freeReg (hc08_reg_a);
5051           shift="ror";
5052         }
5053     }
5054
5055   if ((!hc08_reg_a->isFree) || resultInA)
5056     {
5057       pushReg (hc08_reg_a, TRUE);
5058       needpula = TRUE;
5059     }
5060
5061   /* now we need to put the carry into the
5062      highest order byte of the result */
5063   offset = AOP_SIZE (result) - 1;
5064   emitcode ("clra","");
5065   emitcode ("rora","");
5066   hc08_dirtyReg (hc08_reg_a, FALSE);
5067   if (resultInA)
5068     {
5069       emitcode ("ora", "1,s");
5070       emitcode ("ais", "#1");
5071       hc08_dirtyReg (hc08_reg_a, FALSE);
5072       needpula = FALSE;
5073     }
5074   else
5075     accopWithAop ("ora", AOP (result), offset);
5076   storeRegToAop (hc08_reg_a, AOP (result), offset);
5077
5078   pullOrFreeReg (hc08_reg_a, needpula);
5079
5080   freeAsmop (left, NULL, ic, TRUE);
5081   freeAsmop (result, NULL, ic, TRUE);
5082 }
5083
5084 /*-----------------------------------------------------------------*/
5085 /* genRLC - generate code for rotate left with carry               */
5086 /*-----------------------------------------------------------------*/
5087 static void
5088 genRLC (iCode * ic)
5089 {
5090   operand *left, *result;
5091   int size, offset = 0;
5092   char *shift;
5093   bool resultInA = FALSE;
5094   bool needpula = FALSE;
5095
5096   D(emitcode (";     genRLC",""));
5097
5098   /* rotate right with carry */
5099   left = IC_LEFT (ic);
5100   result = IC_RESULT (ic);
5101   aopOp (left, ic, FALSE);
5102   aopOp (result, ic, FALSE);
5103
5104   if ((AOP_TYPE (result) == AOP_REG)
5105       && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5106    resultInA = TRUE;
5107
5108   size = AOP_SIZE (result);
5109   offset = 0;
5110
5111   shift="lsl";
5112   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5113     {
5114       while (size--)
5115         {
5116           rmwWithAop (shift, AOP (result), offset--);
5117           shift="rol";
5118         }
5119     }
5120   else
5121     {
5122       while (size--)
5123         {
5124           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5125           rmwWithReg (shift, hc08_reg_a);
5126           storeRegToAop (hc08_reg_a, AOP (result), offset++);
5127           hc08_freeReg (hc08_reg_a);
5128           shift="rol";
5129         }
5130     }
5131
5132   if ((!hc08_reg_a->isFree) || resultInA)
5133     {
5134       pushReg (hc08_reg_a, TRUE);
5135       needpula = TRUE;
5136     }
5137
5138   /* now we need to put the carry into the
5139      lowest order byte of the result */
5140   offset = 0;
5141   emitcode ("clra","");
5142   emitcode ("rola","");
5143   hc08_dirtyReg (hc08_reg_a, FALSE);
5144   if (resultInA)
5145     {
5146       emitcode ("ora", "1,s");
5147       emitcode ("ais", "#1");
5148       hc08_dirtyReg (hc08_reg_a, FALSE);
5149       needpula = FALSE;
5150     }
5151   else
5152     accopWithAop ("ora", AOP (result), offset);
5153   storeRegToAop (hc08_reg_a, AOP (result), offset);
5154
5155   pullOrFreeReg (hc08_reg_a, needpula);
5156
5157   freeAsmop (left, NULL, ic, TRUE);
5158   freeAsmop (result, NULL, ic, TRUE);
5159 }
5160
5161 /*-----------------------------------------------------------------*/
5162 /* genGetHbit - generates code get highest order bit               */
5163 /*-----------------------------------------------------------------*/
5164 static void
5165 genGetHbit (iCode * ic)
5166 {
5167   operand *left, *result;
5168
5169   D(emitcode (";     genGetHbit",""));
5170
5171   left = IC_LEFT (ic);
5172   result = IC_RESULT (ic);
5173   aopOp (left, ic, FALSE);
5174   aopOp (result, ic, FALSE);
5175
5176   /* get the highest order byte into a */
5177   loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5178   emitcode ("rola", "");
5179   emitcode ("clra", "");
5180   emitcode ("rola", "");
5181   hc08_dirtyReg (hc08_reg_a, FALSE);
5182   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5183   hc08_freeReg (hc08_reg_a);
5184   
5185   freeAsmop (left, NULL, ic, TRUE);
5186   freeAsmop (result, NULL, ic, TRUE);
5187 }
5188
5189 /*-----------------------------------------------------------------*/
5190 /* genSwap - generates code to swap nibbles or bytes               */
5191 /*-----------------------------------------------------------------*/
5192 static void
5193 genSwap (iCode * ic)
5194 {
5195   operand *left, *result;
5196
5197   D(emitcode (";     genSwap",""));
5198
5199   left = IC_LEFT (ic);
5200   result = IC_RESULT (ic);
5201   aopOp (left, ic, FALSE);
5202   aopOp (result, ic, FALSE);
5203   
5204   switch (AOP_SIZE (left))
5205     {
5206     case 1: /* swap nibbles in byte */
5207       loadRegFromAop (hc08_reg_a, AOP (left), 0);
5208       emitcode ("nsa", "");
5209       hc08_dirtyReg (hc08_reg_a, FALSE);
5210       storeRegToAop (hc08_reg_a, AOP (result), 0);
5211       hc08_freeReg (hc08_reg_a);
5212       break;
5213     case 2: /* swap bytes in a word */
5214       if (operandsEqu (left, result))
5215         {
5216           loadRegFromAop (hc08_reg_a, AOP (left), 0);
5217           hc08_useReg (hc08_reg_a);
5218           transferAopAop (AOP (left), 1, AOP (result), 0);
5219           storeRegToAop (hc08_reg_a, AOP (result), 1);
5220           hc08_freeReg (hc08_reg_a);
5221         }
5222       else
5223         {
5224           transferAopAop (AOP (left), 0, AOP (result), 1);
5225           transferAopAop (AOP (left), 1, AOP (result), 0);
5226         }
5227       break;
5228     default:
5229       wassertl(FALSE, "unsupported SWAP operand size");
5230     }
5231     
5232   freeAsmop (left, NULL, ic, TRUE);
5233   freeAsmop (result, NULL, ic, TRUE);
5234 }
5235
5236 #if 0
5237 /*-----------------------------------------------------------------*/
5238 /* AccRol - rotate left accumulator by known count                 */
5239 /*-----------------------------------------------------------------*/
5240 static void
5241 AccRol (int shCount)
5242 {
5243   shCount &= 0x0007;            // shCount : 0..7
5244
5245   switch (shCount)
5246     {
5247     case 0:
5248       break;
5249     case 1:
5250       emitcode ("rola", "");    /* 1 cycle */
5251       break;
5252     case 2:
5253       emitcode ("rola", "");    /* 1 cycle */
5254       emitcode ("rola", "");    /* 1 cycle */
5255       break;
5256     case 3:
5257       emitcode ("nsa", "");
5258       emitcode ("rora", "");
5259       break;
5260     case 4:
5261       emitcode ("nsa", "");     /* 3 cycles */
5262       break;
5263     case 5:
5264       emitcode ("nsa", "");     /* 3 cycles */
5265       emitcode ("rola", "");    /* 1 cycle */
5266       break;
5267     case 6:
5268       emitcode ("nsa", "");     /* 3 cycles */
5269       emitcode ("rola", "");    /* 1 cycle */
5270       emitcode ("rola", "");    /* 1 cycle */
5271       break;
5272     case 7:
5273       emitcode ("nsa", "");     /* 3 cycles */
5274       emitcode ("rola", "");    /* 1 cycle */
5275       emitcode ("rola", "");    /* 1 cycle */
5276       emitcode ("rola", "");    /* 1 cycle */
5277       break;
5278     }
5279 }
5280 #endif
5281
5282
5283 /*-----------------------------------------------------------------*/
5284 /* AccLsh - left shift accumulator by known count                  */
5285 /*-----------------------------------------------------------------*/
5286 static void
5287 AccLsh (int shCount)
5288 {
5289   int i;
5290   
5291   shCount &= 0x0007;            // shCount : 0..7
5292
5293   /* Shift counts of 4 and 5 are currently optimized for code size.        */
5294   /* Falling through to the unrolled loop would be optimal for code speed. */
5295   /* For shift counts of 6 and 7, the unrolled loop is never optimal.      */
5296   switch (shCount)
5297     {
5298     case 4:
5299       accopWithMisc ("nsa", "");
5300       accopWithMisc ("and", "#0xf0");
5301       /* total: 5 cycles, 3 bytes */
5302       return;
5303     case 5:
5304       accopWithMisc ("nsa", "");
5305       accopWithMisc ("and", "#0xf0");
5306       accopWithMisc ("lsla", "");
5307       /* total: 6 cycles, 4 bytes */
5308       return;
5309     case 6:
5310       accopWithMisc ("rora", "");
5311       accopWithMisc ("rora", "");
5312       accopWithMisc ("rora", "");
5313       accopWithMisc ("and", "#0xc0");
5314       /* total: 5 cycles, 5 bytes */
5315       return;
5316     case 7:
5317       accopWithMisc ("rora", "");
5318       accopWithMisc ("clra", "");
5319       accopWithMisc ("rora", "");
5320       /* total: 3 cycles, 3 bytes */
5321       return;
5322     }
5323
5324     /* lsla is only 1 cycle and byte, so an unrolled loop is often  */
5325     /* the fastest (shCount<6) and shortest (shCount<4).            */
5326     for (i=0;i<shCount;i++)
5327       accopWithMisc ("lsla", "");
5328 }
5329
5330
5331 /*-----------------------------------------------------------------*/
5332 /* AccSRsh - signed right shift accumulator by known count         */
5333 /*-----------------------------------------------------------------*/
5334 static void
5335 AccSRsh (int shCount)
5336 {
5337   int i;
5338   
5339   shCount &= 0x0007;            // shCount : 0..7
5340
5341   if (shCount == 7)
5342     {
5343       accopWithMisc ("rola", "");
5344       accopWithMisc ("clra", "");
5345       accopWithMisc ("sbc", zero);
5346       /* total: 4 cycles, 4 bytes */
5347       return;
5348     }
5349
5350     for (i=0;i<shCount;i++)
5351       accopWithMisc ("asra", "");
5352 }
5353
5354 /*-----------------------------------------------------------------*/
5355 /* AccRsh - right shift accumulator by known count                 */
5356 /*-----------------------------------------------------------------*/
5357 static void
5358 AccRsh (int shCount, bool sign)
5359 {
5360   int i;
5361   
5362   if (sign)
5363     {
5364       AccSRsh (shCount);
5365       return;
5366     }
5367   
5368   shCount &= 0x0007;            // shCount : 0..7
5369
5370   /* Shift counts of 4 and 5 are currently optimized for code size.        */
5371   /* Falling through to the unrolled loop would be optimal for code speed. */
5372   /* For shift counts of 6 and 7, the unrolled loop is never optimal.      */
5373   switch (shCount)
5374     {
5375     case 4:
5376       accopWithMisc ("nsa", "");
5377       accopWithMisc ("and", "#0x0f");
5378       /* total: 5 cycles, 3 bytes */
5379       return;
5380     case 5:
5381       accopWithMisc ("nsa", "");
5382       accopWithMisc ("and", "#0x0f");
5383       accopWithMisc ("lsra", "");
5384       /* total: 6 cycles, 4 bytes */
5385       return;
5386     case 6:
5387       accopWithMisc ("rola", "");
5388       accopWithMisc ("rola", "");
5389       accopWithMisc ("rola", "");
5390       accopWithMisc ("and", "#0x03");
5391       /* total: 5 cycles, 5 bytes */
5392       return;
5393     case 7:
5394       accopWithMisc ("rola", "");
5395       accopWithMisc ("clra", "");
5396       accopWithMisc ("rola", "");
5397       /* total: 3 cycles, 3 bytes */
5398       return;
5399     }
5400
5401     /* lsra is only 1 cycle and byte, so an unrolled loop is often  */
5402     /* the fastest (shCount<6) and shortest (shCount<4).            */
5403     for (i=0;i<shCount;i++)
5404       accopWithMisc ("lsra", "");
5405 }
5406
5407
5408 /*-----------------------------------------------------------------*/
5409 /* XAccLsh - left shift register pair XA by known count            */
5410 /*-----------------------------------------------------------------*/
5411 static void
5412 XAccLsh (int shCount)
5413 {
5414   int i;
5415   
5416   shCount &= 0x000f;            // shCount : 0..15
5417
5418   if (shCount>=8)
5419     {
5420       AccLsh (shCount-8);
5421       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5422       loadRegFromConst (hc08_reg_a, zero);
5423       return;
5424     }
5425
5426   /* if we can beat 2n cycles or bytes for some special case, do it here */
5427   switch (shCount)
5428     {
5429     case 7:
5430       /*          bytes  cycles     reg x      reg a   carry
5431       **                          abcd efgh  ijkl mnop   ?
5432       **   lsrx       1  1        0abc defg  ijkl mnop   h
5433       **   rora       1  1        0abc defg  hijk lmno   p
5434       **   tax        1  1        hijk lmno  hijk lmno   p
5435       **   clra       1  1        hijk lmno  0000 0000   p
5436       **   rora       1  1        hijk lmno  p000 0000   0
5437       ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5438       */
5439       rmwWithReg ("lsr", hc08_reg_x);
5440       rmwWithReg ("ror", hc08_reg_a);
5441       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5442       loadRegFromConst (hc08_reg_a, zero);
5443       rmwWithReg ("ror", hc08_reg_a);
5444       return;
5445
5446     default:
5447       ;
5448     }
5449
5450   /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often  */
5451   /* the fastest and shortest.                                           */
5452   for (i=0;i<shCount;i++)
5453     {
5454       rmwWithReg ("lsl", hc08_reg_a);
5455       rmwWithReg ("rol", hc08_reg_x);
5456     }
5457 }
5458
5459 /*-----------------------------------------------------------------*/
5460 /* XAccSRsh - signed right shift register pair XA by known count   */
5461 /*-----------------------------------------------------------------*/
5462 static void
5463 XAccSRsh (int shCount)
5464 {
5465   int i;
5466   
5467   shCount &= 0x000f;            // shCount : 0..7
5468
5469   /* if we can beat 2n cycles or bytes for some special case, do it here */
5470   switch (shCount)
5471     {
5472     case 15:
5473       /*          bytes  cycles     reg x      reg a   carry
5474       **                          abcd efgh  ijkl mnop   ?
5475       **   lslx       1  1        bcde fgh0  ijkl mnop   a
5476       **   clra       1  1        bcde fgh0  0000 0000   a
5477       **   rola       1  1        bcde fgh0  0000 000a   0
5478       **   nega       1  1        bcde fgh0  aaaa aaaa   a
5479       **   tax        1  1        aaaa aaaa  aaaa aaaa   a
5480       ** total: 5 cycles, 5 bytes
5481       */
5482       rmwWithReg ("lsl", hc08_reg_x);
5483       loadRegFromConst (hc08_reg_a, zero);
5484       rmwWithReg ("rol", hc08_reg_a);
5485       rmwWithReg ("neg", hc08_reg_a);
5486       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5487       return;
5488
5489     case 14:
5490     case 13:
5491     case 12:
5492     case 11:
5493     case 10:
5494     case 9:
5495     case 8:
5496       /*          bytes  cycles     reg x      reg a   carry
5497       **                          abcd efgh  ijkl mnop   ?
5498       **   txa        1  1        abcd efgh  abcd efgh   ?
5499       **   (AccSRsh) <8 <8        abcd efgh  LSBresult   ?
5500       **   lsla       1  1        abcd efgh  ???? ????   a
5501       **   clrx       1  1        0000 0000  ???? ????   a
5502       **   rolx       1  1        0000 000a  ???? ????   0
5503       **   negx       1  1        aaaa aaaa  ???? ????   a
5504       **   rora       1  1        aaaa aaaa  LSBresult   0
5505       ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5506       */
5507       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5508       AccSRsh (shCount-8);
5509       rmwWithReg ("lsl", hc08_reg_a);
5510       loadRegFromConst (hc08_reg_x, zero);
5511       rmwWithReg ("rol", hc08_reg_x);
5512       rmwWithReg ("neg", hc08_reg_x);
5513       rmwWithReg ("ror", hc08_reg_a);
5514       return;
5515
5516     default:
5517       ;
5518     }
5519
5520   /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often  */
5521   /* the fastest and shortest.                                           */
5522   for (i=0;i<shCount;i++)
5523     {
5524       rmwWithReg ("asr", hc08_reg_x);
5525       rmwWithReg ("ror", hc08_reg_a);
5526     }
5527 }
5528
5529 /*-----------------------------------------------------------------*/
5530 /* XAccRsh - right shift register pair XA by known count           */
5531 /*-----------------------------------------------------------------*/
5532 static void
5533 XAccRsh (int shCount, bool sign)
5534 {
5535   int i;
5536   
5537   if (sign)
5538     {
5539       XAccSRsh (shCount);
5540       return;
5541     }
5542   
5543   shCount &= 0x000f;            // shCount : 0..f
5544
5545   /* if we can beat 2n cycles or bytes for some special case, do it here */
5546   switch (shCount)
5547     {
5548     case 15:
5549       /*          bytes  cycles     reg x      reg a   carry
5550       **                          abcd efgh  ijkl mnop   ?
5551       **   clra       1  1        abcd efgh  0000 0000   a
5552       **   lslx       1  1        bcde fgh0  0000 0000   a
5553       **   rola       1  1        bcde fgh0  0000 000a   0
5554       **   clrx       1  1        0000 0000  0000 000a   0
5555       ** total: 4 cycles, 4 bytes
5556       */
5557       loadRegFromConst (hc08_reg_x, zero);
5558       rmwWithReg ("lsl", hc08_reg_x);
5559       rmwWithReg ("rol", hc08_reg_a);
5560       loadRegFromConst (hc08_reg_a, zero);
5561       return;
5562
5563     case 14:
5564       /*          bytes  cycles     reg x      reg a   carry
5565       **                          abcd efgh  ijkl mnop   ?
5566       **   clra       1  1        abcd efgh  0000 0000   a
5567       **   lslx       1  1        bcde fgh0  0000 0000   a
5568       **   rola       1  1        bcde fgh0  0000 000a   0
5569       **   lslx       1  1        cdef gh00  0000 000a   b
5570       **   rola       1  1        cdef gh00  0000 00ab   0
5571       **   clrx       1  1        0000 0000  0000 00ab   0
5572       ** total: 6 cycles, 6 bytes
5573       */
5574       loadRegFromConst (hc08_reg_x, zero);
5575       rmwWithReg ("lsl", hc08_reg_x);
5576       rmwWithReg ("rol", hc08_reg_a);
5577       rmwWithReg ("lsl", hc08_reg_x);
5578       rmwWithReg ("rol", hc08_reg_a);
5579       loadRegFromConst (hc08_reg_a, zero);
5580       return;
5581
5582     case 13:
5583     case 12:
5584     case 11:
5585     case 10:
5586     case 9:
5587     case 8:
5588       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5589       AccRsh (shCount-8, FALSE);
5590       loadRegFromConst (hc08_reg_x, zero);
5591       return;
5592
5593     case 7:
5594       /*          bytes  cycles     reg x      reg a   carry
5595       **                          abcd efgh  ijkl mnop   ?
5596       **   lsla       1  1        abcd efgh  jklm nop0   i
5597       **   txa        1  1        abcd efgh  abcd efgh   i
5598       **   rola       1  1        abcd efgh  bcde fghi   a
5599       **   clrx       1  1        0000 0000  bcde fghi   a
5600       **   rolx       1  1        0000 000a  bcde fghi   0
5601       ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5602       */
5603       rmwWithReg ("lsl", hc08_reg_a);
5604       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5605       rmwWithReg ("rol", hc08_reg_a);
5606       loadRegFromConst (hc08_reg_x, zero);
5607       rmwWithReg ("rol", hc08_reg_x);
5608       return;
5609     case 6:
5610       /*          bytes  cycles     reg x      reg a   carry
5611       **                          abcd efgh  ijkl mnop   ?
5612       **   lsla       1  1        abcd efgh  jklm nop0   i
5613       **   rolx       1  1        bcde fghi  jklm nop0   a
5614       **   rola       1  1        bcde fghi  klmn op0a   j
5615       **   rolx       1  1        cdef ghij  klmn op0a   b
5616       **   rola       1  1        cdef ghij  lmno p0ab   k
5617       **   and #3     2  2        cdef ghij  0000 00ab   k
5618       **   psha       1  2        cdef ghij  0000 00ab   k
5619       **   txa        1  1        cdef ghij  cdef ghij   k
5620       **   pula       1  2        0000 00ab  cdef ghij   k
5621       ** total: 12 cycles, 10 bytes (beats 12 bytes)
5622       */
5623     default:
5624       ;
5625     }
5626
5627   /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often  */
5628   /* the fastest and shortest.                                           */
5629   for (i=0;i<shCount;i++)
5630     {
5631       rmwWithReg ("lsr", hc08_reg_x);
5632       rmwWithReg ("ror", hc08_reg_a);
5633     }
5634
5635 }
5636
5637
5638 #if 0
5639 /*-----------------------------------------------------------------*/
5640 /* shiftR1Left2Result - shift right one byte from left to result   */
5641 /*-----------------------------------------------------------------*/
5642 static void
5643 shiftR1Left2Result (operand * left, int offl,
5644                     operand * result, int offr,
5645                     int shCount, int sign)
5646 {
5647   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5648   /* shift right accumulator */
5649   AccRsh (shCount, sign);
5650   storeRegToAop (hc08_reg_a, AOP (result), offr);
5651 }
5652 #endif
5653
5654 /*-----------------------------------------------------------------*/
5655 /* shiftL1Left2Result - shift left one byte from left to result    */
5656 /*-----------------------------------------------------------------*/
5657 static void
5658 shiftL1Left2Result (operand * left, int offl,
5659                     operand * result, int offr, int shCount)
5660 {
5661   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5662   /* shift left accumulator */
5663   AccLsh (shCount);
5664   storeRegToAop (hc08_reg_a, AOP (result), offr);
5665 }
5666
5667 /*-----------------------------------------------------------------*/
5668 /* movLeft2Result - move byte from left to result                  */
5669 /*-----------------------------------------------------------------*/
5670 static void
5671 movLeft2Result (operand * left, int offl,
5672                 operand * result, int offr, int sign)
5673 {
5674   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5675     {
5676       transferAopAop (AOP (left), offl, AOP (result), offr);
5677     }
5678 }
5679
5680
5681 /*-----------------------------------------------------------------*/
5682 /* shiftL2Left2Result - shift left two bytes from left to result   */
5683 /*-----------------------------------------------------------------*/
5684 static void
5685 shiftL2Left2Result (operand * left, int offl,
5686                     operand * result, int offr, int shCount)
5687 {
5688   int i;
5689   bool needpula = FALSE;
5690   bool needpulx = FALSE;
5691
5692   if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
5693     needpula = pushRegIfUsed (hc08_reg_a);
5694   else
5695     needpula = FALSE;
5696   if (!IS_AOP_XA (AOP (left)))
5697     needpulx = pushRegIfUsed (hc08_reg_x);
5698   else
5699     needpulx = FALSE;
5700
5701   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5702
5703   switch (shCount)
5704     {
5705       case 7:
5706         rmwWithReg ("lsr", hc08_reg_x);
5707         rmwWithReg ("ror", hc08_reg_a);
5708         transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5709         rmwWithReg ("clr", hc08_reg_a);
5710         rmwWithReg ("ror", hc08_reg_a);
5711         break;
5712       default:
5713         for (i=0; i<shCount; i++)
5714           {
5715             rmwWithReg ("lsl", hc08_reg_a);
5716             rmwWithReg ("rol", hc08_reg_x);
5717           }
5718     }
5719   storeRegToAop (hc08_reg_xa, AOP (result), offl);
5720
5721   pullOrFreeReg (hc08_reg_x, needpulx);
5722   pullOrFreeReg (hc08_reg_a, needpula);
5723
5724 }
5725
5726
5727 #if 0
5728 /*-----------------------------------------------------------------*/
5729 /* shiftR2Left2Result - shift right two bytes from left to result  */
5730 /*-----------------------------------------------------------------*/
5731 static void
5732 shiftR2Left2Result (operand * left, int offl,
5733                     operand * result, int offr,
5734                     int shCount, int sign)
5735 {
5736   int i;
5737   bool needpula = FALSE;
5738   bool needpulx = FALSE;
5739   
5740   needpula = pushRegIfUsed (hc08_reg_a);
5741   needpulx = pushRegIfUsed (hc08_reg_x);
5742
5743   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5744   for (i=0; i<shCount; i++)
5745     {
5746       if (sign)
5747         rmwWithReg ("asr", hc08_reg_x);
5748       else
5749         rmwWithReg ("lsr", hc08_reg_x);
5750       rmwWithReg ("ror", hc08_reg_a);
5751     }
5752   storeRegToAop (hc08_reg_xa, AOP (result), offl);
5753
5754   pullOrFreeReg (hc08_reg_x, needpulx);
5755   pullOrFreeReg (hc08_reg_a, needpula);
5756 }
5757 #endif
5758
5759 #if 0
5760 /*-----------------------------------------------------------------*/
5761 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5762 /*-----------------------------------------------------------------*/
5763 static void
5764 shiftLLeftOrResult (operand * left, int offl,
5765                     operand * result, int offr, int shCount)
5766 {
5767   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5768   /* shift left accumulator */
5769   AccLsh (shCount);
5770   /* or with result */
5771   accopWithAop ("ora", AOP (result), offr);
5772   /* back to result */
5773   storeRegToAop (hc08_reg_a, AOP (result), offr);
5774   hc08_freeReg (hc08_reg_a);
5775 }
5776 #endif
5777
5778 /*-----------------------------------------------------------------*/
5779 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5780 /*-----------------------------------------------------------------*/
5781 static void
5782 shiftRLeftOrResult (operand * left, int offl,
5783                     operand * result, int offr, int shCount)
5784 {
5785   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5786   /* shift left accumulator */
5787   AccRsh (shCount, FALSE);
5788   /* or with result */
5789   accopWithAop ("ora", AOP (result), offr);
5790   /* back to result */
5791   storeRegToAop (hc08_reg_a, AOP (result), offr);
5792   hc08_freeReg (hc08_reg_a);
5793 }
5794
5795 /*-----------------------------------------------------------------*/
5796 /* genlshOne - left shift a one byte quantity by known count       */
5797 /*-----------------------------------------------------------------*/
5798 static void
5799 genlshOne (operand * result, operand * left, int shCount)
5800 {
5801   D(emitcode (";     genlshOne",""));
5802
5803   shiftL1Left2Result (left, LSB, result, LSB, shCount);
5804 }
5805
5806 /*-----------------------------------------------------------------*/
5807 /* genlshTwo - left shift two bytes by known amount != 0           */
5808 /*-----------------------------------------------------------------*/
5809 static void
5810 genlshTwo (operand * result, operand * left, int shCount)
5811 {
5812   int size;
5813
5814   D(emitcode (";     genlshTwo",""));
5815
5816   
5817   size = getDataSize (result);
5818
5819   /* if shCount >= 8 */
5820   if (shCount >= 8)
5821     {
5822       shCount -= 8;
5823
5824       if (size > 1)
5825         {
5826           loadRegFromAop (hc08_reg_a, AOP (left), 0);
5827           AccLsh (shCount);
5828           storeRegToAop (hc08_reg_a, AOP (result), 1);
5829         }
5830       storeConstToAop(zero, AOP (result), LSB);
5831     }
5832
5833   /*  1 <= shCount <= 7 */
5834   else
5835     {
5836       loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5837       XAccLsh (shCount);
5838       storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5839     }
5840 }
5841
5842 /*-----------------------------------------------------------------*/
5843 /* shiftLLong - shift left one long from left to result            */
5844 /* offl = LSB or MSB16                                             */
5845 /*-----------------------------------------------------------------*/
5846 static void
5847 shiftLLong (operand * left, operand * result, int offr)
5848 {
5849 //  char *l;
5850 //  int size = AOP_SIZE (result);
5851
5852   bool needpula = FALSE;
5853   bool needpulx = FALSE;
5854
5855   needpula = pushRegIfUsed (hc08_reg_a);
5856   needpulx = pushRegIfUsed (hc08_reg_x);
5857
5858   loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5859   rmwWithReg ("lsl", hc08_reg_a);
5860   rmwWithReg ("rol", hc08_reg_x);
5861   storeRegToAop (hc08_reg_xa, AOP (result), offr);
5862
5863   if (offr==LSB)
5864     {
5865       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5866       rmwWithReg ("rol", hc08_reg_a);
5867       rmwWithReg ("rol", hc08_reg_x);
5868       storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5869     }
5870   else if (offr==MSB16)
5871     {
5872       loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5873       rmwWithReg ("rol", hc08_reg_a);
5874       storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5875     }
5876
5877   pullOrFreeReg (hc08_reg_x, needpulx);
5878   pullOrFreeReg (hc08_reg_a, needpula);
5879 }
5880
5881 /*-----------------------------------------------------------------*/
5882 /* genlshFour - shift four byte by a known amount != 0             */
5883 /*-----------------------------------------------------------------*/
5884 static void
5885 genlshFour (operand * result, operand * left, int shCount)
5886 {
5887   int size;
5888
5889   D(emitcode (";     genlshFour",""));
5890
5891   size = AOP_SIZE (result);
5892
5893   /* TODO: deal with the &result == &left case */
5894
5895   /* if shifting more that 3 bytes */
5896   if (shCount >= 24)
5897     {
5898       shCount -= 24;
5899       if (shCount)
5900         /* lowest order of left goes to the highest
5901            order of the destination */
5902         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5903       else
5904         movLeft2Result (left, LSB, result, MSB32, 0);
5905       storeConstToAop (zero, AOP (result), LSB);
5906       storeConstToAop (zero, AOP (result), MSB16);
5907       storeConstToAop (zero, AOP (result), MSB24);
5908       return;
5909     }
5910
5911   /* more than two bytes */
5912   else if (shCount >= 16)
5913     {
5914       /* lower order two bytes goes to higher order two bytes */
5915       shCount -= 16;
5916       /* if some more remaining */
5917       if (shCount)
5918         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5919       else
5920         {
5921           movLeft2Result (left, MSB16, result, MSB32, 0);
5922           movLeft2Result (left, LSB, result, MSB24, 0);
5923         }
5924       storeConstToAop (zero, AOP (result), LSB);
5925       storeConstToAop (zero, AOP (result), MSB16);
5926       return;
5927     }
5928
5929   /* if more than 1 byte */
5930   else if (shCount >= 8)
5931     {
5932       /* lower order three bytes goes to higher order  three bytes */
5933       shCount -= 8;
5934       if (size == 2)
5935         {
5936           if (shCount)
5937             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5938           else
5939             movLeft2Result (left, LSB, result, MSB16, 0);
5940         }
5941       else
5942         {                       /* size = 4 */
5943           if (shCount == 0)
5944             {
5945               movLeft2Result (left, MSB24, result, MSB32, 0);
5946               movLeft2Result (left, MSB16, result, MSB24, 0);
5947               movLeft2Result (left, LSB, result, MSB16, 0);
5948               storeConstToAop (zero, AOP (result), LSB);
5949             }
5950           else if (shCount == 1)
5951             shiftLLong (left, result, MSB16);
5952           else
5953             {
5954               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5955               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5956               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5957               storeConstToAop (zero, AOP (result), LSB);
5958             }
5959         }
5960     }
5961
5962   /* 1 <= shCount <= 7 */
5963   else if (shCount <= 2)
5964     {
5965       shiftLLong (left, result, LSB);
5966       if (shCount == 2)
5967         shiftLLong (result, result, LSB);
5968     }
5969   /* 3 <= shCount <= 7, optimize */
5970   else
5971     {
5972       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5973       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5974       shiftL2Left2Result (left, LSB, result, LSB, shCount);
5975     }
5976 }
5977
5978 /*-----------------------------------------------------------------*/
5979 /* genLeftShiftLiteral - left shifting by known count              */
5980 /*-----------------------------------------------------------------*/
5981 static void
5982 genLeftShiftLiteral (operand * left,
5983                      operand * right,
5984                      operand * result,
5985                      iCode * ic)
5986 {
5987   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5988   int size;
5989
5990   D(emitcode (";     genLeftShiftLiteral",""));
5991
5992   freeAsmop (right, NULL, ic, TRUE);
5993
5994   aopOp (left, ic, FALSE);
5995   aopOp (result, ic, FALSE);
5996
5997 //  size = getSize (operandType (result));
5998   size = AOP_SIZE (result);
5999
6000 #if VIEW_SIZE
6001   D(emitcode ("; shift left ", "result %d, left %d", size,
6002             AOP_SIZE (left)));
6003 #endif
6004
6005   if (shCount == 0)
6006     {
6007       while (size--)
6008         transferAopAop( AOP(left), size, AOP(result), size);
6009     }
6010   else if (shCount >= (size * 8))
6011     {
6012       while (size--)
6013         storeConstToAop (zero, AOP (result), size);
6014     }
6015   else
6016     {
6017       switch (size)
6018         {
6019         case 1:
6020           genlshOne (result, left, shCount);
6021           break;
6022
6023         case 2:
6024           genlshTwo (result, left, shCount);
6025           break;
6026
6027         case 4:
6028           genlshFour (result, left, shCount);
6029           break;
6030         default:
6031           werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
6032                   "*** ack! mystery literal shift!\n");
6033           break;
6034         }
6035     }
6036   freeAsmop (left, NULL, ic, TRUE);
6037   freeAsmop (result, NULL, ic, TRUE);
6038 }
6039
6040 /*-----------------------------------------------------------------*/
6041 /* genLeftShift - generates code for left shifting                 */
6042 /*-----------------------------------------------------------------*/
6043 static void
6044 genLeftShift (iCode * ic)
6045 {
6046   operand *left, *right, *result;
6047   int size, offset;
6048   symbol *tlbl, *tlbl1;
6049 //  int i;
6050   char *shift;
6051   regs *reg;
6052
6053   D(emitcode (";     genLeftShift",""));
6054
6055   right = IC_RIGHT (ic);
6056   left = IC_LEFT (ic);
6057   result = IC_RESULT (ic);
6058
6059   aopOp (right, ic, FALSE);
6060
6061   /* if the shift count is known then do it
6062      as efficiently as possible */
6063   if (AOP_TYPE (right) == AOP_LIT)
6064     {
6065       genLeftShiftLiteral (left, right, result, ic);
6066       return;
6067     }
6068
6069   /* shift count is unknown then we have to form
6070      a loop get the loop count in A : Note: we take
6071      only the lower order byte since shifting
6072      more that 32 bits make no sense anyway, ( the
6073      largest size of an object can be only 32 bits ) */
6074
6075   aopOp (left, ic, FALSE);
6076   aopOp (result, ic, FALSE);
6077
6078   /* now move the left to the result if they are not the
6079      same */
6080   if (!sameRegs (AOP (left), AOP (result)))
6081     {
6082
6083       size = AOP_SIZE (result);
6084       offset = 0;
6085       while (size--)
6086         {
6087           transferAopAop (AOP (left), offset, AOP (result), offset);
6088           offset++;
6089         }
6090     }
6091   freeAsmop (left, NULL, ic, TRUE);
6092   
6093   tlbl = newiTempLabel (NULL);
6094   size = AOP_SIZE (result);
6095   offset = 0;
6096   tlbl1 = newiTempLabel (NULL);
6097
6098   reg = hc08_reg_a;
6099
6100   loadRegFromAop (reg, AOP (right), 0);
6101   freeAsmop (right, NULL, ic, TRUE);
6102   emitBranch ("beq", tlbl1);
6103   emitLabel (tlbl);
6104   
6105   shift="lsl";
6106   for (offset=0;offset<size;offset++)
6107     {
6108       rmwWithAop (shift, AOP (result), offset);  
6109       shift="rol";
6110     }
6111   rmwWithReg ("dec", reg);
6112   emitBranch ("bne", tlbl);
6113   emitLabel (tlbl1);
6114   hc08_freeReg (reg);
6115   
6116   freeAsmop (result, NULL, ic, TRUE);
6117 }
6118
6119 /*-----------------------------------------------------------------*/
6120 /* genrshOne - right shift a one byte quantity by known count      */
6121 /*-----------------------------------------------------------------*/
6122 static void
6123 genrshOne (operand * result, operand * left,
6124            int shCount, int sign)
6125 {
6126   D(emitcode (";     genrshOne",""));
6127
6128   loadRegFromAop (hc08_reg_a, AOP (left), 0);
6129   AccRsh (shCount, sign);
6130   storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6131 }
6132
6133 /*-----------------------------------------------------------------*/
6134 /* genrshTwo - right shift two bytes by known amount != 0          */
6135 /*-----------------------------------------------------------------*/
6136 static void
6137 genrshTwo (operand * result, operand * left,
6138            int shCount, int sign)
6139 {
6140   D(emitcode (";     genrshTwo",""));
6141
6142   /* if shCount >= 8 */
6143   if (shCount >= 8)
6144     {
6145       if (shCount || sign)
6146         {
6147           loadRegFromAop (hc08_reg_a, AOP (left), 1);
6148           AccRsh (shCount-8, sign);
6149           storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6150         }
6151       else
6152         {
6153           transferAopAop (AOP (left), 1, AOP (result), 0);
6154           storeConstToAop (zero, AOP (result), 1);
6155         }
6156     }
6157
6158   /*  1 <= shCount <= 7 */
6159   else
6160     {
6161       loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6162       XAccRsh (shCount, sign);
6163       storeRegToAop (hc08_reg_xa, AOP (result), 0);
6164     }
6165 }
6166
6167 /*-----------------------------------------------------------------*/
6168 /* shiftRLong - shift right one long from left to result           */
6169 /* offl = LSB or MSB16                                             */
6170 /*-----------------------------------------------------------------*/
6171 static void
6172 shiftRLong (operand * left, int offl,
6173             operand * result, int sign)
6174 {
6175 //  char *l;
6176  // int size = AOP_SIZE (result);
6177
6178   bool needpula = FALSE;
6179   bool needpulx = FALSE;
6180
6181   needpula = pushRegIfUsed (hc08_reg_a);
6182   needpulx = pushRegIfUsed (hc08_reg_x);
6183
6184   if (offl==LSB)
6185     {
6186       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6187       if (sign)
6188         rmwWithReg ("asr", hc08_reg_x);
6189       else
6190         rmwWithReg ("lsr", hc08_reg_x);
6191       rmwWithReg ("rol", hc08_reg_a);
6192       storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6193     }
6194   else if (offl==MSB16)
6195     {
6196       loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6197       if (sign)
6198         rmwWithReg ("asr", hc08_reg_a);
6199       else
6200         rmwWithReg ("lsr", hc08_reg_a);
6201       storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6202     }
6203
6204   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6205   rmwWithReg ("ror", hc08_reg_x);
6206   rmwWithReg ("ror", hc08_reg_a);
6207   storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6208
6209
6210   pullOrFreeReg (hc08_reg_x, needpulx);
6211   pullOrFreeReg (hc08_reg_a, needpula);
6212 }
6213
6214 /*-----------------------------------------------------------------*/
6215 /* genrshFour - shift four byte by a known amount != 0             */
6216 /*-----------------------------------------------------------------*/
6217 static void
6218 genrshFour (operand * result, operand * left,
6219             int shCount, int sign)
6220 {
6221   /* TODO: handle cases where left == result */
6222   
6223   D(emitcode (";     genrshFour",""));
6224
6225   /* if shifting more that 3 bytes */
6226   if (shCount >= 24)
6227     {
6228       loadRegFromAop (hc08_reg_a, AOP (left), 3);
6229       AccRsh (shCount-24, sign);
6230       storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6231       return;
6232     }
6233   else if (shCount >= 16)
6234     {
6235       loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6236       XAccRsh (shCount-16, sign);
6237       storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6238       return;
6239     }
6240   else if (shCount >= 8)
6241     {
6242       if (shCount == 1)
6243         shiftRLong (left, MSB16, result, sign);
6244       else if (shCount == 8)
6245         {
6246           transferAopAop (AOP (left), 1, AOP (result), 0);
6247           transferAopAop (AOP (left), 2, AOP (result), 1);
6248           loadRegFromAop (hc08_reg_a, AOP (left), 3);
6249           storeRegToAop (hc08_reg_a, AOP (result), 2);
6250           storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6251         }
6252       else if (shCount == 9)
6253         {
6254           shiftRLong (left, MSB16, result, sign);
6255         }
6256       else
6257         {
6258           loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6259           XAccRsh (shCount-8, FALSE);
6260           storeRegToAop (hc08_reg_xa, AOP (result), 0);
6261           loadRegFromAop (hc08_reg_x, AOP (left), 3);
6262           loadRegFromConst (hc08_reg_a, zero);
6263           XAccRsh (shCount-8, sign);
6264           accopWithAop ("ora", AOP (result), 1);
6265           storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6266         }
6267     }
6268   else
6269     {                           /* 1 <= shCount <= 7 */
6270       if (shCount == 1)
6271         {
6272           shiftRLong (left, LSB, result, sign);
6273         }
6274       else
6275         {
6276           loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6277           XAccRsh (shCount, FALSE);
6278           storeRegToAop (hc08_reg_xa, AOP (result), 0);
6279           loadRegFromAop (hc08_reg_a, AOP (left), 2);
6280           AccLsh (8-shCount);
6281           accopWithAop ("ora", AOP (result), 1);
6282           storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6283           loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6284           XAccRsh (shCount, sign);
6285           storeRegToAop (hc08_reg_xa, AOP (result), 2);
6286         }
6287     }
6288 }
6289
6290 /*-----------------------------------------------------------------*/
6291 /* genRightShiftLiteral - right shifting by known count            */
6292 /*-----------------------------------------------------------------*/
6293 static void
6294 genRightShiftLiteral (operand * left,
6295                       operand * right,
6296                       operand * result,
6297                       iCode * ic,
6298                       int sign)
6299 {
6300   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6301   int size;
6302
6303   D(emitcode (";     genRightShiftLiteral",""));
6304
6305   freeAsmop (right, NULL, ic, TRUE);
6306
6307   aopOp (left, ic, FALSE);
6308   aopOp (result, ic, FALSE);
6309
6310 #if VIEW_SIZE
6311   D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6312             AOP_SIZE (left)));
6313 #endif
6314
6315   size = getDataSize (left);
6316   /* test the LEFT size !!! */
6317
6318   /* I suppose that the left size >= result size */
6319   if (shCount == 0)
6320     {
6321       size = getDataSize (result);
6322       while (size--)
6323         transferAopAop (AOP (left), size, AOP(result), size);
6324     }
6325   else if (shCount >= (size * 8))
6326     {
6327       if (sign) {
6328         /* get sign in acc.7 */
6329         loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6330       }
6331       addSign (result, LSB, sign);
6332     }
6333   else
6334     {
6335       switch (size)
6336         {
6337         case 1:
6338           genrshOne (result, left, shCount, sign);
6339           break;
6340
6341         case 2:
6342           genrshTwo (result, left, shCount, sign);
6343           break;
6344
6345         case 4:
6346           genrshFour (result, left, shCount, sign);
6347           break;
6348         default:
6349           break;
6350         }
6351     }
6352   freeAsmop (left, NULL, ic, TRUE);
6353   freeAsmop (result, NULL, ic, TRUE);
6354 }
6355
6356
6357 /*-----------------------------------------------------------------*/
6358 /* genRightShift - generate code for right shifting                */
6359 /*-----------------------------------------------------------------*/
6360 static void
6361 genRightShift (iCode * ic)
6362 {
6363   operand *right, *left, *result;
6364   sym_link *retype;
6365   int size, offset;
6366 //  char *l;
6367   symbol *tlbl, *tlbl1;
6368   char *shift;
6369   bool sign;
6370   
6371   D(emitcode (";     genRightShift",""));
6372
6373   /* if signed then we do it the hard way preserve the
6374      sign bit moving it inwards */
6375   retype = getSpec (operandType (IC_RESULT (ic)));
6376   sign = !SPEC_USIGN (retype);
6377
6378   /* signed & unsigned types are treated the same : i.e. the
6379      signed is NOT propagated inwards : quoting from the
6380      ANSI - standard : "for E1 >> E2, is equivalent to division
6381      by 2**E2 if unsigned or if it has a non-negative value,
6382      otherwise the result is implementation defined ", MY definition
6383      is that the sign does not get propagated */
6384
6385   right = IC_RIGHT (ic);
6386   left = IC_LEFT (ic);
6387   result = IC_RESULT (ic);
6388
6389   aopOp (right, ic, FALSE);
6390
6391   /* if the shift count is known then do it
6392      as efficiently as possible */
6393   if (AOP_TYPE (right) == AOP_LIT)
6394     {
6395       genRightShiftLiteral (left, right, result, ic, sign);
6396       return;
6397     }
6398
6399   /* shift count is unknown then we have to form
6400      a loop get the loop count in X : Note: we take
6401      only the lower order byte since shifting
6402      more that 32 bits make no sense anyway, ( the
6403      largest size of an object can be only 32 bits ) */
6404
6405   aopOp (left, ic, FALSE);
6406   aopOp (result, ic, FALSE);
6407
6408   if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6409     AOP (result) = forceStackedAop (AOP (result));
6410   
6411   size = AOP_SIZE (result); 
6412   offset = size-1;
6413   while (size--)
6414     {
6415       transferAopAop (AOP (left), offset, AOP (result), offset);
6416       offset--;
6417     }
6418   
6419   tlbl = newiTempLabel (NULL);
6420   size = AOP_SIZE (result);
6421   offset = 0;
6422   tlbl1 = newiTempLabel (NULL);
6423
6424   loadRegFromAop (hc08_reg_x, AOP (right), 0);
6425   emitcode ("tstx", "");
6426   emitcode ("beq", "%05d$", tlbl1->key + 100);
6427   emitcode ("", "%05d$:", tlbl->key + 100);
6428   shift= sign ? "asr" : "lsr";
6429   for (offset=size-1;offset>=0;offset--)
6430     {
6431       rmwWithAop (shift, AOP (result), offset);
6432       shift="ror";
6433     }
6434   rmwWithReg ("dec", hc08_reg_x);
6435   emitcode ("bne","%05d$", tlbl->key + 100);
6436   emitcode ("", "%05d$:", tlbl1->key + 100);
6437   
6438   freeAsmop (result, NULL, ic, TRUE);
6439   freeAsmop (left, NULL, ic, TRUE);
6440   freeAsmop (right, NULL, ic, TRUE);
6441 }
6442
6443
6444 /*-----------------------------------------------------------------*/
6445 /* genUnpackBits - generates code for unpacking bits               */
6446 /*-----------------------------------------------------------------*/
6447 static void
6448 genUnpackBits (operand * result, iCode *ifx)
6449 {
6450   int offset = 0;       /* result byte offset */
6451   int rsize;            /* result size */
6452   int rlen = 0;         /* remaining bitfield length */
6453   sym_link *etype;      /* bitfield type information */
6454   int blen;             /* bitfield length */
6455   int bstr;             /* bitfield starting bit within byte */
6456
6457   D(emitcode (";     genUnpackBits",""));
6458
6459   etype = getSpec (operandType (result));
6460   rsize = getSize (operandType (result));
6461   blen = SPEC_BLEN (etype);
6462   bstr = SPEC_BSTR (etype);
6463
6464   /* If the bitfield length is less than a byte */
6465   if (blen < 8)
6466     {
6467       emitcode ("lda", ",x");
6468       hc08_dirtyReg (hc08_reg_a, FALSE);
6469       if (!ifx)
6470         {
6471           AccRsh (bstr, FALSE);
6472           emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6473           storeRegToAop (hc08_reg_a, AOP (result), offset++);
6474         }
6475       else
6476         {
6477           emitcode ("and", "#0x%02x",
6478                     (((unsigned char) -1) >> (8 - blen)) << bstr);
6479         }
6480       goto finish;
6481     }
6482
6483   /* Bit field did not fit in a byte. Copy all
6484      but the partial byte at the end.  */
6485   for (rlen=blen;rlen>=8;rlen-=8)
6486     {
6487       emitcode ("lda", ",x");
6488       hc08_dirtyReg (hc08_reg_a, FALSE);
6489       if (!ifx)
6490         storeRegToAop (hc08_reg_a, AOP (result), offset);
6491       offset++;
6492       if (rlen>8)
6493         emitcode ("aix", "#1");
6494     }
6495
6496   /* Handle the partial byte at the end */
6497   if (rlen)
6498     {
6499       emitcode ("lda", ",x");
6500       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6501       storeRegToAop (hc08_reg_a, AOP (result), offset++);
6502     }
6503
6504 finish:
6505   if (offset < rsize)
6506     {
6507       rsize -= offset;
6508       while (rsize--)
6509         storeConstToAop (zero, AOP (result), offset++);
6510     }
6511   
6512   if (ifx && !ifx->generated)
6513     {
6514       genIfxJump (ifx, "a");
6515     }
6516 }
6517
6518
6519 /*-----------------------------------------------------------------*/
6520 /* genUnpackBitsImmed - generates code for unpacking bits          */
6521 /*-----------------------------------------------------------------*/
6522 static void
6523 genUnpackBitsImmed (operand * left,
6524                     operand * result,
6525                     iCode *ic,
6526                     iCode *ifx)
6527 {
6528   int size;
6529   int offset = 0;       /* result byte offset */
6530   int rsize;            /* result size */
6531   int rlen = 0;         /* remaining bitfield length */
6532   sym_link *etype;      /* bitfield type information */
6533   int blen;             /* bitfield length */
6534   int bstr;             /* bitfield starting bit within byte */
6535   asmop *derefaop;
6536   
6537   D(emitcode (";     genUnpackBitsImmed",""));
6538
6539   aopOp (result, ic, TRUE);
6540   size = AOP_SIZE (result);
6541
6542   derefaop = aopDerefAop (AOP (left));
6543   freeAsmop (left, NULL, ic, TRUE);
6544   derefaop->size = size;
6545   
6546   etype = getSpec (operandType (result));
6547   rsize = getSize (operandType (result));
6548   blen = SPEC_BLEN (etype);
6549   bstr = SPEC_BSTR (etype);
6550
6551   /* if the bitfield is a single bit in the direct page */
6552   if (blen == 1 && derefaop->type == AOP_DIR)
6553     {
6554       if (!ifx && bstr)
6555         {
6556           symbol *tlbl = newiTempLabel (NULL);
6557           
6558           loadRegFromConst (hc08_reg_a, zero);
6559           emitcode ("brclr", "#%d,%s,%05d$",
6560                     bstr, aopAdrStr (derefaop, 0, FALSE),
6561                     (tlbl->key + 100));
6562           rmwWithReg ("inc", hc08_reg_a);
6563           emitLabel (tlbl);
6564           storeRegToAop (hc08_reg_a, AOP (result), offset);
6565           hc08_freeReg (hc08_reg_a);
6566           offset++;
6567           goto finish;
6568         }
6569       else if (ifx)
6570         {
6571           symbol *tlbl = newiTempLabel (NULL);
6572           symbol *jlbl;
6573           char * inst;
6574           
6575           if (IC_TRUE (ifx))
6576             {
6577               jlbl = IC_TRUE (ifx);
6578               inst = "brclr";
6579             }
6580           else
6581             {
6582               jlbl = IC_FALSE (ifx);
6583               inst = "brset";
6584             }
6585           emitcode (inst, "#%d,%s,%05d$",
6586                     bstr, aopAdrStr (derefaop, 0, FALSE),
6587                     (tlbl->key + 100));
6588           emitBranch ("jmp", jlbl);
6589           emitLabel (tlbl);
6590           ifx->generated = 1;
6591           offset++;
6592           goto finish;
6593         }
6594     }
6595
6596   /* If the bitfield length is less than a byte */
6597   if (blen < 8)
6598     {
6599       loadRegFromAop (hc08_reg_a, derefaop, 0);
6600       if (!ifx)
6601         {
6602           AccRsh (bstr, FALSE);
6603           emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6604           hc08_dirtyReg (hc08_reg_a, FALSE);
6605           storeRegToAop (hc08_reg_a, AOP (result), offset);
6606         }
6607       else
6608         {
6609           emitcode ("and", "#0x%02x",
6610                     (((unsigned char) -1) >> (8 - blen)) << bstr);
6611           hc08_dirtyReg (hc08_reg_a, FALSE);
6612         }
6613       offset++;
6614       goto finish;
6615     }
6616
6617   /* Bit field did not fit in a byte. Copy all
6618      but the partial byte at the end.  */
6619   for (rlen=blen;rlen>=8;rlen-=8)
6620     {
6621       loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6622       if (!ifx)
6623         storeRegToAop (hc08_reg_a, AOP (result), offset);
6624       else
6625         emitcode ("tsta", "");
6626       offset++;
6627     }
6628
6629   /* Handle the partial byte at the end */
6630   if (rlen)
6631     {
6632       loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6633       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6634       storeRegToAop (hc08_reg_a, AOP (result), offset++);
6635     }
6636
6637 finish:
6638   if (offset < rsize)
6639     {
6640       rsize -= offset;
6641       while (rsize--)
6642         storeConstToAop (zero, AOP (result), offset++);
6643     }
6644   
6645   freeAsmop (NULL, derefaop, ic, TRUE);
6646   freeAsmop (result, NULL, ic, TRUE);
6647   
6648   if (ifx && !ifx->generated)
6649     {
6650       genIfxJump (ifx, "a");
6651     }
6652 }
6653
6654
6655 /*-----------------------------------------------------------------*/
6656 /* genDataPointerGet - generates code when ptr offset is known     */
6657 /*-----------------------------------------------------------------*/
6658 static void
6659 genDataPointerGet (operand * left,
6660                    operand * result,
6661                    iCode * ic,
6662                    iCode * ifx)
6663 {
6664   int size, offset = 0;
6665   asmop *derefaop;
6666   
6667   D(emitcode (";     genDataPointerGet",""));
6668
6669   aopOp (result, ic, TRUE);
6670   size = AOP_SIZE (result);
6671
6672   derefaop = aopDerefAop (AOP (left));
6673   freeAsmop (left, NULL, ic, TRUE);
6674   derefaop->size = size;
6675   
6676   while (size--)
6677     {
6678       if (!ifx)
6679         transferAopAop (derefaop, offset, AOP (result), offset);
6680       else
6681         loadRegFromAop (hc08_reg_a, derefaop, offset);
6682       offset++;
6683     }
6684
6685   freeAsmop (NULL, derefaop, ic, TRUE);
6686   freeAsmop (result, NULL, ic, TRUE);
6687   
6688   if (ifx && !ifx->generated)
6689     {
6690       genIfxJump (ifx, "a");
6691     }
6692 }
6693
6694
6695 /*-----------------------------------------------------------------*/
6696 /* genPointerGet - generate code for pointer get                   */
6697 /*-----------------------------------------------------------------*/
6698 static void
6699 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
6700 {
6701   operand *left = IC_LEFT (ic);
6702   operand *result = IC_RESULT (ic);
6703   int size, offset;
6704   sym_link *retype = getSpec (operandType (result));
6705
6706   D(emitcode (";     genPointerGet",""));
6707
6708   if (getSize (operandType (result))>1)
6709     ifx = NULL;
6710   
6711   aopOp (left, ic, FALSE);
6712
6713   /* if left is rematerialisable and
6714      result is not bit variable type */
6715   if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
6716     {
6717       if (!IS_BITVAR (retype))
6718         {
6719           genDataPointerGet (left, result, ic, ifx);
6720           return;
6721         }
6722       else
6723         {
6724           genUnpackBitsImmed (left, result, ic, ifx);
6725           return;
6726         }
6727     }
6728
6729   /* if the operand is already in hx
6730      then we do nothing else we move the value to hx */
6731   if (AOP_TYPE (left) != AOP_STR)
6732     {
6733       /* if this is remateriazable */
6734       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6735     }
6736
6737   /* so hx now contains the address */
6738   aopOp (result, ic, FALSE);
6739
6740   /* if bit then unpack */
6741   if (IS_BITVAR (retype))
6742     genUnpackBits (result, ifx);
6743   else
6744     {
6745       size = AOP_SIZE (result);
6746       offset = size-1;
6747
6748       while (size--)
6749         {
6750           accopWithMisc ("lda", ",x");
6751           if (size || pi)
6752             {
6753               emitcode ("aix", "#1");
6754               hc08_dirtyReg (hc08_reg_hx, FALSE);
6755             }
6756           if (!ifx)
6757             storeRegToAop (hc08_reg_a, AOP (result), offset);
6758           offset--;
6759           hc08_freeReg (hc08_reg_a);
6760         }
6761     }
6762
6763   freeAsmop (left, NULL, ic, TRUE);
6764   freeAsmop (result, NULL, ic, TRUE);
6765   
6766   if (pi) {
6767     aopOp (IC_RESULT (pi), pi, FALSE);
6768     storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6769     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6770     pi->generated = 1;
6771   }
6772   
6773   if (ifx && !ifx->generated)
6774     {
6775       genIfxJump (ifx, "a");
6776     }
6777
6778   hc08_freeReg (hc08_reg_hx);
6779   
6780 }
6781
6782 /*-----------------------------------------------------------------*/
6783 /* genPackBits - generates code for packed bit storage             */
6784 /*-----------------------------------------------------------------*/
6785 static void
6786 genPackBits (sym_link * etype,
6787              operand * right)
6788 {
6789   int offset = 0;       /* source byte offset */
6790   int rlen = 0;         /* remaining bitfield length */
6791   int blen;             /* bitfield length */
6792   int bstr;             /* bitfield starting bit within byte */
6793   int litval;           /* source literal value (if AOP_LIT) */
6794   unsigned char mask;   /* bitmask within current byte */
6795   int xoffset = 0;
6796
6797   D(emitcode (";     genPackBits",""));
6798
6799   blen = SPEC_BLEN (etype);
6800   bstr = SPEC_BSTR (etype);
6801
6802   /* If the bitfield length is less than a byte */
6803   if (blen < 8)
6804     {
6805       mask = ((unsigned char) (0xFF << (blen + bstr)) |
6806               (unsigned char) (0xFF >> (8 - bstr)));
6807
6808       if (AOP_TYPE (right) == AOP_LIT)
6809         {
6810           /* Case with a bitfield length <8 and literal source
6811           */
6812           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6813           litval <<= bstr;
6814           litval &= (~mask) & 0xff;
6815
6816           emitcode ("lda", ",x");
6817           if ((mask|litval)!=0xff)
6818             emitcode ("and","#0x%02x", mask);
6819           if (litval)
6820             emitcode ("ora","#0x%02x", litval);
6821           hc08_dirtyReg (hc08_reg_a, FALSE);
6822           emitcode ("sta", ",x");
6823           
6824           hc08_freeReg (hc08_reg_a);
6825           return;
6826         }
6827           
6828       /* Case with a bitfield length < 8 and arbitrary source
6829       */
6830       loadRegFromAop (hc08_reg_a, AOP (right), 0);
6831       /* shift and mask source value */
6832       AccLsh (bstr);
6833       emitcode ("and", "#0x%02x", (~mask) & 0xff);
6834       hc08_dirtyReg (hc08_reg_a, FALSE);
6835       pushReg (hc08_reg_a, TRUE);
6836
6837       emitcode ("lda", ",x");
6838       emitcode ("and", "#0x%02x", mask);
6839       emitcode ("ora", "1,s");
6840       emitcode ("sta", ",x");
6841       pullReg (hc08_reg_a);
6842      
6843       hc08_freeReg (hc08_reg_a);
6844       return;
6845     }
6846
6847   /* Bit length is greater than 7 bits. In this case, copy  */
6848   /* all except the partial byte at the end                 */
6849   for (rlen=blen;rlen>=8;rlen-=8)
6850     {
6851       if (AOP (right)->type == AOP_DIR)
6852         {
6853           emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6854           xoffset++;
6855         }
6856       else
6857         {
6858           loadRegFromAop (hc08_reg_a, AOP (right), offset);
6859           emitcode ("sta", "%d,x", offset);
6860         }
6861       offset++;
6862     }
6863
6864   /* If there was a partial byte at the end */
6865   if (rlen)
6866     {
6867       mask = (((unsigned char) -1 << rlen) & 0xff);
6868       
6869       if (AOP_TYPE (right) == AOP_LIT)
6870         {
6871           /* Case with partial byte and literal source
6872           */
6873           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6874           litval >>= (blen-rlen);
6875           litval &= (~mask) & 0xff;
6876           emitcode ("lda", "%d,x", offset - xoffset);
6877           hc08_dirtyReg (hc08_reg_a, FALSE);
6878           if ((mask|litval)!=0xff)
6879             emitcode ("and","#0x%02x", mask);
6880           if (litval)
6881             emitcode ("ora","#0x%02x", litval);
6882           emitcode ("sta", "%d,x", offset - xoffset);
6883           hc08_dirtyReg (hc08_reg_a, FALSE);
6884           hc08_freeReg (hc08_reg_a);
6885           return;
6886         }
6887       
6888       /* Case with partial byte and arbitrary source
6889       */
6890       loadRegFromAop (hc08_reg_a, AOP (right), offset);
6891       emitcode ("and", "#0x%02x", (~mask) & 0xff);
6892       hc08_dirtyReg (hc08_reg_a, FALSE);
6893       pushReg (hc08_reg_a, TRUE);
6894
6895       emitcode ("lda", "%d,x", offset - xoffset);
6896       emitcode ("and", "#0x%02x", mask);
6897       emitcode ("ora", "1,s");
6898       emitcode ("sta", "%d,x", offset - xoffset);
6899       pullReg (hc08_reg_a);
6900     }
6901
6902   hc08_freeReg (hc08_reg_a);
6903 }
6904
6905 /*-----------------------------------------------------------------*/
6906 /* genPackBitsImmed - generates code for packed bit storage        */
6907 /*-----------------------------------------------------------------*/
6908 static void
6909 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
6910 {
6911   asmop *derefaop;
6912   int size;
6913   int offset = 0;       /* source byte offset */
6914   int rlen = 0;         /* remaining bitfield length */
6915   int blen;             /* bitfield length */
6916   int bstr;             /* bitfield starting bit within byte */
6917   int litval;           /* source literal value (if AOP_LIT) */
6918   unsigned char mask;   /* bitmask within current byte */
6919
6920   D(emitcode (";     genPackBitsImmed",""));
6921
6922   blen = SPEC_BLEN (etype);
6923   bstr = SPEC_BSTR (etype);
6924
6925   aopOp (right, ic, FALSE);
6926   size = AOP_SIZE (right);
6927
6928   derefaop = aopDerefAop (AOP (result));
6929   freeAsmop (result, NULL, ic, TRUE);
6930   derefaop->size = size;
6931
6932   /* if the bitfield is a single bit in the direct page */
6933   if (blen == 1 && derefaop->type == AOP_DIR)
6934     {
6935       if (AOP_TYPE (right) == AOP_LIT)
6936         {
6937           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6938       
6939           emitcode ((litval & 1) ? "bset" : "bclr", 
6940                     "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
6941         }
6942       else
6943         {
6944           symbol *tlbl1 = newiTempLabel (NULL);
6945           symbol *tlbl2 = newiTempLabel (NULL);
6946           
6947           loadRegFromAop (hc08_reg_a, AOP (right), 0);
6948           emitcode ("bit", "#1");
6949           emitBranch ("bne", tlbl1);
6950           emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
6951           emitBranch ("bra", tlbl2);
6952           emitLabel (tlbl1);
6953           emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
6954           emitLabel (tlbl2);
6955           hc08_freeReg (hc08_reg_a);
6956         }
6957       goto release;
6958     }
6959     
6960   /* If the bitfield length is less than a byte */
6961   if (blen < 8)
6962     {
6963       mask = ((unsigned char) (0xFF << (blen + bstr)) |
6964               (unsigned char) (0xFF >> (8 - bstr)));
6965
6966       if (AOP_TYPE (right) == AOP_LIT)
6967         {
6968           /* Case with a bitfield length <8 and literal source
6969           */
6970           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6971           litval <<= bstr;
6972           litval &= (~mask) & 0xff;
6973
6974           loadRegFromAop (hc08_reg_a, derefaop, 0);
6975           if ((mask|litval)!=0xff)
6976             emitcode ("and","#0x%02x", mask);
6977           if (litval)
6978             emitcode ("ora","#0x%02x", litval);
6979           hc08_dirtyReg (hc08_reg_a, FALSE);
6980           storeRegToAop (hc08_reg_a, derefaop, 0);
6981           
6982           hc08_freeReg (hc08_reg_a);
6983           goto release;
6984         }
6985           
6986       /* Case with a bitfield length < 8 and arbitrary source
6987       */
6988       loadRegFromAop (hc08_reg_a, AOP (right), 0);
6989       /* shift and mask source value */
6990       AccLsh (bstr);
6991       emitcode ("and", "#0x%02x", (~mask) & 0xff);
6992       hc08_dirtyReg (hc08_reg_a, FALSE);
6993       pushReg (hc08_reg_a, TRUE);
6994
6995       loadRegFromAop (hc08_reg_a, derefaop, 0);
6996       emitcode ("and", "#0x%02x", mask);
6997       emitcode ("ora", "1,s");
6998       storeRegToAop (hc08_reg_a, derefaop, 0);
6999       pullReg (hc08_reg_a);
7000      
7001       hc08_freeReg (hc08_reg_a);
7002       goto release;
7003     }
7004
7005   /* Bit length is greater than 7 bits. In this case, copy  */
7006   /* all except the partial byte at the end                 */
7007   for (rlen=blen;rlen>=8;rlen-=8)
7008     {
7009       transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7010       offset++;
7011     }
7012
7013   /* If there was a partial byte at the end */
7014   if (rlen)
7015     {
7016       mask = (((unsigned char) -1 << rlen) & 0xff);
7017       
7018       if (AOP_TYPE (right) == AOP_LIT)
7019         {
7020           /* Case with partial byte and literal source
7021           */
7022           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7023           litval >>= (blen-rlen);
7024           litval &= (~mask) & 0xff;
7025           loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7026           if ((mask|litval)!=0xff)
7027             emitcode ("and","#0x%02x", mask);
7028           if (litval)
7029             emitcode ("ora","#0x%02x", litval);
7030           hc08_dirtyReg (hc08_reg_a, FALSE);
7031           storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7032           hc08_dirtyReg (hc08_reg_a, FALSE);
7033           hc08_freeReg (hc08_reg_a);
7034           goto release;
7035         }
7036       
7037       /* Case with partial byte and arbitrary source
7038       */
7039       loadRegFromAop (hc08_reg_a, AOP (right), offset);
7040       emitcode ("and", "#0x%02x", (~mask) & 0xff);
7041       hc08_dirtyReg (hc08_reg_a, FALSE);
7042       pushReg (hc08_reg_a, TRUE);
7043
7044       loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7045       emitcode ("and", "#0x%02x", mask);
7046       emitcode ("ora", "1,s");
7047       storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7048       pullReg (hc08_reg_a);
7049     }
7050
7051   hc08_freeReg (hc08_reg_a);
7052
7053 release:  
7054   freeAsmop (right, NULL, ic, TRUE);
7055   freeAsmop (NULL, derefaop, ic, TRUE);
7056 }
7057
7058 /*-----------------------------------------------------------------*/
7059 /* genDataPointerSet - remat pointer to data space                 */
7060 /*-----------------------------------------------------------------*/
7061 static void
7062 genDataPointerSet (operand * right,
7063                    operand * result,
7064                    iCode * ic)
7065 {
7066   int size, offset = 0;
7067   asmop *derefaop;
7068
7069   D(emitcode (";     genDataPointerSet",""));
7070
7071   aopOp (right, ic, FALSE);
7072   size = AOP_SIZE (right);
7073
7074   derefaop = aopDerefAop (AOP (result));
7075   freeAsmop (result, NULL, ic, TRUE);
7076   derefaop->size = size;
7077   
7078   while (size--)
7079     {
7080       transferAopAop (AOP (right), offset, derefaop, offset);
7081       offset++;
7082     }
7083
7084   freeAsmop (right, NULL, ic, TRUE);
7085   freeAsmop (NULL, derefaop, ic, TRUE);
7086 }
7087
7088
7089 /*-----------------------------------------------------------------*/
7090 /* genPointerSet - stores the value into a pointer location        */
7091 /*-----------------------------------------------------------------*/
7092 static void
7093 genPointerSet (iCode * ic, iCode *pi)
7094 {
7095   operand *right = IC_RIGHT (ic);
7096   operand *result = IC_RESULT (ic);
7097   sym_link *type, *etype;
7098   int size, offset;
7099   sym_link *retype = getSpec (operandType (right));
7100   sym_link *letype = getSpec (operandType (result));
7101
7102   D(emitcode (";     genPointerSet",""));
7103
7104   type = operandType (result);
7105   etype = getSpec (type);
7106   
7107   aopOp (result, ic, FALSE);
7108
7109   /* if the result is rematerializable */
7110   if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7111     {
7112       if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7113         {
7114           genDataPointerSet (right, result, ic);
7115           return;
7116         }
7117       else
7118         {
7119           genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7120           return;
7121         }
7122     }
7123
7124   /* if the operand is already in hx
7125      then we do nothing else we move the value to hx */
7126   if (AOP_TYPE (result) != AOP_STR)
7127     {
7128       loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7129     }
7130   /* so hx now contains the address */
7131   aopOp (right, ic, FALSE);
7132
7133   /* if bit then unpack */
7134   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7135     genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7136   else
7137     {
7138       size = AOP_SIZE (right);
7139       offset = size-1;
7140
7141       while (size--)
7142         {
7143           loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7144           accopWithMisc ("sta", ",x");
7145           if (size || pi)
7146             {
7147               emitcode ("aix", "#1");
7148             }
7149           hc08_freeReg (hc08_reg_a);
7150         }
7151     }
7152
7153   freeAsmop (result, NULL, ic, TRUE);
7154   freeAsmop (right, NULL, ic, TRUE);
7155
7156   if (pi) {
7157     aopOp (IC_RESULT (pi), pi, FALSE);
7158     storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7159     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7160     pi->generated=1;
7161   }
7162
7163   hc08_freeReg (hc08_reg_hx);
7164
7165 }
7166
7167 /*-----------------------------------------------------------------*/
7168 /* genIfx - generate code for Ifx statement                        */
7169 /*-----------------------------------------------------------------*/
7170 static void
7171 genIfx (iCode * ic, iCode * popIc)
7172 {
7173   operand *cond = IC_COND (ic);
7174   int isbit = 0;
7175
7176   D(emitcode (";     genIfx",""));
7177
7178   aopOp (cond, ic, FALSE);
7179
7180   /* get the value into acc */
7181   if (AOP_TYPE (cond) != AOP_CRY)
7182     asmopToBool (AOP (cond), FALSE);
7183   else
7184     isbit = 1;
7185   /* the result is now in the accumulator */
7186   freeAsmop (cond, NULL, ic, TRUE);
7187
7188   /* if there was something to be popped then do it */
7189   if (popIc)
7190     genIpop (popIc);
7191
7192   /* if the condition is  a bit variable */
7193   if (isbit && IS_ITEMP (cond) &&
7194       SPIL_LOC (cond))
7195     genIfxJump (ic, SPIL_LOC (cond)->rname);
7196   else if (isbit && !IS_ITEMP (cond))
7197     genIfxJump (ic, OP_SYMBOL (cond)->rname);
7198   else
7199     genIfxJump (ic, "a");
7200
7201   ic->generated = 1;
7202 }
7203
7204 /*-----------------------------------------------------------------*/
7205 /* genAddrOf - generates code for address of                       */
7206 /*-----------------------------------------------------------------*/
7207 static void
7208 genAddrOf (iCode * ic)
7209 {
7210   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7211   int size, offset;
7212
7213   D(emitcode (";     genAddrOf",""));
7214
7215   aopOp (IC_RESULT (ic), ic, FALSE);
7216
7217   /* if the operand is on the stack then we
7218      need to get the stack offset of this
7219      variable */
7220   if (sym->onStack)
7221     {
7222       /* if it has an offset then we need to compute
7223          it */
7224       hc08_useReg (hc08_reg_hx);
7225       emitcode ("tsx", "");
7226       emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7227       storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7228       hc08_freeReg (hc08_reg_hx);
7229
7230       goto release;
7231     }
7232
7233   /* object not on stack then we need the name */
7234   size = AOP_SIZE (IC_RESULT (ic));
7235   offset = 0;
7236
7237   while (size--)
7238     {
7239       char s[SDCC_NAME_MAX+10];
7240       switch (offset) {
7241         case 0:
7242           sprintf (s, "#%s", sym->rname);
7243           break;
7244         case 1:
7245           sprintf (s, "#>%s", sym->rname);
7246           break;
7247         default:
7248           sprintf (s, "#(%s >> %d)",
7249                    sym->rname,
7250                    offset * 8);
7251       }
7252       storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7253     }
7254
7255 release:
7256   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7257
7258 }
7259
7260 /*-----------------------------------------------------------------*/
7261 /* genAssign - generate code for assignment                        */
7262 /*-----------------------------------------------------------------*/
7263 static void
7264 genAssign (iCode * ic)
7265 {
7266   operand *result, *right;
7267   int size, offset;
7268 //  unsigned long lit = 0L;
7269
7270   D(emitcode(";     genAssign",""));
7271
7272   result = IC_RESULT (ic);
7273   right = IC_RIGHT (ic);
7274
7275   /* if they are the same */
7276   if (operandsEqu (result, right)) {
7277     return;
7278   }
7279
7280   aopOp (right, ic, FALSE);
7281   aopOp (result, ic, TRUE);
7282
7283   /* if they are the same registers */
7284   if (sameRegs (AOP (right), AOP (result)))
7285     goto release;
7286
7287   if ((AOP_TYPE (right) == AOP_LIT)
7288       && (IS_AOP_HX(AOP(result))))
7289     {
7290       loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7291       goto release;
7292     }
7293     
7294   /* general case */
7295   size = AOP_SIZE (result);
7296   offset = 0;
7297
7298   while (size--)
7299     {
7300       transferAopAop (AOP (right), offset, AOP (result), offset);
7301       offset++;
7302     }
7303
7304 release:
7305   freeAsmop (right, NULL, ic, TRUE);
7306   freeAsmop (result, NULL, ic, TRUE);
7307 }
7308
7309 /*-----------------------------------------------------------------*/
7310 /* genJumpTab - genrates code for jump table                       */
7311 /*-----------------------------------------------------------------*/
7312 static void
7313 genJumpTab (iCode * ic)
7314 {
7315   symbol *jtab;
7316 //  char *l;
7317
7318   D(emitcode (";     genJumpTab",""));
7319
7320   aopOp (IC_JTCOND (ic), ic, FALSE);
7321   /* get the condition into accumulator */
7322   loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7323   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7324   /* multiply by three */
7325   pushReg (hc08_reg_a, FALSE);
7326   emitcode ("lsla", "");
7327   emitcode ("add","1,s");
7328   transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7329   loadRegFromConst (hc08_reg_h, zero);
7330   pullReg (hc08_reg_a);
7331
7332   jtab = newiTempLabel (NULL);
7333   emitcode ("jmp", "%05d$,x", jtab->key + 100);
7334   emitcode ("", "%05d$:", jtab->key + 100);
7335   /* now generate the jump labels */
7336   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7337        jtab = setNextItem (IC_JTLABELS (ic)))
7338     emitcode ("jmp", "%05d$", jtab->key + 100);
7339
7340   hc08_dirtyReg (hc08_reg_a, TRUE);
7341   hc08_dirtyReg (hc08_reg_hx, TRUE);
7342 }
7343
7344 /*-----------------------------------------------------------------*/
7345 /* genCast - gen code for casting                                  */
7346 /*-----------------------------------------------------------------*/
7347 static void
7348 genCast (iCode * ic)
7349 {
7350   operand *result = IC_RESULT (ic);
7351   sym_link *ctype = operandType (IC_LEFT (ic));
7352   sym_link *rtype = operandType (IC_RIGHT (ic));
7353   operand *right = IC_RIGHT (ic);
7354   int size, offset;
7355
7356   D(emitcode(";     genCast",""));
7357
7358   /* if they are equivalent then do nothing */
7359   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7360     return;
7361
7362   aopOp (right, ic, FALSE);
7363   aopOp (result, ic, FALSE);
7364
7365
7366   /* if they are the same size : or less */
7367   if (AOP_SIZE (result) <= AOP_SIZE (right))
7368     {
7369
7370       /* if they are in the same place */
7371       #if 0
7372       if (sameRegs (AOP (right), AOP (result)))
7373         goto release;
7374       #endif
7375
7376       /* if they in different places then copy */
7377       size = AOP_SIZE (result);
7378       offset = 0;
7379       while (size--)
7380         {
7381           transferAopAop(AOP (right), offset, AOP (result), offset);
7382           offset++;
7383         }
7384       goto release;
7385     }
7386
7387
7388   /* if the result is of type pointer */
7389   if (IS_PTR (ctype))
7390     {
7391
7392       int p_type;
7393       sym_link *type = operandType (right);
7394       sym_link *etype = getSpec (type);
7395
7396       /* pointer to generic pointer */
7397       if (IS_GENPTR (ctype))
7398         {
7399           if (IS_PTR (type))
7400             p_type = DCL_TYPE (type);
7401           else
7402             {
7403               if (SPEC_SCLS(etype)==S_REGISTER) {
7404                 // let's assume it is a generic pointer
7405                 p_type=GPOINTER;
7406               } else {
7407                 /* we have to go by the storage class */
7408                 p_type = PTR_TYPE (SPEC_OCLS (etype));
7409               }
7410             }
7411
7412           /* the first two bytes are known */
7413           size = GPTRSIZE - 1;
7414           offset = 0;
7415           while (size--)
7416             {
7417               transferAopAop(AOP (right), offset, AOP (result), offset);
7418               offset++;
7419             }
7420           /* the last byte depending on type */
7421 #if 0
7422             {
7423                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7424                 char gpValStr[10];
7425             
7426                 if (gpVal == -1)
7427                 {
7428                     // pointerTypeToGPByte will have bitched.
7429                     exit(1);
7430                 }
7431             
7432                 sprintf(gpValStr, "#0x%d", gpVal);
7433                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7434             }       
7435 #endif
7436           goto release;
7437         }
7438
7439       /* just copy the pointers */
7440       size = AOP_SIZE (result);
7441       offset = 0;
7442       while (size--)
7443         {
7444           transferAopAop(AOP (right), offset, AOP (result), offset);
7445           offset++;
7446         }
7447       goto release;
7448     }
7449
7450   /* so we now know that the size of destination is greater
7451      than the size of the source */
7452   /* we move to result for the size of source */
7453   size = AOP_SIZE (right);
7454   offset = 0;
7455   while (size--)
7456     {
7457       transferAopAop(AOP (right), offset, AOP (result), offset);
7458       offset++;
7459     }
7460
7461   /* now depending on the sign of the source && destination */
7462   size = AOP_SIZE (result) - AOP_SIZE (right);
7463   /* if unsigned or not an integral type */
7464   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7465     {
7466       while (size--)
7467         storeConstToAop (zero, AOP (result), offset++); 
7468     }
7469   else
7470     {
7471       /* we need to extend the sign :{ */
7472       loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7473       accopWithMisc ("rola", "");
7474       accopWithMisc ("clra", "");
7475       accopWithMisc ("sbc", zero);
7476       while (size--)
7477         storeRegToAop (hc08_reg_a, AOP (result), offset++);
7478     }
7479
7480   /* we are done hurray !!!! */
7481
7482 release:
7483   freeAsmop (right, NULL, ic, TRUE);
7484   freeAsmop (result, NULL, ic, TRUE);
7485
7486 }
7487
7488 /*-----------------------------------------------------------------*/
7489 /* genDjnz - generate decrement & jump if not zero instrucion      */
7490 /*-----------------------------------------------------------------*/
7491 static int
7492 genDjnz (iCode * ic, iCode * ifx)
7493 {
7494   symbol *lbl, *lbl1;
7495   if (!ifx)
7496     return 0;
7497
7498   D(emitcode (";     genDjnz",""));
7499
7500   /* if the if condition has a false label
7501      then we cannot save */
7502   if (IC_FALSE (ifx))
7503     return 0;
7504
7505   /* if the minus is not of the form
7506      a = a - 1 */
7507   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7508       !IS_OP_LITERAL (IC_RIGHT (ic)))
7509     return 0;
7510
7511   if (operandLitValue (IC_RIGHT (ic)) != 1)
7512     return 0;
7513
7514   /* dbnz doesn't support extended mode */
7515   if (isOperandInFarSpace (IC_RESULT (ic)))
7516     return 0;
7517
7518   /* if the size of this greater than one then no
7519      saving */
7520 //  if (getSize (operandType (IC_RESULT (ic))) > 1)
7521 //    return 0;
7522   aopOp (IC_RESULT (ic), ic, FALSE);
7523   if (AOP_SIZE (IC_RESULT (ic))>1)
7524     {
7525       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7526       return 0;
7527     }
7528
7529   /* otherwise we can save BIG */
7530   lbl = newiTempLabel (NULL);
7531   lbl1 = newiTempLabel (NULL);
7532
7533
7534   emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7535                 lbl->key + 100);
7536  
7537   emitBranch ("bra", lbl1);
7538   emitLabel (lbl);
7539   emitBranch ("jmp", IC_TRUE (ifx));
7540   emitLabel (lbl1);
7541
7542   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7543   ifx->generated = 1;
7544   return 1;
7545 }
7546
7547 /*-----------------------------------------------------------------*/
7548 /* genReceive - generate code for a receive iCode                  */
7549 /*-----------------------------------------------------------------*/
7550 static void
7551 genReceive (iCode * ic)
7552 {
7553   int size;
7554   int offset;
7555   D(emitcode (";     genReceive",""));
7556
7557   aopOp (IC_RESULT (ic), ic, FALSE);
7558   size = AOP_SIZE (IC_RESULT (ic));
7559   offset = 0;
7560   
7561   if (ic->argreg) {
7562       while (size--) {
7563           transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7564                           AOP (IC_RESULT (ic)), offset);
7565           if (hc08_aop_pass[offset]->type == AOP_REG)
7566             hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7567           offset++;
7568       }
7569   }       
7570
7571   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7572 }
7573
7574 /*-----------------------------------------------------------------*/
7575 /* genDummyRead - generate code for dummy read of volatiles        */
7576 /*-----------------------------------------------------------------*/
7577 static void
7578 genDummyRead (iCode * ic)
7579 {
7580   operand *op;
7581   int size, offset;
7582
7583   D(emitcode(";     genDummyRead",""));
7584
7585   op = IC_RIGHT (ic);
7586   if (op && IS_SYMOP (op))
7587     {
7588
7589       aopOp (op, ic, FALSE);
7590
7591       size = AOP_SIZE (op);
7592       offset = 0;
7593
7594       while (size--)
7595         {
7596           loadRegFromAop (hc08_reg_a, AOP (op), offset);
7597           hc08_freeReg (hc08_reg_a);
7598           offset++;
7599         }
7600
7601       freeAsmop (op, NULL, ic, TRUE);
7602    }
7603   op = IC_LEFT (ic);
7604   if (op && IS_SYMOP (op))
7605     {
7606
7607       aopOp (op, ic, FALSE);
7608
7609       size = AOP_SIZE (op);
7610       offset = 0;
7611
7612       while (size--)
7613         {
7614           loadRegFromAop (hc08_reg_a, AOP (op), offset);
7615           hc08_freeReg (hc08_reg_a);
7616           offset++;
7617         }
7618
7619       freeAsmop (op, NULL, ic, TRUE);
7620    }
7621 }
7622
7623 /*-----------------------------------------------------------------*/
7624 /* genCritical - generate code for start of a critical sequence    */
7625 /*-----------------------------------------------------------------*/
7626 static void
7627 genCritical (iCode *ic)
7628 {
7629   D(emitcode(";     genCritical",""));
7630   
7631   if (IC_RESULT (ic))
7632     aopOp (IC_RESULT (ic), ic, TRUE);
7633
7634   emitcode ("tpa", "");
7635   hc08_dirtyReg (hc08_reg_a, FALSE);
7636   emitcode ("sei", "");
7637
7638   if (IC_RESULT (ic))
7639     storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7640   else
7641     pushReg (hc08_reg_a, FALSE);
7642
7643   hc08_freeReg (hc08_reg_a);
7644   if (IC_RESULT (ic))
7645     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7646 }
7647
7648 /*-----------------------------------------------------------------*/
7649 /* genEndCritical - generate code for end of a critical sequence   */
7650 /*-----------------------------------------------------------------*/
7651 static void
7652 genEndCritical (iCode *ic)
7653 {
7654   D(emitcode(";     genEndCritical",""));
7655   
7656   if (IC_RIGHT (ic))
7657     {
7658       aopOp (IC_RIGHT (ic), ic, FALSE);
7659       loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7660       emitcode ("tap", "");
7661       hc08_freeReg (hc08_reg_a);
7662       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7663     }
7664   else
7665     {
7666       pullReg (hc08_reg_a);
7667       emitcode ("tap", "");
7668     }
7669 }
7670
7671
7672
7673 /*-----------------------------------------------------------------*/
7674 /* genhc08Code - generate code for HC08 based controllers          */
7675 /*-----------------------------------------------------------------*/
7676 void
7677 genhc08Code (iCode * lic)
7678 {
7679   iCode *ic;
7680   int cln = 0;
7681   int clevel = 0;
7682   int cblock = 0;
7683
7684   lineHead = lineCurr = NULL;
7685
7686   /* print the allocation information */
7687   if (allocInfo && currFunc)
7688     printAllocInfo (currFunc, codeOutFile);
7689   /* if debug information required */
7690   if (options.debug && currFunc)
7691     {
7692       debugFile->writeFunction (currFunc, lic);
7693       #if 0
7694       _G.debugLine = 1;
7695       if (IS_STATIC (currFunc->etype))
7696         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7697       else
7698         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7699       _G.debugLine = 0;
7700       #endif
7701     }
7702   /* stack pointer name */
7703   if (options.useXstack)
7704     spname = "_spx";
7705   else
7706     spname = "sp";
7707   
7708   debugFile->writeFrameAddress (NULL, NULL, 0);  /* have no idea where frame is now */
7709
7710   hc08_aop_pass[0] = newAsmop (AOP_REG);
7711   hc08_aop_pass[0]->size=1;
7712   hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7713   hc08_aop_pass[1] = newAsmop (AOP_REG);
7714   hc08_aop_pass[1]->size=1;
7715   hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7716   hc08_aop_pass[2] = newAsmop (AOP_DIR);
7717   hc08_aop_pass[2]->size=1;
7718   hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7719   hc08_aop_pass[3] = newAsmop (AOP_DIR);
7720   hc08_aop_pass[3]->size=1;
7721   hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7722
7723   for (ic = lic; ic; ic = ic->next)
7724     {
7725       
7726       _G.current_iCode = ic;
7727       
7728       if (ic->level != clevel || ic->block != cblock)
7729         {
7730           if (options.debug)
7731             {
7732               debugFile->writeScope(ic);
7733             }
7734           clevel = ic->level;
7735           cblock = ic->block;
7736         }
7737         
7738       if (ic->lineno && cln != ic->lineno)
7739         {
7740           if (options.debug)
7741             {
7742               debugFile->writeCLine(ic);
7743               #if 0
7744               _G.debugLine = 1;
7745               emitcode ("", "C$%s$%d$%d$%d ==.",
7746                         FileBaseName (ic->filename), ic->lineno,
7747                         ic->level, ic->block);
7748               _G.debugLine = 0;
7749               #endif
7750             }
7751           if (!options.noCcodeInAsm) {
7752             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, 
7753                       printCLine(ic->filename, ic->lineno));
7754           }
7755           cln = ic->lineno;
7756         }
7757       if (options.iCodeInAsm) {
7758         char regsInUse[80];
7759         int i;
7760
7761         for (i=0; i<6; i++) {
7762           sprintf (&regsInUse[i],
7763                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); 
7764         }
7765         regsInUse[i]=0;
7766         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7767       }
7768       /* if the result is marked as
7769          spilt and rematerializable or code for
7770          this has already been generated then
7771          do nothing */
7772       if (resultRemat (ic) || ic->generated)
7773         continue;
7774
7775       {
7776         int i;
7777         regs *reg;
7778         symbol *sym;
7779         
7780         for (i=A_IDX;i<=XA_IDX;i++)
7781           {
7782             reg = hc08_regWithIdx(i);
7783             if (reg->aop)
7784               emitcode("","; %s = %s offset %d", reg->name,
7785                        aopName(reg->aop), reg->aopofs);
7786             reg->isFree = TRUE;
7787           }
7788         if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7789           {
7790             sym = OP_SYMBOL (IC_LEFT (ic));
7791             if (sym->accuse == ACCUSE_HX)
7792               {
7793                 hc08_reg_h->isFree = FALSE;
7794                 hc08_reg_x->isFree = FALSE;
7795               }
7796             else if (sym->accuse == ACCUSE_XA)
7797               {
7798                 hc08_reg_a->isFree = FALSE;
7799                 if (sym->nRegs>1)
7800                   hc08_reg_x->isFree = FALSE;
7801               }
7802           }
7803         if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7804           {
7805             sym = OP_SYMBOL (IC_RIGHT (ic));
7806             if (sym->accuse == ACCUSE_HX)
7807               {
7808                 hc08_reg_h->isFree = FALSE;
7809                 hc08_reg_x->isFree = FALSE;
7810               }
7811             else if (sym->accuse == ACCUSE_XA)
7812               {
7813                 hc08_reg_a->isFree = FALSE;
7814                 if (sym->nRegs>1)
7815                   hc08_reg_x->isFree = FALSE;
7816               }
7817           }
7818       }
7819       
7820       /* depending on the operation */
7821       switch (ic->op)
7822         {
7823         case '!':
7824           genNot (ic);
7825           break;
7826
7827         case '~':
7828           genCpl (ic);
7829           break;
7830
7831         case UNARYMINUS:
7832           genUminus (ic);
7833           break;
7834
7835         case IPUSH:
7836           genIpush (ic);
7837           break;
7838
7839         case IPOP:
7840           /* IPOP happens only when trying to restore a
7841              spilt live range, if there is an ifx statement
7842              following this pop then the if statement might
7843              be using some of the registers being popped which
7844              would destory the contents of the register so
7845              we need to check for this condition and handle it */
7846           if (ic->next &&
7847               ic->next->op == IFX &&
7848               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7849             genIfx (ic->next, ic);
7850           else
7851             genIpop (ic);
7852           break;
7853
7854         case CALL:
7855           genCall (ic);
7856           break;
7857
7858         case PCALL:
7859           genPcall (ic);
7860           break;
7861
7862         case FUNCTION:
7863           genFunction (ic);
7864           break;
7865
7866         case ENDFUNCTION:
7867           genEndFunction (ic);
7868           break;
7869
7870         case RETURN:
7871           genRet (ic);
7872           break;
7873
7874         case LABEL:
7875           genLabel (ic);
7876           break;
7877
7878         case GOTO:
7879           genGoto (ic);
7880           break;
7881
7882         case '+':
7883           if (!genPointerGetSetOfs (ic))
7884             genPlus (ic);
7885           break;
7886
7887         case '-':
7888           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7889             genMinus (ic);
7890           break;
7891
7892         case '*':
7893           genMult (ic);
7894           break;
7895
7896         case '/':
7897           genDiv (ic);
7898           break;
7899
7900         case '%':
7901           genMod (ic);
7902           break;
7903
7904         case '>':
7905           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7906           break;
7907
7908         case '<':
7909           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7910           break;
7911
7912         case LE_OP:
7913         case GE_OP:
7914         case NE_OP:
7915
7916           /* note these two are xlated by algebraic equivalence
7917              during parsing SDCC.y */
7918           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7919                   "got '>=' or '<=' shouldn't have come here");
7920           break;
7921
7922         case EQ_OP:
7923           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7924           break;
7925
7926         case AND_OP:
7927           genAndOp (ic);
7928           break;
7929
7930         case OR_OP:
7931           genOrOp (ic);
7932           break;
7933
7934         case '^':
7935           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7936           break;
7937
7938         case '|':
7939           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7940           break;
7941
7942         case BITWISEAND:
7943           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7944           break;
7945
7946         case INLINEASM:
7947           genInline (ic);
7948           break;
7949
7950         case RRC:
7951           genRRC (ic);
7952           break;
7953
7954         case RLC:
7955           genRLC (ic);
7956           break;
7957
7958         case GETHBIT:
7959           genGetHbit (ic);
7960           break;
7961
7962         case LEFT_OP:
7963           genLeftShift (ic);
7964           break;
7965
7966         case RIGHT_OP:
7967           genRightShift (ic);
7968           break;
7969
7970         case GET_VALUE_AT_ADDRESS:
7971           genPointerGet (ic,
7972                          hasInc (IC_LEFT (ic), ic,
7973                                  getSize (operandType (IC_RESULT (ic)))),
7974                          ifxForOp (IC_RESULT (ic), ic) );
7975           break;
7976
7977         case '=':
7978           if (POINTER_SET (ic))
7979             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7980           else
7981             genAssign (ic);
7982           break;
7983
7984         case IFX:
7985           genIfx (ic, NULL);
7986           break;
7987
7988         case ADDRESS_OF:
7989           genAddrOf (ic);
7990           break;
7991
7992         case JUMPTABLE:
7993           genJumpTab (ic);
7994           break;
7995
7996         case CAST:
7997           genCast (ic);
7998           break;
7999
8000         case RECEIVE:
8001           genReceive (ic);
8002           break;
8003
8004         case SEND:
8005           addSet (&_G.sendSet, ic);
8006           break;
8007
8008         case DUMMY_READ_VOLATILE:
8009           genDummyRead (ic);
8010           break;
8011
8012         case CRITICAL:
8013           genCritical (ic);
8014           break;
8015
8016         case ENDCRITICAL:
8017           genEndCritical (ic);
8018           break;
8019         
8020         case SWAP:
8021           genSwap (ic);
8022           break;
8023
8024         default:
8025           ic = ic;
8026         }
8027
8028       if (!hc08_reg_a->isFree)
8029         D(emitcode("","; forgot to free a"));
8030       if (!hc08_reg_x->isFree)
8031         D(emitcode("","; forgot to free x"));
8032       if (!hc08_reg_h->isFree)
8033         D(emitcode("","; forgot to free h"));
8034       if (!hc08_reg_hx->isFree)
8035         D(emitcode("","; forgot to free hx"));
8036       if (!hc08_reg_xa->isFree)
8037         D(emitcode("","; forgot to free xa"));
8038     }
8039
8040   debugFile->writeFrameAddress (NULL, NULL, 0);  /* have no idea where frame is now */
8041     
8042
8043   /* now we are ready to call the
8044      peep hole optimizer */
8045   if (!options.nopeep)
8046     peepHole (&lineHead);
8047
8048   /* now do the actual printing */
8049   printLine (lineHead, codeOutFile);
8050   return;
8051 }