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);
6447 /*-----------------------------------------------------------------*/
6448 /* genUnpackBits - generates code for unpacking bits */
6449 /*-----------------------------------------------------------------*/
6451 genUnpackBits (operand * result)
6453 int offset = 0; /* result byte offset */
6454 int rsize; /* result size */
6455 int rlen = 0; /* remaining bitfield length */
6456 sym_link *etype; /* bitfield type information */
6457 int blen; /* bitfield length */
6458 int bstr; /* bitfield starting bit within byte */
6460 D(emitcode ("; genUnpackBits",""));
6462 etype = getSpec (operandType (result));
6463 rsize = getSize (operandType (result));
6464 blen = SPEC_BLEN (etype);
6465 bstr = SPEC_BSTR (etype);
6467 /* If the bitfield length is less than a byte */
6470 emitcode ("lda", ",x");
6471 hc08_dirtyReg (hc08_reg_a, FALSE);
6472 AccRsh (bstr, FALSE);
6473 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6474 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6478 /* Bit field did not fit in a byte. Copy all
6479 but the partial byte at the end. */
6480 for (rlen=blen;rlen>=8;rlen-=8)
6482 emitcode ("lda", ",x");
6483 hc08_dirtyReg (hc08_reg_a, FALSE);
6484 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6486 emitcode ("aix", "#1");
6489 /* Handle the partial byte at the end */
6492 emitcode ("lda", ",x");
6493 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6494 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6502 storeConstToAop (zero, AOP (result), offset++);
6507 /*-----------------------------------------------------------------*/
6508 /* genDataPointerGet - generates code when ptr offset is known */
6509 /*-----------------------------------------------------------------*/
6511 genDataPointerGet (operand * left,
6515 int size, offset = 0;
6518 D(emitcode ("; genDataPointerGet",""));
6520 aopOp (result, ic, TRUE);
6521 size = AOP_SIZE (result);
6523 derefaop = aopDerefAop (AOP (left));
6524 freeAsmop (left, NULL, ic, TRUE);
6525 derefaop->size = size;
6529 transferAopAop(derefaop, offset, AOP (result), offset);
6533 freeAsmop (NULL, derefaop, ic, TRUE);
6534 freeAsmop (result, NULL, ic, TRUE);
6538 /*-----------------------------------------------------------------*/
6539 /* genNearPointerGet - emitcode for near pointer fetch */
6540 /*-----------------------------------------------------------------*/
6542 genNearPointerGet (operand * left,
6548 sym_link *retype = getSpec (operandType (result));
6550 D(emitcode ("; genNearPointerGet",""));
6552 aopOp (left, ic, FALSE);
6554 /* if left is rematerialisable and
6555 result is not bit variable type and
6556 the left is pointer to data space i.e
6557 lower 128 bytes of space */
6558 if ((AOP_TYPE (left) == AOP_IMMD)
6559 || (AOP_TYPE (left) == AOP_LIT)
6560 /* !IS_BITVAR (retype) */
6561 /* && DCL_TYPE (ltype) == POINTER */ )
6563 genDataPointerGet (left, result, ic);
6567 /* if the operand is already in hx
6568 then we do nothing else we move the value to hx */
6569 if (AOP_TYPE (left) != AOP_STR)
6571 /* if this is remateriazable */
6572 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6573 loadRegFromConst (hc08_reg_h, zero);
6576 /* so hx now contains the address */
6577 aopOp (result, ic, FALSE);
6579 /* if bit then unpack */
6580 if (IS_BITVAR (retype))
6581 genUnpackBits (result);
6584 size = AOP_SIZE (result);
6589 accopWithMisc ("lda", ",x");
6592 rmwWithReg ("inc", hc08_reg_x);
6594 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6595 hc08_freeReg (hc08_reg_a);
6599 freeAsmop (left, NULL, ic, TRUE);
6600 freeAsmop (result, NULL, ic, TRUE);
6602 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6603 aopOp (IC_RESULT (pi), pi, FALSE);
6604 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6605 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6609 hc08_freeReg (hc08_reg_hx);
6613 /*-----------------------------------------------------------------*/
6614 /* genFarPointerGet - get value from far space */
6615 /*-----------------------------------------------------------------*/
6617 genFarPointerGet (operand * left,
6618 operand * result, iCode * ic, iCode * pi)
6621 sym_link *retype = getSpec (operandType (result));
6623 D(emitcode ("; genFarPointerGet",""));
6625 aopOp (left, ic, FALSE);
6627 /* if left is rematerialisable and
6628 result is not bit variable type and
6629 the left is pointer to data space i.e
6630 lower 128 bytes of space */
6631 if (AOP_TYPE (left) == AOP_IMMD &&
6633 /* && DCL_TYPE (ltype) == POINTER */ )
6635 genDataPointerGet (left, result, ic);
6639 /* if the operand is already in hx
6640 then we do nothing else we move the value to hx */
6641 if (AOP_TYPE (left) != AOP_STR)
6643 /* if this is remateriazable */
6644 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6647 /* so hx now contains the address */
6648 aopOp (result, ic, FALSE);
6650 /* if bit then unpack */
6651 if (IS_BITVAR (retype))
6652 genUnpackBits (result);
6655 size = AOP_SIZE (result);
6660 accopWithMisc ("lda", ",x");
6663 emitcode ("aix", "#1");
6664 hc08_dirtyReg (hc08_reg_hx, FALSE);
6666 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6667 hc08_freeReg (hc08_reg_a);
6671 freeAsmop (left, NULL, ic, TRUE);
6672 freeAsmop (result, NULL, ic, TRUE);
6674 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6675 aopOp (IC_RESULT (pi), pi, FALSE);
6676 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6677 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6681 hc08_freeReg (hc08_reg_hx);
6687 /*-----------------------------------------------------------------*/
6688 /* genPointerGet - generate code for pointer get */
6689 /*-----------------------------------------------------------------*/
6691 genPointerGet (iCode * ic, iCode *pi)
6693 operand *left, *result;
6694 sym_link *type, *etype;
6697 D(emitcode ("; genPointerGet",""));
6699 left = IC_LEFT (ic);
6700 result = IC_RESULT (ic);
6702 /* depending on the type of pointer we need to
6703 move it to the correct pointer register */
6704 type = operandType (left);
6705 etype = getSpec (type);
6706 /* if left is of type of pointer then it is simple */
6707 if (IS_PTR (type) && !IS_FUNC (type->next))
6708 p_type = DCL_TYPE (type);
6711 /* we have to go by the storage class */
6712 p_type = PTR_TYPE (SPEC_OCLS (etype));
6715 /* special case when cast remat */
6716 if (p_type == GPOINTER && IS_SYMOP(left) && OP_SYMBOL(left)->remat &&
6717 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6718 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6719 type = operandType (left);
6720 p_type = DCL_TYPE (type);
6722 /* now that we have the pointer type we assign
6723 the pointer values */
6730 genNearPointerGet (left, result, ic, pi);
6736 genFarPointerGet (left, result, ic, pi);
6743 /*-----------------------------------------------------------------*/
6744 /* genPackBits - generates code for packed bit storage */
6745 /*-----------------------------------------------------------------*/
6747 genPackBits (sym_link * etype,
6750 int offset = 0; /* source byte offset */
6751 int rlen = 0; /* remaining bitfield length */
6752 int blen; /* bitfield length */
6753 int bstr; /* bitfield starting bit within byte */
6754 int litval; /* source literal value (if AOP_LIT) */
6755 unsigned char mask; /* bitmask within current byte */
6758 D(emitcode ("; genPackBits",""));
6760 blen = SPEC_BLEN (etype);
6761 bstr = SPEC_BSTR (etype);
6763 /* If the bitfield length is less than a byte */
6766 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6767 (unsigned char) (0xFF >> (8 - bstr)));
6769 if (AOP_TYPE (right) == AOP_LIT)
6771 /* Case with a bitfield length <8 and literal source
6773 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6775 litval &= (~mask) & 0xff;
6777 emitcode ("lda", ",x");
6778 if ((mask|litval)!=0xff)
6779 emitcode ("and","#0x%02x", mask);
6781 emitcode ("ora","#0x%02x", litval);
6782 hc08_dirtyReg (hc08_reg_a, FALSE);
6783 emitcode ("sta", ",x");
6785 hc08_freeReg (hc08_reg_a);
6789 /* Case with a bitfield length < 8 and arbitrary source
6791 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6792 /* shift and mask source value */
6794 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6795 hc08_dirtyReg (hc08_reg_a, FALSE);
6796 pushReg (hc08_reg_a, TRUE);
6798 emitcode ("lda", ",x");
6799 emitcode ("and", "#0x%02x", mask);
6800 emitcode ("ora", "1,s");
6801 emitcode ("sta", ",x");
6802 pullReg (hc08_reg_a);
6804 hc08_freeReg (hc08_reg_a);
6808 /* Bit length is greater than 7 bits. In this case, copy */
6809 /* all except the partial byte at the end */
6810 for (rlen=blen;rlen>=8;rlen-=8)
6812 if (AOP (right)->type == AOP_DIR)
6814 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6819 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6820 emitcode ("sta", "%d,x", offset);
6825 /* If there was a partial byte at the end */
6828 mask = (((unsigned char) -1 << rlen) & 0xff);
6830 if (AOP_TYPE (right) == AOP_LIT)
6832 /* Case with partial byte and literal source
6834 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6835 litval >>= (blen-rlen);
6836 litval &= (~mask) & 0xff;
6837 emitcode ("lda", "%d,x", offset - xoffset);
6838 hc08_dirtyReg (hc08_reg_a, FALSE);
6839 if ((mask|litval)!=0xff)
6840 emitcode ("and","#0x%02x", mask);
6842 emitcode ("ora","#0x%02x", litval);
6843 emitcode ("sta", "%d,x", offset - xoffset);
6844 hc08_dirtyReg (hc08_reg_a, FALSE);
6845 hc08_freeReg (hc08_reg_a);
6849 /* Case with partial byte and arbitrary source
6851 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6852 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6853 hc08_dirtyReg (hc08_reg_a, FALSE);
6854 pushReg (hc08_reg_a, TRUE);
6856 emitcode ("lda", "%d,x", offset - xoffset);
6857 emitcode ("and", "#0x%02x", mask);
6858 emitcode ("ora", "1,s");
6859 emitcode ("sta", "%d,x", offset - xoffset);
6860 pullReg (hc08_reg_a);
6863 hc08_freeReg (hc08_reg_a);
6866 /*-----------------------------------------------------------------*/
6867 /* genDataPointerSet - remat pointer to data space */
6868 /*-----------------------------------------------------------------*/
6870 genDataPointerSet (operand * right,
6874 int size, offset = 0;
6877 D(emitcode ("; genDataPointerSet",""));
6879 aopOp (right, ic, FALSE);
6880 size = AOP_SIZE (right);
6882 derefaop = aopDerefAop (AOP (result));
6883 freeAsmop (result, NULL, ic, TRUE);
6884 derefaop->size = size;
6888 transferAopAop (AOP (right), offset, derefaop, offset);
6892 freeAsmop (right, NULL, ic, TRUE);
6893 freeAsmop (NULL, derefaop, ic, TRUE);
6897 /*-----------------------------------------------------------------*/
6898 /* genNearPointerSet - emitcode for near pointer put */
6899 /*-----------------------------------------------------------------*/
6901 genNearPointerSet (operand * right,
6907 sym_link *retype = getSpec (operandType (right));
6908 sym_link *letype = getSpec (operandType (result));
6910 D(emitcode ("; genNearPointerSet",""));
6912 aopOp (result, ic, FALSE);
6914 /* if the result is rematerializable &
6915 in data space & not a bit variable */
6916 if (AOP_TYPE (result) == AOP_IMMD &&
6917 /* DCL_TYPE (ptype) == POINTER && */
6918 !IS_BITVAR (retype) &&
6919 !IS_BITVAR (letype))
6921 genDataPointerSet (right, result, ic);
6925 /* if the operand is already in hx
6926 then we do nothing else we move the value to hx */
6927 if (AOP_TYPE (result) != AOP_STR)
6929 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6930 loadRegFromConst (hc08_reg_h, zero);
6932 /* so hx now contains the address */
6933 aopOp (right, ic, FALSE);
6935 /* if bit then unpack */
6936 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6937 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6940 size = AOP_SIZE (right);
6945 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6946 accopWithMisc ("sta", ",x");
6949 rmwWithReg ("inc", hc08_reg_x);
6951 hc08_freeReg (hc08_reg_a);
6955 freeAsmop (result, NULL, ic, TRUE);
6956 freeAsmop (right, NULL, ic, TRUE);
6958 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6959 aopOp (IC_RESULT (pi), pi, FALSE);
6960 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6961 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6965 hc08_freeReg (hc08_reg_hx);
6970 /*-----------------------------------------------------------------*/
6971 /* genFarPointerSet - set value from far space */
6972 /*-----------------------------------------------------------------*/
6974 genFarPointerSet (operand * right,
6975 operand * result, iCode * ic, iCode * pi)
6978 sym_link *retype = getSpec (operandType (right));
6979 sym_link *letype = getSpec (operandType (result));
6981 D(emitcode ("; genFarPointerSet",""));
6983 aopOp (result, ic, FALSE);
6985 /* if the result is rematerializable &
6986 in data space & not a bit variable */
6987 if (AOP_TYPE (result) == AOP_IMMD &&
6988 /* DCL_TYPE (ptype) == POINTER && */
6989 !IS_BITVAR (retype) &&
6990 !IS_BITVAR (letype))
6992 genDataPointerSet (right, result, ic);
6996 /* if the operand is already in hx
6997 then we do nothing else we move the value to hx */
6998 if (AOP_TYPE (result) != AOP_STR)
7000 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7002 /* so hx now contains the address */
7003 aopOp (right, ic, FALSE);
7005 /* if bit then unpack */
7006 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7007 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7010 size = AOP_SIZE (right);
7015 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7016 accopWithMisc ("sta", ",x");
7019 emitcode ("aix", "#1");
7021 hc08_freeReg (hc08_reg_a);
7025 freeAsmop (result, NULL, ic, TRUE);
7026 freeAsmop (right, NULL, ic, TRUE);
7028 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
7029 aopOp (IC_RESULT (pi), pi, FALSE);
7030 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7031 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7035 hc08_freeReg (hc08_reg_hx);
7041 /*-----------------------------------------------------------------*/
7042 /* genPointerSet - stores the value into a pointer location */
7043 /*-----------------------------------------------------------------*/
7045 genPointerSet (iCode * ic, iCode *pi)
7047 operand *right, *result;
7048 sym_link *type, *etype;
7051 D(emitcode ("; genPointerSet",""));
7053 right = IC_RIGHT (ic);
7054 result = IC_RESULT (ic);
7056 /* depending on the type of pointer we need to
7057 move it to the correct pointer register */
7058 type = operandType (result);
7059 etype = getSpec (type);
7060 /* if left is of type of pointer then it is simple */
7061 if (IS_PTR (type) && !IS_FUNC (type->next))
7063 p_type = DCL_TYPE (type);
7067 /* we have to go by the storage class */
7068 p_type = PTR_TYPE (SPEC_OCLS (etype));
7071 /* special case when cast remat */
7072 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
7073 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
7074 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
7075 type = operandType (result);
7076 p_type = DCL_TYPE (type);
7078 /* now that we have the pointer type we assign
7079 the pointer values */
7086 genNearPointerSet (right, result, ic, pi);
7092 genFarPointerSet (right, result, ic, pi);
7096 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7097 "genPointerSet: illegal pointer type");
7102 /*-----------------------------------------------------------------*/
7103 /* genIfx - generate code for Ifx statement */
7104 /*-----------------------------------------------------------------*/
7106 genIfx (iCode * ic, iCode * popIc)
7108 operand *cond = IC_COND (ic);
7111 D(emitcode ("; genIfx",""));
7113 aopOp (cond, ic, FALSE);
7115 /* get the value into acc */
7116 if (AOP_TYPE (cond) != AOP_CRY)
7117 asmopToBool (AOP (cond), FALSE);
7120 /* the result is now in the accumulator */
7121 freeAsmop (cond, NULL, ic, TRUE);
7123 /* if there was something to be popped then do it */
7127 /* if the condition is a bit variable */
7128 if (isbit && IS_ITEMP (cond) &&
7130 genIfxJump (ic, SPIL_LOC (cond)->rname);
7131 else if (isbit && !IS_ITEMP (cond))
7132 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7134 genIfxJump (ic, "a");
7139 /*-----------------------------------------------------------------*/
7140 /* genAddrOf - generates code for address of */
7141 /*-----------------------------------------------------------------*/
7143 genAddrOf (iCode * ic)
7145 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7148 D(emitcode ("; genAddrOf",""));
7150 aopOp (IC_RESULT (ic), ic, FALSE);
7152 /* if the operand is on the stack then we
7153 need to get the stack offset of this
7157 /* if it has an offset then we need to compute
7159 hc08_useReg (hc08_reg_hx);
7160 emitcode ("tsx", "");
7161 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7162 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7163 hc08_freeReg (hc08_reg_hx);
7168 /* object not on stack then we need the name */
7169 size = AOP_SIZE (IC_RESULT (ic));
7174 char s[SDCC_NAME_MAX+10];
7177 sprintf (s, "#%s", sym->rname);
7180 sprintf (s, "#>%s", sym->rname);
7183 sprintf (s, "#(%s >> %d)",
7187 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7191 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7195 /*-----------------------------------------------------------------*/
7196 /* genAssign - generate code for assignment */
7197 /*-----------------------------------------------------------------*/
7199 genAssign (iCode * ic)
7201 operand *result, *right;
7203 // unsigned long lit = 0L;
7205 D(emitcode("; genAssign",""));
7207 result = IC_RESULT (ic);
7208 right = IC_RIGHT (ic);
7210 /* if they are the same */
7211 if (operandsEqu (result, right)) {
7215 aopOp (right, ic, FALSE);
7216 aopOp (result, ic, TRUE);
7218 /* if they are the same registers */
7219 if (sameRegs (AOP (right), AOP (result)))
7222 if ((AOP_TYPE (right) == AOP_LIT)
7223 && (IS_AOP_HX(AOP(result))))
7225 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7230 size = AOP_SIZE (result);
7235 transferAopAop (AOP (right), offset, AOP (result), offset);
7240 freeAsmop (right, NULL, ic, TRUE);
7241 freeAsmop (result, NULL, ic, TRUE);
7244 /*-----------------------------------------------------------------*/
7245 /* genJumpTab - genrates code for jump table */
7246 /*-----------------------------------------------------------------*/
7248 genJumpTab (iCode * ic)
7253 D(emitcode ("; genJumpTab",""));
7255 aopOp (IC_JTCOND (ic), ic, FALSE);
7256 /* get the condition into accumulator */
7257 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7258 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7259 /* multiply by three */
7260 pushReg (hc08_reg_a, FALSE);
7261 emitcode ("lsla", "");
7262 emitcode ("add","1,s");
7263 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7264 loadRegFromConst (hc08_reg_h, zero);
7265 pullReg (hc08_reg_a);
7267 jtab = newiTempLabel (NULL);
7268 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7269 emitcode ("", "%05d$:", jtab->key + 100);
7270 /* now generate the jump labels */
7271 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7272 jtab = setNextItem (IC_JTLABELS (ic)))
7273 emitcode ("jmp", "%05d$", jtab->key + 100);
7275 hc08_dirtyReg (hc08_reg_a, TRUE);
7276 hc08_dirtyReg (hc08_reg_hx, TRUE);
7279 /*-----------------------------------------------------------------*/
7280 /* genCast - gen code for casting */
7281 /*-----------------------------------------------------------------*/
7283 genCast (iCode * ic)
7285 operand *result = IC_RESULT (ic);
7286 sym_link *ctype = operandType (IC_LEFT (ic));
7287 sym_link *rtype = operandType (IC_RIGHT (ic));
7288 operand *right = IC_RIGHT (ic);
7291 D(emitcode("; genCast",""));
7293 /* if they are equivalent then do nothing */
7294 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7297 aopOp (right, ic, FALSE);
7298 aopOp (result, ic, FALSE);
7301 /* if they are the same size : or less */
7302 if (AOP_SIZE (result) <= AOP_SIZE (right))
7305 /* if they are in the same place */
7307 if (sameRegs (AOP (right), AOP (result)))
7311 /* if they in different places then copy */
7312 size = AOP_SIZE (result);
7316 transferAopAop(AOP (right), offset, AOP (result), offset);
7323 /* if the result is of type pointer */
7328 sym_link *type = operandType (right);
7329 sym_link *etype = getSpec (type);
7331 /* pointer to generic pointer */
7332 if (IS_GENPTR (ctype))
7335 p_type = DCL_TYPE (type);
7338 if (SPEC_SCLS(etype)==S_REGISTER) {
7339 // let's assume it is a generic pointer
7342 /* we have to go by the storage class */
7343 p_type = PTR_TYPE (SPEC_OCLS (etype));
7347 /* the first two bytes are known */
7348 size = GPTRSIZE - 1;
7352 transferAopAop(AOP (right), offset, AOP (result), offset);
7355 /* the last byte depending on type */
7358 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7363 // pointerTypeToGPByte will have bitched.
7367 sprintf(gpValStr, "#0x%d", gpVal);
7368 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7374 /* just copy the pointers */
7375 size = AOP_SIZE (result);
7379 transferAopAop(AOP (right), offset, AOP (result), offset);
7385 /* so we now know that the size of destination is greater
7386 than the size of the source */
7387 /* we move to result for the size of source */
7388 size = AOP_SIZE (right);
7392 transferAopAop(AOP (right), offset, AOP (result), offset);
7396 /* now depending on the sign of the source && destination */
7397 size = AOP_SIZE (result) - AOP_SIZE (right);
7398 /* if unsigned or not an integral type */
7399 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7402 storeConstToAop (zero, AOP (result), offset++);
7406 /* we need to extend the sign :{ */
7407 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7408 accopWithMisc ("rola", "");
7409 accopWithMisc ("clra", "");
7410 accopWithMisc ("sbc", zero);
7412 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7415 /* we are done hurray !!!! */
7418 freeAsmop (right, NULL, ic, TRUE);
7419 freeAsmop (result, NULL, ic, TRUE);
7423 /*-----------------------------------------------------------------*/
7424 /* genDjnz - generate decrement & jump if not zero instrucion */
7425 /*-----------------------------------------------------------------*/
7427 genDjnz (iCode * ic, iCode * ifx)
7433 D(emitcode ("; genDjnz",""));
7435 /* if the if condition has a false label
7436 then we cannot save */
7440 /* if the minus is not of the form
7442 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7443 !IS_OP_LITERAL (IC_RIGHT (ic)))
7446 if (operandLitValue (IC_RIGHT (ic)) != 1)
7449 /* dbnz doesn't support extended mode */
7450 if (isOperandInFarSpace (IC_RESULT (ic)))
7453 /* if the size of this greater than one then no
7455 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7457 aopOp (IC_RESULT (ic), ic, FALSE);
7458 if (AOP_SIZE (IC_RESULT (ic))>1)
7460 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7464 /* otherwise we can save BIG */
7465 lbl = newiTempLabel (NULL);
7466 lbl1 = newiTempLabel (NULL);
7469 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7472 emitBranch ("bra", lbl1);
7474 emitBranch ("jmp", IC_TRUE (ifx));
7477 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7482 /*-----------------------------------------------------------------*/
7483 /* genReceive - generate code for a receive iCode */
7484 /*-----------------------------------------------------------------*/
7486 genReceive (iCode * ic)
7490 D(emitcode ("; genReceive",""));
7492 aopOp (IC_RESULT (ic), ic, FALSE);
7493 size = AOP_SIZE (IC_RESULT (ic));
7498 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7499 AOP (IC_RESULT (ic)), offset);
7500 if (hc08_aop_pass[offset]->type == AOP_REG)
7501 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7506 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7509 /*-----------------------------------------------------------------*/
7510 /* genDummyRead - generate code for dummy read of volatiles */
7511 /*-----------------------------------------------------------------*/
7513 genDummyRead (iCode * ic)
7518 D(emitcode("; genDummyRead",""));
7521 if (op && IS_SYMOP (op))
7524 aopOp (op, ic, FALSE);
7526 size = AOP_SIZE (op);
7531 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7532 hc08_freeReg (hc08_reg_a);
7536 freeAsmop (op, NULL, ic, TRUE);
7539 if (op && IS_SYMOP (op))
7542 aopOp (op, ic, FALSE);
7544 size = AOP_SIZE (op);
7549 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7550 hc08_freeReg (hc08_reg_a);
7554 freeAsmop (op, NULL, ic, TRUE);
7558 /*-----------------------------------------------------------------*/
7559 /* genCritical - generate code for start of a critical sequence */
7560 /*-----------------------------------------------------------------*/
7562 genCritical (iCode *ic)
7564 D(emitcode("; genCritical",""));
7567 aopOp (IC_RESULT (ic), ic, TRUE);
7569 emitcode ("tpa", "");
7570 hc08_dirtyReg (hc08_reg_a, FALSE);
7571 emitcode ("sei", "");
7574 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7576 pushReg (hc08_reg_a, FALSE);
7578 hc08_freeReg (hc08_reg_a);
7580 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7583 /*-----------------------------------------------------------------*/
7584 /* genEndCritical - generate code for end of a critical sequence */
7585 /*-----------------------------------------------------------------*/
7587 genEndCritical (iCode *ic)
7589 D(emitcode("; genEndCritical",""));
7593 aopOp (IC_RIGHT (ic), ic, FALSE);
7594 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7595 emitcode ("tap", "");
7596 hc08_freeReg (hc08_reg_a);
7597 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7601 pullReg (hc08_reg_a);
7602 emitcode ("tap", "");
7608 /*-----------------------------------------------------------------*/
7609 /* genhc08Code - generate code for HC08 based controllers */
7610 /*-----------------------------------------------------------------*/
7612 genhc08Code (iCode * lic)
7619 lineHead = lineCurr = NULL;
7621 /* print the allocation information */
7622 if (allocInfo && currFunc)
7623 printAllocInfo (currFunc, codeOutFile);
7624 /* if debug information required */
7625 if (options.debug && currFunc)
7627 debugFile->writeFunction (currFunc, lic);
7630 if (IS_STATIC (currFunc->etype))
7631 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7633 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7637 /* stack pointer name */
7638 if (options.useXstack)
7643 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
7645 hc08_aop_pass[0] = newAsmop (AOP_REG);
7646 hc08_aop_pass[0]->size=1;
7647 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7648 hc08_aop_pass[1] = newAsmop (AOP_REG);
7649 hc08_aop_pass[1]->size=1;
7650 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7651 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7652 hc08_aop_pass[2]->size=1;
7653 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7654 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7655 hc08_aop_pass[3]->size=1;
7656 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7658 for (ic = lic; ic; ic = ic->next)
7661 _G.current_iCode = ic;
7663 if (ic->level != clevel || ic->block != cblock)
7667 debugFile->writeScope(ic);
7673 if (ic->lineno && cln != ic->lineno)
7677 debugFile->writeCLine(ic);
7680 emitcode ("", "C$%s$%d$%d$%d ==.",
7681 FileBaseName (ic->filename), ic->lineno,
7682 ic->level, ic->block);
7686 if (!options.noCcodeInAsm) {
7687 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7688 printCLine(ic->filename, ic->lineno));
7692 if (options.iCodeInAsm) {
7696 for (i=0; i<6; i++) {
7697 sprintf (®sInUse[i],
7698 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7701 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7703 /* if the result is marked as
7704 spilt and rematerializable or code for
7705 this has already been generated then
7707 if (resultRemat (ic) || ic->generated)
7715 for (i=A_IDX;i<=XA_IDX;i++)
7717 reg = hc08_regWithIdx(i);
7719 emitcode("","; %s = %s offset %d", reg->name,
7720 aopName(reg->aop), reg->aopofs);
7723 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7725 sym = OP_SYMBOL (IC_LEFT (ic));
7726 if (sym->accuse == ACCUSE_HX)
7728 hc08_reg_h->isFree = FALSE;
7729 hc08_reg_x->isFree = FALSE;
7731 else if (sym->accuse == ACCUSE_XA)
7733 hc08_reg_a->isFree = FALSE;
7735 hc08_reg_x->isFree = FALSE;
7738 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7740 sym = OP_SYMBOL (IC_RIGHT (ic));
7741 if (sym->accuse == ACCUSE_HX)
7743 hc08_reg_h->isFree = FALSE;
7744 hc08_reg_x->isFree = FALSE;
7746 else if (sym->accuse == ACCUSE_XA)
7748 hc08_reg_a->isFree = FALSE;
7750 hc08_reg_x->isFree = FALSE;
7755 /* depending on the operation */
7775 /* IPOP happens only when trying to restore a
7776 spilt live range, if there is an ifx statement
7777 following this pop then the if statement might
7778 be using some of the registers being popped which
7779 would destory the contents of the register so
7780 we need to check for this condition and handle it */
7782 ic->next->op == IFX &&
7783 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7784 genIfx (ic->next, ic);
7802 genEndFunction (ic);
7818 if (!genPointerGetSetOfs (ic))
7823 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7840 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7844 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7851 /* note these two are xlated by algebraic equivalence
7852 during parsing SDCC.y */
7853 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7854 "got '>=' or '<=' shouldn't have come here");
7858 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7870 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7874 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7878 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7905 case GET_VALUE_AT_ADDRESS:
7906 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7910 if (POINTER_SET (ic))
7911 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7937 addSet (&_G.sendSet, ic);
7940 case DUMMY_READ_VOLATILE:
7949 genEndCritical (ic);
7960 if (!hc08_reg_a->isFree)
7961 D(emitcode("","; forgot to free a"));
7962 if (!hc08_reg_x->isFree)
7963 D(emitcode("","; forgot to free x"));
7964 if (!hc08_reg_h->isFree)
7965 D(emitcode("","; forgot to free h"));
7966 if (!hc08_reg_hx->isFree)
7967 D(emitcode("","; forgot to free hx"));
7968 if (!hc08_reg_xa->isFree)
7969 D(emitcode("","; forgot to free xa"));
7972 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
7975 /* now we are ready to call the
7976 peep hole optimizer */
7977 if (!options.nopeep)
7978 peepHole (&lineHead);
7980 /* now do the actual printing */
7981 printLine (lineHead, codeOutFile);