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 (strcmp (sym1->rname, sym2->rname) == 0)
1549 /* if left is a tmp & right is not */
1550 if (IS_ITEMP (op1) &&
1553 (sym1->usl.spillLoc == sym2))
1556 if (IS_ITEMP (op2) &&
1560 (sym2->usl.spillLoc == sym1))
1566 /*-----------------------------------------------------------------*/
1567 /* sameRegs - two asmops have the same registers */
1568 /*-----------------------------------------------------------------*/
1570 sameRegs (asmop * aop1, asmop * aop2)
1577 // if (aop1->size != aop2->size)
1580 if (aop1->type == aop2->type)
1585 for (i = 0; i < aop1->size; i++)
1586 if (aop1->aopu.aop_reg[i] !=
1587 aop2->aopu.aop_reg[i])
1591 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1594 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1601 /*-----------------------------------------------------------------*/
1602 /* aopOp - allocates an asmop for an operand : */
1603 /*-----------------------------------------------------------------*/
1605 aopOp (operand * op, iCode * ic, bool result)
1614 // Is this a pointer set result?
1616 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1620 // printf("checking literal\n");
1621 /* if this a literal */
1622 if (IS_OP_LITERAL (op))
1624 op->aop = aop = newAsmop (AOP_LIT);
1625 aop->aopu.aop_lit = op->operand.valOperand;
1626 aop->size = getSize (operandType (op));
1628 aop->isaddr = op->isaddr;
1632 // printf("checking pre-existing\n");
1633 /* if already has a asmop then continue */
1637 op->aop->isaddr = op->isaddr;
1641 // printf("checking underlying sym\n");
1642 /* if the underlying symbol has a aop */
1643 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1645 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1646 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1647 //op->aop = aop = OP_SYMBOL (op)->aop;
1648 aop->size = getSize( operandType (op));
1649 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1650 //printf (" with size = %d\n", aop->size);
1653 aop->isaddr = op->isaddr;
1654 /* if (aop->isaddr & IS_ITEMP (op))
1656 aop->psize=aop->size;
1657 aop->size = getSize( operandType (op)->next);
1662 // printf("checking true sym\n");
1663 /* if this is a true symbol */
1664 if (IS_TRUE_SYMOP (op))
1666 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1668 aop->isaddr = op->isaddr;
1669 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1670 //printf (" with size = %d\n", aop->size);
1674 /* this is a temporary : this has
1680 e) can be a return use only */
1682 sym = OP_SYMBOL (op);
1684 // printf("checking conditional\n");
1685 /* if the type is a conditional */
1686 if (sym->regType == REG_CND)
1688 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1691 aop->isaddr = op->isaddr;
1695 // printf("checking spilt\n");
1696 /* if it is spilt then two situations
1698 b) has a spill location */
1699 if (sym->isspilt || sym->nRegs == 0)
1702 // printf("checking remat\n");
1703 /* rematerialize it NOW */
1706 sym->aop = op->aop = aop =
1708 aop->size = getSize (sym->type);
1710 aop->isaddr = op->isaddr;
1711 /* if (aop->isaddr & IS_ITEMP (op))
1713 aop->psize=aop->size;
1714 aop->size = getSize( operandType (op)->next);
1719 // printf("checking accuse\n");
1722 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1723 aop->size = getSize (sym->type);
1724 switch (sym->accuse)
1727 aop->aopu.aop_reg[0] = hc08_reg_a;
1728 aop->aopu.aop_reg[1] = hc08_reg_x;
1731 aop->aopu.aop_reg[0] = hc08_reg_x;
1732 aop->aopu.aop_reg[1] = hc08_reg_h;
1736 aop->isaddr = op->isaddr;
1740 // printf("checking ruonly\n");
1746 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1747 aop->size = getSize (sym->type);
1748 for (i = 0; i < fReturnSizeHC08; i++)
1749 aop->aopu.aop_str[i] = fReturn2[i];
1751 aop->isaddr = op->isaddr;
1755 /* else spill location */
1756 if (sym->usl.spillLoc)
1758 if (sym->usl.spillLoc->aop
1759 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1761 /* force a new aop if sizes differ */
1762 sym->usl.spillLoc->aop = NULL;
1763 //printf ("forcing new aop\n");
1765 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1766 aop->size = getSize (sym->type);
1768 aop->isaddr = op->isaddr;
1769 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1770 //printf (" with size = %d\n", aop->size);
1774 /* else must be a dummy iTemp */
1775 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1776 aop->size = getSize (sym->type);
1780 // printf("assuming register\n");
1781 /* must be in a register */
1782 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1783 aop->size = sym->nRegs;
1784 for (i = 0; i < sym->nRegs; i++)
1785 aop->aopu.aop_reg[i] = sym->regs[i];
1787 aop->isaddr = op->isaddr;
1791 /*-----------------------------------------------------------------*/
1792 /* freeAsmop - free up the asmop given to an operand */
1793 /*----------------------------------------------------------------*/
1795 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1817 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1820 for (loffset=0; loffset<aop->size; loffset++)
1821 if (aop->stk_aop[loffset])
1823 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1826 pullNull (stackAdjust);
1830 /* all other cases just dealloc */
1836 OP_SYMBOL (op)->aop = NULL;
1837 /* if the symbol has a spill */
1839 SPIL_LOC (op)->aop = NULL;
1845 /*-----------------------------------------------------------------*/
1846 /* aopDerefAop - treating the aop parameter as a pointer, return */
1847 /* an asmop for the object it references */
1848 /*-----------------------------------------------------------------*/
1850 aopDerefAop (asmop *aop)
1855 asmop *newaop = NULL;
1856 sym_link *type, *etype;
1859 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1863 type = operandType (aop->op);
1864 etype = getSpec (type);
1865 /* if op is of type of pointer then it is simple */
1866 if (IS_PTR (type) && !IS_FUNC (type->next))
1867 p_type = DCL_TYPE (type);
1870 /* we have to go by the storage class */
1871 p_type = PTR_TYPE (SPEC_OCLS (etype));
1880 if (p_type == POINTER)
1881 newaop = newAsmop (AOP_DIR);
1883 newaop = newAsmop (AOP_EXT);
1884 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1887 adr = (int) floatFromVal (aop->aopu.aop_lit);
1888 if (p_type == POINTER)
1893 newaop = newAsmop (AOP_DIR);
1894 sprintf (s, "0x%02x",adr);
1898 newaop = newAsmop (AOP_EXT);
1899 sprintf (s, "0x%04x",adr);
1901 rs = Safe_calloc (1, strlen (s) + 1);
1903 newaop->aopu.aop_dir = rs;
1906 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1907 "unsupported asmop");
1917 /*-----------------------------------------------------------------*/
1918 /* aopAdrStr - for referencing the address of the aop */
1919 /*-----------------------------------------------------------------*/
1921 aopAdrStr (asmop * aop, int loffset, bool bit16)
1925 int offset = aop->size - 1 - loffset;
1928 /* offset is greater than
1930 if (loffset > (aop->size - 1) &&
1931 aop->type != AOP_LIT)
1934 /* depending on type */
1942 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1943 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1945 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1949 sprintf (s, "#(%s >> %d)",
1950 aop->aopu.aop_immd.aop_immd1,
1954 aop->aopu.aop_immd.aop_immd1);
1958 aop->aopu.aop_immd.aop_immd1);
1959 rs = Safe_calloc (1, strlen (s) + 1);
1965 sprintf (s, "*(%s + %d)",
1969 sprintf (s, "*%s", aop->aopu.aop_dir);
1970 rs = Safe_calloc (1, strlen (s) + 1);
1976 sprintf (s, "(%s + %d)",
1980 sprintf (s, "%s", aop->aopu.aop_dir);
1981 rs = Safe_calloc (1, strlen (s) + 1);
1986 return aop->aopu.aop_reg[loffset]->name;
1990 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
1992 return aopLiteral (aop->aopu.aop_lit, loffset);
1996 return aop->aopu.aop_str[loffset];
1999 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2001 rs = Safe_calloc (1, strlen (s) + 1);
2007 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2008 "aopAdrStr got unsupported aop->type");
2017 /*-----------------------------------------------------------------*/
2018 /* opIsGptr: returns non-zero if the passed operand is */
2019 /* a generic pointer type. */
2020 /*-----------------------------------------------------------------*/
2022 opIsGptr (operand * op)
2024 sym_link *type = operandType (op);
2026 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2034 /*-----------------------------------------------------------------*/
2035 /* getDataSize - get the operand data size */
2036 /*-----------------------------------------------------------------*/
2038 getDataSize (operand * op)
2041 size = AOP_SIZE (op);
2045 /*-----------------------------------------------------------------*/
2046 /* outAcc - output Acc */
2047 /*-----------------------------------------------------------------*/
2049 outAcc (operand * result)
2052 size = getDataSize (result);
2055 storeRegToAop (hc08_reg_a, AOP (result), 0);
2058 /* unsigned or positive */
2061 storeConstToAop (zero, AOP (result), offset++);
2066 /*-----------------------------------------------------------------*/
2067 /* outBitC - output a bit C */
2068 /*-----------------------------------------------------------------*/
2070 outBitC (operand * result)
2074 /* if the result is bit */
2075 if (AOP_TYPE (result) == AOP_CRY)
2076 aopPut (AOP (result), "c", 0);
2080 emitcode ("clra", "");
2081 emitcode ("rola", "");
2086 /*-----------------------------------------------------------------*/
2087 /* outBitNV - output a bit N^V */
2088 /*-----------------------------------------------------------------*/
2090 outBitNV (operand * result)
2092 symbol *tlbl, *tlbl1;
2094 tlbl = newiTempLabel (NULL);
2095 tlbl1 = newiTempLabel (NULL);
2097 emitBranch ("blt", tlbl);
2098 loadRegFromConst (hc08_reg_a, zero);
2099 emitBranch ("bra", tlbl1);
2101 loadRegFromConst (hc08_reg_a, one);
2107 /*-----------------------------------------------------------------*/
2108 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2109 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2110 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2111 /*-----------------------------------------------------------------*/
2113 asmopToBool (asmop *aop, bool resultInA)
2115 symbol *tlbl, *tlbl1;
2116 int size = aop->size;
2117 bool needpula = FALSE;
2118 bool flagsonly = TRUE;
2123 hc08_freeReg(hc08_reg_a);
2130 emitcode ("tsta", "");
2133 else if (IS_AOP_X(aop))
2134 emitcode ("tstx", "");
2135 else if (IS_AOP_H(aop))
2137 if (hc08_reg_a->isFree)
2139 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2140 emitcode ("tsta", "");
2142 hc08_freeReg(hc08_reg_a);
2144 else if (hc08_reg_x->isFree)
2146 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2147 emitcode ("tstx", "");
2148 hc08_freeReg(hc08_reg_x);
2152 emitcode ("pshh", "");
2153 emitcode ("tst", "1,s");
2154 emitcode ("ais", "#1");
2157 else if (IS_AOP_HX(aop))
2158 emitcode ("cphx", zero);
2159 else if (IS_AOP_XA(aop))
2161 symbol *tlbl = newiTempLabel (NULL);
2162 emitcode ("tsta", "");
2163 emitcode ("bne", "%05d$", (tlbl->key + 100));
2164 emitcode ("tstx", "");
2165 emitcode ("", "%05d$:", (tlbl->key + 100));
2169 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2170 "Bad rIdx in asmToBool");
2178 needpula = pushRegIfUsed (hc08_reg_a);
2179 loadRegFromAop (hc08_reg_a, aop, 0);
2180 for (offset=1; offset<size; offset++)
2181 accopWithAop ("ora", aop, offset);
2183 pullReg (hc08_reg_a);
2186 hc08_freeReg (hc08_reg_a);
2195 loadRegFromAop (hc08_reg_a, aop, 0);
2196 hc08_freeReg (hc08_reg_a);
2200 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2205 if (hc08_reg_a->isFree)
2207 loadRegFromAop (hc08_reg_a, aop, 0);
2208 accopWithAop ("ora", aop, 1);
2209 hc08_freeReg (hc08_reg_a);
2214 tlbl = newiTempLabel (NULL);
2215 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2216 emitcode ("bne", "%05d$", (tlbl->key + 100));
2217 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2218 emitcode ("", "%05d$:", (tlbl->key + 100));
2224 needpula = pushRegIfUsed (hc08_reg_a);
2225 loadRegFromAop (hc08_reg_a, aop, 0);
2226 for (offset=1; offset<size; offset++)
2227 accopWithAop ("ora", aop, offset);
2229 pullReg (hc08_reg_a);
2232 hc08_freeReg (hc08_reg_a);
2240 tlbl = newiTempLabel (NULL);
2244 tlbl1 = newiTempLabel (NULL);
2245 emitBranch ("bne", tlbl1);
2246 loadRegFromConst (hc08_reg_a, zero);
2247 emitBranch ("bra", tlbl);
2249 loadRegFromConst (hc08_reg_a, one);
2253 emitBranch ("beq", tlbl);
2254 loadRegFromConst (hc08_reg_a, one);
2257 hc08_useReg (hc08_reg_a);
2263 /*-----------------------------------------------------------------*/
2264 /* genNot - generate code for ! operation */
2265 /*-----------------------------------------------------------------*/
2269 D(emitcode ("; genNot",""));
2271 /* assign asmOps to operand & result */
2272 aopOp (IC_LEFT (ic), ic, FALSE);
2273 aopOp (IC_RESULT (ic), ic, TRUE);
2275 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2276 emitcode ("eor", one);
2277 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2279 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2280 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2284 /*-----------------------------------------------------------------*/
2285 /* genCpl - generate code for complement */
2286 /*-----------------------------------------------------------------*/
2292 regs* reg = hc08_reg_a;
2296 D(emitcode ("; genCpl",""));
2298 /* assign asmOps to operand & result */
2299 aopOp (IC_LEFT (ic), ic, FALSE);
2300 aopOp (IC_RESULT (ic), ic, TRUE);
2302 size = AOP_SIZE (IC_RESULT (ic));
2305 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2306 rmwWithReg ("com", reg);
2308 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2312 /* release the aops */
2313 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2314 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2317 /*-----------------------------------------------------------------*/
2318 /* genUminusFloat - unary minus for floating points */
2319 /*-----------------------------------------------------------------*/
2321 genUminusFloat (operand * op, operand * result)
2323 int size, offset = 0;
2326 D(emitcode ("; genUminusFloat",""));
2328 /* for this we just copy and then flip the bit */
2330 size = AOP_SIZE (op) - 1;
2336 needpula = pushRegIfUsed (hc08_reg_a);
2337 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2338 emitcode ("eor", "#0x80");
2339 hc08_useReg (hc08_reg_a);
2340 storeRegToAop (hc08_reg_a, AOP (result), offset);
2341 pullOrFreeReg (hc08_reg_a, needpula);
2344 transferAopAop (AOP (op), offset, AOP (result), offset);
2350 /*-----------------------------------------------------------------*/
2351 /* genUminus - unary minus code generation */
2352 /*-----------------------------------------------------------------*/
2354 genUminus (iCode * ic)
2357 sym_link *optype, *rtype;
2362 D(emitcode ("; genUminus",""));
2365 aopOp (IC_LEFT (ic), ic, FALSE);
2366 aopOp (IC_RESULT (ic), ic, TRUE);
2368 optype = operandType (IC_LEFT (ic));
2369 rtype = operandType (IC_RESULT (ic));
2371 /* if float then do float stuff */
2372 if (IS_FLOAT (optype))
2374 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2378 /* otherwise subtract from zero */
2379 size = AOP_SIZE (IC_LEFT (ic));
2384 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2385 needpula = pushRegIfUsed (hc08_reg_a);
2388 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2389 emitcode ("nega", "");
2390 hc08_freeReg (hc08_reg_a);
2391 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2392 SPEC_USIGN (operandType (IC_LEFT (ic))));
2393 pullOrFreeReg (hc08_reg_a, needpula);
2397 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2398 result = forceStackedAop (AOP (IC_RESULT (ic)));
2400 result = AOP (IC_RESULT (ic));
2402 needpula = pushRegIfUsed (hc08_reg_a);
2406 loadRegFromConst (hc08_reg_a, zero);
2407 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2408 storeRegToAop (hc08_reg_a, result, offset++);
2411 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2412 SPEC_USIGN (operandType (IC_LEFT (ic))));
2413 pullOrFreeReg (hc08_reg_a, needpula);
2415 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2416 freeAsmop (NULL, result, ic, TRUE);
2422 /* release the aops */
2423 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2424 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2427 /*-----------------------------------------------------------------*/
2428 /* saveRegisters - will look for a call and save the registers */
2429 /*-----------------------------------------------------------------*/
2431 saveRegisters (iCode * lic)
2438 for (ic = lic; ic; ic = ic->next)
2439 if (ic->op == CALL || ic->op == PCALL)
2444 fprintf (stderr, "found parameter push with no function call\n");
2448 /* if the registers have been saved already or don't need to be then
2452 if (IS_SYMOP(IC_LEFT(ic)) &&
2453 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2454 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2457 /* safe the registers in use at this time but skip the
2458 ones for the result */
2459 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2460 hc08_rUmaskForOp (IC_RESULT(ic)));
2463 for (i = 0; i < hc08_nRegs; i++)
2465 if (bitVectBitValue (rsave, i))
2466 pushReg ( hc08_regWithIdx (i), FALSE);
2470 /*-----------------------------------------------------------------*/
2471 /* unsaveRegisters - pop the pushed registers */
2472 /*-----------------------------------------------------------------*/
2474 unsaveRegisters (iCode * ic)
2479 /* restore the registers in use at this time but skip the
2480 ones for the result */
2481 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2482 hc08_rUmaskForOp (IC_RESULT(ic)));
2484 for (i = hc08_nRegs; i >= 0; i--)
2486 if (bitVectBitValue (rsave, i))
2487 pullReg ( hc08_regWithIdx (i));
2493 /*-----------------------------------------------------------------*/
2495 /*-----------------------------------------------------------------*/
2497 pushSide (operand * oper, int size)
2502 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2503 pushReg ( hc08_reg_a, TRUE);
2507 /*-----------------------------------------------------------------*/
2508 /* assignResultValue - */
2509 /*-----------------------------------------------------------------*/
2511 assignResultValue (operand * oper)
2513 int size = AOP_SIZE (oper);
2517 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2518 if (hc08_aop_pass[offset]->type == AOP_REG)
2519 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2526 /*-----------------------------------------------------------------*/
2527 /* genIpush - genrate code for pushing this gets a little complex */
2528 /*-----------------------------------------------------------------*/
2530 genIpush (iCode * ic)
2532 int size, offset = 0;
2535 D(emitcode ("; genIpush",""));
2537 /* if this is not a parm push : ie. it is spill push
2538 and spill push is always done on the local stack */
2542 /* and the item is spilt then do nothing */
2543 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2546 aopOp (IC_LEFT (ic), ic, FALSE);
2547 size = AOP_SIZE (IC_LEFT (ic));
2549 /* push it on the stack */
2552 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2553 pushReg ( hc08_reg_a, TRUE);
2559 /* this is a paramter push: in this case we call
2560 the routine to find the call and save those
2561 registers that need to be saved */
2564 /* then do the push */
2565 aopOp (IC_LEFT (ic), ic, FALSE);
2568 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2569 size = AOP_SIZE (IC_LEFT (ic));
2572 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2573 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2575 if ((size==2) && hc08_reg_hx->isFree)
2577 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2578 pushReg (hc08_reg_hx, TRUE);
2585 // printf("loading %d\n", offset);
2586 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2587 // printf("pushing \n");
2588 pushReg (hc08_reg_a, TRUE);
2592 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2595 /*-----------------------------------------------------------------*/
2596 /* genIpop - recover the registers: can happen only for spilling */
2597 /*-----------------------------------------------------------------*/
2599 genIpop (iCode * ic)
2603 D(emitcode ("; genIpop",""));
2605 /* if the temp was not pushed then */
2606 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2609 aopOp (IC_LEFT (ic), ic, FALSE);
2610 size = AOP_SIZE (IC_LEFT (ic));
2614 pullReg (hc08_reg_a);
2615 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2617 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2621 /*-----------------------------------------------------------------*/
2622 /* genSend - gen code for SEND */
2623 /*-----------------------------------------------------------------*/
2624 static void genSend(set *sendSet)
2628 for (sic = setFirstItem (_G.sendSet); sic;
2629 sic = setNextItem (_G.sendSet)) {
2630 int size, offset = 0;
2631 aopOp (IC_LEFT (sic), sic, FALSE);
2632 size = AOP_SIZE (IC_LEFT (sic));
2637 transferAopAop( AOP (IC_LEFT (sic)), offset,
2638 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2642 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2646 /*-----------------------------------------------------------------*/
2647 /* genCall - generates a call statement */
2648 /*-----------------------------------------------------------------*/
2650 genCall (iCode * ic)
2653 // bool restoreBank = FALSE;
2654 // bool swapBanks = FALSE;
2656 D(emitcode("; genCall",""));
2658 dtype = operandType (IC_LEFT (ic));
2659 /* if send set is not empty the assign */
2662 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2663 genSend(reverseSet(_G.sendSet));
2665 genSend(_G.sendSet);
2671 /* if caller saves & we have not saved then */
2677 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2678 OP_SYMBOL (IC_LEFT (ic))->rname :
2679 OP_SYMBOL (IC_LEFT (ic))->name));
2682 /* if we need assign a result value */
2683 if ((IS_ITEMP (IC_RESULT (ic)) &&
2684 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2685 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2686 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2687 IS_TRUE_SYMOP (IC_RESULT (ic)))
2691 aopOp (IC_RESULT (ic), ic, FALSE);
2694 assignResultValue (IC_RESULT (ic));
2696 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2699 /* adjust the stack for parameters if
2703 pullNull (ic->parmBytes);
2706 /* if we had saved some registers then unsave them */
2707 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2708 unsaveRegisters (ic);
2712 /*-----------------------------------------------------------------*/
2713 /* -10l - generates a call by pointer statement */
2714 /*-----------------------------------------------------------------*/
2716 genPcall (iCode * ic)
2719 symbol *rlbl = newiTempLabel (NULL);
2720 symbol *tlbl = newiTempLabel (NULL);
2721 // bool restoreBank=FALSE;
2722 // bool swapBanks = FALSE;
2724 D(emitcode("; genPCall",""));
2726 /* if caller saves & we have not saved then */
2730 /* if we are calling a not _naked function that is not using
2731 the same register bank then we need to save the
2732 destination registers on the stack */
2733 dtype = operandType (IC_LEFT (ic))->next;
2735 /* now push the calling address */
2736 emitBranch ("bsr", tlbl);
2737 emitBranch ("bra", rlbl);
2740 /* Push the function's address */
2741 aopOp (IC_LEFT (ic), ic, FALSE);
2742 pushSide (IC_LEFT (ic), FPTRSIZE);
2743 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2745 /* if send set is not empty the assign */
2748 genSend(reverseSet(_G.sendSet));
2754 emitcode ("rts", "");
2759 /* if we need assign a result value */
2760 if ((IS_ITEMP (IC_RESULT (ic)) &&
2761 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2762 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2763 IS_TRUE_SYMOP (IC_RESULT (ic)))
2767 aopOp (IC_RESULT (ic), ic, FALSE);
2770 assignResultValue (IC_RESULT (ic));
2772 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2775 /* adjust the stack for parameters if
2779 pullNull (ic->parmBytes);
2782 /* if we hade saved some registers then
2784 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2785 unsaveRegisters (ic);
2788 /*-----------------------------------------------------------------*/
2789 /* resultRemat - result is rematerializable */
2790 /*-----------------------------------------------------------------*/
2792 resultRemat (iCode * ic)
2794 if (SKIP_IC (ic) || ic->op == IFX)
2797 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2799 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2800 if (sym->remat && !POINTER_SET (ic))
2807 #if defined(__BORLANDC__) || defined(_MSC_VER)
2808 #define STRCASECMP stricmp
2810 #define STRCASECMP strcasecmp
2813 /*-----------------------------------------------------------------*/
2814 /* inExcludeList - return 1 if the string is in exclude Reg list */
2815 /*-----------------------------------------------------------------*/
2817 regsCmp(void *p1, void *p2)
2819 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2823 inExcludeList (char *s)
2825 const char *p = setFirstItem(options.excludeRegsSet);
2827 if (p == NULL || STRCASECMP(p, "none") == 0)
2831 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2834 /*-----------------------------------------------------------------*/
2835 /* genFunction - generated code for function entry */
2836 /*-----------------------------------------------------------------*/
2838 genFunction (iCode * ic)
2842 int calleesaves_saved_register = -1;
2846 /* create the function header */
2847 emitcode (";", "-----------------------------------------");
2848 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2849 emitcode (";", "-----------------------------------------");
2851 emitcode ("", "%s:", sym->rname);
2852 ftype = operandType (IC_LEFT (ic));
2856 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2858 if (IFFUNC_ISNAKED(ftype))
2860 emitcode(";", "naked function: no prologue.");
2866 /* if this is an interrupt service routine then
2868 if (IFFUNC_ISISR (sym->type))
2871 if (!inExcludeList ("h"))
2872 pushReg (hc08_reg_h, FALSE);
2876 /* if callee-save to be used for this function
2877 then save the registers being used in this function */
2878 if (IFFUNC_CALLEESAVES(sym->type))
2882 /* if any registers used */
2885 /* save the registers used */
2886 for (i = 0; i < sym->regsUsed->size; i++)
2888 if (bitVectBitValue (sym->regsUsed, i))
2890 /* remember one saved register for later usage */
2891 if (calleesaves_saved_register < 0)
2892 calleesaves_saved_register = i;
2893 pushReg (hc08_regWithIdx (i), FALSE);
2901 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2906 /* adjust the stack for the function */
2912 // werror (W_STACK_OVERFLOW, sym->name);
2916 _G.stackOfs = sym->stack;
2919 /* if critical function then turn interrupts off */
2920 if (IFFUNC_ISCRITICAL (ftype))
2922 if (IFFUNC_ARGS (ftype))
2924 /* Function was passed parameters, so make sure A is preserved */
2925 pushReg (hc08_reg_a, FALSE);
2926 pushReg (hc08_reg_a, FALSE);
2927 emitcode ("tpa", "");
2928 emitcode ("sta", "2,s");
2929 emitcode ("sei", "");
2930 pullReg (hc08_reg_a);
2934 /* No passed parameters, so A can be freely modified */
2935 emitcode ("tpa", "");
2936 pushReg (hc08_reg_a, TRUE);
2937 emitcode ("sei", "");
2943 /*-----------------------------------------------------------------*/
2944 /* genEndFunction - generates epilogue for functions */
2945 /*-----------------------------------------------------------------*/
2947 genEndFunction (iCode * ic)
2949 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2951 if (IFFUNC_ISNAKED(sym->type))
2953 emitcode(";", "naked function: no epilogue.");
2954 if (options.debug && currFunc)
2955 debugFile->writeEndFunction (currFunc, ic, 0);
2959 if (IFFUNC_ISCRITICAL (sym->type))
2961 if (!IS_VOID(sym->type->next))
2963 /* Function has return value, so make sure A is preserved */
2964 pushReg (hc08_reg_a, FALSE);
2965 emitcode ("lda", "2,s");
2966 emitcode ("tap", "");
2967 pullReg (hc08_reg_a);
2972 /* Function returns void, so A can be freely modified */
2973 pullReg (hc08_reg_a);
2974 emitcode ("tap", "");
2978 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2984 _G.stackPushes += sym->stack;
2985 adjustStack (sym->stack);
2989 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2993 if (IFFUNC_ISISR (sym->type))
2996 if (!inExcludeList ("h"))
2997 pullReg (hc08_reg_h);
3000 /* if debug then send end of function */
3001 if (options.debug && currFunc)
3003 debugFile->writeEndFunction (currFunc, ic, 1);
3006 emitcode ("rti", "");
3010 if (IFFUNC_CALLEESAVES(sym->type))
3014 /* if any registers used */
3017 /* save the registers used */
3018 for (i = sym->regsUsed->size; i >= 0; i--)
3020 if (bitVectBitValue (sym->regsUsed, i) ||
3021 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3022 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3028 /* if debug then send end of function */
3029 if (options.debug && currFunc)
3031 debugFile->writeEndFunction (currFunc, ic, 1);
3034 emitcode ("rts", "");
3039 /*-----------------------------------------------------------------*/
3040 /* genRet - generate code for return statement */
3041 /*-----------------------------------------------------------------*/
3045 int size, offset = 0;
3048 D(emitcode ("; genRet",""));
3050 /* if we have no return value then
3051 just generate the "ret" */
3055 /* we have something to return then
3056 move the return value into place */
3057 aopOp (IC_LEFT (ic), ic, FALSE);
3058 size = AOP_SIZE (IC_LEFT (ic));
3064 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3071 /* 4 byte return: store value in the global return variable */
3075 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3076 STA (fReturn2[offset--], FALSE);
3077 hc08_freeReg (hc08_reg_a);
3081 /* 2 byte return: store value in x:a */
3082 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3083 hc08_freeReg (hc08_reg_xa);
3086 /* 1 byte return: store value in a */
3087 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3088 hc08_freeReg (hc08_reg_a);
3093 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3096 /* generate a jump to the return label
3097 if the next is not the return statement */
3098 if (!(ic->next && ic->next->op == LABEL &&
3099 IC_LABEL (ic->next) == returnLabel))
3101 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3105 /*-----------------------------------------------------------------*/
3106 /* genLabel - generates a label */
3107 /*-----------------------------------------------------------------*/
3109 genLabel (iCode * ic)
3114 /* For the high level labels we cannot depend on any */
3115 /* register's contents. Amnesia time. */
3116 for (i=A_IDX;i<=XA_IDX;i++)
3118 reg = hc08_regWithIdx(i);
3123 /* special case never generate */
3124 if (IC_LABEL (ic) == entryLabel)
3127 debugFile->writeLabel(IC_LABEL (ic), ic);
3129 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3133 /*-----------------------------------------------------------------*/
3134 /* genGoto - generates a jmp */
3135 /*-----------------------------------------------------------------*/
3137 genGoto (iCode * ic)
3139 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3143 /*-----------------------------------------------------------------*/
3144 /* findLabelBackwards: walks back through the iCode chain looking */
3145 /* for the given label. Returns number of iCode instructions */
3146 /* between that label and given ic. */
3147 /* Returns zero if label not found. */
3148 /*-----------------------------------------------------------------*/
3150 findLabelBackwards (iCode * ic, int key)
3159 /* If we have any pushes or pops, we cannot predict the distance.
3160 I don't like this at all, this should be dealt with in the
3162 if (ic->op == IPUSH || ic->op == IPOP) {
3166 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3176 /*-----------------------------------------------------------------*/
3177 /* genPlusIncr :- does addition with increment if possible */
3178 /*-----------------------------------------------------------------*/
3180 genPlusIncr (iCode * ic)
3188 unsigned int size = getDataSize (IC_RESULT (ic));
3190 symbol *tlbl = NULL;
3192 left = IC_LEFT (ic);
3193 result = IC_RESULT (ic);
3195 /* will try to generate an increment */
3196 /* if the right side is not a literal
3198 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3201 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3203 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3205 if ((IS_AOP_HX (AOP (left)) ||
3206 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3208 && (icount>=-128) && (icount<=127) && (size==2))
3210 if (!IS_AOP_HX (AOP (left)))
3212 needpulx = pushRegIfUsed (hc08_reg_x);
3213 needpulh = pushRegIfUsed (hc08_reg_h);
3220 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3221 emitcode ("aix","#%d", icount);
3222 hc08_dirtyReg (hc08_reg_hx, FALSE);
3223 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3224 pullOrFreeReg (hc08_reg_h, needpulh);
3225 pullOrFreeReg (hc08_reg_x, needpulx);
3229 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3230 sameRegs (AOP (left), AOP (result))));
3232 if ((icount > 255) || (icount<0))
3235 if (!sameRegs (AOP (left), AOP (result)))
3238 D(emitcode ("; genPlusIncr",""));
3241 tlbl = newiTempLabel (NULL);
3246 rmwWithAop ("inc", AOP (result), 0);
3248 emitBranch ("bne", tlbl);
3252 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3253 needpula = pushRegIfUsed (hc08_reg_a);
3256 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3257 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3258 hc08_useReg (hc08_reg_a);
3259 storeRegToAop (hc08_reg_a, AOP (result), 0);
3260 hc08_freeReg (hc08_reg_a);
3262 emitBranch ("bcc", tlbl);
3264 for (offset=1; offset<size; offset++)
3266 rmwWithAop ("inc", AOP (result), offset);
3267 if ((offset+1)<size)
3268 emitBranch ("bne", tlbl);
3274 pullOrFreeReg (hc08_reg_a, needpula);
3281 /*-----------------------------------------------------------------*/
3282 /* genPlus - generates code for addition */
3283 /*-----------------------------------------------------------------*/
3285 genPlus (iCode * ic)
3287 int size, offset = 0;
3289 asmop *leftOp, *rightOp;
3291 /* special cases :- */
3293 D(emitcode ("; genPlus",""));
3295 aopOp (IC_LEFT (ic), ic, FALSE);
3296 aopOp (IC_RIGHT (ic), ic, FALSE);
3297 aopOp (IC_RESULT (ic), ic, TRUE);
3299 /* we want registers on the left and literals on the right */
3300 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3301 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3303 operand *t = IC_RIGHT (ic);
3304 IC_RIGHT (ic) = IC_LEFT (ic);
3309 /* if I can do an increment instead
3310 of add then GOOD for ME */
3311 if (genPlusIncr (ic) == TRUE)
3314 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3315 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3316 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3318 size = getDataSize (IC_RESULT (ic));
3320 leftOp = AOP(IC_LEFT(ic));
3321 rightOp = AOP(IC_RIGHT(ic));
3327 loadRegFromAop (hc08_reg_a, leftOp, offset);
3328 accopWithAop(add, rightOp, offset);
3329 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3330 hc08_freeReg (hc08_reg_a);
3331 add = "adc"; /* further adds must propagate carry */
3335 // adjustArithmeticResult (ic);
3338 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3339 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3340 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3343 /*-----------------------------------------------------------------*/
3344 /* genMinusDec :- does subtraction with deccrement if possible */
3345 /*-----------------------------------------------------------------*/
3347 genMinusDec (iCode * ic)
3349 unsigned int icount;
3354 unsigned int size = getDataSize (IC_RESULT (ic));
3358 left = IC_LEFT (ic);
3359 result = IC_RESULT (ic);
3361 /* will try to generate an increment */
3362 /* if the right side is not a literal
3364 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3367 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3369 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3370 && (icount>=-127) && (icount<=128) && (size==2))
3372 if (!IS_AOP_HX (AOP (left)))
3374 needpulx = pushRegIfUsed (hc08_reg_x);
3375 needpulh = pushRegIfUsed (hc08_reg_h);
3382 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3383 emitcode ("aix","#%d", -icount);
3384 hc08_dirtyReg (hc08_reg_hx, FALSE);
3385 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3386 pullOrFreeReg (hc08_reg_h, needpulh);
3387 pullOrFreeReg (hc08_reg_x, needpulx);
3391 if ((icount > 1) || (icount<0))
3394 if (!sameRegs (AOP (left), AOP (result)))
3400 D(emitcode ("; genMinusDec",""));
3402 rmwWithAop ("dec", AOP (result), 0);
3407 /*-----------------------------------------------------------------*/
3408 /* addSign - complete with sign */
3409 /*-----------------------------------------------------------------*/
3411 addSign (operand * result, int offset, int sign)
3413 int size = (getDataSize (result) - offset);
3418 emitcode ("rola", "");
3419 emitcode ("clra", "");
3420 emitcode ("sbc", zero);
3422 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3426 storeConstToAop (zero, AOP (result), offset++);
3431 /*-----------------------------------------------------------------*/
3432 /* genMinus - generates code for subtraction */
3433 /*-----------------------------------------------------------------*/
3435 genMinus (iCode * ic)
3438 int size, offset = 0;
3440 asmop *leftOp, *rightOp;
3442 D(emitcode ("; genMinus",""));
3444 aopOp (IC_LEFT (ic), ic, FALSE);
3445 aopOp (IC_RIGHT (ic), ic, FALSE);
3446 aopOp (IC_RESULT (ic), ic, TRUE);
3448 /* special cases :- */
3449 /* if I can do an decrement instead
3450 of subtract then GOOD for ME */
3451 if (genMinusDec (ic) == TRUE)
3454 size = getDataSize (IC_RESULT (ic));
3457 leftOp = AOP(IC_LEFT(ic));
3458 rightOp = AOP(IC_RIGHT(ic));
3464 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3465 accopWithAop(sub, rightOp, offset);
3466 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3471 // adjustArithmeticResult (ic);
3474 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3475 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3476 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3481 /*-----------------------------------------------------------------*/
3482 /* genMultOneByte : 8*8=8/16 bit multiplication */
3483 /*-----------------------------------------------------------------*/
3485 genMultOneByte (operand * left,
3489 /* sym_link *opetype = operandType (result); */
3490 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3491 int size=AOP_SIZE(result);
3492 bool negLiteral = FALSE;
3494 D(emitcode ("; genMultOneByte",""));
3496 if (size<1 || size>2) {
3497 // this should never happen
3498 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3499 AOP_SIZE(result), __FILE__, lineno);
3503 /* (if two literals: the value is computed before) */
3504 /* if one literal, literal on the right */
3505 if (AOP_TYPE (left) == AOP_LIT)
3510 //D(emitcode (";", "swapped left and right"));
3514 || (SPEC_USIGN(operandType(left)) &&
3515 SPEC_USIGN(operandType(right))))
3517 // just an unsigned 8*8=8/16 multiply
3518 //D(emitcode (";","unsigned"));
3520 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3521 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3522 emitcode ("mul", "");
3523 hc08_dirtyReg (hc08_reg_xa, FALSE);
3524 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3525 hc08_freeReg (hc08_reg_xa);
3530 // we have to do a signed multiply
3533 //D(emitcode (";", "signed"));
3535 emitcode ("clr", "1,s");
3537 tlbl1 = newiTempLabel (NULL);
3538 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3539 emitcode ("tsta","");
3540 emitBranch ("bpl", tlbl1);
3541 emitcode ("inc", "1,s");
3542 rmwWithReg ("neg", hc08_reg_a);
3545 if (AOP_TYPE(right)==AOP_LIT)
3547 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3548 /* AND literal negative */
3550 emitcode ("ldx", "#0x%02x", -val);
3553 emitcode ("ldx", "#0x%02x", val);
3555 hc08_useReg (hc08_reg_x);
3559 tlbl2 = newiTempLabel (NULL);
3560 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3561 emitcode ("tstx", "");
3562 emitBranch ("bpl", tlbl2);
3563 emitcode ("inc", "1,s");
3564 rmwWithReg ("neg", hc08_reg_x);
3568 emitcode ("mul", "");
3569 hc08_dirtyReg (hc08_reg_xa, FALSE);
3571 tlbl3 = newiTempLabel (NULL);
3572 emitcode ("dec", "1,s");
3574 emitBranch ("bne", tlbl3);
3576 emitBranch ("beq", tlbl3);
3578 rmwWithReg ("neg", hc08_reg_a);
3581 tlbl4 = newiTempLabel (NULL);
3582 emitBranch ("bcc", tlbl4);
3583 rmwWithReg ("inc", hc08_reg_x);
3585 rmwWithReg ("neg", hc08_reg_x);
3590 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3591 hc08_freeReg (hc08_reg_xa);
3595 /*-----------------------------------------------------------------*/
3596 /* genMult - generates code for multiplication */
3597 /*-----------------------------------------------------------------*/
3599 genMult (iCode * ic)
3601 operand *left = IC_LEFT (ic);
3602 operand *right = IC_RIGHT (ic);
3603 operand *result = IC_RESULT (ic);
3605 D(emitcode ("; genMult",""));
3607 /* assign the amsops */
3608 aopOp (left, ic, FALSE);
3609 aopOp (right, ic, FALSE);
3610 aopOp (result, ic, TRUE);
3612 /* special cases first */
3613 /* if both are of size == 1 */
3614 // if (getSize(operandType(left)) == 1 &&
3615 // getSize(operandType(right)) == 1)
3616 if (AOP_SIZE (left) == 1 &&
3617 AOP_SIZE (right) == 1)
3619 genMultOneByte (left, right, result);
3623 /* should have been converted to function call */
3624 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3625 getSize(OP_SYMBOL(right)->type));
3626 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3631 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3632 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3633 freeAsmop (result, NULL, ic, TRUE);
3636 /*-----------------------------------------------------------------*/
3637 /* genDivOneByte : 8 bit division */
3638 /*-----------------------------------------------------------------*/
3640 genDivOneByte (operand * left,
3644 sym_link *opetype = operandType (result);
3646 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3648 bool negLiteral = FALSE;
3650 D(emitcode ("; genDivOneByte",""));
3652 size = AOP_SIZE (result);
3653 /* signed or unsigned */
3654 if (SPEC_USIGN (opetype))
3656 /* unsigned is easy */
3657 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3658 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3659 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3660 emitcode ("div", "");
3661 hc08_dirtyReg (hc08_reg_a, FALSE);
3662 hc08_dirtyReg (hc08_reg_h, FALSE);
3663 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3664 hc08_freeReg (hc08_reg_a);
3665 hc08_freeReg (hc08_reg_x);
3666 hc08_freeReg (hc08_reg_h);
3670 /* signed is a little bit more difficult */
3673 emitcode ("clr", "1,s");
3675 tlbl1 = newiTempLabel (NULL);
3676 tlbl2 = newiTempLabel (NULL);
3677 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3678 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3679 emitBranch ("bpl", tlbl1);
3680 emitcode ("inc", "1,s");
3681 rmwWithReg ("neg", hc08_reg_a);
3682 emitBranch ("bcc", tlbl2);
3683 rmwWithReg ("inc", hc08_reg_x);
3685 rmwWithReg ("neg", hc08_reg_x);
3686 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3689 if (AOP_TYPE(right)==AOP_LIT)
3691 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3692 /* AND literal negative */
3694 emitcode ("ldx", "#0x%02x", -val);
3697 emitcode ("ldx", "#0x%02x", val);
3699 hc08_useReg (hc08_reg_x);
3703 tlbl3 = newiTempLabel (NULL);
3704 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3705 emitBranch ("bpl", tlbl3);
3706 emitcode ("inc", "1,s");
3707 rmwWithReg ("neg", hc08_reg_x);
3711 emitcode ("div", "");
3712 hc08_dirtyReg (hc08_reg_x, FALSE);
3713 hc08_dirtyReg (hc08_reg_a, FALSE);
3714 hc08_dirtyReg (hc08_reg_h, FALSE);
3716 tlbl4 = newiTempLabel (NULL);
3717 emitcode ("dec", "1,s");
3719 emitBranch ("bne", tlbl4);
3721 emitBranch ("beq", tlbl4);
3722 rmwWithReg ("neg", hc08_reg_a);
3726 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3727 hc08_freeReg (hc08_reg_a);
3728 hc08_freeReg (hc08_reg_x);
3729 hc08_freeReg (hc08_reg_h);
3734 /*-----------------------------------------------------------------*/
3735 /* genDiv - generates code for division */
3736 /*-----------------------------------------------------------------*/
3740 operand *left = IC_LEFT (ic);
3741 operand *right = IC_RIGHT (ic);
3742 operand *result = IC_RESULT (ic);
3744 D(emitcode ("; genDiv",""));
3746 /* assign the amsops */
3747 aopOp (left, ic, FALSE);
3748 aopOp (right, ic, FALSE);
3749 aopOp (result, ic, TRUE);
3751 /* special cases first */
3752 /* if both are of size == 1 */
3753 if (AOP_SIZE (left) <= 2 &&
3754 AOP_SIZE (right) == 1)
3756 genDivOneByte (left, right, result);
3760 /* should have been converted to function call */
3763 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3764 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3765 freeAsmop (result, NULL, ic, TRUE);
3768 /*-----------------------------------------------------------------*/
3769 /* genModOneByte : 8 bit modulus */
3770 /*-----------------------------------------------------------------*/
3772 genModOneByte (operand * left,
3776 sym_link *opetype = operandType (result);
3778 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3780 bool negLiteral = FALSE;
3782 D(emitcode ("; genModOneByte",""));
3784 size = AOP_SIZE (result);
3785 /* signed or unsigned */
3786 if (SPEC_USIGN (opetype))
3788 /* unsigned is easy */
3789 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3790 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3791 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3792 emitcode ("div", "");
3793 hc08_dirtyReg (hc08_reg_a, FALSE);
3794 hc08_dirtyReg (hc08_reg_h, FALSE);
3795 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3796 hc08_freeReg (hc08_reg_a);
3797 hc08_freeReg (hc08_reg_x);
3798 hc08_freeReg (hc08_reg_h);
3802 /* signed is a little bit more difficult */
3805 emitcode ("clr", "1,s");
3807 tlbl1 = newiTempLabel (NULL);
3808 tlbl2 = newiTempLabel (NULL);
3809 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3810 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3811 emitBranch ("bpl", tlbl1);
3812 emitcode ("inc", "1,s");
3813 rmwWithReg ("neg", hc08_reg_a);
3814 emitBranch ("bcc", tlbl2);
3815 rmwWithReg ("inc", hc08_reg_x);
3817 rmwWithReg ("neg", hc08_reg_x);
3818 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3821 if (AOP_TYPE(right)==AOP_LIT)
3823 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3824 /* AND literal negative */
3826 emitcode ("ldx", "#0x%02x", -val);
3829 emitcode ("ldx", "#0x%02x", val);
3831 hc08_useReg (hc08_reg_x);
3835 tlbl3 = newiTempLabel (NULL);
3836 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3837 emitBranch ("bpl", tlbl3);
3838 emitcode ("inc", "1,s");
3839 rmwWithReg ("neg", hc08_reg_x);
3843 emitcode ("div", "");
3844 hc08_dirtyReg (hc08_reg_x, FALSE);
3845 hc08_dirtyReg (hc08_reg_a, FALSE);
3846 hc08_dirtyReg (hc08_reg_h, FALSE);
3848 tlbl4 = newiTempLabel (NULL);
3849 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3850 emitcode ("dec", "1,s");
3852 emitBranch ("bne", tlbl4);
3854 emitBranch ("beq", tlbl4);
3855 rmwWithReg ("neg", hc08_reg_a);
3859 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3860 hc08_freeReg (hc08_reg_a);
3861 hc08_freeReg (hc08_reg_x);
3862 hc08_freeReg (hc08_reg_h);
3866 /*-----------------------------------------------------------------*/
3867 /* genMod - generates code for division */
3868 /*-----------------------------------------------------------------*/
3872 operand *left = IC_LEFT (ic);
3873 operand *right = IC_RIGHT (ic);
3874 operand *result = IC_RESULT (ic);
3876 D(emitcode ("; genMod",""));
3878 /* assign the amsops */
3879 aopOp (left, ic, FALSE);
3880 aopOp (right, ic, FALSE);
3881 aopOp (result, ic, TRUE);
3883 /* special cases first */
3884 /* if both are of size == 1 */
3885 if (AOP_SIZE (left) <= 2 &&
3886 AOP_SIZE (right) == 1)
3888 genModOneByte (left, right, result);
3892 /* should have been converted to function call */
3896 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3897 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3898 freeAsmop (result, NULL, ic, TRUE);
3901 /*-----------------------------------------------------------------*/
3902 /* genIfxJump :- will create a jump depending on the ifx */
3903 /*-----------------------------------------------------------------*/
3905 genIfxJump (iCode * ic, char *jval)
3908 symbol *tlbl = newiTempLabel (NULL);
3911 D(emitcode ("; genIfxJump",""));
3913 /* if true label then we jump if condition
3917 jlbl = IC_TRUE (ic);
3918 if (!strcmp (jval, "a"))
3920 else if (!strcmp (jval, "c"))
3927 /* false label is present */
3928 jlbl = IC_FALSE (ic);
3929 if (!strcmp (jval, "a"))
3931 else if (!strcmp (jval, "c"))
3936 emitBranch (inst, tlbl);
3937 emitBranch ("jmp", jlbl);
3940 /* mark the icode as generated */
3944 /*-----------------------------------------------------------------*/
3945 /* genCmp :- greater or less than comparison */
3946 /*-----------------------------------------------------------------*/
3948 genCmp (operand * left, operand * right,
3949 operand * result, iCode * ifx, int sign, iCode *ic)
3951 int size, offset = 0;
3952 unsigned long lit = 0L;
3954 bool needpula = FALSE;
3956 D(emitcode ("; genCmp",""));
3958 /* subtract right from left if at the
3959 end the carry flag is set then we know that
3960 left is greater than right */
3961 size = max (AOP_SIZE (left), AOP_SIZE (right));
3963 if (AOP_TYPE (right) == AOP_LIT)
3965 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3966 /* optimize if(x < 0) or if(x >= 0) */
3975 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3976 emitcode ("rola", "");
3977 hc08_useReg (hc08_reg_a);
3985 && ((AOP_TYPE (right) == AOP_LIT) ||
3986 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3987 && hc08_reg_hx->isFree)
3989 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3990 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3991 hc08_freeReg (hc08_reg_hx);
4002 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4003 accopWithAop (sub, AOP (right), offset);
4004 hc08_freeReg (hc08_reg_a);
4010 freeAsmop (right, NULL, ic, TRUE);
4011 freeAsmop (left, NULL, ic, TRUE);
4012 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4018 /* if the result is used in the next
4019 ifx conditional branch then generate
4020 code a little differently */
4023 pullOrFreeReg(hc08_reg_a,needpula);
4024 genIfxJump (ifx, sign ? "s" : "c");
4031 pullOrFreeReg(hc08_reg_a,needpula);
4035 /*-----------------------------------------------------------------*/
4036 /* genCmpGt :- greater than comparison */
4037 /*-----------------------------------------------------------------*/
4039 genCmpGt (iCode * ic, iCode * ifx)
4041 operand *left, *right, *result;
4042 sym_link *letype, *retype;
4045 D(emitcode ("; genCmpGt",""));
4047 result = IC_RESULT (ic);
4048 left = IC_LEFT (ic);
4049 right = IC_RIGHT (ic);
4051 letype = getSpec (operandType (left));
4052 retype = getSpec (operandType (right));
4053 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4054 /* assign the amsops */
4055 aopOp (left, ic, FALSE);
4056 aopOp (right, ic, FALSE);
4057 aopOp (result, ic, TRUE);
4059 genCmp (right, left, result, ifx, sign,ic);
4061 freeAsmop (result, NULL, ic, TRUE);
4064 /*-----------------------------------------------------------------*/
4065 /* genCmpLt - less than comparisons */
4066 /*-----------------------------------------------------------------*/
4068 genCmpLt (iCode * ic, iCode * ifx)
4070 operand *left, *right, *result;
4071 sym_link *letype, *retype;
4074 D(emitcode ("; genCmpLt",""));
4076 result = IC_RESULT (ic);
4077 left = IC_LEFT (ic);
4078 right = IC_RIGHT (ic);
4080 letype = getSpec (operandType (left));
4081 retype = getSpec (operandType (right));
4082 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4084 /* assign the amsops */
4085 aopOp (left, ic, FALSE);
4086 aopOp (right, ic, FALSE);
4087 aopOp (result, ic, TRUE);
4089 genCmp (left, right, result, ifx, sign,ic);
4091 freeAsmop (result, NULL, ic, TRUE);
4094 /*-----------------------------------------------------------------*/
4095 /* - compare and branch if not equal */
4096 /*-----------------------------------------------------------------*/
4098 gencbneshort (operand * left, operand * right, symbol * lbl)
4100 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4102 unsigned long lit = 0L;
4104 /* if the left side is a literal or
4105 if the right is in a pointer register and left
4107 if (AOP_TYPE (left) == AOP_LIT)
4113 if (AOP_TYPE (right) == AOP_LIT)
4114 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4118 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4119 accopWithAop ("cmp", AOP (right), offset);
4120 hc08_useReg (hc08_reg_a);
4121 hc08_freeReg (hc08_reg_a);
4122 emitBranch ("bne", lbl);
4128 /*-----------------------------------------------------------------*/
4129 /* gencjne - compare and jump if not equal */
4130 /*-----------------------------------------------------------------*/
4132 gencjne (operand * left, operand * right, symbol * lbl)
4134 symbol *tlbl = newiTempLabel (NULL);
4136 gencbneshort (left, right, lbl);
4138 loadRegFromConst (hc08_reg_a, one);
4139 emitBranch ("bra", tlbl);
4141 loadRegFromConst (hc08_reg_a, zero);
4144 hc08_useReg(hc08_reg_a);
4145 hc08_freeReg(hc08_reg_a);
4148 /*-----------------------------------------------------------------*/
4149 /* genCmpEq - generates code for equal to */
4150 /*-----------------------------------------------------------------*/
4152 genCmpEq (iCode * ic, iCode * ifx)
4154 operand *left, *right, *result;
4156 D(emitcode ("; genCmpEq",""));
4158 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4159 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4160 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4162 /* if literal, literal on the right or
4163 if the right is in a pointer register and left
4165 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4167 operand *t = IC_RIGHT (ic);
4168 IC_RIGHT (ic) = IC_LEFT (ic);
4172 if (ifx && !AOP_SIZE (result))
4175 tlbl = newiTempLabel (NULL);
4176 gencbneshort (left, right, tlbl);
4179 emitBranch ("jmp", IC_TRUE (ifx));
4184 symbol *lbl = newiTempLabel (NULL);
4185 emitBranch ("bra", lbl);
4187 emitBranch ("jmp", IC_FALSE (ifx));
4191 /* mark the icode as generated */
4196 gencjne (left, right, newiTempLabel (NULL));
4197 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4199 storeRegToAop (hc08_reg_a, AOP (result), 0);
4204 genIfxJump (ifx, "a");
4207 /* if the result is used in an arithmetic operation
4208 then put the result in place */
4209 if (AOP_TYPE (result) != AOP_CRY)
4213 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4214 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4215 freeAsmop (result, NULL, ic, TRUE);
4218 /*-----------------------------------------------------------------*/
4219 /* ifxForOp - returns the icode containing the ifx for operand */
4220 /*-----------------------------------------------------------------*/
4222 ifxForOp (operand * op, iCode * ic)
4224 /* if true symbol then needs to be assigned */
4225 if (IS_TRUE_SYMOP (op))
4228 /* if this has register type condition and
4229 the next instruction is ifx with the same operand
4230 and live to of the operand is upto the ifx only then */
4232 ic->next->op == IFX &&
4233 IC_COND (ic->next)->key == op->key &&
4234 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4241 genPointerGetSetOfs (iCode *ic)
4243 iCode *lic = ic->next;
4249 /* Make sure we have a next iCode */
4250 D(emitcode("","; checking lic"));
4254 /* Make sure the result of the addition is an iCode */
4255 D(emitcode("","; checking IS_ITEMP"));
4256 if (!IS_ITEMP (IC_RESULT (ic)))
4259 /* Make sure the next iCode is a pointer set or get */
4260 pset = POINTER_SET(lic);
4261 pget = POINTER_GET(lic);
4262 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4266 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), offl);
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);
6443 /*-----------------------------------------------------------------*/
6444 /* genUnpackBits - generates code for unpacking bits */
6445 /*-----------------------------------------------------------------*/
6447 genUnpackBits (operand * result)
6449 int offset = 0; /* result byte offset */
6450 int rsize; /* result size */
6451 int rlen = 0; /* remaining bitfield length */
6452 sym_link *etype; /* bitfield type information */
6453 int blen; /* bitfield length */
6454 int bstr; /* bitfield starting bit within byte */
6456 D(emitcode ("; genUnpackBits",""));
6458 etype = getSpec (operandType (result));
6459 rsize = getSize (operandType (result));
6460 blen = SPEC_BLEN (etype);
6461 bstr = SPEC_BSTR (etype);
6463 /* If the bitfield length is less than a byte */
6466 emitcode ("lda", ",x");
6467 hc08_dirtyReg (hc08_reg_a, FALSE);
6468 AccRsh (bstr, FALSE);
6469 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6470 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6474 /* Bit field did not fit in a byte. Copy all
6475 but the partial byte at the end. */
6476 for (rlen=blen;rlen>=8;rlen-=8)
6478 emitcode ("lda", ",x");
6479 hc08_dirtyReg (hc08_reg_a, FALSE);
6480 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6482 emitcode ("aix", "#1");
6485 /* Handle the partial byte at the end */
6488 emitcode ("lda", ",x");
6489 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6490 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6498 storeConstToAop (zero, AOP (result), offset++);
6503 /*-----------------------------------------------------------------*/
6504 /* genDataPointerGet - generates code when ptr offset is known */
6505 /*-----------------------------------------------------------------*/
6507 genDataPointerGet (operand * left,
6511 int size, offset = 0;
6514 D(emitcode ("; genDataPointerGet",""));
6516 aopOp (result, ic, TRUE);
6517 size = AOP_SIZE (result);
6519 derefaop = aopDerefAop (AOP (left));
6520 freeAsmop (left, NULL, ic, TRUE);
6521 derefaop->size = size;
6525 transferAopAop(derefaop, offset, AOP (result), offset);
6529 freeAsmop (NULL, derefaop, ic, TRUE);
6530 freeAsmop (result, NULL, ic, TRUE);
6534 /*-----------------------------------------------------------------*/
6535 /* genNearPointerGet - emitcode for near pointer fetch */
6536 /*-----------------------------------------------------------------*/
6538 genNearPointerGet (operand * left,
6544 sym_link *retype = getSpec (operandType (result));
6546 D(emitcode ("; genNearPointerGet",""));
6548 aopOp (left, ic, FALSE);
6550 /* if left is rematerialisable and
6551 result is not bit variable type and
6552 the left is pointer to data space i.e
6553 lower 128 bytes of space */
6554 if ((AOP_TYPE (left) == AOP_IMMD)
6555 || (AOP_TYPE (left) == AOP_LIT)
6556 /* !IS_BITVAR (retype) */
6557 /* && DCL_TYPE (ltype) == POINTER */ )
6559 genDataPointerGet (left, result, ic);
6563 /* if the operand is already in hx
6564 then we do nothing else we move the value to hx */
6565 if (AOP_TYPE (left) != AOP_STR)
6567 /* if this is remateriazable */
6568 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6569 loadRegFromConst (hc08_reg_h, zero);
6572 /* so hx now contains the address */
6573 aopOp (result, ic, FALSE);
6575 /* if bit then unpack */
6576 if (IS_BITVAR (retype))
6577 genUnpackBits (result);
6580 size = AOP_SIZE (result);
6585 accopWithMisc ("lda", ",x");
6588 rmwWithReg ("inc", hc08_reg_x);
6590 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6591 hc08_freeReg (hc08_reg_a);
6595 freeAsmop (left, NULL, ic, TRUE);
6596 freeAsmop (result, NULL, ic, TRUE);
6598 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6599 aopOp (IC_RESULT (pi), pi, FALSE);
6600 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6601 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6605 hc08_freeReg (hc08_reg_hx);
6609 /*-----------------------------------------------------------------*/
6610 /* genFarPointerGet - get value from far space */
6611 /*-----------------------------------------------------------------*/
6613 genFarPointerGet (operand * left,
6614 operand * result, iCode * ic, iCode * pi)
6617 sym_link *retype = getSpec (operandType (result));
6619 D(emitcode ("; genFarPointerGet",""));
6621 aopOp (left, ic, FALSE);
6623 /* if left is rematerialisable and
6624 result is not bit variable type and
6625 the left is pointer to data space i.e
6626 lower 128 bytes of space */
6627 if (AOP_TYPE (left) == AOP_IMMD &&
6629 /* && DCL_TYPE (ltype) == POINTER */ )
6631 genDataPointerGet (left, result, ic);
6635 /* if the operand is already in hx
6636 then we do nothing else we move the value to hx */
6637 if (AOP_TYPE (left) != AOP_STR)
6639 /* if this is remateriazable */
6640 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6643 /* so hx now contains the address */
6644 aopOp (result, ic, FALSE);
6646 /* if bit then unpack */
6647 if (IS_BITVAR (retype))
6648 genUnpackBits (result);
6651 size = AOP_SIZE (result);
6656 accopWithMisc ("lda", ",x");
6659 emitcode ("aix", "#1");
6660 hc08_dirtyReg (hc08_reg_hx, FALSE);
6662 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6663 hc08_freeReg (hc08_reg_a);
6667 freeAsmop (left, NULL, ic, TRUE);
6668 freeAsmop (result, NULL, ic, TRUE);
6670 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6671 aopOp (IC_RESULT (pi), pi, FALSE);
6672 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6673 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6677 hc08_freeReg (hc08_reg_hx);
6683 /*-----------------------------------------------------------------*/
6684 /* genPointerGet - generate code for pointer get */
6685 /*-----------------------------------------------------------------*/
6687 genPointerGet (iCode * ic, iCode *pi)
6689 operand *left, *result;
6690 sym_link *type, *etype;
6693 D(emitcode ("; genPointerGet",""));
6695 left = IC_LEFT (ic);
6696 result = IC_RESULT (ic);
6698 /* depending on the type of pointer we need to
6699 move it to the correct pointer register */
6700 type = operandType (left);
6701 etype = getSpec (type);
6702 /* if left is of type of pointer then it is simple */
6703 if (IS_PTR (type) && !IS_FUNC (type->next))
6704 p_type = DCL_TYPE (type);
6707 /* we have to go by the storage class */
6708 p_type = PTR_TYPE (SPEC_OCLS (etype));
6711 /* special case when cast remat */
6712 if (p_type == GPOINTER && IS_SYMOP(left) && OP_SYMBOL(left)->remat &&
6713 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6714 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6715 type = operandType (left);
6716 p_type = DCL_TYPE (type);
6718 /* now that we have the pointer type we assign
6719 the pointer values */
6726 genNearPointerGet (left, result, ic, pi);
6732 genFarPointerGet (left, result, ic, pi);
6739 /*-----------------------------------------------------------------*/
6740 /* genPackBits - generates code for packed bit storage */
6741 /*-----------------------------------------------------------------*/
6743 genPackBits (sym_link * etype,
6746 int offset = 0; /* source byte offset */
6747 int rlen = 0; /* remaining bitfield length */
6748 int blen; /* bitfield length */
6749 int bstr; /* bitfield starting bit within byte */
6750 int litval; /* source literal value (if AOP_LIT) */
6751 unsigned char mask; /* bitmask within current byte */
6753 D(emitcode ("; genPackBits",""));
6755 blen = SPEC_BLEN (etype);
6756 bstr = SPEC_BSTR (etype);
6758 /* If the bitfield length is less than a byte */
6761 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6762 (unsigned char) (0xFF >> (8 - bstr)));
6764 if (AOP_TYPE (right) == AOP_LIT)
6766 /* Case with a bitfield length <8 and literal source
6768 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6770 litval &= (~mask) & 0xff;
6772 emitcode ("lda", ",x");
6773 if ((mask|litval)!=0xff)
6774 emitcode ("and","#0x%02x", mask);
6776 emitcode ("ora","#0x%02x", litval);
6777 hc08_dirtyReg (hc08_reg_a, FALSE);
6778 emitcode ("sta", ",x");
6780 hc08_freeReg (hc08_reg_a);
6784 /* Case with a bitfield length < 8 and arbitrary source
6786 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6787 /* shift and mask source value */
6789 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6790 hc08_dirtyReg (hc08_reg_a, FALSE);
6791 pushReg (hc08_reg_a, TRUE);
6793 emitcode ("lda", ",x");
6794 emitcode ("and", "#0x%02x", mask);
6795 emitcode ("ora", "1,s");
6796 emitcode ("sta", ",x");
6797 pullReg (hc08_reg_a);
6799 hc08_freeReg (hc08_reg_a);
6803 /* Bit length is greater than 7 bits. In this case, copy */
6804 /* all except the partial byte at the end */
6805 for (rlen=blen;rlen>=8;rlen-=8)
6807 if (AOP (right)->type == AOP_DIR)
6809 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6813 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6814 emitcode ("sta", "%d,x", offset);
6819 /* If there was a partial byte at the end */
6822 mask = (((unsigned char) -1 << rlen) & 0xff);
6824 if (AOP_TYPE (right) == AOP_LIT)
6826 /* Case with partial byte and literal source
6828 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6829 litval >>= (blen-rlen);
6830 litval &= (~mask) & 0xff;
6831 emitcode ("lda", "%d,x", offset);
6832 hc08_dirtyReg (hc08_reg_a, FALSE);
6833 if ((mask|litval)!=0xff)
6834 emitcode ("and","#0x%02x", mask);
6836 emitcode ("ora","#0x%02x", litval);
6837 emitcode ("sta", "%d,x", offset);
6838 hc08_dirtyReg (hc08_reg_a, FALSE);
6839 hc08_freeReg (hc08_reg_a);
6843 /* Case with partial byte and arbitrary source
6845 loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6846 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6847 hc08_dirtyReg (hc08_reg_a, FALSE);
6848 pushReg (hc08_reg_a, TRUE);
6850 emitcode ("lda", ",x");
6851 emitcode ("and", "#0x%02x", mask);
6852 emitcode ("ora", "1,s");
6853 emitcode ("sta", ",x");
6854 pullReg (hc08_reg_a);
6857 hc08_freeReg (hc08_reg_a);
6860 /*-----------------------------------------------------------------*/
6861 /* genDataPointerSet - remat pointer to data space */
6862 /*-----------------------------------------------------------------*/
6864 genDataPointerSet (operand * right,
6868 int size, offset = 0;
6871 D(emitcode ("; genDataPointerSet",""));
6873 aopOp (right, ic, FALSE);
6874 size = AOP_SIZE (right);
6876 derefaop = aopDerefAop (AOP (result));
6877 freeAsmop (result, NULL, ic, TRUE);
6878 derefaop->size = size;
6882 transferAopAop (AOP (right), offset, derefaop, offset);
6886 freeAsmop (right, NULL, ic, TRUE);
6887 freeAsmop (NULL, derefaop, ic, TRUE);
6891 /*-----------------------------------------------------------------*/
6892 /* genNearPointerSet - emitcode for near pointer put */
6893 /*-----------------------------------------------------------------*/
6895 genNearPointerSet (operand * right,
6901 sym_link *retype = getSpec (operandType (right));
6902 sym_link *letype = getSpec (operandType (result));
6904 D(emitcode ("; genNearPointerSet",""));
6906 aopOp (result, ic, FALSE);
6908 /* if the result is rematerializable &
6909 in data space & not a bit variable */
6910 if (AOP_TYPE (result) == AOP_IMMD &&
6911 /* DCL_TYPE (ptype) == POINTER && */
6912 !IS_BITVAR (retype) &&
6913 !IS_BITVAR (letype))
6915 genDataPointerSet (right, result, ic);
6919 /* if the operand is already in hx
6920 then we do nothing else we move the value to hx */
6921 if (AOP_TYPE (result) != AOP_STR)
6923 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6924 loadRegFromConst (hc08_reg_h, zero);
6926 /* so hx now contains the address */
6927 aopOp (right, ic, FALSE);
6929 /* if bit then unpack */
6930 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6931 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6934 size = AOP_SIZE (right);
6939 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6940 accopWithMisc ("sta", ",x");
6943 rmwWithReg ("inc", hc08_reg_x);
6945 hc08_freeReg (hc08_reg_a);
6949 freeAsmop (result, NULL, ic, TRUE);
6950 freeAsmop (right, NULL, ic, TRUE);
6952 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6953 aopOp (IC_RESULT (pi), pi, FALSE);
6954 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6955 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6959 hc08_freeReg (hc08_reg_hx);
6964 /*-----------------------------------------------------------------*/
6965 /* genFarPointerSet - set value from far space */
6966 /*-----------------------------------------------------------------*/
6968 genFarPointerSet (operand * right,
6969 operand * result, iCode * ic, iCode * pi)
6972 sym_link *retype = getSpec (operandType (right));
6973 sym_link *letype = getSpec (operandType (result));
6975 D(emitcode ("; genFarPointerSet",""));
6977 aopOp (result, ic, FALSE);
6979 /* if the result is rematerializable &
6980 in data space & not a bit variable */
6981 if (AOP_TYPE (result) == AOP_IMMD &&
6982 /* DCL_TYPE (ptype) == POINTER && */
6983 !IS_BITVAR (retype) &&
6984 !IS_BITVAR (letype))
6986 genDataPointerSet (right, result, ic);
6990 /* if the operand is already in hx
6991 then we do nothing else we move the value to hx */
6992 if (AOP_TYPE (result) != AOP_STR)
6994 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6996 /* so hx now contains the address */
6997 aopOp (right, ic, FALSE);
6999 /* if bit then unpack */
7000 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7001 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7004 size = AOP_SIZE (right);
7009 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7010 accopWithMisc ("sta", ",x");
7013 emitcode ("aix", "#1");
7015 hc08_freeReg (hc08_reg_a);
7019 freeAsmop (result, NULL, ic, TRUE);
7020 freeAsmop (right, NULL, ic, TRUE);
7022 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
7023 aopOp (IC_RESULT (pi), pi, FALSE);
7024 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7025 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7029 hc08_freeReg (hc08_reg_hx);
7035 /*-----------------------------------------------------------------*/
7036 /* genPointerSet - stores the value into a pointer location */
7037 /*-----------------------------------------------------------------*/
7039 genPointerSet (iCode * ic, iCode *pi)
7041 operand *right, *result;
7042 sym_link *type, *etype;
7045 D(emitcode ("; genPointerSet",""));
7047 right = IC_RIGHT (ic);
7048 result = IC_RESULT (ic);
7050 /* depending on the type of pointer we need to
7051 move it to the correct pointer register */
7052 type = operandType (result);
7053 etype = getSpec (type);
7054 /* if left is of type of pointer then it is simple */
7055 if (IS_PTR (type) && !IS_FUNC (type->next))
7057 p_type = DCL_TYPE (type);
7061 /* we have to go by the storage class */
7062 p_type = PTR_TYPE (SPEC_OCLS (etype));
7065 /* special case when cast remat */
7066 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
7067 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
7068 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
7069 type = operandType (result);
7070 p_type = DCL_TYPE (type);
7072 /* now that we have the pointer type we assign
7073 the pointer values */
7080 genNearPointerSet (right, result, ic, pi);
7086 genFarPointerSet (right, result, ic, pi);
7090 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7091 "genPointerSet: illegal pointer type");
7096 /*-----------------------------------------------------------------*/
7097 /* genIfx - generate code for Ifx statement */
7098 /*-----------------------------------------------------------------*/
7100 genIfx (iCode * ic, iCode * popIc)
7102 operand *cond = IC_COND (ic);
7105 D(emitcode ("; genIfx",""));
7107 aopOp (cond, ic, FALSE);
7109 /* get the value into acc */
7110 if (AOP_TYPE (cond) != AOP_CRY)
7111 asmopToBool (AOP (cond), FALSE);
7114 /* the result is now in the accumulator */
7115 freeAsmop (cond, NULL, ic, TRUE);
7117 /* if there was something to be popped then do it */
7121 /* if the condition is a bit variable */
7122 if (isbit && IS_ITEMP (cond) &&
7124 genIfxJump (ic, SPIL_LOC (cond)->rname);
7125 else if (isbit && !IS_ITEMP (cond))
7126 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7128 genIfxJump (ic, "a");
7133 /*-----------------------------------------------------------------*/
7134 /* genAddrOf - generates code for address of */
7135 /*-----------------------------------------------------------------*/
7137 genAddrOf (iCode * ic)
7139 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7142 D(emitcode ("; genAddrOf",""));
7144 aopOp (IC_RESULT (ic), ic, FALSE);
7146 /* if the operand is on the stack then we
7147 need to get the stack offset of this
7151 /* if it has an offset then we need to compute
7153 hc08_useReg (hc08_reg_hx);
7154 emitcode ("tsx", "");
7155 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7156 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7157 hc08_freeReg (hc08_reg_hx);
7162 /* object not on stack then we need the name */
7163 size = AOP_SIZE (IC_RESULT (ic));
7168 char s[SDCC_NAME_MAX+10];
7171 sprintf (s, "#%s", sym->rname);
7174 sprintf (s, "#>%s", sym->rname);
7177 sprintf (s, "#(%s >> %d)",
7181 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7185 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7189 /*-----------------------------------------------------------------*/
7190 /* genAssign - generate code for assignment */
7191 /*-----------------------------------------------------------------*/
7193 genAssign (iCode * ic)
7195 operand *result, *right;
7197 // unsigned long lit = 0L;
7199 D(emitcode("; genAssign",""));
7201 result = IC_RESULT (ic);
7202 right = IC_RIGHT (ic);
7204 /* if they are the same */
7205 if (operandsEqu (result, right)) {
7209 aopOp (right, ic, FALSE);
7210 aopOp (result, ic, TRUE);
7212 /* if they are the same registers */
7213 if (sameRegs (AOP (right), AOP (result)))
7216 if ((AOP_TYPE (right) == AOP_LIT)
7217 && (IS_AOP_HX(AOP(result))))
7219 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7224 size = AOP_SIZE (result);
7229 transferAopAop (AOP (right), offset, AOP (result), offset);
7234 freeAsmop (right, NULL, ic, TRUE);
7235 freeAsmop (result, NULL, ic, TRUE);
7238 /*-----------------------------------------------------------------*/
7239 /* genJumpTab - genrates code for jump table */
7240 /*-----------------------------------------------------------------*/
7242 genJumpTab (iCode * ic)
7247 D(emitcode ("; genJumpTab",""));
7249 aopOp (IC_JTCOND (ic), ic, FALSE);
7250 /* get the condition into accumulator */
7251 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7252 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7253 /* multiply by three */
7254 pushReg (hc08_reg_a, FALSE);
7255 emitcode ("lsla", "");
7256 emitcode ("add","1,s");
7257 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7258 loadRegFromConst (hc08_reg_h, zero);
7259 pullReg (hc08_reg_a);
7261 jtab = newiTempLabel (NULL);
7262 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7263 emitcode ("", "%05d$:", jtab->key + 100);
7264 /* now generate the jump labels */
7265 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7266 jtab = setNextItem (IC_JTLABELS (ic)))
7267 emitcode ("jmp", "%05d$", jtab->key + 100);
7269 hc08_dirtyReg (hc08_reg_a, TRUE);
7270 hc08_dirtyReg (hc08_reg_hx, TRUE);
7273 /*-----------------------------------------------------------------*/
7274 /* genCast - gen code for casting */
7275 /*-----------------------------------------------------------------*/
7277 genCast (iCode * ic)
7279 operand *result = IC_RESULT (ic);
7280 sym_link *ctype = operandType (IC_LEFT (ic));
7281 sym_link *rtype = operandType (IC_RIGHT (ic));
7282 operand *right = IC_RIGHT (ic);
7285 D(emitcode("; genCast",""));
7287 /* if they are equivalent then do nothing */
7288 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7291 aopOp (right, ic, FALSE);
7292 aopOp (result, ic, FALSE);
7295 /* if they are the same size : or less */
7296 if (AOP_SIZE (result) <= AOP_SIZE (right))
7299 /* if they are in the same place */
7301 if (sameRegs (AOP (right), AOP (result)))
7305 /* if they in different places then copy */
7306 size = AOP_SIZE (result);
7310 transferAopAop(AOP (right), offset, AOP (result), offset);
7317 /* if the result is of type pointer */
7322 sym_link *type = operandType (right);
7323 sym_link *etype = getSpec (type);
7325 /* pointer to generic pointer */
7326 if (IS_GENPTR (ctype))
7329 p_type = DCL_TYPE (type);
7332 if (SPEC_SCLS(etype)==S_REGISTER) {
7333 // let's assume it is a generic pointer
7336 /* we have to go by the storage class */
7337 p_type = PTR_TYPE (SPEC_OCLS (etype));
7341 /* the first two bytes are known */
7342 size = GPTRSIZE - 1;
7346 transferAopAop(AOP (right), offset, AOP (result), offset);
7349 /* the last byte depending on type */
7352 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7357 // pointerTypeToGPByte will have bitched.
7361 sprintf(gpValStr, "#0x%d", gpVal);
7362 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7368 /* just copy the pointers */
7369 size = AOP_SIZE (result);
7373 transferAopAop(AOP (right), offset, AOP (result), offset);
7379 /* so we now know that the size of destination is greater
7380 than the size of the source */
7381 /* we move to result for the size of source */
7382 size = AOP_SIZE (right);
7386 transferAopAop(AOP (right), offset, AOP (result), offset);
7390 /* now depending on the sign of the source && destination */
7391 size = AOP_SIZE (result) - AOP_SIZE (right);
7392 /* if unsigned or not an integral type */
7393 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7396 storeConstToAop (zero, AOP (result), offset++);
7400 /* we need to extend the sign :{ */
7401 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7402 accopWithMisc ("rola", "");
7403 accopWithMisc ("clra", "");
7404 accopWithMisc ("sbc", zero);
7406 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7409 /* we are done hurray !!!! */
7412 freeAsmop (right, NULL, ic, TRUE);
7413 freeAsmop (result, NULL, ic, TRUE);
7417 /*-----------------------------------------------------------------*/
7418 /* genDjnz - generate decrement & jump if not zero instrucion */
7419 /*-----------------------------------------------------------------*/
7421 genDjnz (iCode * ic, iCode * ifx)
7427 D(emitcode ("; genDjnz",""));
7429 /* if the if condition has a false label
7430 then we cannot save */
7434 /* if the minus is not of the form
7436 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7437 !IS_OP_LITERAL (IC_RIGHT (ic)))
7440 if (operandLitValue (IC_RIGHT (ic)) != 1)
7443 /* dbnz doesn't support extended mode */
7444 if (isOperandInFarSpace (IC_RESULT (ic)))
7447 /* if the size of this greater than one then no
7449 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7451 aopOp (IC_RESULT (ic), ic, FALSE);
7452 if (AOP_SIZE (IC_RESULT (ic))>1)
7454 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7458 /* otherwise we can save BIG */
7459 lbl = newiTempLabel (NULL);
7460 lbl1 = newiTempLabel (NULL);
7463 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7466 emitBranch ("bra", lbl1);
7468 emitBranch ("jmp", IC_TRUE (ifx));
7471 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7476 /*-----------------------------------------------------------------*/
7477 /* genReceive - generate code for a receive iCode */
7478 /*-----------------------------------------------------------------*/
7480 genReceive (iCode * ic)
7484 D(emitcode ("; genReceive",""));
7486 aopOp (IC_RESULT (ic), ic, FALSE);
7487 size = AOP_SIZE (IC_RESULT (ic));
7492 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7493 AOP (IC_RESULT (ic)), offset);
7494 if (hc08_aop_pass[offset]->type == AOP_REG)
7495 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7500 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7503 /*-----------------------------------------------------------------*/
7504 /* genDummyRead - generate code for dummy read of volatiles */
7505 /*-----------------------------------------------------------------*/
7507 genDummyRead (iCode * ic)
7512 D(emitcode("; genDummyRead",""));
7515 if (op && IS_SYMOP (op))
7518 aopOp (op, ic, FALSE);
7520 size = AOP_SIZE (op);
7525 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7526 hc08_freeReg (hc08_reg_a);
7530 freeAsmop (op, NULL, ic, TRUE);
7533 if (op && IS_SYMOP (op))
7536 aopOp (op, ic, FALSE);
7538 size = AOP_SIZE (op);
7543 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7544 hc08_freeReg (hc08_reg_a);
7548 freeAsmop (op, NULL, ic, TRUE);
7552 /*-----------------------------------------------------------------*/
7553 /* genCritical - generate code for start of a critical sequence */
7554 /*-----------------------------------------------------------------*/
7556 genCritical (iCode *ic)
7558 D(emitcode("; genCritical",""));
7561 aopOp (IC_RESULT (ic), ic, TRUE);
7563 emitcode ("tpa", "");
7564 hc08_dirtyReg (hc08_reg_a, FALSE);
7565 emitcode ("sei", "");
7568 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7570 pushReg (hc08_reg_a, FALSE);
7572 hc08_freeReg (hc08_reg_a);
7574 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7577 /*-----------------------------------------------------------------*/
7578 /* genEndCritical - generate code for end of a critical sequence */
7579 /*-----------------------------------------------------------------*/
7581 genEndCritical (iCode *ic)
7583 D(emitcode("; genEndCritical",""));
7587 aopOp (IC_RIGHT (ic), ic, FALSE);
7588 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7589 emitcode ("tap", "");
7590 hc08_freeReg (hc08_reg_a);
7591 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7595 pullReg (hc08_reg_a);
7596 emitcode ("tap", "");
7602 /*-----------------------------------------------------------------*/
7603 /* genhc08Code - generate code for HC08 based controllers */
7604 /*-----------------------------------------------------------------*/
7606 genhc08Code (iCode * lic)
7613 lineHead = lineCurr = NULL;
7615 /* print the allocation information */
7616 if (allocInfo && currFunc)
7617 printAllocInfo (currFunc, codeOutFile);
7618 /* if debug information required */
7619 if (options.debug && currFunc)
7621 debugFile->writeFunction (currFunc, lic);
7624 if (IS_STATIC (currFunc->etype))
7625 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7627 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7631 /* stack pointer name */
7632 if (options.useXstack)
7637 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
7639 hc08_aop_pass[0] = newAsmop (AOP_REG);
7640 hc08_aop_pass[0]->size=1;
7641 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7642 hc08_aop_pass[1] = newAsmop (AOP_REG);
7643 hc08_aop_pass[1]->size=1;
7644 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7645 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7646 hc08_aop_pass[2]->size=1;
7647 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7648 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7649 hc08_aop_pass[3]->size=1;
7650 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7652 for (ic = lic; ic; ic = ic->next)
7655 _G.current_iCode = ic;
7657 if (ic->level != clevel || ic->block != cblock)
7661 debugFile->writeScope(ic);
7667 if (ic->lineno && cln != ic->lineno)
7671 debugFile->writeCLine(ic);
7674 emitcode ("", "C$%s$%d$%d$%d ==.",
7675 FileBaseName (ic->filename), ic->lineno,
7676 ic->level, ic->block);
7680 if (!options.noCcodeInAsm) {
7681 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7682 printCLine(ic->filename, ic->lineno));
7686 if (options.iCodeInAsm) {
7690 for (i=0; i<6; i++) {
7691 sprintf (®sInUse[i],
7692 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7695 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7697 /* if the result is marked as
7698 spilt and rematerializable or code for
7699 this has already been generated then
7701 if (resultRemat (ic) || ic->generated)
7709 for (i=A_IDX;i<=XA_IDX;i++)
7711 reg = hc08_regWithIdx(i);
7713 emitcode("","; %s = %s offset %d", reg->name,
7714 aopName(reg->aop), reg->aopofs);
7717 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7719 sym = OP_SYMBOL (IC_LEFT (ic));
7720 if (sym->accuse == ACCUSE_HX)
7722 hc08_reg_h->isFree = FALSE;
7723 hc08_reg_x->isFree = FALSE;
7725 else if (sym->accuse == ACCUSE_XA)
7727 hc08_reg_a->isFree = FALSE;
7729 hc08_reg_x->isFree = FALSE;
7732 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7734 sym = OP_SYMBOL (IC_RIGHT (ic));
7735 if (sym->accuse == ACCUSE_HX)
7737 hc08_reg_h->isFree = FALSE;
7738 hc08_reg_x->isFree = FALSE;
7740 else if (sym->accuse == ACCUSE_XA)
7742 hc08_reg_a->isFree = FALSE;
7744 hc08_reg_x->isFree = FALSE;
7749 /* depending on the operation */
7769 /* IPOP happens only when trying to restore a
7770 spilt live range, if there is an ifx statement
7771 following this pop then the if statement might
7772 be using some of the registers being popped which
7773 would destory the contents of the register so
7774 we need to check for this condition and handle it */
7776 ic->next->op == IFX &&
7777 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7778 genIfx (ic->next, ic);
7796 genEndFunction (ic);
7812 if (!genPointerGetSetOfs (ic))
7817 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7834 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7838 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7845 /* note these two are xlated by algebraic equivalence
7846 during parsing SDCC.y */
7847 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7848 "got '>=' or '<=' shouldn't have come here");
7852 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7864 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7868 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7872 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7899 case GET_VALUE_AT_ADDRESS:
7900 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7904 if (POINTER_SET (ic))
7905 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7931 addSet (&_G.sendSet, ic);
7934 case DUMMY_READ_VOLATILE:
7943 genEndCritical (ic);
7954 if (!hc08_reg_a->isFree)
7955 D(emitcode("","; forgot to free a"));
7956 if (!hc08_reg_x->isFree)
7957 D(emitcode("","; forgot to free x"));
7958 if (!hc08_reg_h->isFree)
7959 D(emitcode("","; forgot to free h"));
7960 if (!hc08_reg_hx->isFree)
7961 D(emitcode("","; forgot to free hx"));
7962 if (!hc08_reg_xa->isFree)
7963 D(emitcode("","; forgot to free xa"));
7966 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
7969 /* now we are ready to call the
7970 peep hole optimizer */
7971 if (!options.nopeep)
7972 peepHole (&lineHead);
7974 /* now do the actual printing */
7975 printLine (lineHead, codeOutFile);