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