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 */
665 emitcode ("lda","%s", aopAdrStr (aop, loffset, FALSE));
668 if (aop->type == AOP_REG)
670 if (loffset < aop->size)
671 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
673 emitcode ("clrx", ""); /* TODO: handle sign extension */
676 emitcode ("ldx","%s", aopAdrStr (aop, loffset, FALSE));
679 if (hc08_reg_a->isFree)
681 loadRegFromAop (hc08_reg_a, aop, loffset);
682 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
684 else if (hc08_reg_x->isFree)
686 loadRegFromAop (hc08_reg_x, aop, loffset);
687 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
691 pushReg (hc08_reg_a, TRUE);
692 loadRegFromAop (hc08_reg_a, aop, loffset);
693 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
694 pullReg (hc08_reg_a);
700 else if (IS_AOP_XA(aop))
701 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
702 else if ((aop->type == AOP_DIR))
704 if (aop->size>(loffset+1))
705 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
708 loadRegFromAop (hc08_reg_x, aop, loffset);
709 loadRegFromConst (hc08_reg_h, zero);
712 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
714 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
719 needpula = pushRegIfUsed (hc08_reg_a);
720 loadRegFromAop (hc08_reg_a, aop, loffset+1);
721 loadRegFromAop (hc08_reg_x, aop, loffset);
722 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
723 pullOrFreeReg (hc08_reg_a, needpula);
729 else if (IS_AOP_HX(aop))
730 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
733 loadRegFromAop (hc08_reg_a, aop, loffset);
734 loadRegFromAop (hc08_reg_x, aop, loffset+1);
739 // ignore caching for now
742 reg->aopofs = loffset;
747 /*--------------------------------------------------------------------------*/
748 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
749 /* freeAsmop is called with aop, the stacked data will */
750 /* be copied to the original aop location and */
751 /*--------------------------------------------------------------------------*/
753 forceStackedAop (asmop *aop)
756 asmop *newaop = newAsmop (aop->type);
757 memcpy (newaop, aop, sizeof(*newaop));
759 D(emitcode("", "; forcedStackAop %s", aopName(aop)));
760 for (loffset=0; loffset < newaop->size; loffset++)
762 asmop *aopsof = newAsmop (AOP_SOF);
764 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
765 aopsof->op = aop->op;
766 newaop->stk_aop[loffset] = aopsof;
773 /*--------------------------------------------------------------------------*/
774 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
775 /*--------------------------------------------------------------------------*/
777 storeRegToAop (regs *reg, asmop *aop, int loffset)
779 int regidx = reg->rIdx;
785 D(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
786 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
788 if ((reg->rIdx == HX_IDX) && aop->stacked
789 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
791 storeRegToAop (hc08_reg_h, aop, loffset+1);
792 storeRegToAop (hc08_reg_x, aop, loffset);
796 if ((reg->rIdx == XA_IDX) && aop->stacked
797 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
799 storeRegToAop (hc08_reg_x, aop, loffset+1);
800 storeRegToAop (hc08_reg_a, aop, loffset);
804 if (aop->stacked && aop->stk_aop[loffset])
806 storeRegToAop (reg, aop->stk_aop[loffset], 0);
810 if (aop->type == AOP_STR)
813 transferRegReg (reg, hc08_reg_x, FALSE);
815 transferRegReg (reg, hc08_reg_h, FALSE);
819 if (aop->type == AOP_DUMMY)
825 if ((aop->type == AOP_REG) && (loffset < aop->size))
826 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
828 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
831 if ((aop->type == AOP_REG) && (loffset < aop->size))
832 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
834 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
837 if (hc08_reg_a->isFree)
839 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
840 storeRegToAop (hc08_reg_a, aop, loffset);
841 hc08_freeReg (hc08_reg_a);
843 else if (hc08_reg_x->isFree)
845 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
846 storeRegToAop (hc08_reg_x, aop, loffset);
847 hc08_freeReg (hc08_reg_x);
851 pushReg (hc08_reg_a, TRUE);
852 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
853 storeRegToAop (hc08_reg_a, aop, loffset);
854 pullReg (hc08_reg_a);
858 if ((aop->type == AOP_DIR) )
860 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
862 else if (IS_AOP_XA(aop))
863 transferRegReg(reg, hc08_reg_xa, FALSE);
864 else if (IS_AOP_HX(aop))
869 needpula = pushRegIfUsed (hc08_reg_a);
870 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
871 storeRegToAop (hc08_reg_a, aop, loffset+1);
872 storeRegToAop (hc08_reg_x, aop, loffset);
873 pullOrFreeReg (hc08_reg_a, needpula);
878 transferRegReg(reg, hc08_reg_hx, FALSE);
879 else if (IS_AOP_XA(aop))
883 storeRegToAop (hc08_reg_a, aop, loffset);
884 storeRegToAop (hc08_reg_x, aop, loffset+1);
889 /* Disable the register tracking for now */
891 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
894 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
896 otherreg=hc08_regWithIdx(otheridx);
897 if (otherreg && otherreg->aop
898 && otherreg->aop->op && aop->op
899 && operandsEqu(otherreg->aop->op,aop->op)
900 && (otherreg->aopofs == loffset))
902 D(emitcode("","; marking %s stale", otherreg->name));
906 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
908 hc08_reg_hx->aop = NULL;
909 D(emitcode("","; marking hx stale"));
911 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
913 hc08_reg_xa->aop = NULL;
914 D(emitcode("","; marking xa stale"));
918 reg->aopofs = loffset;
923 /*--------------------------------------------------------------------------*/
924 /* loadRegFromConst - Load register reg from constant c. */
925 /*--------------------------------------------------------------------------*/
927 loadRegFromConst (regs *reg, char *c)
933 emitcode ("clra", "");
935 emitcode ("lda", "%s", c);
939 emitcode ("clrx", "");
941 emitcode ("ldx", "%s", c);
945 emitcode ("clrh", "");
946 else if (hc08_reg_a->isFree)
948 loadRegFromConst (hc08_reg_a, c);
949 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
951 else if (hc08_reg_x->isFree)
953 loadRegFromConst (hc08_reg_x, c);
954 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
958 pushReg (hc08_reg_a, TRUE);
959 loadRegFromConst (hc08_reg_a, c);
960 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
961 pullReg (hc08_reg_a);
965 emitcode ("ldhx", "%s", c);
968 emitcode ("lda", "%s", c);
969 emitcode ("ldx", "%s >> 8", c);
972 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
973 "Bad rIdx in loadRegFromConst");
980 /*--------------------------------------------------------------------------*/
981 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
982 /*--------------------------------------------------------------------------*/
984 storeConstToAop (char *c, asmop *aop, int loffset)
986 if (aop->stacked && aop->stk_aop[loffset])
988 storeConstToAop (c, aop->stk_aop[loffset], 0);
996 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
998 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
1001 if (loffset>(aop->size-1))
1003 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
1008 if (hc08_reg_a->isFree)
1010 loadRegFromConst (hc08_reg_a, c);
1011 storeRegToAop( hc08_reg_a, aop, loffset);
1012 hc08_freeReg (hc08_reg_a);
1014 else if (hc08_reg_x->isFree)
1016 loadRegFromConst (hc08_reg_x, c);
1017 storeRegToAop( hc08_reg_x, aop, loffset);
1018 hc08_freeReg (hc08_reg_x);
1022 pushReg (hc08_reg_a, TRUE);
1023 loadRegFromConst (hc08_reg_a, c);
1024 storeRegToAop( hc08_reg_a, aop, loffset);
1025 pullReg (hc08_reg_a);
1031 /*--------------------------------------------------------------------------*/
1032 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
1033 /* reg is extended to fill logical offsets loffset */
1034 /* and above of asmop aop. Otherwise, logical */
1035 /* offsets loffset and above of asmop aop are */
1036 /* zeroed. reg must be an 8-bit register. */
1037 /*--------------------------------------------------------------------------*/
1039 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
1041 // int regidx = reg->rIdx;
1042 int size = aop->size;
1050 while (loffset<size)
1051 storeConstToAop(zero, aop, loffset++);
1056 transferRegReg (reg, hc08_reg_a, FALSE);
1057 emitcode ("rola","");
1058 emitcode ("clra","");
1059 emitcode ("sbc", "#0");
1060 hc08_useReg (hc08_reg_a);
1061 while (loffset<size)
1062 storeRegToAop (hc08_reg_a, aop, loffset++);
1063 hc08_freeReg (hc08_reg_a);
1067 /*--------------------------------------------------------------------------*/
1068 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1069 /* padding and/or truncation as needed. If isSigned is */
1070 /* true, sign extension will take place in the padding. */
1071 /*--------------------------------------------------------------------------*/
1073 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1075 int regidx = reg->rIdx;
1076 int size = aop->size;
1083 storeRegToAop (reg, aop, 0);
1084 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1089 storeRegToAop (hc08_reg_x, aop, 0);
1093 storeRegToAop (reg, aop, 0);
1094 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1100 storeRegToAop (hc08_reg_a, aop, 0);
1104 storeRegToAop (reg, aop, 0);
1105 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1111 /*--------------------------------------------------------------------------*/
1112 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1113 /* srcaop to logical offset dstofs of asmop dstofs. */
1114 /*--------------------------------------------------------------------------*/
1116 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1118 bool needpula = FALSE;
1121 bool keepreg = FALSE;
1123 /* ignore transfers at the same byte, unless its volatile */
1124 if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
1125 && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
1126 && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs)
1129 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1131 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1135 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1137 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1141 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1142 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1143 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1144 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1146 if (dstofs >= dstaop->size)
1149 if ((dstaop->type == AOP_DIR)
1150 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1152 if (srcaop->type == AOP_LIT)
1155 unsigned char bytemask;
1157 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1158 bytemask = (lit >> (srcofs*8)) & 0xff;
1162 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1167 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1168 aopAdrStr(dstaop, dstofs, FALSE));
1172 if (dstaop->type == AOP_REG)
1174 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1175 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1177 reg = dstaop->aopu.aop_reg[dstofs];
1182 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1184 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1185 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1187 reg = srcaop->aopu.aop_reg[srcofs];
1194 if (hc08_reg_a->isFree)
1196 else if (hc08_reg_x->isFree)
1200 pushReg (hc08_reg_a, TRUE);
1206 loadRegFromAop (reg, srcaop, srcofs);
1207 storeRegToAop (reg, dstaop, dstofs);
1210 pullOrFreeReg (hc08_reg_a, needpula);
1214 /*--------------------------------------------------------------------------*/
1215 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1216 /* parameter param. */
1217 /*--------------------------------------------------------------------------*/
1219 accopWithMisc (char *accop, char *param)
1221 emitcode (accop, "%s", param);
1222 hc08_dirtyReg (hc08_reg_a, FALSE);
1225 /*--------------------------------------------------------------------------*/
1226 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1227 /* byte at logical offset loffset of asmop aop. */
1228 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1229 /*--------------------------------------------------------------------------*/
1231 accopWithAop (char *accop, asmop *aop, int loffset)
1233 if (aop->stacked && aop->stk_aop[loffset])
1235 accopWithAop (accop, aop->stk_aop[loffset], 0);
1239 if (aop->type == AOP_DUMMY)
1242 if (aop->type == AOP_REG)
1244 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1245 emitcode (accop, "1,s");
1249 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1251 hc08_dirtyReg (hc08_reg_a, FALSE);
1255 /*--------------------------------------------------------------------------*/
1256 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1257 /* byte at logical offset loffset of asmop aop. Register reg */
1258 /* must be 8-bit. */
1259 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1260 /*--------------------------------------------------------------------------*/
1262 rmwWithReg (char *rmwop, regs *reg)
1265 char *rmwaop = rmwbuf;
1267 if (reg->rIdx == A_IDX)
1269 sprintf(rmwaop,"%sa", rmwop);
1270 emitcode (rmwaop, "");
1271 hc08_dirtyReg (hc08_reg_a, FALSE);
1273 else if (reg->rIdx == X_IDX)
1275 sprintf(rmwaop,"%sx", rmwop);
1276 emitcode (rmwaop, "");
1277 hc08_dirtyReg (hc08_reg_a, FALSE);
1279 else if (hc08_reg_a->isFree)
1281 transferRegReg(reg, hc08_reg_a, FALSE);
1282 sprintf(rmwaop,"%sa", rmwop);
1283 emitcode (rmwaop, "");
1284 hc08_dirtyReg (hc08_reg_a, FALSE);
1285 transferRegReg(hc08_reg_a, reg, TRUE);
1289 pushReg (reg, FALSE);
1290 emitcode (rmwop, "1,s");
1292 hc08_dirtyReg (reg, FALSE);
1296 /*--------------------------------------------------------------------------*/
1297 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1298 /* logical offset loffset of asmop aop. */
1299 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1300 /*--------------------------------------------------------------------------*/
1302 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1304 bool needpula = FALSE;
1306 if (aop->stacked && aop->stk_aop[loffset])
1308 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1315 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1318 needpula = pushRegIfUsed (hc08_reg_a);
1319 loadRegFromAop (hc08_reg_a, aop, loffset);
1320 rmwWithReg (rmwop, hc08_reg_a);
1321 if (strcmp ("tst", rmwop))
1322 storeRegToAop (hc08_reg_a, aop, loffset);
1323 pullOrFreeReg (hc08_reg_a, needpula);
1328 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1334 /*-----------------------------------------------------------------*/
1335 /* newAsmop - creates a new asmOp */
1336 /*-----------------------------------------------------------------*/
1338 newAsmop (short type)
1342 aop = Safe_calloc (1, sizeof (asmop));
1349 /*-----------------------------------------------------------------*/
1350 /* pointerCode - returns the code for a pointer type */
1351 /*-----------------------------------------------------------------*/
1353 pointerCode (sym_link * etype)
1356 return PTR_TYPE (SPEC_OCLS (etype));
1361 /*-----------------------------------------------------------------*/
1362 /* aopForSym - for a true symbol */
1363 /*-----------------------------------------------------------------*/
1365 aopForSym (iCode * ic, symbol * sym, bool result)
1370 wassertl (ic != NULL, "Got a null iCode");
1371 wassertl (sym != NULL, "Got a null symbol");
1373 // printf("in aopForSym for symbol %s\n", sym->name);
1375 space = SPEC_OCLS (sym->etype);
1377 /* if already has one */
1383 /* special case for a function */
1384 if (IS_FUNC (sym->type))
1386 sym->aop = aop = newAsmop (AOP_IMMD);
1387 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1388 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1389 aop->size = FPTRSIZE;
1393 /* if it is in direct space */
1394 if (IN_DIRSPACE (space))
1396 sym->aop = aop = newAsmop (AOP_DIR);
1397 aop->aopu.aop_dir = sym->rname;
1398 aop->size = getSize (sym->type);
1402 /* if it is in far space */
1403 if (IN_FARSPACE (space))
1405 sym->aop = aop = newAsmop (AOP_EXT);
1406 aop->aopu.aop_dir = sym->rname;
1407 aop->size = getSize (sym->type);
1411 if (IN_STACK (sym->etype))
1413 sym->aop = aop = newAsmop (AOP_SOF);
1414 aop->aopu.aop_dir = sym->rname;
1415 aop->size = getSize (sym->type);
1416 aop->aopu.aop_stk = sym->stack;
1422 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1423 "aopForSym should never reach here");
1427 /* if it is in code space */
1428 if (IN_CODESPACE (space))
1434 /*-----------------------------------------------------------------*/
1435 /* aopForRemat - rematerialzes an object */
1436 /*-----------------------------------------------------------------*/
1438 aopForRemat (symbol * sym)
1440 iCode *ic = sym->rematiCode;
1448 val += (int) operandLitValue (IC_RIGHT (ic));
1449 else if (ic->op == '-')
1450 val -= (int) operandLitValue (IC_RIGHT (ic));
1451 else if (IS_CAST_ICODE(ic)) {
1452 sym_link *from_type = operandType(IC_RIGHT(ic));
1453 aop->aopu.aop_immd.from_cast_remat = 1;
1454 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1455 ptr_type = DCL_TYPE(from_type);
1456 if (ptr_type == IPOINTER) {
1463 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1466 if (ic->op == ADDRESS_OF)
1469 sprintf (buffer, "(%s %c 0x%04x)",
1470 OP_SYMBOL (IC_LEFT (ic))->rname,
1471 val >= 0 ? '+' : '-',
1472 abs (val) & 0xffff);
1474 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1476 aop = newAsmop (AOP_IMMD);
1477 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1478 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1479 /* set immd2 field if required */
1480 if (aop->aopu.aop_immd.from_cast_remat)
1482 sprintf(buffer,"#0x%02x",ptr_type);
1483 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1484 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1487 else if (ic->op == '=')
1489 val += (int) operandLitValue (IC_RIGHT (ic));
1491 sprintf (buffer, "0x%04x", val);
1492 aop = newAsmop (AOP_LIT);
1493 aop->aopu.aop_lit = constVal (buffer);
1496 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1497 "unexpected rematerialization");
1504 /*-----------------------------------------------------------------*/
1505 /* regsInCommon - two operands have some registers in common */
1506 /*-----------------------------------------------------------------*/
1508 regsInCommon (operand * op1, operand * op2)
1510 symbol *sym1, *sym2;
1513 /* if they have registers in common */
1514 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1517 sym1 = OP_SYMBOL (op1);
1518 sym2 = OP_SYMBOL (op2);
1520 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1523 for (i = 0; i < sym1->nRegs; i++)
1529 for (j = 0; j < sym2->nRegs; j++)
1534 if (sym2->regs[j] == sym1->regs[i])
1542 /*-----------------------------------------------------------------*/
1543 /* operandsEqu - equivalent */
1544 /*-----------------------------------------------------------------*/
1546 operandsEqu (operand * op1, operand * op2)
1548 symbol *sym1, *sym2;
1550 /* if they not symbols */
1551 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1554 sym1 = OP_SYMBOL (op1);
1555 sym2 = OP_SYMBOL (op2);
1557 /* if both are itemps & one is spilt
1558 and the other is not then false */
1559 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1560 sym1->isspilt != sym2->isspilt)
1563 /* if they are the same */
1567 if (sym1->rname[0] && sym2->rname[0]
1568 && strcmp (sym1->rname, sym2->rname) == 0)
1571 /* if left is a tmp & right is not */
1572 if (IS_ITEMP (op1) &&
1575 (sym1->usl.spillLoc == sym2))
1578 if (IS_ITEMP (op2) &&
1582 (sym2->usl.spillLoc == sym1))
1588 /*-----------------------------------------------------------------*/
1589 /* sameRegs - two asmops have the same registers */
1590 /*-----------------------------------------------------------------*/
1592 sameRegs (asmop * aop1, asmop * aop2)
1599 // if (aop1->size != aop2->size)
1602 if (aop1->type == aop2->type)
1607 for (i = 0; i < aop1->size; i++)
1608 if (aop1->aopu.aop_reg[i] !=
1609 aop2->aopu.aop_reg[i])
1613 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1616 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1623 /*-----------------------------------------------------------------*/
1624 /* aopOp - allocates an asmop for an operand : */
1625 /*-----------------------------------------------------------------*/
1627 aopOp (operand * op, iCode * ic, bool result)
1636 // Is this a pointer set result?
1638 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1642 // printf("checking literal\n");
1643 /* if this a literal */
1644 if (IS_OP_LITERAL (op))
1646 op->aop = aop = newAsmop (AOP_LIT);
1647 aop->aopu.aop_lit = op->operand.valOperand;
1648 aop->size = getSize (operandType (op));
1650 aop->isaddr = op->isaddr;
1654 // printf("checking pre-existing\n");
1655 /* if already has a asmop then continue */
1659 op->aop->isaddr = op->isaddr;
1663 // printf("checking underlying sym\n");
1664 /* if the underlying symbol has a aop */
1665 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1667 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1668 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1669 //op->aop = aop = OP_SYMBOL (op)->aop;
1670 aop->size = getSize( operandType (op));
1671 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1672 //printf (" with size = %d\n", aop->size);
1675 aop->isaddr = op->isaddr;
1676 /* if (aop->isaddr & IS_ITEMP (op))
1678 aop->psize=aop->size;
1679 aop->size = getSize( operandType (op)->next);
1684 // printf("checking true sym\n");
1685 /* if this is a true symbol */
1686 if (IS_TRUE_SYMOP (op))
1688 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1690 aop->isaddr = op->isaddr;
1691 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1692 //printf (" with size = %d\n", aop->size);
1696 /* this is a temporary : this has
1702 e) can be a return use only */
1704 sym = OP_SYMBOL (op);
1706 // printf("checking conditional\n");
1707 /* if the type is a conditional */
1708 if (sym->regType == REG_CND)
1710 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1713 aop->isaddr = op->isaddr;
1717 // printf("checking spilt\n");
1718 /* if it is spilt then two situations
1720 b) has a spill location */
1721 if (sym->isspilt || sym->nRegs == 0)
1724 // printf("checking remat\n");
1725 /* rematerialize it NOW */
1728 sym->aop = op->aop = aop =
1730 aop->size = getSize (sym->type);
1732 aop->isaddr = op->isaddr;
1733 /* if (aop->isaddr & IS_ITEMP (op))
1735 aop->psize=aop->size;
1736 aop->size = getSize( operandType (op)->next);
1741 // printf("checking accuse\n");
1744 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1745 aop->size = getSize (sym->type);
1746 switch (sym->accuse)
1749 aop->aopu.aop_reg[0] = hc08_reg_a;
1750 aop->aopu.aop_reg[1] = hc08_reg_x;
1753 aop->aopu.aop_reg[0] = hc08_reg_x;
1754 aop->aopu.aop_reg[1] = hc08_reg_h;
1758 aop->isaddr = op->isaddr;
1762 // printf("checking ruonly\n");
1768 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1769 aop->size = getSize (sym->type);
1770 for (i = 0; i < fReturnSizeHC08; i++)
1771 aop->aopu.aop_str[i] = fReturn2[i];
1773 aop->isaddr = op->isaddr;
1777 /* else spill location */
1778 if (sym->usl.spillLoc)
1780 if (sym->usl.spillLoc->aop
1781 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1783 /* force a new aop if sizes differ */
1784 sym->usl.spillLoc->aop = NULL;
1785 //printf ("forcing new aop\n");
1787 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1788 aop->size = getSize (sym->type);
1790 aop->isaddr = op->isaddr;
1791 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1792 //printf (" with size = %d\n", aop->size);
1796 /* else must be a dummy iTemp */
1797 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1798 aop->size = getSize (sym->type);
1802 // printf("assuming register\n");
1803 /* must be in a register */
1804 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1805 aop->size = sym->nRegs;
1806 for (i = 0; i < sym->nRegs; i++)
1807 aop->aopu.aop_reg[i] = sym->regs[i];
1809 aop->isaddr = op->isaddr;
1813 /*-----------------------------------------------------------------*/
1814 /* freeAsmop - free up the asmop given to an operand */
1815 /*----------------------------------------------------------------*/
1817 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1839 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1842 for (loffset=0; loffset<aop->size; loffset++)
1843 if (aop->stk_aop[loffset])
1845 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1848 pullNull (stackAdjust);
1852 /* all other cases just dealloc */
1858 OP_SYMBOL (op)->aop = NULL;
1859 /* if the symbol has a spill */
1861 SPIL_LOC (op)->aop = NULL;
1867 /*-----------------------------------------------------------------*/
1868 /* aopDerefAop - treating the aop parameter as a pointer, return */
1869 /* an asmop for the object it references */
1870 /*-----------------------------------------------------------------*/
1872 aopDerefAop (asmop *aop)
1877 asmop *newaop = NULL;
1878 sym_link *type, *etype;
1881 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1885 type = operandType (aop->op);
1886 etype = getSpec (type);
1887 /* if op is of type of pointer then it is simple */
1888 if (IS_PTR (type) && !IS_FUNC (type->next))
1889 p_type = DCL_TYPE (type);
1892 /* we have to go by the storage class */
1893 p_type = PTR_TYPE (SPEC_OCLS (etype));
1902 if (p_type == POINTER)
1903 newaop = newAsmop (AOP_DIR);
1905 newaop = newAsmop (AOP_EXT);
1906 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1909 adr = (int) floatFromVal (aop->aopu.aop_lit);
1910 if (p_type == POINTER)
1915 newaop = newAsmop (AOP_DIR);
1916 sprintf (s, "0x%02x",adr);
1920 newaop = newAsmop (AOP_EXT);
1921 sprintf (s, "0x%04x",adr);
1923 rs = Safe_calloc (1, strlen (s) + 1);
1925 newaop->aopu.aop_dir = rs;
1928 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1929 "unsupported asmop");
1939 /*-----------------------------------------------------------------*/
1940 /* aopAdrStr - for referencing the address of the aop */
1941 /*-----------------------------------------------------------------*/
1943 aopAdrStr (asmop * aop, int loffset, bool bit16)
1947 int offset = aop->size - 1 - loffset;
1950 /* offset is greater than
1952 if (loffset > (aop->size - 1) &&
1953 aop->type != AOP_LIT)
1956 /* depending on type */
1964 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1965 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1967 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1971 sprintf (s, "#(%s >> %d)",
1972 aop->aopu.aop_immd.aop_immd1,
1976 aop->aopu.aop_immd.aop_immd1);
1980 aop->aopu.aop_immd.aop_immd1);
1981 rs = Safe_calloc (1, strlen (s) + 1);
1987 sprintf (s, "*(%s + %d)",
1991 sprintf (s, "*%s", aop->aopu.aop_dir);
1992 rs = Safe_calloc (1, strlen (s) + 1);
1998 sprintf (s, "(%s + %d)",
2002 sprintf (s, "%s", aop->aopu.aop_dir);
2003 rs = Safe_calloc (1, strlen (s) + 1);
2008 return aop->aopu.aop_reg[loffset]->name;
2012 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2014 return aopLiteral (aop->aopu.aop_lit, loffset);
2018 return aop->aopu.aop_str[loffset];
2021 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2023 rs = Safe_calloc (1, strlen (s) + 1);
2029 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2030 "aopAdrStr got unsupported aop->type");
2039 /*-----------------------------------------------------------------*/
2040 /* opIsGptr: returns non-zero if the passed operand is */
2041 /* a generic pointer type. */
2042 /*-----------------------------------------------------------------*/
2044 opIsGptr (operand * op)
2046 sym_link *type = operandType (op);
2048 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2056 /*-----------------------------------------------------------------*/
2057 /* getDataSize - get the operand data size */
2058 /*-----------------------------------------------------------------*/
2060 getDataSize (operand * op)
2063 size = AOP_SIZE (op);
2067 /*-----------------------------------------------------------------*/
2068 /* outAcc - output Acc */
2069 /*-----------------------------------------------------------------*/
2071 outAcc (operand * result)
2074 size = getDataSize (result);
2077 storeRegToAop (hc08_reg_a, AOP (result), 0);
2080 /* unsigned or positive */
2083 storeConstToAop (zero, AOP (result), offset++);
2088 /*-----------------------------------------------------------------*/
2089 /* outBitC - output a bit C */
2090 /*-----------------------------------------------------------------*/
2092 outBitC (operand * result)
2096 /* if the result is bit */
2097 if (AOP_TYPE (result) == AOP_CRY)
2098 aopPut (AOP (result), "c", 0);
2102 emitcode ("clra", "");
2103 emitcode ("rola", "");
2108 /*-----------------------------------------------------------------*/
2109 /* outBitNV - output a bit N^V */
2110 /*-----------------------------------------------------------------*/
2112 outBitNV (operand * result)
2114 symbol *tlbl, *tlbl1;
2116 tlbl = newiTempLabel (NULL);
2117 tlbl1 = newiTempLabel (NULL);
2119 emitBranch ("blt", tlbl);
2120 loadRegFromConst (hc08_reg_a, zero);
2121 emitBranch ("bra", tlbl1);
2123 loadRegFromConst (hc08_reg_a, one);
2129 /*-----------------------------------------------------------------*/
2130 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2131 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2132 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2133 /*-----------------------------------------------------------------*/
2135 asmopToBool (asmop *aop, bool resultInA)
2137 symbol *tlbl, *tlbl1;
2138 int size = aop->size;
2139 bool needpula = FALSE;
2140 bool flagsonly = TRUE;
2145 hc08_freeReg(hc08_reg_a);
2152 emitcode ("tsta", "");
2155 else if (IS_AOP_X(aop))
2156 emitcode ("tstx", "");
2157 else if (IS_AOP_H(aop))
2159 if (hc08_reg_a->isFree)
2161 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2162 emitcode ("tsta", "");
2164 hc08_freeReg(hc08_reg_a);
2166 else if (hc08_reg_x->isFree)
2168 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2169 emitcode ("tstx", "");
2170 hc08_freeReg(hc08_reg_x);
2174 emitcode ("pshh", "");
2175 emitcode ("tst", "1,s");
2176 emitcode ("ais", "#1");
2179 else if (IS_AOP_HX(aop))
2180 emitcode ("cphx", zero);
2181 else if (IS_AOP_XA(aop))
2183 symbol *tlbl = newiTempLabel (NULL);
2184 emitcode ("tsta", "");
2185 emitcode ("bne", "%05d$", (tlbl->key + 100));
2186 emitcode ("tstx", "");
2187 emitcode ("", "%05d$:", (tlbl->key + 100));
2191 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2192 "Bad rIdx in asmToBool");
2200 needpula = pushRegIfUsed (hc08_reg_a);
2201 loadRegFromAop (hc08_reg_a, aop, 0);
2202 for (offset=1; offset<size; offset++)
2203 accopWithAop ("ora", aop, offset);
2205 pullReg (hc08_reg_a);
2208 hc08_freeReg (hc08_reg_a);
2217 loadRegFromAop (hc08_reg_a, aop, 0);
2218 hc08_freeReg (hc08_reg_a);
2222 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2227 if (hc08_reg_a->isFree)
2229 loadRegFromAop (hc08_reg_a, aop, 0);
2230 accopWithAop ("ora", aop, 1);
2231 hc08_freeReg (hc08_reg_a);
2236 tlbl = newiTempLabel (NULL);
2237 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2238 emitcode ("bne", "%05d$", (tlbl->key + 100));
2239 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2240 emitcode ("", "%05d$:", (tlbl->key + 100));
2246 needpula = pushRegIfUsed (hc08_reg_a);
2247 loadRegFromAop (hc08_reg_a, aop, 0);
2248 for (offset=1; offset<size; offset++)
2249 accopWithAop ("ora", aop, offset);
2251 pullReg (hc08_reg_a);
2254 hc08_freeReg (hc08_reg_a);
2262 tlbl = newiTempLabel (NULL);
2266 tlbl1 = newiTempLabel (NULL);
2267 emitBranch ("bne", tlbl1);
2268 loadRegFromConst (hc08_reg_a, zero);
2269 emitBranch ("bra", tlbl);
2271 loadRegFromConst (hc08_reg_a, one);
2275 emitBranch ("beq", tlbl);
2276 loadRegFromConst (hc08_reg_a, one);
2279 hc08_useReg (hc08_reg_a);
2285 /*-----------------------------------------------------------------*/
2286 /* genNot - generate code for ! operation */
2287 /*-----------------------------------------------------------------*/
2291 D(emitcode ("; genNot",""));
2293 /* assign asmOps to operand & result */
2294 aopOp (IC_LEFT (ic), ic, FALSE);
2295 aopOp (IC_RESULT (ic), ic, TRUE);
2297 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2298 emitcode ("eor", one);
2299 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2301 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2302 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2306 /*-----------------------------------------------------------------*/
2307 /* genCpl - generate code for complement */
2308 /*-----------------------------------------------------------------*/
2314 regs* reg = hc08_reg_a;
2318 D(emitcode ("; genCpl",""));
2320 /* assign asmOps to operand & result */
2321 aopOp (IC_LEFT (ic), ic, FALSE);
2322 aopOp (IC_RESULT (ic), ic, TRUE);
2324 size = AOP_SIZE (IC_RESULT (ic));
2327 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2328 rmwWithReg ("com", reg);
2330 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2335 /* release the aops */
2336 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2337 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2340 /*-----------------------------------------------------------------*/
2341 /* genUminusFloat - unary minus for floating points */
2342 /*-----------------------------------------------------------------*/
2344 genUminusFloat (operand * op, operand * result)
2346 int size, offset = 0;
2349 D(emitcode ("; genUminusFloat",""));
2351 /* for this we just copy and then flip the bit */
2353 size = AOP_SIZE (op) - 1;
2357 transferAopAop (AOP (op), offset, AOP (result), offset);
2361 needpula = pushRegIfUsed (hc08_reg_a);
2362 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2363 emitcode ("eor", "#0x80");
2364 hc08_useReg (hc08_reg_a);
2365 storeRegToAop (hc08_reg_a, AOP (result), offset);
2366 pullOrFreeReg (hc08_reg_a, needpula);
2369 /*-----------------------------------------------------------------*/
2370 /* genUminus - unary minus code generation */
2371 /*-----------------------------------------------------------------*/
2373 genUminus (iCode * ic)
2376 sym_link *optype, *rtype;
2381 D(emitcode ("; genUminus",""));
2384 aopOp (IC_LEFT (ic), ic, FALSE);
2385 aopOp (IC_RESULT (ic), ic, TRUE);
2387 optype = operandType (IC_LEFT (ic));
2388 rtype = operandType (IC_RESULT (ic));
2390 /* if float then do float stuff */
2391 if (IS_FLOAT (optype))
2393 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2397 /* otherwise subtract from zero */
2398 size = AOP_SIZE (IC_LEFT (ic));
2403 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2404 needpula = pushRegIfUsed (hc08_reg_a);
2407 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2408 emitcode ("nega", "");
2409 hc08_freeReg (hc08_reg_a);
2410 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2411 SPEC_USIGN (operandType (IC_LEFT (ic))));
2412 pullOrFreeReg (hc08_reg_a, needpula);
2416 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2417 result = forceStackedAop (AOP (IC_RESULT (ic)));
2419 result = AOP (IC_RESULT (ic));
2421 needpula = pushRegIfUsed (hc08_reg_a);
2425 loadRegFromConst (hc08_reg_a, zero);
2426 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2427 storeRegToAop (hc08_reg_a, result, offset++);
2430 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2431 SPEC_USIGN (operandType (IC_LEFT (ic))));
2432 pullOrFreeReg (hc08_reg_a, needpula);
2434 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2435 freeAsmop (NULL, result, ic, TRUE);
2441 /* release the aops */
2442 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2443 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2446 /*-----------------------------------------------------------------*/
2447 /* saveRegisters - will look for a call and save the registers */
2448 /*-----------------------------------------------------------------*/
2450 saveRegisters (iCode * lic)
2457 for (ic = lic; ic; ic = ic->next)
2458 if (ic->op == CALL || ic->op == PCALL)
2463 fprintf (stderr, "found parameter push with no function call\n");
2467 /* if the registers have been saved already or don't need to be then
2471 if (IS_SYMOP(IC_LEFT(ic)) &&
2472 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2473 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2476 /* safe the registers in use at this time but skip the
2477 ones for the result */
2478 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2479 hc08_rUmaskForOp (IC_RESULT(ic)));
2482 for (i = 0; i < hc08_nRegs; i++)
2484 if (bitVectBitValue (rsave, i))
2485 pushReg ( hc08_regWithIdx (i), FALSE);
2489 /*-----------------------------------------------------------------*/
2490 /* unsaveRegisters - pop the pushed registers */
2491 /*-----------------------------------------------------------------*/
2493 unsaveRegisters (iCode * ic)
2498 /* restore the registers in use at this time but skip the
2499 ones for the result */
2500 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2501 hc08_rUmaskForOp (IC_RESULT(ic)));
2503 for (i = hc08_nRegs; i >= 0; i--)
2505 if (bitVectBitValue (rsave, i))
2506 pullReg ( hc08_regWithIdx (i));
2512 /*-----------------------------------------------------------------*/
2514 /*-----------------------------------------------------------------*/
2516 pushSide (operand * oper, int size)
2521 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2522 pushReg ( hc08_reg_a, TRUE);
2526 /*-----------------------------------------------------------------*/
2527 /* assignResultValue - */
2528 /*-----------------------------------------------------------------*/
2530 assignResultValue (operand * oper)
2532 int size = AOP_SIZE (oper);
2536 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2537 if (hc08_aop_pass[offset]->type == AOP_REG)
2538 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2545 /*-----------------------------------------------------------------*/
2546 /* genIpush - genrate code for pushing this gets a little complex */
2547 /*-----------------------------------------------------------------*/
2549 genIpush (iCode * ic)
2551 int size, offset = 0;
2554 D(emitcode ("; genIpush",""));
2556 /* if this is not a parm push : ie. it is spill push
2557 and spill push is always done on the local stack */
2561 /* and the item is spilt then do nothing */
2562 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2565 aopOp (IC_LEFT (ic), ic, FALSE);
2566 size = AOP_SIZE (IC_LEFT (ic));
2568 /* push it on the stack */
2571 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2572 pushReg ( hc08_reg_a, TRUE);
2578 /* this is a paramter push: in this case we call
2579 the routine to find the call and save those
2580 registers that need to be saved */
2583 /* then do the push */
2584 aopOp (IC_LEFT (ic), ic, FALSE);
2587 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2588 size = AOP_SIZE (IC_LEFT (ic));
2591 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2592 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2594 if ((size==2) && hc08_reg_hx->isFree)
2596 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2597 pushReg (hc08_reg_hx, TRUE);
2604 // printf("loading %d\n", offset);
2605 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2606 // printf("pushing \n");
2607 pushReg (hc08_reg_a, TRUE);
2611 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2614 /*-----------------------------------------------------------------*/
2615 /* genIpop - recover the registers: can happen only for spilling */
2616 /*-----------------------------------------------------------------*/
2618 genIpop (iCode * ic)
2622 D(emitcode ("; genIpop",""));
2624 /* if the temp was not pushed then */
2625 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2628 aopOp (IC_LEFT (ic), ic, FALSE);
2629 size = AOP_SIZE (IC_LEFT (ic));
2633 pullReg (hc08_reg_a);
2634 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2636 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2640 /*-----------------------------------------------------------------*/
2641 /* genSend - gen code for SEND */
2642 /*-----------------------------------------------------------------*/
2643 static void genSend(set *sendSet)
2647 for (sic = setFirstItem (sendSet); sic;
2648 sic = setNextItem (sendSet)) {
2649 int size, offset = 0;
2650 aopOp (IC_LEFT (sic), sic, FALSE);
2651 size = AOP_SIZE (IC_LEFT (sic));
2656 transferAopAop( AOP (IC_LEFT (sic)), offset,
2657 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2661 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2665 /*-----------------------------------------------------------------*/
2666 /* genCall - generates a call statement */
2667 /*-----------------------------------------------------------------*/
2669 genCall (iCode * ic)
2672 // bool restoreBank = FALSE;
2673 // bool swapBanks = FALSE;
2675 D(emitcode("; genCall",""));
2677 dtype = operandType (IC_LEFT (ic));
2678 /* if send set is not empty the assign */
2681 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2682 genSend(reverseSet(_G.sendSet));
2684 genSend(_G.sendSet);
2690 /* if caller saves & we have not saved then */
2696 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2697 OP_SYMBOL (IC_LEFT (ic))->rname :
2698 OP_SYMBOL (IC_LEFT (ic))->name));
2701 /* if we need assign a result value */
2702 if ((IS_ITEMP (IC_RESULT (ic)) &&
2703 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2704 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2705 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2706 IS_TRUE_SYMOP (IC_RESULT (ic)))
2710 aopOp (IC_RESULT (ic), ic, FALSE);
2713 assignResultValue (IC_RESULT (ic));
2715 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2718 /* adjust the stack for parameters if
2722 pullNull (ic->parmBytes);
2725 /* if we had saved some registers then unsave them */
2726 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2727 unsaveRegisters (ic);
2731 /*-----------------------------------------------------------------*/
2732 /* -10l - generates a call by pointer statement */
2733 /*-----------------------------------------------------------------*/
2735 genPcall (iCode * ic)
2738 symbol *rlbl = newiTempLabel (NULL);
2739 symbol *tlbl = newiTempLabel (NULL);
2740 // bool restoreBank=FALSE;
2741 // bool swapBanks = FALSE;
2743 D(emitcode("; genPCall",""));
2745 /* if caller saves & we have not saved then */
2749 /* if we are calling a not _naked function that is not using
2750 the same register bank then we need to save the
2751 destination registers on the stack */
2752 dtype = operandType (IC_LEFT (ic))->next;
2754 /* now push the calling address */
2755 emitBranch ("bsr", tlbl);
2756 emitBranch ("bra", rlbl);
2759 /* Push the function's address */
2760 aopOp (IC_LEFT (ic), ic, FALSE);
2761 pushSide (IC_LEFT (ic), FPTRSIZE);
2762 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2764 /* if send set is not empty the assign */
2767 genSend(reverseSet(_G.sendSet));
2773 emitcode ("rts", "");
2778 /* if we need assign a result value */
2779 if ((IS_ITEMP (IC_RESULT (ic)) &&
2780 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2781 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2782 IS_TRUE_SYMOP (IC_RESULT (ic)))
2786 aopOp (IC_RESULT (ic), ic, FALSE);
2789 assignResultValue (IC_RESULT (ic));
2791 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2794 /* adjust the stack for parameters if
2798 pullNull (ic->parmBytes);
2801 /* if we hade saved some registers then
2803 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2804 unsaveRegisters (ic);
2807 /*-----------------------------------------------------------------*/
2808 /* resultRemat - result is rematerializable */
2809 /*-----------------------------------------------------------------*/
2811 resultRemat (iCode * ic)
2813 if (SKIP_IC (ic) || ic->op == IFX)
2816 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2818 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2819 if (sym->remat && !POINTER_SET (ic))
2826 #if defined(__BORLANDC__) || defined(_MSC_VER)
2827 #define STRCASECMP stricmp
2829 #define STRCASECMP strcasecmp
2832 /*-----------------------------------------------------------------*/
2833 /* inExcludeList - return 1 if the string is in exclude Reg list */
2834 /*-----------------------------------------------------------------*/
2836 regsCmp(void *p1, void *p2)
2838 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2842 inExcludeList (char *s)
2844 const char *p = setFirstItem(options.excludeRegsSet);
2846 if (p == NULL || STRCASECMP(p, "none") == 0)
2850 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2853 /*-----------------------------------------------------------------*/
2854 /* genFunction - generated code for function entry */
2855 /*-----------------------------------------------------------------*/
2857 genFunction (iCode * ic)
2861 int calleesaves_saved_register = -1;
2865 /* create the function header */
2866 emitcode (";", "-----------------------------------------");
2867 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2868 emitcode (";", "-----------------------------------------");
2870 emitcode ("", "%s:", sym->rname);
2871 ftype = operandType (IC_LEFT (ic));
2875 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2877 if (IFFUNC_ISNAKED(ftype))
2879 emitcode(";", "naked function: no prologue.");
2885 /* if this is an interrupt service routine then
2887 if (IFFUNC_ISISR (sym->type))
2890 if (!inExcludeList ("h"))
2891 pushReg (hc08_reg_h, FALSE);
2895 /* if callee-save to be used for this function
2896 then save the registers being used in this function */
2897 if (IFFUNC_CALLEESAVES(sym->type))
2901 /* if any registers used */
2904 /* save the registers used */
2905 for (i = 0; i < sym->regsUsed->size; i++)
2907 if (bitVectBitValue (sym->regsUsed, i))
2909 /* remember one saved register for later usage */
2910 if (calleesaves_saved_register < 0)
2911 calleesaves_saved_register = i;
2912 pushReg (hc08_regWithIdx (i), FALSE);
2920 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2925 /* adjust the stack for the function */
2931 // werror (W_STACK_OVERFLOW, sym->name);
2935 _G.stackOfs = sym->stack;
2938 /* if critical function then turn interrupts off */
2939 if (IFFUNC_ISCRITICAL (ftype))
2941 if (IFFUNC_ARGS (ftype))
2943 /* Function was passed parameters, so make sure A is preserved */
2944 pushReg (hc08_reg_a, FALSE);
2945 pushReg (hc08_reg_a, FALSE);
2946 emitcode ("tpa", "");
2947 emitcode ("sta", "2,s");
2948 emitcode ("sei", "");
2949 pullReg (hc08_reg_a);
2953 /* No passed parameters, so A can be freely modified */
2954 emitcode ("tpa", "");
2955 pushReg (hc08_reg_a, TRUE);
2956 emitcode ("sei", "");
2962 /*-----------------------------------------------------------------*/
2963 /* genEndFunction - generates epilogue for functions */
2964 /*-----------------------------------------------------------------*/
2966 genEndFunction (iCode * ic)
2968 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2970 if (IFFUNC_ISNAKED(sym->type))
2972 emitcode(";", "naked function: no epilogue.");
2973 if (options.debug && currFunc)
2974 debugFile->writeEndFunction (currFunc, ic, 0);
2978 if (IFFUNC_ISCRITICAL (sym->type))
2980 if (!IS_VOID(sym->type->next))
2982 /* Function has return value, so make sure A is preserved */
2983 pushReg (hc08_reg_a, FALSE);
2984 emitcode ("lda", "2,s");
2985 emitcode ("tap", "");
2986 pullReg (hc08_reg_a);
2991 /* Function returns void, so A can be freely modified */
2992 pullReg (hc08_reg_a);
2993 emitcode ("tap", "");
2997 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3003 _G.stackPushes += sym->stack;
3004 adjustStack (sym->stack);
3008 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3012 if (IFFUNC_ISISR (sym->type))
3015 if (!inExcludeList ("h"))
3016 pullReg (hc08_reg_h);
3019 /* if debug then send end of function */
3020 if (options.debug && currFunc)
3022 debugFile->writeEndFunction (currFunc, ic, 1);
3025 emitcode ("rti", "");
3029 if (IFFUNC_CALLEESAVES(sym->type))
3033 /* if any registers used */
3036 /* save the registers used */
3037 for (i = sym->regsUsed->size; i >= 0; i--)
3039 if (bitVectBitValue (sym->regsUsed, i) ||
3040 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3041 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3047 /* if debug then send end of function */
3048 if (options.debug && currFunc)
3050 debugFile->writeEndFunction (currFunc, ic, 1);
3053 emitcode ("rts", "");
3058 /*-----------------------------------------------------------------*/
3059 /* genRet - generate code for return statement */
3060 /*-----------------------------------------------------------------*/
3064 int size, offset = 0;
3067 D(emitcode ("; genRet",""));
3069 /* if we have no return value then
3070 just generate the "ret" */
3074 /* we have something to return then
3075 move the return value into place */
3076 aopOp (IC_LEFT (ic), ic, FALSE);
3077 size = AOP_SIZE (IC_LEFT (ic));
3083 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3090 /* 4 byte return: store value in the global return variable */
3094 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3095 STA (fReturn2[offset--], FALSE);
3096 hc08_freeReg (hc08_reg_a);
3100 /* 2 byte return: store value in x:a */
3101 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3102 hc08_freeReg (hc08_reg_xa);
3105 /* 1 byte return: store value in a */
3106 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3107 hc08_freeReg (hc08_reg_a);
3112 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3115 /* generate a jump to the return label
3116 if the next is not the return statement */
3117 if (!(ic->next && ic->next->op == LABEL &&
3118 IC_LABEL (ic->next) == returnLabel))
3120 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3124 /*-----------------------------------------------------------------*/
3125 /* genLabel - generates a label */
3126 /*-----------------------------------------------------------------*/
3128 genLabel (iCode * ic)
3133 /* For the high level labels we cannot depend on any */
3134 /* register's contents. Amnesia time. */
3135 for (i=A_IDX;i<=XA_IDX;i++)
3137 reg = hc08_regWithIdx(i);
3142 /* special case never generate */
3143 if (IC_LABEL (ic) == entryLabel)
3146 debugFile->writeLabel(IC_LABEL (ic), ic);
3148 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3152 /*-----------------------------------------------------------------*/
3153 /* genGoto - generates a jmp */
3154 /*-----------------------------------------------------------------*/
3156 genGoto (iCode * ic)
3158 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3162 /*-----------------------------------------------------------------*/
3163 /* findLabelBackwards: walks back through the iCode chain looking */
3164 /* for the given label. Returns number of iCode instructions */
3165 /* between that label and given ic. */
3166 /* Returns zero if label not found. */
3167 /*-----------------------------------------------------------------*/
3169 findLabelBackwards (iCode * ic, int key)
3178 /* If we have any pushes or pops, we cannot predict the distance.
3179 I don't like this at all, this should be dealt with in the
3181 if (ic->op == IPUSH || ic->op == IPOP) {
3185 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3195 /*-----------------------------------------------------------------*/
3196 /* genPlusIncr :- does addition with increment if possible */
3197 /*-----------------------------------------------------------------*/
3199 genPlusIncr (iCode * ic)
3207 unsigned int size = getDataSize (IC_RESULT (ic));
3209 symbol *tlbl = NULL;
3211 left = IC_LEFT (ic);
3212 result = IC_RESULT (ic);
3214 /* will try to generate an increment */
3215 /* if the right side is not a literal
3217 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3220 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3222 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3224 if ((IS_AOP_HX (AOP (left)) ||
3225 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3227 && (icount>=-128) && (icount<=127) && (size==2))
3229 if (!IS_AOP_HX (AOP (left)))
3231 needpulx = pushRegIfUsed (hc08_reg_x);
3232 needpulh = pushRegIfUsed (hc08_reg_h);
3239 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3240 emitcode ("aix","#%d", icount);
3241 hc08_dirtyReg (hc08_reg_hx, FALSE);
3242 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3243 pullOrFreeReg (hc08_reg_h, needpulh);
3244 pullOrFreeReg (hc08_reg_x, needpulx);
3248 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3249 sameRegs (AOP (left), AOP (result))));
3251 if ((icount > 255) || (icount<0))
3254 if (!sameRegs (AOP (left), AOP (result)))
3257 D(emitcode ("; genPlusIncr",""));
3260 tlbl = newiTempLabel (NULL);
3265 rmwWithAop ("inc", AOP (result), 0);
3267 emitBranch ("bne", tlbl);
3271 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3272 needpula = pushRegIfUsed (hc08_reg_a);
3275 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3276 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3277 hc08_useReg (hc08_reg_a);
3278 storeRegToAop (hc08_reg_a, AOP (result), 0);
3279 hc08_freeReg (hc08_reg_a);
3281 emitBranch ("bcc", tlbl);
3283 for (offset=1; offset<size; offset++)
3285 rmwWithAop ("inc", AOP (result), offset);
3286 if ((offset+1)<size)
3287 emitBranch ("bne", tlbl);
3293 pullOrFreeReg (hc08_reg_a, needpula);
3300 /*-----------------------------------------------------------------*/
3301 /* genPlus - generates code for addition */
3302 /*-----------------------------------------------------------------*/
3304 genPlus (iCode * ic)
3306 int size, offset = 0;
3308 asmop *leftOp, *rightOp;
3310 /* special cases :- */
3312 D(emitcode ("; genPlus",""));
3314 aopOp (IC_LEFT (ic), ic, FALSE);
3315 aopOp (IC_RIGHT (ic), ic, FALSE);
3316 aopOp (IC_RESULT (ic), ic, TRUE);
3318 /* we want registers on the left and literals on the right */
3319 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3320 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3322 operand *t = IC_RIGHT (ic);
3323 IC_RIGHT (ic) = IC_LEFT (ic);
3328 /* if I can do an increment instead
3329 of add then GOOD for ME */
3330 if (genPlusIncr (ic) == TRUE)
3333 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3334 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3335 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3337 size = getDataSize (IC_RESULT (ic));
3339 leftOp = AOP(IC_LEFT(ic));
3340 rightOp = AOP(IC_RIGHT(ic));
3346 loadRegFromAop (hc08_reg_a, leftOp, offset);
3347 accopWithAop(add, rightOp, offset);
3348 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3349 hc08_freeReg (hc08_reg_a);
3350 add = "adc"; /* further adds must propagate carry */
3354 // adjustArithmeticResult (ic);
3357 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3358 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3359 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3362 /*-----------------------------------------------------------------*/
3363 /* genMinusDec :- does subtraction with deccrement if possible */
3364 /*-----------------------------------------------------------------*/
3366 genMinusDec (iCode * ic)
3368 unsigned int icount;
3373 unsigned int size = getDataSize (IC_RESULT (ic));
3377 left = IC_LEFT (ic);
3378 result = IC_RESULT (ic);
3380 /* will try to generate an increment */
3381 /* if the right side is not a literal
3383 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3386 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3388 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3389 && (icount>=-127) && (icount<=128) && (size==2))
3391 if (!IS_AOP_HX (AOP (left)))
3393 needpulx = pushRegIfUsed (hc08_reg_x);
3394 needpulh = pushRegIfUsed (hc08_reg_h);
3401 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3402 emitcode ("aix","#%d", -icount);
3403 hc08_dirtyReg (hc08_reg_hx, FALSE);
3404 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3405 pullOrFreeReg (hc08_reg_h, needpulh);
3406 pullOrFreeReg (hc08_reg_x, needpulx);
3410 if ((icount > 1) || (icount<0))
3413 if (!sameRegs (AOP (left), AOP (result)))
3419 D(emitcode ("; genMinusDec",""));
3421 rmwWithAop ("dec", AOP (result), 0);
3426 /*-----------------------------------------------------------------*/
3427 /* addSign - complete with sign */
3428 /*-----------------------------------------------------------------*/
3430 addSign (operand * result, int offset, int sign)
3432 int size = (getDataSize (result) - offset);
3437 emitcode ("rola", "");
3438 emitcode ("clra", "");
3439 emitcode ("sbc", zero);
3441 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3445 storeConstToAop (zero, AOP (result), offset++);
3450 /*-----------------------------------------------------------------*/
3451 /* genMinus - generates code for subtraction */
3452 /*-----------------------------------------------------------------*/
3454 genMinus (iCode * ic)
3457 int size, offset = 0;
3459 asmop *leftOp, *rightOp;
3461 D(emitcode ("; genMinus",""));
3463 aopOp (IC_LEFT (ic), ic, FALSE);
3464 aopOp (IC_RIGHT (ic), ic, FALSE);
3465 aopOp (IC_RESULT (ic), ic, TRUE);
3467 /* special cases :- */
3468 /* if I can do an decrement instead
3469 of subtract then GOOD for ME */
3470 if (genMinusDec (ic) == TRUE)
3473 size = getDataSize (IC_RESULT (ic));
3476 leftOp = AOP(IC_LEFT(ic));
3477 rightOp = AOP(IC_RIGHT(ic));
3483 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3484 accopWithAop(sub, rightOp, offset);
3485 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3490 // adjustArithmeticResult (ic);
3493 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3494 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3495 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3500 /*-----------------------------------------------------------------*/
3501 /* genMultOneByte : 8*8=8/16 bit multiplication */
3502 /*-----------------------------------------------------------------*/
3504 genMultOneByte (operand * left,
3508 /* sym_link *opetype = operandType (result); */
3509 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3510 int size=AOP_SIZE(result);
3511 bool negLiteral = FALSE;
3512 bool lUnsigned, rUnsigned;
3514 D(emitcode ("; genMultOneByte",""));
3516 if (size<1 || size>2) {
3517 // this should never happen
3518 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3519 AOP_SIZE(result), __FILE__, lineno);
3523 /* (if two literals: the value is computed before) */
3524 /* if one literal, literal on the right */
3525 if (AOP_TYPE (left) == AOP_LIT)
3531 /* if an operand is in A, make sure it is on the left */
3532 if (IS_AOP_A (AOP (right)))
3539 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3540 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3542 /* lUnsigned rUnsigned negLiteral negate case */
3543 /* false false false odd 3 */
3544 /* false false true even 3 */
3545 /* false true false odd 3 */
3546 /* false true true impossible */
3547 /* true false false odd 3 */
3548 /* true false true always 2 */
3549 /* true true false never 1 */
3550 /* true true true impossible */
3554 || (lUnsigned && rUnsigned))
3556 // just an unsigned 8*8=8/16 multiply
3557 //D(emitcode (";","unsigned"));
3559 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3560 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3561 emitcode ("mul", "");
3562 hc08_dirtyReg (hc08_reg_xa, FALSE);
3563 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3564 hc08_freeReg (hc08_reg_xa);
3569 // we have to do a signed multiply
3572 /* left unsigned, right signed literal -- literal determines sign handling */
3573 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3575 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3577 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3579 emitcode ("ldx", "#0x%02x", -val);
3581 emitcode ("ldx", "#0x%02x", val);
3583 emitcode ("mul", "");
3587 rmwWithReg ("neg", hc08_reg_a);
3588 tlbl4 = newiTempLabel (NULL);
3589 emitBranch ("bcc", tlbl4);
3590 rmwWithReg ("inc", hc08_reg_x);
3592 rmwWithReg ("neg", hc08_reg_x);
3595 hc08_dirtyReg (hc08_reg_xa, FALSE);
3596 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3597 hc08_freeReg (hc08_reg_xa);
3604 emitcode ("clr", "1,s");
3606 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3609 tlbl1 = newiTempLabel (NULL);
3610 emitcode ("tsta","");
3611 emitBranch ("bpl", tlbl1);
3612 emitcode ("inc", "1,s");
3613 rmwWithReg ("neg", hc08_reg_a);
3617 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3619 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3620 /* AND literal negative */
3622 emitcode ("ldx", "#0x%02x", -val);
3625 emitcode ("ldx", "#0x%02x", val);
3627 hc08_useReg (hc08_reg_x);
3631 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3634 tlbl2 = newiTempLabel (NULL);
3635 emitcode ("tstx", "");
3636 emitBranch ("bpl", tlbl2);
3637 emitcode ("inc", "1,s");
3638 rmwWithReg ("neg", hc08_reg_x);
3643 emitcode ("mul", "");
3644 hc08_dirtyReg (hc08_reg_xa, FALSE);
3646 tlbl3 = newiTempLabel (NULL);
3647 emitcode ("dec", "1,s");
3648 if (!lUnsigned && !rUnsigned && negLiteral)
3649 emitBranch ("beq", tlbl3);
3651 emitBranch ("bne", tlbl3);
3653 rmwWithReg ("neg", hc08_reg_a);
3654 tlbl4 = newiTempLabel (NULL);
3655 emitBranch ("bcc", tlbl4);
3656 rmwWithReg ("inc", hc08_reg_x);
3658 rmwWithReg ("neg", hc08_reg_x);
3662 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3663 hc08_freeReg (hc08_reg_xa);
3667 /*-----------------------------------------------------------------*/
3668 /* genMult - generates code for multiplication */
3669 /*-----------------------------------------------------------------*/
3671 genMult (iCode * ic)
3673 operand *left = IC_LEFT (ic);
3674 operand *right = IC_RIGHT (ic);
3675 operand *result = IC_RESULT (ic);
3677 D(emitcode ("; genMult",""));
3679 /* assign the amsops */
3680 aopOp (left, ic, FALSE);
3681 aopOp (right, ic, FALSE);
3682 aopOp (result, ic, TRUE);
3684 /* special cases first */
3685 /* if both are of size == 1 */
3686 // if (getSize(operandType(left)) == 1 &&
3687 // getSize(operandType(right)) == 1)
3688 if (AOP_SIZE (left) == 1 &&
3689 AOP_SIZE (right) == 1)
3691 genMultOneByte (left, right, result);
3695 /* should have been converted to function call */
3696 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3697 getSize(OP_SYMBOL(right)->type));
3698 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3703 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3704 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3705 freeAsmop (result, NULL, ic, TRUE);
3708 /*-----------------------------------------------------------------*/
3709 /* genDivOneByte : 8 bit division */
3710 /*-----------------------------------------------------------------*/
3712 genDivOneByte (operand * left,
3716 symbol *tlbl1, *tlbl2, *tlbl3;
3719 bool lUnsigned, rUnsigned;
3720 bool runtimeSign, compiletimeSign;
3722 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3723 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3725 D(emitcode ("; genDivOneByte",""));
3727 size = AOP_SIZE (result);
3728 /* signed or unsigned */
3729 if (lUnsigned && rUnsigned)
3731 /* unsigned is easy */
3732 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3733 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3734 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3735 emitcode ("div", "");
3736 hc08_dirtyReg (hc08_reg_a, FALSE);
3737 hc08_dirtyReg (hc08_reg_h, FALSE);
3738 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3739 hc08_freeReg (hc08_reg_a);
3740 hc08_freeReg (hc08_reg_x);
3741 hc08_freeReg (hc08_reg_h);
3745 /* signed is a little bit more difficult */
3747 /* now sign adjust for both left & right */
3749 /* let's see what's needed: */
3750 /* apply negative sign during runtime */
3751 runtimeSign = FALSE;
3752 /* negative sign from literals */
3753 compiletimeSign = FALSE;
3757 if (AOP_TYPE(left) == AOP_LIT)
3759 /* signed literal */
3760 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3762 compiletimeSign = TRUE;
3765 /* signed but not literal */
3771 if (AOP_TYPE(right) == AOP_LIT)
3773 /* signed literal */
3774 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3776 compiletimeSign ^= TRUE;
3779 /* signed but not literal */
3783 /* initialize the runtime sign */
3786 if (compiletimeSign)
3787 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3789 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3790 pushReg (hc08_reg_x, TRUE);
3793 /* save the signs of the operands */
3794 if (AOP_TYPE(right) == AOP_LIT)
3796 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3798 if (!rUnsigned && val < 0)
3799 emitcode ("ldx", "#0x%02x", -val);
3801 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3803 else /* ! literal */
3805 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3808 tlbl1 = newiTempLabel (NULL);
3809 emitcode ("tstx", "");
3810 emitBranch ("bpl", tlbl1);
3811 emitcode ("inc", "1,s");
3812 rmwWithReg ("neg", hc08_reg_x);
3817 if (AOP_TYPE(left) == AOP_LIT)
3819 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3821 if (!lUnsigned && val < 0)
3822 emitcode ("lda", "#0x%02x", -val);
3824 emitcode ("lda", "#0x%02x", (unsigned char) val);
3826 else /* ! literal */
3828 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3831 tlbl2 = newiTempLabel (NULL);
3832 emitcode ("tsta", "");
3833 emitBranch ("bpl", tlbl2);
3834 emitcode ("inc", "1,s");
3835 rmwWithReg ("neg", hc08_reg_a);
3840 loadRegFromConst (hc08_reg_h, zero);
3841 emitcode ("div", "");
3842 hc08_dirtyReg (hc08_reg_x, FALSE);
3843 hc08_dirtyReg (hc08_reg_a, FALSE);
3844 hc08_dirtyReg (hc08_reg_h, FALSE);
3846 if (runtimeSign || compiletimeSign)
3848 tlbl3 = newiTempLabel (NULL);
3851 pullReg (hc08_reg_x);
3852 rmwWithReg ("lsr", hc08_reg_x);
3853 rmwWithReg ("ror", hc08_reg_x);
3854 emitBranch ("bpl", tlbl3);
3857 rmwWithReg ("neg", hc08_reg_a);
3861 storeRegToAop (hc08_reg_a, AOP (result), 0);
3865 /* msb is 0x00 or 0xff depending on the sign */
3868 rmwWithReg ("lsl", hc08_reg_x);
3869 emitcode ("clra", "");
3870 emitcode ("sbc", "#0");
3872 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3874 else /* compiletimeSign */
3876 storeConstToAop ("#0xff", AOP (result), ++offset);
3881 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3884 hc08_freeReg (hc08_reg_a);
3885 hc08_freeReg (hc08_reg_x);
3886 hc08_freeReg (hc08_reg_h);
3889 /*-----------------------------------------------------------------*/
3890 /* genDiv - generates code for division */
3891 /*-----------------------------------------------------------------*/
3895 operand *left = IC_LEFT (ic);
3896 operand *right = IC_RIGHT (ic);
3897 operand *result = IC_RESULT (ic);
3899 D(emitcode ("; genDiv",""));
3901 /* assign the amsops */
3902 aopOp (left, ic, FALSE);
3903 aopOp (right, ic, FALSE);
3904 aopOp (result, ic, TRUE);
3906 /* special cases first */
3907 /* if both are of size == 1 */
3908 if (AOP_SIZE (left) <= 2 &&
3909 AOP_SIZE (right) == 1)
3911 genDivOneByte (left, right, result);
3915 /* should have been converted to function call */
3918 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3919 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3920 freeAsmop (result, NULL, ic, TRUE);
3923 /*-----------------------------------------------------------------*/
3924 /* genModOneByte : 8 bit modulus */
3925 /*-----------------------------------------------------------------*/
3927 genModOneByte (operand * left,
3931 symbol *tlbl1, *tlbl2, *tlbl3;
3934 bool lUnsigned, rUnsigned;
3935 bool runtimeSign, compiletimeSign;
3937 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3938 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3940 D(emitcode ("; genModOneByte",""));
3942 size = AOP_SIZE (result);
3944 if (lUnsigned && rUnsigned)
3946 /* unsigned is easy */
3947 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3948 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3949 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3950 emitcode ("div", "");
3951 hc08_dirtyReg (hc08_reg_a, FALSE);
3952 hc08_dirtyReg (hc08_reg_h, FALSE);
3953 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3954 hc08_freeReg (hc08_reg_a);
3955 hc08_freeReg (hc08_reg_x);
3956 hc08_freeReg (hc08_reg_h);
3960 /* signed is a little bit more difficult */
3962 if (AOP_TYPE(right) == AOP_LIT)
3964 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3966 if (!rUnsigned && val < 0)
3967 emitcode ("ldx", "#0x%02x", -val);
3969 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3971 else /* ! literal */
3973 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3976 tlbl1 = newiTempLabel (NULL);
3977 emitcode ("tstx", "");
3978 emitBranch ("bpl", tlbl1);
3979 rmwWithReg ("neg", hc08_reg_x);
3984 /* let's see what's needed: */
3985 /* apply negative sign during runtime */
3986 runtimeSign = FALSE;
3987 /* negative sign from literals */
3988 compiletimeSign = FALSE;
3990 /* sign adjust left side */
3991 if (AOP_TYPE(left) == AOP_LIT)
3993 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3995 if (!lUnsigned && val < 0)
3997 compiletimeSign = TRUE; /* set sign flag */
3998 emitcode ("lda", "#0x%02x", -val);
4001 emitcode ("lda", "#0x%02x", (unsigned char) val);
4003 else /* ! literal */
4006 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4011 emitcode ("clr", "1,s");
4013 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4014 tlbl2 = newiTempLabel (NULL);
4015 emitcode ("tsta", "");
4016 emitBranch ("bpl", tlbl2);
4017 emitcode ("inc", "1,s");
4018 rmwWithReg ("neg", hc08_reg_a);
4023 loadRegFromConst (hc08_reg_h, zero);
4024 emitcode ("div", "");
4025 hc08_dirtyReg (hc08_reg_x, FALSE);
4026 hc08_dirtyReg (hc08_reg_a, FALSE);
4027 hc08_dirtyReg (hc08_reg_h, FALSE);
4029 if (runtimeSign || compiletimeSign)
4031 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4032 tlbl3 = newiTempLabel (NULL);
4035 pullReg (hc08_reg_x);
4036 rmwWithReg ("lsr", hc08_reg_x);
4037 rmwWithReg ("ror", hc08_reg_x);
4038 emitBranch ("bpl", tlbl3);
4041 rmwWithReg ("neg", hc08_reg_a);
4045 storeRegToAop (hc08_reg_a, AOP (result), 0);
4049 /* msb is 0x00 or 0xff depending on the sign */
4052 rmwWithReg ("lsl", hc08_reg_x);
4053 emitcode ("clra", "");
4054 emitcode ("sbc", "#0");
4056 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4058 else /* compiletimeSign */
4060 storeConstToAop ("#0xff", AOP (result), ++offset);
4065 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4068 hc08_freeReg (hc08_reg_a);
4069 hc08_freeReg (hc08_reg_x);
4070 hc08_freeReg (hc08_reg_h);
4073 /*-----------------------------------------------------------------*/
4074 /* genMod - generates code for division */
4075 /*-----------------------------------------------------------------*/
4079 operand *left = IC_LEFT (ic);
4080 operand *right = IC_RIGHT (ic);
4081 operand *result = IC_RESULT (ic);
4083 D(emitcode ("; genMod",""));
4085 /* assign the amsops */
4086 aopOp (left, ic, FALSE);
4087 aopOp (right, ic, FALSE);
4088 aopOp (result, ic, TRUE);
4090 /* special cases first */
4091 /* if both are of size == 1 */
4092 if (AOP_SIZE (left) <= 2 &&
4093 AOP_SIZE (right) == 1)
4095 genModOneByte (left, right, result);
4099 /* should have been converted to function call */
4103 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4104 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4105 freeAsmop (result, NULL, ic, TRUE);
4108 /*-----------------------------------------------------------------*/
4109 /* genIfxJump :- will create a jump depending on the ifx */
4110 /*-----------------------------------------------------------------*/
4112 genIfxJump (iCode * ic, char *jval)
4115 symbol *tlbl = newiTempLabel (NULL);
4118 D(emitcode ("; genIfxJump",""));
4120 /* if true label then we jump if condition
4124 jlbl = IC_TRUE (ic);
4125 if (!strcmp (jval, "a"))
4127 else if (!strcmp (jval, "c"))
4134 /* false label is present */
4135 jlbl = IC_FALSE (ic);
4136 if (!strcmp (jval, "a"))
4138 else if (!strcmp (jval, "c"))
4143 emitBranch (inst, tlbl);
4144 emitBranch ("jmp", jlbl);
4147 /* mark the icode as generated */
4151 /*-----------------------------------------------------------------*/
4152 /* genCmp :- greater or less than comparison */
4153 /*-----------------------------------------------------------------*/
4155 genCmp (operand * left, operand * right,
4156 operand * result, iCode * ifx, int sign, iCode *ic)
4158 int size, offset = 0;
4159 unsigned long lit = 0L;
4161 bool needpula = FALSE;
4163 D(emitcode ("; genCmp",""));
4165 /* subtract right from left if at the
4166 end the carry flag is set then we know that
4167 left is greater than right */
4168 size = max (AOP_SIZE (left), AOP_SIZE (right));
4170 if (AOP_TYPE (right) == AOP_LIT)
4172 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4173 /* optimize if(x < 0) or if(x >= 0) */
4182 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
4183 emitcode ("rola", "");
4184 hc08_useReg (hc08_reg_a);
4192 && ((AOP_TYPE (right) == AOP_LIT) ||
4193 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4194 && hc08_reg_hx->isFree)
4196 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4197 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4198 hc08_freeReg (hc08_reg_hx);
4209 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4210 accopWithAop (sub, AOP (right), offset);
4211 hc08_freeReg (hc08_reg_a);
4217 freeAsmop (right, NULL, ic, TRUE);
4218 freeAsmop (left, NULL, ic, TRUE);
4219 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4225 /* if the result is used in the next
4226 ifx conditional branch then generate
4227 code a little differently */
4230 pullOrFreeReg(hc08_reg_a,needpula);
4231 genIfxJump (ifx, sign ? "s" : "c");
4238 pullOrFreeReg(hc08_reg_a,needpula);
4242 /*-----------------------------------------------------------------*/
4243 /* genCmpGt :- greater than comparison */
4244 /*-----------------------------------------------------------------*/
4246 genCmpGt (iCode * ic, iCode * ifx)
4248 operand *left, *right, *result;
4249 sym_link *letype, *retype;
4252 D(emitcode ("; genCmpGt",""));
4254 result = IC_RESULT (ic);
4255 left = IC_LEFT (ic);
4256 right = IC_RIGHT (ic);
4258 letype = getSpec (operandType (left));
4259 retype = getSpec (operandType (right));
4260 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4261 /* assign the amsops */
4262 aopOp (left, ic, FALSE);
4263 aopOp (right, ic, FALSE);
4264 aopOp (result, ic, TRUE);
4266 genCmp (right, left, result, ifx, sign,ic);
4268 freeAsmop (result, NULL, ic, TRUE);
4271 /*-----------------------------------------------------------------*/
4272 /* genCmpLt - less than comparisons */
4273 /*-----------------------------------------------------------------*/
4275 genCmpLt (iCode * ic, iCode * ifx)
4277 operand *left, *right, *result;
4278 sym_link *letype, *retype;
4281 D(emitcode ("; genCmpLt",""));
4283 result = IC_RESULT (ic);
4284 left = IC_LEFT (ic);
4285 right = IC_RIGHT (ic);
4287 letype = getSpec (operandType (left));
4288 retype = getSpec (operandType (right));
4289 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4291 /* assign the amsops */
4292 aopOp (left, ic, FALSE);
4293 aopOp (right, ic, FALSE);
4294 aopOp (result, ic, TRUE);
4296 genCmp (left, right, result, ifx, sign,ic);
4298 freeAsmop (result, NULL, ic, TRUE);
4301 /*-----------------------------------------------------------------*/
4302 /* - compare and branch if not equal */
4303 /*-----------------------------------------------------------------*/
4305 gencbneshort (operand * left, operand * right, symbol * lbl)
4307 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4309 unsigned long lit = 0L;
4311 /* if the left side is a literal or
4312 if the right is in a pointer register and left
4314 if (AOP_TYPE (left) == AOP_LIT)
4320 if (AOP_TYPE (right) == AOP_LIT)
4321 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4325 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4326 accopWithAop ("cmp", AOP (right), offset);
4327 hc08_useReg (hc08_reg_a);
4328 hc08_freeReg (hc08_reg_a);
4329 emitBranch ("bne", lbl);
4335 /*-----------------------------------------------------------------*/
4336 /* gencjne - compare and jump if not equal */
4337 /*-----------------------------------------------------------------*/
4339 gencjne (operand * left, operand * right, symbol * lbl)
4341 symbol *tlbl = newiTempLabel (NULL);
4343 gencbneshort (left, right, lbl);
4345 loadRegFromConst (hc08_reg_a, one);
4346 emitBranch ("bra", tlbl);
4348 loadRegFromConst (hc08_reg_a, zero);
4351 hc08_useReg(hc08_reg_a);
4352 hc08_freeReg(hc08_reg_a);
4355 /*-----------------------------------------------------------------*/
4356 /* genCmpEq - generates code for equal to */
4357 /*-----------------------------------------------------------------*/
4359 genCmpEq (iCode * ic, iCode * ifx)
4361 operand *left, *right, *result;
4363 D(emitcode ("; genCmpEq",""));
4365 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4366 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4367 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4369 /* if literal, literal on the right or
4370 if the right is in a pointer register and left
4372 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4374 operand *t = IC_RIGHT (ic);
4375 IC_RIGHT (ic) = IC_LEFT (ic);
4379 if (ifx && !AOP_SIZE (result))
4382 tlbl = newiTempLabel (NULL);
4383 gencbneshort (left, right, tlbl);
4386 emitBranch ("jmp", IC_TRUE (ifx));
4391 symbol *lbl = newiTempLabel (NULL);
4392 emitBranch ("bra", lbl);
4394 emitBranch ("jmp", IC_FALSE (ifx));
4398 /* mark the icode as generated */
4403 gencjne (left, right, newiTempLabel (NULL));
4404 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4406 storeRegToAop (hc08_reg_a, AOP (result), 0);
4411 genIfxJump (ifx, "a");
4414 /* if the result is used in an arithmetic operation
4415 then put the result in place */
4416 if (AOP_TYPE (result) != AOP_CRY)
4420 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4421 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4422 freeAsmop (result, NULL, ic, TRUE);
4425 /*-----------------------------------------------------------------*/
4426 /* ifxForOp - returns the icode containing the ifx for operand */
4427 /*-----------------------------------------------------------------*/
4429 ifxForOp (operand * op, iCode * ic)
4431 /* if true symbol then needs to be assigned */
4432 if (IS_TRUE_SYMOP (op))
4435 /* if this has register type condition and
4436 the next instruction is ifx with the same operand
4437 and live to of the operand is upto the ifx only then */
4439 ic->next->op == IFX &&
4440 IC_COND (ic->next)->key == op->key &&
4441 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4448 genPointerGetSetOfs (iCode *ic)
4450 iCode *lic = ic->next;
4456 /* Make sure we have a next iCode */
4457 D(emitcode("","; checking lic"));
4461 /* Make sure the result of the addition is an iCode */
4462 D(emitcode("","; checking IS_ITEMP"));
4463 if (!IS_ITEMP (IC_RESULT (ic)))
4466 /* Make sure the next iCode is a pointer set or get */
4467 pset = POINTER_SET(lic);
4468 pget = POINTER_GET(lic);
4469 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4473 /* Make sure this is the only use of the pointer */
4474 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4477 D(emitcode("", "; checking pset operandsEqu"));
4478 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4481 D(emitcode("", "; checking pget operandsEqu"));
4482 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4485 D(emitcode("", "; checking IS_SYMOP"));
4486 if (!IS_SYMOP (IC_LEFT (ic)))
4489 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4490 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4493 sym = OP_SYMBOL (IC_LEFT (ic));
4495 D(emitcode("", "; checking remat"));
4502 D(emitcode ("; genPointerGetOfs",""));
4503 aopOp (IC_LEFT(ic), ic, FALSE);
4504 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4505 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4507 aopOp (IC_RIGHT(ic), ic, FALSE);
4508 aopOp (IC_RESULT(lic), lic, FALSE);
4510 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4512 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4514 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4515 loadRegFromConst (hc08_reg_h, zero);
4519 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4520 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4521 emitcode ("rola","");
4522 emitcode ("clra","");
4523 emitcode ("sbc", "#0");
4524 hc08_useReg (hc08_reg_a);
4525 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4529 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4530 size = AOP_SIZE (IC_RESULT(lic));
4531 derefaop->size = size;
4536 emitcode ("lda", "%s,x",
4537 aopAdrStr (derefaop, offset, TRUE));
4538 hc08_useReg (hc08_reg_a);
4539 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4540 hc08_freeReg (hc08_reg_a);
4544 hc08_freeReg (hc08_reg_hx);
4546 freeAsmop (NULL, derefaop, ic, TRUE);
4547 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4548 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4555 D(emitcode ("; genPointerSetOfs",""));
4556 aopOp (IC_LEFT(ic), ic, FALSE);
4557 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4558 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4560 aopOp (IC_RIGHT(ic), ic, FALSE);
4561 aopOp (IC_RIGHT(lic), lic, FALSE);
4563 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4565 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4567 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4568 loadRegFromConst (hc08_reg_h, zero);
4572 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4573 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4574 emitcode ("rola","");
4575 emitcode ("clra","");
4576 emitcode ("sbc", "#0");
4577 hc08_useReg (hc08_reg_a);
4578 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4582 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4583 size = AOP_SIZE (IC_RIGHT(lic));
4584 derefaop->size = size;
4589 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4590 emitcode ("sta", "%s,x",
4591 aopAdrStr (derefaop, offset, TRUE));
4592 hc08_freeReg (hc08_reg_a);
4597 hc08_freeReg (hc08_reg_hx);
4599 freeAsmop (NULL, derefaop, ic, TRUE);
4600 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4601 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4610 /*-----------------------------------------------------------------*/
4611 /* hasInc - operand is incremented before any other use */
4612 /*-----------------------------------------------------------------*/
4614 hasInc (operand *op, iCode *ic,int osize)
4616 sym_link *type = operandType(op);
4617 sym_link *retype = getSpec (type);
4618 iCode *lic = ic->next;
4621 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4622 if (!IS_SYMOP(op)) return NULL;
4624 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4625 if (IS_AGGREGATE(type->next)) return NULL;
4626 if (osize != (isize = getSize(type->next))) return NULL;
4629 /* if operand of the form op = op + <sizeof *op> */
4630 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4631 isOperandEqual(IC_RESULT(lic),op) &&
4632 isOperandLiteral(IC_RIGHT(lic)) &&
4633 operandLitValue(IC_RIGHT(lic)) == isize) {
4636 /* if the operand used or deffed */
4637 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4640 /* if GOTO or IFX */
4641 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4647 /*-----------------------------------------------------------------*/
4648 /* genAndOp - for && operation */
4649 /*-----------------------------------------------------------------*/
4651 genAndOp (iCode * ic)
4653 operand *left, *right, *result;
4654 symbol *tlbl, *tlbl0;
4656 D(emitcode ("; genAndOp",""));
4658 /* note here that && operations that are in an
4659 if statement are taken away by backPatchLabels
4660 only those used in arthmetic operations remain */
4661 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4662 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4663 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4665 tlbl = newiTempLabel (NULL);
4666 tlbl0 = newiTempLabel (NULL);
4668 asmopToBool (AOP (left), FALSE);
4669 emitBranch ("beq", tlbl0);
4670 asmopToBool (AOP (right), FALSE);
4671 emitBranch ("beq", tlbl0);
4672 loadRegFromConst (hc08_reg_a,one);
4673 emitBranch ("bra", tlbl);
4675 loadRegFromConst (hc08_reg_a,zero);
4678 hc08_useReg (hc08_reg_a);
4679 hc08_freeReg (hc08_reg_a);
4681 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4683 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4684 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4685 freeAsmop (result, NULL, ic, TRUE);
4689 /*-----------------------------------------------------------------*/
4690 /* genOrOp - for || operation */
4691 /*-----------------------------------------------------------------*/
4693 genOrOp (iCode * ic)
4695 operand *left, *right, *result;
4696 symbol *tlbl, *tlbl0;
4698 D(emitcode ("; genOrOp",""));
4700 /* note here that || operations that are in an
4701 if statement are taken away by backPatchLabels
4702 only those used in arthmetic operations remain */
4703 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4704 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4705 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4707 tlbl = newiTempLabel (NULL);
4708 tlbl0 = newiTempLabel (NULL);
4710 asmopToBool (AOP (left), FALSE);
4711 emitBranch ("bne", tlbl0);
4712 asmopToBool (AOP (right), FALSE);
4713 emitBranch ("bne", tlbl0);
4714 loadRegFromConst (hc08_reg_a,zero);
4715 emitBranch ("bra", tlbl);
4717 loadRegFromConst (hc08_reg_a,one);
4720 hc08_useReg (hc08_reg_a);
4721 hc08_freeReg (hc08_reg_a);
4723 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4726 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4727 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4728 freeAsmop (result, NULL, ic, TRUE);
4731 /*-----------------------------------------------------------------*/
4732 /* isLiteralBit - test if lit == 2^n */
4733 /*-----------------------------------------------------------------*/
4735 isLiteralBit (unsigned long lit)
4737 unsigned long pw[32] =
4738 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4739 0x100L, 0x200L, 0x400L, 0x800L,
4740 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4741 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4742 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4743 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4744 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4747 for (idx = 0; idx < 32; idx++)
4754 /*-----------------------------------------------------------------*/
4755 /* continueIfTrue - */
4756 /*-----------------------------------------------------------------*/
4758 continueIfTrue (iCode * ic)
4761 emitBranch ("jmp", IC_TRUE (ic));
4765 /*-----------------------------------------------------------------*/
4767 /*-----------------------------------------------------------------*/
4769 jumpIfTrue (iCode * ic)
4772 emitBranch ("jmp", IC_FALSE (ic));
4776 /*-----------------------------------------------------------------*/
4777 /* jmpTrueOrFalse - */
4778 /*-----------------------------------------------------------------*/
4780 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4782 // ugly but optimized by peephole
4785 symbol *nlbl = newiTempLabel (NULL);
4786 emitBranch ("bra", nlbl);
4788 emitBranch ("jmp", IC_TRUE (ic));
4793 emitBranch ("jmp", IC_FALSE (ic));
4800 /*-----------------------------------------------------------------*/
4801 /* genAnd - code for and */
4802 /*-----------------------------------------------------------------*/
4804 genAnd (iCode * ic, iCode * ifx)
4806 operand *left, *right, *result;
4807 int size, offset = 0;
4808 unsigned long lit = 0L;
4809 unsigned long litinv;
4810 unsigned char bytemask;
4816 D(emitcode ("; genAnd",""));
4818 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4819 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4820 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4823 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4825 AOP_TYPE (left), AOP_TYPE (right)));
4826 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4828 AOP_SIZE (left), AOP_SIZE (right)));
4831 /* if left is a literal & right is not then exchange them */
4832 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4834 operand *tmp = right;
4839 /* if right is accumulator & left is not then exchange them */
4840 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4842 operand *tmp = right;
4847 if (AOP_TYPE (right) == AOP_LIT)
4848 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4850 if (AOP_TYPE (result) == AOP_CRY)
4852 symbol *tlbl = NULL;
4853 wassertl (ifx, "AOP_CRY result without ifx");
4855 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4859 bytemask = (lit >> (offset*8)) & 0xff;
4861 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
4863 if (isOperandVolatile (left, FALSE))
4865 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4866 hc08_freeReg( hc08_reg_a);
4869 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
4871 rmwWithAop ("tst", AOP (left), offset);
4875 tlbl = newiTempLabel (NULL);
4876 emitBranch ("bne", tlbl);
4881 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4882 accopWithAop ("and", AOP (right), offset);
4883 hc08_freeReg( hc08_reg_a);
4887 tlbl = newiTempLabel (NULL);
4888 emitBranch ("bne", tlbl);
4895 genIfxJump (ifx, "a");
4898 size = AOP_SIZE (result);
4900 if (AOP_TYPE (right) == AOP_LIT)
4902 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4903 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4904 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4906 int bitpos = isLiteralBit(litinv)-1;
4907 emitcode ("bclr","#%d,%s",bitpos & 7,
4908 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4916 bytemask = (lit >> (offset*8)) & 0xff;
4918 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
4920 if (isOperandVolatile (left, FALSE))
4922 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4923 hc08_freeReg( hc08_reg_a);
4925 storeConstToAop (zero, AOP (result), offset);
4927 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
4929 transferAopAop (AOP (left), offset, AOP (result), offset);
4933 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4934 accopWithAop ("and", AOP (right), offset);
4935 storeRegToAop (hc08_reg_a, AOP (result), offset);
4936 hc08_freeReg (hc08_reg_a);
4942 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4944 freeAsmop (result, NULL, ic, TRUE);
4947 /*-----------------------------------------------------------------*/
4948 /* genOr - code for or */
4949 /*-----------------------------------------------------------------*/
4951 genOr (iCode * ic, iCode * ifx)
4953 operand *left, *right, *result;
4954 int size, offset = 0;
4955 unsigned long lit = 0L;
4956 unsigned char bytemask;
4958 D(emitcode ("; genOr",""));
4960 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4961 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4962 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4965 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4967 AOP_TYPE (left), AOP_TYPE (right)));
4968 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4970 AOP_SIZE (left), AOP_SIZE (right)));
4973 /* if left is a literal & right is not then exchange them */
4974 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4976 operand *tmp = right;
4981 /* if left is accumulator & right is not then exchange them */
4982 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4984 operand *tmp = right;
4989 if (AOP_TYPE (right) == AOP_LIT)
4990 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4992 if (AOP_TYPE (result) == AOP_CRY)
4994 symbol *tlbl = NULL;
4995 wassertl (ifx, "AOP_CRY result without ifx");
4997 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5001 bytemask = (lit >> (offset*8)) & 0xff;
5003 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5005 rmwWithAop ("tst", AOP (left), offset);
5009 tlbl = newiTempLabel (NULL);
5010 emitBranch ("bne", tlbl);
5015 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5016 accopWithAop ("ora", AOP (right), offset);
5017 hc08_freeReg( hc08_reg_a);
5021 tlbl = newiTempLabel (NULL);
5022 emitBranch ("bne", tlbl);
5029 genIfxJump (ifx, "a");
5032 if (AOP_TYPE (right) == AOP_LIT)
5033 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5035 size = AOP_SIZE (result);
5037 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5038 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5039 (AOP_TYPE (left) == AOP_DIR))
5041 int bitpos = isLiteralBit(lit)-1;
5042 emitcode ("bset","#%d,%s",bitpos & 7,
5043 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5050 bytemask = (lit >> (offset*8)) & 0xff;
5052 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5054 if (isOperandVolatile (left, FALSE))
5056 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5057 hc08_freeReg( hc08_reg_a);
5059 transferAopAop (AOP (right), offset, AOP (result), offset);
5061 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5063 transferAopAop (AOP (left), offset, AOP (result), offset);
5067 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5068 accopWithAop ("ora", AOP (right), offset);
5069 storeRegToAop (hc08_reg_a, AOP (result), offset);
5070 hc08_freeReg (hc08_reg_a);
5077 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5078 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5079 freeAsmop (result, NULL, ic, TRUE);
5082 /*-----------------------------------------------------------------*/
5083 /* genXor - code for xclusive or */
5084 /*-----------------------------------------------------------------*/
5086 genXor (iCode * ic, iCode * ifx)
5088 operand *left, *right, *result;
5089 int size, offset = 0;
5090 unsigned long lit = 0L;
5092 D(emitcode ("; genXor",""));
5094 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5095 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5096 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5099 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5101 AOP_TYPE (left), AOP_TYPE (right)));
5102 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5104 AOP_SIZE (left), AOP_SIZE (right)));
5107 /* if left is a literal & right is not ||
5108 if left needs acc & right does not */
5109 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5111 operand *tmp = right;
5116 /* if left is accumulator & right is not then exchange them */
5117 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5119 operand *tmp = right;
5124 if (AOP_TYPE (result) == AOP_CRY)
5127 wassertl (ifx, "AOP_CPY result without ifx");
5129 tlbl = newiTempLabel (NULL);
5130 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5134 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5135 if ((AOP_TYPE (right) == AOP_LIT)
5136 && (((lit >> (offset*8)) & 0xff) == 0))
5137 emitcode ("tsta","");
5139 accopWithAop ("eor", AOP (right), offset);
5140 hc08_freeReg( hc08_reg_a);
5142 emitBranch ("bne", tlbl);
5146 genIfxJump (ifx, "a");
5152 if (AOP_TYPE (right) == AOP_LIT)
5153 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5155 size = AOP_SIZE (result);
5159 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5160 accopWithAop ("eor", AOP (right), offset);
5161 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5162 hc08_freeReg( hc08_reg_a);
5166 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5167 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5168 freeAsmop (result, NULL, ic, TRUE);
5172 emitinline (iCode * ic, char *inlin)
5178 symbol *sym, *tempsym;
5187 while (isalnum(*inlin) || (*inlin == '_'))
5191 //printf("Found possible symbol '%s'\n",symname);
5192 tempsym = newSymbol (symname, ic->level);
5193 tempsym->block = ic->block;
5194 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5203 aop = aopForSym (ic, sym, FALSE);
5204 l = aopAdrStr (aop, aop->size - 1, TRUE);
5208 if (!sym->allocreq && !sym->ismyparm)
5210 werror (E_ID_UNDEF, sym->name);
5212 " Add 'volatile' to the variable declaration so that it\n"
5213 " can be referenced within inline assembly");
5215 //printf("Replacing with '%s'\n",l);
5219 if ((2+bp-buffer)>sizeof(buffer))
5228 if ((2+bp-buffer)>sizeof(buffer))
5235 if ((2+bp-buffer)>sizeof(buffer))
5236 fprintf(stderr, "Inline assembly buffer overflow\n");
5238 //printf("%s\n",buffer);
5239 emitcode (buffer,"");
5243 /*-----------------------------------------------------------------*/
5244 /* genInline - write the inline code out */
5245 /*-----------------------------------------------------------------*/
5247 genInline (iCode * ic)
5249 char *buffer, *bp, *bp1;
5251 D(emitcode ("; genInline",""));
5253 _G.inLine += (!options.asmpeep);
5255 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5256 strcpy (buffer, IC_INLINE (ic));
5258 /* emit each line as a code */
5264 /* emitcode (bp1, ""); */
5265 emitinline (ic, bp1);
5284 /* emitcode (bp1, ""); */
5285 emitinline (ic, bp1);
5287 /* emitcode("",buffer); */
5288 _G.inLine -= (!options.asmpeep);
5291 /*-----------------------------------------------------------------*/
5292 /* genRRC - rotate right with carry */
5293 /*-----------------------------------------------------------------*/
5297 operand *left, *result;
5298 int size, offset = 0;
5299 bool needpula = FALSE;
5300 bool resultInA = FALSE;
5303 D(emitcode ("; genRRC",""));
5305 /* rotate right with carry */
5306 left = IC_LEFT (ic);
5307 result = IC_RESULT (ic);
5308 aopOp (left, ic, FALSE);
5309 aopOp (result, ic, FALSE);
5311 if ((AOP_TYPE (result) == AOP_REG)
5312 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5315 size = AOP_SIZE (result);
5319 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5323 rmwWithAop (shift, AOP (result), offset--);
5331 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5332 rmwWithReg (shift, hc08_reg_a);
5333 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5334 hc08_freeReg (hc08_reg_a);
5339 if ((!hc08_reg_a->isFree) || resultInA)
5341 pushReg (hc08_reg_a, TRUE);
5345 /* now we need to put the carry into the
5346 highest order byte of the result */
5347 offset = AOP_SIZE (result) - 1;
5348 emitcode ("clra","");
5349 emitcode ("rora","");
5350 hc08_dirtyReg (hc08_reg_a, FALSE);
5353 emitcode ("ora", "1,s");
5354 emitcode ("ais", "#1");
5355 hc08_dirtyReg (hc08_reg_a, FALSE);
5359 accopWithAop ("ora", AOP (result), offset);
5360 storeRegToAop (hc08_reg_a, AOP (result), offset);
5362 pullOrFreeReg (hc08_reg_a, needpula);
5364 freeAsmop (left, NULL, ic, TRUE);
5365 freeAsmop (result, NULL, ic, TRUE);
5368 /*-----------------------------------------------------------------*/
5369 /* genRLC - generate code for rotate left with carry */
5370 /*-----------------------------------------------------------------*/
5374 operand *left, *result;
5375 int size, offset = 0;
5377 bool resultInA = FALSE;
5378 bool needpula = FALSE;
5380 D(emitcode ("; genRLC",""));
5382 /* rotate right with carry */
5383 left = IC_LEFT (ic);
5384 result = IC_RESULT (ic);
5385 aopOp (left, ic, FALSE);
5386 aopOp (result, ic, FALSE);
5388 if ((AOP_TYPE (result) == AOP_REG)
5389 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5392 size = AOP_SIZE (result);
5396 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5400 rmwWithAop (shift, AOP (result), offset--);
5408 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5409 rmwWithReg (shift, hc08_reg_a);
5410 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5411 hc08_freeReg (hc08_reg_a);
5416 if ((!hc08_reg_a->isFree) || resultInA)
5418 pushReg (hc08_reg_a, TRUE);
5422 /* now we need to put the carry into the
5423 lowest order byte of the result */
5425 emitcode ("clra","");
5426 emitcode ("rola","");
5427 hc08_dirtyReg (hc08_reg_a, FALSE);
5430 emitcode ("ora", "1,s");
5431 emitcode ("ais", "#1");
5432 hc08_dirtyReg (hc08_reg_a, FALSE);
5436 accopWithAop ("ora", AOP (result), offset);
5437 storeRegToAop (hc08_reg_a, AOP (result), offset);
5439 pullOrFreeReg (hc08_reg_a, needpula);
5441 freeAsmop (left, NULL, ic, TRUE);
5442 freeAsmop (result, NULL, ic, TRUE);
5445 /*-----------------------------------------------------------------*/
5446 /* genGetHbit - generates code get highest order bit */
5447 /*-----------------------------------------------------------------*/
5449 genGetHbit (iCode * ic)
5451 operand *left, *result;
5453 D(emitcode ("; genGetHbit",""));
5455 left = IC_LEFT (ic);
5456 result = IC_RESULT (ic);
5457 aopOp (left, ic, FALSE);
5458 aopOp (result, ic, FALSE);
5460 /* get the highest order byte into a */
5461 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5462 emitcode ("rola", "");
5463 emitcode ("clra", "");
5464 emitcode ("rola", "");
5465 hc08_dirtyReg (hc08_reg_a, FALSE);
5466 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5467 hc08_freeReg (hc08_reg_a);
5469 freeAsmop (left, NULL, ic, TRUE);
5470 freeAsmop (result, NULL, ic, TRUE);
5473 /*-----------------------------------------------------------------*/
5474 /* genSwap - generates code to swap nibbles or bytes */
5475 /*-----------------------------------------------------------------*/
5477 genSwap (iCode * ic)
5479 operand *left, *result;
5481 D(emitcode ("; genSwap",""));
5483 left = IC_LEFT (ic);
5484 result = IC_RESULT (ic);
5485 aopOp (left, ic, FALSE);
5486 aopOp (result, ic, FALSE);
5488 switch (AOP_SIZE (left))
5490 case 1: /* swap nibbles in byte */
5491 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5492 emitcode ("nsa", "");
5493 hc08_dirtyReg (hc08_reg_a, FALSE);
5494 storeRegToAop (hc08_reg_a, AOP (result), 0);
5495 hc08_freeReg (hc08_reg_a);
5497 case 2: /* swap bytes in a word */
5498 if (operandsEqu (left, result))
5500 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5501 hc08_useReg (hc08_reg_a);
5502 transferAopAop (AOP (left), 1, AOP (result), 0);
5503 storeRegToAop (hc08_reg_a, AOP (result), 1);
5504 hc08_freeReg (hc08_reg_a);
5508 transferAopAop (AOP (left), 0, AOP (result), 1);
5509 transferAopAop (AOP (left), 1, AOP (result), 0);
5513 wassertl(FALSE, "unsupported SWAP operand size");
5516 freeAsmop (left, NULL, ic, TRUE);
5517 freeAsmop (result, NULL, ic, TRUE);
5521 /*-----------------------------------------------------------------*/
5522 /* AccRol - rotate left accumulator by known count */
5523 /*-----------------------------------------------------------------*/
5525 AccRol (int shCount)
5527 shCount &= 0x0007; // shCount : 0..7
5534 emitcode ("rola", ""); /* 1 cycle */
5537 emitcode ("rola", ""); /* 1 cycle */
5538 emitcode ("rola", ""); /* 1 cycle */
5541 emitcode ("nsa", "");
5542 emitcode ("rora", "");
5545 emitcode ("nsa", ""); /* 3 cycles */
5548 emitcode ("nsa", ""); /* 3 cycles */
5549 emitcode ("rola", ""); /* 1 cycle */
5552 emitcode ("nsa", ""); /* 3 cycles */
5553 emitcode ("rola", ""); /* 1 cycle */
5554 emitcode ("rola", ""); /* 1 cycle */
5557 emitcode ("nsa", ""); /* 3 cycles */
5558 emitcode ("rola", ""); /* 1 cycle */
5559 emitcode ("rola", ""); /* 1 cycle */
5560 emitcode ("rola", ""); /* 1 cycle */
5567 /*-----------------------------------------------------------------*/
5568 /* AccLsh - left shift accumulator by known count */
5569 /*-----------------------------------------------------------------*/
5571 AccLsh (int shCount)
5575 shCount &= 0x0007; // shCount : 0..7
5577 /* Shift counts of 4 and 5 are currently optimized for code size. */
5578 /* Falling through to the unrolled loop would be optimal for code speed. */
5579 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5583 accopWithMisc ("nsa", "");
5584 accopWithMisc ("and", "#0xf0");
5585 /* total: 5 cycles, 3 bytes */
5588 accopWithMisc ("nsa", "");
5589 accopWithMisc ("and", "#0xf0");
5590 accopWithMisc ("lsla", "");
5591 /* total: 6 cycles, 4 bytes */
5594 accopWithMisc ("rora", "");
5595 accopWithMisc ("rora", "");
5596 accopWithMisc ("rora", "");
5597 accopWithMisc ("and", "#0xc0");
5598 /* total: 5 cycles, 5 bytes */
5601 accopWithMisc ("rora", "");
5602 accopWithMisc ("clra", "");
5603 accopWithMisc ("rora", "");
5604 /* total: 3 cycles, 3 bytes */
5608 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5609 /* the fastest (shCount<6) and shortest (shCount<4). */
5610 for (i=0;i<shCount;i++)
5611 accopWithMisc ("lsla", "");
5615 /*-----------------------------------------------------------------*/
5616 /* AccSRsh - signed right shift accumulator by known count */
5617 /*-----------------------------------------------------------------*/
5619 AccSRsh (int shCount)
5623 shCount &= 0x0007; // shCount : 0..7
5627 accopWithMisc ("rola", "");
5628 accopWithMisc ("clra", "");
5629 accopWithMisc ("sbc", zero);
5630 /* total: 4 cycles, 4 bytes */
5634 for (i=0;i<shCount;i++)
5635 accopWithMisc ("asra", "");
5638 /*-----------------------------------------------------------------*/
5639 /* AccRsh - right shift accumulator by known count */
5640 /*-----------------------------------------------------------------*/
5642 AccRsh (int shCount, bool sign)
5652 shCount &= 0x0007; // shCount : 0..7
5654 /* Shift counts of 4 and 5 are currently optimized for code size. */
5655 /* Falling through to the unrolled loop would be optimal for code speed. */
5656 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5660 accopWithMisc ("nsa", "");
5661 accopWithMisc ("and", "#0x0f");
5662 /* total: 5 cycles, 3 bytes */
5665 accopWithMisc ("nsa", "");
5666 accopWithMisc ("and", "#0x0f");
5667 accopWithMisc ("lsra", "");
5668 /* total: 6 cycles, 4 bytes */
5671 accopWithMisc ("rola", "");
5672 accopWithMisc ("rola", "");
5673 accopWithMisc ("rola", "");
5674 accopWithMisc ("and", "#0x03");
5675 /* total: 5 cycles, 5 bytes */
5678 accopWithMisc ("rola", "");
5679 accopWithMisc ("clra", "");
5680 accopWithMisc ("rola", "");
5681 /* total: 3 cycles, 3 bytes */
5685 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5686 /* the fastest (shCount<6) and shortest (shCount<4). */
5687 for (i=0;i<shCount;i++)
5688 accopWithMisc ("lsra", "");
5692 /*-----------------------------------------------------------------*/
5693 /* XAccLsh - left shift register pair XA by known count */
5694 /*-----------------------------------------------------------------*/
5696 XAccLsh (int shCount)
5700 shCount &= 0x000f; // shCount : 0..15
5705 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5706 loadRegFromConst (hc08_reg_a, zero);
5710 /* if we can beat 2n cycles or bytes for some special case, do it here */
5714 /* bytes cycles reg x reg a carry
5715 ** abcd efgh ijkl mnop ?
5716 ** lsrx 1 1 0abc defg ijkl mnop h
5717 ** rora 1 1 0abc defg hijk lmno p
5718 ** tax 1 1 hijk lmno hijk lmno p
5719 ** clra 1 1 hijk lmno 0000 0000 p
5720 ** rora 1 1 hijk lmno p000 0000 0
5721 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5723 rmwWithReg ("lsr", hc08_reg_x);
5724 rmwWithReg ("ror", hc08_reg_a);
5725 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5726 loadRegFromConst (hc08_reg_a, zero);
5727 rmwWithReg ("ror", hc08_reg_a);
5734 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5735 /* the fastest and shortest. */
5736 for (i=0;i<shCount;i++)
5738 rmwWithReg ("lsl", hc08_reg_a);
5739 rmwWithReg ("rol", hc08_reg_x);
5743 /*-----------------------------------------------------------------*/
5744 /* XAccSRsh - signed right shift register pair XA by known count */
5745 /*-----------------------------------------------------------------*/
5747 XAccSRsh (int shCount)
5751 shCount &= 0x000f; // shCount : 0..7
5753 /* if we can beat 2n cycles or bytes for some special case, do it here */
5757 /* bytes cycles reg x reg a carry
5758 ** abcd efgh ijkl mnop ?
5759 ** lslx 1 1 bcde fgh0 ijkl mnop a
5760 ** clra 1 1 bcde fgh0 0000 0000 a
5761 ** rola 1 1 bcde fgh0 0000 000a 0
5762 ** nega 1 1 bcde fgh0 aaaa aaaa a
5763 ** tax 1 1 aaaa aaaa aaaa aaaa a
5764 ** total: 5 cycles, 5 bytes
5766 rmwWithReg ("lsl", hc08_reg_x);
5767 loadRegFromConst (hc08_reg_a, zero);
5768 rmwWithReg ("rol", hc08_reg_a);
5769 rmwWithReg ("neg", hc08_reg_a);
5770 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5780 /* bytes cycles reg x reg a carry
5781 ** abcd efgh ijkl mnop ?
5782 ** txa 1 1 abcd efgh abcd efgh ?
5783 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5784 ** lsla 1 1 abcd efgh ???? ???? a
5785 ** clrx 1 1 0000 0000 ???? ???? a
5786 ** rolx 1 1 0000 000a ???? ???? 0
5787 ** negx 1 1 aaaa aaaa ???? ???? a
5788 ** rora 1 1 aaaa aaaa LSBresult 0
5789 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5791 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5792 AccSRsh (shCount-8);
5793 rmwWithReg ("lsl", hc08_reg_a);
5794 loadRegFromConst (hc08_reg_x, zero);
5795 rmwWithReg ("rol", hc08_reg_x);
5796 rmwWithReg ("neg", hc08_reg_x);
5797 rmwWithReg ("ror", hc08_reg_a);
5804 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5805 /* the fastest and shortest. */
5806 for (i=0;i<shCount;i++)
5808 rmwWithReg ("asr", hc08_reg_x);
5809 rmwWithReg ("ror", hc08_reg_a);
5813 /*-----------------------------------------------------------------*/
5814 /* XAccRsh - right shift register pair XA by known count */
5815 /*-----------------------------------------------------------------*/
5817 XAccRsh (int shCount, bool sign)
5827 shCount &= 0x000f; // shCount : 0..f
5829 /* if we can beat 2n cycles or bytes for some special case, do it here */
5833 /* bytes cycles reg x reg a carry
5834 ** abcd efgh ijkl mnop ?
5835 ** clra 1 1 abcd efgh 0000 0000 a
5836 ** lslx 1 1 bcde fgh0 0000 0000 a
5837 ** rola 1 1 bcde fgh0 0000 000a 0
5838 ** clrx 1 1 0000 0000 0000 000a 0
5839 ** total: 4 cycles, 4 bytes
5841 loadRegFromConst (hc08_reg_x, zero);
5842 rmwWithReg ("lsl", hc08_reg_x);
5843 rmwWithReg ("rol", hc08_reg_a);
5844 loadRegFromConst (hc08_reg_a, zero);
5848 /* bytes cycles reg x reg a carry
5849 ** abcd efgh ijkl mnop ?
5850 ** clra 1 1 abcd efgh 0000 0000 a
5851 ** lslx 1 1 bcde fgh0 0000 0000 a
5852 ** rola 1 1 bcde fgh0 0000 000a 0
5853 ** lslx 1 1 cdef gh00 0000 000a b
5854 ** rola 1 1 cdef gh00 0000 00ab 0
5855 ** clrx 1 1 0000 0000 0000 00ab 0
5856 ** total: 6 cycles, 6 bytes
5858 loadRegFromConst (hc08_reg_x, zero);
5859 rmwWithReg ("lsl", hc08_reg_x);
5860 rmwWithReg ("rol", hc08_reg_a);
5861 rmwWithReg ("lsl", hc08_reg_x);
5862 rmwWithReg ("rol", hc08_reg_a);
5863 loadRegFromConst (hc08_reg_a, zero);
5872 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5873 AccRsh (shCount-8, FALSE);
5874 loadRegFromConst (hc08_reg_x, zero);
5878 /* bytes cycles reg x reg a carry
5879 ** abcd efgh ijkl mnop ?
5880 ** lsla 1 1 abcd efgh jklm nop0 i
5881 ** txa 1 1 abcd efgh abcd efgh i
5882 ** rola 1 1 abcd efgh bcde fghi a
5883 ** clrx 1 1 0000 0000 bcde fghi a
5884 ** rolx 1 1 0000 000a bcde fghi 0
5885 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5887 rmwWithReg ("lsl", hc08_reg_a);
5888 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5889 rmwWithReg ("rol", hc08_reg_a);
5890 loadRegFromConst (hc08_reg_x, zero);
5891 rmwWithReg ("rol", hc08_reg_x);
5894 /* bytes cycles reg x reg a carry
5895 ** abcd efgh ijkl mnop ?
5896 ** lsla 1 1 abcd efgh jklm nop0 i
5897 ** rolx 1 1 bcde fghi jklm nop0 a
5898 ** rola 1 1 bcde fghi klmn op0a j
5899 ** rolx 1 1 cdef ghij klmn op0a b
5900 ** rola 1 1 cdef ghij lmno p0ab k
5901 ** and #3 2 2 cdef ghij 0000 00ab k
5902 ** psha 1 2 cdef ghij 0000 00ab k
5903 ** txa 1 1 cdef ghij cdef ghij k
5904 ** pula 1 2 0000 00ab cdef ghij k
5905 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5911 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5912 /* the fastest and shortest. */
5913 for (i=0;i<shCount;i++)
5915 rmwWithReg ("lsr", hc08_reg_x);
5916 rmwWithReg ("ror", hc08_reg_a);
5923 /*-----------------------------------------------------------------*/
5924 /* shiftR1Left2Result - shift right one byte from left to result */
5925 /*-----------------------------------------------------------------*/
5927 shiftR1Left2Result (operand * left, int offl,
5928 operand * result, int offr,
5929 int shCount, int sign)
5931 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5932 /* shift right accumulator */
5933 AccRsh (shCount, sign);
5934 storeRegToAop (hc08_reg_a, AOP (result), offr);
5938 /*-----------------------------------------------------------------*/
5939 /* shiftL1Left2Result - shift left one byte from left to result */
5940 /*-----------------------------------------------------------------*/
5942 shiftL1Left2Result (operand * left, int offl,
5943 operand * result, int offr, int shCount)
5945 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5946 /* shift left accumulator */
5948 storeRegToAop (hc08_reg_a, AOP (result), offr);
5951 /*-----------------------------------------------------------------*/
5952 /* movLeft2Result - move byte from left to result */
5953 /*-----------------------------------------------------------------*/
5955 movLeft2Result (operand * left, int offl,
5956 operand * result, int offr, int sign)
5958 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5960 transferAopAop (AOP (left), offl, AOP (result), offr);
5965 /*-----------------------------------------------------------------*/
5966 /* shiftL2Left2Result - shift left two bytes from left to result */
5967 /*-----------------------------------------------------------------*/
5969 shiftL2Left2Result (operand * left, int offl,
5970 operand * result, int offr, int shCount)
5973 bool needpula = FALSE;
5974 bool needpulx = FALSE;
5976 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
5977 needpula = pushRegIfUsed (hc08_reg_a);
5980 if (!IS_AOP_XA (AOP (left)))
5981 needpulx = pushRegIfUsed (hc08_reg_x);
5985 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5990 rmwWithReg ("lsr", hc08_reg_x);
5991 rmwWithReg ("ror", hc08_reg_a);
5992 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5993 rmwWithReg ("clr", hc08_reg_a);
5994 rmwWithReg ("ror", hc08_reg_a);
5997 for (i=0; i<shCount; i++)
5999 rmwWithReg ("lsl", hc08_reg_a);
6000 rmwWithReg ("rol", hc08_reg_x);
6003 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6005 pullOrFreeReg (hc08_reg_x, needpulx);
6006 pullOrFreeReg (hc08_reg_a, needpula);
6012 /*-----------------------------------------------------------------*/
6013 /* shiftR2Left2Result - shift right two bytes from left to result */
6014 /*-----------------------------------------------------------------*/
6016 shiftR2Left2Result (operand * left, int offl,
6017 operand * result, int offr,
6018 int shCount, int sign)
6021 bool needpula = FALSE;
6022 bool needpulx = FALSE;
6024 needpula = pushRegIfUsed (hc08_reg_a);
6025 needpulx = pushRegIfUsed (hc08_reg_x);
6027 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6028 for (i=0; i<shCount; i++)
6031 rmwWithReg ("asr", hc08_reg_x);
6033 rmwWithReg ("lsr", hc08_reg_x);
6034 rmwWithReg ("ror", hc08_reg_a);
6036 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6038 pullOrFreeReg (hc08_reg_x, needpulx);
6039 pullOrFreeReg (hc08_reg_a, needpula);
6044 /*-----------------------------------------------------------------*/
6045 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6046 /*-----------------------------------------------------------------*/
6048 shiftLLeftOrResult (operand * left, int offl,
6049 operand * result, int offr, int shCount)
6051 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6052 /* shift left accumulator */
6054 /* or with result */
6055 accopWithAop ("ora", AOP (result), offr);
6056 /* back to result */
6057 storeRegToAop (hc08_reg_a, AOP (result), offr);
6058 hc08_freeReg (hc08_reg_a);
6062 /*-----------------------------------------------------------------*/
6063 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6064 /*-----------------------------------------------------------------*/
6066 shiftRLeftOrResult (operand * left, int offl,
6067 operand * result, int offr, int shCount)
6069 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6070 /* shift left accumulator */
6071 AccRsh (shCount, FALSE);
6072 /* or with result */
6073 accopWithAop ("ora", AOP (result), offr);
6074 /* back to result */
6075 storeRegToAop (hc08_reg_a, AOP (result), offr);
6076 hc08_freeReg (hc08_reg_a);
6079 /*-----------------------------------------------------------------*/
6080 /* genlshOne - left shift a one byte quantity by known count */
6081 /*-----------------------------------------------------------------*/
6083 genlshOne (operand * result, operand * left, int shCount)
6085 D(emitcode ("; genlshOne",""));
6087 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6090 /*-----------------------------------------------------------------*/
6091 /* genlshTwo - left shift two bytes by known amount != 0 */
6092 /*-----------------------------------------------------------------*/
6094 genlshTwo (operand * result, operand * left, int shCount)
6098 D(emitcode ("; genlshTwo",""));
6101 size = getDataSize (result);
6103 /* if shCount >= 8 */
6110 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6112 storeRegToAop (hc08_reg_a, AOP (result), 1);
6114 storeConstToAop(zero, AOP (result), LSB);
6117 /* 1 <= shCount <= 7 */
6120 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6122 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6126 /*-----------------------------------------------------------------*/
6127 /* shiftLLong - shift left one long from left to result */
6128 /* offl = LSB or MSB16 */
6129 /*-----------------------------------------------------------------*/
6131 shiftLLong (operand * left, operand * result, int offr)
6134 // int size = AOP_SIZE (result);
6136 bool needpula = FALSE;
6137 bool needpulx = FALSE;
6139 needpula = pushRegIfUsed (hc08_reg_a);
6140 needpulx = pushRegIfUsed (hc08_reg_x);
6142 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6143 rmwWithReg ("lsl", hc08_reg_a);
6144 rmwWithReg ("rol", hc08_reg_x);
6145 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6149 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6150 rmwWithReg ("rol", hc08_reg_a);
6151 rmwWithReg ("rol", hc08_reg_x);
6152 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6154 else if (offr==MSB16)
6156 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6157 rmwWithReg ("rol", hc08_reg_a);
6158 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6161 pullOrFreeReg (hc08_reg_x, needpulx);
6162 pullOrFreeReg (hc08_reg_a, needpula);
6165 /*-----------------------------------------------------------------*/
6166 /* genlshFour - shift four byte by a known amount != 0 */
6167 /*-----------------------------------------------------------------*/
6169 genlshFour (operand * result, operand * left, int shCount)
6173 D(emitcode ("; genlshFour",""));
6175 size = AOP_SIZE (result);
6177 /* TODO: deal with the &result == &left case */
6179 /* if shifting more that 3 bytes */
6184 /* lowest order of left goes to the highest
6185 order of the destination */
6186 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6188 movLeft2Result (left, LSB, result, MSB32, 0);
6189 storeConstToAop (zero, AOP (result), LSB);
6190 storeConstToAop (zero, AOP (result), MSB16);
6191 storeConstToAop (zero, AOP (result), MSB24);
6195 /* more than two bytes */
6196 else if (shCount >= 16)
6198 /* lower order two bytes goes to higher order two bytes */
6200 /* if some more remaining */
6202 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6205 movLeft2Result (left, MSB16, result, MSB32, 0);
6206 movLeft2Result (left, LSB, result, MSB24, 0);
6208 storeConstToAop (zero, AOP (result), LSB);
6209 storeConstToAop (zero, AOP (result), MSB16);
6213 /* if more than 1 byte */
6214 else if (shCount >= 8)
6216 /* lower order three bytes goes to higher order three bytes */
6221 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6223 movLeft2Result (left, LSB, result, MSB16, 0);
6229 movLeft2Result (left, MSB24, result, MSB32, 0);
6230 movLeft2Result (left, MSB16, result, MSB24, 0);
6231 movLeft2Result (left, LSB, result, MSB16, 0);
6232 storeConstToAop (zero, AOP (result), LSB);
6234 else if (shCount == 1)
6235 shiftLLong (left, result, MSB16);
6238 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6239 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6240 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6241 storeConstToAop (zero, AOP (result), LSB);
6246 /* 1 <= shCount <= 7 */
6247 else if (shCount <= 2)
6249 shiftLLong (left, result, LSB);
6251 shiftLLong (result, result, LSB);
6253 /* 3 <= shCount <= 7, optimize */
6256 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6257 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6258 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6262 /*-----------------------------------------------------------------*/
6263 /* genLeftShiftLiteral - left shifting by known count */
6264 /*-----------------------------------------------------------------*/
6266 genLeftShiftLiteral (operand * left,
6271 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6274 D(emitcode ("; genLeftShiftLiteral",""));
6276 freeAsmop (right, NULL, ic, TRUE);
6278 aopOp (left, ic, FALSE);
6279 aopOp (result, ic, FALSE);
6281 // size = getSize (operandType (result));
6282 size = AOP_SIZE (result);
6285 D(emitcode ("; shift left ", "result %d, left %d", size,
6292 transferAopAop( AOP(left), size, AOP(result), size);
6294 else if (shCount >= (size * 8))
6297 storeConstToAop (zero, AOP (result), size);
6304 genlshOne (result, left, shCount);
6308 genlshTwo (result, left, shCount);
6312 genlshFour (result, left, shCount);
6315 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6316 "*** ack! mystery literal shift!\n");
6320 freeAsmop (left, NULL, ic, TRUE);
6321 freeAsmop (result, NULL, ic, TRUE);
6324 /*-----------------------------------------------------------------*/
6325 /* genLeftShift - generates code for left shifting */
6326 /*-----------------------------------------------------------------*/
6328 genLeftShift (iCode * ic)
6330 operand *left, *right, *result;
6332 symbol *tlbl, *tlbl1;
6337 D(emitcode ("; genLeftShift",""));
6339 right = IC_RIGHT (ic);
6340 left = IC_LEFT (ic);
6341 result = IC_RESULT (ic);
6343 aopOp (right, ic, FALSE);
6345 /* if the shift count is known then do it
6346 as efficiently as possible */
6347 if (AOP_TYPE (right) == AOP_LIT)
6349 genLeftShiftLiteral (left, right, result, ic);
6353 /* shift count is unknown then we have to form
6354 a loop get the loop count in A : Note: we take
6355 only the lower order byte since shifting
6356 more that 32 bits make no sense anyway, ( the
6357 largest size of an object can be only 32 bits ) */
6359 aopOp (left, ic, FALSE);
6360 aopOp (result, ic, FALSE);
6362 /* now move the left to the result if they are not the
6364 if (!sameRegs (AOP (left), AOP (result)))
6367 size = AOP_SIZE (result);
6371 transferAopAop (AOP (left), offset, AOP (result), offset);
6375 freeAsmop (left, NULL, ic, TRUE);
6377 tlbl = newiTempLabel (NULL);
6378 size = AOP_SIZE (result);
6380 tlbl1 = newiTempLabel (NULL);
6384 loadRegFromAop (reg, AOP (right), 0);
6385 freeAsmop (right, NULL, ic, TRUE);
6386 emitBranch ("beq", tlbl1);
6390 for (offset=0;offset<size;offset++)
6392 rmwWithAop (shift, AOP (result), offset);
6395 rmwWithReg ("dec", reg);
6396 emitBranch ("bne", tlbl);
6400 freeAsmop (result, NULL, ic, TRUE);
6403 /*-----------------------------------------------------------------*/
6404 /* genrshOne - right shift a one byte quantity by known count */
6405 /*-----------------------------------------------------------------*/
6407 genrshOne (operand * result, operand * left,
6408 int shCount, int sign)
6410 D(emitcode ("; genrshOne",""));
6412 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6413 AccRsh (shCount, sign);
6414 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6417 /*-----------------------------------------------------------------*/
6418 /* genrshTwo - right shift two bytes by known amount != 0 */
6419 /*-----------------------------------------------------------------*/
6421 genrshTwo (operand * result, operand * left,
6422 int shCount, int sign)
6424 D(emitcode ("; genrshTwo",""));
6426 /* if shCount >= 8 */
6429 if (shCount || sign)
6431 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6432 AccRsh (shCount-8, sign);
6433 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6437 transferAopAop (AOP (left), 1, AOP (result), 0);
6438 storeConstToAop (zero, AOP (result), 1);
6442 /* 1 <= shCount <= 7 */
6445 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6446 XAccRsh (shCount, sign);
6447 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6451 /*-----------------------------------------------------------------*/
6452 /* shiftRLong - shift right one long from left to result */
6453 /* offl = LSB or MSB16 */
6454 /*-----------------------------------------------------------------*/
6456 shiftRLong (operand * left, int offl,
6457 operand * result, int sign)
6460 // int size = AOP_SIZE (result);
6462 bool needpula = FALSE;
6463 bool needpulx = FALSE;
6465 needpula = pushRegIfUsed (hc08_reg_a);
6466 needpulx = pushRegIfUsed (hc08_reg_x);
6470 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6472 rmwWithReg ("asr", hc08_reg_x);
6474 rmwWithReg ("lsr", hc08_reg_x);
6475 rmwWithReg ("rol", hc08_reg_a);
6476 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6478 else if (offl==MSB16)
6480 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6482 rmwWithReg ("asr", hc08_reg_a);
6484 rmwWithReg ("lsr", hc08_reg_a);
6485 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6488 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6489 rmwWithReg ("ror", hc08_reg_x);
6490 rmwWithReg ("ror", hc08_reg_a);
6491 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6494 pullOrFreeReg (hc08_reg_x, needpulx);
6495 pullOrFreeReg (hc08_reg_a, needpula);
6498 /*-----------------------------------------------------------------*/
6499 /* genrshFour - shift four byte by a known amount != 0 */
6500 /*-----------------------------------------------------------------*/
6502 genrshFour (operand * result, operand * left,
6503 int shCount, int sign)
6505 /* TODO: handle cases where left == result */
6507 D(emitcode ("; genrshFour",""));
6509 /* if shifting more that 3 bytes */
6512 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6513 AccRsh (shCount-24, sign);
6514 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6517 else if (shCount >= 16)
6519 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6520 XAccRsh (shCount-16, sign);
6521 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6524 else if (shCount >= 8)
6527 shiftRLong (left, MSB16, result, sign);
6528 else if (shCount == 8)
6530 transferAopAop (AOP (left), 1, AOP (result), 0);
6531 transferAopAop (AOP (left), 2, AOP (result), 1);
6532 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6533 storeRegToAop (hc08_reg_a, AOP (result), 2);
6534 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6536 else if (shCount == 9)
6538 shiftRLong (left, MSB16, result, sign);
6542 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6543 XAccRsh (shCount-8, FALSE);
6544 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6545 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6546 loadRegFromConst (hc08_reg_a, zero);
6547 XAccRsh (shCount-8, sign);
6548 accopWithAop ("ora", AOP (result), 1);
6549 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6553 { /* 1 <= shCount <= 7 */
6556 shiftRLong (left, LSB, result, sign);
6560 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6561 XAccRsh (shCount, FALSE);
6562 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6563 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6565 accopWithAop ("ora", AOP (result), 1);
6566 storeRegToAop (hc08_reg_a, AOP (result), 1);
6567 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6568 XAccRsh (shCount, sign);
6569 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6574 /*-----------------------------------------------------------------*/
6575 /* genRightShiftLiteral - right shifting by known count */
6576 /*-----------------------------------------------------------------*/
6578 genRightShiftLiteral (operand * left,
6584 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6587 D(emitcode ("; genRightShiftLiteral",""));
6589 freeAsmop (right, NULL, ic, TRUE);
6591 aopOp (left, ic, FALSE);
6592 aopOp (result, ic, FALSE);
6595 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6599 size = getDataSize (left);
6600 /* test the LEFT size !!! */
6602 /* I suppose that the left size >= result size */
6605 size = getDataSize (result);
6607 transferAopAop (AOP (left), size, AOP(result), size);
6609 else if (shCount >= (size * 8))
6612 /* get sign in acc.7 */
6613 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6615 addSign (result, LSB, sign);
6622 genrshOne (result, left, shCount, sign);
6626 genrshTwo (result, left, shCount, sign);
6630 genrshFour (result, left, shCount, sign);
6636 freeAsmop (left, NULL, ic, TRUE);
6637 freeAsmop (result, NULL, ic, TRUE);
6641 /*-----------------------------------------------------------------*/
6642 /* genRightShift - generate code for right shifting */
6643 /*-----------------------------------------------------------------*/
6645 genRightShift (iCode * ic)
6647 operand *right, *left, *result;
6651 symbol *tlbl, *tlbl1;
6655 D(emitcode ("; genRightShift",""));
6657 /* if signed then we do it the hard way preserve the
6658 sign bit moving it inwards */
6659 retype = getSpec (operandType (IC_RESULT (ic)));
6660 sign = !SPEC_USIGN (retype);
6662 /* signed & unsigned types are treated the same : i.e. the
6663 signed is NOT propagated inwards : quoting from the
6664 ANSI - standard : "for E1 >> E2, is equivalent to division
6665 by 2**E2 if unsigned or if it has a non-negative value,
6666 otherwise the result is implementation defined ", MY definition
6667 is that the sign does not get propagated */
6669 right = IC_RIGHT (ic);
6670 left = IC_LEFT (ic);
6671 result = IC_RESULT (ic);
6673 aopOp (right, ic, FALSE);
6675 /* if the shift count is known then do it
6676 as efficiently as possible */
6677 if (AOP_TYPE (right) == AOP_LIT)
6679 genRightShiftLiteral (left, right, result, ic, sign);
6683 /* shift count is unknown then we have to form
6684 a loop get the loop count in X : Note: we take
6685 only the lower order byte since shifting
6686 more that 32 bits make no sense anyway, ( the
6687 largest size of an object can be only 32 bits ) */
6689 aopOp (left, ic, FALSE);
6690 aopOp (result, ic, FALSE);
6692 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6693 AOP (result) = forceStackedAop (AOP (result));
6695 size = AOP_SIZE (result);
6699 transferAopAop (AOP (left), offset, AOP (result), offset);
6703 tlbl = newiTempLabel (NULL);
6704 size = AOP_SIZE (result);
6706 tlbl1 = newiTempLabel (NULL);
6708 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6709 emitcode ("tstx", "");
6710 emitcode ("beq", "%05d$", tlbl1->key + 100);
6711 emitcode ("", "%05d$:", tlbl->key + 100);
6712 shift= sign ? "asr" : "lsr";
6713 for (offset=size-1;offset>=0;offset--)
6715 rmwWithAop (shift, AOP (result), offset);
6718 rmwWithReg ("dec", hc08_reg_x);
6719 emitcode ("bne","%05d$", tlbl->key + 100);
6720 emitcode ("", "%05d$:", tlbl1->key + 100);
6722 freeAsmop (result, NULL, ic, TRUE);
6723 freeAsmop (left, NULL, ic, TRUE);
6724 freeAsmop (right, NULL, ic, TRUE);
6728 /*-----------------------------------------------------------------*/
6729 /* genUnpackBits - generates code for unpacking bits */
6730 /*-----------------------------------------------------------------*/
6732 genUnpackBits (operand * result, iCode *ifx)
6734 int offset = 0; /* result byte offset */
6735 int rsize; /* result size */
6736 int rlen = 0; /* remaining bitfield length */
6737 sym_link *etype; /* bitfield type information */
6738 int blen; /* bitfield length */
6739 int bstr; /* bitfield starting bit within byte */
6741 D(emitcode ("; genUnpackBits",""));
6743 etype = getSpec (operandType (result));
6744 rsize = getSize (operandType (result));
6745 blen = SPEC_BLEN (etype);
6746 bstr = SPEC_BSTR (etype);
6748 /* If the bitfield length is less than a byte */
6751 emitcode ("lda", ",x");
6752 hc08_dirtyReg (hc08_reg_a, FALSE);
6755 AccRsh (bstr, FALSE);
6756 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6757 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6761 emitcode ("and", "#0x%02x",
6762 (((unsigned char) -1) >> (8 - blen)) << bstr);
6767 /* Bit field did not fit in a byte. Copy all
6768 but the partial byte at the end. */
6769 for (rlen=blen;rlen>=8;rlen-=8)
6771 emitcode ("lda", ",x");
6772 hc08_dirtyReg (hc08_reg_a, FALSE);
6774 storeRegToAop (hc08_reg_a, AOP (result), offset);
6777 emitcode ("aix", "#1");
6780 /* Handle the partial byte at the end */
6783 emitcode ("lda", ",x");
6784 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6785 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6793 storeConstToAop (zero, AOP (result), offset++);
6796 if (ifx && !ifx->generated)
6798 genIfxJump (ifx, "a");
6803 /*-----------------------------------------------------------------*/
6804 /* genUnpackBitsImmed - generates code for unpacking bits */
6805 /*-----------------------------------------------------------------*/
6807 genUnpackBitsImmed (operand * left,
6813 int offset = 0; /* result byte offset */
6814 int rsize; /* result size */
6815 int rlen = 0; /* remaining bitfield length */
6816 sym_link *etype; /* bitfield type information */
6817 int blen; /* bitfield length */
6818 int bstr; /* bitfield starting bit within byte */
6821 D(emitcode ("; genUnpackBitsImmed",""));
6823 aopOp (result, ic, TRUE);
6824 size = AOP_SIZE (result);
6826 derefaop = aopDerefAop (AOP (left));
6827 freeAsmop (left, NULL, ic, TRUE);
6828 derefaop->size = size;
6830 etype = getSpec (operandType (result));
6831 rsize = getSize (operandType (result));
6832 blen = SPEC_BLEN (etype);
6833 bstr = SPEC_BSTR (etype);
6835 /* if the bitfield is a single bit in the direct page */
6836 if (blen == 1 && derefaop->type == AOP_DIR)
6840 symbol *tlbl = newiTempLabel (NULL);
6842 loadRegFromConst (hc08_reg_a, zero);
6843 emitcode ("brclr", "#%d,%s,%05d$",
6844 bstr, aopAdrStr (derefaop, 0, FALSE),
6846 rmwWithReg ("inc", hc08_reg_a);
6848 storeRegToAop (hc08_reg_a, AOP (result), offset);
6849 hc08_freeReg (hc08_reg_a);
6855 symbol *tlbl = newiTempLabel (NULL);
6861 jlbl = IC_TRUE (ifx);
6866 jlbl = IC_FALSE (ifx);
6869 emitcode (inst, "#%d,%s,%05d$",
6870 bstr, aopAdrStr (derefaop, 0, FALSE),
6872 emitBranch ("jmp", jlbl);
6880 /* If the bitfield length is less than a byte */
6883 loadRegFromAop (hc08_reg_a, derefaop, 0);
6886 AccRsh (bstr, FALSE);
6887 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6888 hc08_dirtyReg (hc08_reg_a, FALSE);
6889 storeRegToAop (hc08_reg_a, AOP (result), offset);
6893 emitcode ("and", "#0x%02x",
6894 (((unsigned char) -1) >> (8 - blen)) << bstr);
6895 hc08_dirtyReg (hc08_reg_a, FALSE);
6901 /* Bit field did not fit in a byte. Copy all
6902 but the partial byte at the end. */
6903 for (rlen=blen;rlen>=8;rlen-=8)
6905 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6907 storeRegToAop (hc08_reg_a, AOP (result), offset);
6909 emitcode ("tsta", "");
6913 /* Handle the partial byte at the end */
6916 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6917 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6918 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6926 storeConstToAop (zero, AOP (result), offset++);
6929 freeAsmop (NULL, derefaop, ic, TRUE);
6930 freeAsmop (result, NULL, ic, TRUE);
6932 if (ifx && !ifx->generated)
6934 genIfxJump (ifx, "a");
6939 /*-----------------------------------------------------------------*/
6940 /* genDataPointerGet - generates code when ptr offset is known */
6941 /*-----------------------------------------------------------------*/
6943 genDataPointerGet (operand * left,
6948 int size, offset = 0;
6951 D(emitcode ("; genDataPointerGet",""));
6953 aopOp (result, ic, TRUE);
6954 size = AOP_SIZE (result);
6956 derefaop = aopDerefAop (AOP (left));
6957 freeAsmop (left, NULL, ic, TRUE);
6958 derefaop->size = size;
6963 transferAopAop (derefaop, offset, AOP (result), offset);
6965 loadRegFromAop (hc08_reg_a, derefaop, offset);
6969 freeAsmop (NULL, derefaop, ic, TRUE);
6970 freeAsmop (result, NULL, ic, TRUE);
6972 if (ifx && !ifx->generated)
6974 genIfxJump (ifx, "a");
6979 /*-----------------------------------------------------------------*/
6980 /* genPointerGet - generate code for pointer get */
6981 /*-----------------------------------------------------------------*/
6983 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
6985 operand *left = IC_LEFT (ic);
6986 operand *result = IC_RESULT (ic);
6988 sym_link *retype = getSpec (operandType (result));
6990 D(emitcode ("; genPointerGet",""));
6992 if (getSize (operandType (result))>1)
6995 aopOp (left, ic, FALSE);
6997 /* if left is rematerialisable and
6998 result is not bit variable type */
6999 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7001 if (!IS_BITVAR (retype))
7003 genDataPointerGet (left, result, ic, ifx);
7008 genUnpackBitsImmed (left, result, ic, ifx);
7013 /* if the operand is already in hx
7014 then we do nothing else we move the value to hx */
7015 if (AOP_TYPE (left) != AOP_STR)
7017 /* if this is remateriazable */
7018 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7021 /* so hx now contains the address */
7022 aopOp (result, ic, FALSE);
7024 /* if bit then unpack */
7025 if (IS_BITVAR (retype))
7026 genUnpackBits (result, ifx);
7029 size = AOP_SIZE (result);
7034 accopWithMisc ("lda", ",x");
7037 emitcode ("aix", "#1");
7038 hc08_dirtyReg (hc08_reg_hx, FALSE);
7041 storeRegToAop (hc08_reg_a, AOP (result), offset);
7043 hc08_freeReg (hc08_reg_a);
7047 freeAsmop (left, NULL, ic, TRUE);
7048 freeAsmop (result, NULL, ic, TRUE);
7051 aopOp (IC_RESULT (pi), pi, FALSE);
7052 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7053 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7057 if (ifx && !ifx->generated)
7059 genIfxJump (ifx, "a");
7062 hc08_freeReg (hc08_reg_hx);
7066 /*-----------------------------------------------------------------*/
7067 /* genPackBits - generates code for packed bit storage */
7068 /*-----------------------------------------------------------------*/
7070 genPackBits (sym_link * etype,
7073 int offset = 0; /* source byte offset */
7074 int rlen = 0; /* remaining bitfield length */
7075 int blen; /* bitfield length */
7076 int bstr; /* bitfield starting bit within byte */
7077 int litval; /* source literal value (if AOP_LIT) */
7078 unsigned char mask; /* bitmask within current byte */
7081 D(emitcode ("; genPackBits",""));
7083 blen = SPEC_BLEN (etype);
7084 bstr = SPEC_BSTR (etype);
7086 /* If the bitfield length is less than a byte */
7089 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7090 (unsigned char) (0xFF >> (8 - bstr)));
7092 if (AOP_TYPE (right) == AOP_LIT)
7094 /* Case with a bitfield length <8 and literal source
7096 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7098 litval &= (~mask) & 0xff;
7100 emitcode ("lda", ",x");
7101 if ((mask|litval)!=0xff)
7102 emitcode ("and","#0x%02x", mask);
7104 emitcode ("ora","#0x%02x", litval);
7105 hc08_dirtyReg (hc08_reg_a, FALSE);
7106 emitcode ("sta", ",x");
7108 hc08_freeReg (hc08_reg_a);
7112 /* Case with a bitfield length < 8 and arbitrary source
7114 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7115 /* shift and mask source value */
7117 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7118 hc08_dirtyReg (hc08_reg_a, FALSE);
7119 pushReg (hc08_reg_a, TRUE);
7121 emitcode ("lda", ",x");
7122 emitcode ("and", "#0x%02x", mask);
7123 emitcode ("ora", "1,s");
7124 emitcode ("sta", ",x");
7125 pullReg (hc08_reg_a);
7127 hc08_freeReg (hc08_reg_a);
7131 /* Bit length is greater than 7 bits. In this case, copy */
7132 /* all except the partial byte at the end */
7133 for (rlen=blen;rlen>=8;rlen-=8)
7135 if (AOP (right)->type == AOP_DIR)
7137 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7142 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7143 emitcode ("sta", "%d,x", offset);
7148 /* If there was a partial byte at the end */
7151 mask = (((unsigned char) -1 << rlen) & 0xff);
7153 if (AOP_TYPE (right) == AOP_LIT)
7155 /* Case with partial byte and literal source
7157 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7158 litval >>= (blen-rlen);
7159 litval &= (~mask) & 0xff;
7160 emitcode ("lda", "%d,x", offset - xoffset);
7161 hc08_dirtyReg (hc08_reg_a, FALSE);
7162 if ((mask|litval)!=0xff)
7163 emitcode ("and","#0x%02x", mask);
7165 emitcode ("ora","#0x%02x", litval);
7166 emitcode ("sta", "%d,x", offset - xoffset);
7167 hc08_dirtyReg (hc08_reg_a, FALSE);
7168 hc08_freeReg (hc08_reg_a);
7172 /* Case with partial byte and arbitrary source
7174 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7175 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7176 hc08_dirtyReg (hc08_reg_a, FALSE);
7177 pushReg (hc08_reg_a, TRUE);
7179 emitcode ("lda", "%d,x", offset - xoffset);
7180 emitcode ("and", "#0x%02x", mask);
7181 emitcode ("ora", "1,s");
7182 emitcode ("sta", "%d,x", offset - xoffset);
7183 pullReg (hc08_reg_a);
7186 hc08_freeReg (hc08_reg_a);
7189 /*-----------------------------------------------------------------*/
7190 /* genPackBitsImmed - generates code for packed bit storage */
7191 /*-----------------------------------------------------------------*/
7193 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7197 int offset = 0; /* source byte offset */
7198 int rlen = 0; /* remaining bitfield length */
7199 int blen; /* bitfield length */
7200 int bstr; /* bitfield starting bit within byte */
7201 int litval; /* source literal value (if AOP_LIT) */
7202 unsigned char mask; /* bitmask within current byte */
7204 D(emitcode ("; genPackBitsImmed",""));
7206 blen = SPEC_BLEN (etype);
7207 bstr = SPEC_BSTR (etype);
7209 aopOp (right, ic, FALSE);
7210 size = AOP_SIZE (right);
7212 derefaop = aopDerefAop (AOP (result));
7213 freeAsmop (result, NULL, ic, TRUE);
7214 derefaop->size = size;
7216 /* if the bitfield is a single bit in the direct page */
7217 if (blen == 1 && derefaop->type == AOP_DIR)
7219 if (AOP_TYPE (right) == AOP_LIT)
7221 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7223 emitcode ((litval & 1) ? "bset" : "bclr",
7224 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7228 symbol *tlbl1 = newiTempLabel (NULL);
7229 symbol *tlbl2 = newiTempLabel (NULL);
7231 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7232 emitcode ("bit", "#1");
7233 emitBranch ("bne", tlbl1);
7234 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7235 emitBranch ("bra", tlbl2);
7237 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7239 hc08_freeReg (hc08_reg_a);
7244 /* If the bitfield length is less than a byte */
7247 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7248 (unsigned char) (0xFF >> (8 - bstr)));
7250 if (AOP_TYPE (right) == AOP_LIT)
7252 /* Case with a bitfield length <8 and literal source
7254 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7256 litval &= (~mask) & 0xff;
7258 loadRegFromAop (hc08_reg_a, derefaop, 0);
7259 if ((mask|litval)!=0xff)
7260 emitcode ("and","#0x%02x", mask);
7262 emitcode ("ora","#0x%02x", litval);
7263 hc08_dirtyReg (hc08_reg_a, FALSE);
7264 storeRegToAop (hc08_reg_a, derefaop, 0);
7266 hc08_freeReg (hc08_reg_a);
7270 /* Case with a bitfield length < 8 and arbitrary source
7272 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7273 /* shift and mask source value */
7275 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7276 hc08_dirtyReg (hc08_reg_a, FALSE);
7277 pushReg (hc08_reg_a, TRUE);
7279 loadRegFromAop (hc08_reg_a, derefaop, 0);
7280 emitcode ("and", "#0x%02x", mask);
7281 emitcode ("ora", "1,s");
7282 storeRegToAop (hc08_reg_a, derefaop, 0);
7283 pullReg (hc08_reg_a);
7285 hc08_freeReg (hc08_reg_a);
7289 /* Bit length is greater than 7 bits. In this case, copy */
7290 /* all except the partial byte at the end */
7291 for (rlen=blen;rlen>=8;rlen-=8)
7293 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7297 /* If there was a partial byte at the end */
7300 mask = (((unsigned char) -1 << rlen) & 0xff);
7302 if (AOP_TYPE (right) == AOP_LIT)
7304 /* Case with partial byte and literal source
7306 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7307 litval >>= (blen-rlen);
7308 litval &= (~mask) & 0xff;
7309 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7310 if ((mask|litval)!=0xff)
7311 emitcode ("and","#0x%02x", mask);
7313 emitcode ("ora","#0x%02x", litval);
7314 hc08_dirtyReg (hc08_reg_a, FALSE);
7315 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7316 hc08_dirtyReg (hc08_reg_a, FALSE);
7317 hc08_freeReg (hc08_reg_a);
7321 /* Case with partial byte and arbitrary source
7323 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7324 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7325 hc08_dirtyReg (hc08_reg_a, FALSE);
7326 pushReg (hc08_reg_a, TRUE);
7328 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7329 emitcode ("and", "#0x%02x", mask);
7330 emitcode ("ora", "1,s");
7331 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7332 pullReg (hc08_reg_a);
7335 hc08_freeReg (hc08_reg_a);
7338 freeAsmop (right, NULL, ic, TRUE);
7339 freeAsmop (NULL, derefaop, ic, TRUE);
7342 /*-----------------------------------------------------------------*/
7343 /* genDataPointerSet - remat pointer to data space */
7344 /*-----------------------------------------------------------------*/
7346 genDataPointerSet (operand * right,
7350 int size, offset = 0;
7353 D(emitcode ("; genDataPointerSet",""));
7355 aopOp (right, ic, FALSE);
7356 size = AOP_SIZE (right);
7358 derefaop = aopDerefAop (AOP (result));
7359 freeAsmop (result, NULL, ic, TRUE);
7360 derefaop->size = size;
7364 transferAopAop (AOP (right), offset, derefaop, offset);
7368 freeAsmop (right, NULL, ic, TRUE);
7369 freeAsmop (NULL, derefaop, ic, TRUE);
7373 /*-----------------------------------------------------------------*/
7374 /* genPointerSet - stores the value into a pointer location */
7375 /*-----------------------------------------------------------------*/
7377 genPointerSet (iCode * ic, iCode *pi)
7379 operand *right = IC_RIGHT (ic);
7380 operand *result = IC_RESULT (ic);
7381 sym_link *type, *etype;
7383 sym_link *retype = getSpec (operandType (right));
7384 sym_link *letype = getSpec (operandType (result));
7386 D(emitcode ("; genPointerSet",""));
7388 type = operandType (result);
7389 etype = getSpec (type);
7391 aopOp (result, ic, FALSE);
7393 /* if the result is rematerializable */
7394 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7396 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7398 genDataPointerSet (right, result, ic);
7403 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7408 /* if the operand is already in hx
7409 then we do nothing else we move the value to hx */
7410 if (AOP_TYPE (result) != AOP_STR)
7412 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7414 /* so hx now contains the address */
7415 aopOp (right, ic, FALSE);
7417 /* if bit then unpack */
7418 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7419 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7422 size = AOP_SIZE (right);
7427 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7428 accopWithMisc ("sta", ",x");
7431 emitcode ("aix", "#1");
7433 hc08_freeReg (hc08_reg_a);
7437 freeAsmop (result, NULL, ic, TRUE);
7438 freeAsmop (right, NULL, ic, TRUE);
7441 aopOp (IC_RESULT (pi), pi, FALSE);
7442 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7443 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7447 hc08_freeReg (hc08_reg_hx);
7451 /*-----------------------------------------------------------------*/
7452 /* genIfx - generate code for Ifx statement */
7453 /*-----------------------------------------------------------------*/
7455 genIfx (iCode * ic, iCode * popIc)
7457 operand *cond = IC_COND (ic);
7460 D(emitcode ("; genIfx",""));
7462 aopOp (cond, ic, FALSE);
7464 /* get the value into acc */
7465 if (AOP_TYPE (cond) != AOP_CRY)
7466 asmopToBool (AOP (cond), FALSE);
7469 /* the result is now in the accumulator */
7470 freeAsmop (cond, NULL, ic, TRUE);
7472 /* if there was something to be popped then do it */
7476 /* if the condition is a bit variable */
7477 if (isbit && IS_ITEMP (cond) &&
7479 genIfxJump (ic, SPIL_LOC (cond)->rname);
7480 else if (isbit && !IS_ITEMP (cond))
7481 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7483 genIfxJump (ic, "a");
7488 /*-----------------------------------------------------------------*/
7489 /* genAddrOf - generates code for address of */
7490 /*-----------------------------------------------------------------*/
7492 genAddrOf (iCode * ic)
7494 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7497 D(emitcode ("; genAddrOf",""));
7499 aopOp (IC_RESULT (ic), ic, FALSE);
7501 /* if the operand is on the stack then we
7502 need to get the stack offset of this
7506 /* if it has an offset then we need to compute
7508 hc08_useReg (hc08_reg_hx);
7509 emitcode ("tsx", "");
7510 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7511 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7512 hc08_freeReg (hc08_reg_hx);
7517 /* object not on stack then we need the name */
7518 size = AOP_SIZE (IC_RESULT (ic));
7523 char s[SDCC_NAME_MAX+10];
7526 sprintf (s, "#%s", sym->rname);
7529 sprintf (s, "#>%s", sym->rname);
7532 sprintf (s, "#(%s >> %d)",
7536 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7540 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7544 /*-----------------------------------------------------------------*/
7545 /* genAssign - generate code for assignment */
7546 /*-----------------------------------------------------------------*/
7548 genAssign (iCode * ic)
7550 operand *result, *right;
7552 // unsigned long lit = 0L;
7554 D(emitcode("; genAssign",""));
7556 result = IC_RESULT (ic);
7557 right = IC_RIGHT (ic);
7559 /* if they are the same */
7560 if (operandsEqu (result, right)) {
7564 aopOp (right, ic, FALSE);
7565 aopOp (result, ic, TRUE);
7567 /* if they are the same registers */
7568 if (sameRegs (AOP (right), AOP (result)))
7571 if ((AOP_TYPE (right) == AOP_LIT)
7572 && (IS_AOP_HX(AOP(result))))
7574 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7579 size = AOP_SIZE (result);
7584 transferAopAop (AOP (right), offset, AOP (result), offset);
7589 freeAsmop (right, NULL, ic, TRUE);
7590 freeAsmop (result, NULL, ic, TRUE);
7593 /*-----------------------------------------------------------------*/
7594 /* genJumpTab - genrates code for jump table */
7595 /*-----------------------------------------------------------------*/
7597 genJumpTab (iCode * ic)
7602 D(emitcode ("; genJumpTab",""));
7604 aopOp (IC_JTCOND (ic), ic, FALSE);
7605 /* get the condition into accumulator */
7606 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7607 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7608 /* multiply by three */
7609 pushReg (hc08_reg_a, FALSE);
7610 emitcode ("lsla", "");
7611 emitcode ("add","1,s");
7612 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7613 loadRegFromConst (hc08_reg_h, zero);
7614 pullReg (hc08_reg_a);
7616 jtab = newiTempLabel (NULL);
7617 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7618 emitcode ("", "%05d$:", jtab->key + 100);
7619 /* now generate the jump labels */
7620 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7621 jtab = setNextItem (IC_JTLABELS (ic)))
7622 emitcode ("jmp", "%05d$", jtab->key + 100);
7624 hc08_dirtyReg (hc08_reg_a, TRUE);
7625 hc08_dirtyReg (hc08_reg_hx, TRUE);
7628 /*-----------------------------------------------------------------*/
7629 /* genCast - gen code for casting */
7630 /*-----------------------------------------------------------------*/
7632 genCast (iCode * ic)
7634 operand *result = IC_RESULT (ic);
7635 sym_link *ctype = operandType (IC_LEFT (ic));
7636 sym_link *rtype = operandType (IC_RIGHT (ic));
7637 operand *right = IC_RIGHT (ic);
7640 D(emitcode("; genCast",""));
7642 /* if they are equivalent then do nothing */
7643 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7646 aopOp (right, ic, FALSE);
7647 aopOp (result, ic, FALSE);
7650 /* if they are the same size : or less */
7651 if (AOP_SIZE (result) <= AOP_SIZE (right))
7654 /* if they are in the same place */
7656 if (sameRegs (AOP (right), AOP (result)))
7660 /* if they in different places then copy */
7661 size = AOP_SIZE (result);
7665 transferAopAop(AOP (right), offset, AOP (result), offset);
7672 /* if the result is of type pointer */
7677 sym_link *type = operandType (right);
7678 sym_link *etype = getSpec (type);
7680 /* pointer to generic pointer */
7681 if (IS_GENPTR (ctype))
7684 p_type = DCL_TYPE (type);
7687 if (SPEC_SCLS(etype)==S_REGISTER) {
7688 // let's assume it is a generic pointer
7691 /* we have to go by the storage class */
7692 p_type = PTR_TYPE (SPEC_OCLS (etype));
7696 /* the first two bytes are known */
7697 size = GPTRSIZE - 1;
7701 transferAopAop(AOP (right), offset, AOP (result), offset);
7704 /* the last byte depending on type */
7707 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7712 // pointerTypeToGPByte will have bitched.
7716 sprintf(gpValStr, "#0x%d", gpVal);
7717 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7723 /* just copy the pointers */
7724 size = AOP_SIZE (result);
7728 transferAopAop(AOP (right), offset, AOP (result), offset);
7734 /* so we now know that the size of destination is greater
7735 than the size of the source */
7736 /* we move to result for the size of source */
7737 size = AOP_SIZE (right);
7741 transferAopAop(AOP (right), offset, AOP (result), offset);
7745 /* now depending on the sign of the source && destination */
7746 size = AOP_SIZE (result) - AOP_SIZE (right);
7747 /* if unsigned or not an integral type */
7748 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7751 storeConstToAop (zero, AOP (result), offset++);
7755 /* we need to extend the sign :{ */
7756 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7757 accopWithMisc ("rola", "");
7758 accopWithMisc ("clra", "");
7759 accopWithMisc ("sbc", zero);
7761 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7764 /* we are done hurray !!!! */
7767 freeAsmop (right, NULL, ic, TRUE);
7768 freeAsmop (result, NULL, ic, TRUE);
7772 /*-----------------------------------------------------------------*/
7773 /* genDjnz - generate decrement & jump if not zero instrucion */
7774 /*-----------------------------------------------------------------*/
7776 genDjnz (iCode * ic, iCode * ifx)
7782 D(emitcode ("; genDjnz",""));
7784 /* if the if condition has a false label
7785 then we cannot save */
7789 /* if the minus is not of the form
7791 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7792 !IS_OP_LITERAL (IC_RIGHT (ic)))
7795 if (operandLitValue (IC_RIGHT (ic)) != 1)
7798 /* dbnz doesn't support extended mode */
7799 if (isOperandInFarSpace (IC_RESULT (ic)))
7802 /* if the size of this greater than one then no
7804 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7806 aopOp (IC_RESULT (ic), ic, FALSE);
7807 if (AOP_SIZE (IC_RESULT (ic))>1)
7809 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7813 /* otherwise we can save BIG */
7814 lbl = newiTempLabel (NULL);
7815 lbl1 = newiTempLabel (NULL);
7818 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7821 emitBranch ("bra", lbl1);
7823 emitBranch ("jmp", IC_TRUE (ifx));
7826 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7831 /*-----------------------------------------------------------------*/
7832 /* genReceive - generate code for a receive iCode */
7833 /*-----------------------------------------------------------------*/
7835 genReceive (iCode * ic)
7839 D(emitcode ("; genReceive",""));
7841 aopOp (IC_RESULT (ic), ic, FALSE);
7842 size = AOP_SIZE (IC_RESULT (ic));
7847 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7848 AOP (IC_RESULT (ic)), offset);
7849 if (hc08_aop_pass[offset]->type == AOP_REG)
7850 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7855 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7858 /*-----------------------------------------------------------------*/
7859 /* genDummyRead - generate code for dummy read of volatiles */
7860 /*-----------------------------------------------------------------*/
7862 genDummyRead (iCode * ic)
7867 D(emitcode("; genDummyRead",""));
7870 if (op && IS_SYMOP (op))
7873 aopOp (op, ic, FALSE);
7875 size = AOP_SIZE (op);
7880 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7881 hc08_freeReg (hc08_reg_a);
7885 freeAsmop (op, NULL, ic, TRUE);
7888 if (op && IS_SYMOP (op))
7891 aopOp (op, ic, FALSE);
7893 size = AOP_SIZE (op);
7898 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7899 hc08_freeReg (hc08_reg_a);
7903 freeAsmop (op, NULL, ic, TRUE);
7907 /*-----------------------------------------------------------------*/
7908 /* genCritical - generate code for start of a critical sequence */
7909 /*-----------------------------------------------------------------*/
7911 genCritical (iCode *ic)
7913 D(emitcode("; genCritical",""));
7916 aopOp (IC_RESULT (ic), ic, TRUE);
7918 emitcode ("tpa", "");
7919 hc08_dirtyReg (hc08_reg_a, FALSE);
7920 emitcode ("sei", "");
7923 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7925 pushReg (hc08_reg_a, FALSE);
7927 hc08_freeReg (hc08_reg_a);
7929 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7932 /*-----------------------------------------------------------------*/
7933 /* genEndCritical - generate code for end of a critical sequence */
7934 /*-----------------------------------------------------------------*/
7936 genEndCritical (iCode *ic)
7938 D(emitcode("; genEndCritical",""));
7942 aopOp (IC_RIGHT (ic), ic, FALSE);
7943 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7944 emitcode ("tap", "");
7945 hc08_freeReg (hc08_reg_a);
7946 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7950 pullReg (hc08_reg_a);
7951 emitcode ("tap", "");
7957 /*-----------------------------------------------------------------*/
7958 /* genhc08Code - generate code for HC08 based controllers */
7959 /*-----------------------------------------------------------------*/
7961 genhc08Code (iCode * lic)
7968 lineHead = lineCurr = NULL;
7970 /* print the allocation information */
7971 if (allocInfo && currFunc)
7972 printAllocInfo (currFunc, codeOutFile);
7973 /* if debug information required */
7974 if (options.debug && currFunc)
7976 debugFile->writeFunction (currFunc, lic);
7979 if (IS_STATIC (currFunc->etype))
7980 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7982 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7986 /* stack pointer name */
7987 if (options.useXstack)
7992 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
7994 hc08_aop_pass[0] = newAsmop (AOP_REG);
7995 hc08_aop_pass[0]->size=1;
7996 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7997 hc08_aop_pass[1] = newAsmop (AOP_REG);
7998 hc08_aop_pass[1]->size=1;
7999 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8000 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8001 hc08_aop_pass[2]->size=1;
8002 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8003 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8004 hc08_aop_pass[3]->size=1;
8005 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8007 for (ic = lic; ic; ic = ic->next)
8010 _G.current_iCode = ic;
8012 if (ic->level != clevel || ic->block != cblock)
8016 debugFile->writeScope(ic);
8022 if (ic->lineno && cln != ic->lineno)
8026 debugFile->writeCLine(ic);
8029 emitcode ("", "C$%s$%d$%d$%d ==.",
8030 FileBaseName (ic->filename), ic->lineno,
8031 ic->level, ic->block);
8035 if (!options.noCcodeInAsm) {
8036 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8037 printCLine(ic->filename, ic->lineno));
8041 if (options.iCodeInAsm) {
8045 for (i=0; i<6; i++) {
8046 sprintf (®sInUse[i],
8047 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8050 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8052 /* if the result is marked as
8053 spilt and rematerializable or code for
8054 this has already been generated then
8056 if (resultRemat (ic) || ic->generated)
8064 for (i=A_IDX;i<=XA_IDX;i++)
8066 reg = hc08_regWithIdx(i);
8068 emitcode("","; %s = %s offset %d", reg->name,
8069 aopName(reg->aop), reg->aopofs);
8072 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8074 sym = OP_SYMBOL (IC_LEFT (ic));
8075 if (sym->accuse == ACCUSE_HX)
8077 hc08_reg_h->isFree = FALSE;
8078 hc08_reg_x->isFree = FALSE;
8080 else if (sym->accuse == ACCUSE_XA)
8082 hc08_reg_a->isFree = FALSE;
8084 hc08_reg_x->isFree = FALSE;
8087 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8089 sym = OP_SYMBOL (IC_RIGHT (ic));
8090 if (sym->accuse == ACCUSE_HX)
8092 hc08_reg_h->isFree = FALSE;
8093 hc08_reg_x->isFree = FALSE;
8095 else if (sym->accuse == ACCUSE_XA)
8097 hc08_reg_a->isFree = FALSE;
8099 hc08_reg_x->isFree = FALSE;
8104 /* depending on the operation */
8124 /* IPOP happens only when trying to restore a
8125 spilt live range, if there is an ifx statement
8126 following this pop then the if statement might
8127 be using some of the registers being popped which
8128 would destory the contents of the register so
8129 we need to check for this condition and handle it */
8131 ic->next->op == IFX &&
8132 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8133 genIfx (ic->next, ic);
8151 genEndFunction (ic);
8167 if (!genPointerGetSetOfs (ic))
8172 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8189 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8193 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8200 /* note these two are xlated by algebraic equivalence
8201 during parsing SDCC.y */
8202 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8203 "got '>=' or '<=' shouldn't have come here");
8207 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8219 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8223 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8227 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8254 case GET_VALUE_AT_ADDRESS:
8256 hasInc (IC_LEFT (ic), ic,
8257 getSize (operandType (IC_RESULT (ic)))),
8258 ifxForOp (IC_RESULT (ic), ic) );
8262 if (POINTER_SET (ic))
8263 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8289 addSet (&_G.sendSet, ic);
8292 case DUMMY_READ_VOLATILE:
8301 genEndCritical (ic);
8312 if (!hc08_reg_a->isFree)
8313 D(emitcode("","; forgot to free a"));
8314 if (!hc08_reg_x->isFree)
8315 D(emitcode("","; forgot to free x"));
8316 if (!hc08_reg_h->isFree)
8317 D(emitcode("","; forgot to free h"));
8318 if (!hc08_reg_hx->isFree)
8319 D(emitcode("","; forgot to free hx"));
8320 if (!hc08_reg_xa->isFree)
8321 D(emitcode("","; forgot to free xa"));
8324 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8327 /* now we are ready to call the
8328 peep hole optimizer */
8329 if (!options.nopeep)
8330 peepHole (&lineHead);
8332 /* now do the actual printing */
8333 printLine (lineHead, codeOutFile);