1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for the 68HC08
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)
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
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.
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.
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!
28 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 char *aopLiteral (value * val, int offset);
46 char *aopLiteralLong (value * val, int offset, int size);
48 static int pushReg (regs *reg, bool freereg);
49 static void pullReg (regs *reg);
51 static char *zero = "#0x00";
52 static char *one = "#0x01";
56 {"a", "x", "_ret2", "_ret3"};
57 unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */
58 char **fReturn2 = fReturnhc08;
77 static asmop *hc08_aop_pass[4];
79 extern int hc08_ptrRegReq;
80 extern int hc08_nRegs;
81 extern FILE *codeOutFile;
82 //static void saveRBank (int, iCode *, bool);
83 static bool operandsEqu (operand * op1, operand * op2);
84 static void loadRegFromConst (regs *reg, char *c);
85 static char *aopName (asmop *aop);
86 static asmop * newAsmop (short type);
87 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define IS_AOP_HX(x) \
93 (((x)->type == AOP_REG) \
94 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
95 && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
97 #define IS_AOP_XA(x) \
98 (((x)->type == AOP_REG) \
99 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
100 && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
102 #define IS_AOP_A(x) \
103 (((x)->type == AOP_REG) \
104 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
105 && ((x)->size == 1) )
107 #define IS_AOP_X(x) \
108 (((x)->type == AOP_REG) \
109 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
110 && ((x)->size == 1) )
112 #define IS_AOP_H(x) \
113 (((x)->type == AOP_REG) \
114 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
115 && ((x)->size == 1) )
117 #define CLRC emitcode("clc","")
119 static lineNode *lineHead = NULL;
120 static lineNode *lineCurr = NULL;
123 static unsigned char SLMask[] =
124 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
125 0xE0, 0xC0, 0x80, 0x00};
126 static unsigned char SRMask[] =
127 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
128 0x07, 0x03, 0x01, 0x00};
136 #define AOP(op) op->aop
137 #define AOP_TYPE(op) AOP(op)->type
138 #define AOP_SIZE(op) AOP(op)->size
139 #define AOP_OP(aop) aop->op
142 /*-----------------------------------------------------------------*/
143 /* emitcode - writes the code into a file : for now it is simple */
144 /*-----------------------------------------------------------------*/
146 emitcode (char *inst, char *fmt,...)
149 char lb[INITIAL_INLINEASM];
157 sprintf (lb, "%s\t", inst);
159 sprintf (lb, "%s", inst);
160 vsprintf (lb + (strlen (lb)), fmt, ap);
163 vsprintf (lb, fmt, ap);
165 while (isspace (*lbp))
169 lineCurr = (lineCurr ?
170 connectLine (lineCurr, newLineNode (lb)) :
171 (lineHead = newLineNode (lb)));
172 lineCurr->isInline = _G.inLine;
173 lineCurr->isDebug = _G.debugLine;
174 lineCurr->ic = _G.current_iCode;
176 //printf("%s\n", lb);
181 emitBranch (char *branchop, symbol *tlbl)
183 emitcode (branchop, "%05d$", (tlbl->key + 100));
187 emitLabel (symbol *tlbl)
189 emitcode ("", "%05d$:", (tlbl->key +100));
192 /*-----------------------------------------------------------------*/
193 /* hc08_emitDebuggerSymbol - associate the current code location */
194 /* with a debugger symbol */
195 /*-----------------------------------------------------------------*/
197 hc08_emitDebuggerSymbol (char * debugSym)
200 emitcode ("", "%s ==.", debugSym);
205 /*--------------------------------------------------------------------------*/
206 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
207 /* freesrc is true, sreg is marked free and available for */
208 /* reuse. sreg and dreg must be of equal size */
209 /*--------------------------------------------------------------------------*/
211 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
217 /* Nothing to do if no destination. */
221 /* But it's definately an error if there's no source. */
224 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
225 "NULL sreg in transferRegReg");
229 D(emitcode ("", "; transferRegReg(%s,%s)",
230 sreg->name, dreg->name));
243 case H_IDX: /* H to A */
244 pushReg (hc08_reg_h, FALSE);
245 pullReg (hc08_reg_a);
247 case X_IDX: /* X to A */
248 emitcode ("txa", "");
257 case A_IDX: /* A to H */
258 pushReg (hc08_reg_a, FALSE);
259 pullReg (hc08_reg_h);
261 case X_IDX: /* X to H */
262 pushReg (hc08_reg_x, FALSE);
263 pullReg (hc08_reg_h);
272 case A_IDX: /* A to X */
273 emitcode ("tax", "");
275 case H_IDX: /* H to X */
276 pushReg (hc08_reg_h, FALSE);
277 pullReg (hc08_reg_x);
286 case XA_IDX: /* XA to HX */
287 pushReg (hc08_reg_x, FALSE);
288 pullReg (hc08_reg_h);
289 emitcode ("tax", "");
298 case HX_IDX: /* HX to XA */
299 emitcode ("txa", "");
300 pushReg (hc08_reg_h, FALSE);
301 pullReg (hc08_reg_x);
311 wassertl (!error, "bad combo in transferRegReg");
316 dreg->aop = sreg->aop;
317 dreg->aopofs = sreg->aopofs;
318 dreg->isFree = FALSE;
322 /*--------------------------------------------------------------------------*/
323 /* updateCFA - update the debugger information to reflect the current */
324 /* connonical frame address relative to the stack pointer */
325 /*--------------------------------------------------------------------------*/
329 /* there is no frame unless there is a function */
333 debugFile->writeFrameAddress (NULL, hc08_reg_sp,
334 1 + _G.stackOfs + _G.stackPushes);
337 /*--------------------------------------------------------------------------*/
338 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
339 /* marked free and available for reuse. */
340 /*--------------------------------------------------------------------------*/
342 pushReg (regs *reg, bool freereg)
344 int regidx = reg->rIdx;
349 emitcode ("psha", "");
354 emitcode ("pshx", "");
359 emitcode ("pshh", "");
364 emitcode ("pshx", "");
367 emitcode ("pshh", "");
372 emitcode ("psha", "");
375 emitcode ("pshx", "");
384 return -_G.stackOfs-_G.stackPushes;
387 /*--------------------------------------------------------------------------*/
388 /* pullReg - Pull register reg off the stack. */
389 /*--------------------------------------------------------------------------*/
393 int regidx = reg->rIdx;
398 emitcode ("pula", "");
403 emitcode ("pulx", "");
408 emitcode ("pulh", "");
413 emitcode ("pulx", "");
416 emitcode ("pulh", "");
421 emitcode ("pula", "");
424 emitcode ("pulx", "");
432 hc08_dirtyReg(reg, FALSE);
435 /*--------------------------------------------------------------------------*/
436 /* pullNull - Discard n bytes off the top of the stack */
437 /*--------------------------------------------------------------------------*/
443 emitcode("ais","#%d",n);
449 /*--------------------------------------------------------------------------*/
450 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
451 /* push was performed, false otherwise. */
452 /*--------------------------------------------------------------------------*/
454 pushRegIfUsed (regs *reg)
465 /*--------------------------------------------------------------------------*/
466 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
467 /* stack. Otherwise register reg is marked as free. */
468 /*--------------------------------------------------------------------------*/
470 pullOrFreeReg (regs *reg, bool needpull)
478 /*--------------------------------------------------------------------------*/
479 /* adjustStack - Adjust the stack pointer by n bytes. */
480 /*--------------------------------------------------------------------------*/
488 emitcode ("ais","#127");
490 _G.stackPushes -= 127;
495 emitcode ("ais","#-128");
497 _G.stackPushes += 128;
502 emitcode ("ais", "#%d", n);
511 /*--------------------------------------------------------------------------*/
512 /* aopName - Return a string with debugging information about an asmop. */
513 /*--------------------------------------------------------------------------*/
517 static char buffer[256];
521 return "(asmop*)NULL";
526 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
529 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
532 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
535 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
538 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
541 sprintf (buf, "REG(%s,%s,%s,%s)",
542 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
543 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
544 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
545 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
552 sprintf (buf,"?%d", aop->type);
560 /*--------------------------------------------------------------------------*/
561 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
562 /*--------------------------------------------------------------------------*/
564 loadRegFromAop (regs *reg, asmop *aop, int loffset)
566 int regidx = reg->rIdx;
568 if (aop->stacked && aop->stk_aop[loffset])
570 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
575 printf("loadRegFromAop called\n");
578 printf(" reg = NULL\n");
581 printf(" reg = %s\n", reg->name);
584 printf(" aop = NULL\n");
587 printf(" aop->type = %d\n", aop->type);
588 printf(" loffset = %d\n", loffset);
591 printf(" aop has operand link\n");
593 printf(" aop missing operand link\n");
595 printf(" reg has operand link\n");
597 printf(" reg missing operand link\n");
600 D(emitcode ("", "; loadRegFromAop (%s, %s, %d)",
601 reg->name, aopName (aop), loffset));
603 /* If operand is volatile, we cannot optimize. */
604 if (!aop->op || isOperandVolatile (aop->op, FALSE))
608 /* If this register already has this offset of the operand
609 then we need only mark it as in use. */
610 if (reg->aop && reg->aop->op && aop->op
611 && operandsEqu(reg->aop->op,aop->op)
612 && (reg->aopofs == loffset))
615 D(emitcode ("","; already had correct value for %s", reg->name));
619 /* TODO: check to see if we can transfer from another register */
621 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
622 && operandsEqu(hc08_reg_h->aop->op,aop->op)
623 && (hc08_reg_h->aopofs == loffset))
625 D(emitcode ("","; found correct value for %s in h", reg->name));
626 transferRegReg (hc08_reg_h, reg, FALSE);
632 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
633 && operandsEqu(hc08_reg_x->aop->op,aop->op)
634 && (hc08_reg_x->aopofs == loffset))
636 D(emitcode ("","; found correct value for %s in x", reg->name));
637 transferRegReg (hc08_reg_x, reg, FALSE);
642 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
643 && operandsEqu(hc08_reg_a->aop->op,aop->op)
644 && (hc08_reg_a->aopofs == loffset))
646 D(emitcode ("","; found correct value for %s in a", reg->name));
647 transferRegReg (hc08_reg_a, reg, FALSE);
657 if (aop->type == AOP_REG)
659 if (loffset < aop->size)
660 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
662 emitcode ("clra", ""); /* TODO: handle sign extension */
666 char * l = aopAdrStr (aop, loffset, FALSE);
667 if (!strcmp (l, zero))
668 emitcode ("clra", "");
670 emitcode ("lda", "%s", l);
674 if (aop->type == AOP_REG)
676 if (loffset < aop->size)
677 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
679 emitcode ("clrx", ""); /* TODO: handle sign extension */
683 char * l = aopAdrStr (aop, loffset, FALSE);
684 if (!strcmp (l, zero))
685 emitcode ("clrx", "");
687 emitcode ("ldx", "%s", l);
691 if (hc08_reg_a->isFree)
693 loadRegFromAop (hc08_reg_a, aop, loffset);
694 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
696 else if (hc08_reg_x->isFree)
698 loadRegFromAop (hc08_reg_x, aop, loffset);
699 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
703 pushReg (hc08_reg_a, TRUE);
704 loadRegFromAop (hc08_reg_a, aop, loffset);
705 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
706 pullReg (hc08_reg_a);
712 else if (IS_AOP_XA(aop))
713 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
714 else if ((aop->type == AOP_DIR))
716 if (aop->size>(loffset+1))
717 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
720 loadRegFromAop (hc08_reg_x, aop, loffset);
721 loadRegFromConst (hc08_reg_h, zero);
724 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
726 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
731 needpula = pushRegIfUsed (hc08_reg_a);
732 loadRegFromAop (hc08_reg_a, aop, loffset+1);
733 loadRegFromAop (hc08_reg_x, aop, loffset);
734 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
735 pullOrFreeReg (hc08_reg_a, needpula);
741 else if (IS_AOP_HX(aop))
742 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
745 loadRegFromAop (hc08_reg_a, aop, loffset);
746 loadRegFromAop (hc08_reg_x, aop, loffset+1);
751 // ignore caching for now
754 reg->aopofs = loffset;
759 /*--------------------------------------------------------------------------*/
760 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
761 /* freeAsmop is called with aop, the stacked data will */
762 /* be copied to the original aop location and */
763 /*--------------------------------------------------------------------------*/
765 forceStackedAop (asmop *aop)
768 asmop *newaop = newAsmop (aop->type);
769 memcpy (newaop, aop, sizeof(*newaop));
771 D(emitcode("", "; forcedStackAop %s", aopName(aop)));
772 for (loffset=0; loffset < newaop->size; loffset++)
774 asmop *aopsof = newAsmop (AOP_SOF);
776 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
777 aopsof->op = aop->op;
778 newaop->stk_aop[loffset] = aopsof;
785 /*--------------------------------------------------------------------------*/
786 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
787 /*--------------------------------------------------------------------------*/
789 storeRegToAop (regs *reg, asmop *aop, int loffset)
791 int regidx = reg->rIdx;
797 D(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
798 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
800 if ((reg->rIdx == HX_IDX) && aop->stacked
801 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
803 storeRegToAop (hc08_reg_h, aop, loffset+1);
804 storeRegToAop (hc08_reg_x, aop, loffset);
808 if ((reg->rIdx == XA_IDX) && aop->stacked
809 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
811 storeRegToAop (hc08_reg_x, aop, loffset+1);
812 storeRegToAop (hc08_reg_a, aop, loffset);
816 if (aop->stacked && aop->stk_aop[loffset])
818 storeRegToAop (reg, aop->stk_aop[loffset], 0);
822 if (aop->type == AOP_STR)
825 transferRegReg (reg, hc08_reg_x, FALSE);
827 transferRegReg (reg, hc08_reg_h, FALSE);
831 if (aop->type == AOP_DUMMY)
837 if ((aop->type == AOP_REG) && (loffset < aop->size))
838 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
840 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
843 if ((aop->type == AOP_REG) && (loffset < aop->size))
844 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
846 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
849 if (hc08_reg_a->isFree)
851 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
852 storeRegToAop (hc08_reg_a, aop, loffset);
853 hc08_freeReg (hc08_reg_a);
855 else if (hc08_reg_x->isFree)
857 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
858 storeRegToAop (hc08_reg_x, aop, loffset);
859 hc08_freeReg (hc08_reg_x);
863 pushReg (hc08_reg_a, TRUE);
864 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
865 storeRegToAop (hc08_reg_a, aop, loffset);
866 pullReg (hc08_reg_a);
870 if ((aop->type == AOP_DIR) )
872 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
874 else if (IS_AOP_XA(aop))
875 transferRegReg(reg, hc08_reg_xa, FALSE);
876 else if (IS_AOP_HX(aop))
881 needpula = pushRegIfUsed (hc08_reg_a);
882 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
883 storeRegToAop (hc08_reg_a, aop, loffset+1);
884 storeRegToAop (hc08_reg_x, aop, loffset);
885 pullOrFreeReg (hc08_reg_a, needpula);
890 transferRegReg(reg, hc08_reg_hx, FALSE);
891 else if (IS_AOP_XA(aop))
895 storeRegToAop (hc08_reg_a, aop, loffset);
896 storeRegToAop (hc08_reg_x, aop, loffset+1);
901 /* Disable the register tracking for now */
903 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
906 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
908 otherreg=hc08_regWithIdx(otheridx);
909 if (otherreg && otherreg->aop
910 && otherreg->aop->op && aop->op
911 && operandsEqu(otherreg->aop->op,aop->op)
912 && (otherreg->aopofs == loffset))
914 D(emitcode("","; marking %s stale", otherreg->name));
918 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
920 hc08_reg_hx->aop = NULL;
921 D(emitcode("","; marking hx stale"));
923 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
925 hc08_reg_xa->aop = NULL;
926 D(emitcode("","; marking xa stale"));
930 reg->aopofs = loffset;
935 /*--------------------------------------------------------------------------*/
936 /* loadRegFromConst - Load register reg from constant c. */
937 /*--------------------------------------------------------------------------*/
939 loadRegFromConst (regs *reg, char *c)
945 emitcode ("clra", "");
947 emitcode ("lda", "%s", c);
951 emitcode ("clrx", "");
953 emitcode ("ldx", "%s", c);
957 emitcode ("clrh", "");
958 else if (hc08_reg_a->isFree)
960 loadRegFromConst (hc08_reg_a, c);
961 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
963 else if (hc08_reg_x->isFree)
965 loadRegFromConst (hc08_reg_x, c);
966 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
970 pushReg (hc08_reg_a, TRUE);
971 loadRegFromConst (hc08_reg_a, c);
972 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
973 pullReg (hc08_reg_a);
977 emitcode ("ldhx", "%s", c);
980 emitcode ("lda", "%s", c);
981 emitcode ("ldx", "%s >> 8", c);
984 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
985 "Bad rIdx in loadRegFromConst");
992 /*--------------------------------------------------------------------------*/
993 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
994 /*--------------------------------------------------------------------------*/
996 storeConstToAop (char *c, asmop *aop, int loffset)
998 if (aop->stacked && aop->stk_aop[loffset])
1000 storeConstToAop (c, aop->stk_aop[loffset], 0);
1007 if (!strcmp(c,zero))
1008 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
1010 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
1013 if (loffset>(aop->size-1))
1015 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
1020 if (hc08_reg_a->isFree)
1022 loadRegFromConst (hc08_reg_a, c);
1023 storeRegToAop( hc08_reg_a, aop, loffset);
1024 hc08_freeReg (hc08_reg_a);
1026 else if (hc08_reg_x->isFree)
1028 loadRegFromConst (hc08_reg_x, c);
1029 storeRegToAop( hc08_reg_x, aop, loffset);
1030 hc08_freeReg (hc08_reg_x);
1034 pushReg (hc08_reg_a, TRUE);
1035 loadRegFromConst (hc08_reg_a, c);
1036 storeRegToAop( hc08_reg_a, aop, loffset);
1037 pullReg (hc08_reg_a);
1043 /*--------------------------------------------------------------------------*/
1044 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
1045 /* reg is extended to fill logical offsets loffset */
1046 /* and above of asmop aop. Otherwise, logical */
1047 /* offsets loffset and above of asmop aop are */
1048 /* zeroed. reg must be an 8-bit register. */
1049 /*--------------------------------------------------------------------------*/
1051 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
1053 // int regidx = reg->rIdx;
1054 int size = aop->size;
1062 while (loffset<size)
1063 storeConstToAop(zero, aop, loffset++);
1068 transferRegReg (reg, hc08_reg_a, FALSE);
1069 emitcode ("rola","");
1070 emitcode ("clra","");
1071 emitcode ("sbc", "#0");
1072 hc08_useReg (hc08_reg_a);
1073 while (loffset<size)
1074 storeRegToAop (hc08_reg_a, aop, loffset++);
1075 hc08_freeReg (hc08_reg_a);
1079 /*--------------------------------------------------------------------------*/
1080 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1081 /* padding and/or truncation as needed. If isSigned is */
1082 /* true, sign extension will take place in the padding. */
1083 /*--------------------------------------------------------------------------*/
1085 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1087 int regidx = reg->rIdx;
1088 int size = aop->size;
1095 storeRegToAop (reg, aop, 0);
1096 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1101 storeRegToAop (hc08_reg_x, aop, 0);
1105 storeRegToAop (reg, aop, 0);
1106 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1112 storeRegToAop (hc08_reg_a, aop, 0);
1116 storeRegToAop (reg, aop, 0);
1117 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1123 /*--------------------------------------------------------------------------*/
1124 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1125 /* srcaop to logical offset dstofs of asmop dstofs. */
1126 /*--------------------------------------------------------------------------*/
1128 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1130 bool needpula = FALSE;
1133 bool keepreg = FALSE;
1135 /* ignore transfers at the same byte, unless its volatile */
1136 if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
1137 && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
1138 && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs)
1141 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1143 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1147 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1149 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1153 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1154 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1155 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1156 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1158 if (dstofs >= dstaop->size)
1161 if ((dstaop->type == AOP_DIR)
1162 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1164 if (srcaop->type == AOP_LIT)
1167 unsigned char bytemask;
1169 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1170 bytemask = (lit >> (srcofs*8)) & 0xff;
1174 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1179 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1180 aopAdrStr(dstaop, dstofs, FALSE));
1184 if (dstaop->type == AOP_REG)
1186 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1187 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1189 reg = dstaop->aopu.aop_reg[dstofs];
1194 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1196 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1197 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1199 reg = srcaop->aopu.aop_reg[srcofs];
1206 if (hc08_reg_a->isFree)
1208 else if (hc08_reg_x->isFree)
1212 pushReg (hc08_reg_a, TRUE);
1218 loadRegFromAop (reg, srcaop, srcofs);
1219 storeRegToAop (reg, dstaop, dstofs);
1222 pullOrFreeReg (hc08_reg_a, needpula);
1226 /*--------------------------------------------------------------------------*/
1227 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1228 /* parameter param. */
1229 /*--------------------------------------------------------------------------*/
1231 accopWithMisc (char *accop, char *param)
1233 emitcode (accop, "%s", param);
1234 hc08_dirtyReg (hc08_reg_a, FALSE);
1237 /*--------------------------------------------------------------------------*/
1238 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1239 /* byte at logical offset loffset of asmop aop. */
1240 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1241 /*--------------------------------------------------------------------------*/
1243 accopWithAop (char *accop, asmop *aop, int loffset)
1245 if (aop->stacked && aop->stk_aop[loffset])
1247 accopWithAop (accop, aop->stk_aop[loffset], 0);
1251 if (aop->type == AOP_DUMMY)
1254 if (aop->type == AOP_REG)
1256 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1257 emitcode (accop, "1,s");
1261 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1263 hc08_dirtyReg (hc08_reg_a, FALSE);
1267 /*--------------------------------------------------------------------------*/
1268 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1269 /* byte at logical offset loffset of asmop aop. Register reg */
1270 /* must be 8-bit. */
1271 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1272 /*--------------------------------------------------------------------------*/
1274 rmwWithReg (char *rmwop, regs *reg)
1277 char *rmwaop = rmwbuf;
1279 if (reg->rIdx == A_IDX)
1281 sprintf(rmwaop,"%sa", rmwop);
1282 emitcode (rmwaop, "");
1283 hc08_dirtyReg (hc08_reg_a, FALSE);
1285 else if (reg->rIdx == X_IDX)
1287 sprintf(rmwaop,"%sx", rmwop);
1288 emitcode (rmwaop, "");
1289 hc08_dirtyReg (hc08_reg_a, FALSE);
1291 else if (hc08_reg_a->isFree)
1293 transferRegReg(reg, hc08_reg_a, FALSE);
1294 sprintf(rmwaop,"%sa", rmwop);
1295 emitcode (rmwaop, "");
1296 hc08_dirtyReg (hc08_reg_a, FALSE);
1297 transferRegReg(hc08_reg_a, reg, TRUE);
1301 pushReg (reg, FALSE);
1302 emitcode (rmwop, "1,s");
1304 hc08_dirtyReg (reg, FALSE);
1308 /*--------------------------------------------------------------------------*/
1309 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1310 /* logical offset loffset of asmop aop. */
1311 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1312 /*--------------------------------------------------------------------------*/
1314 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1316 bool needpula = FALSE;
1318 if (aop->stacked && aop->stk_aop[loffset])
1320 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1327 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1330 needpula = pushRegIfUsed (hc08_reg_a);
1331 loadRegFromAop (hc08_reg_a, aop, loffset);
1332 rmwWithReg (rmwop, hc08_reg_a);
1333 if (strcmp ("tst", rmwop))
1334 storeRegToAop (hc08_reg_a, aop, loffset);
1335 pullOrFreeReg (hc08_reg_a, needpula);
1340 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1346 /*-----------------------------------------------------------------*/
1347 /* newAsmop - creates a new asmOp */
1348 /*-----------------------------------------------------------------*/
1350 newAsmop (short type)
1354 aop = Safe_calloc (1, sizeof (asmop));
1361 /*-----------------------------------------------------------------*/
1362 /* pointerCode - returns the code for a pointer type */
1363 /*-----------------------------------------------------------------*/
1365 pointerCode (sym_link * etype)
1368 return PTR_TYPE (SPEC_OCLS (etype));
1373 /*-----------------------------------------------------------------*/
1374 /* aopForSym - for a true symbol */
1375 /*-----------------------------------------------------------------*/
1377 aopForSym (iCode * ic, symbol * sym, bool result)
1382 wassertl (ic != NULL, "Got a null iCode");
1383 wassertl (sym != NULL, "Got a null symbol");
1385 // printf("in aopForSym for symbol %s\n", sym->name);
1387 space = SPEC_OCLS (sym->etype);
1389 /* if already has one */
1395 /* special case for a function */
1396 if (IS_FUNC (sym->type))
1398 sym->aop = aop = newAsmop (AOP_IMMD);
1399 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1400 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1401 aop->size = FPTRSIZE;
1405 /* if it is in direct space */
1406 if (IN_DIRSPACE (space))
1408 sym->aop = aop = newAsmop (AOP_DIR);
1409 aop->aopu.aop_dir = sym->rname;
1410 aop->size = getSize (sym->type);
1414 /* if it is in far space */
1415 if (IN_FARSPACE (space))
1417 sym->aop = aop = newAsmop (AOP_EXT);
1418 aop->aopu.aop_dir = sym->rname;
1419 aop->size = getSize (sym->type);
1423 if (IN_STACK (sym->etype))
1425 sym->aop = aop = newAsmop (AOP_SOF);
1426 aop->aopu.aop_dir = sym->rname;
1427 aop->size = getSize (sym->type);
1428 aop->aopu.aop_stk = sym->stack;
1434 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1435 "aopForSym should never reach here");
1439 /* if it is in code space */
1440 if (IN_CODESPACE (space))
1446 /*-----------------------------------------------------------------*/
1447 /* aopForRemat - rematerialzes an object */
1448 /*-----------------------------------------------------------------*/
1450 aopForRemat (symbol * sym)
1452 iCode *ic = sym->rematiCode;
1460 val += (int) operandLitValue (IC_RIGHT (ic));
1461 else if (ic->op == '-')
1462 val -= (int) operandLitValue (IC_RIGHT (ic));
1463 else if (IS_CAST_ICODE(ic)) {
1464 sym_link *from_type = operandType(IC_RIGHT(ic));
1465 aop->aopu.aop_immd.from_cast_remat = 1;
1466 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1467 ptr_type = DCL_TYPE(from_type);
1468 if (ptr_type == IPOINTER) {
1475 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1478 if (ic->op == ADDRESS_OF)
1481 sprintf (buffer, "(%s %c 0x%04x)",
1482 OP_SYMBOL (IC_LEFT (ic))->rname,
1483 val >= 0 ? '+' : '-',
1484 abs (val) & 0xffff);
1486 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1488 aop = newAsmop (AOP_IMMD);
1489 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1490 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1491 /* set immd2 field if required */
1492 if (aop->aopu.aop_immd.from_cast_remat)
1494 sprintf(buffer,"#0x%02x",ptr_type);
1495 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1496 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1499 else if (ic->op == '=')
1501 val += (int) operandLitValue (IC_RIGHT (ic));
1503 sprintf (buffer, "0x%04x", val);
1504 aop = newAsmop (AOP_LIT);
1505 aop->aopu.aop_lit = constVal (buffer);
1508 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1509 "unexpected rematerialization");
1516 /*-----------------------------------------------------------------*/
1517 /* regsInCommon - two operands have some registers in common */
1518 /*-----------------------------------------------------------------*/
1520 regsInCommon (operand * op1, operand * op2)
1522 symbol *sym1, *sym2;
1525 /* if they have registers in common */
1526 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1529 sym1 = OP_SYMBOL (op1);
1530 sym2 = OP_SYMBOL (op2);
1532 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1535 for (i = 0; i < sym1->nRegs; i++)
1541 for (j = 0; j < sym2->nRegs; j++)
1546 if (sym2->regs[j] == sym1->regs[i])
1554 /*-----------------------------------------------------------------*/
1555 /* operandsEqu - equivalent */
1556 /*-----------------------------------------------------------------*/
1558 operandsEqu (operand * op1, operand * op2)
1560 symbol *sym1, *sym2;
1562 /* if they not symbols */
1563 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1566 sym1 = OP_SYMBOL (op1);
1567 sym2 = OP_SYMBOL (op2);
1569 /* if both are itemps & one is spilt
1570 and the other is not then false */
1571 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1572 sym1->isspilt != sym2->isspilt)
1575 /* if they are the same */
1579 if (sym1->rname[0] && sym2->rname[0]
1580 && strcmp (sym1->rname, sym2->rname) == 0)
1583 /* if left is a tmp & right is not */
1584 if (IS_ITEMP (op1) &&
1587 (sym1->usl.spillLoc == sym2))
1590 if (IS_ITEMP (op2) &&
1594 (sym2->usl.spillLoc == sym1))
1600 /*-----------------------------------------------------------------*/
1601 /* sameRegs - two asmops have the same registers */
1602 /*-----------------------------------------------------------------*/
1604 sameRegs (asmop * aop1, asmop * aop2)
1611 // if (aop1->size != aop2->size)
1614 if (aop1->type == aop2->type)
1619 for (i = 0; i < aop1->size; i++)
1620 if (aop1->aopu.aop_reg[i] !=
1621 aop2->aopu.aop_reg[i])
1625 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1628 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1635 /*-----------------------------------------------------------------*/
1636 /* aopOp - allocates an asmop for an operand : */
1637 /*-----------------------------------------------------------------*/
1639 aopOp (operand * op, iCode * ic, bool result)
1648 // Is this a pointer set result?
1650 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1654 // printf("checking literal\n");
1655 /* if this a literal */
1656 if (IS_OP_LITERAL (op))
1658 op->aop = aop = newAsmop (AOP_LIT);
1659 aop->aopu.aop_lit = op->operand.valOperand;
1660 aop->size = getSize (operandType (op));
1662 aop->isaddr = op->isaddr;
1666 // printf("checking pre-existing\n");
1667 /* if already has a asmop then continue */
1671 op->aop->isaddr = op->isaddr;
1675 // printf("checking underlying sym\n");
1676 /* if the underlying symbol has a aop */
1677 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1679 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1680 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1681 //op->aop = aop = OP_SYMBOL (op)->aop;
1682 aop->size = getSize( operandType (op));
1683 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1684 //printf (" with size = %d\n", aop->size);
1687 aop->isaddr = op->isaddr;
1688 /* if (aop->isaddr & IS_ITEMP (op))
1690 aop->psize=aop->size;
1691 aop->size = getSize( operandType (op)->next);
1696 // printf("checking true sym\n");
1697 /* if this is a true symbol */
1698 if (IS_TRUE_SYMOP (op))
1700 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1702 aop->isaddr = op->isaddr;
1703 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1704 //printf (" with size = %d\n", aop->size);
1708 /* this is a temporary : this has
1714 e) can be a return use only */
1716 sym = OP_SYMBOL (op);
1718 // printf("checking conditional\n");
1719 /* if the type is a conditional */
1720 if (sym->regType == REG_CND)
1722 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1725 aop->isaddr = op->isaddr;
1729 // printf("checking spilt\n");
1730 /* if it is spilt then two situations
1732 b) has a spill location */
1733 if (sym->isspilt || sym->nRegs == 0)
1736 // printf("checking remat\n");
1737 /* rematerialize it NOW */
1740 sym->aop = op->aop = aop =
1742 aop->size = getSize (sym->type);
1744 aop->isaddr = op->isaddr;
1745 /* if (aop->isaddr & IS_ITEMP (op))
1747 aop->psize=aop->size;
1748 aop->size = getSize( operandType (op)->next);
1753 // printf("checking accuse\n");
1756 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1757 aop->size = getSize (sym->type);
1758 switch (sym->accuse)
1761 aop->aopu.aop_reg[0] = hc08_reg_a;
1762 aop->aopu.aop_reg[1] = hc08_reg_x;
1765 aop->aopu.aop_reg[0] = hc08_reg_x;
1766 aop->aopu.aop_reg[1] = hc08_reg_h;
1770 aop->isaddr = op->isaddr;
1774 // printf("checking ruonly\n");
1780 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1781 aop->size = getSize (sym->type);
1782 for (i = 0; i < fReturnSizeHC08; i++)
1783 aop->aopu.aop_str[i] = fReturn2[i];
1785 aop->isaddr = op->isaddr;
1789 /* else spill location */
1790 if (sym->usl.spillLoc)
1792 if (sym->usl.spillLoc->aop
1793 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1795 /* force a new aop if sizes differ */
1796 sym->usl.spillLoc->aop = NULL;
1797 //printf ("forcing new aop\n");
1799 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1800 aop->size = getSize (sym->type);
1802 aop->isaddr = op->isaddr;
1803 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1804 //printf (" with size = %d\n", aop->size);
1808 /* else must be a dummy iTemp */
1809 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1810 aop->size = getSize (sym->type);
1814 // printf("assuming register\n");
1815 /* must be in a register */
1816 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1817 aop->size = sym->nRegs;
1818 for (i = 0; i < sym->nRegs; i++)
1819 aop->aopu.aop_reg[i] = sym->regs[i];
1821 aop->isaddr = op->isaddr;
1825 /*-----------------------------------------------------------------*/
1826 /* freeAsmop - free up the asmop given to an operand */
1827 /*----------------------------------------------------------------*/
1829 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1851 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1854 for (loffset=0; loffset<aop->size; loffset++)
1855 if (aop->stk_aop[loffset])
1857 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1860 pullNull (stackAdjust);
1864 /* all other cases just dealloc */
1870 OP_SYMBOL (op)->aop = NULL;
1871 /* if the symbol has a spill */
1873 SPIL_LOC (op)->aop = NULL;
1879 /*-----------------------------------------------------------------*/
1880 /* aopDerefAop - treating the aop parameter as a pointer, return */
1881 /* an asmop for the object it references */
1882 /*-----------------------------------------------------------------*/
1884 aopDerefAop (asmop *aop)
1889 asmop *newaop = NULL;
1890 sym_link *type, *etype;
1893 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1897 type = operandType (aop->op);
1898 etype = getSpec (type);
1899 /* if op is of type of pointer then it is simple */
1900 if (IS_PTR (type) && !IS_FUNC (type->next))
1901 p_type = DCL_TYPE (type);
1904 /* we have to go by the storage class */
1905 p_type = PTR_TYPE (SPEC_OCLS (etype));
1914 if (p_type == POINTER)
1915 newaop = newAsmop (AOP_DIR);
1917 newaop = newAsmop (AOP_EXT);
1918 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1921 adr = (int) floatFromVal (aop->aopu.aop_lit);
1922 if (p_type == POINTER)
1927 newaop = newAsmop (AOP_DIR);
1928 sprintf (s, "0x%02x",adr);
1932 newaop = newAsmop (AOP_EXT);
1933 sprintf (s, "0x%04x",adr);
1935 rs = Safe_calloc (1, strlen (s) + 1);
1937 newaop->aopu.aop_dir = rs;
1940 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1941 "unsupported asmop");
1951 /*-----------------------------------------------------------------*/
1952 /* aopAdrStr - for referencing the address of the aop */
1953 /*-----------------------------------------------------------------*/
1955 aopAdrStr (asmop * aop, int loffset, bool bit16)
1959 int offset = aop->size - 1 - loffset;
1962 /* offset is greater than
1964 if (loffset > (aop->size - 1) &&
1965 aop->type != AOP_LIT)
1968 /* depending on type */
1976 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1977 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1979 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1983 sprintf (s, "#(%s >> %d)",
1984 aop->aopu.aop_immd.aop_immd1,
1988 aop->aopu.aop_immd.aop_immd1);
1992 aop->aopu.aop_immd.aop_immd1);
1993 rs = Safe_calloc (1, strlen (s) + 1);
1999 sprintf (s, "*(%s + %d)",
2003 sprintf (s, "*%s", aop->aopu.aop_dir);
2004 rs = Safe_calloc (1, strlen (s) + 1);
2010 sprintf (s, "(%s + %d)",
2014 sprintf (s, "%s", aop->aopu.aop_dir);
2015 rs = Safe_calloc (1, strlen (s) + 1);
2020 return aop->aopu.aop_reg[loffset]->name;
2024 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2026 return aopLiteral (aop->aopu.aop_lit, loffset);
2030 return aop->aopu.aop_str[loffset];
2033 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2035 rs = Safe_calloc (1, strlen (s) + 1);
2041 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2042 "aopAdrStr got unsupported aop->type");
2051 /*-----------------------------------------------------------------*/
2052 /* opIsGptr: returns non-zero if the passed operand is */
2053 /* a generic pointer type. */
2054 /*-----------------------------------------------------------------*/
2056 opIsGptr (operand * op)
2058 sym_link *type = operandType (op);
2060 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2068 /*-----------------------------------------------------------------*/
2069 /* getDataSize - get the operand data size */
2070 /*-----------------------------------------------------------------*/
2072 getDataSize (operand * op)
2075 size = AOP_SIZE (op);
2079 /*-----------------------------------------------------------------*/
2080 /* outAcc - output Acc */
2081 /*-----------------------------------------------------------------*/
2083 outAcc (operand * result)
2086 size = getDataSize (result);
2089 storeRegToAop (hc08_reg_a, AOP (result), 0);
2092 /* unsigned or positive */
2095 storeConstToAop (zero, AOP (result), offset++);
2100 /*-----------------------------------------------------------------*/
2101 /* outBitC - output a bit C */
2102 /*-----------------------------------------------------------------*/
2104 outBitC (operand * result)
2108 /* if the result is bit */
2109 if (AOP_TYPE (result) == AOP_CRY)
2110 aopPut (AOP (result), "c", 0);
2114 emitcode ("clra", "");
2115 emitcode ("rola", "");
2120 /*-----------------------------------------------------------------*/
2121 /* outBitNV - output a bit N^V */
2122 /*-----------------------------------------------------------------*/
2124 outBitNV (operand * result)
2126 symbol *tlbl, *tlbl1;
2128 tlbl = newiTempLabel (NULL);
2129 tlbl1 = newiTempLabel (NULL);
2131 emitBranch ("blt", tlbl);
2132 loadRegFromConst (hc08_reg_a, zero);
2133 emitBranch ("bra", tlbl1);
2135 loadRegFromConst (hc08_reg_a, one);
2141 /*-----------------------------------------------------------------*/
2142 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2143 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2144 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2145 /*-----------------------------------------------------------------*/
2147 asmopToBool (asmop *aop, bool resultInA)
2149 symbol *tlbl, *tlbl1;
2150 int size = aop->size;
2151 bool needpula = FALSE;
2152 bool flagsonly = TRUE;
2157 hc08_freeReg(hc08_reg_a);
2164 emitcode ("tsta", "");
2167 else if (IS_AOP_X(aop))
2168 emitcode ("tstx", "");
2169 else if (IS_AOP_H(aop))
2171 if (hc08_reg_a->isFree)
2173 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2174 emitcode ("tsta", "");
2176 hc08_freeReg(hc08_reg_a);
2178 else if (hc08_reg_x->isFree)
2180 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2181 emitcode ("tstx", "");
2182 hc08_freeReg(hc08_reg_x);
2186 emitcode ("pshh", "");
2187 emitcode ("tst", "1,s");
2188 emitcode ("ais", "#1");
2191 else if (IS_AOP_HX(aop))
2192 emitcode ("cphx", zero);
2193 else if (IS_AOP_XA(aop))
2195 symbol *tlbl = newiTempLabel (NULL);
2196 emitcode ("tsta", "");
2197 emitcode ("bne", "%05d$", (tlbl->key + 100));
2198 emitcode ("tstx", "");
2199 emitcode ("", "%05d$:", (tlbl->key + 100));
2203 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2204 "Bad rIdx in asmToBool");
2212 needpula = pushRegIfUsed (hc08_reg_a);
2213 loadRegFromAop (hc08_reg_a, aop, 0);
2214 for (offset=1; offset<size; offset++)
2215 accopWithAop ("ora", aop, offset);
2217 pullReg (hc08_reg_a);
2220 hc08_freeReg (hc08_reg_a);
2229 loadRegFromAop (hc08_reg_a, aop, 0);
2230 hc08_freeReg (hc08_reg_a);
2234 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2239 if (hc08_reg_a->isFree)
2241 loadRegFromAop (hc08_reg_a, aop, 0);
2242 accopWithAop ("ora", aop, 1);
2243 hc08_freeReg (hc08_reg_a);
2248 tlbl = newiTempLabel (NULL);
2249 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2250 emitcode ("bne", "%05d$", (tlbl->key + 100));
2251 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2252 emitcode ("", "%05d$:", (tlbl->key + 100));
2258 needpula = pushRegIfUsed (hc08_reg_a);
2259 loadRegFromAop (hc08_reg_a, aop, 0);
2260 for (offset=1; offset<size; offset++)
2261 accopWithAop ("ora", aop, offset);
2263 pullReg (hc08_reg_a);
2266 hc08_freeReg (hc08_reg_a);
2274 tlbl = newiTempLabel (NULL);
2278 tlbl1 = newiTempLabel (NULL);
2279 emitBranch ("bne", tlbl1);
2280 loadRegFromConst (hc08_reg_a, zero);
2281 emitBranch ("bra", tlbl);
2283 loadRegFromConst (hc08_reg_a, one);
2287 emitBranch ("beq", tlbl);
2288 loadRegFromConst (hc08_reg_a, one);
2291 hc08_useReg (hc08_reg_a);
2297 /*-----------------------------------------------------------------*/
2298 /* genNot - generate code for ! operation */
2299 /*-----------------------------------------------------------------*/
2303 D(emitcode ("; genNot",""));
2305 /* assign asmOps to operand & result */
2306 aopOp (IC_LEFT (ic), ic, FALSE);
2307 aopOp (IC_RESULT (ic), ic, TRUE);
2309 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2310 emitcode ("eor", one);
2311 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2313 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2314 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2318 /*-----------------------------------------------------------------*/
2319 /* genCpl - generate code for complement */
2320 /*-----------------------------------------------------------------*/
2326 regs* reg = hc08_reg_a;
2330 D(emitcode ("; genCpl",""));
2332 /* assign asmOps to operand & result */
2333 aopOp (IC_LEFT (ic), ic, FALSE);
2334 aopOp (IC_RESULT (ic), ic, TRUE);
2336 size = AOP_SIZE (IC_RESULT (ic));
2339 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2340 rmwWithReg ("com", reg);
2342 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2347 /* release the aops */
2348 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2349 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2352 /*-----------------------------------------------------------------*/
2353 /* genUminusFloat - unary minus for floating points */
2354 /*-----------------------------------------------------------------*/
2356 genUminusFloat (operand * op, operand * result)
2358 int size, offset = 0;
2361 D(emitcode ("; genUminusFloat",""));
2363 /* for this we just copy and then flip the bit */
2365 size = AOP_SIZE (op) - 1;
2369 transferAopAop (AOP (op), offset, AOP (result), offset);
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);
2381 /*-----------------------------------------------------------------*/
2382 /* genUminus - unary minus code generation */
2383 /*-----------------------------------------------------------------*/
2385 genUminus (iCode * ic)
2388 sym_link *optype, *rtype;
2393 D(emitcode ("; genUminus",""));
2396 aopOp (IC_LEFT (ic), ic, FALSE);
2397 aopOp (IC_RESULT (ic), ic, TRUE);
2399 optype = operandType (IC_LEFT (ic));
2400 rtype = operandType (IC_RESULT (ic));
2402 /* if float then do float stuff */
2403 if (IS_FLOAT (optype))
2405 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2409 /* otherwise subtract from zero */
2410 size = AOP_SIZE (IC_LEFT (ic));
2415 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2416 needpula = pushRegIfUsed (hc08_reg_a);
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);
2428 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2429 result = forceStackedAop (AOP (IC_RESULT (ic)));
2431 result = AOP (IC_RESULT (ic));
2433 needpula = pushRegIfUsed (hc08_reg_a);
2437 loadRegFromConst (hc08_reg_a, zero);
2438 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2439 storeRegToAop (hc08_reg_a, result, offset++);
2442 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2443 SPEC_USIGN (operandType (IC_LEFT (ic))));
2444 pullOrFreeReg (hc08_reg_a, needpula);
2446 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2447 freeAsmop (NULL, result, ic, TRUE);
2453 /* release the aops */
2454 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2455 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2458 /*-----------------------------------------------------------------*/
2459 /* saveRegisters - will look for a call and save the registers */
2460 /*-----------------------------------------------------------------*/
2462 saveRegisters (iCode * lic)
2469 for (ic = lic; ic; ic = ic->next)
2470 if (ic->op == CALL || ic->op == PCALL)
2475 fprintf (stderr, "found parameter push with no function call\n");
2479 /* if the registers have been saved already or don't need to be then
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)))))
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)));
2494 for (i = 0; i < hc08_nRegs; i++)
2496 if (bitVectBitValue (rsave, i))
2497 pushReg ( hc08_regWithIdx (i), FALSE);
2501 /*-----------------------------------------------------------------*/
2502 /* unsaveRegisters - pop the pushed registers */
2503 /*-----------------------------------------------------------------*/
2505 unsaveRegisters (iCode * ic)
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)));
2515 for (i = hc08_nRegs; i >= 0; i--)
2517 if (bitVectBitValue (rsave, i))
2518 pullReg ( hc08_regWithIdx (i));
2524 /*-----------------------------------------------------------------*/
2526 /*-----------------------------------------------------------------*/
2528 pushSide (operand * oper, int size)
2533 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2534 pushReg ( hc08_reg_a, TRUE);
2538 /*-----------------------------------------------------------------*/
2539 /* assignResultValue - */
2540 /*-----------------------------------------------------------------*/
2542 assignResultValue (operand * oper)
2544 int size = AOP_SIZE (oper);
2548 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2549 if (hc08_aop_pass[offset]->type == AOP_REG)
2550 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2557 /*-----------------------------------------------------------------*/
2558 /* genIpush - genrate code for pushing this gets a little complex */
2559 /*-----------------------------------------------------------------*/
2561 genIpush (iCode * ic)
2563 int size, offset = 0;
2566 D(emitcode ("; genIpush",""));
2568 /* if this is not a parm push : ie. it is spill push
2569 and spill push is always done on the local stack */
2573 /* and the item is spilt then do nothing */
2574 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2577 aopOp (IC_LEFT (ic), ic, FALSE);
2578 size = AOP_SIZE (IC_LEFT (ic));
2580 /* push it on the stack */
2583 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2584 pushReg ( hc08_reg_a, TRUE);
2590 /* this is a paramter push: in this case we call
2591 the routine to find the call and save those
2592 registers that need to be saved */
2595 /* then do the push */
2596 aopOp (IC_LEFT (ic), ic, FALSE);
2599 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2600 size = AOP_SIZE (IC_LEFT (ic));
2603 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2604 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2606 if ((size==2) && hc08_reg_hx->isFree)
2608 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2609 pushReg (hc08_reg_hx, TRUE);
2616 // printf("loading %d\n", offset);
2617 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2618 // printf("pushing \n");
2619 pushReg (hc08_reg_a, TRUE);
2623 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2626 /*-----------------------------------------------------------------*/
2627 /* genIpop - recover the registers: can happen only for spilling */
2628 /*-----------------------------------------------------------------*/
2630 genIpop (iCode * ic)
2634 D(emitcode ("; genIpop",""));
2636 /* if the temp was not pushed then */
2637 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2640 aopOp (IC_LEFT (ic), ic, FALSE);
2641 size = AOP_SIZE (IC_LEFT (ic));
2645 pullReg (hc08_reg_a);
2646 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2648 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2652 /*-----------------------------------------------------------------*/
2653 /* genSend - gen code for SEND */
2654 /*-----------------------------------------------------------------*/
2655 static void genSend(set *sendSet)
2659 for (sic = setFirstItem (sendSet); sic;
2660 sic = setNextItem (sendSet)) {
2661 int size, offset = 0;
2662 aopOp (IC_LEFT (sic), sic, FALSE);
2663 size = AOP_SIZE (IC_LEFT (sic));
2668 transferAopAop( AOP (IC_LEFT (sic)), offset,
2669 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2673 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2677 /*-----------------------------------------------------------------*/
2678 /* genCall - generates a call statement */
2679 /*-----------------------------------------------------------------*/
2681 genCall (iCode * ic)
2684 // bool restoreBank = FALSE;
2685 // bool swapBanks = FALSE;
2687 D(emitcode("; genCall",""));
2689 dtype = operandType (IC_LEFT (ic));
2690 /* if send set is not empty the assign */
2693 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2694 genSend(reverseSet(_G.sendSet));
2696 genSend(_G.sendSet);
2702 /* if caller saves & we have not saved then */
2708 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2709 OP_SYMBOL (IC_LEFT (ic))->rname :
2710 OP_SYMBOL (IC_LEFT (ic))->name));
2713 /* if we need assign a result value */
2714 if ((IS_ITEMP (IC_RESULT (ic)) &&
2715 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2716 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2717 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2718 IS_TRUE_SYMOP (IC_RESULT (ic)))
2722 aopOp (IC_RESULT (ic), ic, FALSE);
2725 assignResultValue (IC_RESULT (ic));
2727 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2730 /* adjust the stack for parameters if
2734 pullNull (ic->parmBytes);
2737 /* if we had saved some registers then unsave them */
2738 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2739 unsaveRegisters (ic);
2743 /*-----------------------------------------------------------------*/
2744 /* -10l - generates a call by pointer statement */
2745 /*-----------------------------------------------------------------*/
2747 genPcall (iCode * ic)
2750 symbol *rlbl = newiTempLabel (NULL);
2751 symbol *tlbl = newiTempLabel (NULL);
2752 // bool restoreBank=FALSE;
2753 // bool swapBanks = FALSE;
2755 D(emitcode("; genPCall",""));
2757 /* if caller saves & we have not saved then */
2761 /* if we are calling a not _naked function that is not using
2762 the same register bank then we need to save the
2763 destination registers on the stack */
2764 dtype = operandType (IC_LEFT (ic))->next;
2766 /* now push the calling address */
2767 emitBranch ("bsr", tlbl);
2768 emitBranch ("bra", rlbl);
2771 /* Push the function's address */
2772 aopOp (IC_LEFT (ic), ic, FALSE);
2773 pushSide (IC_LEFT (ic), FPTRSIZE);
2774 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2776 /* if send set is not empty the assign */
2779 genSend(reverseSet(_G.sendSet));
2785 emitcode ("rts", "");
2790 /* if we need assign a result value */
2791 if ((IS_ITEMP (IC_RESULT (ic)) &&
2792 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2793 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2794 IS_TRUE_SYMOP (IC_RESULT (ic)))
2798 aopOp (IC_RESULT (ic), ic, FALSE);
2801 assignResultValue (IC_RESULT (ic));
2803 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2806 /* adjust the stack for parameters if
2810 pullNull (ic->parmBytes);
2813 /* if we hade saved some registers then
2815 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2816 unsaveRegisters (ic);
2819 /*-----------------------------------------------------------------*/
2820 /* resultRemat - result is rematerializable */
2821 /*-----------------------------------------------------------------*/
2823 resultRemat (iCode * ic)
2825 if (SKIP_IC (ic) || ic->op == IFX)
2828 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2830 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2831 if (sym->remat && !POINTER_SET (ic))
2838 #if defined(__BORLANDC__) || defined(_MSC_VER)
2839 #define STRCASECMP stricmp
2841 #define STRCASECMP strcasecmp
2844 /*-----------------------------------------------------------------*/
2845 /* inExcludeList - return 1 if the string is in exclude Reg list */
2846 /*-----------------------------------------------------------------*/
2848 regsCmp(void *p1, void *p2)
2850 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2854 inExcludeList (char *s)
2856 const char *p = setFirstItem(options.excludeRegsSet);
2858 if (p == NULL || STRCASECMP(p, "none") == 0)
2862 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2865 /*-----------------------------------------------------------------*/
2866 /* genFunction - generated code for function entry */
2867 /*-----------------------------------------------------------------*/
2869 genFunction (iCode * ic)
2873 int calleesaves_saved_register = -1;
2877 /* create the function header */
2878 emitcode (";", "-----------------------------------------");
2879 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2880 emitcode (";", "-----------------------------------------");
2882 emitcode ("", "%s:", sym->rname);
2883 ftype = operandType (IC_LEFT (ic));
2887 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2889 if (IFFUNC_ISNAKED(ftype))
2891 emitcode(";", "naked function: no prologue.");
2897 /* if this is an interrupt service routine then
2899 if (IFFUNC_ISISR (sym->type))
2902 if (!inExcludeList ("h"))
2903 pushReg (hc08_reg_h, FALSE);
2907 /* if callee-save to be used for this function
2908 then save the registers being used in this function */
2909 if (IFFUNC_CALLEESAVES(sym->type))
2913 /* if any registers used */
2916 /* save the registers used */
2917 for (i = 0; i < sym->regsUsed->size; i++)
2919 if (bitVectBitValue (sym->regsUsed, i))
2921 /* remember one saved register for later usage */
2922 if (calleesaves_saved_register < 0)
2923 calleesaves_saved_register = i;
2924 pushReg (hc08_regWithIdx (i), FALSE);
2932 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2937 /* adjust the stack for the function */
2943 // werror (W_STACK_OVERFLOW, sym->name);
2947 _G.stackOfs = sym->stack;
2950 /* if critical function then turn interrupts off */
2951 if (IFFUNC_ISCRITICAL (ftype))
2953 if (IFFUNC_ARGS (ftype))
2955 /* Function was passed parameters, so make sure A is preserved */
2956 pushReg (hc08_reg_a, FALSE);
2957 pushReg (hc08_reg_a, FALSE);
2958 emitcode ("tpa", "");
2959 emitcode ("sta", "2,s");
2960 emitcode ("sei", "");
2961 pullReg (hc08_reg_a);
2965 /* No passed parameters, so A can be freely modified */
2966 emitcode ("tpa", "");
2967 pushReg (hc08_reg_a, TRUE);
2968 emitcode ("sei", "");
2974 /*-----------------------------------------------------------------*/
2975 /* genEndFunction - generates epilogue for functions */
2976 /*-----------------------------------------------------------------*/
2978 genEndFunction (iCode * ic)
2980 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2982 if (IFFUNC_ISNAKED(sym->type))
2984 emitcode(";", "naked function: no epilogue.");
2985 if (options.debug && currFunc)
2986 debugFile->writeEndFunction (currFunc, ic, 0);
2990 if (IFFUNC_ISCRITICAL (sym->type))
2992 if (!IS_VOID(sym->type->next))
2994 /* Function has return value, so make sure A is preserved */
2995 pushReg (hc08_reg_a, FALSE);
2996 emitcode ("lda", "2,s");
2997 emitcode ("tap", "");
2998 pullReg (hc08_reg_a);
3003 /* Function returns void, so A can be freely modified */
3004 pullReg (hc08_reg_a);
3005 emitcode ("tap", "");
3009 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3015 _G.stackPushes += sym->stack;
3016 adjustStack (sym->stack);
3020 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3024 if (IFFUNC_ISISR (sym->type))
3027 if (!inExcludeList ("h"))
3028 pullReg (hc08_reg_h);
3031 /* if debug then send end of function */
3032 if (options.debug && currFunc)
3034 debugFile->writeEndFunction (currFunc, ic, 1);
3037 emitcode ("rti", "");
3041 if (IFFUNC_CALLEESAVES(sym->type))
3045 /* if any registers used */
3048 /* save the registers used */
3049 for (i = sym->regsUsed->size; i >= 0; i--)
3051 if (bitVectBitValue (sym->regsUsed, i) ||
3052 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3053 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3059 /* if debug then send end of function */
3060 if (options.debug && currFunc)
3062 debugFile->writeEndFunction (currFunc, ic, 1);
3065 emitcode ("rts", "");
3070 /*-----------------------------------------------------------------*/
3071 /* genRet - generate code for return statement */
3072 /*-----------------------------------------------------------------*/
3076 int size, offset = 0;
3079 D(emitcode ("; genRet",""));
3081 /* if we have no return value then
3082 just generate the "ret" */
3086 /* we have something to return then
3087 move the return value into place */
3088 aopOp (IC_LEFT (ic), ic, FALSE);
3089 size = AOP_SIZE (IC_LEFT (ic));
3095 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3102 /* 4 byte return: store value in the global return variable */
3106 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3107 STA (fReturn2[offset--], FALSE);
3108 hc08_freeReg (hc08_reg_a);
3112 /* 2 byte return: store value in x:a */
3113 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3114 hc08_freeReg (hc08_reg_xa);
3117 /* 1 byte return: store value in a */
3118 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3119 hc08_freeReg (hc08_reg_a);
3124 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3127 /* generate a jump to the return label
3128 if the next is not the return statement */
3129 if (!(ic->next && ic->next->op == LABEL &&
3130 IC_LABEL (ic->next) == returnLabel))
3132 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3136 /*-----------------------------------------------------------------*/
3137 /* genLabel - generates a label */
3138 /*-----------------------------------------------------------------*/
3140 genLabel (iCode * ic)
3145 /* For the high level labels we cannot depend on any */
3146 /* register's contents. Amnesia time. */
3147 for (i=A_IDX;i<=XA_IDX;i++)
3149 reg = hc08_regWithIdx(i);
3154 /* special case never generate */
3155 if (IC_LABEL (ic) == entryLabel)
3158 debugFile->writeLabel(IC_LABEL (ic), ic);
3160 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3164 /*-----------------------------------------------------------------*/
3165 /* genGoto - generates a jmp */
3166 /*-----------------------------------------------------------------*/
3168 genGoto (iCode * ic)
3170 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3174 /*-----------------------------------------------------------------*/
3175 /* findLabelBackwards: walks back through the iCode chain looking */
3176 /* for the given label. Returns number of iCode instructions */
3177 /* between that label and given ic. */
3178 /* Returns zero if label not found. */
3179 /*-----------------------------------------------------------------*/
3181 findLabelBackwards (iCode * ic, int key)
3190 /* If we have any pushes or pops, we cannot predict the distance.
3191 I don't like this at all, this should be dealt with in the
3193 if (ic->op == IPUSH || ic->op == IPOP) {
3197 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3207 /*-----------------------------------------------------------------*/
3208 /* genPlusIncr :- does addition with increment if possible */
3209 /*-----------------------------------------------------------------*/
3211 genPlusIncr (iCode * ic)
3219 unsigned int size = getDataSize (IC_RESULT (ic));
3221 symbol *tlbl = NULL;
3223 left = IC_LEFT (ic);
3224 result = IC_RESULT (ic);
3226 /* will try to generate an increment */
3227 /* if the right side is not a literal
3229 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3232 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3234 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3236 if ((IS_AOP_HX (AOP (left)) ||
3237 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3239 && (icount>=-128) && (icount<=127) && (size==2))
3241 if (!IS_AOP_HX (AOP (left)))
3243 needpulx = pushRegIfUsed (hc08_reg_x);
3244 needpulh = pushRegIfUsed (hc08_reg_h);
3251 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3252 emitcode ("aix","#%d", icount);
3253 hc08_dirtyReg (hc08_reg_hx, FALSE);
3254 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3255 pullOrFreeReg (hc08_reg_h, needpulh);
3256 pullOrFreeReg (hc08_reg_x, needpulx);
3260 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3261 sameRegs (AOP (left), AOP (result))));
3263 if ((icount > 255) || (icount<0))
3266 if (!sameRegs (AOP (left), AOP (result)))
3269 D(emitcode ("; genPlusIncr",""));
3272 tlbl = newiTempLabel (NULL);
3277 rmwWithAop ("inc", AOP (result), 0);
3279 emitBranch ("bne", tlbl);
3283 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3284 needpula = pushRegIfUsed (hc08_reg_a);
3287 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3288 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3289 hc08_useReg (hc08_reg_a);
3290 storeRegToAop (hc08_reg_a, AOP (result), 0);
3291 hc08_freeReg (hc08_reg_a);
3293 emitBranch ("bcc", tlbl);
3295 for (offset=1; offset<size; offset++)
3297 rmwWithAop ("inc", AOP (result), offset);
3298 if ((offset+1)<size)
3299 emitBranch ("bne", tlbl);
3305 pullOrFreeReg (hc08_reg_a, needpula);
3312 /*-----------------------------------------------------------------*/
3313 /* genPlus - generates code for addition */
3314 /*-----------------------------------------------------------------*/
3316 genPlus (iCode * ic)
3318 int size, offset = 0;
3320 asmop *leftOp, *rightOp;
3322 /* special cases :- */
3324 D(emitcode ("; genPlus",""));
3326 aopOp (IC_LEFT (ic), ic, FALSE);
3327 aopOp (IC_RIGHT (ic), ic, FALSE);
3328 aopOp (IC_RESULT (ic), ic, TRUE);
3330 /* we want registers on the left and literals on the right */
3331 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3332 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3334 operand *t = IC_RIGHT (ic);
3335 IC_RIGHT (ic) = IC_LEFT (ic);
3340 /* if I can do an increment instead
3341 of add then GOOD for ME */
3342 if (genPlusIncr (ic) == TRUE)
3345 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3346 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3347 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3349 size = getDataSize (IC_RESULT (ic));
3351 leftOp = AOP(IC_LEFT(ic));
3352 rightOp = AOP(IC_RIGHT(ic));
3358 loadRegFromAop (hc08_reg_a, leftOp, offset);
3359 accopWithAop(add, rightOp, offset);
3360 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3361 hc08_freeReg (hc08_reg_a);
3362 add = "adc"; /* further adds must propagate carry */
3366 // adjustArithmeticResult (ic);
3369 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3370 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3371 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3374 /*-----------------------------------------------------------------*/
3375 /* genMinusDec :- does subtraction with deccrement if possible */
3376 /*-----------------------------------------------------------------*/
3378 genMinusDec (iCode * ic)
3380 unsigned int icount;
3385 unsigned int size = getDataSize (IC_RESULT (ic));
3389 left = IC_LEFT (ic);
3390 result = IC_RESULT (ic);
3392 /* will try to generate an increment */
3393 /* if the right side is not a literal
3395 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3398 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3400 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3401 && (icount>=-127) && (icount<=128) && (size==2))
3403 if (!IS_AOP_HX (AOP (left)))
3405 needpulx = pushRegIfUsed (hc08_reg_x);
3406 needpulh = pushRegIfUsed (hc08_reg_h);
3413 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3414 emitcode ("aix","#%d", -icount);
3415 hc08_dirtyReg (hc08_reg_hx, FALSE);
3416 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3417 pullOrFreeReg (hc08_reg_h, needpulh);
3418 pullOrFreeReg (hc08_reg_x, needpulx);
3422 if ((icount > 1) || (icount<0))
3425 if (!sameRegs (AOP (left), AOP (result)))
3431 D(emitcode ("; genMinusDec",""));
3433 rmwWithAop ("dec", AOP (result), 0);
3438 /*-----------------------------------------------------------------*/
3439 /* addSign - complete with sign */
3440 /*-----------------------------------------------------------------*/
3442 addSign (operand * result, int offset, int sign)
3444 int size = (getDataSize (result) - offset);
3449 emitcode ("rola", "");
3450 emitcode ("clra", "");
3451 emitcode ("sbc", zero);
3453 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3457 storeConstToAop (zero, AOP (result), offset++);
3462 /*-----------------------------------------------------------------*/
3463 /* genMinus - generates code for subtraction */
3464 /*-----------------------------------------------------------------*/
3466 genMinus (iCode * ic)
3469 int size, offset = 0;
3471 asmop *leftOp, *rightOp;
3473 D(emitcode ("; genMinus",""));
3475 aopOp (IC_LEFT (ic), ic, FALSE);
3476 aopOp (IC_RIGHT (ic), ic, FALSE);
3477 aopOp (IC_RESULT (ic), ic, TRUE);
3479 /* special cases :- */
3480 /* if I can do an decrement instead
3481 of subtract then GOOD for ME */
3482 if (genMinusDec (ic) == TRUE)
3485 size = getDataSize (IC_RESULT (ic));
3488 leftOp = AOP(IC_LEFT(ic));
3489 rightOp = AOP(IC_RIGHT(ic));
3495 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3496 accopWithAop(sub, rightOp, offset);
3497 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3502 // adjustArithmeticResult (ic);
3505 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3506 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3507 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3512 /*-----------------------------------------------------------------*/
3513 /* genMultOneByte : 8*8=8/16 bit multiplication */
3514 /*-----------------------------------------------------------------*/
3516 genMultOneByte (operand * left,
3520 /* sym_link *opetype = operandType (result); */
3521 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3522 int size=AOP_SIZE(result);
3523 bool negLiteral = FALSE;
3524 bool lUnsigned, rUnsigned;
3526 D(emitcode ("; genMultOneByte",""));
3528 if (size<1 || size>2) {
3529 // this should never happen
3530 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3531 AOP_SIZE(result), __FILE__, lineno);
3535 /* (if two literals: the value is computed before) */
3536 /* if one literal, literal on the right */
3537 if (AOP_TYPE (left) == AOP_LIT)
3543 /* if an operand is in A, make sure it is on the left */
3544 if (IS_AOP_A (AOP (right)))
3551 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3552 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3554 /* lUnsigned rUnsigned negLiteral negate case */
3555 /* false false false odd 3 */
3556 /* false false true even 3 */
3557 /* false true false odd 3 */
3558 /* false true true impossible */
3559 /* true false false odd 3 */
3560 /* true false true always 2 */
3561 /* true true false never 1 */
3562 /* true true true impossible */
3566 || (lUnsigned && rUnsigned))
3568 // just an unsigned 8*8=8/16 multiply
3569 //D(emitcode (";","unsigned"));
3571 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3572 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3573 emitcode ("mul", "");
3574 hc08_dirtyReg (hc08_reg_xa, FALSE);
3575 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3576 hc08_freeReg (hc08_reg_xa);
3581 // we have to do a signed multiply
3584 /* left unsigned, right signed literal -- literal determines sign handling */
3585 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3587 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3589 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3591 emitcode ("ldx", "#0x%02x", -val);
3593 emitcode ("ldx", "#0x%02x", val);
3595 emitcode ("mul", "");
3599 rmwWithReg ("neg", hc08_reg_a);
3600 tlbl4 = newiTempLabel (NULL);
3601 emitBranch ("bcc", tlbl4);
3602 rmwWithReg ("inc", hc08_reg_x);
3604 rmwWithReg ("neg", hc08_reg_x);
3607 hc08_dirtyReg (hc08_reg_xa, FALSE);
3608 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3609 hc08_freeReg (hc08_reg_xa);
3616 emitcode ("clr", "1,s");
3618 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3621 tlbl1 = newiTempLabel (NULL);
3622 emitcode ("tsta","");
3623 emitBranch ("bpl", tlbl1);
3624 emitcode ("inc", "1,s");
3625 rmwWithReg ("neg", hc08_reg_a);
3629 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3631 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3632 /* AND literal negative */
3634 emitcode ("ldx", "#0x%02x", -val);
3637 emitcode ("ldx", "#0x%02x", val);
3639 hc08_useReg (hc08_reg_x);
3643 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3646 tlbl2 = newiTempLabel (NULL);
3647 emitcode ("tstx", "");
3648 emitBranch ("bpl", tlbl2);
3649 emitcode ("inc", "1,s");
3650 rmwWithReg ("neg", hc08_reg_x);
3655 emitcode ("mul", "");
3656 hc08_dirtyReg (hc08_reg_xa, FALSE);
3658 tlbl3 = newiTempLabel (NULL);
3659 emitcode ("dec", "1,s");
3660 if (!lUnsigned && !rUnsigned && negLiteral)
3661 emitBranch ("beq", tlbl3);
3663 emitBranch ("bne", tlbl3);
3665 rmwWithReg ("neg", hc08_reg_a);
3666 tlbl4 = newiTempLabel (NULL);
3667 emitBranch ("bcc", tlbl4);
3668 rmwWithReg ("inc", hc08_reg_x);
3670 rmwWithReg ("neg", hc08_reg_x);
3674 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3675 hc08_freeReg (hc08_reg_xa);
3679 /*-----------------------------------------------------------------*/
3680 /* genMult - generates code for multiplication */
3681 /*-----------------------------------------------------------------*/
3683 genMult (iCode * ic)
3685 operand *left = IC_LEFT (ic);
3686 operand *right = IC_RIGHT (ic);
3687 operand *result = IC_RESULT (ic);
3689 D(emitcode ("; genMult",""));
3691 /* assign the amsops */
3692 aopOp (left, ic, FALSE);
3693 aopOp (right, ic, FALSE);
3694 aopOp (result, ic, TRUE);
3696 /* special cases first */
3697 /* if both are of size == 1 */
3698 // if (getSize(operandType(left)) == 1 &&
3699 // getSize(operandType(right)) == 1)
3700 if (AOP_SIZE (left) == 1 &&
3701 AOP_SIZE (right) == 1)
3703 genMultOneByte (left, right, result);
3707 /* should have been converted to function call */
3708 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3709 getSize(OP_SYMBOL(right)->type));
3710 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3715 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3716 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3717 freeAsmop (result, NULL, ic, TRUE);
3720 /*-----------------------------------------------------------------*/
3721 /* genDivOneByte : 8 bit division */
3722 /*-----------------------------------------------------------------*/
3724 genDivOneByte (operand * left,
3728 symbol *tlbl1, *tlbl2, *tlbl3;
3731 bool lUnsigned, rUnsigned;
3732 bool runtimeSign, compiletimeSign;
3734 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3735 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3737 D(emitcode ("; genDivOneByte",""));
3739 size = AOP_SIZE (result);
3740 /* signed or unsigned */
3741 if (lUnsigned && rUnsigned)
3743 /* unsigned is easy */
3744 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3745 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3746 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3747 emitcode ("div", "");
3748 hc08_dirtyReg (hc08_reg_a, FALSE);
3749 hc08_dirtyReg (hc08_reg_h, FALSE);
3750 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3751 hc08_freeReg (hc08_reg_a);
3752 hc08_freeReg (hc08_reg_x);
3753 hc08_freeReg (hc08_reg_h);
3757 /* signed is a little bit more difficult */
3759 /* now sign adjust for both left & right */
3761 /* let's see what's needed: */
3762 /* apply negative sign during runtime */
3763 runtimeSign = FALSE;
3764 /* negative sign from literals */
3765 compiletimeSign = FALSE;
3769 if (AOP_TYPE(left) == AOP_LIT)
3771 /* signed literal */
3772 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3774 compiletimeSign = TRUE;
3777 /* signed but not literal */
3783 if (AOP_TYPE(right) == AOP_LIT)
3785 /* signed literal */
3786 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3788 compiletimeSign ^= TRUE;
3791 /* signed but not literal */
3795 /* initialize the runtime sign */
3798 if (compiletimeSign)
3799 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3801 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3802 pushReg (hc08_reg_x, TRUE);
3805 /* save the signs of the operands */
3806 if (AOP_TYPE(right) == AOP_LIT)
3808 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3810 if (!rUnsigned && val < 0)
3811 emitcode ("ldx", "#0x%02x", -val);
3813 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3815 else /* ! literal */
3817 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3820 tlbl1 = newiTempLabel (NULL);
3821 emitcode ("tstx", "");
3822 emitBranch ("bpl", tlbl1);
3823 emitcode ("inc", "1,s");
3824 rmwWithReg ("neg", hc08_reg_x);
3829 if (AOP_TYPE(left) == AOP_LIT)
3831 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3833 if (!lUnsigned && val < 0)
3834 emitcode ("lda", "#0x%02x", -val);
3836 emitcode ("lda", "#0x%02x", (unsigned char) val);
3838 else /* ! literal */
3840 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3843 tlbl2 = newiTempLabel (NULL);
3844 emitcode ("tsta", "");
3845 emitBranch ("bpl", tlbl2);
3846 emitcode ("inc", "1,s");
3847 rmwWithReg ("neg", hc08_reg_a);
3852 loadRegFromConst (hc08_reg_h, zero);
3853 emitcode ("div", "");
3854 hc08_dirtyReg (hc08_reg_x, FALSE);
3855 hc08_dirtyReg (hc08_reg_a, FALSE);
3856 hc08_dirtyReg (hc08_reg_h, FALSE);
3858 if (runtimeSign || compiletimeSign)
3860 tlbl3 = newiTempLabel (NULL);
3863 pullReg (hc08_reg_x);
3864 rmwWithReg ("lsr", hc08_reg_x);
3865 rmwWithReg ("ror", hc08_reg_x);
3866 emitBranch ("bpl", tlbl3);
3869 rmwWithReg ("neg", hc08_reg_a);
3873 storeRegToAop (hc08_reg_a, AOP (result), 0);
3877 /* msb is 0x00 or 0xff depending on the sign */
3880 rmwWithReg ("lsl", hc08_reg_x);
3881 emitcode ("clra", "");
3882 emitcode ("sbc", "#0");
3884 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3886 else /* compiletimeSign */
3888 storeConstToAop ("#0xff", AOP (result), ++offset);
3893 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3896 hc08_freeReg (hc08_reg_a);
3897 hc08_freeReg (hc08_reg_x);
3898 hc08_freeReg (hc08_reg_h);
3901 /*-----------------------------------------------------------------*/
3902 /* genDiv - generates code for division */
3903 /*-----------------------------------------------------------------*/
3907 operand *left = IC_LEFT (ic);
3908 operand *right = IC_RIGHT (ic);
3909 operand *result = IC_RESULT (ic);
3911 D(emitcode ("; genDiv",""));
3913 /* assign the amsops */
3914 aopOp (left, ic, FALSE);
3915 aopOp (right, ic, FALSE);
3916 aopOp (result, ic, TRUE);
3918 /* special cases first */
3919 /* if both are of size == 1 */
3920 if (AOP_SIZE (left) <= 2 &&
3921 AOP_SIZE (right) == 1)
3923 genDivOneByte (left, right, result);
3927 /* should have been converted to function call */
3930 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3931 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3932 freeAsmop (result, NULL, ic, TRUE);
3935 /*-----------------------------------------------------------------*/
3936 /* genModOneByte : 8 bit modulus */
3937 /*-----------------------------------------------------------------*/
3939 genModOneByte (operand * left,
3943 symbol *tlbl1, *tlbl2, *tlbl3;
3946 bool lUnsigned, rUnsigned;
3947 bool runtimeSign, compiletimeSign;
3949 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3950 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3952 D(emitcode ("; genModOneByte",""));
3954 size = AOP_SIZE (result);
3956 if (lUnsigned && rUnsigned)
3958 /* unsigned is easy */
3959 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3960 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3961 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3962 emitcode ("div", "");
3963 hc08_dirtyReg (hc08_reg_a, FALSE);
3964 hc08_dirtyReg (hc08_reg_h, FALSE);
3965 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3966 hc08_freeReg (hc08_reg_a);
3967 hc08_freeReg (hc08_reg_x);
3968 hc08_freeReg (hc08_reg_h);
3972 /* signed is a little bit more difficult */
3974 if (AOP_TYPE(right) == AOP_LIT)
3976 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3978 if (!rUnsigned && val < 0)
3979 emitcode ("ldx", "#0x%02x", -val);
3981 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3983 else /* ! literal */
3985 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3988 tlbl1 = newiTempLabel (NULL);
3989 emitcode ("tstx", "");
3990 emitBranch ("bpl", tlbl1);
3991 rmwWithReg ("neg", hc08_reg_x);
3996 /* let's see what's needed: */
3997 /* apply negative sign during runtime */
3998 runtimeSign = FALSE;
3999 /* negative sign from literals */
4000 compiletimeSign = FALSE;
4002 /* sign adjust left side */
4003 if (AOP_TYPE(left) == AOP_LIT)
4005 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4007 if (!lUnsigned && val < 0)
4009 compiletimeSign = TRUE; /* set sign flag */
4010 emitcode ("lda", "#0x%02x", -val);
4013 emitcode ("lda", "#0x%02x", (unsigned char) val);
4015 else /* ! literal */
4018 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4023 emitcode ("clr", "1,s");
4025 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4026 tlbl2 = newiTempLabel (NULL);
4027 emitcode ("tsta", "");
4028 emitBranch ("bpl", tlbl2);
4029 emitcode ("inc", "1,s");
4030 rmwWithReg ("neg", hc08_reg_a);
4035 loadRegFromConst (hc08_reg_h, zero);
4036 emitcode ("div", "");
4037 hc08_dirtyReg (hc08_reg_x, FALSE);
4038 hc08_dirtyReg (hc08_reg_a, FALSE);
4039 hc08_dirtyReg (hc08_reg_h, FALSE);
4041 if (runtimeSign || compiletimeSign)
4043 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4044 tlbl3 = newiTempLabel (NULL);
4047 pullReg (hc08_reg_x);
4048 rmwWithReg ("lsr", hc08_reg_x);
4049 rmwWithReg ("ror", hc08_reg_x);
4050 emitBranch ("bpl", tlbl3);
4053 rmwWithReg ("neg", hc08_reg_a);
4057 storeRegToAop (hc08_reg_a, AOP (result), 0);
4061 /* msb is 0x00 or 0xff depending on the sign */
4064 rmwWithReg ("lsl", hc08_reg_x);
4065 emitcode ("clra", "");
4066 emitcode ("sbc", "#0");
4068 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4070 else /* compiletimeSign */
4072 storeConstToAop ("#0xff", AOP (result), ++offset);
4077 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4080 hc08_freeReg (hc08_reg_a);
4081 hc08_freeReg (hc08_reg_x);
4082 hc08_freeReg (hc08_reg_h);
4085 /*-----------------------------------------------------------------*/
4086 /* genMod - generates code for division */
4087 /*-----------------------------------------------------------------*/
4091 operand *left = IC_LEFT (ic);
4092 operand *right = IC_RIGHT (ic);
4093 operand *result = IC_RESULT (ic);
4095 D(emitcode ("; genMod",""));
4097 /* assign the amsops */
4098 aopOp (left, ic, FALSE);
4099 aopOp (right, ic, FALSE);
4100 aopOp (result, ic, TRUE);
4102 /* special cases first */
4103 /* if both are of size == 1 */
4104 if (AOP_SIZE (left) <= 2 &&
4105 AOP_SIZE (right) == 1)
4107 genModOneByte (left, right, result);
4111 /* should have been converted to function call */
4115 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4116 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4117 freeAsmop (result, NULL, ic, TRUE);
4120 /*-----------------------------------------------------------------*/
4121 /* genIfxJump :- will create a jump depending on the ifx */
4122 /*-----------------------------------------------------------------*/
4124 genIfxJump (iCode * ic, char *jval)
4127 symbol *tlbl = newiTempLabel (NULL);
4130 D(emitcode ("; genIfxJump",""));
4132 /* if true label then we jump if condition
4136 jlbl = IC_TRUE (ic);
4137 if (!strcmp (jval, "a"))
4139 else if (!strcmp (jval, "c"))
4146 /* false label is present */
4147 jlbl = IC_FALSE (ic);
4148 if (!strcmp (jval, "a"))
4150 else if (!strcmp (jval, "c"))
4155 emitBranch (inst, tlbl);
4156 emitBranch ("jmp", jlbl);
4159 /* mark the icode as generated */
4163 /*-----------------------------------------------------------------*/
4164 /* genCmp :- greater or less than comparison */
4165 /*-----------------------------------------------------------------*/
4167 genCmp (operand * left, operand * right,
4168 operand * result, iCode * ifx, int sign, iCode *ic)
4170 int size, offset = 0;
4171 unsigned long lit = 0L;
4173 bool needpula = FALSE;
4175 D(emitcode ("; genCmp",""));
4177 /* subtract right from left if at the
4178 end the carry flag is set then we know that
4179 left is greater than right */
4180 size = max (AOP_SIZE (left), AOP_SIZE (right));
4182 if (AOP_TYPE (right) == AOP_LIT)
4184 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4185 /* optimize if(x < 0) or if(x >= 0) */
4194 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
4195 emitcode ("rola", "");
4196 hc08_useReg (hc08_reg_a);
4204 && ((AOP_TYPE (right) == AOP_LIT) ||
4205 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4206 && hc08_reg_hx->isFree)
4208 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4209 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4210 hc08_freeReg (hc08_reg_hx);
4221 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4222 accopWithAop (sub, AOP (right), offset);
4223 hc08_freeReg (hc08_reg_a);
4229 freeAsmop (right, NULL, ic, TRUE);
4230 freeAsmop (left, NULL, ic, TRUE);
4231 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4237 /* if the result is used in the next
4238 ifx conditional branch then generate
4239 code a little differently */
4242 pullOrFreeReg(hc08_reg_a,needpula);
4243 genIfxJump (ifx, sign ? "s" : "c");
4250 pullOrFreeReg(hc08_reg_a,needpula);
4254 /*-----------------------------------------------------------------*/
4255 /* genCmpGt :- greater than comparison */
4256 /*-----------------------------------------------------------------*/
4258 genCmpGt (iCode * ic, iCode * ifx)
4260 operand *left, *right, *result;
4261 sym_link *letype, *retype;
4264 D(emitcode ("; genCmpGt",""));
4266 result = IC_RESULT (ic);
4267 left = IC_LEFT (ic);
4268 right = IC_RIGHT (ic);
4270 letype = getSpec (operandType (left));
4271 retype = getSpec (operandType (right));
4272 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4273 /* assign the amsops */
4274 aopOp (left, ic, FALSE);
4275 aopOp (right, ic, FALSE);
4276 aopOp (result, ic, TRUE);
4278 genCmp (right, left, result, ifx, sign,ic);
4280 freeAsmop (result, NULL, ic, TRUE);
4283 /*-----------------------------------------------------------------*/
4284 /* genCmpLt - less than comparisons */
4285 /*-----------------------------------------------------------------*/
4287 genCmpLt (iCode * ic, iCode * ifx)
4289 operand *left, *right, *result;
4290 sym_link *letype, *retype;
4293 D(emitcode ("; genCmpLt",""));
4295 result = IC_RESULT (ic);
4296 left = IC_LEFT (ic);
4297 right = IC_RIGHT (ic);
4299 letype = getSpec (operandType (left));
4300 retype = getSpec (operandType (right));
4301 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4303 /* assign the amsops */
4304 aopOp (left, ic, FALSE);
4305 aopOp (right, ic, FALSE);
4306 aopOp (result, ic, TRUE);
4308 genCmp (left, right, result, ifx, sign,ic);
4310 freeAsmop (result, NULL, ic, TRUE);
4313 /*-----------------------------------------------------------------*/
4314 /* - compare and branch if not equal */
4315 /*-----------------------------------------------------------------*/
4317 gencbneshort (operand * left, operand * right, symbol * lbl)
4319 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4321 unsigned long lit = 0L;
4323 /* if the left side is a literal or
4324 if the right is in a pointer register and left
4326 if (AOP_TYPE (left) == AOP_LIT)
4332 if (AOP_TYPE (right) == AOP_LIT)
4333 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4337 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4338 accopWithAop ("cmp", AOP (right), offset);
4339 hc08_useReg (hc08_reg_a);
4340 hc08_freeReg (hc08_reg_a);
4341 emitBranch ("bne", lbl);
4347 /*-----------------------------------------------------------------*/
4348 /* gencjne - compare and jump if not equal */
4349 /*-----------------------------------------------------------------*/
4351 gencjne (operand * left, operand * right, symbol * lbl)
4353 symbol *tlbl = newiTempLabel (NULL);
4355 gencbneshort (left, right, lbl);
4357 loadRegFromConst (hc08_reg_a, one);
4358 emitBranch ("bra", tlbl);
4360 loadRegFromConst (hc08_reg_a, zero);
4363 hc08_useReg(hc08_reg_a);
4364 hc08_freeReg(hc08_reg_a);
4367 /*-----------------------------------------------------------------*/
4368 /* genCmpEq - generates code for equal to */
4369 /*-----------------------------------------------------------------*/
4371 genCmpEq (iCode * ic, iCode * ifx)
4373 operand *left, *right, *result;
4375 D(emitcode ("; genCmpEq",""));
4377 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4378 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4379 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4381 /* if literal, literal on the right or
4382 if the right is in a pointer register and left
4384 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4386 operand *t = IC_RIGHT (ic);
4387 IC_RIGHT (ic) = IC_LEFT (ic);
4391 if (ifx && !AOP_SIZE (result))
4394 tlbl = newiTempLabel (NULL);
4395 gencbneshort (left, right, tlbl);
4398 emitBranch ("jmp", IC_TRUE (ifx));
4403 symbol *lbl = newiTempLabel (NULL);
4404 emitBranch ("bra", lbl);
4406 emitBranch ("jmp", IC_FALSE (ifx));
4410 /* mark the icode as generated */
4415 gencjne (left, right, newiTempLabel (NULL));
4416 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4418 storeRegToAop (hc08_reg_a, AOP (result), 0);
4423 genIfxJump (ifx, "a");
4426 /* if the result is used in an arithmetic operation
4427 then put the result in place */
4428 if (AOP_TYPE (result) != AOP_CRY)
4432 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4433 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4434 freeAsmop (result, NULL, ic, TRUE);
4437 /*-----------------------------------------------------------------*/
4438 /* ifxForOp - returns the icode containing the ifx for operand */
4439 /*-----------------------------------------------------------------*/
4441 ifxForOp (operand * op, iCode * ic)
4443 /* if true symbol then needs to be assigned */
4444 if (IS_TRUE_SYMOP (op))
4447 /* if this has register type condition and
4448 the next instruction is ifx with the same operand
4449 and live to of the operand is upto the ifx only then */
4451 ic->next->op == IFX &&
4452 IC_COND (ic->next)->key == op->key &&
4453 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4460 genPointerGetSetOfs (iCode *ic)
4462 iCode *lic = ic->next;
4468 /* Make sure we have a next iCode */
4469 D(emitcode("","; checking lic"));
4473 /* Make sure the result of the addition is an iCode */
4474 D(emitcode("","; checking IS_ITEMP"));
4475 if (!IS_ITEMP (IC_RESULT (ic)))
4478 /* Make sure the next iCode is a pointer set or get */
4479 pset = POINTER_SET(lic);
4480 pget = POINTER_GET(lic);
4481 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4485 /* Make sure this is the only use of the pointer */
4486 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4489 D(emitcode("", "; checking pset operandsEqu"));
4490 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4493 D(emitcode("", "; checking pget operandsEqu"));
4494 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4497 D(emitcode("", "; checking IS_SYMOP"));
4498 if (!IS_SYMOP (IC_LEFT (ic)))
4501 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4502 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4505 sym = OP_SYMBOL (IC_LEFT (ic));
4507 D(emitcode("", "; checking remat"));
4514 D(emitcode ("; genPointerGetOfs",""));
4515 aopOp (IC_LEFT(ic), ic, FALSE);
4516 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4517 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4519 aopOp (IC_RIGHT(ic), ic, FALSE);
4520 aopOp (IC_RESULT(lic), lic, FALSE);
4522 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4524 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4526 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4527 loadRegFromConst (hc08_reg_h, zero);
4531 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4532 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4533 emitcode ("rola","");
4534 emitcode ("clra","");
4535 emitcode ("sbc", "#0");
4536 hc08_useReg (hc08_reg_a);
4537 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4541 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4542 size = AOP_SIZE (IC_RESULT(lic));
4543 derefaop->size = size;
4548 emitcode ("lda", "%s,x",
4549 aopAdrStr (derefaop, offset, TRUE));
4550 hc08_useReg (hc08_reg_a);
4551 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4552 hc08_freeReg (hc08_reg_a);
4556 hc08_freeReg (hc08_reg_hx);
4558 freeAsmop (NULL, derefaop, ic, TRUE);
4559 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4560 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4567 D(emitcode ("; genPointerSetOfs",""));
4568 aopOp (IC_LEFT(ic), ic, FALSE);
4569 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4570 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4572 aopOp (IC_RIGHT(ic), ic, FALSE);
4573 aopOp (IC_RIGHT(lic), lic, FALSE);
4575 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4577 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4579 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4580 loadRegFromConst (hc08_reg_h, zero);
4584 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4585 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4586 emitcode ("rola","");
4587 emitcode ("clra","");
4588 emitcode ("sbc", "#0");
4589 hc08_useReg (hc08_reg_a);
4590 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4594 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4595 size = AOP_SIZE (IC_RIGHT(lic));
4596 derefaop->size = size;
4601 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4602 emitcode ("sta", "%s,x",
4603 aopAdrStr (derefaop, offset, TRUE));
4604 hc08_freeReg (hc08_reg_a);
4609 hc08_freeReg (hc08_reg_hx);
4611 freeAsmop (NULL, derefaop, ic, TRUE);
4612 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4613 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4622 /*-----------------------------------------------------------------*/
4623 /* hasInc - operand is incremented before any other use */
4624 /*-----------------------------------------------------------------*/
4626 hasInc (operand *op, iCode *ic,int osize)
4628 sym_link *type = operandType(op);
4629 sym_link *retype = getSpec (type);
4630 iCode *lic = ic->next;
4633 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4634 if (!IS_SYMOP(op)) return NULL;
4636 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4637 if (IS_AGGREGATE(type->next)) return NULL;
4638 if (osize != (isize = getSize(type->next))) return NULL;
4641 /* if operand of the form op = op + <sizeof *op> */
4642 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4643 isOperandEqual(IC_RESULT(lic),op) &&
4644 isOperandLiteral(IC_RIGHT(lic)) &&
4645 operandLitValue(IC_RIGHT(lic)) == isize) {
4648 /* if the operand used or deffed */
4649 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4652 /* if GOTO or IFX */
4653 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4659 /*-----------------------------------------------------------------*/
4660 /* genAndOp - for && operation */
4661 /*-----------------------------------------------------------------*/
4663 genAndOp (iCode * ic)
4665 operand *left, *right, *result;
4666 symbol *tlbl, *tlbl0;
4668 D(emitcode ("; genAndOp",""));
4670 /* note here that && operations that are in an
4671 if statement are taken away by backPatchLabels
4672 only those used in arthmetic operations remain */
4673 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4674 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4675 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4677 tlbl = newiTempLabel (NULL);
4678 tlbl0 = newiTempLabel (NULL);
4680 asmopToBool (AOP (left), FALSE);
4681 emitBranch ("beq", tlbl0);
4682 asmopToBool (AOP (right), FALSE);
4683 emitBranch ("beq", tlbl0);
4684 loadRegFromConst (hc08_reg_a,one);
4685 emitBranch ("bra", tlbl);
4687 loadRegFromConst (hc08_reg_a,zero);
4690 hc08_useReg (hc08_reg_a);
4691 hc08_freeReg (hc08_reg_a);
4693 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4695 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4696 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4697 freeAsmop (result, NULL, ic, TRUE);
4701 /*-----------------------------------------------------------------*/
4702 /* genOrOp - for || operation */
4703 /*-----------------------------------------------------------------*/
4705 genOrOp (iCode * ic)
4707 operand *left, *right, *result;
4708 symbol *tlbl, *tlbl0;
4710 D(emitcode ("; genOrOp",""));
4712 /* note here that || operations that are in an
4713 if statement are taken away by backPatchLabels
4714 only those used in arthmetic operations remain */
4715 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4716 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4717 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4719 tlbl = newiTempLabel (NULL);
4720 tlbl0 = newiTempLabel (NULL);
4722 asmopToBool (AOP (left), FALSE);
4723 emitBranch ("bne", tlbl0);
4724 asmopToBool (AOP (right), FALSE);
4725 emitBranch ("bne", tlbl0);
4726 loadRegFromConst (hc08_reg_a,zero);
4727 emitBranch ("bra", tlbl);
4729 loadRegFromConst (hc08_reg_a,one);
4732 hc08_useReg (hc08_reg_a);
4733 hc08_freeReg (hc08_reg_a);
4735 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4738 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4739 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4740 freeAsmop (result, NULL, ic, TRUE);
4743 /*-----------------------------------------------------------------*/
4744 /* isLiteralBit - test if lit == 2^n */
4745 /*-----------------------------------------------------------------*/
4747 isLiteralBit (unsigned long lit)
4749 unsigned long pw[32] =
4750 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4751 0x100L, 0x200L, 0x400L, 0x800L,
4752 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4753 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4754 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4755 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4756 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4759 for (idx = 0; idx < 32; idx++)
4766 /*-----------------------------------------------------------------*/
4767 /* continueIfTrue - */
4768 /*-----------------------------------------------------------------*/
4770 continueIfTrue (iCode * ic)
4773 emitBranch ("jmp", IC_TRUE (ic));
4777 /*-----------------------------------------------------------------*/
4779 /*-----------------------------------------------------------------*/
4781 jumpIfTrue (iCode * ic)
4784 emitBranch ("jmp", IC_FALSE (ic));
4788 /*-----------------------------------------------------------------*/
4789 /* jmpTrueOrFalse - */
4790 /*-----------------------------------------------------------------*/
4792 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4794 // ugly but optimized by peephole
4797 symbol *nlbl = newiTempLabel (NULL);
4798 emitBranch ("bra", nlbl);
4800 emitBranch ("jmp", IC_TRUE (ic));
4805 emitBranch ("jmp", IC_FALSE (ic));
4812 /*-----------------------------------------------------------------*/
4813 /* genAnd - code for and */
4814 /*-----------------------------------------------------------------*/
4816 genAnd (iCode * ic, iCode * ifx)
4818 operand *left, *right, *result;
4819 int size, offset = 0;
4820 unsigned long lit = 0L;
4821 unsigned long litinv;
4822 unsigned char bytemask;
4828 D(emitcode ("; genAnd",""));
4830 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4831 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4832 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4835 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4837 AOP_TYPE (left), AOP_TYPE (right)));
4838 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4840 AOP_SIZE (left), AOP_SIZE (right)));
4843 /* if left is a literal & right is not then exchange them */
4844 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4846 operand *tmp = right;
4851 /* if right is accumulator & left is not then exchange them */
4852 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4854 operand *tmp = right;
4859 if (AOP_TYPE (right) == AOP_LIT)
4860 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4862 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4864 if (AOP_TYPE (result) == AOP_CRY
4866 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
4868 /* this generates ugly code, but meets volatility requirements */
4869 loadRegFromConst (hc08_reg_a, zero);
4870 pushReg (hc08_reg_a, TRUE);
4875 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4876 accopWithAop ("and", AOP (right), offset);
4877 emitcode ("ora", "1,s");
4878 emitcode ("sta", "1,s");
4882 pullReg (hc08_reg_a);
4883 emitcode ("tsta", "");
4884 genIfxJump (ifx, "a");
4888 if (AOP_TYPE (result) == AOP_CRY)
4890 symbol *tlbl = NULL;
4891 wassertl (ifx, "AOP_CRY result without ifx");
4896 bytemask = (lit >> (offset*8)) & 0xff;
4898 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
4902 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
4904 rmwWithAop ("tst", AOP (left), offset);
4908 tlbl = newiTempLabel (NULL);
4909 emitBranch ("bne", tlbl);
4914 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4915 accopWithAop ("and", AOP (right), offset);
4916 hc08_freeReg( hc08_reg_a);
4920 tlbl = newiTempLabel (NULL);
4921 emitBranch ("bne", tlbl);
4928 genIfxJump (ifx, "a");
4932 size = AOP_SIZE (result);
4934 if (AOP_TYPE (right) == AOP_LIT)
4936 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4937 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4938 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4940 int bitpos = isLiteralBit(litinv)-1;
4941 emitcode ("bclr","#%d,%s",bitpos & 7,
4942 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4950 bytemask = (lit >> (offset*8)) & 0xff;
4952 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
4954 if (isOperandVolatile (left, FALSE))
4956 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4957 hc08_freeReg( hc08_reg_a);
4959 storeConstToAop (zero, AOP (result), offset);
4961 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
4963 transferAopAop (AOP (left), offset, AOP (result), offset);
4967 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4968 accopWithAop ("and", AOP (right), offset);
4969 storeRegToAop (hc08_reg_a, AOP (result), offset);
4970 hc08_freeReg (hc08_reg_a);
4976 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4977 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4978 freeAsmop (result, NULL, ic, TRUE);
4981 /*-----------------------------------------------------------------*/
4982 /* genOr - code for or */
4983 /*-----------------------------------------------------------------*/
4985 genOr (iCode * ic, iCode * ifx)
4987 operand *left, *right, *result;
4988 int size, offset = 0;
4989 unsigned long lit = 0L;
4990 unsigned char bytemask;
4992 D(emitcode ("; genOr",""));
4994 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4995 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4996 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4999 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5001 AOP_TYPE (left), AOP_TYPE (right)));
5002 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5004 AOP_SIZE (left), AOP_SIZE (right)));
5007 /* if left is a literal & right is not then exchange them */
5008 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5010 operand *tmp = right;
5015 /* if left is accumulator & right is not then exchange them */
5016 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5018 operand *tmp = right;
5023 if (AOP_TYPE (right) == AOP_LIT)
5024 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5026 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5028 if (AOP_TYPE (result) == AOP_CRY
5030 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5032 /* this generates ugly code, but meets volatility requirements */
5033 loadRegFromConst (hc08_reg_a, zero);
5034 pushReg (hc08_reg_a, TRUE);
5039 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5040 accopWithAop ("ora", AOP (right), offset);
5041 emitcode ("ora", "1,s");
5042 emitcode ("sta", "1,s");
5046 pullReg (hc08_reg_a);
5047 emitcode ("tsta", "");
5048 genIfxJump (ifx, "a");
5052 if (AOP_TYPE (result) == AOP_CRY)
5054 symbol *tlbl = NULL;
5055 wassertl (ifx, "AOP_CRY result without ifx");
5060 bytemask = (lit >> (offset*8)) & 0xff;
5062 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5064 rmwWithAop ("tst", AOP (left), offset);
5068 tlbl = newiTempLabel (NULL);
5069 emitBranch ("bne", tlbl);
5074 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5075 accopWithAop ("ora", AOP (right), offset);
5076 hc08_freeReg( hc08_reg_a);
5080 tlbl = newiTempLabel (NULL);
5081 emitBranch ("bne", tlbl);
5088 genIfxJump (ifx, "a");
5091 if (AOP_TYPE (right) == AOP_LIT)
5092 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5094 size = AOP_SIZE (result);
5096 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5097 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5098 (AOP_TYPE (left) == AOP_DIR))
5100 int bitpos = isLiteralBit(lit)-1;
5101 emitcode ("bset","#%d,%s",bitpos & 7,
5102 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5109 bytemask = (lit >> (offset*8)) & 0xff;
5111 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5113 if (isOperandVolatile (left, FALSE))
5115 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5116 hc08_freeReg( hc08_reg_a);
5118 transferAopAop (AOP (right), offset, AOP (result), offset);
5120 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5122 transferAopAop (AOP (left), offset, AOP (result), offset);
5126 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5127 accopWithAop ("ora", AOP (right), offset);
5128 storeRegToAop (hc08_reg_a, AOP (result), offset);
5129 hc08_freeReg (hc08_reg_a);
5136 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5137 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5138 freeAsmop (result, NULL, ic, TRUE);
5141 /*-----------------------------------------------------------------*/
5142 /* genXor - code for xclusive or */
5143 /*-----------------------------------------------------------------*/
5145 genXor (iCode * ic, iCode * ifx)
5147 operand *left, *right, *result;
5148 int size, offset = 0;
5149 unsigned long lit = 0L;
5151 D(emitcode ("; genXor",""));
5153 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5154 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5155 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5158 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5160 AOP_TYPE (left), AOP_TYPE (right)));
5161 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5163 AOP_SIZE (left), AOP_SIZE (right)));
5166 /* if left is a literal & right is not ||
5167 if left needs acc & right does not */
5168 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5170 operand *tmp = right;
5175 /* if left is accumulator & right is not then exchange them */
5176 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5178 operand *tmp = right;
5183 if (AOP_TYPE (result) == AOP_CRY)
5186 wassertl (ifx, "AOP_CPY result without ifx");
5188 tlbl = newiTempLabel (NULL);
5189 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5193 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5194 if ((AOP_TYPE (right) == AOP_LIT)
5195 && (((lit >> (offset*8)) & 0xff) == 0))
5196 emitcode ("tsta","");
5198 accopWithAop ("eor", AOP (right), offset);
5199 hc08_freeReg( hc08_reg_a);
5201 emitBranch ("bne", tlbl);
5205 genIfxJump (ifx, "a");
5211 if (AOP_TYPE (right) == AOP_LIT)
5212 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5214 size = AOP_SIZE (result);
5218 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5219 accopWithAop ("eor", AOP (right), offset);
5220 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5221 hc08_freeReg( hc08_reg_a);
5225 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5226 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5227 freeAsmop (result, NULL, ic, TRUE);
5231 emitinline (iCode * ic, char *inlin)
5237 symbol *sym, *tempsym;
5246 while (isalnum(*inlin) || (*inlin == '_'))
5250 //printf("Found possible symbol '%s'\n",symname);
5251 tempsym = newSymbol (symname, ic->level);
5252 tempsym->block = ic->block;
5253 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5262 aop = aopForSym (ic, sym, FALSE);
5263 l = aopAdrStr (aop, aop->size - 1, TRUE);
5267 if (!sym->allocreq && !sym->ismyparm)
5269 werror (E_ID_UNDEF, sym->name);
5271 " Add 'volatile' to the variable declaration so that it\n"
5272 " can be referenced within inline assembly");
5274 //printf("Replacing with '%s'\n",l);
5278 if ((2+bp-buffer)>sizeof(buffer))
5287 if ((2+bp-buffer)>sizeof(buffer))
5294 if ((2+bp-buffer)>sizeof(buffer))
5295 fprintf(stderr, "Inline assembly buffer overflow\n");
5297 //printf("%s\n",buffer);
5298 emitcode (buffer,"");
5302 /*-----------------------------------------------------------------*/
5303 /* genInline - write the inline code out */
5304 /*-----------------------------------------------------------------*/
5306 genInline (iCode * ic)
5308 char *buffer, *bp, *bp1;
5310 D(emitcode ("; genInline",""));
5312 _G.inLine += (!options.asmpeep);
5314 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5315 strcpy (buffer, IC_INLINE (ic));
5317 /* emit each line as a code */
5323 /* emitcode (bp1, ""); */
5324 emitinline (ic, bp1);
5343 /* emitcode (bp1, ""); */
5344 emitinline (ic, bp1);
5346 /* emitcode("",buffer); */
5347 _G.inLine -= (!options.asmpeep);
5350 /*-----------------------------------------------------------------*/
5351 /* genRRC - rotate right with carry */
5352 /*-----------------------------------------------------------------*/
5356 operand *left, *result;
5357 int size, offset = 0;
5358 bool needpula = FALSE;
5359 bool resultInA = FALSE;
5362 D(emitcode ("; genRRC",""));
5364 /* rotate right with carry */
5365 left = IC_LEFT (ic);
5366 result = IC_RESULT (ic);
5367 aopOp (left, ic, FALSE);
5368 aopOp (result, ic, FALSE);
5370 if ((AOP_TYPE (result) == AOP_REG)
5371 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5374 size = AOP_SIZE (result);
5378 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5382 rmwWithAop (shift, AOP (result), offset--);
5390 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5391 rmwWithReg (shift, hc08_reg_a);
5392 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5393 hc08_freeReg (hc08_reg_a);
5398 if ((!hc08_reg_a->isFree) || resultInA)
5400 pushReg (hc08_reg_a, TRUE);
5404 /* now we need to put the carry into the
5405 highest order byte of the result */
5406 offset = AOP_SIZE (result) - 1;
5407 emitcode ("clra","");
5408 emitcode ("rora","");
5409 hc08_dirtyReg (hc08_reg_a, FALSE);
5412 emitcode ("ora", "1,s");
5413 emitcode ("ais", "#1");
5414 hc08_dirtyReg (hc08_reg_a, FALSE);
5418 accopWithAop ("ora", AOP (result), offset);
5419 storeRegToAop (hc08_reg_a, AOP (result), offset);
5421 pullOrFreeReg (hc08_reg_a, needpula);
5423 freeAsmop (left, NULL, ic, TRUE);
5424 freeAsmop (result, NULL, ic, TRUE);
5427 /*-----------------------------------------------------------------*/
5428 /* genRLC - generate code for rotate left with carry */
5429 /*-----------------------------------------------------------------*/
5433 operand *left, *result;
5434 int size, offset = 0;
5436 bool resultInA = FALSE;
5437 bool needpula = FALSE;
5439 D(emitcode ("; genRLC",""));
5441 /* rotate right with carry */
5442 left = IC_LEFT (ic);
5443 result = IC_RESULT (ic);
5444 aopOp (left, ic, FALSE);
5445 aopOp (result, ic, FALSE);
5447 if ((AOP_TYPE (result) == AOP_REG)
5448 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5451 size = AOP_SIZE (result);
5455 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5459 rmwWithAop (shift, AOP (result), offset--);
5467 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5468 rmwWithReg (shift, hc08_reg_a);
5469 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5470 hc08_freeReg (hc08_reg_a);
5475 if ((!hc08_reg_a->isFree) || resultInA)
5477 pushReg (hc08_reg_a, TRUE);
5481 /* now we need to put the carry into the
5482 lowest order byte of the result */
5484 emitcode ("clra","");
5485 emitcode ("rola","");
5486 hc08_dirtyReg (hc08_reg_a, FALSE);
5489 emitcode ("ora", "1,s");
5490 emitcode ("ais", "#1");
5491 hc08_dirtyReg (hc08_reg_a, FALSE);
5495 accopWithAop ("ora", AOP (result), offset);
5496 storeRegToAop (hc08_reg_a, AOP (result), offset);
5498 pullOrFreeReg (hc08_reg_a, needpula);
5500 freeAsmop (left, NULL, ic, TRUE);
5501 freeAsmop (result, NULL, ic, TRUE);
5504 /*-----------------------------------------------------------------*/
5505 /* genGetHbit - generates code get highest order bit */
5506 /*-----------------------------------------------------------------*/
5508 genGetHbit (iCode * ic)
5510 operand *left, *result;
5512 D(emitcode ("; genGetHbit",""));
5514 left = IC_LEFT (ic);
5515 result = IC_RESULT (ic);
5516 aopOp (left, ic, FALSE);
5517 aopOp (result, ic, FALSE);
5519 /* get the highest order byte into a */
5520 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5521 emitcode ("rola", "");
5522 emitcode ("clra", "");
5523 emitcode ("rola", "");
5524 hc08_dirtyReg (hc08_reg_a, FALSE);
5525 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5526 hc08_freeReg (hc08_reg_a);
5528 freeAsmop (left, NULL, ic, TRUE);
5529 freeAsmop (result, NULL, ic, TRUE);
5532 /*-----------------------------------------------------------------*/
5533 /* genSwap - generates code to swap nibbles or bytes */
5534 /*-----------------------------------------------------------------*/
5536 genSwap (iCode * ic)
5538 operand *left, *result;
5540 D(emitcode ("; genSwap",""));
5542 left = IC_LEFT (ic);
5543 result = IC_RESULT (ic);
5544 aopOp (left, ic, FALSE);
5545 aopOp (result, ic, FALSE);
5547 switch (AOP_SIZE (left))
5549 case 1: /* swap nibbles in byte */
5550 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5551 emitcode ("nsa", "");
5552 hc08_dirtyReg (hc08_reg_a, FALSE);
5553 storeRegToAop (hc08_reg_a, AOP (result), 0);
5554 hc08_freeReg (hc08_reg_a);
5556 case 2: /* swap bytes in a word */
5557 if (operandsEqu (left, result))
5559 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5560 hc08_useReg (hc08_reg_a);
5561 transferAopAop (AOP (left), 1, AOP (result), 0);
5562 storeRegToAop (hc08_reg_a, AOP (result), 1);
5563 hc08_freeReg (hc08_reg_a);
5567 transferAopAop (AOP (left), 0, AOP (result), 1);
5568 transferAopAop (AOP (left), 1, AOP (result), 0);
5572 wassertl(FALSE, "unsupported SWAP operand size");
5575 freeAsmop (left, NULL, ic, TRUE);
5576 freeAsmop (result, NULL, ic, TRUE);
5580 /*-----------------------------------------------------------------*/
5581 /* AccRol - rotate left accumulator by known count */
5582 /*-----------------------------------------------------------------*/
5584 AccRol (int shCount)
5586 shCount &= 0x0007; // shCount : 0..7
5593 emitcode ("rola", ""); /* 1 cycle */
5596 emitcode ("rola", ""); /* 1 cycle */
5597 emitcode ("rola", ""); /* 1 cycle */
5600 emitcode ("nsa", "");
5601 emitcode ("rora", "");
5604 emitcode ("nsa", ""); /* 3 cycles */
5607 emitcode ("nsa", ""); /* 3 cycles */
5608 emitcode ("rola", ""); /* 1 cycle */
5611 emitcode ("nsa", ""); /* 3 cycles */
5612 emitcode ("rola", ""); /* 1 cycle */
5613 emitcode ("rola", ""); /* 1 cycle */
5616 emitcode ("nsa", ""); /* 3 cycles */
5617 emitcode ("rola", ""); /* 1 cycle */
5618 emitcode ("rola", ""); /* 1 cycle */
5619 emitcode ("rola", ""); /* 1 cycle */
5626 /*-----------------------------------------------------------------*/
5627 /* AccLsh - left shift accumulator by known count */
5628 /*-----------------------------------------------------------------*/
5630 AccLsh (int shCount)
5634 shCount &= 0x0007; // shCount : 0..7
5636 /* Shift counts of 4 and 5 are currently optimized for code size. */
5637 /* Falling through to the unrolled loop would be optimal for code speed. */
5638 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5642 accopWithMisc ("nsa", "");
5643 accopWithMisc ("and", "#0xf0");
5644 /* total: 5 cycles, 3 bytes */
5647 accopWithMisc ("nsa", "");
5648 accopWithMisc ("and", "#0xf0");
5649 accopWithMisc ("lsla", "");
5650 /* total: 6 cycles, 4 bytes */
5653 accopWithMisc ("rora", "");
5654 accopWithMisc ("rora", "");
5655 accopWithMisc ("rora", "");
5656 accopWithMisc ("and", "#0xc0");
5657 /* total: 5 cycles, 5 bytes */
5660 accopWithMisc ("rora", "");
5661 accopWithMisc ("clra", "");
5662 accopWithMisc ("rora", "");
5663 /* total: 3 cycles, 3 bytes */
5667 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5668 /* the fastest (shCount<6) and shortest (shCount<4). */
5669 for (i=0;i<shCount;i++)
5670 accopWithMisc ("lsla", "");
5674 /*-----------------------------------------------------------------*/
5675 /* AccSRsh - signed right shift accumulator by known count */
5676 /*-----------------------------------------------------------------*/
5678 AccSRsh (int shCount)
5682 shCount &= 0x0007; // shCount : 0..7
5686 accopWithMisc ("rola", "");
5687 accopWithMisc ("clra", "");
5688 accopWithMisc ("sbc", zero);
5689 /* total: 4 cycles, 4 bytes */
5693 for (i=0;i<shCount;i++)
5694 accopWithMisc ("asra", "");
5697 /*-----------------------------------------------------------------*/
5698 /* AccRsh - right shift accumulator by known count */
5699 /*-----------------------------------------------------------------*/
5701 AccRsh (int shCount, bool sign)
5711 shCount &= 0x0007; // shCount : 0..7
5713 /* Shift counts of 4 and 5 are currently optimized for code size. */
5714 /* Falling through to the unrolled loop would be optimal for code speed. */
5715 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5719 accopWithMisc ("nsa", "");
5720 accopWithMisc ("and", "#0x0f");
5721 /* total: 5 cycles, 3 bytes */
5724 accopWithMisc ("nsa", "");
5725 accopWithMisc ("and", "#0x0f");
5726 accopWithMisc ("lsra", "");
5727 /* total: 6 cycles, 4 bytes */
5730 accopWithMisc ("rola", "");
5731 accopWithMisc ("rola", "");
5732 accopWithMisc ("rola", "");
5733 accopWithMisc ("and", "#0x03");
5734 /* total: 5 cycles, 5 bytes */
5737 accopWithMisc ("rola", "");
5738 accopWithMisc ("clra", "");
5739 accopWithMisc ("rola", "");
5740 /* total: 3 cycles, 3 bytes */
5744 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5745 /* the fastest (shCount<6) and shortest (shCount<4). */
5746 for (i=0;i<shCount;i++)
5747 accopWithMisc ("lsra", "");
5751 /*-----------------------------------------------------------------*/
5752 /* XAccLsh - left shift register pair XA by known count */
5753 /*-----------------------------------------------------------------*/
5755 XAccLsh (int shCount)
5759 shCount &= 0x000f; // shCount : 0..15
5764 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5765 loadRegFromConst (hc08_reg_a, zero);
5769 /* if we can beat 2n cycles or bytes for some special case, do it here */
5773 /* bytes cycles reg x reg a carry
5774 ** abcd efgh ijkl mnop ?
5775 ** lsrx 1 1 0abc defg ijkl mnop h
5776 ** rora 1 1 0abc defg hijk lmno p
5777 ** tax 1 1 hijk lmno hijk lmno p
5778 ** clra 1 1 hijk lmno 0000 0000 p
5779 ** rora 1 1 hijk lmno p000 0000 0
5780 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5782 rmwWithReg ("lsr", hc08_reg_x);
5783 rmwWithReg ("ror", hc08_reg_a);
5784 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5785 loadRegFromConst (hc08_reg_a, zero);
5786 rmwWithReg ("ror", hc08_reg_a);
5793 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5794 /* the fastest and shortest. */
5795 for (i=0;i<shCount;i++)
5797 rmwWithReg ("lsl", hc08_reg_a);
5798 rmwWithReg ("rol", hc08_reg_x);
5802 /*-----------------------------------------------------------------*/
5803 /* XAccSRsh - signed right shift register pair XA by known count */
5804 /*-----------------------------------------------------------------*/
5806 XAccSRsh (int shCount)
5810 shCount &= 0x000f; // shCount : 0..7
5812 /* if we can beat 2n cycles or bytes for some special case, do it here */
5816 /* bytes cycles reg x reg a carry
5817 ** abcd efgh ijkl mnop ?
5818 ** lslx 1 1 bcde fgh0 ijkl mnop a
5819 ** clra 1 1 bcde fgh0 0000 0000 a
5820 ** rola 1 1 bcde fgh0 0000 000a 0
5821 ** nega 1 1 bcde fgh0 aaaa aaaa a
5822 ** tax 1 1 aaaa aaaa aaaa aaaa a
5823 ** total: 5 cycles, 5 bytes
5825 rmwWithReg ("lsl", hc08_reg_x);
5826 loadRegFromConst (hc08_reg_a, zero);
5827 rmwWithReg ("rol", hc08_reg_a);
5828 rmwWithReg ("neg", hc08_reg_a);
5829 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5839 /* bytes cycles reg x reg a carry
5840 ** abcd efgh ijkl mnop ?
5841 ** txa 1 1 abcd efgh abcd efgh ?
5842 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5843 ** lsla 1 1 abcd efgh ???? ???? a
5844 ** clrx 1 1 0000 0000 ???? ???? a
5845 ** rolx 1 1 0000 000a ???? ???? 0
5846 ** negx 1 1 aaaa aaaa ???? ???? a
5847 ** rora 1 1 aaaa aaaa LSBresult 0
5848 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5850 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5851 AccSRsh (shCount-8);
5852 rmwWithReg ("lsl", hc08_reg_a);
5853 loadRegFromConst (hc08_reg_x, zero);
5854 rmwWithReg ("rol", hc08_reg_x);
5855 rmwWithReg ("neg", hc08_reg_x);
5856 rmwWithReg ("ror", hc08_reg_a);
5863 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5864 /* the fastest and shortest. */
5865 for (i=0;i<shCount;i++)
5867 rmwWithReg ("asr", hc08_reg_x);
5868 rmwWithReg ("ror", hc08_reg_a);
5872 /*-----------------------------------------------------------------*/
5873 /* XAccRsh - right shift register pair XA by known count */
5874 /*-----------------------------------------------------------------*/
5876 XAccRsh (int shCount, bool sign)
5886 shCount &= 0x000f; // shCount : 0..f
5888 /* if we can beat 2n cycles or bytes for some special case, do it here */
5892 /* bytes cycles reg x reg a carry
5893 ** abcd efgh ijkl mnop ?
5894 ** clra 1 1 abcd efgh 0000 0000 a
5895 ** lslx 1 1 bcde fgh0 0000 0000 a
5896 ** rola 1 1 bcde fgh0 0000 000a 0
5897 ** clrx 1 1 0000 0000 0000 000a 0
5898 ** total: 4 cycles, 4 bytes
5900 loadRegFromConst (hc08_reg_x, zero);
5901 rmwWithReg ("lsl", hc08_reg_x);
5902 rmwWithReg ("rol", hc08_reg_a);
5903 loadRegFromConst (hc08_reg_a, zero);
5907 /* bytes cycles reg x reg a carry
5908 ** abcd efgh ijkl mnop ?
5909 ** clra 1 1 abcd efgh 0000 0000 a
5910 ** lslx 1 1 bcde fgh0 0000 0000 a
5911 ** rola 1 1 bcde fgh0 0000 000a 0
5912 ** lslx 1 1 cdef gh00 0000 000a b
5913 ** rola 1 1 cdef gh00 0000 00ab 0
5914 ** clrx 1 1 0000 0000 0000 00ab 0
5915 ** total: 6 cycles, 6 bytes
5917 loadRegFromConst (hc08_reg_x, zero);
5918 rmwWithReg ("lsl", hc08_reg_x);
5919 rmwWithReg ("rol", hc08_reg_a);
5920 rmwWithReg ("lsl", hc08_reg_x);
5921 rmwWithReg ("rol", hc08_reg_a);
5922 loadRegFromConst (hc08_reg_a, zero);
5931 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5932 AccRsh (shCount-8, FALSE);
5933 loadRegFromConst (hc08_reg_x, zero);
5937 /* bytes cycles reg x reg a carry
5938 ** abcd efgh ijkl mnop ?
5939 ** lsla 1 1 abcd efgh jklm nop0 i
5940 ** txa 1 1 abcd efgh abcd efgh i
5941 ** rola 1 1 abcd efgh bcde fghi a
5942 ** clrx 1 1 0000 0000 bcde fghi a
5943 ** rolx 1 1 0000 000a bcde fghi 0
5944 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5946 rmwWithReg ("lsl", hc08_reg_a);
5947 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5948 rmwWithReg ("rol", hc08_reg_a);
5949 loadRegFromConst (hc08_reg_x, zero);
5950 rmwWithReg ("rol", hc08_reg_x);
5953 /* bytes cycles reg x reg a carry
5954 ** abcd efgh ijkl mnop ?
5955 ** lsla 1 1 abcd efgh jklm nop0 i
5956 ** rolx 1 1 bcde fghi jklm nop0 a
5957 ** rola 1 1 bcde fghi klmn op0a j
5958 ** rolx 1 1 cdef ghij klmn op0a b
5959 ** rola 1 1 cdef ghij lmno p0ab k
5960 ** and #3 2 2 cdef ghij 0000 00ab k
5961 ** psha 1 2 cdef ghij 0000 00ab k
5962 ** txa 1 1 cdef ghij cdef ghij k
5963 ** pula 1 2 0000 00ab cdef ghij k
5964 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5970 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5971 /* the fastest and shortest. */
5972 for (i=0;i<shCount;i++)
5974 rmwWithReg ("lsr", hc08_reg_x);
5975 rmwWithReg ("ror", hc08_reg_a);
5982 /*-----------------------------------------------------------------*/
5983 /* shiftR1Left2Result - shift right one byte from left to result */
5984 /*-----------------------------------------------------------------*/
5986 shiftR1Left2Result (operand * left, int offl,
5987 operand * result, int offr,
5988 int shCount, int sign)
5990 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5991 /* shift right accumulator */
5992 AccRsh (shCount, sign);
5993 storeRegToAop (hc08_reg_a, AOP (result), offr);
5997 /*-----------------------------------------------------------------*/
5998 /* shiftL1Left2Result - shift left one byte from left to result */
5999 /*-----------------------------------------------------------------*/
6001 shiftL1Left2Result (operand * left, int offl,
6002 operand * result, int offr, int shCount)
6004 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6005 /* shift left accumulator */
6007 storeRegToAop (hc08_reg_a, AOP (result), offr);
6010 /*-----------------------------------------------------------------*/
6011 /* movLeft2Result - move byte from left to result */
6012 /*-----------------------------------------------------------------*/
6014 movLeft2Result (operand * left, int offl,
6015 operand * result, int offr, int sign)
6017 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6019 transferAopAop (AOP (left), offl, AOP (result), offr);
6024 /*-----------------------------------------------------------------*/
6025 /* shiftL2Left2Result - shift left two bytes from left to result */
6026 /*-----------------------------------------------------------------*/
6028 shiftL2Left2Result (operand * left, int offl,
6029 operand * result, int offr, int shCount)
6032 bool needpula = FALSE;
6033 bool needpulx = FALSE;
6035 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6036 needpula = pushRegIfUsed (hc08_reg_a);
6039 if (!IS_AOP_XA (AOP (left)))
6040 needpulx = pushRegIfUsed (hc08_reg_x);
6044 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6049 rmwWithReg ("lsr", hc08_reg_x);
6050 rmwWithReg ("ror", hc08_reg_a);
6051 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6052 rmwWithReg ("clr", hc08_reg_a);
6053 rmwWithReg ("ror", hc08_reg_a);
6056 for (i=0; i<shCount; i++)
6058 rmwWithReg ("lsl", hc08_reg_a);
6059 rmwWithReg ("rol", hc08_reg_x);
6062 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6064 pullOrFreeReg (hc08_reg_x, needpulx);
6065 pullOrFreeReg (hc08_reg_a, needpula);
6071 /*-----------------------------------------------------------------*/
6072 /* shiftR2Left2Result - shift right two bytes from left to result */
6073 /*-----------------------------------------------------------------*/
6075 shiftR2Left2Result (operand * left, int offl,
6076 operand * result, int offr,
6077 int shCount, int sign)
6080 bool needpula = FALSE;
6081 bool needpulx = FALSE;
6083 needpula = pushRegIfUsed (hc08_reg_a);
6084 needpulx = pushRegIfUsed (hc08_reg_x);
6086 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6087 for (i=0; i<shCount; i++)
6090 rmwWithReg ("asr", hc08_reg_x);
6092 rmwWithReg ("lsr", hc08_reg_x);
6093 rmwWithReg ("ror", hc08_reg_a);
6095 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6097 pullOrFreeReg (hc08_reg_x, needpulx);
6098 pullOrFreeReg (hc08_reg_a, needpula);
6103 /*-----------------------------------------------------------------*/
6104 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6105 /*-----------------------------------------------------------------*/
6107 shiftLLeftOrResult (operand * left, int offl,
6108 operand * result, int offr, int shCount)
6110 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6111 /* shift left accumulator */
6113 /* or with result */
6114 accopWithAop ("ora", AOP (result), offr);
6115 /* back to result */
6116 storeRegToAop (hc08_reg_a, AOP (result), offr);
6117 hc08_freeReg (hc08_reg_a);
6121 /*-----------------------------------------------------------------*/
6122 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6123 /*-----------------------------------------------------------------*/
6125 shiftRLeftOrResult (operand * left, int offl,
6126 operand * result, int offr, int shCount)
6128 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6129 /* shift left accumulator */
6130 AccRsh (shCount, FALSE);
6131 /* or with result */
6132 accopWithAop ("ora", AOP (result), offr);
6133 /* back to result */
6134 storeRegToAop (hc08_reg_a, AOP (result), offr);
6135 hc08_freeReg (hc08_reg_a);
6138 /*-----------------------------------------------------------------*/
6139 /* genlshOne - left shift a one byte quantity by known count */
6140 /*-----------------------------------------------------------------*/
6142 genlshOne (operand * result, operand * left, int shCount)
6144 D(emitcode ("; genlshOne",""));
6146 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6149 /*-----------------------------------------------------------------*/
6150 /* genlshTwo - left shift two bytes by known amount != 0 */
6151 /*-----------------------------------------------------------------*/
6153 genlshTwo (operand * result, operand * left, int shCount)
6157 D(emitcode ("; genlshTwo",""));
6160 size = getDataSize (result);
6162 /* if shCount >= 8 */
6169 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6171 storeRegToAop (hc08_reg_a, AOP (result), 1);
6173 storeConstToAop(zero, AOP (result), LSB);
6176 /* 1 <= shCount <= 7 */
6179 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6181 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6185 /*-----------------------------------------------------------------*/
6186 /* shiftLLong - shift left one long from left to result */
6187 /* offl = LSB or MSB16 */
6188 /*-----------------------------------------------------------------*/
6190 shiftLLong (operand * left, operand * result, int offr)
6193 // int size = AOP_SIZE (result);
6195 bool needpula = FALSE;
6196 bool needpulx = FALSE;
6198 needpula = pushRegIfUsed (hc08_reg_a);
6199 needpulx = pushRegIfUsed (hc08_reg_x);
6201 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6202 rmwWithReg ("lsl", hc08_reg_a);
6203 rmwWithReg ("rol", hc08_reg_x);
6204 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6208 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6209 rmwWithReg ("rol", hc08_reg_a);
6210 rmwWithReg ("rol", hc08_reg_x);
6211 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6213 else if (offr==MSB16)
6215 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6216 rmwWithReg ("rol", hc08_reg_a);
6217 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6220 pullOrFreeReg (hc08_reg_x, needpulx);
6221 pullOrFreeReg (hc08_reg_a, needpula);
6224 /*-----------------------------------------------------------------*/
6225 /* genlshFour - shift four byte by a known amount != 0 */
6226 /*-----------------------------------------------------------------*/
6228 genlshFour (operand * result, operand * left, int shCount)
6232 D(emitcode ("; genlshFour",""));
6234 size = AOP_SIZE (result);
6236 /* TODO: deal with the &result == &left case */
6238 /* if shifting more that 3 bytes */
6243 /* lowest order of left goes to the highest
6244 order of the destination */
6245 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6247 movLeft2Result (left, LSB, result, MSB32, 0);
6248 storeConstToAop (zero, AOP (result), LSB);
6249 storeConstToAop (zero, AOP (result), MSB16);
6250 storeConstToAop (zero, AOP (result), MSB24);
6254 /* more than two bytes */
6255 else if (shCount >= 16)
6257 /* lower order two bytes goes to higher order two bytes */
6259 /* if some more remaining */
6261 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6264 movLeft2Result (left, MSB16, result, MSB32, 0);
6265 movLeft2Result (left, LSB, result, MSB24, 0);
6267 storeConstToAop (zero, AOP (result), LSB);
6268 storeConstToAop (zero, AOP (result), MSB16);
6272 /* if more than 1 byte */
6273 else if (shCount >= 8)
6275 /* lower order three bytes goes to higher order three bytes */
6280 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6282 movLeft2Result (left, LSB, result, MSB16, 0);
6288 movLeft2Result (left, MSB24, result, MSB32, 0);
6289 movLeft2Result (left, MSB16, result, MSB24, 0);
6290 movLeft2Result (left, LSB, result, MSB16, 0);
6291 storeConstToAop (zero, AOP (result), LSB);
6293 else if (shCount == 1)
6294 shiftLLong (left, result, MSB16);
6297 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6298 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6299 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6300 storeConstToAop (zero, AOP (result), LSB);
6305 /* 1 <= shCount <= 7 */
6306 else if (shCount <= 2)
6308 shiftLLong (left, result, LSB);
6310 shiftLLong (result, result, LSB);
6312 /* 3 <= shCount <= 7, optimize */
6315 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6316 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6317 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6321 /*-----------------------------------------------------------------*/
6322 /* genLeftShiftLiteral - left shifting by known count */
6323 /*-----------------------------------------------------------------*/
6325 genLeftShiftLiteral (operand * left,
6330 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6333 D(emitcode ("; genLeftShiftLiteral",""));
6335 freeAsmop (right, NULL, ic, TRUE);
6337 aopOp (left, ic, FALSE);
6338 aopOp (result, ic, FALSE);
6340 // size = getSize (operandType (result));
6341 size = AOP_SIZE (result);
6344 D(emitcode ("; shift left ", "result %d, left %d", size,
6351 transferAopAop( AOP(left), size, AOP(result), size);
6353 else if (shCount >= (size * 8))
6356 storeConstToAop (zero, AOP (result), size);
6363 genlshOne (result, left, shCount);
6367 genlshTwo (result, left, shCount);
6371 genlshFour (result, left, shCount);
6374 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6375 "*** ack! mystery literal shift!\n");
6379 freeAsmop (left, NULL, ic, TRUE);
6380 freeAsmop (result, NULL, ic, TRUE);
6383 /*-----------------------------------------------------------------*/
6384 /* genLeftShift - generates code for left shifting */
6385 /*-----------------------------------------------------------------*/
6387 genLeftShift (iCode * ic)
6389 operand *left, *right, *result;
6391 symbol *tlbl, *tlbl1;
6396 D(emitcode ("; genLeftShift",""));
6398 right = IC_RIGHT (ic);
6399 left = IC_LEFT (ic);
6400 result = IC_RESULT (ic);
6402 aopOp (right, ic, FALSE);
6404 /* if the shift count is known then do it
6405 as efficiently as possible */
6406 if (AOP_TYPE (right) == AOP_LIT)
6408 genLeftShiftLiteral (left, right, result, ic);
6412 /* shift count is unknown then we have to form
6413 a loop get the loop count in A : Note: we take
6414 only the lower order byte since shifting
6415 more that 32 bits make no sense anyway, ( the
6416 largest size of an object can be only 32 bits ) */
6418 aopOp (left, ic, FALSE);
6419 aopOp (result, ic, FALSE);
6421 /* now move the left to the result if they are not the
6423 if (!sameRegs (AOP (left), AOP (result)))
6426 size = AOP_SIZE (result);
6430 transferAopAop (AOP (left), offset, AOP (result), offset);
6434 freeAsmop (left, NULL, ic, TRUE);
6436 tlbl = newiTempLabel (NULL);
6437 size = AOP_SIZE (result);
6439 tlbl1 = newiTempLabel (NULL);
6443 loadRegFromAop (reg, AOP (right), 0);
6444 freeAsmop (right, NULL, ic, TRUE);
6445 emitBranch ("beq", tlbl1);
6449 for (offset=0;offset<size;offset++)
6451 rmwWithAop (shift, AOP (result), offset);
6454 rmwWithReg ("dec", reg);
6455 emitBranch ("bne", tlbl);
6459 freeAsmop (result, NULL, ic, TRUE);
6462 /*-----------------------------------------------------------------*/
6463 /* genrshOne - right shift a one byte quantity by known count */
6464 /*-----------------------------------------------------------------*/
6466 genrshOne (operand * result, operand * left,
6467 int shCount, int sign)
6469 D(emitcode ("; genrshOne",""));
6471 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6472 AccRsh (shCount, sign);
6473 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6476 /*-----------------------------------------------------------------*/
6477 /* genrshTwo - right shift two bytes by known amount != 0 */
6478 /*-----------------------------------------------------------------*/
6480 genrshTwo (operand * result, operand * left,
6481 int shCount, int sign)
6483 D(emitcode ("; genrshTwo",""));
6485 /* if shCount >= 8 */
6488 if (shCount || sign)
6490 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6491 AccRsh (shCount-8, sign);
6492 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6496 transferAopAop (AOP (left), 1, AOP (result), 0);
6497 storeConstToAop (zero, AOP (result), 1);
6501 /* 1 <= shCount <= 7 */
6504 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6505 XAccRsh (shCount, sign);
6506 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6510 /*-----------------------------------------------------------------*/
6511 /* shiftRLong - shift right one long from left to result */
6512 /* offl = LSB or MSB16 */
6513 /*-----------------------------------------------------------------*/
6515 shiftRLong (operand * left, int offl,
6516 operand * result, int sign)
6519 // int size = AOP_SIZE (result);
6521 bool needpula = FALSE;
6522 bool needpulx = FALSE;
6524 needpula = pushRegIfUsed (hc08_reg_a);
6525 needpulx = pushRegIfUsed (hc08_reg_x);
6529 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6531 rmwWithReg ("asr", hc08_reg_x);
6533 rmwWithReg ("lsr", hc08_reg_x);
6534 rmwWithReg ("ror", hc08_reg_a);
6535 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6537 else if (offl==MSB16)
6539 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6541 rmwWithReg ("asr", hc08_reg_a);
6543 rmwWithReg ("lsr", hc08_reg_a);
6544 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6547 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6548 rmwWithReg ("ror", hc08_reg_x);
6549 rmwWithReg ("ror", hc08_reg_a);
6550 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6553 pullOrFreeReg (hc08_reg_x, needpulx);
6554 pullOrFreeReg (hc08_reg_a, needpula);
6557 /*-----------------------------------------------------------------*/
6558 /* genrshFour - shift four byte by a known amount != 0 */
6559 /*-----------------------------------------------------------------*/
6561 genrshFour (operand * result, operand * left,
6562 int shCount, int sign)
6564 /* TODO: handle cases where left == result */
6566 D(emitcode ("; genrshFour",""));
6568 /* if shifting more that 3 bytes */
6571 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6572 AccRsh (shCount-24, sign);
6573 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6576 else if (shCount >= 16)
6578 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6579 XAccRsh (shCount-16, sign);
6580 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6583 else if (shCount >= 8)
6586 shiftRLong (left, MSB16, result, sign);
6587 else if (shCount == 8)
6589 transferAopAop (AOP (left), 1, AOP (result), 0);
6590 transferAopAop (AOP (left), 2, AOP (result), 1);
6591 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6592 storeRegToAop (hc08_reg_a, AOP (result), 2);
6593 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6595 else if (shCount == 9)
6597 shiftRLong (left, MSB16, result, sign);
6601 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6602 XAccRsh (shCount-8, FALSE);
6603 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6604 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6605 loadRegFromConst (hc08_reg_a, zero);
6606 XAccRsh (shCount-8, sign);
6607 accopWithAop ("ora", AOP (result), 1);
6608 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6612 { /* 1 <= shCount <= 7 */
6615 shiftRLong (left, LSB, result, sign);
6619 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6620 XAccRsh (shCount, FALSE);
6621 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6622 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6624 accopWithAop ("ora", AOP (result), 1);
6625 storeRegToAop (hc08_reg_a, AOP (result), 1);
6626 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6627 XAccRsh (shCount, sign);
6628 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6633 /*-----------------------------------------------------------------*/
6634 /* genRightShiftLiteral - right shifting by known count */
6635 /*-----------------------------------------------------------------*/
6637 genRightShiftLiteral (operand * left,
6643 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6646 D(emitcode ("; genRightShiftLiteral",""));
6648 freeAsmop (right, NULL, ic, TRUE);
6650 aopOp (left, ic, FALSE);
6651 aopOp (result, ic, FALSE);
6654 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6658 size = getDataSize (left);
6659 /* test the LEFT size !!! */
6661 /* I suppose that the left size >= result size */
6664 size = getDataSize (result);
6666 transferAopAop (AOP (left), size, AOP(result), size);
6668 else if (shCount >= (size * 8))
6671 /* get sign in acc.7 */
6672 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6674 addSign (result, LSB, sign);
6681 genrshOne (result, left, shCount, sign);
6685 genrshTwo (result, left, shCount, sign);
6689 genrshFour (result, left, shCount, sign);
6695 freeAsmop (left, NULL, ic, TRUE);
6696 freeAsmop (result, NULL, ic, TRUE);
6700 /*-----------------------------------------------------------------*/
6701 /* genRightShift - generate code for right shifting */
6702 /*-----------------------------------------------------------------*/
6704 genRightShift (iCode * ic)
6706 operand *right, *left, *result;
6710 symbol *tlbl, *tlbl1;
6714 D(emitcode ("; genRightShift",""));
6716 /* if signed then we do it the hard way preserve the
6717 sign bit moving it inwards */
6718 retype = getSpec (operandType (IC_RESULT (ic)));
6719 sign = !SPEC_USIGN (retype);
6721 /* signed & unsigned types are treated the same : i.e. the
6722 signed is NOT propagated inwards : quoting from the
6723 ANSI - standard : "for E1 >> E2, is equivalent to division
6724 by 2**E2 if unsigned or if it has a non-negative value,
6725 otherwise the result is implementation defined ", MY definition
6726 is that the sign does not get propagated */
6728 right = IC_RIGHT (ic);
6729 left = IC_LEFT (ic);
6730 result = IC_RESULT (ic);
6732 aopOp (right, ic, FALSE);
6734 /* if the shift count is known then do it
6735 as efficiently as possible */
6736 if (AOP_TYPE (right) == AOP_LIT)
6738 genRightShiftLiteral (left, right, result, ic, sign);
6742 /* shift count is unknown then we have to form
6743 a loop get the loop count in X : Note: we take
6744 only the lower order byte since shifting
6745 more that 32 bits make no sense anyway, ( the
6746 largest size of an object can be only 32 bits ) */
6748 aopOp (left, ic, FALSE);
6749 aopOp (result, ic, FALSE);
6751 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6752 AOP (result) = forceStackedAop (AOP (result));
6754 size = AOP_SIZE (result);
6758 transferAopAop (AOP (left), offset, AOP (result), offset);
6762 tlbl = newiTempLabel (NULL);
6763 size = AOP_SIZE (result);
6765 tlbl1 = newiTempLabel (NULL);
6767 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6768 emitcode ("tstx", "");
6769 emitcode ("beq", "%05d$", tlbl1->key + 100);
6770 emitcode ("", "%05d$:", tlbl->key + 100);
6771 shift= sign ? "asr" : "lsr";
6772 for (offset=size-1;offset>=0;offset--)
6774 rmwWithAop (shift, AOP (result), offset);
6777 rmwWithReg ("dec", hc08_reg_x);
6778 emitcode ("bne","%05d$", tlbl->key + 100);
6779 emitcode ("", "%05d$:", tlbl1->key + 100);
6781 freeAsmop (result, NULL, ic, TRUE);
6782 freeAsmop (left, NULL, ic, TRUE);
6783 freeAsmop (right, NULL, ic, TRUE);
6787 /*-----------------------------------------------------------------*/
6788 /* genUnpackBits - generates code for unpacking bits */
6789 /*-----------------------------------------------------------------*/
6791 genUnpackBits (operand * result, iCode *ifx)
6793 int offset = 0; /* result byte offset */
6794 int rsize; /* result size */
6795 int rlen = 0; /* remaining bitfield length */
6796 sym_link *etype; /* bitfield type information */
6797 int blen; /* bitfield length */
6798 int bstr; /* bitfield starting bit within byte */
6800 D(emitcode ("; genUnpackBits",""));
6802 etype = getSpec (operandType (result));
6803 rsize = getSize (operandType (result));
6804 blen = SPEC_BLEN (etype);
6805 bstr = SPEC_BSTR (etype);
6807 /* If the bitfield length is less than a byte */
6810 emitcode ("lda", ",x");
6811 hc08_dirtyReg (hc08_reg_a, FALSE);
6814 AccRsh (bstr, FALSE);
6815 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6816 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6820 emitcode ("and", "#0x%02x",
6821 (((unsigned char) -1) >> (8 - blen)) << bstr);
6826 /* Bit field did not fit in a byte. Copy all
6827 but the partial byte at the end. */
6828 for (rlen=blen;rlen>=8;rlen-=8)
6830 emitcode ("lda", ",x");
6831 hc08_dirtyReg (hc08_reg_a, FALSE);
6833 storeRegToAop (hc08_reg_a, AOP (result), offset);
6836 emitcode ("aix", "#1");
6839 /* Handle the partial byte at the end */
6842 emitcode ("lda", ",x");
6843 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6844 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6852 storeConstToAop (zero, AOP (result), offset++);
6855 if (ifx && !ifx->generated)
6857 genIfxJump (ifx, "a");
6862 /*-----------------------------------------------------------------*/
6863 /* genUnpackBitsImmed - generates code for unpacking bits */
6864 /*-----------------------------------------------------------------*/
6866 genUnpackBitsImmed (operand * left,
6872 int offset = 0; /* result byte offset */
6873 int rsize; /* result size */
6874 int rlen = 0; /* remaining bitfield length */
6875 sym_link *etype; /* bitfield type information */
6876 int blen; /* bitfield length */
6877 int bstr; /* bitfield starting bit within byte */
6880 D(emitcode ("; genUnpackBitsImmed",""));
6882 aopOp (result, ic, TRUE);
6883 size = AOP_SIZE (result);
6885 derefaop = aopDerefAop (AOP (left));
6886 freeAsmop (left, NULL, ic, TRUE);
6887 derefaop->size = size;
6889 etype = getSpec (operandType (result));
6890 rsize = getSize (operandType (result));
6891 blen = SPEC_BLEN (etype);
6892 bstr = SPEC_BSTR (etype);
6894 /* if the bitfield is a single bit in the direct page */
6895 if (blen == 1 && derefaop->type == AOP_DIR)
6899 symbol *tlbl = newiTempLabel (NULL);
6901 loadRegFromConst (hc08_reg_a, zero);
6902 emitcode ("brclr", "#%d,%s,%05d$",
6903 bstr, aopAdrStr (derefaop, 0, FALSE),
6905 rmwWithReg ("inc", hc08_reg_a);
6907 storeRegToAop (hc08_reg_a, AOP (result), offset);
6908 hc08_freeReg (hc08_reg_a);
6914 symbol *tlbl = newiTempLabel (NULL);
6920 jlbl = IC_TRUE (ifx);
6925 jlbl = IC_FALSE (ifx);
6928 emitcode (inst, "#%d,%s,%05d$",
6929 bstr, aopAdrStr (derefaop, 0, FALSE),
6931 emitBranch ("jmp", jlbl);
6939 /* If the bitfield length is less than a byte */
6942 loadRegFromAop (hc08_reg_a, derefaop, 0);
6945 AccRsh (bstr, FALSE);
6946 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6947 hc08_dirtyReg (hc08_reg_a, FALSE);
6948 storeRegToAop (hc08_reg_a, AOP (result), offset);
6952 emitcode ("and", "#0x%02x",
6953 (((unsigned char) -1) >> (8 - blen)) << bstr);
6954 hc08_dirtyReg (hc08_reg_a, FALSE);
6960 /* Bit field did not fit in a byte. Copy all
6961 but the partial byte at the end. */
6962 for (rlen=blen;rlen>=8;rlen-=8)
6964 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6966 storeRegToAop (hc08_reg_a, AOP (result), offset);
6968 emitcode ("tsta", "");
6972 /* Handle the partial byte at the end */
6975 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6976 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6977 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6985 storeConstToAop (zero, AOP (result), offset++);
6988 freeAsmop (NULL, derefaop, ic, TRUE);
6989 freeAsmop (result, NULL, ic, TRUE);
6991 if (ifx && !ifx->generated)
6993 genIfxJump (ifx, "a");
6998 /*-----------------------------------------------------------------*/
6999 /* genDataPointerGet - generates code when ptr offset is known */
7000 /*-----------------------------------------------------------------*/
7002 genDataPointerGet (operand * left,
7007 int size, offset = 0;
7010 D(emitcode ("; genDataPointerGet",""));
7012 aopOp (result, ic, TRUE);
7013 size = AOP_SIZE (result);
7015 derefaop = aopDerefAop (AOP (left));
7016 freeAsmop (left, NULL, ic, TRUE);
7017 derefaop->size = size;
7022 transferAopAop (derefaop, offset, AOP (result), offset);
7024 loadRegFromAop (hc08_reg_a, derefaop, offset);
7028 freeAsmop (NULL, derefaop, ic, TRUE);
7029 freeAsmop (result, NULL, ic, TRUE);
7031 if (ifx && !ifx->generated)
7033 genIfxJump (ifx, "a");
7038 /*-----------------------------------------------------------------*/
7039 /* genPointerGet - generate code for pointer get */
7040 /*-----------------------------------------------------------------*/
7042 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7044 operand *left = IC_LEFT (ic);
7045 operand *result = IC_RESULT (ic);
7047 sym_link *retype = getSpec (operandType (result));
7049 D(emitcode ("; genPointerGet",""));
7051 if (getSize (operandType (result))>1)
7054 aopOp (left, ic, FALSE);
7056 /* if left is rematerialisable and
7057 result is not bit variable type */
7058 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7060 if (!IS_BITVAR (retype))
7062 genDataPointerGet (left, result, ic, ifx);
7067 genUnpackBitsImmed (left, result, ic, ifx);
7072 /* if the operand is already in hx
7073 then we do nothing else we move the value to hx */
7074 if (AOP_TYPE (left) != AOP_STR)
7076 /* if this is remateriazable */
7077 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7080 /* so hx now contains the address */
7081 aopOp (result, ic, FALSE);
7083 /* if bit then unpack */
7084 if (IS_BITVAR (retype))
7085 genUnpackBits (result, ifx);
7088 size = AOP_SIZE (result);
7093 accopWithMisc ("lda", ",x");
7096 emitcode ("aix", "#1");
7097 hc08_dirtyReg (hc08_reg_hx, FALSE);
7100 storeRegToAop (hc08_reg_a, AOP (result), offset);
7102 hc08_freeReg (hc08_reg_a);
7106 freeAsmop (left, NULL, ic, TRUE);
7107 freeAsmop (result, NULL, ic, TRUE);
7110 aopOp (IC_RESULT (pi), pi, FALSE);
7111 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7112 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7116 if (ifx && !ifx->generated)
7118 genIfxJump (ifx, "a");
7121 hc08_freeReg (hc08_reg_hx);
7125 /*-----------------------------------------------------------------*/
7126 /* genPackBits - generates code for packed bit storage */
7127 /*-----------------------------------------------------------------*/
7129 genPackBits (sym_link * etype,
7132 int offset = 0; /* source byte offset */
7133 int rlen = 0; /* remaining bitfield length */
7134 int blen; /* bitfield length */
7135 int bstr; /* bitfield starting bit within byte */
7136 int litval; /* source literal value (if AOP_LIT) */
7137 unsigned char mask; /* bitmask within current byte */
7140 D(emitcode ("; genPackBits",""));
7142 blen = SPEC_BLEN (etype);
7143 bstr = SPEC_BSTR (etype);
7145 /* If the bitfield length is less than a byte */
7148 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7149 (unsigned char) (0xFF >> (8 - bstr)));
7151 if (AOP_TYPE (right) == AOP_LIT)
7153 /* Case with a bitfield length <8 and literal source
7155 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7157 litval &= (~mask) & 0xff;
7159 emitcode ("lda", ",x");
7160 if ((mask|litval)!=0xff)
7161 emitcode ("and","#0x%02x", mask);
7163 emitcode ("ora","#0x%02x", litval);
7164 hc08_dirtyReg (hc08_reg_a, FALSE);
7165 emitcode ("sta", ",x");
7167 hc08_freeReg (hc08_reg_a);
7171 /* Case with a bitfield length < 8 and arbitrary source
7173 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7174 /* shift and mask source value */
7176 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7177 hc08_dirtyReg (hc08_reg_a, FALSE);
7178 pushReg (hc08_reg_a, TRUE);
7180 emitcode ("lda", ",x");
7181 emitcode ("and", "#0x%02x", mask);
7182 emitcode ("ora", "1,s");
7183 emitcode ("sta", ",x");
7184 pullReg (hc08_reg_a);
7186 hc08_freeReg (hc08_reg_a);
7190 /* Bit length is greater than 7 bits. In this case, copy */
7191 /* all except the partial byte at the end */
7192 for (rlen=blen;rlen>=8;rlen-=8)
7194 if (AOP (right)->type == AOP_DIR)
7196 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7201 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7202 emitcode ("sta", "%d,x", offset);
7207 /* If there was a partial byte at the end */
7210 mask = (((unsigned char) -1 << rlen) & 0xff);
7212 if (AOP_TYPE (right) == AOP_LIT)
7214 /* Case with partial byte and literal source
7216 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7217 litval >>= (blen-rlen);
7218 litval &= (~mask) & 0xff;
7219 emitcode ("lda", "%d,x", offset - xoffset);
7220 hc08_dirtyReg (hc08_reg_a, FALSE);
7221 if ((mask|litval)!=0xff)
7222 emitcode ("and","#0x%02x", mask);
7224 emitcode ("ora","#0x%02x", litval);
7225 emitcode ("sta", "%d,x", offset - xoffset);
7226 hc08_dirtyReg (hc08_reg_a, FALSE);
7227 hc08_freeReg (hc08_reg_a);
7231 /* Case with partial byte and arbitrary source
7233 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7234 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7235 hc08_dirtyReg (hc08_reg_a, FALSE);
7236 pushReg (hc08_reg_a, TRUE);
7238 emitcode ("lda", "%d,x", offset - xoffset);
7239 emitcode ("and", "#0x%02x", mask);
7240 emitcode ("ora", "1,s");
7241 emitcode ("sta", "%d,x", offset - xoffset);
7242 pullReg (hc08_reg_a);
7245 hc08_freeReg (hc08_reg_a);
7248 /*-----------------------------------------------------------------*/
7249 /* genPackBitsImmed - generates code for packed bit storage */
7250 /*-----------------------------------------------------------------*/
7252 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7256 int offset = 0; /* source byte offset */
7257 int rlen = 0; /* remaining bitfield length */
7258 int blen; /* bitfield length */
7259 int bstr; /* bitfield starting bit within byte */
7260 int litval; /* source literal value (if AOP_LIT) */
7261 unsigned char mask; /* bitmask within current byte */
7263 D(emitcode ("; genPackBitsImmed",""));
7265 blen = SPEC_BLEN (etype);
7266 bstr = SPEC_BSTR (etype);
7268 aopOp (right, ic, FALSE);
7269 size = AOP_SIZE (right);
7271 derefaop = aopDerefAop (AOP (result));
7272 freeAsmop (result, NULL, ic, TRUE);
7273 derefaop->size = size;
7275 /* if the bitfield is a single bit in the direct page */
7276 if (blen == 1 && derefaop->type == AOP_DIR)
7278 if (AOP_TYPE (right) == AOP_LIT)
7280 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7282 emitcode ((litval & 1) ? "bset" : "bclr",
7283 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7287 symbol *tlbl1 = newiTempLabel (NULL);
7288 symbol *tlbl2 = newiTempLabel (NULL);
7290 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7291 emitcode ("bit", "#1");
7292 emitBranch ("bne", tlbl1);
7293 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7294 emitBranch ("bra", tlbl2);
7296 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7298 hc08_freeReg (hc08_reg_a);
7303 /* If the bitfield length is less than a byte */
7306 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7307 (unsigned char) (0xFF >> (8 - bstr)));
7309 if (AOP_TYPE (right) == AOP_LIT)
7311 /* Case with a bitfield length <8 and literal source
7313 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7315 litval &= (~mask) & 0xff;
7317 loadRegFromAop (hc08_reg_a, derefaop, 0);
7318 if ((mask|litval)!=0xff)
7319 emitcode ("and","#0x%02x", mask);
7321 emitcode ("ora","#0x%02x", litval);
7322 hc08_dirtyReg (hc08_reg_a, FALSE);
7323 storeRegToAop (hc08_reg_a, derefaop, 0);
7325 hc08_freeReg (hc08_reg_a);
7329 /* Case with a bitfield length < 8 and arbitrary source
7331 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7332 /* shift and mask source value */
7334 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7335 hc08_dirtyReg (hc08_reg_a, FALSE);
7336 pushReg (hc08_reg_a, TRUE);
7338 loadRegFromAop (hc08_reg_a, derefaop, 0);
7339 emitcode ("and", "#0x%02x", mask);
7340 emitcode ("ora", "1,s");
7341 storeRegToAop (hc08_reg_a, derefaop, 0);
7342 pullReg (hc08_reg_a);
7344 hc08_freeReg (hc08_reg_a);
7348 /* Bit length is greater than 7 bits. In this case, copy */
7349 /* all except the partial byte at the end */
7350 for (rlen=blen;rlen>=8;rlen-=8)
7352 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7356 /* If there was a partial byte at the end */
7359 mask = (((unsigned char) -1 << rlen) & 0xff);
7361 if (AOP_TYPE (right) == AOP_LIT)
7363 /* Case with partial byte and literal source
7365 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7366 litval >>= (blen-rlen);
7367 litval &= (~mask) & 0xff;
7368 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7369 if ((mask|litval)!=0xff)
7370 emitcode ("and","#0x%02x", mask);
7372 emitcode ("ora","#0x%02x", litval);
7373 hc08_dirtyReg (hc08_reg_a, FALSE);
7374 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7375 hc08_dirtyReg (hc08_reg_a, FALSE);
7376 hc08_freeReg (hc08_reg_a);
7380 /* Case with partial byte and arbitrary source
7382 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7383 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7384 hc08_dirtyReg (hc08_reg_a, FALSE);
7385 pushReg (hc08_reg_a, TRUE);
7387 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7388 emitcode ("and", "#0x%02x", mask);
7389 emitcode ("ora", "1,s");
7390 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7391 pullReg (hc08_reg_a);
7394 hc08_freeReg (hc08_reg_a);
7397 freeAsmop (right, NULL, ic, TRUE);
7398 freeAsmop (NULL, derefaop, ic, TRUE);
7401 /*-----------------------------------------------------------------*/
7402 /* genDataPointerSet - remat pointer to data space */
7403 /*-----------------------------------------------------------------*/
7405 genDataPointerSet (operand * right,
7409 int size, offset = 0;
7412 D(emitcode ("; genDataPointerSet",""));
7414 aopOp (right, ic, FALSE);
7415 size = AOP_SIZE (right);
7417 derefaop = aopDerefAop (AOP (result));
7418 freeAsmop (result, NULL, ic, TRUE);
7419 derefaop->size = size;
7423 transferAopAop (AOP (right), offset, derefaop, offset);
7427 freeAsmop (right, NULL, ic, TRUE);
7428 freeAsmop (NULL, derefaop, ic, TRUE);
7432 /*-----------------------------------------------------------------*/
7433 /* genPointerSet - stores the value into a pointer location */
7434 /*-----------------------------------------------------------------*/
7436 genPointerSet (iCode * ic, iCode *pi)
7438 operand *right = IC_RIGHT (ic);
7439 operand *result = IC_RESULT (ic);
7440 sym_link *type, *etype;
7442 sym_link *retype = getSpec (operandType (right));
7443 sym_link *letype = getSpec (operandType (result));
7445 D(emitcode ("; genPointerSet",""));
7447 type = operandType (result);
7448 etype = getSpec (type);
7450 aopOp (result, ic, FALSE);
7452 /* if the result is rematerializable */
7453 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7455 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7457 genDataPointerSet (right, result, ic);
7462 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7467 /* if the operand is already in hx
7468 then we do nothing else we move the value to hx */
7469 if (AOP_TYPE (result) != AOP_STR)
7471 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7473 /* so hx now contains the address */
7474 aopOp (right, ic, FALSE);
7476 /* if bit then unpack */
7477 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7478 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7481 size = AOP_SIZE (right);
7486 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7487 accopWithMisc ("sta", ",x");
7490 emitcode ("aix", "#1");
7492 hc08_freeReg (hc08_reg_a);
7496 freeAsmop (result, NULL, ic, TRUE);
7497 freeAsmop (right, NULL, ic, TRUE);
7500 aopOp (IC_RESULT (pi), pi, FALSE);
7501 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7502 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7506 hc08_freeReg (hc08_reg_hx);
7510 /*-----------------------------------------------------------------*/
7511 /* genIfx - generate code for Ifx statement */
7512 /*-----------------------------------------------------------------*/
7514 genIfx (iCode * ic, iCode * popIc)
7516 operand *cond = IC_COND (ic);
7519 D(emitcode ("; genIfx",""));
7521 aopOp (cond, ic, FALSE);
7523 /* get the value into acc */
7524 if (AOP_TYPE (cond) != AOP_CRY)
7525 asmopToBool (AOP (cond), FALSE);
7528 /* the result is now in the accumulator */
7529 freeAsmop (cond, NULL, ic, TRUE);
7531 /* if there was something to be popped then do it */
7535 /* if the condition is a bit variable */
7536 if (isbit && IS_ITEMP (cond) &&
7538 genIfxJump (ic, SPIL_LOC (cond)->rname);
7539 else if (isbit && !IS_ITEMP (cond))
7540 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7542 genIfxJump (ic, "a");
7547 /*-----------------------------------------------------------------*/
7548 /* genAddrOf - generates code for address of */
7549 /*-----------------------------------------------------------------*/
7551 genAddrOf (iCode * ic)
7553 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7556 D(emitcode ("; genAddrOf",""));
7558 aopOp (IC_RESULT (ic), ic, FALSE);
7560 /* if the operand is on the stack then we
7561 need to get the stack offset of this
7565 /* if it has an offset then we need to compute
7567 hc08_useReg (hc08_reg_hx);
7568 emitcode ("tsx", "");
7569 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7570 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7571 hc08_freeReg (hc08_reg_hx);
7576 /* object not on stack then we need the name */
7577 size = AOP_SIZE (IC_RESULT (ic));
7582 char s[SDCC_NAME_MAX+10];
7585 sprintf (s, "#%s", sym->rname);
7588 sprintf (s, "#>%s", sym->rname);
7591 sprintf (s, "#(%s >> %d)",
7595 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7599 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7603 /*-----------------------------------------------------------------*/
7604 /* genAssign - generate code for assignment */
7605 /*-----------------------------------------------------------------*/
7607 genAssign (iCode * ic)
7609 operand *result, *right;
7611 // unsigned long lit = 0L;
7613 D(emitcode("; genAssign",""));
7615 result = IC_RESULT (ic);
7616 right = IC_RIGHT (ic);
7618 /* if they are the same */
7619 if (operandsEqu (result, right)) {
7623 aopOp (right, ic, FALSE);
7624 aopOp (result, ic, TRUE);
7626 /* if they are the same registers */
7627 if (sameRegs (AOP (right), AOP (result)))
7630 if ((AOP_TYPE (right) == AOP_LIT)
7631 && (IS_AOP_HX(AOP(result))))
7633 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7638 size = AOP_SIZE (result);
7643 transferAopAop (AOP (right), offset, AOP (result), offset);
7648 freeAsmop (right, NULL, ic, TRUE);
7649 freeAsmop (result, NULL, ic, TRUE);
7652 /*-----------------------------------------------------------------*/
7653 /* genJumpTab - genrates code for jump table */
7654 /*-----------------------------------------------------------------*/
7656 genJumpTab (iCode * ic)
7661 D(emitcode ("; genJumpTab",""));
7663 aopOp (IC_JTCOND (ic), ic, FALSE);
7664 /* get the condition into accumulator */
7665 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7666 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7667 /* multiply by three */
7668 pushReg (hc08_reg_a, FALSE);
7669 emitcode ("lsla", "");
7670 emitcode ("add","1,s");
7671 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7672 loadRegFromConst (hc08_reg_h, zero);
7673 pullReg (hc08_reg_a);
7675 jtab = newiTempLabel (NULL);
7676 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7677 emitcode ("", "%05d$:", jtab->key + 100);
7678 /* now generate the jump labels */
7679 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7680 jtab = setNextItem (IC_JTLABELS (ic)))
7681 emitcode ("jmp", "%05d$", jtab->key + 100);
7683 hc08_dirtyReg (hc08_reg_a, TRUE);
7684 hc08_dirtyReg (hc08_reg_hx, TRUE);
7687 /*-----------------------------------------------------------------*/
7688 /* genCast - gen code for casting */
7689 /*-----------------------------------------------------------------*/
7691 genCast (iCode * ic)
7693 operand *result = IC_RESULT (ic);
7694 sym_link *ctype = operandType (IC_LEFT (ic));
7695 sym_link *rtype = operandType (IC_RIGHT (ic));
7696 operand *right = IC_RIGHT (ic);
7699 D(emitcode("; genCast",""));
7701 /* if they are equivalent then do nothing */
7702 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7705 aopOp (right, ic, FALSE);
7706 aopOp (result, ic, FALSE);
7709 /* if they are the same size : or less */
7710 if (AOP_SIZE (result) <= AOP_SIZE (right))
7713 /* if they are in the same place */
7715 if (sameRegs (AOP (right), AOP (result)))
7719 /* if they in different places then copy */
7720 size = AOP_SIZE (result);
7724 transferAopAop(AOP (right), offset, AOP (result), offset);
7731 /* if the result is of type pointer */
7736 sym_link *type = operandType (right);
7737 sym_link *etype = getSpec (type);
7739 /* pointer to generic pointer */
7740 if (IS_GENPTR (ctype))
7743 p_type = DCL_TYPE (type);
7746 if (SPEC_SCLS(etype)==S_REGISTER) {
7747 // let's assume it is a generic pointer
7750 /* we have to go by the storage class */
7751 p_type = PTR_TYPE (SPEC_OCLS (etype));
7755 /* the first two bytes are known */
7756 size = GPTRSIZE - 1;
7760 transferAopAop(AOP (right), offset, AOP (result), offset);
7763 /* the last byte depending on type */
7766 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7771 // pointerTypeToGPByte will have bitched.
7775 sprintf(gpValStr, "#0x%d", gpVal);
7776 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7782 /* just copy the pointers */
7783 size = AOP_SIZE (result);
7787 transferAopAop(AOP (right), offset, AOP (result), offset);
7793 /* so we now know that the size of destination is greater
7794 than the size of the source */
7795 /* we move to result for the size of source */
7796 size = AOP_SIZE (right);
7800 transferAopAop(AOP (right), offset, AOP (result), offset);
7804 /* now depending on the sign of the source && destination */
7805 size = AOP_SIZE (result) - AOP_SIZE (right);
7806 /* if unsigned or not an integral type */
7807 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7810 storeConstToAop (zero, AOP (result), offset++);
7814 /* we need to extend the sign :{ */
7815 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7816 accopWithMisc ("rola", "");
7817 accopWithMisc ("clra", "");
7818 accopWithMisc ("sbc", zero);
7820 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7823 /* we are done hurray !!!! */
7826 freeAsmop (right, NULL, ic, TRUE);
7827 freeAsmop (result, NULL, ic, TRUE);
7831 /*-----------------------------------------------------------------*/
7832 /* genDjnz - generate decrement & jump if not zero instrucion */
7833 /*-----------------------------------------------------------------*/
7835 genDjnz (iCode * ic, iCode * ifx)
7841 D(emitcode ("; genDjnz",""));
7843 /* if the if condition has a false label
7844 then we cannot save */
7848 /* if the minus is not of the form
7850 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7851 !IS_OP_LITERAL (IC_RIGHT (ic)))
7854 if (operandLitValue (IC_RIGHT (ic)) != 1)
7857 /* dbnz doesn't support extended mode */
7858 if (isOperandInFarSpace (IC_RESULT (ic)))
7861 /* if the size of this greater than one then no
7863 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7865 aopOp (IC_RESULT (ic), ic, FALSE);
7866 if (AOP_SIZE (IC_RESULT (ic))>1)
7868 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7872 /* otherwise we can save BIG */
7873 lbl = newiTempLabel (NULL);
7874 lbl1 = newiTempLabel (NULL);
7877 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7880 emitBranch ("bra", lbl1);
7882 emitBranch ("jmp", IC_TRUE (ifx));
7885 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7890 /*-----------------------------------------------------------------*/
7891 /* genReceive - generate code for a receive iCode */
7892 /*-----------------------------------------------------------------*/
7894 genReceive (iCode * ic)
7898 D(emitcode ("; genReceive",""));
7900 aopOp (IC_RESULT (ic), ic, FALSE);
7901 size = AOP_SIZE (IC_RESULT (ic));
7906 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7907 AOP (IC_RESULT (ic)), offset);
7908 if (hc08_aop_pass[offset]->type == AOP_REG)
7909 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7914 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7917 /*-----------------------------------------------------------------*/
7918 /* genDummyRead - generate code for dummy read of volatiles */
7919 /*-----------------------------------------------------------------*/
7921 genDummyRead (iCode * ic)
7926 D(emitcode("; genDummyRead",""));
7929 if (op && IS_SYMOP (op))
7932 aopOp (op, ic, FALSE);
7934 size = AOP_SIZE (op);
7939 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7940 hc08_freeReg (hc08_reg_a);
7944 freeAsmop (op, NULL, ic, TRUE);
7947 if (op && IS_SYMOP (op))
7950 aopOp (op, ic, FALSE);
7952 size = AOP_SIZE (op);
7957 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7958 hc08_freeReg (hc08_reg_a);
7962 freeAsmop (op, NULL, ic, TRUE);
7966 /*-----------------------------------------------------------------*/
7967 /* genCritical - generate code for start of a critical sequence */
7968 /*-----------------------------------------------------------------*/
7970 genCritical (iCode *ic)
7972 D(emitcode("; genCritical",""));
7975 aopOp (IC_RESULT (ic), ic, TRUE);
7977 emitcode ("tpa", "");
7978 hc08_dirtyReg (hc08_reg_a, FALSE);
7979 emitcode ("sei", "");
7982 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7984 pushReg (hc08_reg_a, FALSE);
7986 hc08_freeReg (hc08_reg_a);
7988 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7991 /*-----------------------------------------------------------------*/
7992 /* genEndCritical - generate code for end of a critical sequence */
7993 /*-----------------------------------------------------------------*/
7995 genEndCritical (iCode *ic)
7997 D(emitcode("; genEndCritical",""));
8001 aopOp (IC_RIGHT (ic), ic, FALSE);
8002 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8003 emitcode ("tap", "");
8004 hc08_freeReg (hc08_reg_a);
8005 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8009 pullReg (hc08_reg_a);
8010 emitcode ("tap", "");
8016 /*-----------------------------------------------------------------*/
8017 /* genhc08Code - generate code for HC08 based controllers */
8018 /*-----------------------------------------------------------------*/
8020 genhc08Code (iCode * lic)
8027 lineHead = lineCurr = NULL;
8029 /* print the allocation information */
8030 if (allocInfo && currFunc)
8031 printAllocInfo (currFunc, codeOutFile);
8032 /* if debug information required */
8033 if (options.debug && currFunc)
8035 debugFile->writeFunction (currFunc, lic);
8038 if (IS_STATIC (currFunc->etype))
8039 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8041 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8045 /* stack pointer name */
8046 if (options.useXstack)
8051 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8053 hc08_aop_pass[0] = newAsmop (AOP_REG);
8054 hc08_aop_pass[0]->size=1;
8055 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8056 hc08_aop_pass[1] = newAsmop (AOP_REG);
8057 hc08_aop_pass[1]->size=1;
8058 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8059 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8060 hc08_aop_pass[2]->size=1;
8061 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8062 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8063 hc08_aop_pass[3]->size=1;
8064 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8066 for (ic = lic; ic; ic = ic->next)
8069 _G.current_iCode = ic;
8071 if (ic->level != clevel || ic->block != cblock)
8075 debugFile->writeScope(ic);
8081 if (ic->lineno && cln != ic->lineno)
8085 debugFile->writeCLine(ic);
8088 emitcode ("", "C$%s$%d$%d$%d ==.",
8089 FileBaseName (ic->filename), ic->lineno,
8090 ic->level, ic->block);
8094 if (!options.noCcodeInAsm) {
8095 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8096 printCLine(ic->filename, ic->lineno));
8100 if (options.iCodeInAsm) {
8104 for (i=0; i<6; i++) {
8105 sprintf (®sInUse[i],
8106 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8109 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8111 /* if the result is marked as
8112 spilt and rematerializable or code for
8113 this has already been generated then
8115 if (resultRemat (ic) || ic->generated)
8123 for (i=A_IDX;i<=XA_IDX;i++)
8125 reg = hc08_regWithIdx(i);
8127 emitcode("","; %s = %s offset %d", reg->name,
8128 aopName(reg->aop), reg->aopofs);
8131 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8133 sym = OP_SYMBOL (IC_LEFT (ic));
8134 if (sym->accuse == ACCUSE_HX)
8136 hc08_reg_h->isFree = FALSE;
8137 hc08_reg_x->isFree = FALSE;
8139 else if (sym->accuse == ACCUSE_XA)
8141 hc08_reg_a->isFree = FALSE;
8143 hc08_reg_x->isFree = FALSE;
8146 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8148 sym = OP_SYMBOL (IC_RIGHT (ic));
8149 if (sym->accuse == ACCUSE_HX)
8151 hc08_reg_h->isFree = FALSE;
8152 hc08_reg_x->isFree = FALSE;
8154 else if (sym->accuse == ACCUSE_XA)
8156 hc08_reg_a->isFree = FALSE;
8158 hc08_reg_x->isFree = FALSE;
8163 /* depending on the operation */
8183 /* IPOP happens only when trying to restore a
8184 spilt live range, if there is an ifx statement
8185 following this pop then the if statement might
8186 be using some of the registers being popped which
8187 would destory the contents of the register so
8188 we need to check for this condition and handle it */
8190 ic->next->op == IFX &&
8191 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8192 genIfx (ic->next, ic);
8210 genEndFunction (ic);
8226 if (!genPointerGetSetOfs (ic))
8231 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8248 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8252 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8259 /* note these two are xlated by algebraic equivalence
8260 during parsing SDCC.y */
8261 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8262 "got '>=' or '<=' shouldn't have come here");
8266 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8278 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8282 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8286 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8313 case GET_VALUE_AT_ADDRESS:
8315 hasInc (IC_LEFT (ic), ic,
8316 getSize (operandType (IC_RESULT (ic)))),
8317 ifxForOp (IC_RESULT (ic), ic) );
8321 if (POINTER_SET (ic))
8322 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8348 addSet (&_G.sendSet, ic);
8351 case DUMMY_READ_VOLATILE:
8360 genEndCritical (ic);
8371 if (!hc08_reg_a->isFree)
8372 D(emitcode("","; forgot to free a"));
8373 if (!hc08_reg_x->isFree)
8374 D(emitcode("","; forgot to free x"));
8375 if (!hc08_reg_h->isFree)
8376 D(emitcode("","; forgot to free h"));
8377 if (!hc08_reg_hx->isFree)
8378 D(emitcode("","; forgot to free hx"));
8379 if (!hc08_reg_xa->isFree)
8380 D(emitcode("","; forgot to free xa"));
8383 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8386 /* now we are ready to call the
8387 peep hole optimizer */
8388 if (!options.nopeep)
8389 peepHole (&lineHead);
8391 /* now do the actual printing */
8392 printLine (lineHead, codeOutFile);