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 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1125 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1129 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1131 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1135 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1136 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1137 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1138 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1140 if (dstofs >= dstaop->size)
1143 if ((dstaop->type == AOP_DIR)
1144 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1146 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1147 aopAdrStr(dstaop, dstofs, FALSE));
1151 if (dstaop->type == AOP_REG)
1153 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1154 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1156 reg = dstaop->aopu.aop_reg[dstofs];
1161 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1163 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1164 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1166 reg = srcaop->aopu.aop_reg[srcofs];
1173 if (hc08_reg_a->isFree)
1175 else if (hc08_reg_x->isFree)
1179 pushReg (hc08_reg_a, TRUE);
1185 loadRegFromAop (reg, srcaop, srcofs);
1186 storeRegToAop (reg, dstaop, dstofs);
1189 pullOrFreeReg (hc08_reg_a, needpula);
1193 /*--------------------------------------------------------------------------*/
1194 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1195 /* parameter param. */
1196 /*--------------------------------------------------------------------------*/
1198 accopWithMisc (char *accop, char *param)
1200 emitcode (accop, "%s", param);
1201 hc08_dirtyReg (hc08_reg_a, FALSE);
1204 /*--------------------------------------------------------------------------*/
1205 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1206 /* byte at logical offset loffset of asmop aop. */
1207 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1208 /*--------------------------------------------------------------------------*/
1210 accopWithAop (char *accop, asmop *aop, int loffset)
1212 if (aop->stacked && aop->stk_aop[loffset])
1214 accopWithAop (accop, aop->stk_aop[loffset], 0);
1218 if (aop->type == AOP_DUMMY)
1221 if (aop->type == AOP_REG)
1223 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1224 emitcode (accop, "1,s");
1228 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1230 hc08_dirtyReg (hc08_reg_a, FALSE);
1234 /*--------------------------------------------------------------------------*/
1235 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1236 /* byte at logical offset loffset of asmop aop. Register reg */
1237 /* must be 8-bit. */
1238 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1239 /*--------------------------------------------------------------------------*/
1241 rmwWithReg (char *rmwop, regs *reg)
1244 char *rmwaop = rmwbuf;
1246 if (reg->rIdx == A_IDX)
1248 sprintf(rmwaop,"%sa", rmwop);
1249 emitcode (rmwaop, "");
1250 hc08_dirtyReg (hc08_reg_a, FALSE);
1252 else if (reg->rIdx == X_IDX)
1254 sprintf(rmwaop,"%sx", rmwop);
1255 emitcode (rmwaop, "");
1256 hc08_dirtyReg (hc08_reg_a, FALSE);
1258 else if (hc08_reg_a->isFree)
1260 transferRegReg(reg, hc08_reg_a, FALSE);
1261 sprintf(rmwaop,"%sa", rmwop);
1262 emitcode (rmwaop, "");
1263 hc08_dirtyReg (hc08_reg_a, FALSE);
1264 transferRegReg(hc08_reg_a, reg, TRUE);
1268 pushReg (reg, FALSE);
1269 emitcode (rmwop, "1,s");
1271 hc08_dirtyReg (reg, FALSE);
1275 /*--------------------------------------------------------------------------*/
1276 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1277 /* logical offset loffset of asmop aop. */
1278 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1279 /*--------------------------------------------------------------------------*/
1281 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1283 bool needpula = FALSE;
1285 if (aop->stacked && aop->stk_aop[loffset])
1287 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1294 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1297 needpula = pushRegIfUsed (hc08_reg_a);
1298 loadRegFromAop (hc08_reg_a, aop, loffset);
1299 rmwWithReg (rmwop, hc08_reg_a);
1300 storeRegToAop (hc08_reg_a, aop, loffset);
1301 pullOrFreeReg (hc08_reg_a, needpula);
1306 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1312 /*-----------------------------------------------------------------*/
1313 /* newAsmop - creates a new asmOp */
1314 /*-----------------------------------------------------------------*/
1316 newAsmop (short type)
1320 aop = Safe_calloc (1, sizeof (asmop));
1327 /*-----------------------------------------------------------------*/
1328 /* pointerCode - returns the code for a pointer type */
1329 /*-----------------------------------------------------------------*/
1331 pointerCode (sym_link * etype)
1334 return PTR_TYPE (SPEC_OCLS (etype));
1339 /*-----------------------------------------------------------------*/
1340 /* aopForSym - for a true symbol */
1341 /*-----------------------------------------------------------------*/
1343 aopForSym (iCode * ic, symbol * sym, bool result)
1348 wassertl (ic != NULL, "Got a null iCode");
1349 wassertl (sym != NULL, "Got a null symbol");
1351 // printf("in aopForSym for symbol %s\n", sym->name);
1353 space = SPEC_OCLS (sym->etype);
1355 /* if already has one */
1361 /* special case for a function */
1362 if (IS_FUNC (sym->type))
1364 sym->aop = aop = newAsmop (AOP_IMMD);
1365 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1366 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1367 aop->size = FPTRSIZE;
1371 /* if it is in direct space */
1372 if (IN_DIRSPACE (space))
1374 sym->aop = aop = newAsmop (AOP_DIR);
1375 aop->aopu.aop_dir = sym->rname;
1376 aop->size = getSize (sym->type);
1380 /* if it is in far space */
1381 if (IN_FARSPACE (space))
1383 sym->aop = aop = newAsmop (AOP_EXT);
1384 aop->aopu.aop_dir = sym->rname;
1385 aop->size = getSize (sym->type);
1389 if (IN_STACK (sym->etype))
1391 sym->aop = aop = newAsmop (AOP_SOF);
1392 aop->aopu.aop_dir = sym->rname;
1393 aop->size = getSize (sym->type);
1394 aop->aopu.aop_stk = sym->stack;
1400 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1401 "aopForSym should never reach here");
1405 /* if it is in code space */
1406 if (IN_CODESPACE (space))
1412 /*-----------------------------------------------------------------*/
1413 /* aopForRemat - rematerialzes an object */
1414 /*-----------------------------------------------------------------*/
1416 aopForRemat (symbol * sym)
1418 iCode *ic = sym->rematiCode;
1426 val += (int) operandLitValue (IC_RIGHT (ic));
1427 else if (ic->op == '-')
1428 val -= (int) operandLitValue (IC_RIGHT (ic));
1429 else if (IS_CAST_ICODE(ic)) {
1430 sym_link *from_type = operandType(IC_RIGHT(ic));
1431 aop->aopu.aop_immd.from_cast_remat = 1;
1432 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1433 ptr_type = DCL_TYPE(from_type);
1434 if (ptr_type == IPOINTER) {
1441 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1444 if (ic->op == ADDRESS_OF)
1447 sprintf (buffer, "(%s %c 0x%04x)",
1448 OP_SYMBOL (IC_LEFT (ic))->rname,
1449 val >= 0 ? '+' : '-',
1450 abs (val) & 0xffff);
1452 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1454 aop = newAsmop (AOP_IMMD);
1455 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1456 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1457 /* set immd2 field if required */
1458 if (aop->aopu.aop_immd.from_cast_remat)
1460 sprintf(buffer,"#0x%02x",ptr_type);
1461 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1462 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1465 else if (ic->op == '=')
1467 val += (int) operandLitValue (IC_RIGHT (ic));
1469 sprintf (buffer, "0x%04x", val);
1470 aop = newAsmop (AOP_LIT);
1471 aop->aopu.aop_lit = constVal (buffer);
1474 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1475 "unexpected rematerialization");
1482 /*-----------------------------------------------------------------*/
1483 /* regsInCommon - two operands have some registers in common */
1484 /*-----------------------------------------------------------------*/
1486 regsInCommon (operand * op1, operand * op2)
1488 symbol *sym1, *sym2;
1491 /* if they have registers in common */
1492 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1495 sym1 = OP_SYMBOL (op1);
1496 sym2 = OP_SYMBOL (op2);
1498 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1501 for (i = 0; i < sym1->nRegs; i++)
1507 for (j = 0; j < sym2->nRegs; j++)
1512 if (sym2->regs[j] == sym1->regs[i])
1520 /*-----------------------------------------------------------------*/
1521 /* operandsEqu - equivalent */
1522 /*-----------------------------------------------------------------*/
1524 operandsEqu (operand * op1, operand * op2)
1526 symbol *sym1, *sym2;
1528 /* if they not symbols */
1529 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1532 sym1 = OP_SYMBOL (op1);
1533 sym2 = OP_SYMBOL (op2);
1535 /* if both are itemps & one is spilt
1536 and the other is not then false */
1537 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1538 sym1->isspilt != sym2->isspilt)
1541 /* if they are the same */
1545 if (sym1->rname[0] && sym2->rname[0]
1546 && strcmp (sym1->rname, sym2->rname) == 0)
1549 /* if left is a tmp & right is not */
1550 if (IS_ITEMP (op1) &&
1553 (sym1->usl.spillLoc == sym2))
1556 if (IS_ITEMP (op2) &&
1560 (sym2->usl.spillLoc == sym1))
1566 /*-----------------------------------------------------------------*/
1567 /* sameRegs - two asmops have the same registers */
1568 /*-----------------------------------------------------------------*/
1570 sameRegs (asmop * aop1, asmop * aop2)
1577 // if (aop1->size != aop2->size)
1580 if (aop1->type == aop2->type)
1585 for (i = 0; i < aop1->size; i++)
1586 if (aop1->aopu.aop_reg[i] !=
1587 aop2->aopu.aop_reg[i])
1591 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1594 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1601 /*-----------------------------------------------------------------*/
1602 /* aopOp - allocates an asmop for an operand : */
1603 /*-----------------------------------------------------------------*/
1605 aopOp (operand * op, iCode * ic, bool result)
1614 // Is this a pointer set result?
1616 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1620 // printf("checking literal\n");
1621 /* if this a literal */
1622 if (IS_OP_LITERAL (op))
1624 op->aop = aop = newAsmop (AOP_LIT);
1625 aop->aopu.aop_lit = op->operand.valOperand;
1626 aop->size = getSize (operandType (op));
1628 aop->isaddr = op->isaddr;
1632 // printf("checking pre-existing\n");
1633 /* if already has a asmop then continue */
1637 op->aop->isaddr = op->isaddr;
1641 // printf("checking underlying sym\n");
1642 /* if the underlying symbol has a aop */
1643 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1645 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1646 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1647 //op->aop = aop = OP_SYMBOL (op)->aop;
1648 aop->size = getSize( operandType (op));
1649 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1650 //printf (" with size = %d\n", aop->size);
1653 aop->isaddr = op->isaddr;
1654 /* if (aop->isaddr & IS_ITEMP (op))
1656 aop->psize=aop->size;
1657 aop->size = getSize( operandType (op)->next);
1662 // printf("checking true sym\n");
1663 /* if this is a true symbol */
1664 if (IS_TRUE_SYMOP (op))
1666 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1668 aop->isaddr = op->isaddr;
1669 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1670 //printf (" with size = %d\n", aop->size);
1674 /* this is a temporary : this has
1680 e) can be a return use only */
1682 sym = OP_SYMBOL (op);
1684 // printf("checking conditional\n");
1685 /* if the type is a conditional */
1686 if (sym->regType == REG_CND)
1688 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1691 aop->isaddr = op->isaddr;
1695 // printf("checking spilt\n");
1696 /* if it is spilt then two situations
1698 b) has a spill location */
1699 if (sym->isspilt || sym->nRegs == 0)
1702 // printf("checking remat\n");
1703 /* rematerialize it NOW */
1706 sym->aop = op->aop = aop =
1708 aop->size = getSize (sym->type);
1710 aop->isaddr = op->isaddr;
1711 /* if (aop->isaddr & IS_ITEMP (op))
1713 aop->psize=aop->size;
1714 aop->size = getSize( operandType (op)->next);
1719 // printf("checking accuse\n");
1722 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1723 aop->size = getSize (sym->type);
1724 switch (sym->accuse)
1727 aop->aopu.aop_reg[0] = hc08_reg_a;
1728 aop->aopu.aop_reg[1] = hc08_reg_x;
1731 aop->aopu.aop_reg[0] = hc08_reg_x;
1732 aop->aopu.aop_reg[1] = hc08_reg_h;
1736 aop->isaddr = op->isaddr;
1740 // printf("checking ruonly\n");
1746 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1747 aop->size = getSize (sym->type);
1748 for (i = 0; i < fReturnSizeHC08; i++)
1749 aop->aopu.aop_str[i] = fReturn2[i];
1751 aop->isaddr = op->isaddr;
1755 /* else spill location */
1756 if (sym->usl.spillLoc)
1758 if (sym->usl.spillLoc->aop
1759 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1761 /* force a new aop if sizes differ */
1762 sym->usl.spillLoc->aop = NULL;
1763 //printf ("forcing new aop\n");
1765 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1766 aop->size = getSize (sym->type);
1768 aop->isaddr = op->isaddr;
1769 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1770 //printf (" with size = %d\n", aop->size);
1774 /* else must be a dummy iTemp */
1775 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1776 aop->size = getSize (sym->type);
1780 // printf("assuming register\n");
1781 /* must be in a register */
1782 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1783 aop->size = sym->nRegs;
1784 for (i = 0; i < sym->nRegs; i++)
1785 aop->aopu.aop_reg[i] = sym->regs[i];
1787 aop->isaddr = op->isaddr;
1791 /*-----------------------------------------------------------------*/
1792 /* freeAsmop - free up the asmop given to an operand */
1793 /*----------------------------------------------------------------*/
1795 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1817 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1820 for (loffset=0; loffset<aop->size; loffset++)
1821 if (aop->stk_aop[loffset])
1823 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1826 pullNull (stackAdjust);
1830 /* all other cases just dealloc */
1836 OP_SYMBOL (op)->aop = NULL;
1837 /* if the symbol has a spill */
1839 SPIL_LOC (op)->aop = NULL;
1845 /*-----------------------------------------------------------------*/
1846 /* aopDerefAop - treating the aop parameter as a pointer, return */
1847 /* an asmop for the object it references */
1848 /*-----------------------------------------------------------------*/
1850 aopDerefAop (asmop *aop)
1855 asmop *newaop = NULL;
1856 sym_link *type, *etype;
1859 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1863 type = operandType (aop->op);
1864 etype = getSpec (type);
1865 /* if op is of type of pointer then it is simple */
1866 if (IS_PTR (type) && !IS_FUNC (type->next))
1867 p_type = DCL_TYPE (type);
1870 /* we have to go by the storage class */
1871 p_type = PTR_TYPE (SPEC_OCLS (etype));
1880 if (p_type == POINTER)
1881 newaop = newAsmop (AOP_DIR);
1883 newaop = newAsmop (AOP_EXT);
1884 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1887 adr = (int) floatFromVal (aop->aopu.aop_lit);
1888 if (p_type == POINTER)
1893 newaop = newAsmop (AOP_DIR);
1894 sprintf (s, "0x%02x",adr);
1898 newaop = newAsmop (AOP_EXT);
1899 sprintf (s, "0x%04x",adr);
1901 rs = Safe_calloc (1, strlen (s) + 1);
1903 newaop->aopu.aop_dir = rs;
1906 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1907 "unsupported asmop");
1917 /*-----------------------------------------------------------------*/
1918 /* aopAdrStr - for referencing the address of the aop */
1919 /*-----------------------------------------------------------------*/
1921 aopAdrStr (asmop * aop, int loffset, bool bit16)
1925 int offset = aop->size - 1 - loffset;
1928 /* offset is greater than
1930 if (loffset > (aop->size - 1) &&
1931 aop->type != AOP_LIT)
1934 /* depending on type */
1942 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1943 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1945 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1949 sprintf (s, "#(%s >> %d)",
1950 aop->aopu.aop_immd.aop_immd1,
1954 aop->aopu.aop_immd.aop_immd1);
1958 aop->aopu.aop_immd.aop_immd1);
1959 rs = Safe_calloc (1, strlen (s) + 1);
1965 sprintf (s, "*(%s + %d)",
1969 sprintf (s, "*%s", aop->aopu.aop_dir);
1970 rs = Safe_calloc (1, strlen (s) + 1);
1976 sprintf (s, "(%s + %d)",
1980 sprintf (s, "%s", aop->aopu.aop_dir);
1981 rs = Safe_calloc (1, strlen (s) + 1);
1986 return aop->aopu.aop_reg[loffset]->name;
1990 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
1992 return aopLiteral (aop->aopu.aop_lit, loffset);
1996 return aop->aopu.aop_str[loffset];
1999 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2001 rs = Safe_calloc (1, strlen (s) + 1);
2007 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2008 "aopAdrStr got unsupported aop->type");
2017 /*-----------------------------------------------------------------*/
2018 /* opIsGptr: returns non-zero if the passed operand is */
2019 /* a generic pointer type. */
2020 /*-----------------------------------------------------------------*/
2022 opIsGptr (operand * op)
2024 sym_link *type = operandType (op);
2026 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2034 /*-----------------------------------------------------------------*/
2035 /* getDataSize - get the operand data size */
2036 /*-----------------------------------------------------------------*/
2038 getDataSize (operand * op)
2041 size = AOP_SIZE (op);
2045 /*-----------------------------------------------------------------*/
2046 /* outAcc - output Acc */
2047 /*-----------------------------------------------------------------*/
2049 outAcc (operand * result)
2052 size = getDataSize (result);
2055 storeRegToAop (hc08_reg_a, AOP (result), 0);
2058 /* unsigned or positive */
2061 storeConstToAop (zero, AOP (result), offset++);
2066 /*-----------------------------------------------------------------*/
2067 /* outBitC - output a bit C */
2068 /*-----------------------------------------------------------------*/
2070 outBitC (operand * result)
2074 /* if the result is bit */
2075 if (AOP_TYPE (result) == AOP_CRY)
2076 aopPut (AOP (result), "c", 0);
2080 emitcode ("clra", "");
2081 emitcode ("rola", "");
2086 /*-----------------------------------------------------------------*/
2087 /* outBitNV - output a bit N^V */
2088 /*-----------------------------------------------------------------*/
2090 outBitNV (operand * result)
2092 symbol *tlbl, *tlbl1;
2094 tlbl = newiTempLabel (NULL);
2095 tlbl1 = newiTempLabel (NULL);
2097 emitBranch ("blt", tlbl);
2098 loadRegFromConst (hc08_reg_a, zero);
2099 emitBranch ("bra", tlbl1);
2101 loadRegFromConst (hc08_reg_a, one);
2107 /*-----------------------------------------------------------------*/
2108 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2109 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2110 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2111 /*-----------------------------------------------------------------*/
2113 asmopToBool (asmop *aop, bool resultInA)
2115 symbol *tlbl, *tlbl1;
2116 int size = aop->size;
2117 bool needpula = FALSE;
2118 bool flagsonly = TRUE;
2123 hc08_freeReg(hc08_reg_a);
2130 emitcode ("tsta", "");
2133 else if (IS_AOP_X(aop))
2134 emitcode ("tstx", "");
2135 else if (IS_AOP_H(aop))
2137 if (hc08_reg_a->isFree)
2139 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2140 emitcode ("tsta", "");
2142 hc08_freeReg(hc08_reg_a);
2144 else if (hc08_reg_x->isFree)
2146 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2147 emitcode ("tstx", "");
2148 hc08_freeReg(hc08_reg_x);
2152 emitcode ("pshh", "");
2153 emitcode ("tst", "1,s");
2154 emitcode ("ais", "#1");
2157 else if (IS_AOP_HX(aop))
2158 emitcode ("cphx", zero);
2159 else if (IS_AOP_XA(aop))
2161 symbol *tlbl = newiTempLabel (NULL);
2162 emitcode ("tsta", "");
2163 emitcode ("bne", "%05d$", (tlbl->key + 100));
2164 emitcode ("tstx", "");
2165 emitcode ("", "%05d$:", (tlbl->key + 100));
2169 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2170 "Bad rIdx in asmToBool");
2178 needpula = pushRegIfUsed (hc08_reg_a);
2179 loadRegFromAop (hc08_reg_a, aop, 0);
2180 for (offset=1; offset<size; offset++)
2181 accopWithAop ("ora", aop, offset);
2183 pullReg (hc08_reg_a);
2186 hc08_freeReg (hc08_reg_a);
2195 loadRegFromAop (hc08_reg_a, aop, 0);
2196 hc08_freeReg (hc08_reg_a);
2200 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2205 if (hc08_reg_a->isFree)
2207 loadRegFromAop (hc08_reg_a, aop, 0);
2208 accopWithAop ("ora", aop, 1);
2209 hc08_freeReg (hc08_reg_a);
2214 tlbl = newiTempLabel (NULL);
2215 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2216 emitcode ("bne", "%05d$", (tlbl->key + 100));
2217 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2218 emitcode ("", "%05d$:", (tlbl->key + 100));
2224 needpula = pushRegIfUsed (hc08_reg_a);
2225 loadRegFromAop (hc08_reg_a, aop, 0);
2226 for (offset=1; offset<size; offset++)
2227 accopWithAop ("ora", aop, offset);
2229 pullReg (hc08_reg_a);
2232 hc08_freeReg (hc08_reg_a);
2240 tlbl = newiTempLabel (NULL);
2244 tlbl1 = newiTempLabel (NULL);
2245 emitBranch ("bne", tlbl1);
2246 loadRegFromConst (hc08_reg_a, zero);
2247 emitBranch ("bra", tlbl);
2249 loadRegFromConst (hc08_reg_a, one);
2253 emitBranch ("beq", tlbl);
2254 loadRegFromConst (hc08_reg_a, one);
2257 hc08_useReg (hc08_reg_a);
2263 /*-----------------------------------------------------------------*/
2264 /* genNot - generate code for ! operation */
2265 /*-----------------------------------------------------------------*/
2269 D(emitcode ("; genNot",""));
2271 /* assign asmOps to operand & result */
2272 aopOp (IC_LEFT (ic), ic, FALSE);
2273 aopOp (IC_RESULT (ic), ic, TRUE);
2275 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2276 emitcode ("eor", one);
2277 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2279 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2280 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2284 /*-----------------------------------------------------------------*/
2285 /* genCpl - generate code for complement */
2286 /*-----------------------------------------------------------------*/
2292 regs* reg = hc08_reg_a;
2296 D(emitcode ("; genCpl",""));
2298 /* assign asmOps to operand & result */
2299 aopOp (IC_LEFT (ic), ic, FALSE);
2300 aopOp (IC_RESULT (ic), ic, TRUE);
2302 size = AOP_SIZE (IC_RESULT (ic));
2305 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2306 rmwWithReg ("com", reg);
2308 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2312 /* release the aops */
2313 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2314 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2317 /*-----------------------------------------------------------------*/
2318 /* genUminusFloat - unary minus for floating points */
2319 /*-----------------------------------------------------------------*/
2321 genUminusFloat (operand * op, operand * result)
2323 int size, offset = 0;
2326 D(emitcode ("; genUminusFloat",""));
2328 /* for this we just copy and then flip the bit */
2330 size = AOP_SIZE (op) - 1;
2336 needpula = pushRegIfUsed (hc08_reg_a);
2337 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2338 emitcode ("eor", "#0x80");
2339 hc08_useReg (hc08_reg_a);
2340 storeRegToAop (hc08_reg_a, AOP (result), offset);
2341 pullOrFreeReg (hc08_reg_a, needpula);
2344 transferAopAop (AOP (op), offset, AOP (result), offset);
2350 /*-----------------------------------------------------------------*/
2351 /* genUminus - unary minus code generation */
2352 /*-----------------------------------------------------------------*/
2354 genUminus (iCode * ic)
2357 sym_link *optype, *rtype;
2362 D(emitcode ("; genUminus",""));
2365 aopOp (IC_LEFT (ic), ic, FALSE);
2366 aopOp (IC_RESULT (ic), ic, TRUE);
2368 optype = operandType (IC_LEFT (ic));
2369 rtype = operandType (IC_RESULT (ic));
2371 /* if float then do float stuff */
2372 if (IS_FLOAT (optype))
2374 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2378 /* otherwise subtract from zero */
2379 size = AOP_SIZE (IC_LEFT (ic));
2384 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2385 needpula = pushRegIfUsed (hc08_reg_a);
2388 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2389 emitcode ("nega", "");
2390 hc08_freeReg (hc08_reg_a);
2391 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2392 SPEC_USIGN (operandType (IC_LEFT (ic))));
2393 pullOrFreeReg (hc08_reg_a, needpula);
2397 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2398 result = forceStackedAop (AOP (IC_RESULT (ic)));
2400 result = AOP (IC_RESULT (ic));
2402 needpula = pushRegIfUsed (hc08_reg_a);
2406 loadRegFromConst (hc08_reg_a, zero);
2407 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2408 storeRegToAop (hc08_reg_a, result, offset++);
2411 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2412 SPEC_USIGN (operandType (IC_LEFT (ic))));
2413 pullOrFreeReg (hc08_reg_a, needpula);
2415 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2416 freeAsmop (NULL, result, ic, TRUE);
2422 /* release the aops */
2423 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2424 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2427 /*-----------------------------------------------------------------*/
2428 /* saveRegisters - will look for a call and save the registers */
2429 /*-----------------------------------------------------------------*/
2431 saveRegisters (iCode * lic)
2438 for (ic = lic; ic; ic = ic->next)
2439 if (ic->op == CALL || ic->op == PCALL)
2444 fprintf (stderr, "found parameter push with no function call\n");
2448 /* if the registers have been saved already or don't need to be then
2452 if (IS_SYMOP(IC_LEFT(ic)) &&
2453 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2454 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2457 /* safe the registers in use at this time but skip the
2458 ones for the result */
2459 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2460 hc08_rUmaskForOp (IC_RESULT(ic)));
2463 for (i = 0; i < hc08_nRegs; i++)
2465 if (bitVectBitValue (rsave, i))
2466 pushReg ( hc08_regWithIdx (i), FALSE);
2470 /*-----------------------------------------------------------------*/
2471 /* unsaveRegisters - pop the pushed registers */
2472 /*-----------------------------------------------------------------*/
2474 unsaveRegisters (iCode * ic)
2479 /* restore the registers in use at this time but skip the
2480 ones for the result */
2481 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2482 hc08_rUmaskForOp (IC_RESULT(ic)));
2484 for (i = hc08_nRegs; i >= 0; i--)
2486 if (bitVectBitValue (rsave, i))
2487 pullReg ( hc08_regWithIdx (i));
2493 /*-----------------------------------------------------------------*/
2495 /*-----------------------------------------------------------------*/
2497 pushSide (operand * oper, int size)
2502 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2503 pushReg ( hc08_reg_a, TRUE);
2507 /*-----------------------------------------------------------------*/
2508 /* assignResultValue - */
2509 /*-----------------------------------------------------------------*/
2511 assignResultValue (operand * oper)
2513 int size = AOP_SIZE (oper);
2517 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2518 if (hc08_aop_pass[offset]->type == AOP_REG)
2519 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2526 /*-----------------------------------------------------------------*/
2527 /* genIpush - genrate code for pushing this gets a little complex */
2528 /*-----------------------------------------------------------------*/
2530 genIpush (iCode * ic)
2532 int size, offset = 0;
2535 D(emitcode ("; genIpush",""));
2537 /* if this is not a parm push : ie. it is spill push
2538 and spill push is always done on the local stack */
2542 /* and the item is spilt then do nothing */
2543 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2546 aopOp (IC_LEFT (ic), ic, FALSE);
2547 size = AOP_SIZE (IC_LEFT (ic));
2549 /* push it on the stack */
2552 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2553 pushReg ( hc08_reg_a, TRUE);
2559 /* this is a paramter push: in this case we call
2560 the routine to find the call and save those
2561 registers that need to be saved */
2564 /* then do the push */
2565 aopOp (IC_LEFT (ic), ic, FALSE);
2568 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2569 size = AOP_SIZE (IC_LEFT (ic));
2572 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2573 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2575 if ((size==2) && hc08_reg_hx->isFree)
2577 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2578 pushReg (hc08_reg_hx, TRUE);
2585 // printf("loading %d\n", offset);
2586 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2587 // printf("pushing \n");
2588 pushReg (hc08_reg_a, TRUE);
2592 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2595 /*-----------------------------------------------------------------*/
2596 /* genIpop - recover the registers: can happen only for spilling */
2597 /*-----------------------------------------------------------------*/
2599 genIpop (iCode * ic)
2603 D(emitcode ("; genIpop",""));
2605 /* if the temp was not pushed then */
2606 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2609 aopOp (IC_LEFT (ic), ic, FALSE);
2610 size = AOP_SIZE (IC_LEFT (ic));
2614 pullReg (hc08_reg_a);
2615 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2617 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2621 /*-----------------------------------------------------------------*/
2622 /* genSend - gen code for SEND */
2623 /*-----------------------------------------------------------------*/
2624 static void genSend(set *sendSet)
2628 for (sic = setFirstItem (_G.sendSet); sic;
2629 sic = setNextItem (_G.sendSet)) {
2630 int size, offset = 0;
2631 aopOp (IC_LEFT (sic), sic, FALSE);
2632 size = AOP_SIZE (IC_LEFT (sic));
2637 transferAopAop( AOP (IC_LEFT (sic)), offset,
2638 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2642 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2646 /*-----------------------------------------------------------------*/
2647 /* genCall - generates a call statement */
2648 /*-----------------------------------------------------------------*/
2650 genCall (iCode * ic)
2653 // bool restoreBank = FALSE;
2654 // bool swapBanks = FALSE;
2656 D(emitcode("; genCall",""));
2658 dtype = operandType (IC_LEFT (ic));
2659 /* if send set is not empty the assign */
2662 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2663 genSend(reverseSet(_G.sendSet));
2665 genSend(_G.sendSet);
2671 /* if caller saves & we have not saved then */
2677 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2678 OP_SYMBOL (IC_LEFT (ic))->rname :
2679 OP_SYMBOL (IC_LEFT (ic))->name));
2682 /* if we need assign a result value */
2683 if ((IS_ITEMP (IC_RESULT (ic)) &&
2684 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2685 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2686 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2687 IS_TRUE_SYMOP (IC_RESULT (ic)))
2691 aopOp (IC_RESULT (ic), ic, FALSE);
2694 assignResultValue (IC_RESULT (ic));
2696 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2699 /* adjust the stack for parameters if
2703 pullNull (ic->parmBytes);
2706 /* if we had saved some registers then unsave them */
2707 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2708 unsaveRegisters (ic);
2712 /*-----------------------------------------------------------------*/
2713 /* -10l - generates a call by pointer statement */
2714 /*-----------------------------------------------------------------*/
2716 genPcall (iCode * ic)
2719 symbol *rlbl = newiTempLabel (NULL);
2720 symbol *tlbl = newiTempLabel (NULL);
2721 // bool restoreBank=FALSE;
2722 // bool swapBanks = FALSE;
2724 D(emitcode("; genPCall",""));
2726 /* if caller saves & we have not saved then */
2730 /* if we are calling a not _naked function that is not using
2731 the same register bank then we need to save the
2732 destination registers on the stack */
2733 dtype = operandType (IC_LEFT (ic))->next;
2735 /* now push the calling address */
2736 emitBranch ("bsr", tlbl);
2737 emitBranch ("bra", rlbl);
2740 /* Push the function's address */
2741 aopOp (IC_LEFT (ic), ic, FALSE);
2742 pushSide (IC_LEFT (ic), FPTRSIZE);
2743 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2745 /* if send set is not empty the assign */
2748 genSend(reverseSet(_G.sendSet));
2754 emitcode ("rts", "");
2759 /* if we need assign a result value */
2760 if ((IS_ITEMP (IC_RESULT (ic)) &&
2761 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2762 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2763 IS_TRUE_SYMOP (IC_RESULT (ic)))
2767 aopOp (IC_RESULT (ic), ic, FALSE);
2770 assignResultValue (IC_RESULT (ic));
2772 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2775 /* adjust the stack for parameters if
2779 pullNull (ic->parmBytes);
2782 /* if we hade saved some registers then
2784 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2785 unsaveRegisters (ic);
2788 /*-----------------------------------------------------------------*/
2789 /* resultRemat - result is rematerializable */
2790 /*-----------------------------------------------------------------*/
2792 resultRemat (iCode * ic)
2794 if (SKIP_IC (ic) || ic->op == IFX)
2797 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2799 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2800 if (sym->remat && !POINTER_SET (ic))
2807 #if defined(__BORLANDC__) || defined(_MSC_VER)
2808 #define STRCASECMP stricmp
2810 #define STRCASECMP strcasecmp
2813 /*-----------------------------------------------------------------*/
2814 /* inExcludeList - return 1 if the string is in exclude Reg list */
2815 /*-----------------------------------------------------------------*/
2817 regsCmp(void *p1, void *p2)
2819 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2823 inExcludeList (char *s)
2825 const char *p = setFirstItem(options.excludeRegsSet);
2827 if (p == NULL || STRCASECMP(p, "none") == 0)
2831 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2834 /*-----------------------------------------------------------------*/
2835 /* genFunction - generated code for function entry */
2836 /*-----------------------------------------------------------------*/
2838 genFunction (iCode * ic)
2842 int calleesaves_saved_register = -1;
2846 /* create the function header */
2847 emitcode (";", "-----------------------------------------");
2848 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2849 emitcode (";", "-----------------------------------------");
2851 emitcode ("", "%s:", sym->rname);
2852 ftype = operandType (IC_LEFT (ic));
2856 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2858 if (IFFUNC_ISNAKED(ftype))
2860 emitcode(";", "naked function: no prologue.");
2866 /* if this is an interrupt service routine then
2868 if (IFFUNC_ISISR (sym->type))
2871 if (!inExcludeList ("h"))
2872 pushReg (hc08_reg_h, FALSE);
2876 /* if callee-save to be used for this function
2877 then save the registers being used in this function */
2878 if (IFFUNC_CALLEESAVES(sym->type))
2882 /* if any registers used */
2885 /* save the registers used */
2886 for (i = 0; i < sym->regsUsed->size; i++)
2888 if (bitVectBitValue (sym->regsUsed, i))
2890 /* remember one saved register for later usage */
2891 if (calleesaves_saved_register < 0)
2892 calleesaves_saved_register = i;
2893 pushReg (hc08_regWithIdx (i), FALSE);
2901 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2906 /* adjust the stack for the function */
2912 // werror (W_STACK_OVERFLOW, sym->name);
2916 _G.stackOfs = sym->stack;
2919 /* if critical function then turn interrupts off */
2920 if (IFFUNC_ISCRITICAL (ftype))
2922 if (IFFUNC_ARGS (ftype))
2924 /* Function was passed parameters, so make sure A is preserved */
2925 pushReg (hc08_reg_a, FALSE);
2926 pushReg (hc08_reg_a, FALSE);
2927 emitcode ("tpa", "");
2928 emitcode ("sta", "2,s");
2929 emitcode ("sei", "");
2930 pullReg (hc08_reg_a);
2934 /* No passed parameters, so A can be freely modified */
2935 emitcode ("tpa", "");
2936 pushReg (hc08_reg_a, TRUE);
2937 emitcode ("sei", "");
2943 /*-----------------------------------------------------------------*/
2944 /* genEndFunction - generates epilogue for functions */
2945 /*-----------------------------------------------------------------*/
2947 genEndFunction (iCode * ic)
2949 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2951 if (IFFUNC_ISNAKED(sym->type))
2953 emitcode(";", "naked function: no epilogue.");
2954 if (options.debug && currFunc)
2955 debugFile->writeEndFunction (currFunc, ic, 0);
2959 if (IFFUNC_ISCRITICAL (sym->type))
2961 if (!IS_VOID(sym->type->next))
2963 /* Function has return value, so make sure A is preserved */
2964 pushReg (hc08_reg_a, FALSE);
2965 emitcode ("lda", "2,s");
2966 emitcode ("tap", "");
2967 pullReg (hc08_reg_a);
2972 /* Function returns void, so A can be freely modified */
2973 pullReg (hc08_reg_a);
2974 emitcode ("tap", "");
2978 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2984 _G.stackPushes += sym->stack;
2985 adjustStack (sym->stack);
2989 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2993 if (IFFUNC_ISISR (sym->type))
2996 if (!inExcludeList ("h"))
2997 pullReg (hc08_reg_h);
3000 /* if debug then send end of function */
3001 if (options.debug && currFunc)
3003 debugFile->writeEndFunction (currFunc, ic, 1);
3006 emitcode ("rti", "");
3010 if (IFFUNC_CALLEESAVES(sym->type))
3014 /* if any registers used */
3017 /* save the registers used */
3018 for (i = sym->regsUsed->size; i >= 0; i--)
3020 if (bitVectBitValue (sym->regsUsed, i) ||
3021 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3022 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3028 /* if debug then send end of function */
3029 if (options.debug && currFunc)
3031 debugFile->writeEndFunction (currFunc, ic, 1);
3034 emitcode ("rts", "");
3039 /*-----------------------------------------------------------------*/
3040 /* genRet - generate code for return statement */
3041 /*-----------------------------------------------------------------*/
3045 int size, offset = 0;
3048 D(emitcode ("; genRet",""));
3050 /* if we have no return value then
3051 just generate the "ret" */
3055 /* we have something to return then
3056 move the return value into place */
3057 aopOp (IC_LEFT (ic), ic, FALSE);
3058 size = AOP_SIZE (IC_LEFT (ic));
3064 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3071 /* 4 byte return: store value in the global return variable */
3075 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3076 STA (fReturn2[offset--], FALSE);
3077 hc08_freeReg (hc08_reg_a);
3081 /* 2 byte return: store value in x:a */
3082 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3083 hc08_freeReg (hc08_reg_xa);
3086 /* 1 byte return: store value in a */
3087 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3088 hc08_freeReg (hc08_reg_a);
3093 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3096 /* generate a jump to the return label
3097 if the next is not the return statement */
3098 if (!(ic->next && ic->next->op == LABEL &&
3099 IC_LABEL (ic->next) == returnLabel))
3101 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3105 /*-----------------------------------------------------------------*/
3106 /* genLabel - generates a label */
3107 /*-----------------------------------------------------------------*/
3109 genLabel (iCode * ic)
3114 /* For the high level labels we cannot depend on any */
3115 /* register's contents. Amnesia time. */
3116 for (i=A_IDX;i<=XA_IDX;i++)
3118 reg = hc08_regWithIdx(i);
3123 /* special case never generate */
3124 if (IC_LABEL (ic) == entryLabel)
3127 debugFile->writeLabel(IC_LABEL (ic), ic);
3129 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3133 /*-----------------------------------------------------------------*/
3134 /* genGoto - generates a jmp */
3135 /*-----------------------------------------------------------------*/
3137 genGoto (iCode * ic)
3139 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3143 /*-----------------------------------------------------------------*/
3144 /* findLabelBackwards: walks back through the iCode chain looking */
3145 /* for the given label. Returns number of iCode instructions */
3146 /* between that label and given ic. */
3147 /* Returns zero if label not found. */
3148 /*-----------------------------------------------------------------*/
3150 findLabelBackwards (iCode * ic, int key)
3159 /* If we have any pushes or pops, we cannot predict the distance.
3160 I don't like this at all, this should be dealt with in the
3162 if (ic->op == IPUSH || ic->op == IPOP) {
3166 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3176 /*-----------------------------------------------------------------*/
3177 /* genPlusIncr :- does addition with increment if possible */
3178 /*-----------------------------------------------------------------*/
3180 genPlusIncr (iCode * ic)
3188 unsigned int size = getDataSize (IC_RESULT (ic));
3190 symbol *tlbl = NULL;
3192 left = IC_LEFT (ic);
3193 result = IC_RESULT (ic);
3195 /* will try to generate an increment */
3196 /* if the right side is not a literal
3198 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3201 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3203 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3205 if ((IS_AOP_HX (AOP (left)) ||
3206 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3208 && (icount>=-128) && (icount<=127) && (size==2))
3210 if (!IS_AOP_HX (AOP (left)))
3212 needpulx = pushRegIfUsed (hc08_reg_x);
3213 needpulh = pushRegIfUsed (hc08_reg_h);
3220 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3221 emitcode ("aix","#%d", icount);
3222 hc08_dirtyReg (hc08_reg_hx, FALSE);
3223 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3224 pullOrFreeReg (hc08_reg_h, needpulh);
3225 pullOrFreeReg (hc08_reg_x, needpulx);
3229 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3230 sameRegs (AOP (left), AOP (result))));
3232 if ((icount > 255) || (icount<0))
3235 if (!sameRegs (AOP (left), AOP (result)))
3238 D(emitcode ("; genPlusIncr",""));
3241 tlbl = newiTempLabel (NULL);
3246 rmwWithAop ("inc", AOP (result), 0);
3248 emitBranch ("bne", tlbl);
3252 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3253 needpula = pushRegIfUsed (hc08_reg_a);
3256 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3257 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3258 hc08_useReg (hc08_reg_a);
3259 storeRegToAop (hc08_reg_a, AOP (result), 0);
3260 hc08_freeReg (hc08_reg_a);
3262 emitBranch ("bcc", tlbl);
3264 for (offset=1; offset<size; offset++)
3266 rmwWithAop ("inc", AOP (result), offset);
3267 if ((offset+1)<size)
3268 emitBranch ("bne", tlbl);
3274 pullOrFreeReg (hc08_reg_a, needpula);
3281 /*-----------------------------------------------------------------*/
3282 /* genPlus - generates code for addition */
3283 /*-----------------------------------------------------------------*/
3285 genPlus (iCode * ic)
3287 int size, offset = 0;
3289 asmop *leftOp, *rightOp;
3291 /* special cases :- */
3293 D(emitcode ("; genPlus",""));
3295 aopOp (IC_LEFT (ic), ic, FALSE);
3296 aopOp (IC_RIGHT (ic), ic, FALSE);
3297 aopOp (IC_RESULT (ic), ic, TRUE);
3299 /* we want registers on the left and literals on the right */
3300 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3301 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3303 operand *t = IC_RIGHT (ic);
3304 IC_RIGHT (ic) = IC_LEFT (ic);
3309 /* if I can do an increment instead
3310 of add then GOOD for ME */
3311 if (genPlusIncr (ic) == TRUE)
3314 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3315 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3316 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3318 size = getDataSize (IC_RESULT (ic));
3320 leftOp = AOP(IC_LEFT(ic));
3321 rightOp = AOP(IC_RIGHT(ic));
3327 loadRegFromAop (hc08_reg_a, leftOp, offset);
3328 accopWithAop(add, rightOp, offset);
3329 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3330 hc08_freeReg (hc08_reg_a);
3331 add = "adc"; /* further adds must propagate carry */
3335 // adjustArithmeticResult (ic);
3338 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3339 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3340 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3343 /*-----------------------------------------------------------------*/
3344 /* genMinusDec :- does subtraction with deccrement if possible */
3345 /*-----------------------------------------------------------------*/
3347 genMinusDec (iCode * ic)
3349 unsigned int icount;
3354 unsigned int size = getDataSize (IC_RESULT (ic));
3358 left = IC_LEFT (ic);
3359 result = IC_RESULT (ic);
3361 /* will try to generate an increment */
3362 /* if the right side is not a literal
3364 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3367 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3369 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3370 && (icount>=-127) && (icount<=128) && (size==2))
3372 if (!IS_AOP_HX (AOP (left)))
3374 needpulx = pushRegIfUsed (hc08_reg_x);
3375 needpulh = pushRegIfUsed (hc08_reg_h);
3382 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3383 emitcode ("aix","#%d", -icount);
3384 hc08_dirtyReg (hc08_reg_hx, FALSE);
3385 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3386 pullOrFreeReg (hc08_reg_h, needpulh);
3387 pullOrFreeReg (hc08_reg_x, needpulx);
3391 if ((icount > 1) || (icount<0))
3394 if (!sameRegs (AOP (left), AOP (result)))
3400 D(emitcode ("; genMinusDec",""));
3402 rmwWithAop ("dec", AOP (result), 0);
3407 /*-----------------------------------------------------------------*/
3408 /* addSign - complete with sign */
3409 /*-----------------------------------------------------------------*/
3411 addSign (operand * result, int offset, int sign)
3413 int size = (getDataSize (result) - offset);
3418 emitcode ("rola", "");
3419 emitcode ("clra", "");
3420 emitcode ("sbc", zero);
3422 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3426 storeConstToAop (zero, AOP (result), offset++);
3431 /*-----------------------------------------------------------------*/
3432 /* genMinus - generates code for subtraction */
3433 /*-----------------------------------------------------------------*/
3435 genMinus (iCode * ic)
3438 int size, offset = 0;
3440 asmop *leftOp, *rightOp;
3442 D(emitcode ("; genMinus",""));
3444 aopOp (IC_LEFT (ic), ic, FALSE);
3445 aopOp (IC_RIGHT (ic), ic, FALSE);
3446 aopOp (IC_RESULT (ic), ic, TRUE);
3448 /* special cases :- */
3449 /* if I can do an decrement instead
3450 of subtract then GOOD for ME */
3451 if (genMinusDec (ic) == TRUE)
3454 size = getDataSize (IC_RESULT (ic));
3457 leftOp = AOP(IC_LEFT(ic));
3458 rightOp = AOP(IC_RIGHT(ic));
3464 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3465 accopWithAop(sub, rightOp, offset);
3466 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3471 // adjustArithmeticResult (ic);
3474 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3475 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3476 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3481 /*-----------------------------------------------------------------*/
3482 /* genMultOneByte : 8*8=8/16 bit multiplication */
3483 /*-----------------------------------------------------------------*/
3485 genMultOneByte (operand * left,
3489 /* sym_link *opetype = operandType (result); */
3490 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3491 int size=AOP_SIZE(result);
3492 bool negLiteral = FALSE;
3494 D(emitcode ("; genMultOneByte",""));
3496 if (size<1 || size>2) {
3497 // this should never happen
3498 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3499 AOP_SIZE(result), __FILE__, lineno);
3503 /* (if two literals: the value is computed before) */
3504 /* if one literal, literal on the right */
3505 if (AOP_TYPE (left) == AOP_LIT)
3510 //D(emitcode (";", "swapped left and right"));
3514 || (SPEC_USIGN(operandType(left)) &&
3515 SPEC_USIGN(operandType(right))))
3517 // just an unsigned 8*8=8/16 multiply
3518 //D(emitcode (";","unsigned"));
3520 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3521 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3522 emitcode ("mul", "");
3523 hc08_dirtyReg (hc08_reg_xa, FALSE);
3524 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3525 hc08_freeReg (hc08_reg_xa);
3530 // we have to do a signed multiply
3533 //D(emitcode (";", "signed"));
3535 emitcode ("clr", "1,s");
3537 tlbl1 = newiTempLabel (NULL);
3538 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3539 emitcode ("tsta","");
3540 emitBranch ("bpl", tlbl1);
3541 emitcode ("inc", "1,s");
3542 rmwWithReg ("neg", hc08_reg_a);
3545 if (AOP_TYPE(right)==AOP_LIT)
3547 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3548 /* AND literal negative */
3550 emitcode ("ldx", "#0x%02x", -val);
3553 emitcode ("ldx", "#0x%02x", val);
3555 hc08_useReg (hc08_reg_x);
3559 tlbl2 = newiTempLabel (NULL);
3560 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3561 emitcode ("tstx", "");
3562 emitBranch ("bpl", tlbl2);
3563 emitcode ("inc", "1,s");
3564 rmwWithReg ("neg", hc08_reg_x);
3568 emitcode ("mul", "");
3569 hc08_dirtyReg (hc08_reg_xa, FALSE);
3571 tlbl3 = newiTempLabel (NULL);
3572 emitcode ("dec", "1,s");
3574 emitBranch ("bne", tlbl3);
3576 emitBranch ("beq", tlbl3);
3578 rmwWithReg ("neg", hc08_reg_a);
3581 tlbl4 = newiTempLabel (NULL);
3582 emitBranch ("bcc", tlbl4);
3583 rmwWithReg ("inc", hc08_reg_x);
3585 rmwWithReg ("neg", hc08_reg_x);
3590 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3591 hc08_freeReg (hc08_reg_xa);
3595 /*-----------------------------------------------------------------*/
3596 /* genMult - generates code for multiplication */
3597 /*-----------------------------------------------------------------*/
3599 genMult (iCode * ic)
3601 operand *left = IC_LEFT (ic);
3602 operand *right = IC_RIGHT (ic);
3603 operand *result = IC_RESULT (ic);
3605 D(emitcode ("; genMult",""));
3607 /* assign the amsops */
3608 aopOp (left, ic, FALSE);
3609 aopOp (right, ic, FALSE);
3610 aopOp (result, ic, TRUE);
3612 /* special cases first */
3613 /* if both are of size == 1 */
3614 // if (getSize(operandType(left)) == 1 &&
3615 // getSize(operandType(right)) == 1)
3616 if (AOP_SIZE (left) == 1 &&
3617 AOP_SIZE (right) == 1)
3619 genMultOneByte (left, right, result);
3623 /* should have been converted to function call */
3624 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3625 getSize(OP_SYMBOL(right)->type));
3626 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3631 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3632 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3633 freeAsmop (result, NULL, ic, TRUE);
3636 /*-----------------------------------------------------------------*/
3637 /* genDivOneByte : 8 bit division */
3638 /*-----------------------------------------------------------------*/
3640 genDivOneByte (operand * left,
3644 sym_link *opetype = operandType (result);
3646 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3648 bool negLiteral = FALSE;
3650 D(emitcode ("; genDivOneByte",""));
3652 size = AOP_SIZE (result);
3653 /* signed or unsigned */
3654 if (SPEC_USIGN (opetype))
3656 /* unsigned is easy */
3657 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3658 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3659 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3660 emitcode ("div", "");
3661 hc08_dirtyReg (hc08_reg_a, FALSE);
3662 hc08_dirtyReg (hc08_reg_h, FALSE);
3663 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3664 hc08_freeReg (hc08_reg_a);
3665 hc08_freeReg (hc08_reg_x);
3666 hc08_freeReg (hc08_reg_h);
3670 /* signed is a little bit more difficult */
3673 emitcode ("clr", "1,s");
3675 tlbl1 = newiTempLabel (NULL);
3676 tlbl2 = newiTempLabel (NULL);
3677 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3678 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3679 emitBranch ("bpl", tlbl1);
3680 emitcode ("inc", "1,s");
3681 rmwWithReg ("neg", hc08_reg_a);
3682 emitBranch ("bcc", tlbl2);
3683 rmwWithReg ("inc", hc08_reg_x);
3685 rmwWithReg ("neg", hc08_reg_x);
3686 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3689 if (AOP_TYPE(right)==AOP_LIT)
3691 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3692 /* AND literal negative */
3694 emitcode ("ldx", "#0x%02x", -val);
3697 emitcode ("ldx", "#0x%02x", val);
3699 hc08_useReg (hc08_reg_x);
3703 tlbl3 = newiTempLabel (NULL);
3704 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3705 emitBranch ("bpl", tlbl3);
3706 emitcode ("inc", "1,s");
3707 rmwWithReg ("neg", hc08_reg_x);
3711 emitcode ("div", "");
3712 hc08_dirtyReg (hc08_reg_x, FALSE);
3713 hc08_dirtyReg (hc08_reg_a, FALSE);
3714 hc08_dirtyReg (hc08_reg_h, FALSE);
3716 tlbl4 = newiTempLabel (NULL);
3717 emitcode ("dec", "1,s");
3719 emitBranch ("bne", tlbl4);
3721 emitBranch ("beq", tlbl4);
3722 rmwWithReg ("neg", hc08_reg_a);
3726 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3727 hc08_freeReg (hc08_reg_a);
3728 hc08_freeReg (hc08_reg_x);
3729 hc08_freeReg (hc08_reg_h);
3734 /*-----------------------------------------------------------------*/
3735 /* genDiv - generates code for division */
3736 /*-----------------------------------------------------------------*/
3740 operand *left = IC_LEFT (ic);
3741 operand *right = IC_RIGHT (ic);
3742 operand *result = IC_RESULT (ic);
3744 D(emitcode ("; genDiv",""));
3746 /* assign the amsops */
3747 aopOp (left, ic, FALSE);
3748 aopOp (right, ic, FALSE);
3749 aopOp (result, ic, TRUE);
3751 /* special cases first */
3752 /* if both are of size == 1 */
3753 if (AOP_SIZE (left) <= 2 &&
3754 AOP_SIZE (right) == 1)
3756 genDivOneByte (left, right, result);
3760 /* should have been converted to function call */
3763 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3764 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3765 freeAsmop (result, NULL, ic, TRUE);
3768 /*-----------------------------------------------------------------*/
3769 /* genModOneByte : 8 bit modulus */
3770 /*-----------------------------------------------------------------*/
3772 genModOneByte (operand * left,
3776 sym_link *opetype = operandType (result);
3778 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3780 bool negLiteral = FALSE;
3782 D(emitcode ("; genModOneByte",""));
3784 size = AOP_SIZE (result);
3785 /* signed or unsigned */
3786 if (SPEC_USIGN (opetype))
3788 /* unsigned is easy */
3789 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3790 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3791 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3792 emitcode ("div", "");
3793 hc08_dirtyReg (hc08_reg_a, FALSE);
3794 hc08_dirtyReg (hc08_reg_h, FALSE);
3795 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3796 hc08_freeReg (hc08_reg_a);
3797 hc08_freeReg (hc08_reg_x);
3798 hc08_freeReg (hc08_reg_h);
3802 /* signed is a little bit more difficult */
3805 emitcode ("clr", "1,s");
3807 tlbl1 = newiTempLabel (NULL);
3808 tlbl2 = newiTempLabel (NULL);
3809 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3810 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3811 emitBranch ("bpl", tlbl1);
3812 emitcode ("inc", "1,s");
3813 rmwWithReg ("neg", hc08_reg_a);
3814 emitBranch ("bcc", tlbl2);
3815 rmwWithReg ("inc", hc08_reg_x);
3817 rmwWithReg ("neg", hc08_reg_x);
3818 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3821 if (AOP_TYPE(right)==AOP_LIT)
3823 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3824 /* AND literal negative */
3826 emitcode ("ldx", "#0x%02x", -val);
3829 emitcode ("ldx", "#0x%02x", val);
3831 hc08_useReg (hc08_reg_x);
3835 tlbl3 = newiTempLabel (NULL);
3836 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3837 emitBranch ("bpl", tlbl3);
3838 emitcode ("inc", "1,s");
3839 rmwWithReg ("neg", hc08_reg_x);
3843 emitcode ("div", "");
3844 hc08_dirtyReg (hc08_reg_x, FALSE);
3845 hc08_dirtyReg (hc08_reg_a, FALSE);
3846 hc08_dirtyReg (hc08_reg_h, FALSE);
3848 tlbl4 = newiTempLabel (NULL);
3849 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3850 emitcode ("dec", "1,s");
3852 emitBranch ("bne", tlbl4);
3854 emitBranch ("beq", tlbl4);
3855 rmwWithReg ("neg", hc08_reg_a);
3859 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3860 hc08_freeReg (hc08_reg_a);
3861 hc08_freeReg (hc08_reg_x);
3862 hc08_freeReg (hc08_reg_h);
3866 /*-----------------------------------------------------------------*/
3867 /* genMod - generates code for division */
3868 /*-----------------------------------------------------------------*/
3872 operand *left = IC_LEFT (ic);
3873 operand *right = IC_RIGHT (ic);
3874 operand *result = IC_RESULT (ic);
3876 D(emitcode ("; genMod",""));
3878 /* assign the amsops */
3879 aopOp (left, ic, FALSE);
3880 aopOp (right, ic, FALSE);
3881 aopOp (result, ic, TRUE);
3883 /* special cases first */
3884 /* if both are of size == 1 */
3885 if (AOP_SIZE (left) <= 2 &&
3886 AOP_SIZE (right) == 1)
3888 genModOneByte (left, right, result);
3892 /* should have been converted to function call */
3896 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3897 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3898 freeAsmop (result, NULL, ic, TRUE);
3901 /*-----------------------------------------------------------------*/
3902 /* genIfxJump :- will create a jump depending on the ifx */
3903 /*-----------------------------------------------------------------*/
3905 genIfxJump (iCode * ic, char *jval)
3908 symbol *tlbl = newiTempLabel (NULL);
3911 D(emitcode ("; genIfxJump",""));
3913 /* if true label then we jump if condition
3917 jlbl = IC_TRUE (ic);
3918 if (!strcmp (jval, "a"))
3920 else if (!strcmp (jval, "c"))
3927 /* false label is present */
3928 jlbl = IC_FALSE (ic);
3929 if (!strcmp (jval, "a"))
3931 else if (!strcmp (jval, "c"))
3936 emitBranch (inst, tlbl);
3937 emitBranch ("jmp", jlbl);
3940 /* mark the icode as generated */
3944 /*-----------------------------------------------------------------*/
3945 /* genCmp :- greater or less than comparison */
3946 /*-----------------------------------------------------------------*/
3948 genCmp (operand * left, operand * right,
3949 operand * result, iCode * ifx, int sign, iCode *ic)
3951 int size, offset = 0;
3952 unsigned long lit = 0L;
3954 bool needpula = FALSE;
3956 D(emitcode ("; genCmp",""));
3958 /* subtract right from left if at the
3959 end the carry flag is set then we know that
3960 left is greater than right */
3961 size = max (AOP_SIZE (left), AOP_SIZE (right));
3963 if (AOP_TYPE (right) == AOP_LIT)
3965 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3966 /* optimize if(x < 0) or if(x >= 0) */
3975 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3976 emitcode ("rola", "");
3977 hc08_useReg (hc08_reg_a);
3985 && ((AOP_TYPE (right) == AOP_LIT) ||
3986 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3987 && hc08_reg_hx->isFree)
3989 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3990 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3991 hc08_freeReg (hc08_reg_hx);
4002 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4003 accopWithAop (sub, AOP (right), offset);
4004 hc08_freeReg (hc08_reg_a);
4010 freeAsmop (right, NULL, ic, TRUE);
4011 freeAsmop (left, NULL, ic, TRUE);
4012 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4018 /* if the result is used in the next
4019 ifx conditional branch then generate
4020 code a little differently */
4023 pullOrFreeReg(hc08_reg_a,needpula);
4024 genIfxJump (ifx, sign ? "s" : "c");
4031 pullOrFreeReg(hc08_reg_a,needpula);
4035 /*-----------------------------------------------------------------*/
4036 /* genCmpGt :- greater than comparison */
4037 /*-----------------------------------------------------------------*/
4039 genCmpGt (iCode * ic, iCode * ifx)
4041 operand *left, *right, *result;
4042 sym_link *letype, *retype;
4045 D(emitcode ("; genCmpGt",""));
4047 result = IC_RESULT (ic);
4048 left = IC_LEFT (ic);
4049 right = IC_RIGHT (ic);
4051 letype = getSpec (operandType (left));
4052 retype = getSpec (operandType (right));
4053 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4054 /* assign the amsops */
4055 aopOp (left, ic, FALSE);
4056 aopOp (right, ic, FALSE);
4057 aopOp (result, ic, TRUE);
4059 genCmp (right, left, result, ifx, sign,ic);
4061 freeAsmop (result, NULL, ic, TRUE);
4064 /*-----------------------------------------------------------------*/
4065 /* genCmpLt - less than comparisons */
4066 /*-----------------------------------------------------------------*/
4068 genCmpLt (iCode * ic, iCode * ifx)
4070 operand *left, *right, *result;
4071 sym_link *letype, *retype;
4074 D(emitcode ("; genCmpLt",""));
4076 result = IC_RESULT (ic);
4077 left = IC_LEFT (ic);
4078 right = IC_RIGHT (ic);
4080 letype = getSpec (operandType (left));
4081 retype = getSpec (operandType (right));
4082 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4084 /* assign the amsops */
4085 aopOp (left, ic, FALSE);
4086 aopOp (right, ic, FALSE);
4087 aopOp (result, ic, TRUE);
4089 genCmp (left, right, result, ifx, sign,ic);
4091 freeAsmop (result, NULL, ic, TRUE);
4094 /*-----------------------------------------------------------------*/
4095 /* - compare and branch if not equal */
4096 /*-----------------------------------------------------------------*/
4098 gencbneshort (operand * left, operand * right, symbol * lbl)
4100 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4102 unsigned long lit = 0L;
4104 /* if the left side is a literal or
4105 if the right is in a pointer register and left
4107 if (AOP_TYPE (left) == AOP_LIT)
4113 if (AOP_TYPE (right) == AOP_LIT)
4114 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4118 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4119 accopWithAop ("cmp", AOP (right), offset);
4120 hc08_useReg (hc08_reg_a);
4121 hc08_freeReg (hc08_reg_a);
4122 emitBranch ("bne", lbl);
4128 /*-----------------------------------------------------------------*/
4129 /* gencjne - compare and jump if not equal */
4130 /*-----------------------------------------------------------------*/
4132 gencjne (operand * left, operand * right, symbol * lbl)
4134 symbol *tlbl = newiTempLabel (NULL);
4136 gencbneshort (left, right, lbl);
4138 loadRegFromConst (hc08_reg_a, one);
4139 emitBranch ("bra", tlbl);
4141 loadRegFromConst (hc08_reg_a, zero);
4144 hc08_useReg(hc08_reg_a);
4145 hc08_freeReg(hc08_reg_a);
4148 /*-----------------------------------------------------------------*/
4149 /* genCmpEq - generates code for equal to */
4150 /*-----------------------------------------------------------------*/
4152 genCmpEq (iCode * ic, iCode * ifx)
4154 operand *left, *right, *result;
4156 D(emitcode ("; genCmpEq",""));
4158 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4159 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4160 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4162 /* if literal, literal on the right or
4163 if the right is in a pointer register and left
4165 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4167 operand *t = IC_RIGHT (ic);
4168 IC_RIGHT (ic) = IC_LEFT (ic);
4172 if (ifx && !AOP_SIZE (result))
4175 tlbl = newiTempLabel (NULL);
4176 gencbneshort (left, right, tlbl);
4179 emitBranch ("jmp", IC_TRUE (ifx));
4184 symbol *lbl = newiTempLabel (NULL);
4185 emitBranch ("bra", lbl);
4187 emitBranch ("jmp", IC_FALSE (ifx));
4191 /* mark the icode as generated */
4196 gencjne (left, right, newiTempLabel (NULL));
4197 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4199 storeRegToAop (hc08_reg_a, AOP (result), 0);
4204 genIfxJump (ifx, "a");
4207 /* if the result is used in an arithmetic operation
4208 then put the result in place */
4209 if (AOP_TYPE (result) != AOP_CRY)
4213 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4214 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4215 freeAsmop (result, NULL, ic, TRUE);
4218 /*-----------------------------------------------------------------*/
4219 /* ifxForOp - returns the icode containing the ifx for operand */
4220 /*-----------------------------------------------------------------*/
4222 ifxForOp (operand * op, iCode * ic)
4224 /* if true symbol then needs to be assigned */
4225 if (IS_TRUE_SYMOP (op))
4228 /* if this has register type condition and
4229 the next instruction is ifx with the same operand
4230 and live to of the operand is upto the ifx only then */
4232 ic->next->op == IFX &&
4233 IC_COND (ic->next)->key == op->key &&
4234 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4241 genPointerGetSetOfs (iCode *ic)
4243 iCode *lic = ic->next;
4249 /* Make sure we have a next iCode */
4250 D(emitcode("","; checking lic"));
4254 /* Make sure the result of the addition is an iCode */
4255 D(emitcode("","; checking IS_ITEMP"));
4256 if (!IS_ITEMP (IC_RESULT (ic)))
4259 /* Make sure the next iCode is a pointer set or get */
4260 pset = POINTER_SET(lic);
4261 pget = POINTER_GET(lic);
4262 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4266 /* Make sure this is the only use of the pointer */
4267 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4270 D(emitcode("", "; checking pset operandsEqu"));
4271 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4274 D(emitcode("", "; checking pget operandsEqu"));
4275 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4278 D(emitcode("", "; checking IS_SYMOP"));
4279 if (!IS_SYMOP (IC_LEFT (ic)))
4282 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4283 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4286 sym = OP_SYMBOL (IC_LEFT (ic));
4288 D(emitcode("", "; checking remat"));
4295 D(emitcode ("; genPointerGetOfs",""));
4296 aopOp (IC_LEFT(ic), ic, FALSE);
4297 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4298 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4300 aopOp (IC_RIGHT(ic), ic, FALSE);
4301 aopOp (IC_RESULT(lic), lic, FALSE);
4303 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4305 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4307 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4308 loadRegFromConst (hc08_reg_h, zero);
4312 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4313 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4314 emitcode ("rola","");
4315 emitcode ("clra","");
4316 emitcode ("sbc", "#0");
4317 hc08_useReg (hc08_reg_a);
4318 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4322 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4323 size = AOP_SIZE (IC_RESULT(lic));
4324 derefaop->size = size;
4329 emitcode ("lda", "%s,x",
4330 aopAdrStr (derefaop, offset, TRUE));
4331 hc08_useReg (hc08_reg_a);
4332 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4333 hc08_freeReg (hc08_reg_a);
4337 hc08_freeReg (hc08_reg_hx);
4339 freeAsmop (NULL, derefaop, ic, TRUE);
4340 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4341 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4348 D(emitcode ("; genPointerSetOfs",""));
4349 aopOp (IC_LEFT(ic), ic, FALSE);
4350 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4351 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4353 aopOp (IC_RIGHT(ic), ic, FALSE);
4354 aopOp (IC_RIGHT(lic), lic, FALSE);
4356 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4358 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4360 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4361 loadRegFromConst (hc08_reg_h, zero);
4365 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4366 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4367 emitcode ("rola","");
4368 emitcode ("clra","");
4369 emitcode ("sbc", "#0");
4370 hc08_useReg (hc08_reg_a);
4371 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4375 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4376 size = AOP_SIZE (IC_RIGHT(lic));
4377 derefaop->size = size;
4382 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4383 emitcode ("sta", "%s,x",
4384 aopAdrStr (derefaop, offset, TRUE));
4385 hc08_freeReg (hc08_reg_a);
4390 hc08_freeReg (hc08_reg_hx);
4392 freeAsmop (NULL, derefaop, ic, TRUE);
4393 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4394 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4403 /*-----------------------------------------------------------------*/
4404 /* hasInc - operand is incremented before any other use */
4405 /*-----------------------------------------------------------------*/
4407 hasInc (operand *op, iCode *ic,int osize)
4409 sym_link *type = operandType(op);
4410 sym_link *retype = getSpec (type);
4411 iCode *lic = ic->next;
4414 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4415 if (!IS_SYMOP(op)) return NULL;
4417 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4418 if (IS_AGGREGATE(type->next)) return NULL;
4419 if (osize != (isize = getSize(type->next))) return NULL;
4422 /* if operand of the form op = op + <sizeof *op> */
4423 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4424 isOperandEqual(IC_RESULT(lic),op) &&
4425 isOperandLiteral(IC_RIGHT(lic)) &&
4426 operandLitValue(IC_RIGHT(lic)) == isize) {
4429 /* if the operand used or deffed */
4430 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4433 /* if GOTO or IFX */
4434 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4440 /*-----------------------------------------------------------------*/
4441 /* genAndOp - for && operation */
4442 /*-----------------------------------------------------------------*/
4444 genAndOp (iCode * ic)
4446 operand *left, *right, *result;
4447 symbol *tlbl, *tlbl0;
4449 D(emitcode ("; genAndOp",""));
4451 /* note here that && operations that are in an
4452 if statement are taken away by backPatchLabels
4453 only those used in arthmetic operations remain */
4454 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4455 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4456 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4458 tlbl = newiTempLabel (NULL);
4459 tlbl0 = newiTempLabel (NULL);
4461 asmopToBool (AOP (left), FALSE);
4462 emitBranch ("beq", tlbl0);
4463 asmopToBool (AOP (right), FALSE);
4464 emitBranch ("beq", tlbl0);
4465 loadRegFromConst (hc08_reg_a,one);
4466 emitBranch ("bra", tlbl);
4468 loadRegFromConst (hc08_reg_a,zero);
4471 hc08_useReg (hc08_reg_a);
4472 hc08_freeReg (hc08_reg_a);
4474 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4476 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4477 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4478 freeAsmop (result, NULL, ic, TRUE);
4482 /*-----------------------------------------------------------------*/
4483 /* genOrOp - for || operation */
4484 /*-----------------------------------------------------------------*/
4486 genOrOp (iCode * ic)
4488 operand *left, *right, *result;
4489 symbol *tlbl, *tlbl0;
4491 D(emitcode ("; genOrOp",""));
4493 /* note here that || operations that are in an
4494 if statement are taken away by backPatchLabels
4495 only those used in arthmetic operations remain */
4496 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4497 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4498 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4500 tlbl = newiTempLabel (NULL);
4501 tlbl0 = newiTempLabel (NULL);
4503 asmopToBool (AOP (left), FALSE);
4504 emitBranch ("bne", tlbl0);
4505 asmopToBool (AOP (right), FALSE);
4506 emitBranch ("bne", tlbl0);
4507 loadRegFromConst (hc08_reg_a,zero);
4508 emitBranch ("bra", tlbl);
4510 loadRegFromConst (hc08_reg_a,one);
4513 hc08_useReg (hc08_reg_a);
4514 hc08_freeReg (hc08_reg_a);
4516 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4519 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4520 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4521 freeAsmop (result, NULL, ic, TRUE);
4524 /*-----------------------------------------------------------------*/
4525 /* isLiteralBit - test if lit == 2^n */
4526 /*-----------------------------------------------------------------*/
4528 isLiteralBit (unsigned long lit)
4530 unsigned long pw[32] =
4531 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4532 0x100L, 0x200L, 0x400L, 0x800L,
4533 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4534 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4535 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4536 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4537 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4540 for (idx = 0; idx < 32; idx++)
4547 /*-----------------------------------------------------------------*/
4548 /* continueIfTrue - */
4549 /*-----------------------------------------------------------------*/
4551 continueIfTrue (iCode * ic)
4554 emitBranch ("jmp", IC_TRUE (ic));
4558 /*-----------------------------------------------------------------*/
4560 /*-----------------------------------------------------------------*/
4562 jumpIfTrue (iCode * ic)
4565 emitBranch ("jmp", IC_FALSE (ic));
4569 /*-----------------------------------------------------------------*/
4570 /* jmpTrueOrFalse - */
4571 /*-----------------------------------------------------------------*/
4573 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4575 // ugly but optimized by peephole
4578 symbol *nlbl = newiTempLabel (NULL);
4579 emitBranch ("bra", nlbl);
4581 emitBranch ("jmp", IC_TRUE (ic));
4586 emitBranch ("jmp", IC_FALSE (ic));
4593 /*-----------------------------------------------------------------*/
4594 /* genAnd - code for and */
4595 /*-----------------------------------------------------------------*/
4597 genAnd (iCode * ic, iCode * ifx)
4599 operand *left, *right, *result;
4600 int size, offset = 0;
4601 unsigned long lit = 0L;
4602 unsigned long litinv;
4608 D(emitcode ("; genAnd",""));
4610 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4611 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4612 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4615 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4617 AOP_TYPE (left), AOP_TYPE (right)));
4618 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4620 AOP_SIZE (left), AOP_SIZE (right)));
4623 /* if left is a literal & right is not then exchange them */
4624 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4626 operand *tmp = right;
4631 /* if left is accumulator & right is not then exchange them */
4632 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4634 operand *tmp = right;
4640 if (AOP_TYPE (result) == AOP_CRY)
4643 wassertl (ifx, "AOP_CPY result without ifx");
4645 tlbl = newiTempLabel (NULL);
4646 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4650 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4651 if ((AOP_TYPE (right) == AOP_LIT)
4652 && (((lit >> (offset*8)) & 0xff) == 0xff))
4653 emitcode ("tsta","");
4655 accopWithAop ("and", AOP (right), offset);
4656 hc08_freeReg( hc08_reg_a);
4658 emitBranch ("bne", tlbl);
4662 genIfxJump (ifx, "a");
4668 size = AOP_SIZE (result);
4670 if (AOP_TYPE (right) == AOP_LIT)
4672 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4673 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4675 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4676 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4678 int bitpos = isLiteralBit(litinv)-1;
4679 emitcode ("bclr","#%d,%s",bitpos & 7,
4680 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4688 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4689 if ((AOP_TYPE (right) != AOP_LIT)
4690 || (((lit >> (offset*8)) & 0xff) != 0xff))
4691 accopWithAop ("and", AOP (right), offset);
4692 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4693 hc08_freeReg( hc08_reg_a);
4697 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4698 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4699 freeAsmop (result, NULL, ic, TRUE);
4702 /*-----------------------------------------------------------------*/
4703 /* genOr - code for or */
4704 /*-----------------------------------------------------------------*/
4706 genOr (iCode * ic, iCode * ifx)
4708 operand *left, *right, *result;
4709 int size, offset = 0;
4710 unsigned long lit = 0L;
4712 D(emitcode ("; genOr",""));
4714 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4715 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4716 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4719 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4721 AOP_TYPE (left), AOP_TYPE (right)));
4722 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4724 AOP_SIZE (left), AOP_SIZE (right)));
4727 /* if left is a literal & right is not then exchange them */
4728 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4730 operand *tmp = right;
4735 /* if left is accumulator & right is not then exchange them */
4736 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4738 operand *tmp = right;
4743 if (AOP_TYPE (result) == AOP_CRY)
4746 wassertl (ifx, "AOP_CPY result without ifx");
4748 tlbl = newiTempLabel (NULL);
4749 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4753 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4754 if ((AOP_TYPE (right) == AOP_LIT)
4755 && (((lit >> (offset*8)) & 0xff) == 0))
4756 emitcode ("tsta","");
4758 accopWithAop ("ora", AOP (right), offset);
4759 hc08_freeReg( hc08_reg_a);
4761 emitBranch ("bne", tlbl);
4765 genIfxJump (ifx, "a");
4771 if (AOP_TYPE (right) == AOP_LIT)
4772 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4774 size = AOP_SIZE (result);
4776 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4777 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4778 (AOP_TYPE (left) == AOP_DIR))
4780 int bitpos = isLiteralBit(lit)-1;
4781 emitcode ("bset","#%d,%s",bitpos & 7,
4782 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4789 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4790 accopWithAop ("ora", AOP (right), offset);
4791 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4792 hc08_freeReg( hc08_reg_a);
4797 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4798 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4799 freeAsmop (result, NULL, ic, TRUE);
4802 /*-----------------------------------------------------------------*/
4803 /* genXor - code for xclusive or */
4804 /*-----------------------------------------------------------------*/
4806 genXor (iCode * ic, iCode * ifx)
4808 operand *left, *right, *result;
4809 int size, offset = 0;
4810 unsigned long lit = 0L;
4812 D(emitcode ("; genXor",""));
4814 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4815 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4816 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4819 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4821 AOP_TYPE (left), AOP_TYPE (right)));
4822 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4824 AOP_SIZE (left), AOP_SIZE (right)));
4827 /* if left is a literal & right is not ||
4828 if left needs acc & right does not */
4829 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4831 operand *tmp = right;
4836 /* if left is accumulator & right is not then exchange them */
4837 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4839 operand *tmp = right;
4844 if (AOP_TYPE (result) == AOP_CRY)
4847 wassertl (ifx, "AOP_CPY result without ifx");
4849 tlbl = newiTempLabel (NULL);
4850 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4854 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4855 if ((AOP_TYPE (right) == AOP_LIT)
4856 && (((lit >> (offset*8)) & 0xff) == 0))
4857 emitcode ("tsta","");
4859 accopWithAop ("eor", AOP (right), offset);
4860 hc08_freeReg( hc08_reg_a);
4862 emitBranch ("bne", tlbl);
4866 genIfxJump (ifx, "a");
4872 if (AOP_TYPE (right) == AOP_LIT)
4873 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4875 size = AOP_SIZE (result);
4879 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4880 accopWithAop ("eor", AOP (right), offset);
4881 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4882 hc08_freeReg( hc08_reg_a);
4886 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4887 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4888 freeAsmop (result, NULL, ic, TRUE);
4892 emitinline (iCode * ic, char *inlin)
4898 symbol *sym, *tempsym;
4907 while (isalnum(*inlin) || (*inlin == '_'))
4911 //printf("Found possible symbol '%s'\n",symname);
4912 tempsym = newSymbol (symname, ic->level);
4913 tempsym->block = ic->block;
4914 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4923 aop = aopForSym (ic, sym, FALSE);
4924 l = aopAdrStr (aop, aop->size - 1, TRUE);
4928 if (!sym->allocreq && !sym->ismyparm)
4930 werror (E_ID_UNDEF, sym->name);
4932 " Add 'volatile' to the variable declaration so that it\n"
4933 " can be referenced within inline assembly");
4935 //printf("Replacing with '%s'\n",l);
4939 if ((2+bp-buffer)>sizeof(buffer))
4948 if ((2+bp-buffer)>sizeof(buffer))
4955 if ((2+bp-buffer)>sizeof(buffer))
4956 fprintf(stderr, "Inline assembly buffer overflow\n");
4958 //printf("%s\n",buffer);
4959 emitcode (buffer,"");
4963 /*-----------------------------------------------------------------*/
4964 /* genInline - write the inline code out */
4965 /*-----------------------------------------------------------------*/
4967 genInline (iCode * ic)
4969 char *buffer, *bp, *bp1;
4971 D(emitcode ("; genInline",""));
4973 _G.inLine += (!options.asmpeep);
4975 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4976 strcpy (buffer, IC_INLINE (ic));
4978 /* emit each line as a code */
4984 /* emitcode (bp1, ""); */
4985 emitinline (ic, bp1);
5004 /* emitcode (bp1, ""); */
5005 emitinline (ic, bp1);
5007 /* emitcode("",buffer); */
5008 _G.inLine -= (!options.asmpeep);
5011 /*-----------------------------------------------------------------*/
5012 /* genRRC - rotate right with carry */
5013 /*-----------------------------------------------------------------*/
5017 operand *left, *result;
5018 int size, offset = 0;
5019 bool needpula = FALSE;
5020 bool resultInA = FALSE;
5023 D(emitcode ("; genRRC",""));
5025 /* rotate right with carry */
5026 left = IC_LEFT (ic);
5027 result = IC_RESULT (ic);
5028 aopOp (left, ic, FALSE);
5029 aopOp (result, ic, FALSE);
5031 if ((AOP_TYPE (result) == AOP_REG)
5032 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5035 size = AOP_SIZE (result);
5039 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5043 rmwWithAop (shift, AOP (result), offset--);
5051 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5052 rmwWithReg (shift, hc08_reg_a);
5053 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5054 hc08_freeReg (hc08_reg_a);
5059 if ((!hc08_reg_a->isFree) || resultInA)
5061 pushReg (hc08_reg_a, TRUE);
5065 /* now we need to put the carry into the
5066 highest order byte of the result */
5067 offset = AOP_SIZE (result) - 1;
5068 emitcode ("clra","");
5069 emitcode ("rora","");
5070 hc08_dirtyReg (hc08_reg_a, FALSE);
5073 emitcode ("ora", "1,s");
5074 emitcode ("ais", "#1");
5075 hc08_dirtyReg (hc08_reg_a, FALSE);
5079 accopWithAop ("ora", AOP (result), offset);
5080 storeRegToAop (hc08_reg_a, AOP (result), offset);
5082 pullOrFreeReg (hc08_reg_a, needpula);
5084 freeAsmop (left, NULL, ic, TRUE);
5085 freeAsmop (result, NULL, ic, TRUE);
5088 /*-----------------------------------------------------------------*/
5089 /* genRLC - generate code for rotate left with carry */
5090 /*-----------------------------------------------------------------*/
5094 operand *left, *result;
5095 int size, offset = 0;
5097 bool resultInA = FALSE;
5098 bool needpula = FALSE;
5100 D(emitcode ("; genRLC",""));
5102 /* rotate right with carry */
5103 left = IC_LEFT (ic);
5104 result = IC_RESULT (ic);
5105 aopOp (left, ic, FALSE);
5106 aopOp (result, ic, FALSE);
5108 if ((AOP_TYPE (result) == AOP_REG)
5109 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5112 size = AOP_SIZE (result);
5116 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5120 rmwWithAop (shift, AOP (result), offset--);
5128 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5129 rmwWithReg (shift, hc08_reg_a);
5130 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5131 hc08_freeReg (hc08_reg_a);
5136 if ((!hc08_reg_a->isFree) || resultInA)
5138 pushReg (hc08_reg_a, TRUE);
5142 /* now we need to put the carry into the
5143 lowest order byte of the result */
5145 emitcode ("clra","");
5146 emitcode ("rola","");
5147 hc08_dirtyReg (hc08_reg_a, FALSE);
5150 emitcode ("ora", "1,s");
5151 emitcode ("ais", "#1");
5152 hc08_dirtyReg (hc08_reg_a, FALSE);
5156 accopWithAop ("ora", AOP (result), offset);
5157 storeRegToAop (hc08_reg_a, AOP (result), offset);
5159 pullOrFreeReg (hc08_reg_a, needpula);
5161 freeAsmop (left, NULL, ic, TRUE);
5162 freeAsmop (result, NULL, ic, TRUE);
5165 /*-----------------------------------------------------------------*/
5166 /* genGetHbit - generates code get highest order bit */
5167 /*-----------------------------------------------------------------*/
5169 genGetHbit (iCode * ic)
5171 operand *left, *result;
5173 D(emitcode ("; genGetHbit",""));
5175 left = IC_LEFT (ic);
5176 result = IC_RESULT (ic);
5177 aopOp (left, ic, FALSE);
5178 aopOp (result, ic, FALSE);
5180 /* get the highest order byte into a */
5181 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5182 emitcode ("rola", "");
5183 emitcode ("clra", "");
5184 emitcode ("rola", "");
5185 hc08_dirtyReg (hc08_reg_a, FALSE);
5186 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5187 hc08_freeReg (hc08_reg_a);
5189 freeAsmop (left, NULL, ic, TRUE);
5190 freeAsmop (result, NULL, ic, TRUE);
5193 /*-----------------------------------------------------------------*/
5194 /* genSwap - generates code to swap nibbles or bytes */
5195 /*-----------------------------------------------------------------*/
5197 genSwap (iCode * ic)
5199 operand *left, *result;
5201 D(emitcode ("; genSwap",""));
5203 left = IC_LEFT (ic);
5204 result = IC_RESULT (ic);
5205 aopOp (left, ic, FALSE);
5206 aopOp (result, ic, FALSE);
5208 switch (AOP_SIZE (left))
5210 case 1: /* swap nibbles in byte */
5211 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5212 emitcode ("nsa", "");
5213 hc08_dirtyReg (hc08_reg_a, FALSE);
5214 storeRegToAop (hc08_reg_a, AOP (result), 0);
5215 hc08_freeReg (hc08_reg_a);
5217 case 2: /* swap bytes in a word */
5218 if (operandsEqu (left, result))
5220 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5221 hc08_useReg (hc08_reg_a);
5222 transferAopAop (AOP (left), 1, AOP (result), 0);
5223 storeRegToAop (hc08_reg_a, AOP (result), 1);
5224 hc08_freeReg (hc08_reg_a);
5228 transferAopAop (AOP (left), 0, AOP (result), 1);
5229 transferAopAop (AOP (left), 1, AOP (result), 0);
5233 wassertl(FALSE, "unsupported SWAP operand size");
5236 freeAsmop (left, NULL, ic, TRUE);
5237 freeAsmop (result, NULL, ic, TRUE);
5241 /*-----------------------------------------------------------------*/
5242 /* AccRol - rotate left accumulator by known count */
5243 /*-----------------------------------------------------------------*/
5245 AccRol (int shCount)
5247 shCount &= 0x0007; // shCount : 0..7
5254 emitcode ("rola", ""); /* 1 cycle */
5257 emitcode ("rola", ""); /* 1 cycle */
5258 emitcode ("rola", ""); /* 1 cycle */
5261 emitcode ("nsa", "");
5262 emitcode ("rora", "");
5265 emitcode ("nsa", ""); /* 3 cycles */
5268 emitcode ("nsa", ""); /* 3 cycles */
5269 emitcode ("rola", ""); /* 1 cycle */
5272 emitcode ("nsa", ""); /* 3 cycles */
5273 emitcode ("rola", ""); /* 1 cycle */
5274 emitcode ("rola", ""); /* 1 cycle */
5277 emitcode ("nsa", ""); /* 3 cycles */
5278 emitcode ("rola", ""); /* 1 cycle */
5279 emitcode ("rola", ""); /* 1 cycle */
5280 emitcode ("rola", ""); /* 1 cycle */
5287 /*-----------------------------------------------------------------*/
5288 /* AccLsh - left shift accumulator by known count */
5289 /*-----------------------------------------------------------------*/
5291 AccLsh (int shCount)
5295 shCount &= 0x0007; // shCount : 0..7
5297 /* Shift counts of 4 and 5 are currently optimized for code size. */
5298 /* Falling through to the unrolled loop would be optimal for code speed. */
5299 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5303 accopWithMisc ("nsa", "");
5304 accopWithMisc ("and", "#0xf0");
5305 /* total: 5 cycles, 3 bytes */
5308 accopWithMisc ("nsa", "");
5309 accopWithMisc ("and", "#0xf0");
5310 accopWithMisc ("lsla", "");
5311 /* total: 6 cycles, 4 bytes */
5314 accopWithMisc ("rora", "");
5315 accopWithMisc ("rora", "");
5316 accopWithMisc ("rora", "");
5317 accopWithMisc ("and", "#0xc0");
5318 /* total: 5 cycles, 5 bytes */
5321 accopWithMisc ("rora", "");
5322 accopWithMisc ("clra", "");
5323 accopWithMisc ("rora", "");
5324 /* total: 3 cycles, 3 bytes */
5328 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5329 /* the fastest (shCount<6) and shortest (shCount<4). */
5330 for (i=0;i<shCount;i++)
5331 accopWithMisc ("lsla", "");
5335 /*-----------------------------------------------------------------*/
5336 /* AccSRsh - signed right shift accumulator by known count */
5337 /*-----------------------------------------------------------------*/
5339 AccSRsh (int shCount)
5343 shCount &= 0x0007; // shCount : 0..7
5347 accopWithMisc ("rola", "");
5348 accopWithMisc ("clra", "");
5349 accopWithMisc ("sbc", zero);
5350 /* total: 4 cycles, 4 bytes */
5354 for (i=0;i<shCount;i++)
5355 accopWithMisc ("asra", "");
5358 /*-----------------------------------------------------------------*/
5359 /* AccRsh - right shift accumulator by known count */
5360 /*-----------------------------------------------------------------*/
5362 AccRsh (int shCount, bool sign)
5372 shCount &= 0x0007; // shCount : 0..7
5374 /* Shift counts of 4 and 5 are currently optimized for code size. */
5375 /* Falling through to the unrolled loop would be optimal for code speed. */
5376 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5380 accopWithMisc ("nsa", "");
5381 accopWithMisc ("and", "#0x0f");
5382 /* total: 5 cycles, 3 bytes */
5385 accopWithMisc ("nsa", "");
5386 accopWithMisc ("and", "#0x0f");
5387 accopWithMisc ("lsra", "");
5388 /* total: 6 cycles, 4 bytes */
5391 accopWithMisc ("rola", "");
5392 accopWithMisc ("rola", "");
5393 accopWithMisc ("rola", "");
5394 accopWithMisc ("and", "#0x03");
5395 /* total: 5 cycles, 5 bytes */
5398 accopWithMisc ("rola", "");
5399 accopWithMisc ("clra", "");
5400 accopWithMisc ("rola", "");
5401 /* total: 3 cycles, 3 bytes */
5405 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5406 /* the fastest (shCount<6) and shortest (shCount<4). */
5407 for (i=0;i<shCount;i++)
5408 accopWithMisc ("lsra", "");
5412 /*-----------------------------------------------------------------*/
5413 /* XAccLsh - left shift register pair XA by known count */
5414 /*-----------------------------------------------------------------*/
5416 XAccLsh (int shCount)
5420 shCount &= 0x000f; // shCount : 0..15
5425 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5426 loadRegFromConst (hc08_reg_a, zero);
5430 /* if we can beat 2n cycles or bytes for some special case, do it here */
5434 /* bytes cycles reg x reg a carry
5435 ** abcd efgh ijkl mnop ?
5436 ** lsrx 1 1 0abc defg ijkl mnop h
5437 ** rora 1 1 0abc defg hijk lmno p
5438 ** tax 1 1 hijk lmno hijk lmno p
5439 ** clra 1 1 hijk lmno 0000 0000 p
5440 ** rora 1 1 hijk lmno p000 0000 0
5441 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5443 rmwWithReg ("lsr", hc08_reg_x);
5444 rmwWithReg ("ror", hc08_reg_a);
5445 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5446 loadRegFromConst (hc08_reg_a, zero);
5447 rmwWithReg ("ror", hc08_reg_a);
5454 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5455 /* the fastest and shortest. */
5456 for (i=0;i<shCount;i++)
5458 rmwWithReg ("lsl", hc08_reg_a);
5459 rmwWithReg ("rol", hc08_reg_x);
5463 /*-----------------------------------------------------------------*/
5464 /* XAccSRsh - signed right shift register pair XA by known count */
5465 /*-----------------------------------------------------------------*/
5467 XAccSRsh (int shCount)
5471 shCount &= 0x000f; // shCount : 0..7
5473 /* if we can beat 2n cycles or bytes for some special case, do it here */
5477 /* bytes cycles reg x reg a carry
5478 ** abcd efgh ijkl mnop ?
5479 ** lslx 1 1 bcde fgh0 ijkl mnop a
5480 ** clra 1 1 bcde fgh0 0000 0000 a
5481 ** rola 1 1 bcde fgh0 0000 000a 0
5482 ** nega 1 1 bcde fgh0 aaaa aaaa a
5483 ** tax 1 1 aaaa aaaa aaaa aaaa a
5484 ** total: 5 cycles, 5 bytes
5486 rmwWithReg ("lsl", hc08_reg_x);
5487 loadRegFromConst (hc08_reg_a, zero);
5488 rmwWithReg ("rol", hc08_reg_a);
5489 rmwWithReg ("neg", hc08_reg_a);
5490 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5500 /* bytes cycles reg x reg a carry
5501 ** abcd efgh ijkl mnop ?
5502 ** txa 1 1 abcd efgh abcd efgh ?
5503 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5504 ** lsla 1 1 abcd efgh ???? ???? a
5505 ** clrx 1 1 0000 0000 ???? ???? a
5506 ** rolx 1 1 0000 000a ???? ???? 0
5507 ** negx 1 1 aaaa aaaa ???? ???? a
5508 ** rora 1 1 aaaa aaaa LSBresult 0
5509 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5511 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5512 AccSRsh (shCount-8);
5513 rmwWithReg ("lsl", hc08_reg_a);
5514 loadRegFromConst (hc08_reg_x, zero);
5515 rmwWithReg ("rol", hc08_reg_x);
5516 rmwWithReg ("neg", hc08_reg_x);
5517 rmwWithReg ("ror", hc08_reg_a);
5524 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5525 /* the fastest and shortest. */
5526 for (i=0;i<shCount;i++)
5528 rmwWithReg ("asr", hc08_reg_x);
5529 rmwWithReg ("ror", hc08_reg_a);
5533 /*-----------------------------------------------------------------*/
5534 /* XAccRsh - right shift register pair XA by known count */
5535 /*-----------------------------------------------------------------*/
5537 XAccRsh (int shCount, bool sign)
5547 shCount &= 0x000f; // shCount : 0..f
5549 /* if we can beat 2n cycles or bytes for some special case, do it here */
5553 /* bytes cycles reg x reg a carry
5554 ** abcd efgh ijkl mnop ?
5555 ** clra 1 1 abcd efgh 0000 0000 a
5556 ** lslx 1 1 bcde fgh0 0000 0000 a
5557 ** rola 1 1 bcde fgh0 0000 000a 0
5558 ** clrx 1 1 0000 0000 0000 000a 0
5559 ** total: 4 cycles, 4 bytes
5561 loadRegFromConst (hc08_reg_x, zero);
5562 rmwWithReg ("lsl", hc08_reg_x);
5563 rmwWithReg ("rol", hc08_reg_a);
5564 loadRegFromConst (hc08_reg_a, zero);
5568 /* bytes cycles reg x reg a carry
5569 ** abcd efgh ijkl mnop ?
5570 ** clra 1 1 abcd efgh 0000 0000 a
5571 ** lslx 1 1 bcde fgh0 0000 0000 a
5572 ** rola 1 1 bcde fgh0 0000 000a 0
5573 ** lslx 1 1 cdef gh00 0000 000a b
5574 ** rola 1 1 cdef gh00 0000 00ab 0
5575 ** clrx 1 1 0000 0000 0000 00ab 0
5576 ** total: 6 cycles, 6 bytes
5578 loadRegFromConst (hc08_reg_x, zero);
5579 rmwWithReg ("lsl", hc08_reg_x);
5580 rmwWithReg ("rol", hc08_reg_a);
5581 rmwWithReg ("lsl", hc08_reg_x);
5582 rmwWithReg ("rol", hc08_reg_a);
5583 loadRegFromConst (hc08_reg_a, zero);
5592 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5593 AccRsh (shCount-8, FALSE);
5594 loadRegFromConst (hc08_reg_x, zero);
5598 /* bytes cycles reg x reg a carry
5599 ** abcd efgh ijkl mnop ?
5600 ** lsla 1 1 abcd efgh jklm nop0 i
5601 ** txa 1 1 abcd efgh abcd efgh i
5602 ** rola 1 1 abcd efgh bcde fghi a
5603 ** clrx 1 1 0000 0000 bcde fghi a
5604 ** rolx 1 1 0000 000a bcde fghi 0
5605 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5607 rmwWithReg ("lsl", hc08_reg_a);
5608 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5609 rmwWithReg ("rol", hc08_reg_a);
5610 loadRegFromConst (hc08_reg_x, zero);
5611 rmwWithReg ("rol", hc08_reg_x);
5614 /* bytes cycles reg x reg a carry
5615 ** abcd efgh ijkl mnop ?
5616 ** lsla 1 1 abcd efgh jklm nop0 i
5617 ** rolx 1 1 bcde fghi jklm nop0 a
5618 ** rola 1 1 bcde fghi klmn op0a j
5619 ** rolx 1 1 cdef ghij klmn op0a b
5620 ** rola 1 1 cdef ghij lmno p0ab k
5621 ** and #3 2 2 cdef ghij 0000 00ab k
5622 ** psha 1 2 cdef ghij 0000 00ab k
5623 ** txa 1 1 cdef ghij cdef ghij k
5624 ** pula 1 2 0000 00ab cdef ghij k
5625 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5631 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5632 /* the fastest and shortest. */
5633 for (i=0;i<shCount;i++)
5635 rmwWithReg ("lsr", hc08_reg_x);
5636 rmwWithReg ("ror", hc08_reg_a);
5643 /*-----------------------------------------------------------------*/
5644 /* shiftR1Left2Result - shift right one byte from left to result */
5645 /*-----------------------------------------------------------------*/
5647 shiftR1Left2Result (operand * left, int offl,
5648 operand * result, int offr,
5649 int shCount, int sign)
5651 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5652 /* shift right accumulator */
5653 AccRsh (shCount, sign);
5654 storeRegToAop (hc08_reg_a, AOP (result), offr);
5658 /*-----------------------------------------------------------------*/
5659 /* shiftL1Left2Result - shift left one byte from left to result */
5660 /*-----------------------------------------------------------------*/
5662 shiftL1Left2Result (operand * left, int offl,
5663 operand * result, int offr, int shCount)
5665 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5666 /* shift left accumulator */
5668 storeRegToAop (hc08_reg_a, AOP (result), offr);
5671 /*-----------------------------------------------------------------*/
5672 /* movLeft2Result - move byte from left to result */
5673 /*-----------------------------------------------------------------*/
5675 movLeft2Result (operand * left, int offl,
5676 operand * result, int offr, int sign)
5678 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5680 transferAopAop (AOP (left), offl, AOP (result), offr);
5685 /*-----------------------------------------------------------------*/
5686 /* shiftL2Left2Result - shift left two bytes from left to result */
5687 /*-----------------------------------------------------------------*/
5689 shiftL2Left2Result (operand * left, int offl,
5690 operand * result, int offr, int shCount)
5693 bool needpula = FALSE;
5694 bool needpulx = FALSE;
5696 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
5697 needpula = pushRegIfUsed (hc08_reg_a);
5700 if (!IS_AOP_XA (AOP (left)))
5701 needpulx = pushRegIfUsed (hc08_reg_x);
5705 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5710 rmwWithReg ("lsr", hc08_reg_x);
5711 rmwWithReg ("ror", hc08_reg_a);
5712 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5713 rmwWithReg ("clr", hc08_reg_a);
5714 rmwWithReg ("ror", hc08_reg_a);
5717 for (i=0; i<shCount; i++)
5719 rmwWithReg ("lsl", hc08_reg_a);
5720 rmwWithReg ("rol", hc08_reg_x);
5723 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5725 pullOrFreeReg (hc08_reg_x, needpulx);
5726 pullOrFreeReg (hc08_reg_a, needpula);
5732 /*-----------------------------------------------------------------*/
5733 /* shiftR2Left2Result - shift right two bytes from left to result */
5734 /*-----------------------------------------------------------------*/
5736 shiftR2Left2Result (operand * left, int offl,
5737 operand * result, int offr,
5738 int shCount, int sign)
5741 bool needpula = FALSE;
5742 bool needpulx = FALSE;
5744 needpula = pushRegIfUsed (hc08_reg_a);
5745 needpulx = pushRegIfUsed (hc08_reg_x);
5747 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5748 for (i=0; i<shCount; i++)
5751 rmwWithReg ("asr", hc08_reg_x);
5753 rmwWithReg ("lsr", hc08_reg_x);
5754 rmwWithReg ("ror", hc08_reg_a);
5756 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5758 pullOrFreeReg (hc08_reg_x, needpulx);
5759 pullOrFreeReg (hc08_reg_a, needpula);
5764 /*-----------------------------------------------------------------*/
5765 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5766 /*-----------------------------------------------------------------*/
5768 shiftLLeftOrResult (operand * left, int offl,
5769 operand * result, int offr, int shCount)
5771 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5772 /* shift left accumulator */
5774 /* or with result */
5775 accopWithAop ("ora", AOP (result), offr);
5776 /* back to result */
5777 storeRegToAop (hc08_reg_a, AOP (result), offr);
5778 hc08_freeReg (hc08_reg_a);
5782 /*-----------------------------------------------------------------*/
5783 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5784 /*-----------------------------------------------------------------*/
5786 shiftRLeftOrResult (operand * left, int offl,
5787 operand * result, int offr, int shCount)
5789 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5790 /* shift left accumulator */
5791 AccRsh (shCount, FALSE);
5792 /* or with result */
5793 accopWithAop ("ora", AOP (result), offr);
5794 /* back to result */
5795 storeRegToAop (hc08_reg_a, AOP (result), offr);
5796 hc08_freeReg (hc08_reg_a);
5799 /*-----------------------------------------------------------------*/
5800 /* genlshOne - left shift a one byte quantity by known count */
5801 /*-----------------------------------------------------------------*/
5803 genlshOne (operand * result, operand * left, int shCount)
5805 D(emitcode ("; genlshOne",""));
5807 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5810 /*-----------------------------------------------------------------*/
5811 /* genlshTwo - left shift two bytes by known amount != 0 */
5812 /*-----------------------------------------------------------------*/
5814 genlshTwo (operand * result, operand * left, int shCount)
5818 D(emitcode ("; genlshTwo",""));
5821 size = getDataSize (result);
5823 /* if shCount >= 8 */
5830 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5832 storeRegToAop (hc08_reg_a, AOP (result), 1);
5834 storeConstToAop(zero, AOP (result), LSB);
5837 /* 1 <= shCount <= 7 */
5840 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5842 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5846 /*-----------------------------------------------------------------*/
5847 /* shiftLLong - shift left one long from left to result */
5848 /* offl = LSB or MSB16 */
5849 /*-----------------------------------------------------------------*/
5851 shiftLLong (operand * left, operand * result, int offr)
5854 // int size = AOP_SIZE (result);
5856 bool needpula = FALSE;
5857 bool needpulx = FALSE;
5859 needpula = pushRegIfUsed (hc08_reg_a);
5860 needpulx = pushRegIfUsed (hc08_reg_x);
5862 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5863 rmwWithReg ("lsl", hc08_reg_a);
5864 rmwWithReg ("rol", hc08_reg_x);
5865 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5869 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5870 rmwWithReg ("rol", hc08_reg_a);
5871 rmwWithReg ("rol", hc08_reg_x);
5872 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5874 else if (offr==MSB16)
5876 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5877 rmwWithReg ("rol", hc08_reg_a);
5878 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5881 pullOrFreeReg (hc08_reg_x, needpulx);
5882 pullOrFreeReg (hc08_reg_a, needpula);
5885 /*-----------------------------------------------------------------*/
5886 /* genlshFour - shift four byte by a known amount != 0 */
5887 /*-----------------------------------------------------------------*/
5889 genlshFour (operand * result, operand * left, int shCount)
5893 D(emitcode ("; genlshFour",""));
5895 size = AOP_SIZE (result);
5897 /* TODO: deal with the &result == &left case */
5899 /* if shifting more that 3 bytes */
5904 /* lowest order of left goes to the highest
5905 order of the destination */
5906 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5908 movLeft2Result (left, LSB, result, MSB32, 0);
5909 storeConstToAop (zero, AOP (result), LSB);
5910 storeConstToAop (zero, AOP (result), MSB16);
5911 storeConstToAop (zero, AOP (result), MSB24);
5915 /* more than two bytes */
5916 else if (shCount >= 16)
5918 /* lower order two bytes goes to higher order two bytes */
5920 /* if some more remaining */
5922 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5925 movLeft2Result (left, MSB16, result, MSB32, 0);
5926 movLeft2Result (left, LSB, result, MSB24, 0);
5928 storeConstToAop (zero, AOP (result), LSB);
5929 storeConstToAop (zero, AOP (result), MSB16);
5933 /* if more than 1 byte */
5934 else if (shCount >= 8)
5936 /* lower order three bytes goes to higher order three bytes */
5941 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5943 movLeft2Result (left, LSB, result, MSB16, 0);
5949 movLeft2Result (left, MSB24, result, MSB32, 0);
5950 movLeft2Result (left, MSB16, result, MSB24, 0);
5951 movLeft2Result (left, LSB, result, MSB16, 0);
5952 storeConstToAop (zero, AOP (result), LSB);
5954 else if (shCount == 1)
5955 shiftLLong (left, result, MSB16);
5958 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5959 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5960 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5961 storeConstToAop (zero, AOP (result), LSB);
5966 /* 1 <= shCount <= 7 */
5967 else if (shCount <= 2)
5969 shiftLLong (left, result, LSB);
5971 shiftLLong (result, result, LSB);
5973 /* 3 <= shCount <= 7, optimize */
5976 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5977 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5978 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5982 /*-----------------------------------------------------------------*/
5983 /* genLeftShiftLiteral - left shifting by known count */
5984 /*-----------------------------------------------------------------*/
5986 genLeftShiftLiteral (operand * left,
5991 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5994 D(emitcode ("; genLeftShiftLiteral",""));
5996 freeAsmop (right, NULL, ic, TRUE);
5998 aopOp (left, ic, FALSE);
5999 aopOp (result, ic, FALSE);
6001 // size = getSize (operandType (result));
6002 size = AOP_SIZE (result);
6005 D(emitcode ("; shift left ", "result %d, left %d", size,
6012 transferAopAop( AOP(left), size, AOP(result), size);
6014 else if (shCount >= (size * 8))
6017 storeConstToAop (zero, AOP (result), size);
6024 genlshOne (result, left, shCount);
6028 genlshTwo (result, left, shCount);
6032 genlshFour (result, left, shCount);
6035 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6036 "*** ack! mystery literal shift!\n");
6040 freeAsmop (left, NULL, ic, TRUE);
6041 freeAsmop (result, NULL, ic, TRUE);
6044 /*-----------------------------------------------------------------*/
6045 /* genLeftShift - generates code for left shifting */
6046 /*-----------------------------------------------------------------*/
6048 genLeftShift (iCode * ic)
6050 operand *left, *right, *result;
6052 symbol *tlbl, *tlbl1;
6057 D(emitcode ("; genLeftShift",""));
6059 right = IC_RIGHT (ic);
6060 left = IC_LEFT (ic);
6061 result = IC_RESULT (ic);
6063 aopOp (right, ic, FALSE);
6065 /* if the shift count is known then do it
6066 as efficiently as possible */
6067 if (AOP_TYPE (right) == AOP_LIT)
6069 genLeftShiftLiteral (left, right, result, ic);
6073 /* shift count is unknown then we have to form
6074 a loop get the loop count in A : Note: we take
6075 only the lower order byte since shifting
6076 more that 32 bits make no sense anyway, ( the
6077 largest size of an object can be only 32 bits ) */
6079 aopOp (left, ic, FALSE);
6080 aopOp (result, ic, FALSE);
6082 /* now move the left to the result if they are not the
6084 if (!sameRegs (AOP (left), AOP (result)))
6087 size = AOP_SIZE (result);
6091 transferAopAop (AOP (left), offset, AOP (result), offset);
6095 freeAsmop (left, NULL, ic, TRUE);
6097 tlbl = newiTempLabel (NULL);
6098 size = AOP_SIZE (result);
6100 tlbl1 = newiTempLabel (NULL);
6104 loadRegFromAop (reg, AOP (right), 0);
6105 freeAsmop (right, NULL, ic, TRUE);
6106 emitBranch ("beq", tlbl1);
6110 for (offset=0;offset<size;offset++)
6112 rmwWithAop (shift, AOP (result), offset);
6115 rmwWithReg ("dec", reg);
6116 emitBranch ("bne", tlbl);
6120 freeAsmop (result, NULL, ic, TRUE);
6123 /*-----------------------------------------------------------------*/
6124 /* genrshOne - right shift a one byte quantity by known count */
6125 /*-----------------------------------------------------------------*/
6127 genrshOne (operand * result, operand * left,
6128 int shCount, int sign)
6130 D(emitcode ("; genrshOne",""));
6132 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6133 AccRsh (shCount, sign);
6134 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6137 /*-----------------------------------------------------------------*/
6138 /* genrshTwo - right shift two bytes by known amount != 0 */
6139 /*-----------------------------------------------------------------*/
6141 genrshTwo (operand * result, operand * left,
6142 int shCount, int sign)
6144 D(emitcode ("; genrshTwo",""));
6146 /* if shCount >= 8 */
6149 if (shCount || sign)
6151 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6152 AccRsh (shCount-8, sign);
6153 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6157 transferAopAop (AOP (left), 1, AOP (result), 0);
6158 storeConstToAop (zero, AOP (result), 1);
6162 /* 1 <= shCount <= 7 */
6165 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6166 XAccRsh (shCount, sign);
6167 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6171 /*-----------------------------------------------------------------*/
6172 /* shiftRLong - shift right one long from left to result */
6173 /* offl = LSB or MSB16 */
6174 /*-----------------------------------------------------------------*/
6176 shiftRLong (operand * left, int offl,
6177 operand * result, int sign)
6180 // int size = AOP_SIZE (result);
6182 bool needpula = FALSE;
6183 bool needpulx = FALSE;
6185 needpula = pushRegIfUsed (hc08_reg_a);
6186 needpulx = pushRegIfUsed (hc08_reg_x);
6190 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6192 rmwWithReg ("asr", hc08_reg_x);
6194 rmwWithReg ("lsr", hc08_reg_x);
6195 rmwWithReg ("rol", hc08_reg_a);
6196 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6198 else if (offl==MSB16)
6200 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6202 rmwWithReg ("asr", hc08_reg_a);
6204 rmwWithReg ("lsr", hc08_reg_a);
6205 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6208 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6209 rmwWithReg ("ror", hc08_reg_x);
6210 rmwWithReg ("ror", hc08_reg_a);
6211 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6214 pullOrFreeReg (hc08_reg_x, needpulx);
6215 pullOrFreeReg (hc08_reg_a, needpula);
6218 /*-----------------------------------------------------------------*/
6219 /* genrshFour - shift four byte by a known amount != 0 */
6220 /*-----------------------------------------------------------------*/
6222 genrshFour (operand * result, operand * left,
6223 int shCount, int sign)
6225 /* TODO: handle cases where left == result */
6227 D(emitcode ("; genrshFour",""));
6229 /* if shifting more that 3 bytes */
6232 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6233 AccRsh (shCount-24, sign);
6234 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6237 else if (shCount >= 16)
6239 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6240 XAccRsh (shCount-16, sign);
6241 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6244 else if (shCount >= 8)
6247 shiftRLong (left, MSB16, result, sign);
6248 else if (shCount == 8)
6250 transferAopAop (AOP (left), 1, AOP (result), 0);
6251 transferAopAop (AOP (left), 2, AOP (result), 1);
6252 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6253 storeRegToAop (hc08_reg_a, AOP (result), 2);
6254 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6256 else if (shCount == 9)
6258 shiftRLong (left, MSB16, result, sign);
6262 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6263 XAccRsh (shCount-8, FALSE);
6264 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6265 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6266 loadRegFromConst (hc08_reg_a, zero);
6267 XAccRsh (shCount-8, sign);
6268 accopWithAop ("ora", AOP (result), 1);
6269 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6273 { /* 1 <= shCount <= 7 */
6276 shiftRLong (left, LSB, result, sign);
6280 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6281 XAccRsh (shCount, FALSE);
6282 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6283 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6285 accopWithAop ("ora", AOP (result), 1);
6286 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6287 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6288 XAccRsh (shCount, sign);
6289 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6294 /*-----------------------------------------------------------------*/
6295 /* genRightShiftLiteral - right shifting by known count */
6296 /*-----------------------------------------------------------------*/
6298 genRightShiftLiteral (operand * left,
6304 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6307 D(emitcode ("; genRightShiftLiteral",""));
6309 freeAsmop (right, NULL, ic, TRUE);
6311 aopOp (left, ic, FALSE);
6312 aopOp (result, ic, FALSE);
6315 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6319 size = getDataSize (left);
6320 /* test the LEFT size !!! */
6322 /* I suppose that the left size >= result size */
6325 size = getDataSize (result);
6327 transferAopAop (AOP (left), size, AOP(result), size);
6329 else if (shCount >= (size * 8))
6332 /* get sign in acc.7 */
6333 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6335 addSign (result, LSB, sign);
6342 genrshOne (result, left, shCount, sign);
6346 genrshTwo (result, left, shCount, sign);
6350 genrshFour (result, left, shCount, sign);
6356 freeAsmop (left, NULL, ic, TRUE);
6357 freeAsmop (result, NULL, ic, TRUE);
6361 /*-----------------------------------------------------------------*/
6362 /* genRightShift - generate code for right shifting */
6363 /*-----------------------------------------------------------------*/
6365 genRightShift (iCode * ic)
6367 operand *right, *left, *result;
6371 symbol *tlbl, *tlbl1;
6375 D(emitcode ("; genRightShift",""));
6377 /* if signed then we do it the hard way preserve the
6378 sign bit moving it inwards */
6379 retype = getSpec (operandType (IC_RESULT (ic)));
6380 sign = !SPEC_USIGN (retype);
6382 /* signed & unsigned types are treated the same : i.e. the
6383 signed is NOT propagated inwards : quoting from the
6384 ANSI - standard : "for E1 >> E2, is equivalent to division
6385 by 2**E2 if unsigned or if it has a non-negative value,
6386 otherwise the result is implementation defined ", MY definition
6387 is that the sign does not get propagated */
6389 right = IC_RIGHT (ic);
6390 left = IC_LEFT (ic);
6391 result = IC_RESULT (ic);
6393 aopOp (right, ic, FALSE);
6395 /* if the shift count is known then do it
6396 as efficiently as possible */
6397 if (AOP_TYPE (right) == AOP_LIT)
6399 genRightShiftLiteral (left, right, result, ic, sign);
6403 /* shift count is unknown then we have to form
6404 a loop get the loop count in X : Note: we take
6405 only the lower order byte since shifting
6406 more that 32 bits make no sense anyway, ( the
6407 largest size of an object can be only 32 bits ) */
6409 aopOp (left, ic, FALSE);
6410 aopOp (result, ic, FALSE);
6412 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6413 AOP (result) = forceStackedAop (AOP (result));
6415 size = AOP_SIZE (result);
6419 transferAopAop (AOP (left), offset, AOP (result), offset);
6423 tlbl = newiTempLabel (NULL);
6424 size = AOP_SIZE (result);
6426 tlbl1 = newiTempLabel (NULL);
6428 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6429 emitcode ("tstx", "");
6430 emitcode ("beq", "%05d$", tlbl1->key + 100);
6431 emitcode ("", "%05d$:", tlbl->key + 100);
6432 shift= sign ? "asr" : "lsr";
6433 for (offset=size-1;offset>=0;offset--)
6435 rmwWithAop (shift, AOP (result), offset);
6438 rmwWithReg ("dec", hc08_reg_x);
6439 emitcode ("bne","%05d$", tlbl->key + 100);
6440 emitcode ("", "%05d$:", tlbl1->key + 100);
6442 freeAsmop (result, NULL, ic, TRUE);
6443 freeAsmop (left, NULL, ic, TRUE);
6444 freeAsmop (right, NULL, ic, TRUE);
6448 /*-----------------------------------------------------------------*/
6449 /* genUnpackBits - generates code for unpacking bits */
6450 /*-----------------------------------------------------------------*/
6452 genUnpackBits (operand * result, iCode *ifx)
6454 int offset = 0; /* result byte offset */
6455 int rsize; /* result size */
6456 int rlen = 0; /* remaining bitfield length */
6457 sym_link *etype; /* bitfield type information */
6458 int blen; /* bitfield length */
6459 int bstr; /* bitfield starting bit within byte */
6461 D(emitcode ("; genUnpackBits",""));
6463 etype = getSpec (operandType (result));
6464 rsize = getSize (operandType (result));
6465 blen = SPEC_BLEN (etype);
6466 bstr = SPEC_BSTR (etype);
6468 /* If the bitfield length is less than a byte */
6471 emitcode ("lda", ",x");
6472 hc08_dirtyReg (hc08_reg_a, FALSE);
6475 AccRsh (bstr, FALSE);
6476 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6477 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6481 emitcode ("and", "#0x%02x",
6482 (((unsigned char) -1) >> (8 - blen)) << bstr);
6487 /* Bit field did not fit in a byte. Copy all
6488 but the partial byte at the end. */
6489 for (rlen=blen;rlen>=8;rlen-=8)
6491 emitcode ("lda", ",x");
6492 hc08_dirtyReg (hc08_reg_a, FALSE);
6494 storeRegToAop (hc08_reg_a, AOP (result), offset);
6497 emitcode ("aix", "#1");
6500 /* Handle the partial byte at the end */
6503 emitcode ("lda", ",x");
6504 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6505 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6513 storeConstToAop (zero, AOP (result), offset++);
6516 if (ifx && !ifx->generated)
6518 genIfxJump (ifx, "a");
6523 /*-----------------------------------------------------------------*/
6524 /* genUnpackBitsImmed - generates code for unpacking bits */
6525 /*-----------------------------------------------------------------*/
6527 genUnpackBitsImmed (operand * left,
6533 int offset = 0; /* result byte offset */
6534 int rsize; /* result size */
6535 int rlen = 0; /* remaining bitfield length */
6536 sym_link *etype; /* bitfield type information */
6537 int blen; /* bitfield length */
6538 int bstr; /* bitfield starting bit within byte */
6541 D(emitcode ("; genUnpackBitsImmed",""));
6543 aopOp (result, ic, TRUE);
6544 size = AOP_SIZE (result);
6546 derefaop = aopDerefAop (AOP (left));
6547 freeAsmop (left, NULL, ic, TRUE);
6548 derefaop->size = size;
6550 etype = getSpec (operandType (result));
6551 rsize = getSize (operandType (result));
6552 blen = SPEC_BLEN (etype);
6553 bstr = SPEC_BSTR (etype);
6555 /* if the bitfield is a single bit in the direct page */
6556 if (blen == 1 && derefaop->type == AOP_DIR)
6560 symbol *tlbl = newiTempLabel (NULL);
6562 loadRegFromConst (hc08_reg_a, zero);
6563 emitcode ("brclr", "#%d,%s,%05d$",
6564 bstr, aopAdrStr (derefaop, 0, FALSE),
6566 rmwWithReg ("inc", hc08_reg_a);
6568 storeRegToAop (hc08_reg_a, AOP (result), offset);
6569 hc08_freeReg (hc08_reg_a);
6575 symbol *tlbl = newiTempLabel (NULL);
6581 jlbl = IC_TRUE (ifx);
6586 jlbl = IC_FALSE (ifx);
6589 emitcode (inst, "#%d,%s,%05d$",
6590 bstr, aopAdrStr (derefaop, 0, FALSE),
6592 emitBranch ("jmp", jlbl);
6600 /* If the bitfield length is less than a byte */
6603 loadRegFromAop (hc08_reg_a, derefaop, 0);
6606 AccRsh (bstr, FALSE);
6607 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6608 hc08_dirtyReg (hc08_reg_a, FALSE);
6609 storeRegToAop (hc08_reg_a, AOP (result), offset);
6613 emitcode ("and", "#0x%02x",
6614 (((unsigned char) -1) >> (8 - blen)) << bstr);
6615 hc08_dirtyReg (hc08_reg_a, FALSE);
6621 /* Bit field did not fit in a byte. Copy all
6622 but the partial byte at the end. */
6623 for (rlen=blen;rlen>=8;rlen-=8)
6625 loadRegFromAop (hc08_reg_a, derefaop, size-offset);
6627 storeRegToAop (hc08_reg_a, AOP (result), offset);
6629 emitcode ("tsta", "");
6633 /* Handle the partial byte at the end */
6636 loadRegFromAop (hc08_reg_a, derefaop, size-offset);
6637 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6638 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6646 storeConstToAop (zero, AOP (result), offset++);
6649 freeAsmop (NULL, derefaop, ic, TRUE);
6650 freeAsmop (result, NULL, ic, TRUE);
6652 if (ifx && !ifx->generated)
6654 genIfxJump (ifx, "a");
6659 /*-----------------------------------------------------------------*/
6660 /* genDataPointerGet - generates code when ptr offset is known */
6661 /*-----------------------------------------------------------------*/
6663 genDataPointerGet (operand * left,
6668 int size, offset = 0;
6671 D(emitcode ("; genDataPointerGet",""));
6673 aopOp (result, ic, TRUE);
6674 size = AOP_SIZE (result);
6676 derefaop = aopDerefAop (AOP (left));
6677 freeAsmop (left, NULL, ic, TRUE);
6678 derefaop->size = size;
6683 transferAopAop (derefaop, offset, AOP (result), offset);
6685 loadRegFromAop (hc08_reg_a, derefaop, offset);
6689 freeAsmop (NULL, derefaop, ic, TRUE);
6690 freeAsmop (result, NULL, ic, TRUE);
6692 if (ifx && !ifx->generated)
6694 genIfxJump (ifx, "a");
6699 /*-----------------------------------------------------------------*/
6700 /* genPointerGet - generate code for pointer get */
6701 /*-----------------------------------------------------------------*/
6703 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
6705 operand *left = IC_LEFT (ic);
6706 operand *result = IC_RESULT (ic);
6708 sym_link *retype = getSpec (operandType (result));
6710 D(emitcode ("; genPointerGet",""));
6712 if (getSize (operandType (result))>1)
6715 aopOp (left, ic, FALSE);
6717 /* if left is rematerialisable and
6718 result is not bit variable type */
6719 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
6721 if (!IS_BITVAR (retype))
6723 genDataPointerGet (left, result, ic, ifx);
6728 genUnpackBitsImmed (left, result, ic, ifx);
6733 /* if the operand is already in hx
6734 then we do nothing else we move the value to hx */
6735 if (AOP_TYPE (left) != AOP_STR)
6737 /* if this is remateriazable */
6738 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6741 /* so hx now contains the address */
6742 aopOp (result, ic, FALSE);
6744 /* if bit then unpack */
6745 if (IS_BITVAR (retype))
6746 genUnpackBits (result, ifx);
6749 size = AOP_SIZE (result);
6754 accopWithMisc ("lda", ",x");
6757 emitcode ("aix", "#1");
6758 hc08_dirtyReg (hc08_reg_hx, FALSE);
6761 storeRegToAop (hc08_reg_a, AOP (result), offset);
6763 hc08_freeReg (hc08_reg_a);
6767 freeAsmop (left, NULL, ic, TRUE);
6768 freeAsmop (result, NULL, ic, TRUE);
6771 aopOp (IC_RESULT (pi), pi, FALSE);
6772 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6773 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6777 if (ifx && !ifx->generated)
6779 genIfxJump (ifx, "a");
6782 hc08_freeReg (hc08_reg_hx);
6786 /*-----------------------------------------------------------------*/
6787 /* genPackBits - generates code for packed bit storage */
6788 /*-----------------------------------------------------------------*/
6790 genPackBits (sym_link * etype,
6793 int offset = 0; /* source byte offset */
6794 int rlen = 0; /* remaining bitfield length */
6795 int blen; /* bitfield length */
6796 int bstr; /* bitfield starting bit within byte */
6797 int litval; /* source literal value (if AOP_LIT) */
6798 unsigned char mask; /* bitmask within current byte */
6801 D(emitcode ("; genPackBits",""));
6803 blen = SPEC_BLEN (etype);
6804 bstr = SPEC_BSTR (etype);
6806 /* If the bitfield length is less than a byte */
6809 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6810 (unsigned char) (0xFF >> (8 - bstr)));
6812 if (AOP_TYPE (right) == AOP_LIT)
6814 /* Case with a bitfield length <8 and literal source
6816 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6818 litval &= (~mask) & 0xff;
6820 emitcode ("lda", ",x");
6821 if ((mask|litval)!=0xff)
6822 emitcode ("and","#0x%02x", mask);
6824 emitcode ("ora","#0x%02x", litval);
6825 hc08_dirtyReg (hc08_reg_a, FALSE);
6826 emitcode ("sta", ",x");
6828 hc08_freeReg (hc08_reg_a);
6832 /* Case with a bitfield length < 8 and arbitrary source
6834 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6835 /* shift and mask source value */
6837 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6838 hc08_dirtyReg (hc08_reg_a, FALSE);
6839 pushReg (hc08_reg_a, TRUE);
6841 emitcode ("lda", ",x");
6842 emitcode ("and", "#0x%02x", mask);
6843 emitcode ("ora", "1,s");
6844 emitcode ("sta", ",x");
6845 pullReg (hc08_reg_a);
6847 hc08_freeReg (hc08_reg_a);
6851 /* Bit length is greater than 7 bits. In this case, copy */
6852 /* all except the partial byte at the end */
6853 for (rlen=blen;rlen>=8;rlen-=8)
6855 if (AOP (right)->type == AOP_DIR)
6857 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6862 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6863 emitcode ("sta", "%d,x", offset);
6868 /* If there was a partial byte at the end */
6871 mask = (((unsigned char) -1 << rlen) & 0xff);
6873 if (AOP_TYPE (right) == AOP_LIT)
6875 /* Case with partial byte and literal source
6877 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6878 litval >>= (blen-rlen);
6879 litval &= (~mask) & 0xff;
6880 emitcode ("lda", "%d,x", offset - xoffset);
6881 hc08_dirtyReg (hc08_reg_a, FALSE);
6882 if ((mask|litval)!=0xff)
6883 emitcode ("and","#0x%02x", mask);
6885 emitcode ("ora","#0x%02x", litval);
6886 emitcode ("sta", "%d,x", offset - xoffset);
6887 hc08_dirtyReg (hc08_reg_a, FALSE);
6888 hc08_freeReg (hc08_reg_a);
6892 /* Case with partial byte and arbitrary source
6894 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6895 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6896 hc08_dirtyReg (hc08_reg_a, FALSE);
6897 pushReg (hc08_reg_a, TRUE);
6899 emitcode ("lda", "%d,x", offset - xoffset);
6900 emitcode ("and", "#0x%02x", mask);
6901 emitcode ("ora", "1,s");
6902 emitcode ("sta", "%d,x", offset - xoffset);
6903 pullReg (hc08_reg_a);
6906 hc08_freeReg (hc08_reg_a);
6909 /*-----------------------------------------------------------------*/
6910 /* genPackBits - generates code for packed bit storage */
6911 /*-----------------------------------------------------------------*/
6913 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
6917 int offset = 0; /* source byte offset */
6918 int rlen = 0; /* remaining bitfield length */
6919 int blen; /* bitfield length */
6920 int bstr; /* bitfield starting bit within byte */
6921 int litval; /* source literal value (if AOP_LIT) */
6922 unsigned char mask; /* bitmask within current byte */
6924 D(emitcode ("; genPackBitsImmed",""));
6926 blen = SPEC_BLEN (etype);
6927 bstr = SPEC_BSTR (etype);
6929 aopOp (right, ic, FALSE);
6930 size = AOP_SIZE (right);
6932 derefaop = aopDerefAop (AOP (result));
6933 freeAsmop (result, NULL, ic, TRUE);
6934 derefaop->size = size;
6936 /* if the bitfield is a single bit in the direct page */
6937 if (blen == 1 && derefaop->type == AOP_DIR)
6939 if (AOP_TYPE (right) == AOP_LIT)
6941 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6943 emitcode ((litval & 1) ? "bset" : "bclr",
6944 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
6948 symbol *tlbl1 = newiTempLabel (NULL);
6949 symbol *tlbl2 = newiTempLabel (NULL);
6951 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6952 emitcode ("bit", "#1");
6953 emitBranch ("bne", tlbl1);
6954 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
6955 emitBranch ("bra", tlbl2);
6957 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
6959 hc08_freeReg (hc08_reg_a);
6964 /* If the bitfield length is less than a byte */
6967 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6968 (unsigned char) (0xFF >> (8 - bstr)));
6970 if (AOP_TYPE (right) == AOP_LIT)
6972 /* Case with a bitfield length <8 and literal source
6974 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6976 litval &= (~mask) & 0xff;
6978 loadRegFromAop (hc08_reg_a, derefaop, 0);
6979 if ((mask|litval)!=0xff)
6980 emitcode ("and","#0x%02x", mask);
6982 emitcode ("ora","#0x%02x", litval);
6983 hc08_dirtyReg (hc08_reg_a, FALSE);
6984 storeRegToAop (hc08_reg_a, derefaop, 0);
6986 hc08_freeReg (hc08_reg_a);
6990 /* Case with a bitfield length < 8 and arbitrary source
6992 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6993 /* shift and mask source value */
6995 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6996 hc08_dirtyReg (hc08_reg_a, FALSE);
6997 pushReg (hc08_reg_a, TRUE);
6999 loadRegFromAop (hc08_reg_a, derefaop, 0);
7000 emitcode ("and", "#0x%02x", mask);
7001 emitcode ("ora", "1,s");
7002 storeRegToAop (hc08_reg_a, derefaop, 0);
7003 pullReg (hc08_reg_a);
7005 hc08_freeReg (hc08_reg_a);
7009 /* Bit length is greater than 7 bits. In this case, copy */
7010 /* all except the partial byte at the end */
7011 for (rlen=blen;rlen>=8;rlen-=8)
7013 transferAopAop (AOP (right), offset, derefaop, size-offset);
7017 /* If there was a partial byte at the end */
7020 mask = (((unsigned char) -1 << rlen) & 0xff);
7022 if (AOP_TYPE (right) == AOP_LIT)
7024 /* Case with partial byte and literal source
7026 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7027 litval >>= (blen-rlen);
7028 litval &= (~mask) & 0xff;
7029 loadRegFromAop (hc08_reg_a, derefaop, size-offset);
7030 if ((mask|litval)!=0xff)
7031 emitcode ("and","#0x%02x", mask);
7033 emitcode ("ora","#0x%02x", litval);
7034 hc08_dirtyReg (hc08_reg_a, FALSE);
7035 storeRegToAop (hc08_reg_a, derefaop, size-offset);
7036 hc08_dirtyReg (hc08_reg_a, FALSE);
7037 hc08_freeReg (hc08_reg_a);
7041 /* Case with partial byte and arbitrary source
7043 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7044 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7045 hc08_dirtyReg (hc08_reg_a, FALSE);
7046 pushReg (hc08_reg_a, TRUE);
7048 loadRegFromAop (hc08_reg_a, derefaop, size-offset);
7049 emitcode ("and", "#0x%02x", mask);
7050 emitcode ("ora", "1,s");
7051 storeRegToAop (hc08_reg_a, derefaop, size-offset);
7052 pullReg (hc08_reg_a);
7055 hc08_freeReg (hc08_reg_a);
7058 freeAsmop (right, NULL, ic, TRUE);
7059 freeAsmop (NULL, derefaop, ic, TRUE);
7062 /*-----------------------------------------------------------------*/
7063 /* genDataPointerSet - remat pointer to data space */
7064 /*-----------------------------------------------------------------*/
7066 genDataPointerSet (operand * right,
7070 int size, offset = 0;
7073 D(emitcode ("; genDataPointerSet",""));
7075 aopOp (right, ic, FALSE);
7076 size = AOP_SIZE (right);
7078 derefaop = aopDerefAop (AOP (result));
7079 freeAsmop (result, NULL, ic, TRUE);
7080 derefaop->size = size;
7084 transferAopAop (AOP (right), offset, derefaop, offset);
7088 freeAsmop (right, NULL, ic, TRUE);
7089 freeAsmop (NULL, derefaop, ic, TRUE);
7093 /*-----------------------------------------------------------------*/
7094 /* genPointerSet - stores the value into a pointer location */
7095 /*-----------------------------------------------------------------*/
7097 genPointerSet (iCode * ic, iCode *pi)
7099 operand *right = IC_RIGHT (ic);
7100 operand *result = IC_RESULT (ic);
7101 sym_link *type, *etype;
7103 sym_link *retype = getSpec (operandType (right));
7104 sym_link *letype = getSpec (operandType (result));
7106 D(emitcode ("; genPointerSet",""));
7108 type = operandType (result);
7109 etype = getSpec (type);
7111 aopOp (result, ic, FALSE);
7113 /* if the result is rematerializable */
7114 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7116 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7118 genDataPointerSet (right, result, ic);
7123 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7128 /* if the operand is already in hx
7129 then we do nothing else we move the value to hx */
7130 if (AOP_TYPE (result) != AOP_STR)
7132 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7134 /* so hx now contains the address */
7135 aopOp (right, ic, FALSE);
7137 /* if bit then unpack */
7138 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7139 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7142 size = AOP_SIZE (right);
7147 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7148 accopWithMisc ("sta", ",x");
7151 emitcode ("aix", "#1");
7153 hc08_freeReg (hc08_reg_a);
7157 freeAsmop (result, NULL, ic, TRUE);
7158 freeAsmop (right, NULL, ic, TRUE);
7161 aopOp (IC_RESULT (pi), pi, FALSE);
7162 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7163 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7167 hc08_freeReg (hc08_reg_hx);
7171 /*-----------------------------------------------------------------*/
7172 /* genIfx - generate code for Ifx statement */
7173 /*-----------------------------------------------------------------*/
7175 genIfx (iCode * ic, iCode * popIc)
7177 operand *cond = IC_COND (ic);
7180 D(emitcode ("; genIfx",""));
7182 aopOp (cond, ic, FALSE);
7184 /* get the value into acc */
7185 if (AOP_TYPE (cond) != AOP_CRY)
7186 asmopToBool (AOP (cond), FALSE);
7189 /* the result is now in the accumulator */
7190 freeAsmop (cond, NULL, ic, TRUE);
7192 /* if there was something to be popped then do it */
7196 /* if the condition is a bit variable */
7197 if (isbit && IS_ITEMP (cond) &&
7199 genIfxJump (ic, SPIL_LOC (cond)->rname);
7200 else if (isbit && !IS_ITEMP (cond))
7201 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7203 genIfxJump (ic, "a");
7208 /*-----------------------------------------------------------------*/
7209 /* genAddrOf - generates code for address of */
7210 /*-----------------------------------------------------------------*/
7212 genAddrOf (iCode * ic)
7214 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7217 D(emitcode ("; genAddrOf",""));
7219 aopOp (IC_RESULT (ic), ic, FALSE);
7221 /* if the operand is on the stack then we
7222 need to get the stack offset of this
7226 /* if it has an offset then we need to compute
7228 hc08_useReg (hc08_reg_hx);
7229 emitcode ("tsx", "");
7230 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7231 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7232 hc08_freeReg (hc08_reg_hx);
7237 /* object not on stack then we need the name */
7238 size = AOP_SIZE (IC_RESULT (ic));
7243 char s[SDCC_NAME_MAX+10];
7246 sprintf (s, "#%s", sym->rname);
7249 sprintf (s, "#>%s", sym->rname);
7252 sprintf (s, "#(%s >> %d)",
7256 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7260 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7264 /*-----------------------------------------------------------------*/
7265 /* genAssign - generate code for assignment */
7266 /*-----------------------------------------------------------------*/
7268 genAssign (iCode * ic)
7270 operand *result, *right;
7272 // unsigned long lit = 0L;
7274 D(emitcode("; genAssign",""));
7276 result = IC_RESULT (ic);
7277 right = IC_RIGHT (ic);
7279 /* if they are the same */
7280 if (operandsEqu (result, right)) {
7284 aopOp (right, ic, FALSE);
7285 aopOp (result, ic, TRUE);
7287 /* if they are the same registers */
7288 if (sameRegs (AOP (right), AOP (result)))
7291 if ((AOP_TYPE (right) == AOP_LIT)
7292 && (IS_AOP_HX(AOP(result))))
7294 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7299 size = AOP_SIZE (result);
7304 transferAopAop (AOP (right), offset, AOP (result), offset);
7309 freeAsmop (right, NULL, ic, TRUE);
7310 freeAsmop (result, NULL, ic, TRUE);
7313 /*-----------------------------------------------------------------*/
7314 /* genJumpTab - genrates code for jump table */
7315 /*-----------------------------------------------------------------*/
7317 genJumpTab (iCode * ic)
7322 D(emitcode ("; genJumpTab",""));
7324 aopOp (IC_JTCOND (ic), ic, FALSE);
7325 /* get the condition into accumulator */
7326 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7327 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7328 /* multiply by three */
7329 pushReg (hc08_reg_a, FALSE);
7330 emitcode ("lsla", "");
7331 emitcode ("add","1,s");
7332 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7333 loadRegFromConst (hc08_reg_h, zero);
7334 pullReg (hc08_reg_a);
7336 jtab = newiTempLabel (NULL);
7337 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7338 emitcode ("", "%05d$:", jtab->key + 100);
7339 /* now generate the jump labels */
7340 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7341 jtab = setNextItem (IC_JTLABELS (ic)))
7342 emitcode ("jmp", "%05d$", jtab->key + 100);
7344 hc08_dirtyReg (hc08_reg_a, TRUE);
7345 hc08_dirtyReg (hc08_reg_hx, TRUE);
7348 /*-----------------------------------------------------------------*/
7349 /* genCast - gen code for casting */
7350 /*-----------------------------------------------------------------*/
7352 genCast (iCode * ic)
7354 operand *result = IC_RESULT (ic);
7355 sym_link *ctype = operandType (IC_LEFT (ic));
7356 sym_link *rtype = operandType (IC_RIGHT (ic));
7357 operand *right = IC_RIGHT (ic);
7360 D(emitcode("; genCast",""));
7362 /* if they are equivalent then do nothing */
7363 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7366 aopOp (right, ic, FALSE);
7367 aopOp (result, ic, FALSE);
7370 /* if they are the same size : or less */
7371 if (AOP_SIZE (result) <= AOP_SIZE (right))
7374 /* if they are in the same place */
7376 if (sameRegs (AOP (right), AOP (result)))
7380 /* if they in different places then copy */
7381 size = AOP_SIZE (result);
7385 transferAopAop(AOP (right), offset, AOP (result), offset);
7392 /* if the result is of type pointer */
7397 sym_link *type = operandType (right);
7398 sym_link *etype = getSpec (type);
7400 /* pointer to generic pointer */
7401 if (IS_GENPTR (ctype))
7404 p_type = DCL_TYPE (type);
7407 if (SPEC_SCLS(etype)==S_REGISTER) {
7408 // let's assume it is a generic pointer
7411 /* we have to go by the storage class */
7412 p_type = PTR_TYPE (SPEC_OCLS (etype));
7416 /* the first two bytes are known */
7417 size = GPTRSIZE - 1;
7421 transferAopAop(AOP (right), offset, AOP (result), offset);
7424 /* the last byte depending on type */
7427 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7432 // pointerTypeToGPByte will have bitched.
7436 sprintf(gpValStr, "#0x%d", gpVal);
7437 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7443 /* just copy the pointers */
7444 size = AOP_SIZE (result);
7448 transferAopAop(AOP (right), offset, AOP (result), offset);
7454 /* so we now know that the size of destination is greater
7455 than the size of the source */
7456 /* we move to result for the size of source */
7457 size = AOP_SIZE (right);
7461 transferAopAop(AOP (right), offset, AOP (result), offset);
7465 /* now depending on the sign of the source && destination */
7466 size = AOP_SIZE (result) - AOP_SIZE (right);
7467 /* if unsigned or not an integral type */
7468 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7471 storeConstToAop (zero, AOP (result), offset++);
7475 /* we need to extend the sign :{ */
7476 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7477 accopWithMisc ("rola", "");
7478 accopWithMisc ("clra", "");
7479 accopWithMisc ("sbc", zero);
7481 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7484 /* we are done hurray !!!! */
7487 freeAsmop (right, NULL, ic, TRUE);
7488 freeAsmop (result, NULL, ic, TRUE);
7492 /*-----------------------------------------------------------------*/
7493 /* genDjnz - generate decrement & jump if not zero instrucion */
7494 /*-----------------------------------------------------------------*/
7496 genDjnz (iCode * ic, iCode * ifx)
7502 D(emitcode ("; genDjnz",""));
7504 /* if the if condition has a false label
7505 then we cannot save */
7509 /* if the minus is not of the form
7511 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7512 !IS_OP_LITERAL (IC_RIGHT (ic)))
7515 if (operandLitValue (IC_RIGHT (ic)) != 1)
7518 /* dbnz doesn't support extended mode */
7519 if (isOperandInFarSpace (IC_RESULT (ic)))
7522 /* if the size of this greater than one then no
7524 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7526 aopOp (IC_RESULT (ic), ic, FALSE);
7527 if (AOP_SIZE (IC_RESULT (ic))>1)
7529 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7533 /* otherwise we can save BIG */
7534 lbl = newiTempLabel (NULL);
7535 lbl1 = newiTempLabel (NULL);
7538 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7541 emitBranch ("bra", lbl1);
7543 emitBranch ("jmp", IC_TRUE (ifx));
7546 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7551 /*-----------------------------------------------------------------*/
7552 /* genReceive - generate code for a receive iCode */
7553 /*-----------------------------------------------------------------*/
7555 genReceive (iCode * ic)
7559 D(emitcode ("; genReceive",""));
7561 aopOp (IC_RESULT (ic), ic, FALSE);
7562 size = AOP_SIZE (IC_RESULT (ic));
7567 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7568 AOP (IC_RESULT (ic)), offset);
7569 if (hc08_aop_pass[offset]->type == AOP_REG)
7570 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7575 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7578 /*-----------------------------------------------------------------*/
7579 /* genDummyRead - generate code for dummy read of volatiles */
7580 /*-----------------------------------------------------------------*/
7582 genDummyRead (iCode * ic)
7587 D(emitcode("; genDummyRead",""));
7590 if (op && IS_SYMOP (op))
7593 aopOp (op, ic, FALSE);
7595 size = AOP_SIZE (op);
7600 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7601 hc08_freeReg (hc08_reg_a);
7605 freeAsmop (op, NULL, ic, TRUE);
7608 if (op && IS_SYMOP (op))
7611 aopOp (op, ic, FALSE);
7613 size = AOP_SIZE (op);
7618 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7619 hc08_freeReg (hc08_reg_a);
7623 freeAsmop (op, NULL, ic, TRUE);
7627 /*-----------------------------------------------------------------*/
7628 /* genCritical - generate code for start of a critical sequence */
7629 /*-----------------------------------------------------------------*/
7631 genCritical (iCode *ic)
7633 D(emitcode("; genCritical",""));
7636 aopOp (IC_RESULT (ic), ic, TRUE);
7638 emitcode ("tpa", "");
7639 hc08_dirtyReg (hc08_reg_a, FALSE);
7640 emitcode ("sei", "");
7643 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7645 pushReg (hc08_reg_a, FALSE);
7647 hc08_freeReg (hc08_reg_a);
7649 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7652 /*-----------------------------------------------------------------*/
7653 /* genEndCritical - generate code for end of a critical sequence */
7654 /*-----------------------------------------------------------------*/
7656 genEndCritical (iCode *ic)
7658 D(emitcode("; genEndCritical",""));
7662 aopOp (IC_RIGHT (ic), ic, FALSE);
7663 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7664 emitcode ("tap", "");
7665 hc08_freeReg (hc08_reg_a);
7666 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7670 pullReg (hc08_reg_a);
7671 emitcode ("tap", "");
7677 /*-----------------------------------------------------------------*/
7678 /* genhc08Code - generate code for HC08 based controllers */
7679 /*-----------------------------------------------------------------*/
7681 genhc08Code (iCode * lic)
7688 lineHead = lineCurr = NULL;
7690 /* print the allocation information */
7691 if (allocInfo && currFunc)
7692 printAllocInfo (currFunc, codeOutFile);
7693 /* if debug information required */
7694 if (options.debug && currFunc)
7696 debugFile->writeFunction (currFunc, lic);
7699 if (IS_STATIC (currFunc->etype))
7700 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7702 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7706 /* stack pointer name */
7707 if (options.useXstack)
7712 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
7714 hc08_aop_pass[0] = newAsmop (AOP_REG);
7715 hc08_aop_pass[0]->size=1;
7716 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7717 hc08_aop_pass[1] = newAsmop (AOP_REG);
7718 hc08_aop_pass[1]->size=1;
7719 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7720 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7721 hc08_aop_pass[2]->size=1;
7722 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7723 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7724 hc08_aop_pass[3]->size=1;
7725 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7727 for (ic = lic; ic; ic = ic->next)
7730 _G.current_iCode = ic;
7732 if (ic->level != clevel || ic->block != cblock)
7736 debugFile->writeScope(ic);
7742 if (ic->lineno && cln != ic->lineno)
7746 debugFile->writeCLine(ic);
7749 emitcode ("", "C$%s$%d$%d$%d ==.",
7750 FileBaseName (ic->filename), ic->lineno,
7751 ic->level, ic->block);
7755 if (!options.noCcodeInAsm) {
7756 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7757 printCLine(ic->filename, ic->lineno));
7761 if (options.iCodeInAsm) {
7765 for (i=0; i<6; i++) {
7766 sprintf (®sInUse[i],
7767 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7770 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7772 /* if the result is marked as
7773 spilt and rematerializable or code for
7774 this has already been generated then
7776 if (resultRemat (ic) || ic->generated)
7784 for (i=A_IDX;i<=XA_IDX;i++)
7786 reg = hc08_regWithIdx(i);
7788 emitcode("","; %s = %s offset %d", reg->name,
7789 aopName(reg->aop), reg->aopofs);
7792 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7794 sym = OP_SYMBOL (IC_LEFT (ic));
7795 if (sym->accuse == ACCUSE_HX)
7797 hc08_reg_h->isFree = FALSE;
7798 hc08_reg_x->isFree = FALSE;
7800 else if (sym->accuse == ACCUSE_XA)
7802 hc08_reg_a->isFree = FALSE;
7804 hc08_reg_x->isFree = FALSE;
7807 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7809 sym = OP_SYMBOL (IC_RIGHT (ic));
7810 if (sym->accuse == ACCUSE_HX)
7812 hc08_reg_h->isFree = FALSE;
7813 hc08_reg_x->isFree = FALSE;
7815 else if (sym->accuse == ACCUSE_XA)
7817 hc08_reg_a->isFree = FALSE;
7819 hc08_reg_x->isFree = FALSE;
7824 /* depending on the operation */
7844 /* IPOP happens only when trying to restore a
7845 spilt live range, if there is an ifx statement
7846 following this pop then the if statement might
7847 be using some of the registers being popped which
7848 would destory the contents of the register so
7849 we need to check for this condition and handle it */
7851 ic->next->op == IFX &&
7852 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7853 genIfx (ic->next, ic);
7871 genEndFunction (ic);
7887 if (!genPointerGetSetOfs (ic))
7892 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7909 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7913 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7920 /* note these two are xlated by algebraic equivalence
7921 during parsing SDCC.y */
7922 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7923 "got '>=' or '<=' shouldn't have come here");
7927 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7939 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7943 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7947 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7974 case GET_VALUE_AT_ADDRESS:
7976 hasInc (IC_LEFT (ic), ic,
7977 getSize (operandType (IC_RESULT (ic)))),
7978 ifxForOp (IC_RESULT (ic), ic) );
7982 if (POINTER_SET (ic))
7983 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8009 addSet (&_G.sendSet, ic);
8012 case DUMMY_READ_VOLATILE:
8021 genEndCritical (ic);
8032 if (!hc08_reg_a->isFree)
8033 D(emitcode("","; forgot to free a"));
8034 if (!hc08_reg_x->isFree)
8035 D(emitcode("","; forgot to free x"));
8036 if (!hc08_reg_h->isFree)
8037 D(emitcode("","; forgot to free h"));
8038 if (!hc08_reg_hx->isFree)
8039 D(emitcode("","; forgot to free hx"));
8040 if (!hc08_reg_xa->isFree)
8041 D(emitcode("","; forgot to free xa"));
8044 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8047 /* now we are ready to call the
8048 peep hole optimizer */
8049 if (!options.nopeep)
8050 peepHole (&lineHead);
8052 /* now do the actual printing */
8053 printLine (lineHead, codeOutFile);