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