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;
2334 transferAopAop (AOP (op), offset, AOP (result), offset);
2338 needpula = pushRegIfUsed (hc08_reg_a);
2339 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2340 emitcode ("eor", "#0x80");
2341 hc08_useReg (hc08_reg_a);
2342 storeRegToAop (hc08_reg_a, AOP (result), offset);
2343 pullOrFreeReg (hc08_reg_a, needpula);
2346 /*-----------------------------------------------------------------*/
2347 /* genUminus - unary minus code generation */
2348 /*-----------------------------------------------------------------*/
2350 genUminus (iCode * ic)
2353 sym_link *optype, *rtype;
2358 D(emitcode ("; genUminus",""));
2361 aopOp (IC_LEFT (ic), ic, FALSE);
2362 aopOp (IC_RESULT (ic), ic, TRUE);
2364 optype = operandType (IC_LEFT (ic));
2365 rtype = operandType (IC_RESULT (ic));
2367 /* if float then do float stuff */
2368 if (IS_FLOAT (optype))
2370 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2374 /* otherwise subtract from zero */
2375 size = AOP_SIZE (IC_LEFT (ic));
2380 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2381 needpula = pushRegIfUsed (hc08_reg_a);
2384 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2385 emitcode ("nega", "");
2386 hc08_freeReg (hc08_reg_a);
2387 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2388 SPEC_USIGN (operandType (IC_LEFT (ic))));
2389 pullOrFreeReg (hc08_reg_a, needpula);
2393 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2394 result = forceStackedAop (AOP (IC_RESULT (ic)));
2396 result = AOP (IC_RESULT (ic));
2398 needpula = pushRegIfUsed (hc08_reg_a);
2402 loadRegFromConst (hc08_reg_a, zero);
2403 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2404 storeRegToAop (hc08_reg_a, result, offset++);
2407 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2408 SPEC_USIGN (operandType (IC_LEFT (ic))));
2409 pullOrFreeReg (hc08_reg_a, needpula);
2411 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2412 freeAsmop (NULL, result, ic, TRUE);
2418 /* release the aops */
2419 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2420 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2423 /*-----------------------------------------------------------------*/
2424 /* saveRegisters - will look for a call and save the registers */
2425 /*-----------------------------------------------------------------*/
2427 saveRegisters (iCode * lic)
2434 for (ic = lic; ic; ic = ic->next)
2435 if (ic->op == CALL || ic->op == PCALL)
2440 fprintf (stderr, "found parameter push with no function call\n");
2444 /* if the registers have been saved already or don't need to be then
2448 if (IS_SYMOP(IC_LEFT(ic)) &&
2449 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2450 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2453 /* safe the registers in use at this time but skip the
2454 ones for the result */
2455 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2456 hc08_rUmaskForOp (IC_RESULT(ic)));
2459 for (i = 0; i < hc08_nRegs; i++)
2461 if (bitVectBitValue (rsave, i))
2462 pushReg ( hc08_regWithIdx (i), FALSE);
2466 /*-----------------------------------------------------------------*/
2467 /* unsaveRegisters - pop the pushed registers */
2468 /*-----------------------------------------------------------------*/
2470 unsaveRegisters (iCode * ic)
2475 /* restore the registers in use at this time but skip the
2476 ones for the result */
2477 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2478 hc08_rUmaskForOp (IC_RESULT(ic)));
2480 for (i = hc08_nRegs; i >= 0; i--)
2482 if (bitVectBitValue (rsave, i))
2483 pullReg ( hc08_regWithIdx (i));
2489 /*-----------------------------------------------------------------*/
2491 /*-----------------------------------------------------------------*/
2493 pushSide (operand * oper, int size)
2498 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2499 pushReg ( hc08_reg_a, TRUE);
2503 /*-----------------------------------------------------------------*/
2504 /* assignResultValue - */
2505 /*-----------------------------------------------------------------*/
2507 assignResultValue (operand * oper)
2509 int size = AOP_SIZE (oper);
2513 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2514 if (hc08_aop_pass[offset]->type == AOP_REG)
2515 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2522 /*-----------------------------------------------------------------*/
2523 /* genIpush - genrate code for pushing this gets a little complex */
2524 /*-----------------------------------------------------------------*/
2526 genIpush (iCode * ic)
2528 int size, offset = 0;
2531 D(emitcode ("; genIpush",""));
2533 /* if this is not a parm push : ie. it is spill push
2534 and spill push is always done on the local stack */
2538 /* and the item is spilt then do nothing */
2539 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2542 aopOp (IC_LEFT (ic), ic, FALSE);
2543 size = AOP_SIZE (IC_LEFT (ic));
2545 /* push it on the stack */
2548 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2549 pushReg ( hc08_reg_a, TRUE);
2555 /* this is a paramter push: in this case we call
2556 the routine to find the call and save those
2557 registers that need to be saved */
2560 /* then do the push */
2561 aopOp (IC_LEFT (ic), ic, FALSE);
2564 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2565 size = AOP_SIZE (IC_LEFT (ic));
2568 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2569 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2571 if ((size==2) && hc08_reg_hx->isFree)
2573 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2574 pushReg (hc08_reg_hx, TRUE);
2581 // printf("loading %d\n", offset);
2582 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2583 // printf("pushing \n");
2584 pushReg (hc08_reg_a, TRUE);
2588 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2591 /*-----------------------------------------------------------------*/
2592 /* genIpop - recover the registers: can happen only for spilling */
2593 /*-----------------------------------------------------------------*/
2595 genIpop (iCode * ic)
2599 D(emitcode ("; genIpop",""));
2601 /* if the temp was not pushed then */
2602 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2605 aopOp (IC_LEFT (ic), ic, FALSE);
2606 size = AOP_SIZE (IC_LEFT (ic));
2610 pullReg (hc08_reg_a);
2611 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2613 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2617 /*-----------------------------------------------------------------*/
2618 /* genSend - gen code for SEND */
2619 /*-----------------------------------------------------------------*/
2620 static void genSend(set *sendSet)
2624 for (sic = setFirstItem (_G.sendSet); sic;
2625 sic = setNextItem (_G.sendSet)) {
2626 int size, offset = 0;
2627 aopOp (IC_LEFT (sic), sic, FALSE);
2628 size = AOP_SIZE (IC_LEFT (sic));
2633 transferAopAop( AOP (IC_LEFT (sic)), offset,
2634 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2638 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2642 /*-----------------------------------------------------------------*/
2643 /* genCall - generates a call statement */
2644 /*-----------------------------------------------------------------*/
2646 genCall (iCode * ic)
2649 // bool restoreBank = FALSE;
2650 // bool swapBanks = FALSE;
2652 D(emitcode("; genCall",""));
2654 dtype = operandType (IC_LEFT (ic));
2655 /* if send set is not empty the assign */
2658 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2659 genSend(reverseSet(_G.sendSet));
2661 genSend(_G.sendSet);
2667 /* if caller saves & we have not saved then */
2673 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2674 OP_SYMBOL (IC_LEFT (ic))->rname :
2675 OP_SYMBOL (IC_LEFT (ic))->name));
2678 /* if we need assign a result value */
2679 if ((IS_ITEMP (IC_RESULT (ic)) &&
2680 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2681 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2682 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2683 IS_TRUE_SYMOP (IC_RESULT (ic)))
2687 aopOp (IC_RESULT (ic), ic, FALSE);
2690 assignResultValue (IC_RESULT (ic));
2692 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2695 /* adjust the stack for parameters if
2699 pullNull (ic->parmBytes);
2702 /* if we had saved some registers then unsave them */
2703 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2704 unsaveRegisters (ic);
2708 /*-----------------------------------------------------------------*/
2709 /* -10l - generates a call by pointer statement */
2710 /*-----------------------------------------------------------------*/
2712 genPcall (iCode * ic)
2715 symbol *rlbl = newiTempLabel (NULL);
2716 symbol *tlbl = newiTempLabel (NULL);
2717 // bool restoreBank=FALSE;
2718 // bool swapBanks = FALSE;
2720 D(emitcode("; genPCall",""));
2722 /* if caller saves & we have not saved then */
2726 /* if we are calling a not _naked function that is not using
2727 the same register bank then we need to save the
2728 destination registers on the stack */
2729 dtype = operandType (IC_LEFT (ic))->next;
2731 /* now push the calling address */
2732 emitBranch ("bsr", tlbl);
2733 emitBranch ("bra", rlbl);
2736 /* Push the function's address */
2737 aopOp (IC_LEFT (ic), ic, FALSE);
2738 pushSide (IC_LEFT (ic), FPTRSIZE);
2739 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2741 /* if send set is not empty the assign */
2744 genSend(reverseSet(_G.sendSet));
2750 emitcode ("rts", "");
2755 /* if we need assign a result value */
2756 if ((IS_ITEMP (IC_RESULT (ic)) &&
2757 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2758 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2759 IS_TRUE_SYMOP (IC_RESULT (ic)))
2763 aopOp (IC_RESULT (ic), ic, FALSE);
2766 assignResultValue (IC_RESULT (ic));
2768 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2771 /* adjust the stack for parameters if
2775 pullNull (ic->parmBytes);
2778 /* if we hade saved some registers then
2780 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2781 unsaveRegisters (ic);
2784 /*-----------------------------------------------------------------*/
2785 /* resultRemat - result is rematerializable */
2786 /*-----------------------------------------------------------------*/
2788 resultRemat (iCode * ic)
2790 if (SKIP_IC (ic) || ic->op == IFX)
2793 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2795 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2796 if (sym->remat && !POINTER_SET (ic))
2803 #if defined(__BORLANDC__) || defined(_MSC_VER)
2804 #define STRCASECMP stricmp
2806 #define STRCASECMP strcasecmp
2809 /*-----------------------------------------------------------------*/
2810 /* inExcludeList - return 1 if the string is in exclude Reg list */
2811 /*-----------------------------------------------------------------*/
2813 regsCmp(void *p1, void *p2)
2815 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2819 inExcludeList (char *s)
2821 const char *p = setFirstItem(options.excludeRegsSet);
2823 if (p == NULL || STRCASECMP(p, "none") == 0)
2827 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2830 /*-----------------------------------------------------------------*/
2831 /* genFunction - generated code for function entry */
2832 /*-----------------------------------------------------------------*/
2834 genFunction (iCode * ic)
2838 int calleesaves_saved_register = -1;
2842 /* create the function header */
2843 emitcode (";", "-----------------------------------------");
2844 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2845 emitcode (";", "-----------------------------------------");
2847 emitcode ("", "%s:", sym->rname);
2848 ftype = operandType (IC_LEFT (ic));
2852 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2854 if (IFFUNC_ISNAKED(ftype))
2856 emitcode(";", "naked function: no prologue.");
2862 /* if this is an interrupt service routine then
2864 if (IFFUNC_ISISR (sym->type))
2867 if (!inExcludeList ("h"))
2868 pushReg (hc08_reg_h, FALSE);
2872 /* if callee-save to be used for this function
2873 then save the registers being used in this function */
2874 if (IFFUNC_CALLEESAVES(sym->type))
2878 /* if any registers used */
2881 /* save the registers used */
2882 for (i = 0; i < sym->regsUsed->size; i++)
2884 if (bitVectBitValue (sym->regsUsed, i))
2886 /* remember one saved register for later usage */
2887 if (calleesaves_saved_register < 0)
2888 calleesaves_saved_register = i;
2889 pushReg (hc08_regWithIdx (i), FALSE);
2897 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2902 /* adjust the stack for the function */
2908 // werror (W_STACK_OVERFLOW, sym->name);
2912 _G.stackOfs = sym->stack;
2915 /* if critical function then turn interrupts off */
2916 if (IFFUNC_ISCRITICAL (ftype))
2918 if (IFFUNC_ARGS (ftype))
2920 /* Function was passed parameters, so make sure A is preserved */
2921 pushReg (hc08_reg_a, FALSE);
2922 pushReg (hc08_reg_a, FALSE);
2923 emitcode ("tpa", "");
2924 emitcode ("sta", "2,s");
2925 emitcode ("sei", "");
2926 pullReg (hc08_reg_a);
2930 /* No passed parameters, so A can be freely modified */
2931 emitcode ("tpa", "");
2932 pushReg (hc08_reg_a, TRUE);
2933 emitcode ("sei", "");
2939 /*-----------------------------------------------------------------*/
2940 /* genEndFunction - generates epilogue for functions */
2941 /*-----------------------------------------------------------------*/
2943 genEndFunction (iCode * ic)
2945 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2947 if (IFFUNC_ISNAKED(sym->type))
2949 emitcode(";", "naked function: no epilogue.");
2950 if (options.debug && currFunc)
2951 debugFile->writeEndFunction (currFunc, ic, 0);
2955 if (IFFUNC_ISCRITICAL (sym->type))
2957 if (!IS_VOID(sym->type->next))
2959 /* Function has return value, so make sure A is preserved */
2960 pushReg (hc08_reg_a, FALSE);
2961 emitcode ("lda", "2,s");
2962 emitcode ("tap", "");
2963 pullReg (hc08_reg_a);
2968 /* Function returns void, so A can be freely modified */
2969 pullReg (hc08_reg_a);
2970 emitcode ("tap", "");
2974 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2980 _G.stackPushes += sym->stack;
2981 adjustStack (sym->stack);
2985 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2989 if (IFFUNC_ISISR (sym->type))
2992 if (!inExcludeList ("h"))
2993 pullReg (hc08_reg_h);
2996 /* if debug then send end of function */
2997 if (options.debug && currFunc)
2999 debugFile->writeEndFunction (currFunc, ic, 1);
3002 emitcode ("rti", "");
3006 if (IFFUNC_CALLEESAVES(sym->type))
3010 /* if any registers used */
3013 /* save the registers used */
3014 for (i = sym->regsUsed->size; i >= 0; i--)
3016 if (bitVectBitValue (sym->regsUsed, i) ||
3017 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3018 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3024 /* if debug then send end of function */
3025 if (options.debug && currFunc)
3027 debugFile->writeEndFunction (currFunc, ic, 1);
3030 emitcode ("rts", "");
3035 /*-----------------------------------------------------------------*/
3036 /* genRet - generate code for return statement */
3037 /*-----------------------------------------------------------------*/
3041 int size, offset = 0;
3044 D(emitcode ("; genRet",""));
3046 /* if we have no return value then
3047 just generate the "ret" */
3051 /* we have something to return then
3052 move the return value into place */
3053 aopOp (IC_LEFT (ic), ic, FALSE);
3054 size = AOP_SIZE (IC_LEFT (ic));
3060 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3067 /* 4 byte return: store value in the global return variable */
3071 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3072 STA (fReturn2[offset--], FALSE);
3073 hc08_freeReg (hc08_reg_a);
3077 /* 2 byte return: store value in x:a */
3078 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3079 hc08_freeReg (hc08_reg_xa);
3082 /* 1 byte return: store value in a */
3083 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3084 hc08_freeReg (hc08_reg_a);
3089 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3092 /* generate a jump to the return label
3093 if the next is not the return statement */
3094 if (!(ic->next && ic->next->op == LABEL &&
3095 IC_LABEL (ic->next) == returnLabel))
3097 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3101 /*-----------------------------------------------------------------*/
3102 /* genLabel - generates a label */
3103 /*-----------------------------------------------------------------*/
3105 genLabel (iCode * ic)
3110 /* For the high level labels we cannot depend on any */
3111 /* register's contents. Amnesia time. */
3112 for (i=A_IDX;i<=XA_IDX;i++)
3114 reg = hc08_regWithIdx(i);
3119 /* special case never generate */
3120 if (IC_LABEL (ic) == entryLabel)
3123 debugFile->writeLabel(IC_LABEL (ic), ic);
3125 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3129 /*-----------------------------------------------------------------*/
3130 /* genGoto - generates a jmp */
3131 /*-----------------------------------------------------------------*/
3133 genGoto (iCode * ic)
3135 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3139 /*-----------------------------------------------------------------*/
3140 /* findLabelBackwards: walks back through the iCode chain looking */
3141 /* for the given label. Returns number of iCode instructions */
3142 /* between that label and given ic. */
3143 /* Returns zero if label not found. */
3144 /*-----------------------------------------------------------------*/
3146 findLabelBackwards (iCode * ic, int key)
3155 /* If we have any pushes or pops, we cannot predict the distance.
3156 I don't like this at all, this should be dealt with in the
3158 if (ic->op == IPUSH || ic->op == IPOP) {
3162 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3172 /*-----------------------------------------------------------------*/
3173 /* genPlusIncr :- does addition with increment if possible */
3174 /*-----------------------------------------------------------------*/
3176 genPlusIncr (iCode * ic)
3184 unsigned int size = getDataSize (IC_RESULT (ic));
3186 symbol *tlbl = NULL;
3188 left = IC_LEFT (ic);
3189 result = IC_RESULT (ic);
3191 /* will try to generate an increment */
3192 /* if the right side is not a literal
3194 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3197 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3199 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3201 if ((IS_AOP_HX (AOP (left)) ||
3202 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3204 && (icount>=-128) && (icount<=127) && (size==2))
3206 if (!IS_AOP_HX (AOP (left)))
3208 needpulx = pushRegIfUsed (hc08_reg_x);
3209 needpulh = pushRegIfUsed (hc08_reg_h);
3216 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3217 emitcode ("aix","#%d", icount);
3218 hc08_dirtyReg (hc08_reg_hx, FALSE);
3219 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3220 pullOrFreeReg (hc08_reg_h, needpulh);
3221 pullOrFreeReg (hc08_reg_x, needpulx);
3225 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3226 sameRegs (AOP (left), AOP (result))));
3228 if ((icount > 255) || (icount<0))
3231 if (!sameRegs (AOP (left), AOP (result)))
3234 D(emitcode ("; genPlusIncr",""));
3237 tlbl = newiTempLabel (NULL);
3242 rmwWithAop ("inc", AOP (result), 0);
3244 emitBranch ("bne", tlbl);
3248 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3249 needpula = pushRegIfUsed (hc08_reg_a);
3252 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3253 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3254 hc08_useReg (hc08_reg_a);
3255 storeRegToAop (hc08_reg_a, AOP (result), 0);
3256 hc08_freeReg (hc08_reg_a);
3258 emitBranch ("bcc", tlbl);
3260 for (offset=1; offset<size; offset++)
3262 rmwWithAop ("inc", AOP (result), offset);
3263 if ((offset+1)<size)
3264 emitBranch ("bne", tlbl);
3270 pullOrFreeReg (hc08_reg_a, needpula);
3277 /*-----------------------------------------------------------------*/
3278 /* genPlus - generates code for addition */
3279 /*-----------------------------------------------------------------*/
3281 genPlus (iCode * ic)
3283 int size, offset = 0;
3285 asmop *leftOp, *rightOp;
3287 /* special cases :- */
3289 D(emitcode ("; genPlus",""));
3291 aopOp (IC_LEFT (ic), ic, FALSE);
3292 aopOp (IC_RIGHT (ic), ic, FALSE);
3293 aopOp (IC_RESULT (ic), ic, TRUE);
3295 /* we want registers on the left and literals on the right */
3296 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3297 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3299 operand *t = IC_RIGHT (ic);
3300 IC_RIGHT (ic) = IC_LEFT (ic);
3305 /* if I can do an increment instead
3306 of add then GOOD for ME */
3307 if (genPlusIncr (ic) == TRUE)
3310 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3311 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3312 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3314 size = getDataSize (IC_RESULT (ic));
3316 leftOp = AOP(IC_LEFT(ic));
3317 rightOp = AOP(IC_RIGHT(ic));
3323 loadRegFromAop (hc08_reg_a, leftOp, offset);
3324 accopWithAop(add, rightOp, offset);
3325 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3326 hc08_freeReg (hc08_reg_a);
3327 add = "adc"; /* further adds must propagate carry */
3331 // adjustArithmeticResult (ic);
3334 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3335 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3336 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3339 /*-----------------------------------------------------------------*/
3340 /* genMinusDec :- does subtraction with deccrement if possible */
3341 /*-----------------------------------------------------------------*/
3343 genMinusDec (iCode * ic)
3345 unsigned int icount;
3350 unsigned int size = getDataSize (IC_RESULT (ic));
3354 left = IC_LEFT (ic);
3355 result = IC_RESULT (ic);
3357 /* will try to generate an increment */
3358 /* if the right side is not a literal
3360 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3363 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3365 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3366 && (icount>=-127) && (icount<=128) && (size==2))
3368 if (!IS_AOP_HX (AOP (left)))
3370 needpulx = pushRegIfUsed (hc08_reg_x);
3371 needpulh = pushRegIfUsed (hc08_reg_h);
3378 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3379 emitcode ("aix","#%d", -icount);
3380 hc08_dirtyReg (hc08_reg_hx, FALSE);
3381 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3382 pullOrFreeReg (hc08_reg_h, needpulh);
3383 pullOrFreeReg (hc08_reg_x, needpulx);
3387 if ((icount > 1) || (icount<0))
3390 if (!sameRegs (AOP (left), AOP (result)))
3396 D(emitcode ("; genMinusDec",""));
3398 rmwWithAop ("dec", AOP (result), 0);
3403 /*-----------------------------------------------------------------*/
3404 /* addSign - complete with sign */
3405 /*-----------------------------------------------------------------*/
3407 addSign (operand * result, int offset, int sign)
3409 int size = (getDataSize (result) - offset);
3414 emitcode ("rola", "");
3415 emitcode ("clra", "");
3416 emitcode ("sbc", zero);
3418 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3422 storeConstToAop (zero, AOP (result), offset++);
3427 /*-----------------------------------------------------------------*/
3428 /* genMinus - generates code for subtraction */
3429 /*-----------------------------------------------------------------*/
3431 genMinus (iCode * ic)
3434 int size, offset = 0;
3436 asmop *leftOp, *rightOp;
3438 D(emitcode ("; genMinus",""));
3440 aopOp (IC_LEFT (ic), ic, FALSE);
3441 aopOp (IC_RIGHT (ic), ic, FALSE);
3442 aopOp (IC_RESULT (ic), ic, TRUE);
3444 /* special cases :- */
3445 /* if I can do an decrement instead
3446 of subtract then GOOD for ME */
3447 if (genMinusDec (ic) == TRUE)
3450 size = getDataSize (IC_RESULT (ic));
3453 leftOp = AOP(IC_LEFT(ic));
3454 rightOp = AOP(IC_RIGHT(ic));
3460 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3461 accopWithAop(sub, rightOp, offset);
3462 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3467 // adjustArithmeticResult (ic);
3470 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3471 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3472 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3477 /*-----------------------------------------------------------------*/
3478 /* genMultOneByte : 8*8=8/16 bit multiplication */
3479 /*-----------------------------------------------------------------*/
3481 genMultOneByte (operand * left,
3485 /* sym_link *opetype = operandType (result); */
3486 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3487 int size=AOP_SIZE(result);
3488 bool negLiteral = FALSE;
3490 D(emitcode ("; genMultOneByte",""));
3492 if (size<1 || size>2) {
3493 // this should never happen
3494 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3495 AOP_SIZE(result), __FILE__, lineno);
3499 /* (if two literals: the value is computed before) */
3500 /* if one literal, literal on the right */
3501 if (AOP_TYPE (left) == AOP_LIT)
3506 //D(emitcode (";", "swapped left and right"));
3510 || (SPEC_USIGN(operandType(left)) &&
3511 SPEC_USIGN(operandType(right))))
3513 // just an unsigned 8*8=8/16 multiply
3514 //D(emitcode (";","unsigned"));
3516 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3517 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3518 emitcode ("mul", "");
3519 hc08_dirtyReg (hc08_reg_xa, FALSE);
3520 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3521 hc08_freeReg (hc08_reg_xa);
3526 // we have to do a signed multiply
3529 //D(emitcode (";", "signed"));
3531 emitcode ("clr", "1,s");
3533 tlbl1 = newiTempLabel (NULL);
3534 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3535 emitcode ("tsta","");
3536 emitBranch ("bpl", tlbl1);
3537 emitcode ("inc", "1,s");
3538 rmwWithReg ("neg", hc08_reg_a);
3541 if (AOP_TYPE(right)==AOP_LIT)
3543 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3544 /* AND literal negative */
3546 emitcode ("ldx", "#0x%02x", -val);
3549 emitcode ("ldx", "#0x%02x", val);
3551 hc08_useReg (hc08_reg_x);
3555 tlbl2 = newiTempLabel (NULL);
3556 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3557 emitcode ("tstx", "");
3558 emitBranch ("bpl", tlbl2);
3559 emitcode ("inc", "1,s");
3560 rmwWithReg ("neg", hc08_reg_x);
3564 emitcode ("mul", "");
3565 hc08_dirtyReg (hc08_reg_xa, FALSE);
3567 tlbl3 = newiTempLabel (NULL);
3568 emitcode ("dec", "1,s");
3570 emitBranch ("bne", tlbl3);
3572 emitBranch ("beq", tlbl3);
3574 rmwWithReg ("neg", hc08_reg_a);
3577 tlbl4 = newiTempLabel (NULL);
3578 emitBranch ("bcc", tlbl4);
3579 rmwWithReg ("inc", hc08_reg_x);
3581 rmwWithReg ("neg", hc08_reg_x);
3586 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3587 hc08_freeReg (hc08_reg_xa);
3591 /*-----------------------------------------------------------------*/
3592 /* genMult - generates code for multiplication */
3593 /*-----------------------------------------------------------------*/
3595 genMult (iCode * ic)
3597 operand *left = IC_LEFT (ic);
3598 operand *right = IC_RIGHT (ic);
3599 operand *result = IC_RESULT (ic);
3601 D(emitcode ("; genMult",""));
3603 /* assign the amsops */
3604 aopOp (left, ic, FALSE);
3605 aopOp (right, ic, FALSE);
3606 aopOp (result, ic, TRUE);
3608 /* special cases first */
3609 /* if both are of size == 1 */
3610 // if (getSize(operandType(left)) == 1 &&
3611 // getSize(operandType(right)) == 1)
3612 if (AOP_SIZE (left) == 1 &&
3613 AOP_SIZE (right) == 1)
3615 genMultOneByte (left, right, result);
3619 /* should have been converted to function call */
3620 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3621 getSize(OP_SYMBOL(right)->type));
3622 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3627 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3628 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3629 freeAsmop (result, NULL, ic, TRUE);
3632 /*-----------------------------------------------------------------*/
3633 /* genDivOneByte : 8 bit division */
3634 /*-----------------------------------------------------------------*/
3636 genDivOneByte (operand * left,
3640 sym_link *opetype = operandType (result);
3642 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3644 bool negLiteral = FALSE;
3646 D(emitcode ("; genDivOneByte",""));
3648 size = AOP_SIZE (result);
3649 /* signed or unsigned */
3650 if (SPEC_USIGN (opetype))
3652 /* unsigned is easy */
3653 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3654 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3655 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3656 emitcode ("div", "");
3657 hc08_dirtyReg (hc08_reg_a, FALSE);
3658 hc08_dirtyReg (hc08_reg_h, FALSE);
3659 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3660 hc08_freeReg (hc08_reg_a);
3661 hc08_freeReg (hc08_reg_x);
3662 hc08_freeReg (hc08_reg_h);
3666 /* signed is a little bit more difficult */
3669 emitcode ("clr", "1,s");
3671 tlbl1 = newiTempLabel (NULL);
3672 tlbl2 = newiTempLabel (NULL);
3673 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3674 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3675 emitBranch ("bpl", tlbl1);
3676 emitcode ("inc", "1,s");
3677 rmwWithReg ("neg", hc08_reg_a);
3678 emitBranch ("bcc", tlbl2);
3679 rmwWithReg ("inc", hc08_reg_x);
3681 rmwWithReg ("neg", hc08_reg_x);
3682 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3685 if (AOP_TYPE(right)==AOP_LIT)
3687 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3688 /* AND literal negative */
3690 emitcode ("ldx", "#0x%02x", -val);
3693 emitcode ("ldx", "#0x%02x", val);
3695 hc08_useReg (hc08_reg_x);
3699 tlbl3 = newiTempLabel (NULL);
3700 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3701 emitBranch ("bpl", tlbl3);
3702 emitcode ("inc", "1,s");
3703 rmwWithReg ("neg", hc08_reg_x);
3707 emitcode ("div", "");
3708 hc08_dirtyReg (hc08_reg_x, FALSE);
3709 hc08_dirtyReg (hc08_reg_a, FALSE);
3710 hc08_dirtyReg (hc08_reg_h, FALSE);
3712 tlbl4 = newiTempLabel (NULL);
3713 emitcode ("dec", "1,s");
3715 emitBranch ("bne", tlbl4);
3717 emitBranch ("beq", tlbl4);
3718 rmwWithReg ("neg", hc08_reg_a);
3722 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3723 hc08_freeReg (hc08_reg_a);
3724 hc08_freeReg (hc08_reg_x);
3725 hc08_freeReg (hc08_reg_h);
3730 /*-----------------------------------------------------------------*/
3731 /* genDiv - generates code for division */
3732 /*-----------------------------------------------------------------*/
3736 operand *left = IC_LEFT (ic);
3737 operand *right = IC_RIGHT (ic);
3738 operand *result = IC_RESULT (ic);
3740 D(emitcode ("; genDiv",""));
3742 /* assign the amsops */
3743 aopOp (left, ic, FALSE);
3744 aopOp (right, ic, FALSE);
3745 aopOp (result, ic, TRUE);
3747 /* special cases first */
3748 /* if both are of size == 1 */
3749 if (AOP_SIZE (left) <= 2 &&
3750 AOP_SIZE (right) == 1)
3752 genDivOneByte (left, right, result);
3756 /* should have been converted to function call */
3759 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3760 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3761 freeAsmop (result, NULL, ic, TRUE);
3764 /*-----------------------------------------------------------------*/
3765 /* genModOneByte : 8 bit modulus */
3766 /*-----------------------------------------------------------------*/
3768 genModOneByte (operand * left,
3772 sym_link *opetype = operandType (result);
3774 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3776 bool negLiteral = FALSE;
3778 D(emitcode ("; genModOneByte",""));
3780 size = AOP_SIZE (result);
3781 /* signed or unsigned */
3782 if (SPEC_USIGN (opetype))
3784 /* unsigned is easy */
3785 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3786 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3787 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3788 emitcode ("div", "");
3789 hc08_dirtyReg (hc08_reg_a, FALSE);
3790 hc08_dirtyReg (hc08_reg_h, FALSE);
3791 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3792 hc08_freeReg (hc08_reg_a);
3793 hc08_freeReg (hc08_reg_x);
3794 hc08_freeReg (hc08_reg_h);
3798 /* signed is a little bit more difficult */
3801 emitcode ("clr", "1,s");
3803 tlbl1 = newiTempLabel (NULL);
3804 tlbl2 = newiTempLabel (NULL);
3805 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3806 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3807 emitBranch ("bpl", tlbl1);
3808 emitcode ("inc", "1,s");
3809 rmwWithReg ("neg", hc08_reg_a);
3810 emitBranch ("bcc", tlbl2);
3811 rmwWithReg ("inc", hc08_reg_x);
3813 rmwWithReg ("neg", hc08_reg_x);
3814 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3817 if (AOP_TYPE(right)==AOP_LIT)
3819 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3820 /* AND literal negative */
3822 emitcode ("ldx", "#0x%02x", -val);
3825 emitcode ("ldx", "#0x%02x", val);
3827 hc08_useReg (hc08_reg_x);
3831 tlbl3 = newiTempLabel (NULL);
3832 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3833 emitBranch ("bpl", tlbl3);
3834 emitcode ("inc", "1,s");
3835 rmwWithReg ("neg", hc08_reg_x);
3839 emitcode ("div", "");
3840 hc08_dirtyReg (hc08_reg_x, FALSE);
3841 hc08_dirtyReg (hc08_reg_a, FALSE);
3842 hc08_dirtyReg (hc08_reg_h, FALSE);
3844 tlbl4 = newiTempLabel (NULL);
3845 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3846 emitcode ("dec", "1,s");
3848 emitBranch ("bne", tlbl4);
3850 emitBranch ("beq", tlbl4);
3851 rmwWithReg ("neg", hc08_reg_a);
3855 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3856 hc08_freeReg (hc08_reg_a);
3857 hc08_freeReg (hc08_reg_x);
3858 hc08_freeReg (hc08_reg_h);
3862 /*-----------------------------------------------------------------*/
3863 /* genMod - generates code for division */
3864 /*-----------------------------------------------------------------*/
3868 operand *left = IC_LEFT (ic);
3869 operand *right = IC_RIGHT (ic);
3870 operand *result = IC_RESULT (ic);
3872 D(emitcode ("; genMod",""));
3874 /* assign the amsops */
3875 aopOp (left, ic, FALSE);
3876 aopOp (right, ic, FALSE);
3877 aopOp (result, ic, TRUE);
3879 /* special cases first */
3880 /* if both are of size == 1 */
3881 if (AOP_SIZE (left) <= 2 &&
3882 AOP_SIZE (right) == 1)
3884 genModOneByte (left, right, result);
3888 /* should have been converted to function call */
3892 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3893 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3894 freeAsmop (result, NULL, ic, TRUE);
3897 /*-----------------------------------------------------------------*/
3898 /* genIfxJump :- will create a jump depending on the ifx */
3899 /*-----------------------------------------------------------------*/
3901 genIfxJump (iCode * ic, char *jval)
3904 symbol *tlbl = newiTempLabel (NULL);
3907 D(emitcode ("; genIfxJump",""));
3909 /* if true label then we jump if condition
3913 jlbl = IC_TRUE (ic);
3914 if (!strcmp (jval, "a"))
3916 else if (!strcmp (jval, "c"))
3923 /* false label is present */
3924 jlbl = IC_FALSE (ic);
3925 if (!strcmp (jval, "a"))
3927 else if (!strcmp (jval, "c"))
3932 emitBranch (inst, tlbl);
3933 emitBranch ("jmp", jlbl);
3936 /* mark the icode as generated */
3940 /*-----------------------------------------------------------------*/
3941 /* genCmp :- greater or less than comparison */
3942 /*-----------------------------------------------------------------*/
3944 genCmp (operand * left, operand * right,
3945 operand * result, iCode * ifx, int sign, iCode *ic)
3947 int size, offset = 0;
3948 unsigned long lit = 0L;
3950 bool needpula = FALSE;
3952 D(emitcode ("; genCmp",""));
3954 /* subtract right from left if at the
3955 end the carry flag is set then we know that
3956 left is greater than right */
3957 size = max (AOP_SIZE (left), AOP_SIZE (right));
3959 if (AOP_TYPE (right) == AOP_LIT)
3961 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3962 /* optimize if(x < 0) or if(x >= 0) */
3971 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3972 emitcode ("rola", "");
3973 hc08_useReg (hc08_reg_a);
3981 && ((AOP_TYPE (right) == AOP_LIT) ||
3982 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3983 && hc08_reg_hx->isFree)
3985 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3986 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3987 hc08_freeReg (hc08_reg_hx);
3998 loadRegFromAop (hc08_reg_a, AOP (left), offset);
3999 accopWithAop (sub, AOP (right), offset);
4000 hc08_freeReg (hc08_reg_a);
4006 freeAsmop (right, NULL, ic, TRUE);
4007 freeAsmop (left, NULL, ic, TRUE);
4008 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4014 /* if the result is used in the next
4015 ifx conditional branch then generate
4016 code a little differently */
4019 pullOrFreeReg(hc08_reg_a,needpula);
4020 genIfxJump (ifx, sign ? "s" : "c");
4027 pullOrFreeReg(hc08_reg_a,needpula);
4031 /*-----------------------------------------------------------------*/
4032 /* genCmpGt :- greater than comparison */
4033 /*-----------------------------------------------------------------*/
4035 genCmpGt (iCode * ic, iCode * ifx)
4037 operand *left, *right, *result;
4038 sym_link *letype, *retype;
4041 D(emitcode ("; genCmpGt",""));
4043 result = IC_RESULT (ic);
4044 left = IC_LEFT (ic);
4045 right = IC_RIGHT (ic);
4047 letype = getSpec (operandType (left));
4048 retype = getSpec (operandType (right));
4049 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4050 /* assign the amsops */
4051 aopOp (left, ic, FALSE);
4052 aopOp (right, ic, FALSE);
4053 aopOp (result, ic, TRUE);
4055 genCmp (right, left, result, ifx, sign,ic);
4057 freeAsmop (result, NULL, ic, TRUE);
4060 /*-----------------------------------------------------------------*/
4061 /* genCmpLt - less than comparisons */
4062 /*-----------------------------------------------------------------*/
4064 genCmpLt (iCode * ic, iCode * ifx)
4066 operand *left, *right, *result;
4067 sym_link *letype, *retype;
4070 D(emitcode ("; genCmpLt",""));
4072 result = IC_RESULT (ic);
4073 left = IC_LEFT (ic);
4074 right = IC_RIGHT (ic);
4076 letype = getSpec (operandType (left));
4077 retype = getSpec (operandType (right));
4078 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4080 /* assign the amsops */
4081 aopOp (left, ic, FALSE);
4082 aopOp (right, ic, FALSE);
4083 aopOp (result, ic, TRUE);
4085 genCmp (left, right, result, ifx, sign,ic);
4087 freeAsmop (result, NULL, ic, TRUE);
4090 /*-----------------------------------------------------------------*/
4091 /* - compare and branch if not equal */
4092 /*-----------------------------------------------------------------*/
4094 gencbneshort (operand * left, operand * right, symbol * lbl)
4096 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4098 unsigned long lit = 0L;
4100 /* if the left side is a literal or
4101 if the right is in a pointer register and left
4103 if (AOP_TYPE (left) == AOP_LIT)
4109 if (AOP_TYPE (right) == AOP_LIT)
4110 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4114 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4115 accopWithAop ("cmp", AOP (right), offset);
4116 hc08_useReg (hc08_reg_a);
4117 hc08_freeReg (hc08_reg_a);
4118 emitBranch ("bne", lbl);
4124 /*-----------------------------------------------------------------*/
4125 /* gencjne - compare and jump if not equal */
4126 /*-----------------------------------------------------------------*/
4128 gencjne (operand * left, operand * right, symbol * lbl)
4130 symbol *tlbl = newiTempLabel (NULL);
4132 gencbneshort (left, right, lbl);
4134 loadRegFromConst (hc08_reg_a, one);
4135 emitBranch ("bra", tlbl);
4137 loadRegFromConst (hc08_reg_a, zero);
4140 hc08_useReg(hc08_reg_a);
4141 hc08_freeReg(hc08_reg_a);
4144 /*-----------------------------------------------------------------*/
4145 /* genCmpEq - generates code for equal to */
4146 /*-----------------------------------------------------------------*/
4148 genCmpEq (iCode * ic, iCode * ifx)
4150 operand *left, *right, *result;
4152 D(emitcode ("; genCmpEq",""));
4154 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4155 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4156 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4158 /* if literal, literal on the right or
4159 if the right is in a pointer register and left
4161 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4163 operand *t = IC_RIGHT (ic);
4164 IC_RIGHT (ic) = IC_LEFT (ic);
4168 if (ifx && !AOP_SIZE (result))
4171 tlbl = newiTempLabel (NULL);
4172 gencbneshort (left, right, tlbl);
4175 emitBranch ("jmp", IC_TRUE (ifx));
4180 symbol *lbl = newiTempLabel (NULL);
4181 emitBranch ("bra", lbl);
4183 emitBranch ("jmp", IC_FALSE (ifx));
4187 /* mark the icode as generated */
4192 gencjne (left, right, newiTempLabel (NULL));
4193 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4195 storeRegToAop (hc08_reg_a, AOP (result), 0);
4200 genIfxJump (ifx, "a");
4203 /* if the result is used in an arithmetic operation
4204 then put the result in place */
4205 if (AOP_TYPE (result) != AOP_CRY)
4209 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4210 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4211 freeAsmop (result, NULL, ic, TRUE);
4214 /*-----------------------------------------------------------------*/
4215 /* ifxForOp - returns the icode containing the ifx for operand */
4216 /*-----------------------------------------------------------------*/
4218 ifxForOp (operand * op, iCode * ic)
4220 /* if true symbol then needs to be assigned */
4221 if (IS_TRUE_SYMOP (op))
4224 /* if this has register type condition and
4225 the next instruction is ifx with the same operand
4226 and live to of the operand is upto the ifx only then */
4228 ic->next->op == IFX &&
4229 IC_COND (ic->next)->key == op->key &&
4230 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4237 genPointerGetSetOfs (iCode *ic)
4239 iCode *lic = ic->next;
4245 /* Make sure we have a next iCode */
4246 D(emitcode("","; checking lic"));
4250 /* Make sure the result of the addition is an iCode */
4251 D(emitcode("","; checking IS_ITEMP"));
4252 if (!IS_ITEMP (IC_RESULT (ic)))
4255 /* Make sure the next iCode is a pointer set or get */
4256 pset = POINTER_SET(lic);
4257 pget = POINTER_GET(lic);
4258 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4262 /* Make sure this is the only use of the pointer */
4263 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4266 D(emitcode("", "; checking pset operandsEqu"));
4267 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4270 D(emitcode("", "; checking pget operandsEqu"));
4271 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4274 D(emitcode("", "; checking IS_SYMOP"));
4275 if (!IS_SYMOP (IC_LEFT (ic)))
4278 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4279 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4282 sym = OP_SYMBOL (IC_LEFT (ic));
4284 D(emitcode("", "; checking remat"));
4291 D(emitcode ("; genPointerGetOfs",""));
4292 aopOp (IC_LEFT(ic), ic, FALSE);
4293 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4294 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4296 aopOp (IC_RIGHT(ic), ic, FALSE);
4297 aopOp (IC_RESULT(lic), lic, FALSE);
4299 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4301 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4303 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4304 loadRegFromConst (hc08_reg_h, zero);
4308 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4309 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4310 emitcode ("rola","");
4311 emitcode ("clra","");
4312 emitcode ("sbc", "#0");
4313 hc08_useReg (hc08_reg_a);
4314 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4318 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4319 size = AOP_SIZE (IC_RESULT(lic));
4320 derefaop->size = size;
4325 emitcode ("lda", "%s,x",
4326 aopAdrStr (derefaop, offset, TRUE));
4327 hc08_useReg (hc08_reg_a);
4328 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4329 hc08_freeReg (hc08_reg_a);
4333 hc08_freeReg (hc08_reg_hx);
4335 freeAsmop (NULL, derefaop, ic, TRUE);
4336 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4337 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4344 D(emitcode ("; genPointerSetOfs",""));
4345 aopOp (IC_LEFT(ic), ic, FALSE);
4346 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4347 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4349 aopOp (IC_RIGHT(ic), ic, FALSE);
4350 aopOp (IC_RIGHT(lic), lic, FALSE);
4352 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4354 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4356 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4357 loadRegFromConst (hc08_reg_h, zero);
4361 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4362 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4363 emitcode ("rola","");
4364 emitcode ("clra","");
4365 emitcode ("sbc", "#0");
4366 hc08_useReg (hc08_reg_a);
4367 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4371 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4372 size = AOP_SIZE (IC_RIGHT(lic));
4373 derefaop->size = size;
4378 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4379 emitcode ("sta", "%s,x",
4380 aopAdrStr (derefaop, offset, TRUE));
4381 hc08_freeReg (hc08_reg_a);
4386 hc08_freeReg (hc08_reg_hx);
4388 freeAsmop (NULL, derefaop, ic, TRUE);
4389 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4390 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4399 /*-----------------------------------------------------------------*/
4400 /* hasInc - operand is incremented before any other use */
4401 /*-----------------------------------------------------------------*/
4403 hasInc (operand *op, iCode *ic,int osize)
4405 sym_link *type = operandType(op);
4406 sym_link *retype = getSpec (type);
4407 iCode *lic = ic->next;
4410 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4411 if (!IS_SYMOP(op)) return NULL;
4413 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4414 if (IS_AGGREGATE(type->next)) return NULL;
4415 if (osize != (isize = getSize(type->next))) return NULL;
4418 /* if operand of the form op = op + <sizeof *op> */
4419 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4420 isOperandEqual(IC_RESULT(lic),op) &&
4421 isOperandLiteral(IC_RIGHT(lic)) &&
4422 operandLitValue(IC_RIGHT(lic)) == isize) {
4425 /* if the operand used or deffed */
4426 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4429 /* if GOTO or IFX */
4430 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4436 /*-----------------------------------------------------------------*/
4437 /* genAndOp - for && operation */
4438 /*-----------------------------------------------------------------*/
4440 genAndOp (iCode * ic)
4442 operand *left, *right, *result;
4443 symbol *tlbl, *tlbl0;
4445 D(emitcode ("; genAndOp",""));
4447 /* note here that && operations that are in an
4448 if statement are taken away by backPatchLabels
4449 only those used in arthmetic operations remain */
4450 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4451 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4452 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4454 tlbl = newiTempLabel (NULL);
4455 tlbl0 = newiTempLabel (NULL);
4457 asmopToBool (AOP (left), FALSE);
4458 emitBranch ("beq", tlbl0);
4459 asmopToBool (AOP (right), FALSE);
4460 emitBranch ("beq", tlbl0);
4461 loadRegFromConst (hc08_reg_a,one);
4462 emitBranch ("bra", tlbl);
4464 loadRegFromConst (hc08_reg_a,zero);
4467 hc08_useReg (hc08_reg_a);
4468 hc08_freeReg (hc08_reg_a);
4470 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4472 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4473 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4474 freeAsmop (result, NULL, ic, TRUE);
4478 /*-----------------------------------------------------------------*/
4479 /* genOrOp - for || operation */
4480 /*-----------------------------------------------------------------*/
4482 genOrOp (iCode * ic)
4484 operand *left, *right, *result;
4485 symbol *tlbl, *tlbl0;
4487 D(emitcode ("; genOrOp",""));
4489 /* note here that || operations that are in an
4490 if statement are taken away by backPatchLabels
4491 only those used in arthmetic operations remain */
4492 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4493 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4494 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4496 tlbl = newiTempLabel (NULL);
4497 tlbl0 = newiTempLabel (NULL);
4499 asmopToBool (AOP (left), FALSE);
4500 emitBranch ("bne", tlbl0);
4501 asmopToBool (AOP (right), FALSE);
4502 emitBranch ("bne", tlbl0);
4503 loadRegFromConst (hc08_reg_a,zero);
4504 emitBranch ("bra", tlbl);
4506 loadRegFromConst (hc08_reg_a,one);
4509 hc08_useReg (hc08_reg_a);
4510 hc08_freeReg (hc08_reg_a);
4512 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4515 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4517 freeAsmop (result, NULL, ic, TRUE);
4520 /*-----------------------------------------------------------------*/
4521 /* isLiteralBit - test if lit == 2^n */
4522 /*-----------------------------------------------------------------*/
4524 isLiteralBit (unsigned long lit)
4526 unsigned long pw[32] =
4527 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4528 0x100L, 0x200L, 0x400L, 0x800L,
4529 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4530 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4531 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4532 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4533 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4536 for (idx = 0; idx < 32; idx++)
4543 /*-----------------------------------------------------------------*/
4544 /* continueIfTrue - */
4545 /*-----------------------------------------------------------------*/
4547 continueIfTrue (iCode * ic)
4550 emitBranch ("jmp", IC_TRUE (ic));
4554 /*-----------------------------------------------------------------*/
4556 /*-----------------------------------------------------------------*/
4558 jumpIfTrue (iCode * ic)
4561 emitBranch ("jmp", IC_FALSE (ic));
4565 /*-----------------------------------------------------------------*/
4566 /* jmpTrueOrFalse - */
4567 /*-----------------------------------------------------------------*/
4569 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4571 // ugly but optimized by peephole
4574 symbol *nlbl = newiTempLabel (NULL);
4575 emitBranch ("bra", nlbl);
4577 emitBranch ("jmp", IC_TRUE (ic));
4582 emitBranch ("jmp", IC_FALSE (ic));
4589 /*-----------------------------------------------------------------*/
4590 /* genAnd - code for and */
4591 /*-----------------------------------------------------------------*/
4593 genAnd (iCode * ic, iCode * ifx)
4595 operand *left, *right, *result;
4596 int size, offset = 0;
4597 unsigned long lit = 0L;
4598 unsigned long litinv;
4604 D(emitcode ("; genAnd",""));
4606 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4607 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4608 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4611 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4613 AOP_TYPE (left), AOP_TYPE (right)));
4614 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4616 AOP_SIZE (left), AOP_SIZE (right)));
4619 /* if left is a literal & right is not then exchange them */
4620 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4622 operand *tmp = right;
4627 /* if left is accumulator & right is not then exchange them */
4628 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4630 operand *tmp = right;
4636 if (AOP_TYPE (result) == AOP_CRY)
4639 wassertl (ifx, "AOP_CPY result without ifx");
4641 tlbl = newiTempLabel (NULL);
4642 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4646 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4647 if ((AOP_TYPE (right) == AOP_LIT)
4648 && (((lit >> (offset*8)) & 0xff) == 0xff))
4649 emitcode ("tsta","");
4651 accopWithAop ("and", AOP (right), offset);
4652 hc08_freeReg( hc08_reg_a);
4654 emitBranch ("bne", tlbl);
4658 genIfxJump (ifx, "a");
4664 size = AOP_SIZE (result);
4666 if (AOP_TYPE (right) == AOP_LIT)
4668 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4669 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4671 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4672 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4674 int bitpos = isLiteralBit(litinv)-1;
4675 emitcode ("bclr","#%d,%s",bitpos & 7,
4676 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4684 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4685 if ((AOP_TYPE (right) != AOP_LIT)
4686 || (((lit >> (offset*8)) & 0xff) != 0xff))
4687 accopWithAop ("and", AOP (right), offset);
4688 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4689 hc08_freeReg( hc08_reg_a);
4693 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4694 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4695 freeAsmop (result, NULL, ic, TRUE);
4698 /*-----------------------------------------------------------------*/
4699 /* genOr - code for or */
4700 /*-----------------------------------------------------------------*/
4702 genOr (iCode * ic, iCode * ifx)
4704 operand *left, *right, *result;
4705 int size, offset = 0;
4706 unsigned long lit = 0L;
4708 D(emitcode ("; genOr",""));
4710 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4711 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4712 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4715 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4717 AOP_TYPE (left), AOP_TYPE (right)));
4718 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4720 AOP_SIZE (left), AOP_SIZE (right)));
4723 /* if left is a literal & right is not then exchange them */
4724 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4726 operand *tmp = right;
4731 /* if left is accumulator & right is not then exchange them */
4732 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4734 operand *tmp = right;
4739 if (AOP_TYPE (result) == AOP_CRY)
4742 wassertl (ifx, "AOP_CPY result without ifx");
4744 tlbl = newiTempLabel (NULL);
4745 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4749 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4750 if ((AOP_TYPE (right) == AOP_LIT)
4751 && (((lit >> (offset*8)) & 0xff) == 0))
4752 emitcode ("tsta","");
4754 accopWithAop ("ora", AOP (right), offset);
4755 hc08_freeReg( hc08_reg_a);
4757 emitBranch ("bne", tlbl);
4761 genIfxJump (ifx, "a");
4767 if (AOP_TYPE (right) == AOP_LIT)
4768 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4770 size = AOP_SIZE (result);
4772 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4773 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4774 (AOP_TYPE (left) == AOP_DIR))
4776 int bitpos = isLiteralBit(lit)-1;
4777 emitcode ("bset","#%d,%s",bitpos & 7,
4778 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4785 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4786 accopWithAop ("ora", AOP (right), offset);
4787 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4788 hc08_freeReg( hc08_reg_a);
4793 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4794 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4795 freeAsmop (result, NULL, ic, TRUE);
4798 /*-----------------------------------------------------------------*/
4799 /* genXor - code for xclusive or */
4800 /*-----------------------------------------------------------------*/
4802 genXor (iCode * ic, iCode * ifx)
4804 operand *left, *right, *result;
4805 int size, offset = 0;
4806 unsigned long lit = 0L;
4808 D(emitcode ("; genXor",""));
4810 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4811 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4812 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4815 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4817 AOP_TYPE (left), AOP_TYPE (right)));
4818 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4820 AOP_SIZE (left), AOP_SIZE (right)));
4823 /* if left is a literal & right is not ||
4824 if left needs acc & right does not */
4825 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4827 operand *tmp = right;
4832 /* if left is accumulator & right is not then exchange them */
4833 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4835 operand *tmp = right;
4840 if (AOP_TYPE (result) == AOP_CRY)
4843 wassertl (ifx, "AOP_CPY result without ifx");
4845 tlbl = newiTempLabel (NULL);
4846 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4850 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4851 if ((AOP_TYPE (right) == AOP_LIT)
4852 && (((lit >> (offset*8)) & 0xff) == 0))
4853 emitcode ("tsta","");
4855 accopWithAop ("eor", AOP (right), offset);
4856 hc08_freeReg( hc08_reg_a);
4858 emitBranch ("bne", tlbl);
4862 genIfxJump (ifx, "a");
4868 if (AOP_TYPE (right) == AOP_LIT)
4869 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4871 size = AOP_SIZE (result);
4875 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4876 accopWithAop ("eor", AOP (right), offset);
4877 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4878 hc08_freeReg( hc08_reg_a);
4882 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4883 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4884 freeAsmop (result, NULL, ic, TRUE);
4888 emitinline (iCode * ic, char *inlin)
4894 symbol *sym, *tempsym;
4903 while (isalnum(*inlin) || (*inlin == '_'))
4907 //printf("Found possible symbol '%s'\n",symname);
4908 tempsym = newSymbol (symname, ic->level);
4909 tempsym->block = ic->block;
4910 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4919 aop = aopForSym (ic, sym, FALSE);
4920 l = aopAdrStr (aop, aop->size - 1, TRUE);
4924 if (!sym->allocreq && !sym->ismyparm)
4926 werror (E_ID_UNDEF, sym->name);
4928 " Add 'volatile' to the variable declaration so that it\n"
4929 " can be referenced within inline assembly");
4931 //printf("Replacing with '%s'\n",l);
4935 if ((2+bp-buffer)>sizeof(buffer))
4944 if ((2+bp-buffer)>sizeof(buffer))
4951 if ((2+bp-buffer)>sizeof(buffer))
4952 fprintf(stderr, "Inline assembly buffer overflow\n");
4954 //printf("%s\n",buffer);
4955 emitcode (buffer,"");
4959 /*-----------------------------------------------------------------*/
4960 /* genInline - write the inline code out */
4961 /*-----------------------------------------------------------------*/
4963 genInline (iCode * ic)
4965 char *buffer, *bp, *bp1;
4967 D(emitcode ("; genInline",""));
4969 _G.inLine += (!options.asmpeep);
4971 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4972 strcpy (buffer, IC_INLINE (ic));
4974 /* emit each line as a code */
4980 /* emitcode (bp1, ""); */
4981 emitinline (ic, bp1);
5000 /* emitcode (bp1, ""); */
5001 emitinline (ic, bp1);
5003 /* emitcode("",buffer); */
5004 _G.inLine -= (!options.asmpeep);
5007 /*-----------------------------------------------------------------*/
5008 /* genRRC - rotate right with carry */
5009 /*-----------------------------------------------------------------*/
5013 operand *left, *result;
5014 int size, offset = 0;
5015 bool needpula = FALSE;
5016 bool resultInA = FALSE;
5019 D(emitcode ("; genRRC",""));
5021 /* rotate right with carry */
5022 left = IC_LEFT (ic);
5023 result = IC_RESULT (ic);
5024 aopOp (left, ic, FALSE);
5025 aopOp (result, ic, FALSE);
5027 if ((AOP_TYPE (result) == AOP_REG)
5028 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5031 size = AOP_SIZE (result);
5035 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5039 rmwWithAop (shift, AOP (result), offset--);
5047 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5048 rmwWithReg (shift, hc08_reg_a);
5049 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5050 hc08_freeReg (hc08_reg_a);
5055 if ((!hc08_reg_a->isFree) || resultInA)
5057 pushReg (hc08_reg_a, TRUE);
5061 /* now we need to put the carry into the
5062 highest order byte of the result */
5063 offset = AOP_SIZE (result) - 1;
5064 emitcode ("clra","");
5065 emitcode ("rora","");
5066 hc08_dirtyReg (hc08_reg_a, FALSE);
5069 emitcode ("ora", "1,s");
5070 emitcode ("ais", "#1");
5071 hc08_dirtyReg (hc08_reg_a, FALSE);
5075 accopWithAop ("ora", AOP (result), offset);
5076 storeRegToAop (hc08_reg_a, AOP (result), offset);
5078 pullOrFreeReg (hc08_reg_a, needpula);
5080 freeAsmop (left, NULL, ic, TRUE);
5081 freeAsmop (result, NULL, ic, TRUE);
5084 /*-----------------------------------------------------------------*/
5085 /* genRLC - generate code for rotate left with carry */
5086 /*-----------------------------------------------------------------*/
5090 operand *left, *result;
5091 int size, offset = 0;
5093 bool resultInA = FALSE;
5094 bool needpula = FALSE;
5096 D(emitcode ("; genRLC",""));
5098 /* rotate right with carry */
5099 left = IC_LEFT (ic);
5100 result = IC_RESULT (ic);
5101 aopOp (left, ic, FALSE);
5102 aopOp (result, ic, FALSE);
5104 if ((AOP_TYPE (result) == AOP_REG)
5105 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5108 size = AOP_SIZE (result);
5112 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5116 rmwWithAop (shift, AOP (result), offset--);
5124 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5125 rmwWithReg (shift, hc08_reg_a);
5126 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5127 hc08_freeReg (hc08_reg_a);
5132 if ((!hc08_reg_a->isFree) || resultInA)
5134 pushReg (hc08_reg_a, TRUE);
5138 /* now we need to put the carry into the
5139 lowest order byte of the result */
5141 emitcode ("clra","");
5142 emitcode ("rola","");
5143 hc08_dirtyReg (hc08_reg_a, FALSE);
5146 emitcode ("ora", "1,s");
5147 emitcode ("ais", "#1");
5148 hc08_dirtyReg (hc08_reg_a, FALSE);
5152 accopWithAop ("ora", AOP (result), offset);
5153 storeRegToAop (hc08_reg_a, AOP (result), offset);
5155 pullOrFreeReg (hc08_reg_a, needpula);
5157 freeAsmop (left, NULL, ic, TRUE);
5158 freeAsmop (result, NULL, ic, TRUE);
5161 /*-----------------------------------------------------------------*/
5162 /* genGetHbit - generates code get highest order bit */
5163 /*-----------------------------------------------------------------*/
5165 genGetHbit (iCode * ic)
5167 operand *left, *result;
5169 D(emitcode ("; genGetHbit",""));
5171 left = IC_LEFT (ic);
5172 result = IC_RESULT (ic);
5173 aopOp (left, ic, FALSE);
5174 aopOp (result, ic, FALSE);
5176 /* get the highest order byte into a */
5177 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5178 emitcode ("rola", "");
5179 emitcode ("clra", "");
5180 emitcode ("rola", "");
5181 hc08_dirtyReg (hc08_reg_a, FALSE);
5182 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5183 hc08_freeReg (hc08_reg_a);
5185 freeAsmop (left, NULL, ic, TRUE);
5186 freeAsmop (result, NULL, ic, TRUE);
5189 /*-----------------------------------------------------------------*/
5190 /* genSwap - generates code to swap nibbles or bytes */
5191 /*-----------------------------------------------------------------*/
5193 genSwap (iCode * ic)
5195 operand *left, *result;
5197 D(emitcode ("; genSwap",""));
5199 left = IC_LEFT (ic);
5200 result = IC_RESULT (ic);
5201 aopOp (left, ic, FALSE);
5202 aopOp (result, ic, FALSE);
5204 switch (AOP_SIZE (left))
5206 case 1: /* swap nibbles in byte */
5207 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5208 emitcode ("nsa", "");
5209 hc08_dirtyReg (hc08_reg_a, FALSE);
5210 storeRegToAop (hc08_reg_a, AOP (result), 0);
5211 hc08_freeReg (hc08_reg_a);
5213 case 2: /* swap bytes in a word */
5214 if (operandsEqu (left, result))
5216 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5217 hc08_useReg (hc08_reg_a);
5218 transferAopAop (AOP (left), 1, AOP (result), 0);
5219 storeRegToAop (hc08_reg_a, AOP (result), 1);
5220 hc08_freeReg (hc08_reg_a);
5224 transferAopAop (AOP (left), 0, AOP (result), 1);
5225 transferAopAop (AOP (left), 1, AOP (result), 0);
5229 wassertl(FALSE, "unsupported SWAP operand size");
5232 freeAsmop (left, NULL, ic, TRUE);
5233 freeAsmop (result, NULL, ic, TRUE);
5237 /*-----------------------------------------------------------------*/
5238 /* AccRol - rotate left accumulator by known count */
5239 /*-----------------------------------------------------------------*/
5241 AccRol (int shCount)
5243 shCount &= 0x0007; // shCount : 0..7
5250 emitcode ("rola", ""); /* 1 cycle */
5253 emitcode ("rola", ""); /* 1 cycle */
5254 emitcode ("rola", ""); /* 1 cycle */
5257 emitcode ("nsa", "");
5258 emitcode ("rora", "");
5261 emitcode ("nsa", ""); /* 3 cycles */
5264 emitcode ("nsa", ""); /* 3 cycles */
5265 emitcode ("rola", ""); /* 1 cycle */
5268 emitcode ("nsa", ""); /* 3 cycles */
5269 emitcode ("rola", ""); /* 1 cycle */
5270 emitcode ("rola", ""); /* 1 cycle */
5273 emitcode ("nsa", ""); /* 3 cycles */
5274 emitcode ("rola", ""); /* 1 cycle */
5275 emitcode ("rola", ""); /* 1 cycle */
5276 emitcode ("rola", ""); /* 1 cycle */
5283 /*-----------------------------------------------------------------*/
5284 /* AccLsh - left shift accumulator by known count */
5285 /*-----------------------------------------------------------------*/
5287 AccLsh (int shCount)
5291 shCount &= 0x0007; // shCount : 0..7
5293 /* Shift counts of 4 and 5 are currently optimized for code size. */
5294 /* Falling through to the unrolled loop would be optimal for code speed. */
5295 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5299 accopWithMisc ("nsa", "");
5300 accopWithMisc ("and", "#0xf0");
5301 /* total: 5 cycles, 3 bytes */
5304 accopWithMisc ("nsa", "");
5305 accopWithMisc ("and", "#0xf0");
5306 accopWithMisc ("lsla", "");
5307 /* total: 6 cycles, 4 bytes */
5310 accopWithMisc ("rora", "");
5311 accopWithMisc ("rora", "");
5312 accopWithMisc ("rora", "");
5313 accopWithMisc ("and", "#0xc0");
5314 /* total: 5 cycles, 5 bytes */
5317 accopWithMisc ("rora", "");
5318 accopWithMisc ("clra", "");
5319 accopWithMisc ("rora", "");
5320 /* total: 3 cycles, 3 bytes */
5324 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5325 /* the fastest (shCount<6) and shortest (shCount<4). */
5326 for (i=0;i<shCount;i++)
5327 accopWithMisc ("lsla", "");
5331 /*-----------------------------------------------------------------*/
5332 /* AccSRsh - signed right shift accumulator by known count */
5333 /*-----------------------------------------------------------------*/
5335 AccSRsh (int shCount)
5339 shCount &= 0x0007; // shCount : 0..7
5343 accopWithMisc ("rola", "");
5344 accopWithMisc ("clra", "");
5345 accopWithMisc ("sbc", zero);
5346 /* total: 4 cycles, 4 bytes */
5350 for (i=0;i<shCount;i++)
5351 accopWithMisc ("asra", "");
5354 /*-----------------------------------------------------------------*/
5355 /* AccRsh - right shift accumulator by known count */
5356 /*-----------------------------------------------------------------*/
5358 AccRsh (int shCount, bool sign)
5368 shCount &= 0x0007; // shCount : 0..7
5370 /* Shift counts of 4 and 5 are currently optimized for code size. */
5371 /* Falling through to the unrolled loop would be optimal for code speed. */
5372 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5376 accopWithMisc ("nsa", "");
5377 accopWithMisc ("and", "#0x0f");
5378 /* total: 5 cycles, 3 bytes */
5381 accopWithMisc ("nsa", "");
5382 accopWithMisc ("and", "#0x0f");
5383 accopWithMisc ("lsra", "");
5384 /* total: 6 cycles, 4 bytes */
5387 accopWithMisc ("rola", "");
5388 accopWithMisc ("rola", "");
5389 accopWithMisc ("rola", "");
5390 accopWithMisc ("and", "#0x03");
5391 /* total: 5 cycles, 5 bytes */
5394 accopWithMisc ("rola", "");
5395 accopWithMisc ("clra", "");
5396 accopWithMisc ("rola", "");
5397 /* total: 3 cycles, 3 bytes */
5401 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5402 /* the fastest (shCount<6) and shortest (shCount<4). */
5403 for (i=0;i<shCount;i++)
5404 accopWithMisc ("lsra", "");
5408 /*-----------------------------------------------------------------*/
5409 /* XAccLsh - left shift register pair XA by known count */
5410 /*-----------------------------------------------------------------*/
5412 XAccLsh (int shCount)
5416 shCount &= 0x000f; // shCount : 0..15
5421 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5422 loadRegFromConst (hc08_reg_a, zero);
5426 /* if we can beat 2n cycles or bytes for some special case, do it here */
5430 /* bytes cycles reg x reg a carry
5431 ** abcd efgh ijkl mnop ?
5432 ** lsrx 1 1 0abc defg ijkl mnop h
5433 ** rora 1 1 0abc defg hijk lmno p
5434 ** tax 1 1 hijk lmno hijk lmno p
5435 ** clra 1 1 hijk lmno 0000 0000 p
5436 ** rora 1 1 hijk lmno p000 0000 0
5437 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5439 rmwWithReg ("lsr", hc08_reg_x);
5440 rmwWithReg ("ror", hc08_reg_a);
5441 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5442 loadRegFromConst (hc08_reg_a, zero);
5443 rmwWithReg ("ror", hc08_reg_a);
5450 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5451 /* the fastest and shortest. */
5452 for (i=0;i<shCount;i++)
5454 rmwWithReg ("lsl", hc08_reg_a);
5455 rmwWithReg ("rol", hc08_reg_x);
5459 /*-----------------------------------------------------------------*/
5460 /* XAccSRsh - signed right shift register pair XA by known count */
5461 /*-----------------------------------------------------------------*/
5463 XAccSRsh (int shCount)
5467 shCount &= 0x000f; // shCount : 0..7
5469 /* if we can beat 2n cycles or bytes for some special case, do it here */
5473 /* bytes cycles reg x reg a carry
5474 ** abcd efgh ijkl mnop ?
5475 ** lslx 1 1 bcde fgh0 ijkl mnop a
5476 ** clra 1 1 bcde fgh0 0000 0000 a
5477 ** rola 1 1 bcde fgh0 0000 000a 0
5478 ** nega 1 1 bcde fgh0 aaaa aaaa a
5479 ** tax 1 1 aaaa aaaa aaaa aaaa a
5480 ** total: 5 cycles, 5 bytes
5482 rmwWithReg ("lsl", hc08_reg_x);
5483 loadRegFromConst (hc08_reg_a, zero);
5484 rmwWithReg ("rol", hc08_reg_a);
5485 rmwWithReg ("neg", hc08_reg_a);
5486 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5496 /* bytes cycles reg x reg a carry
5497 ** abcd efgh ijkl mnop ?
5498 ** txa 1 1 abcd efgh abcd efgh ?
5499 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5500 ** lsla 1 1 abcd efgh ???? ???? a
5501 ** clrx 1 1 0000 0000 ???? ???? a
5502 ** rolx 1 1 0000 000a ???? ???? 0
5503 ** negx 1 1 aaaa aaaa ???? ???? a
5504 ** rora 1 1 aaaa aaaa LSBresult 0
5505 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5507 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5508 AccSRsh (shCount-8);
5509 rmwWithReg ("lsl", hc08_reg_a);
5510 loadRegFromConst (hc08_reg_x, zero);
5511 rmwWithReg ("rol", hc08_reg_x);
5512 rmwWithReg ("neg", hc08_reg_x);
5513 rmwWithReg ("ror", hc08_reg_a);
5520 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5521 /* the fastest and shortest. */
5522 for (i=0;i<shCount;i++)
5524 rmwWithReg ("asr", hc08_reg_x);
5525 rmwWithReg ("ror", hc08_reg_a);
5529 /*-----------------------------------------------------------------*/
5530 /* XAccRsh - right shift register pair XA by known count */
5531 /*-----------------------------------------------------------------*/
5533 XAccRsh (int shCount, bool sign)
5543 shCount &= 0x000f; // shCount : 0..f
5545 /* if we can beat 2n cycles or bytes for some special case, do it here */
5549 /* bytes cycles reg x reg a carry
5550 ** abcd efgh ijkl mnop ?
5551 ** clra 1 1 abcd efgh 0000 0000 a
5552 ** lslx 1 1 bcde fgh0 0000 0000 a
5553 ** rola 1 1 bcde fgh0 0000 000a 0
5554 ** clrx 1 1 0000 0000 0000 000a 0
5555 ** total: 4 cycles, 4 bytes
5557 loadRegFromConst (hc08_reg_x, zero);
5558 rmwWithReg ("lsl", hc08_reg_x);
5559 rmwWithReg ("rol", hc08_reg_a);
5560 loadRegFromConst (hc08_reg_a, zero);
5564 /* bytes cycles reg x reg a carry
5565 ** abcd efgh ijkl mnop ?
5566 ** clra 1 1 abcd efgh 0000 0000 a
5567 ** lslx 1 1 bcde fgh0 0000 0000 a
5568 ** rola 1 1 bcde fgh0 0000 000a 0
5569 ** lslx 1 1 cdef gh00 0000 000a b
5570 ** rola 1 1 cdef gh00 0000 00ab 0
5571 ** clrx 1 1 0000 0000 0000 00ab 0
5572 ** total: 6 cycles, 6 bytes
5574 loadRegFromConst (hc08_reg_x, zero);
5575 rmwWithReg ("lsl", hc08_reg_x);
5576 rmwWithReg ("rol", hc08_reg_a);
5577 rmwWithReg ("lsl", hc08_reg_x);
5578 rmwWithReg ("rol", hc08_reg_a);
5579 loadRegFromConst (hc08_reg_a, zero);
5588 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5589 AccRsh (shCount-8, FALSE);
5590 loadRegFromConst (hc08_reg_x, zero);
5594 /* bytes cycles reg x reg a carry
5595 ** abcd efgh ijkl mnop ?
5596 ** lsla 1 1 abcd efgh jklm nop0 i
5597 ** txa 1 1 abcd efgh abcd efgh i
5598 ** rola 1 1 abcd efgh bcde fghi a
5599 ** clrx 1 1 0000 0000 bcde fghi a
5600 ** rolx 1 1 0000 000a bcde fghi 0
5601 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5603 rmwWithReg ("lsl", hc08_reg_a);
5604 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5605 rmwWithReg ("rol", hc08_reg_a);
5606 loadRegFromConst (hc08_reg_x, zero);
5607 rmwWithReg ("rol", hc08_reg_x);
5610 /* bytes cycles reg x reg a carry
5611 ** abcd efgh ijkl mnop ?
5612 ** lsla 1 1 abcd efgh jklm nop0 i
5613 ** rolx 1 1 bcde fghi jklm nop0 a
5614 ** rola 1 1 bcde fghi klmn op0a j
5615 ** rolx 1 1 cdef ghij klmn op0a b
5616 ** rola 1 1 cdef ghij lmno p0ab k
5617 ** and #3 2 2 cdef ghij 0000 00ab k
5618 ** psha 1 2 cdef ghij 0000 00ab k
5619 ** txa 1 1 cdef ghij cdef ghij k
5620 ** pula 1 2 0000 00ab cdef ghij k
5621 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5627 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5628 /* the fastest and shortest. */
5629 for (i=0;i<shCount;i++)
5631 rmwWithReg ("lsr", hc08_reg_x);
5632 rmwWithReg ("ror", hc08_reg_a);
5639 /*-----------------------------------------------------------------*/
5640 /* shiftR1Left2Result - shift right one byte from left to result */
5641 /*-----------------------------------------------------------------*/
5643 shiftR1Left2Result (operand * left, int offl,
5644 operand * result, int offr,
5645 int shCount, int sign)
5647 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5648 /* shift right accumulator */
5649 AccRsh (shCount, sign);
5650 storeRegToAop (hc08_reg_a, AOP (result), offr);
5654 /*-----------------------------------------------------------------*/
5655 /* shiftL1Left2Result - shift left one byte from left to result */
5656 /*-----------------------------------------------------------------*/
5658 shiftL1Left2Result (operand * left, int offl,
5659 operand * result, int offr, int shCount)
5661 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5662 /* shift left accumulator */
5664 storeRegToAop (hc08_reg_a, AOP (result), offr);
5667 /*-----------------------------------------------------------------*/
5668 /* movLeft2Result - move byte from left to result */
5669 /*-----------------------------------------------------------------*/
5671 movLeft2Result (operand * left, int offl,
5672 operand * result, int offr, int sign)
5674 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5676 transferAopAop (AOP (left), offl, AOP (result), offr);
5681 /*-----------------------------------------------------------------*/
5682 /* shiftL2Left2Result - shift left two bytes from left to result */
5683 /*-----------------------------------------------------------------*/
5685 shiftL2Left2Result (operand * left, int offl,
5686 operand * result, int offr, int shCount)
5689 bool needpula = FALSE;
5690 bool needpulx = FALSE;
5692 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
5693 needpula = pushRegIfUsed (hc08_reg_a);
5696 if (!IS_AOP_XA (AOP (left)))
5697 needpulx = pushRegIfUsed (hc08_reg_x);
5701 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5706 rmwWithReg ("lsr", hc08_reg_x);
5707 rmwWithReg ("ror", hc08_reg_a);
5708 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5709 rmwWithReg ("clr", hc08_reg_a);
5710 rmwWithReg ("ror", hc08_reg_a);
5713 for (i=0; i<shCount; i++)
5715 rmwWithReg ("lsl", hc08_reg_a);
5716 rmwWithReg ("rol", hc08_reg_x);
5719 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5721 pullOrFreeReg (hc08_reg_x, needpulx);
5722 pullOrFreeReg (hc08_reg_a, needpula);
5728 /*-----------------------------------------------------------------*/
5729 /* shiftR2Left2Result - shift right two bytes from left to result */
5730 /*-----------------------------------------------------------------*/
5732 shiftR2Left2Result (operand * left, int offl,
5733 operand * result, int offr,
5734 int shCount, int sign)
5737 bool needpula = FALSE;
5738 bool needpulx = FALSE;
5740 needpula = pushRegIfUsed (hc08_reg_a);
5741 needpulx = pushRegIfUsed (hc08_reg_x);
5743 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5744 for (i=0; i<shCount; i++)
5747 rmwWithReg ("asr", hc08_reg_x);
5749 rmwWithReg ("lsr", hc08_reg_x);
5750 rmwWithReg ("ror", hc08_reg_a);
5752 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5754 pullOrFreeReg (hc08_reg_x, needpulx);
5755 pullOrFreeReg (hc08_reg_a, needpula);
5760 /*-----------------------------------------------------------------*/
5761 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5762 /*-----------------------------------------------------------------*/
5764 shiftLLeftOrResult (operand * left, int offl,
5765 operand * result, int offr, int shCount)
5767 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5768 /* shift left accumulator */
5770 /* or with result */
5771 accopWithAop ("ora", AOP (result), offr);
5772 /* back to result */
5773 storeRegToAop (hc08_reg_a, AOP (result), offr);
5774 hc08_freeReg (hc08_reg_a);
5778 /*-----------------------------------------------------------------*/
5779 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5780 /*-----------------------------------------------------------------*/
5782 shiftRLeftOrResult (operand * left, int offl,
5783 operand * result, int offr, int shCount)
5785 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5786 /* shift left accumulator */
5787 AccRsh (shCount, FALSE);
5788 /* or with result */
5789 accopWithAop ("ora", AOP (result), offr);
5790 /* back to result */
5791 storeRegToAop (hc08_reg_a, AOP (result), offr);
5792 hc08_freeReg (hc08_reg_a);
5795 /*-----------------------------------------------------------------*/
5796 /* genlshOne - left shift a one byte quantity by known count */
5797 /*-----------------------------------------------------------------*/
5799 genlshOne (operand * result, operand * left, int shCount)
5801 D(emitcode ("; genlshOne",""));
5803 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5806 /*-----------------------------------------------------------------*/
5807 /* genlshTwo - left shift two bytes by known amount != 0 */
5808 /*-----------------------------------------------------------------*/
5810 genlshTwo (operand * result, operand * left, int shCount)
5814 D(emitcode ("; genlshTwo",""));
5817 size = getDataSize (result);
5819 /* if shCount >= 8 */
5826 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5828 storeRegToAop (hc08_reg_a, AOP (result), 1);
5830 storeConstToAop(zero, AOP (result), LSB);
5833 /* 1 <= shCount <= 7 */
5836 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5838 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5842 /*-----------------------------------------------------------------*/
5843 /* shiftLLong - shift left one long from left to result */
5844 /* offl = LSB or MSB16 */
5845 /*-----------------------------------------------------------------*/
5847 shiftLLong (operand * left, operand * result, int offr)
5850 // int size = AOP_SIZE (result);
5852 bool needpula = FALSE;
5853 bool needpulx = FALSE;
5855 needpula = pushRegIfUsed (hc08_reg_a);
5856 needpulx = pushRegIfUsed (hc08_reg_x);
5858 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5859 rmwWithReg ("lsl", hc08_reg_a);
5860 rmwWithReg ("rol", hc08_reg_x);
5861 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5865 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5866 rmwWithReg ("rol", hc08_reg_a);
5867 rmwWithReg ("rol", hc08_reg_x);
5868 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5870 else if (offr==MSB16)
5872 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5873 rmwWithReg ("rol", hc08_reg_a);
5874 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5877 pullOrFreeReg (hc08_reg_x, needpulx);
5878 pullOrFreeReg (hc08_reg_a, needpula);
5881 /*-----------------------------------------------------------------*/
5882 /* genlshFour - shift four byte by a known amount != 0 */
5883 /*-----------------------------------------------------------------*/
5885 genlshFour (operand * result, operand * left, int shCount)
5889 D(emitcode ("; genlshFour",""));
5891 size = AOP_SIZE (result);
5893 /* TODO: deal with the &result == &left case */
5895 /* if shifting more that 3 bytes */
5900 /* lowest order of left goes to the highest
5901 order of the destination */
5902 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5904 movLeft2Result (left, LSB, result, MSB32, 0);
5905 storeConstToAop (zero, AOP (result), LSB);
5906 storeConstToAop (zero, AOP (result), MSB16);
5907 storeConstToAop (zero, AOP (result), MSB24);
5911 /* more than two bytes */
5912 else if (shCount >= 16)
5914 /* lower order two bytes goes to higher order two bytes */
5916 /* if some more remaining */
5918 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5921 movLeft2Result (left, MSB16, result, MSB32, 0);
5922 movLeft2Result (left, LSB, result, MSB24, 0);
5924 storeConstToAop (zero, AOP (result), LSB);
5925 storeConstToAop (zero, AOP (result), MSB16);
5929 /* if more than 1 byte */
5930 else if (shCount >= 8)
5932 /* lower order three bytes goes to higher order three bytes */
5937 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5939 movLeft2Result (left, LSB, result, MSB16, 0);
5945 movLeft2Result (left, MSB24, result, MSB32, 0);
5946 movLeft2Result (left, MSB16, result, MSB24, 0);
5947 movLeft2Result (left, LSB, result, MSB16, 0);
5948 storeConstToAop (zero, AOP (result), LSB);
5950 else if (shCount == 1)
5951 shiftLLong (left, result, MSB16);
5954 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5955 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5956 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5957 storeConstToAop (zero, AOP (result), LSB);
5962 /* 1 <= shCount <= 7 */
5963 else if (shCount <= 2)
5965 shiftLLong (left, result, LSB);
5967 shiftLLong (result, result, LSB);
5969 /* 3 <= shCount <= 7, optimize */
5972 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5973 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5974 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5978 /*-----------------------------------------------------------------*/
5979 /* genLeftShiftLiteral - left shifting by known count */
5980 /*-----------------------------------------------------------------*/
5982 genLeftShiftLiteral (operand * left,
5987 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5990 D(emitcode ("; genLeftShiftLiteral",""));
5992 freeAsmop (right, NULL, ic, TRUE);
5994 aopOp (left, ic, FALSE);
5995 aopOp (result, ic, FALSE);
5997 // size = getSize (operandType (result));
5998 size = AOP_SIZE (result);
6001 D(emitcode ("; shift left ", "result %d, left %d", size,
6008 transferAopAop( AOP(left), size, AOP(result), size);
6010 else if (shCount >= (size * 8))
6013 storeConstToAop (zero, AOP (result), size);
6020 genlshOne (result, left, shCount);
6024 genlshTwo (result, left, shCount);
6028 genlshFour (result, left, shCount);
6031 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6032 "*** ack! mystery literal shift!\n");
6036 freeAsmop (left, NULL, ic, TRUE);
6037 freeAsmop (result, NULL, ic, TRUE);
6040 /*-----------------------------------------------------------------*/
6041 /* genLeftShift - generates code for left shifting */
6042 /*-----------------------------------------------------------------*/
6044 genLeftShift (iCode * ic)
6046 operand *left, *right, *result;
6048 symbol *tlbl, *tlbl1;
6053 D(emitcode ("; genLeftShift",""));
6055 right = IC_RIGHT (ic);
6056 left = IC_LEFT (ic);
6057 result = IC_RESULT (ic);
6059 aopOp (right, ic, FALSE);
6061 /* if the shift count is known then do it
6062 as efficiently as possible */
6063 if (AOP_TYPE (right) == AOP_LIT)
6065 genLeftShiftLiteral (left, right, result, ic);
6069 /* shift count is unknown then we have to form
6070 a loop get the loop count in A : Note: we take
6071 only the lower order byte since shifting
6072 more that 32 bits make no sense anyway, ( the
6073 largest size of an object can be only 32 bits ) */
6075 aopOp (left, ic, FALSE);
6076 aopOp (result, ic, FALSE);
6078 /* now move the left to the result if they are not the
6080 if (!sameRegs (AOP (left), AOP (result)))
6083 size = AOP_SIZE (result);
6087 transferAopAop (AOP (left), offset, AOP (result), offset);
6091 freeAsmop (left, NULL, ic, TRUE);
6093 tlbl = newiTempLabel (NULL);
6094 size = AOP_SIZE (result);
6096 tlbl1 = newiTempLabel (NULL);
6100 loadRegFromAop (reg, AOP (right), 0);
6101 freeAsmop (right, NULL, ic, TRUE);
6102 emitBranch ("beq", tlbl1);
6106 for (offset=0;offset<size;offset++)
6108 rmwWithAop (shift, AOP (result), offset);
6111 rmwWithReg ("dec", reg);
6112 emitBranch ("bne", tlbl);
6116 freeAsmop (result, NULL, ic, TRUE);
6119 /*-----------------------------------------------------------------*/
6120 /* genrshOne - right shift a one byte quantity by known count */
6121 /*-----------------------------------------------------------------*/
6123 genrshOne (operand * result, operand * left,
6124 int shCount, int sign)
6126 D(emitcode ("; genrshOne",""));
6128 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6129 AccRsh (shCount, sign);
6130 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6133 /*-----------------------------------------------------------------*/
6134 /* genrshTwo - right shift two bytes by known amount != 0 */
6135 /*-----------------------------------------------------------------*/
6137 genrshTwo (operand * result, operand * left,
6138 int shCount, int sign)
6140 D(emitcode ("; genrshTwo",""));
6142 /* if shCount >= 8 */
6145 if (shCount || sign)
6147 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6148 AccRsh (shCount-8, sign);
6149 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6153 transferAopAop (AOP (left), 1, AOP (result), 0);
6154 storeConstToAop (zero, AOP (result), 1);
6158 /* 1 <= shCount <= 7 */
6161 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6162 XAccRsh (shCount, sign);
6163 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6167 /*-----------------------------------------------------------------*/
6168 /* shiftRLong - shift right one long from left to result */
6169 /* offl = LSB or MSB16 */
6170 /*-----------------------------------------------------------------*/
6172 shiftRLong (operand * left, int offl,
6173 operand * result, int sign)
6176 // int size = AOP_SIZE (result);
6178 bool needpula = FALSE;
6179 bool needpulx = FALSE;
6181 needpula = pushRegIfUsed (hc08_reg_a);
6182 needpulx = pushRegIfUsed (hc08_reg_x);
6186 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6188 rmwWithReg ("asr", hc08_reg_x);
6190 rmwWithReg ("lsr", hc08_reg_x);
6191 rmwWithReg ("rol", hc08_reg_a);
6192 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6194 else if (offl==MSB16)
6196 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6198 rmwWithReg ("asr", hc08_reg_a);
6200 rmwWithReg ("lsr", hc08_reg_a);
6201 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6204 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6205 rmwWithReg ("ror", hc08_reg_x);
6206 rmwWithReg ("ror", hc08_reg_a);
6207 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6210 pullOrFreeReg (hc08_reg_x, needpulx);
6211 pullOrFreeReg (hc08_reg_a, needpula);
6214 /*-----------------------------------------------------------------*/
6215 /* genrshFour - shift four byte by a known amount != 0 */
6216 /*-----------------------------------------------------------------*/
6218 genrshFour (operand * result, operand * left,
6219 int shCount, int sign)
6221 /* TODO: handle cases where left == result */
6223 D(emitcode ("; genrshFour",""));
6225 /* if shifting more that 3 bytes */
6228 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6229 AccRsh (shCount-24, sign);
6230 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6233 else if (shCount >= 16)
6235 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6236 XAccRsh (shCount-16, sign);
6237 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6240 else if (shCount >= 8)
6243 shiftRLong (left, MSB16, result, sign);
6244 else if (shCount == 8)
6246 transferAopAop (AOP (left), 1, AOP (result), 0);
6247 transferAopAop (AOP (left), 2, AOP (result), 1);
6248 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6249 storeRegToAop (hc08_reg_a, AOP (result), 2);
6250 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6252 else if (shCount == 9)
6254 shiftRLong (left, MSB16, result, sign);
6258 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6259 XAccRsh (shCount-8, FALSE);
6260 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6261 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6262 loadRegFromConst (hc08_reg_a, zero);
6263 XAccRsh (shCount-8, sign);
6264 accopWithAop ("ora", AOP (result), 1);
6265 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6269 { /* 1 <= shCount <= 7 */
6272 shiftRLong (left, LSB, result, sign);
6276 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6277 XAccRsh (shCount, FALSE);
6278 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6279 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6281 accopWithAop ("ora", AOP (result), 1);
6282 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6283 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6284 XAccRsh (shCount, sign);
6285 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6290 /*-----------------------------------------------------------------*/
6291 /* genRightShiftLiteral - right shifting by known count */
6292 /*-----------------------------------------------------------------*/
6294 genRightShiftLiteral (operand * left,
6300 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6303 D(emitcode ("; genRightShiftLiteral",""));
6305 freeAsmop (right, NULL, ic, TRUE);
6307 aopOp (left, ic, FALSE);
6308 aopOp (result, ic, FALSE);
6311 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6315 size = getDataSize (left);
6316 /* test the LEFT size !!! */
6318 /* I suppose that the left size >= result size */
6321 size = getDataSize (result);
6323 transferAopAop (AOP (left), size, AOP(result), size);
6325 else if (shCount >= (size * 8))
6328 /* get sign in acc.7 */
6329 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6331 addSign (result, LSB, sign);
6338 genrshOne (result, left, shCount, sign);
6342 genrshTwo (result, left, shCount, sign);
6346 genrshFour (result, left, shCount, sign);
6352 freeAsmop (left, NULL, ic, TRUE);
6353 freeAsmop (result, NULL, ic, TRUE);
6357 /*-----------------------------------------------------------------*/
6358 /* genRightShift - generate code for right shifting */
6359 /*-----------------------------------------------------------------*/
6361 genRightShift (iCode * ic)
6363 operand *right, *left, *result;
6367 symbol *tlbl, *tlbl1;
6371 D(emitcode ("; genRightShift",""));
6373 /* if signed then we do it the hard way preserve the
6374 sign bit moving it inwards */
6375 retype = getSpec (operandType (IC_RESULT (ic)));
6376 sign = !SPEC_USIGN (retype);
6378 /* signed & unsigned types are treated the same : i.e. the
6379 signed is NOT propagated inwards : quoting from the
6380 ANSI - standard : "for E1 >> E2, is equivalent to division
6381 by 2**E2 if unsigned or if it has a non-negative value,
6382 otherwise the result is implementation defined ", MY definition
6383 is that the sign does not get propagated */
6385 right = IC_RIGHT (ic);
6386 left = IC_LEFT (ic);
6387 result = IC_RESULT (ic);
6389 aopOp (right, ic, FALSE);
6391 /* if the shift count is known then do it
6392 as efficiently as possible */
6393 if (AOP_TYPE (right) == AOP_LIT)
6395 genRightShiftLiteral (left, right, result, ic, sign);
6399 /* shift count is unknown then we have to form
6400 a loop get the loop count in X : Note: we take
6401 only the lower order byte since shifting
6402 more that 32 bits make no sense anyway, ( the
6403 largest size of an object can be only 32 bits ) */
6405 aopOp (left, ic, FALSE);
6406 aopOp (result, ic, FALSE);
6408 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6409 AOP (result) = forceStackedAop (AOP (result));
6411 size = AOP_SIZE (result);
6415 transferAopAop (AOP (left), offset, AOP (result), offset);
6419 tlbl = newiTempLabel (NULL);
6420 size = AOP_SIZE (result);
6422 tlbl1 = newiTempLabel (NULL);
6424 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6425 emitcode ("tstx", "");
6426 emitcode ("beq", "%05d$", tlbl1->key + 100);
6427 emitcode ("", "%05d$:", tlbl->key + 100);
6428 shift= sign ? "asr" : "lsr";
6429 for (offset=size-1;offset>=0;offset--)
6431 rmwWithAop (shift, AOP (result), offset);
6434 rmwWithReg ("dec", hc08_reg_x);
6435 emitcode ("bne","%05d$", tlbl->key + 100);
6436 emitcode ("", "%05d$:", tlbl1->key + 100);
6438 freeAsmop (result, NULL, ic, TRUE);
6439 freeAsmop (left, NULL, ic, TRUE);
6440 freeAsmop (right, NULL, ic, TRUE);
6444 /*-----------------------------------------------------------------*/
6445 /* genUnpackBits - generates code for unpacking bits */
6446 /*-----------------------------------------------------------------*/
6448 genUnpackBits (operand * result, iCode *ifx)
6450 int offset = 0; /* result byte offset */
6451 int rsize; /* result size */
6452 int rlen = 0; /* remaining bitfield length */
6453 sym_link *etype; /* bitfield type information */
6454 int blen; /* bitfield length */
6455 int bstr; /* bitfield starting bit within byte */
6457 D(emitcode ("; genUnpackBits",""));
6459 etype = getSpec (operandType (result));
6460 rsize = getSize (operandType (result));
6461 blen = SPEC_BLEN (etype);
6462 bstr = SPEC_BSTR (etype);
6464 /* If the bitfield length is less than a byte */
6467 emitcode ("lda", ",x");
6468 hc08_dirtyReg (hc08_reg_a, FALSE);
6471 AccRsh (bstr, FALSE);
6472 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6473 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6477 emitcode ("and", "#0x%02x",
6478 (((unsigned char) -1) >> (8 - blen)) << bstr);
6483 /* Bit field did not fit in a byte. Copy all
6484 but the partial byte at the end. */
6485 for (rlen=blen;rlen>=8;rlen-=8)
6487 emitcode ("lda", ",x");
6488 hc08_dirtyReg (hc08_reg_a, FALSE);
6490 storeRegToAop (hc08_reg_a, AOP (result), offset);
6493 emitcode ("aix", "#1");
6496 /* Handle the partial byte at the end */
6499 emitcode ("lda", ",x");
6500 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6501 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6509 storeConstToAop (zero, AOP (result), offset++);
6512 if (ifx && !ifx->generated)
6514 genIfxJump (ifx, "a");
6519 /*-----------------------------------------------------------------*/
6520 /* genUnpackBitsImmed - generates code for unpacking bits */
6521 /*-----------------------------------------------------------------*/
6523 genUnpackBitsImmed (operand * left,
6529 int offset = 0; /* result byte offset */
6530 int rsize; /* result size */
6531 int rlen = 0; /* remaining bitfield length */
6532 sym_link *etype; /* bitfield type information */
6533 int blen; /* bitfield length */
6534 int bstr; /* bitfield starting bit within byte */
6537 D(emitcode ("; genUnpackBitsImmed",""));
6539 aopOp (result, ic, TRUE);
6540 size = AOP_SIZE (result);
6542 derefaop = aopDerefAop (AOP (left));
6543 freeAsmop (left, NULL, ic, TRUE);
6544 derefaop->size = size;
6546 etype = getSpec (operandType (result));
6547 rsize = getSize (operandType (result));
6548 blen = SPEC_BLEN (etype);
6549 bstr = SPEC_BSTR (etype);
6551 /* if the bitfield is a single bit in the direct page */
6552 if (blen == 1 && derefaop->type == AOP_DIR)
6556 symbol *tlbl = newiTempLabel (NULL);
6558 loadRegFromConst (hc08_reg_a, zero);
6559 emitcode ("brclr", "#%d,%s,%05d$",
6560 bstr, aopAdrStr (derefaop, 0, FALSE),
6562 rmwWithReg ("inc", hc08_reg_a);
6564 storeRegToAop (hc08_reg_a, AOP (result), offset);
6565 hc08_freeReg (hc08_reg_a);
6571 symbol *tlbl = newiTempLabel (NULL);
6577 jlbl = IC_TRUE (ifx);
6582 jlbl = IC_FALSE (ifx);
6585 emitcode (inst, "#%d,%s,%05d$",
6586 bstr, aopAdrStr (derefaop, 0, FALSE),
6588 emitBranch ("jmp", jlbl);
6596 /* If the bitfield length is less than a byte */
6599 loadRegFromAop (hc08_reg_a, derefaop, 0);
6602 AccRsh (bstr, FALSE);
6603 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6604 hc08_dirtyReg (hc08_reg_a, FALSE);
6605 storeRegToAop (hc08_reg_a, AOP (result), offset);
6609 emitcode ("and", "#0x%02x",
6610 (((unsigned char) -1) >> (8 - blen)) << bstr);
6611 hc08_dirtyReg (hc08_reg_a, FALSE);
6617 /* Bit field did not fit in a byte. Copy all
6618 but the partial byte at the end. */
6619 for (rlen=blen;rlen>=8;rlen-=8)
6621 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6623 storeRegToAop (hc08_reg_a, AOP (result), offset);
6625 emitcode ("tsta", "");
6629 /* Handle the partial byte at the end */
6632 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6633 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6634 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6642 storeConstToAop (zero, AOP (result), offset++);
6645 freeAsmop (NULL, derefaop, ic, TRUE);
6646 freeAsmop (result, NULL, ic, TRUE);
6648 if (ifx && !ifx->generated)
6650 genIfxJump (ifx, "a");
6655 /*-----------------------------------------------------------------*/
6656 /* genDataPointerGet - generates code when ptr offset is known */
6657 /*-----------------------------------------------------------------*/
6659 genDataPointerGet (operand * left,
6664 int size, offset = 0;
6667 D(emitcode ("; genDataPointerGet",""));
6669 aopOp (result, ic, TRUE);
6670 size = AOP_SIZE (result);
6672 derefaop = aopDerefAop (AOP (left));
6673 freeAsmop (left, NULL, ic, TRUE);
6674 derefaop->size = size;
6679 transferAopAop (derefaop, offset, AOP (result), offset);
6681 loadRegFromAop (hc08_reg_a, derefaop, offset);
6685 freeAsmop (NULL, derefaop, ic, TRUE);
6686 freeAsmop (result, NULL, ic, TRUE);
6688 if (ifx && !ifx->generated)
6690 genIfxJump (ifx, "a");
6695 /*-----------------------------------------------------------------*/
6696 /* genPointerGet - generate code for pointer get */
6697 /*-----------------------------------------------------------------*/
6699 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
6701 operand *left = IC_LEFT (ic);
6702 operand *result = IC_RESULT (ic);
6704 sym_link *retype = getSpec (operandType (result));
6706 D(emitcode ("; genPointerGet",""));
6708 if (getSize (operandType (result))>1)
6711 aopOp (left, ic, FALSE);
6713 /* if left is rematerialisable and
6714 result is not bit variable type */
6715 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
6717 if (!IS_BITVAR (retype))
6719 genDataPointerGet (left, result, ic, ifx);
6724 genUnpackBitsImmed (left, result, ic, ifx);
6729 /* if the operand is already in hx
6730 then we do nothing else we move the value to hx */
6731 if (AOP_TYPE (left) != AOP_STR)
6733 /* if this is remateriazable */
6734 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6737 /* so hx now contains the address */
6738 aopOp (result, ic, FALSE);
6740 /* if bit then unpack */
6741 if (IS_BITVAR (retype))
6742 genUnpackBits (result, ifx);
6745 size = AOP_SIZE (result);
6750 accopWithMisc ("lda", ",x");
6753 emitcode ("aix", "#1");
6754 hc08_dirtyReg (hc08_reg_hx, FALSE);
6757 storeRegToAop (hc08_reg_a, AOP (result), offset);
6759 hc08_freeReg (hc08_reg_a);
6763 freeAsmop (left, NULL, ic, TRUE);
6764 freeAsmop (result, NULL, ic, TRUE);
6767 aopOp (IC_RESULT (pi), pi, FALSE);
6768 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6769 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6773 if (ifx && !ifx->generated)
6775 genIfxJump (ifx, "a");
6778 hc08_freeReg (hc08_reg_hx);
6782 /*-----------------------------------------------------------------*/
6783 /* genPackBits - generates code for packed bit storage */
6784 /*-----------------------------------------------------------------*/
6786 genPackBits (sym_link * etype,
6789 int offset = 0; /* source byte offset */
6790 int rlen = 0; /* remaining bitfield length */
6791 int blen; /* bitfield length */
6792 int bstr; /* bitfield starting bit within byte */
6793 int litval; /* source literal value (if AOP_LIT) */
6794 unsigned char mask; /* bitmask within current byte */
6797 D(emitcode ("; genPackBits",""));
6799 blen = SPEC_BLEN (etype);
6800 bstr = SPEC_BSTR (etype);
6802 /* If the bitfield length is less than a byte */
6805 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6806 (unsigned char) (0xFF >> (8 - bstr)));
6808 if (AOP_TYPE (right) == AOP_LIT)
6810 /* Case with a bitfield length <8 and literal source
6812 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6814 litval &= (~mask) & 0xff;
6816 emitcode ("lda", ",x");
6817 if ((mask|litval)!=0xff)
6818 emitcode ("and","#0x%02x", mask);
6820 emitcode ("ora","#0x%02x", litval);
6821 hc08_dirtyReg (hc08_reg_a, FALSE);
6822 emitcode ("sta", ",x");
6824 hc08_freeReg (hc08_reg_a);
6828 /* Case with a bitfield length < 8 and arbitrary source
6830 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6831 /* shift and mask source value */
6833 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6834 hc08_dirtyReg (hc08_reg_a, FALSE);
6835 pushReg (hc08_reg_a, TRUE);
6837 emitcode ("lda", ",x");
6838 emitcode ("and", "#0x%02x", mask);
6839 emitcode ("ora", "1,s");
6840 emitcode ("sta", ",x");
6841 pullReg (hc08_reg_a);
6843 hc08_freeReg (hc08_reg_a);
6847 /* Bit length is greater than 7 bits. In this case, copy */
6848 /* all except the partial byte at the end */
6849 for (rlen=blen;rlen>=8;rlen-=8)
6851 if (AOP (right)->type == AOP_DIR)
6853 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6858 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6859 emitcode ("sta", "%d,x", offset);
6864 /* If there was a partial byte at the end */
6867 mask = (((unsigned char) -1 << rlen) & 0xff);
6869 if (AOP_TYPE (right) == AOP_LIT)
6871 /* Case with partial byte and literal source
6873 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6874 litval >>= (blen-rlen);
6875 litval &= (~mask) & 0xff;
6876 emitcode ("lda", "%d,x", offset - xoffset);
6877 hc08_dirtyReg (hc08_reg_a, FALSE);
6878 if ((mask|litval)!=0xff)
6879 emitcode ("and","#0x%02x", mask);
6881 emitcode ("ora","#0x%02x", litval);
6882 emitcode ("sta", "%d,x", offset - xoffset);
6883 hc08_dirtyReg (hc08_reg_a, FALSE);
6884 hc08_freeReg (hc08_reg_a);
6888 /* Case with partial byte and arbitrary source
6890 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6891 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6892 hc08_dirtyReg (hc08_reg_a, FALSE);
6893 pushReg (hc08_reg_a, TRUE);
6895 emitcode ("lda", "%d,x", offset - xoffset);
6896 emitcode ("and", "#0x%02x", mask);
6897 emitcode ("ora", "1,s");
6898 emitcode ("sta", "%d,x", offset - xoffset);
6899 pullReg (hc08_reg_a);
6902 hc08_freeReg (hc08_reg_a);
6905 /*-----------------------------------------------------------------*/
6906 /* genPackBitsImmed - generates code for packed bit storage */
6907 /*-----------------------------------------------------------------*/
6909 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
6913 int offset = 0; /* source byte offset */
6914 int rlen = 0; /* remaining bitfield length */
6915 int blen; /* bitfield length */
6916 int bstr; /* bitfield starting bit within byte */
6917 int litval; /* source literal value (if AOP_LIT) */
6918 unsigned char mask; /* bitmask within current byte */
6920 D(emitcode ("; genPackBitsImmed",""));
6922 blen = SPEC_BLEN (etype);
6923 bstr = SPEC_BSTR (etype);
6925 aopOp (right, ic, FALSE);
6926 size = AOP_SIZE (right);
6928 derefaop = aopDerefAop (AOP (result));
6929 freeAsmop (result, NULL, ic, TRUE);
6930 derefaop->size = size;
6932 /* if the bitfield is a single bit in the direct page */
6933 if (blen == 1 && derefaop->type == AOP_DIR)
6935 if (AOP_TYPE (right) == AOP_LIT)
6937 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6939 emitcode ((litval & 1) ? "bset" : "bclr",
6940 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
6944 symbol *tlbl1 = newiTempLabel (NULL);
6945 symbol *tlbl2 = newiTempLabel (NULL);
6947 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6948 emitcode ("bit", "#1");
6949 emitBranch ("bne", tlbl1);
6950 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
6951 emitBranch ("bra", tlbl2);
6953 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
6955 hc08_freeReg (hc08_reg_a);
6960 /* If the bitfield length is less than a byte */
6963 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6964 (unsigned char) (0xFF >> (8 - bstr)));
6966 if (AOP_TYPE (right) == AOP_LIT)
6968 /* Case with a bitfield length <8 and literal source
6970 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6972 litval &= (~mask) & 0xff;
6974 loadRegFromAop (hc08_reg_a, derefaop, 0);
6975 if ((mask|litval)!=0xff)
6976 emitcode ("and","#0x%02x", mask);
6978 emitcode ("ora","#0x%02x", litval);
6979 hc08_dirtyReg (hc08_reg_a, FALSE);
6980 storeRegToAop (hc08_reg_a, derefaop, 0);
6982 hc08_freeReg (hc08_reg_a);
6986 /* Case with a bitfield length < 8 and arbitrary source
6988 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6989 /* shift and mask source value */
6991 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6992 hc08_dirtyReg (hc08_reg_a, FALSE);
6993 pushReg (hc08_reg_a, TRUE);
6995 loadRegFromAop (hc08_reg_a, derefaop, 0);
6996 emitcode ("and", "#0x%02x", mask);
6997 emitcode ("ora", "1,s");
6998 storeRegToAop (hc08_reg_a, derefaop, 0);
6999 pullReg (hc08_reg_a);
7001 hc08_freeReg (hc08_reg_a);
7005 /* Bit length is greater than 7 bits. In this case, copy */
7006 /* all except the partial byte at the end */
7007 for (rlen=blen;rlen>=8;rlen-=8)
7009 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7013 /* If there was a partial byte at the end */
7016 mask = (((unsigned char) -1 << rlen) & 0xff);
7018 if (AOP_TYPE (right) == AOP_LIT)
7020 /* Case with partial byte and literal source
7022 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7023 litval >>= (blen-rlen);
7024 litval &= (~mask) & 0xff;
7025 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7026 if ((mask|litval)!=0xff)
7027 emitcode ("and","#0x%02x", mask);
7029 emitcode ("ora","#0x%02x", litval);
7030 hc08_dirtyReg (hc08_reg_a, FALSE);
7031 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7032 hc08_dirtyReg (hc08_reg_a, FALSE);
7033 hc08_freeReg (hc08_reg_a);
7037 /* Case with partial byte and arbitrary source
7039 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7040 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7041 hc08_dirtyReg (hc08_reg_a, FALSE);
7042 pushReg (hc08_reg_a, TRUE);
7044 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7045 emitcode ("and", "#0x%02x", mask);
7046 emitcode ("ora", "1,s");
7047 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7048 pullReg (hc08_reg_a);
7051 hc08_freeReg (hc08_reg_a);
7054 freeAsmop (right, NULL, ic, TRUE);
7055 freeAsmop (NULL, derefaop, ic, TRUE);
7058 /*-----------------------------------------------------------------*/
7059 /* genDataPointerSet - remat pointer to data space */
7060 /*-----------------------------------------------------------------*/
7062 genDataPointerSet (operand * right,
7066 int size, offset = 0;
7069 D(emitcode ("; genDataPointerSet",""));
7071 aopOp (right, ic, FALSE);
7072 size = AOP_SIZE (right);
7074 derefaop = aopDerefAop (AOP (result));
7075 freeAsmop (result, NULL, ic, TRUE);
7076 derefaop->size = size;
7080 transferAopAop (AOP (right), offset, derefaop, offset);
7084 freeAsmop (right, NULL, ic, TRUE);
7085 freeAsmop (NULL, derefaop, ic, TRUE);
7089 /*-----------------------------------------------------------------*/
7090 /* genPointerSet - stores the value into a pointer location */
7091 /*-----------------------------------------------------------------*/
7093 genPointerSet (iCode * ic, iCode *pi)
7095 operand *right = IC_RIGHT (ic);
7096 operand *result = IC_RESULT (ic);
7097 sym_link *type, *etype;
7099 sym_link *retype = getSpec (operandType (right));
7100 sym_link *letype = getSpec (operandType (result));
7102 D(emitcode ("; genPointerSet",""));
7104 type = operandType (result);
7105 etype = getSpec (type);
7107 aopOp (result, ic, FALSE);
7109 /* if the result is rematerializable */
7110 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7112 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7114 genDataPointerSet (right, result, ic);
7119 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7124 /* if the operand is already in hx
7125 then we do nothing else we move the value to hx */
7126 if (AOP_TYPE (result) != AOP_STR)
7128 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7130 /* so hx now contains the address */
7131 aopOp (right, ic, FALSE);
7133 /* if bit then unpack */
7134 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7135 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7138 size = AOP_SIZE (right);
7143 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7144 accopWithMisc ("sta", ",x");
7147 emitcode ("aix", "#1");
7149 hc08_freeReg (hc08_reg_a);
7153 freeAsmop (result, NULL, ic, TRUE);
7154 freeAsmop (right, NULL, ic, TRUE);
7157 aopOp (IC_RESULT (pi), pi, FALSE);
7158 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7159 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7163 hc08_freeReg (hc08_reg_hx);
7167 /*-----------------------------------------------------------------*/
7168 /* genIfx - generate code for Ifx statement */
7169 /*-----------------------------------------------------------------*/
7171 genIfx (iCode * ic, iCode * popIc)
7173 operand *cond = IC_COND (ic);
7176 D(emitcode ("; genIfx",""));
7178 aopOp (cond, ic, FALSE);
7180 /* get the value into acc */
7181 if (AOP_TYPE (cond) != AOP_CRY)
7182 asmopToBool (AOP (cond), FALSE);
7185 /* the result is now in the accumulator */
7186 freeAsmop (cond, NULL, ic, TRUE);
7188 /* if there was something to be popped then do it */
7192 /* if the condition is a bit variable */
7193 if (isbit && IS_ITEMP (cond) &&
7195 genIfxJump (ic, SPIL_LOC (cond)->rname);
7196 else if (isbit && !IS_ITEMP (cond))
7197 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7199 genIfxJump (ic, "a");
7204 /*-----------------------------------------------------------------*/
7205 /* genAddrOf - generates code for address of */
7206 /*-----------------------------------------------------------------*/
7208 genAddrOf (iCode * ic)
7210 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7213 D(emitcode ("; genAddrOf",""));
7215 aopOp (IC_RESULT (ic), ic, FALSE);
7217 /* if the operand is on the stack then we
7218 need to get the stack offset of this
7222 /* if it has an offset then we need to compute
7224 hc08_useReg (hc08_reg_hx);
7225 emitcode ("tsx", "");
7226 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7227 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7228 hc08_freeReg (hc08_reg_hx);
7233 /* object not on stack then we need the name */
7234 size = AOP_SIZE (IC_RESULT (ic));
7239 char s[SDCC_NAME_MAX+10];
7242 sprintf (s, "#%s", sym->rname);
7245 sprintf (s, "#>%s", sym->rname);
7248 sprintf (s, "#(%s >> %d)",
7252 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7256 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7260 /*-----------------------------------------------------------------*/
7261 /* genAssign - generate code for assignment */
7262 /*-----------------------------------------------------------------*/
7264 genAssign (iCode * ic)
7266 operand *result, *right;
7268 // unsigned long lit = 0L;
7270 D(emitcode("; genAssign",""));
7272 result = IC_RESULT (ic);
7273 right = IC_RIGHT (ic);
7275 /* if they are the same */
7276 if (operandsEqu (result, right)) {
7280 aopOp (right, ic, FALSE);
7281 aopOp (result, ic, TRUE);
7283 /* if they are the same registers */
7284 if (sameRegs (AOP (right), AOP (result)))
7287 if ((AOP_TYPE (right) == AOP_LIT)
7288 && (IS_AOP_HX(AOP(result))))
7290 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7295 size = AOP_SIZE (result);
7300 transferAopAop (AOP (right), offset, AOP (result), offset);
7305 freeAsmop (right, NULL, ic, TRUE);
7306 freeAsmop (result, NULL, ic, TRUE);
7309 /*-----------------------------------------------------------------*/
7310 /* genJumpTab - genrates code for jump table */
7311 /*-----------------------------------------------------------------*/
7313 genJumpTab (iCode * ic)
7318 D(emitcode ("; genJumpTab",""));
7320 aopOp (IC_JTCOND (ic), ic, FALSE);
7321 /* get the condition into accumulator */
7322 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7323 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7324 /* multiply by three */
7325 pushReg (hc08_reg_a, FALSE);
7326 emitcode ("lsla", "");
7327 emitcode ("add","1,s");
7328 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7329 loadRegFromConst (hc08_reg_h, zero);
7330 pullReg (hc08_reg_a);
7332 jtab = newiTempLabel (NULL);
7333 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7334 emitcode ("", "%05d$:", jtab->key + 100);
7335 /* now generate the jump labels */
7336 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7337 jtab = setNextItem (IC_JTLABELS (ic)))
7338 emitcode ("jmp", "%05d$", jtab->key + 100);
7340 hc08_dirtyReg (hc08_reg_a, TRUE);
7341 hc08_dirtyReg (hc08_reg_hx, TRUE);
7344 /*-----------------------------------------------------------------*/
7345 /* genCast - gen code for casting */
7346 /*-----------------------------------------------------------------*/
7348 genCast (iCode * ic)
7350 operand *result = IC_RESULT (ic);
7351 sym_link *ctype = operandType (IC_LEFT (ic));
7352 sym_link *rtype = operandType (IC_RIGHT (ic));
7353 operand *right = IC_RIGHT (ic);
7356 D(emitcode("; genCast",""));
7358 /* if they are equivalent then do nothing */
7359 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7362 aopOp (right, ic, FALSE);
7363 aopOp (result, ic, FALSE);
7366 /* if they are the same size : or less */
7367 if (AOP_SIZE (result) <= AOP_SIZE (right))
7370 /* if they are in the same place */
7372 if (sameRegs (AOP (right), AOP (result)))
7376 /* if they in different places then copy */
7377 size = AOP_SIZE (result);
7381 transferAopAop(AOP (right), offset, AOP (result), offset);
7388 /* if the result is of type pointer */
7393 sym_link *type = operandType (right);
7394 sym_link *etype = getSpec (type);
7396 /* pointer to generic pointer */
7397 if (IS_GENPTR (ctype))
7400 p_type = DCL_TYPE (type);
7403 if (SPEC_SCLS(etype)==S_REGISTER) {
7404 // let's assume it is a generic pointer
7407 /* we have to go by the storage class */
7408 p_type = PTR_TYPE (SPEC_OCLS (etype));
7412 /* the first two bytes are known */
7413 size = GPTRSIZE - 1;
7417 transferAopAop(AOP (right), offset, AOP (result), offset);
7420 /* the last byte depending on type */
7423 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7428 // pointerTypeToGPByte will have bitched.
7432 sprintf(gpValStr, "#0x%d", gpVal);
7433 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7439 /* just copy the pointers */
7440 size = AOP_SIZE (result);
7444 transferAopAop(AOP (right), offset, AOP (result), offset);
7450 /* so we now know that the size of destination is greater
7451 than the size of the source */
7452 /* we move to result for the size of source */
7453 size = AOP_SIZE (right);
7457 transferAopAop(AOP (right), offset, AOP (result), offset);
7461 /* now depending on the sign of the source && destination */
7462 size = AOP_SIZE (result) - AOP_SIZE (right);
7463 /* if unsigned or not an integral type */
7464 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7467 storeConstToAop (zero, AOP (result), offset++);
7471 /* we need to extend the sign :{ */
7472 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7473 accopWithMisc ("rola", "");
7474 accopWithMisc ("clra", "");
7475 accopWithMisc ("sbc", zero);
7477 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7480 /* we are done hurray !!!! */
7483 freeAsmop (right, NULL, ic, TRUE);
7484 freeAsmop (result, NULL, ic, TRUE);
7488 /*-----------------------------------------------------------------*/
7489 /* genDjnz - generate decrement & jump if not zero instrucion */
7490 /*-----------------------------------------------------------------*/
7492 genDjnz (iCode * ic, iCode * ifx)
7498 D(emitcode ("; genDjnz",""));
7500 /* if the if condition has a false label
7501 then we cannot save */
7505 /* if the minus is not of the form
7507 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7508 !IS_OP_LITERAL (IC_RIGHT (ic)))
7511 if (operandLitValue (IC_RIGHT (ic)) != 1)
7514 /* dbnz doesn't support extended mode */
7515 if (isOperandInFarSpace (IC_RESULT (ic)))
7518 /* if the size of this greater than one then no
7520 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7522 aopOp (IC_RESULT (ic), ic, FALSE);
7523 if (AOP_SIZE (IC_RESULT (ic))>1)
7525 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7529 /* otherwise we can save BIG */
7530 lbl = newiTempLabel (NULL);
7531 lbl1 = newiTempLabel (NULL);
7534 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7537 emitBranch ("bra", lbl1);
7539 emitBranch ("jmp", IC_TRUE (ifx));
7542 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7547 /*-----------------------------------------------------------------*/
7548 /* genReceive - generate code for a receive iCode */
7549 /*-----------------------------------------------------------------*/
7551 genReceive (iCode * ic)
7555 D(emitcode ("; genReceive",""));
7557 aopOp (IC_RESULT (ic), ic, FALSE);
7558 size = AOP_SIZE (IC_RESULT (ic));
7563 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7564 AOP (IC_RESULT (ic)), offset);
7565 if (hc08_aop_pass[offset]->type == AOP_REG)
7566 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7571 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7574 /*-----------------------------------------------------------------*/
7575 /* genDummyRead - generate code for dummy read of volatiles */
7576 /*-----------------------------------------------------------------*/
7578 genDummyRead (iCode * ic)
7583 D(emitcode("; genDummyRead",""));
7586 if (op && IS_SYMOP (op))
7589 aopOp (op, ic, FALSE);
7591 size = AOP_SIZE (op);
7596 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7597 hc08_freeReg (hc08_reg_a);
7601 freeAsmop (op, NULL, ic, TRUE);
7604 if (op && IS_SYMOP (op))
7607 aopOp (op, ic, FALSE);
7609 size = AOP_SIZE (op);
7614 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7615 hc08_freeReg (hc08_reg_a);
7619 freeAsmop (op, NULL, ic, TRUE);
7623 /*-----------------------------------------------------------------*/
7624 /* genCritical - generate code for start of a critical sequence */
7625 /*-----------------------------------------------------------------*/
7627 genCritical (iCode *ic)
7629 D(emitcode("; genCritical",""));
7632 aopOp (IC_RESULT (ic), ic, TRUE);
7634 emitcode ("tpa", "");
7635 hc08_dirtyReg (hc08_reg_a, FALSE);
7636 emitcode ("sei", "");
7639 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7641 pushReg (hc08_reg_a, FALSE);
7643 hc08_freeReg (hc08_reg_a);
7645 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7648 /*-----------------------------------------------------------------*/
7649 /* genEndCritical - generate code for end of a critical sequence */
7650 /*-----------------------------------------------------------------*/
7652 genEndCritical (iCode *ic)
7654 D(emitcode("; genEndCritical",""));
7658 aopOp (IC_RIGHT (ic), ic, FALSE);
7659 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7660 emitcode ("tap", "");
7661 hc08_freeReg (hc08_reg_a);
7662 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7666 pullReg (hc08_reg_a);
7667 emitcode ("tap", "");
7673 /*-----------------------------------------------------------------*/
7674 /* genhc08Code - generate code for HC08 based controllers */
7675 /*-----------------------------------------------------------------*/
7677 genhc08Code (iCode * lic)
7684 lineHead = lineCurr = NULL;
7686 /* print the allocation information */
7687 if (allocInfo && currFunc)
7688 printAllocInfo (currFunc, codeOutFile);
7689 /* if debug information required */
7690 if (options.debug && currFunc)
7692 debugFile->writeFunction (currFunc, lic);
7695 if (IS_STATIC (currFunc->etype))
7696 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7698 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7702 /* stack pointer name */
7703 if (options.useXstack)
7708 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
7710 hc08_aop_pass[0] = newAsmop (AOP_REG);
7711 hc08_aop_pass[0]->size=1;
7712 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7713 hc08_aop_pass[1] = newAsmop (AOP_REG);
7714 hc08_aop_pass[1]->size=1;
7715 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7716 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7717 hc08_aop_pass[2]->size=1;
7718 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7719 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7720 hc08_aop_pass[3]->size=1;
7721 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7723 for (ic = lic; ic; ic = ic->next)
7726 _G.current_iCode = ic;
7728 if (ic->level != clevel || ic->block != cblock)
7732 debugFile->writeScope(ic);
7738 if (ic->lineno && cln != ic->lineno)
7742 debugFile->writeCLine(ic);
7745 emitcode ("", "C$%s$%d$%d$%d ==.",
7746 FileBaseName (ic->filename), ic->lineno,
7747 ic->level, ic->block);
7751 if (!options.noCcodeInAsm) {
7752 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7753 printCLine(ic->filename, ic->lineno));
7757 if (options.iCodeInAsm) {
7761 for (i=0; i<6; i++) {
7762 sprintf (®sInUse[i],
7763 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7766 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7768 /* if the result is marked as
7769 spilt and rematerializable or code for
7770 this has already been generated then
7772 if (resultRemat (ic) || ic->generated)
7780 for (i=A_IDX;i<=XA_IDX;i++)
7782 reg = hc08_regWithIdx(i);
7784 emitcode("","; %s = %s offset %d", reg->name,
7785 aopName(reg->aop), reg->aopofs);
7788 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7790 sym = OP_SYMBOL (IC_LEFT (ic));
7791 if (sym->accuse == ACCUSE_HX)
7793 hc08_reg_h->isFree = FALSE;
7794 hc08_reg_x->isFree = FALSE;
7796 else if (sym->accuse == ACCUSE_XA)
7798 hc08_reg_a->isFree = FALSE;
7800 hc08_reg_x->isFree = FALSE;
7803 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7805 sym = OP_SYMBOL (IC_RIGHT (ic));
7806 if (sym->accuse == ACCUSE_HX)
7808 hc08_reg_h->isFree = FALSE;
7809 hc08_reg_x->isFree = FALSE;
7811 else if (sym->accuse == ACCUSE_XA)
7813 hc08_reg_a->isFree = FALSE;
7815 hc08_reg_x->isFree = FALSE;
7820 /* depending on the operation */
7840 /* IPOP happens only when trying to restore a
7841 spilt live range, if there is an ifx statement
7842 following this pop then the if statement might
7843 be using some of the registers being popped which
7844 would destory the contents of the register so
7845 we need to check for this condition and handle it */
7847 ic->next->op == IFX &&
7848 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7849 genIfx (ic->next, ic);
7867 genEndFunction (ic);
7883 if (!genPointerGetSetOfs (ic))
7888 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7905 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7909 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7916 /* note these two are xlated by algebraic equivalence
7917 during parsing SDCC.y */
7918 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7919 "got '>=' or '<=' shouldn't have come here");
7923 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7935 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7939 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7943 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7970 case GET_VALUE_AT_ADDRESS:
7972 hasInc (IC_LEFT (ic), ic,
7973 getSize (operandType (IC_RESULT (ic)))),
7974 ifxForOp (IC_RESULT (ic), ic) );
7978 if (POINTER_SET (ic))
7979 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8005 addSet (&_G.sendSet, ic);
8008 case DUMMY_READ_VOLATILE:
8017 genEndCritical (ic);
8028 if (!hc08_reg_a->isFree)
8029 D(emitcode("","; forgot to free a"));
8030 if (!hc08_reg_x->isFree)
8031 D(emitcode("","; forgot to free x"));
8032 if (!hc08_reg_h->isFree)
8033 D(emitcode("","; forgot to free h"));
8034 if (!hc08_reg_hx->isFree)
8035 D(emitcode("","; forgot to free hx"));
8036 if (!hc08_reg_xa->isFree)
8037 D(emitcode("","; forgot to free xa"));
8040 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8043 /* now we are ready to call the
8044 peep hole optimizer */
8045 if (!options.nopeep)
8046 peepHole (&lineHead);
8048 /* now do the actual printing */
8049 printLine (lineHead, codeOutFile);