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 -------------------------------------------------------------------------*/
30 /* Use the D macro for basic (unobtrusive) debugging messages */
33 /* Use the DD macro for detailed debugging messages */
41 #include "SDCCglobl.h"
45 #include "SDCCpeeph.h"
49 char *aopLiteral (value * val, int offset);
50 char *aopLiteralLong (value * val, int offset, int size);
52 static int pushReg (regs *reg, bool freereg);
53 static void pullReg (regs *reg);
54 static void transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs);
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"a", "x", "_ret2", "_ret3"};
62 unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */
63 char **fReturn2 = fReturnhc08;
82 static asmop *hc08_aop_pass[4];
84 extern int hc08_ptrRegReq;
85 extern int hc08_nRegs;
86 extern FILE *codeOutFile;
87 //static void saveRBank (int, iCode *, bool);
88 static bool operandsEqu (operand * op1, operand * op2);
89 static void loadRegFromConst (regs *reg, char *c);
90 static char *aopName (asmop *aop);
91 static asmop * newAsmop (short type);
92 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define IS_AOP_HX(x) \
98 (((x)->type == AOP_REG) \
99 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
100 && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
102 #define IS_AOP_XA(x) \
103 (((x)->type == AOP_REG) \
104 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
105 && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
107 #define IS_AOP_A(x) \
108 (((x)->type == AOP_REG) \
109 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
110 && ((x)->size == 1) )
112 #define IS_AOP_X(x) \
113 (((x)->type == AOP_REG) \
114 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
115 && ((x)->size == 1) )
117 #define IS_AOP_H(x) \
118 (((x)->type == AOP_REG) \
119 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
120 && ((x)->size == 1) )
122 #define CLRC emitcode("clc","")
124 static lineNode *lineHead = NULL;
125 static lineNode *lineCurr = NULL;
128 static unsigned char SLMask[] =
129 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
130 0xE0, 0xC0, 0x80, 0x00};
131 static unsigned char SRMask[] =
132 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
133 0x07, 0x03, 0x01, 0x00};
141 #define AOP(op) op->aop
142 #define AOP_TYPE(op) AOP(op)->type
143 #define AOP_SIZE(op) AOP(op)->size
144 #define AOP_OP(aop) aop->op
147 /*-----------------------------------------------------------------*/
148 /* emitcode - writes the code into a file : for now it is simple */
149 /*-----------------------------------------------------------------*/
151 emitcode (char *inst, char *fmt,...)
154 char lb[INITIAL_INLINEASM];
162 sprintf (lb, "%s\t", inst);
164 sprintf (lb, "%s", inst);
165 vsprintf (lb + (strlen (lb)), fmt, ap);
168 vsprintf (lb, fmt, ap);
170 while (isspace ((unsigned char)*lbp))
174 lineCurr = (lineCurr ?
175 connectLine (lineCurr, newLineNode (lb)) :
176 (lineHead = newLineNode (lb)));
177 lineCurr->isInline = _G.inLine;
178 lineCurr->isDebug = _G.debugLine;
179 lineCurr->ic = _G.current_iCode;
180 lineCurr->isComment = (*lbp==';');
182 //printf("%s\n", lb);
187 emitBranch (char *branchop, symbol *tlbl)
189 emitcode (branchop, "%05d$", (tlbl->key + 100));
193 emitLabel (symbol *tlbl)
195 emitcode ("", "%05d$:", (tlbl->key +100));
198 /*-----------------------------------------------------------------*/
199 /* hc08_emitDebuggerSymbol - associate the current code location */
200 /* with a debugger symbol */
201 /*-----------------------------------------------------------------*/
203 hc08_emitDebuggerSymbol (char * debugSym)
206 emitcode ("", "%s ==.", debugSym);
211 /*--------------------------------------------------------------------------*/
212 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
213 /* freesrc is true, sreg is marked free and available for */
214 /* reuse. sreg and dreg must be of equal size */
215 /*--------------------------------------------------------------------------*/
217 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
223 /* Nothing to do if no destination. */
227 /* But it's definately an error if there's no source. */
230 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
231 "NULL sreg in transferRegReg");
235 DD(emitcode ("", "; transferRegReg(%s,%s)",
236 sreg->name, dreg->name));
249 case H_IDX: /* H to A */
250 pushReg (hc08_reg_h, FALSE);
251 pullReg (hc08_reg_a);
253 case X_IDX: /* X to A */
254 emitcode ("txa", "");
263 case A_IDX: /* A to H */
264 pushReg (hc08_reg_a, FALSE);
265 pullReg (hc08_reg_h);
267 case X_IDX: /* X to H */
268 pushReg (hc08_reg_x, FALSE);
269 pullReg (hc08_reg_h);
278 case A_IDX: /* A to X */
279 emitcode ("tax", "");
281 case H_IDX: /* H to X */
282 pushReg (hc08_reg_h, FALSE);
283 pullReg (hc08_reg_x);
292 case XA_IDX: /* XA to HX */
293 pushReg (hc08_reg_x, FALSE);
294 pullReg (hc08_reg_h);
295 emitcode ("tax", "");
304 case HX_IDX: /* HX to XA */
305 emitcode ("txa", "");
306 pushReg (hc08_reg_h, FALSE);
307 pullReg (hc08_reg_x);
317 wassertl (!error, "bad combo in transferRegReg");
322 dreg->aop = sreg->aop;
323 dreg->aopofs = sreg->aopofs;
324 dreg->isFree = FALSE;
328 /*--------------------------------------------------------------------------*/
329 /* updateCFA - update the debugger information to reflect the current */
330 /* connonical frame address relative to the stack pointer */
331 /*--------------------------------------------------------------------------*/
335 /* there is no frame unless there is a function */
339 debugFile->writeFrameAddress (NULL, hc08_reg_sp,
340 1 + _G.stackOfs + _G.stackPushes);
343 /*--------------------------------------------------------------------------*/
344 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
345 /* marked free and available for reuse. */
346 /*--------------------------------------------------------------------------*/
348 pushReg (regs *reg, bool freereg)
350 int regidx = reg->rIdx;
355 emitcode ("psha", "");
360 emitcode ("pshx", "");
365 emitcode ("pshh", "");
370 emitcode ("pshx", "");
373 emitcode ("pshh", "");
378 emitcode ("psha", "");
381 emitcode ("pshx", "");
390 return -_G.stackOfs-_G.stackPushes;
393 /*--------------------------------------------------------------------------*/
394 /* pullReg - Pull register reg off the stack. */
395 /*--------------------------------------------------------------------------*/
399 int regidx = reg->rIdx;
404 emitcode ("pula", "");
409 emitcode ("pulx", "");
414 emitcode ("pulh", "");
419 emitcode ("pulh", "");
422 emitcode ("pulx", "");
427 emitcode ("pulx", "");
430 emitcode ("pula", "");
438 hc08_dirtyReg(reg, FALSE);
441 /*--------------------------------------------------------------------------*/
442 /* pullNull - Discard n bytes off the top of the stack */
443 /*--------------------------------------------------------------------------*/
449 emitcode("ais","#%d",n);
455 /*--------------------------------------------------------------------------*/
456 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
457 /* push was performed, false otherwise. */
458 /*--------------------------------------------------------------------------*/
460 pushRegIfUsed (regs *reg)
471 /*--------------------------------------------------------------------------*/
472 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
473 /* stack. Otherwise register reg is marked as free. */
474 /*--------------------------------------------------------------------------*/
476 pullOrFreeReg (regs *reg, bool needpull)
484 /*--------------------------------------------------------------------------*/
485 /* adjustStack - Adjust the stack pointer by n bytes. */
486 /*--------------------------------------------------------------------------*/
494 emitcode ("ais","#127");
496 _G.stackPushes -= 127;
501 emitcode ("ais","#-128");
503 _G.stackPushes += 128;
508 emitcode ("ais", "#%d", n);
517 /*--------------------------------------------------------------------------*/
518 /* aopName - Return a string with debugging information about an asmop. */
519 /*--------------------------------------------------------------------------*/
523 static char buffer[256];
527 return "(asmop*)NULL";
532 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
535 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
538 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
541 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
544 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
547 sprintf (buf, "REG(%s,%s,%s,%s)",
548 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
549 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
550 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
551 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
558 sprintf (buf,"?%d", aop->type);
566 /*--------------------------------------------------------------------------*/
567 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
568 /*--------------------------------------------------------------------------*/
570 loadRegFromAop (regs *reg, asmop *aop, int loffset)
572 int regidx = reg->rIdx;
574 if (aop->stacked && aop->stk_aop[loffset])
576 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
581 printf("loadRegFromAop called\n");
584 printf(" reg = NULL\n");
587 printf(" reg = %s\n", reg->name);
590 printf(" aop = NULL\n");
593 printf(" aop->type = %d\n", aop->type);
594 printf(" loffset = %d\n", loffset);
597 printf(" aop has operand link\n");
599 printf(" aop missing operand link\n");
601 printf(" reg has operand link\n");
603 printf(" reg missing operand link\n");
606 DD(emitcode ("", "; loadRegFromAop (%s, %s, %d)",
607 reg->name, aopName (aop), loffset));
609 /* If operand is volatile, we cannot optimize. */
610 if (!aop->op || isOperandVolatile (aop->op, FALSE))
614 /* If this register already has this offset of the operand
615 then we need only mark it as in use. */
616 if (reg->aop && reg->aop->op && aop->op
617 && operandsEqu(reg->aop->op,aop->op)
618 && (reg->aopofs == loffset))
621 DD(emitcode ("","; already had correct value for %s", reg->name));
625 /* TODO: check to see if we can transfer from another register */
627 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
628 && operandsEqu(hc08_reg_h->aop->op,aop->op)
629 && (hc08_reg_h->aopofs == loffset))
631 DD(emitcode ("","; found correct value for %s in h", reg->name));
632 transferRegReg (hc08_reg_h, reg, FALSE);
638 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
639 && operandsEqu(hc08_reg_x->aop->op,aop->op)
640 && (hc08_reg_x->aopofs == loffset))
642 DD(emitcode ("","; found correct value for %s in x", reg->name));
643 transferRegReg (hc08_reg_x, reg, FALSE);
648 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
649 && operandsEqu(hc08_reg_a->aop->op,aop->op)
650 && (hc08_reg_a->aopofs == loffset))
652 DD(emitcode ("","; found correct value for %s in a", reg->name));
653 transferRegReg (hc08_reg_a, reg, FALSE);
663 if (aop->type == AOP_REG)
665 if (loffset < aop->size)
666 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
668 emitcode ("clra", ""); /* TODO: handle sign extension */
672 char * l = aopAdrStr (aop, loffset, FALSE);
673 if (!strcmp (l, zero))
674 emitcode ("clra", "");
676 emitcode ("lda", "%s", l);
680 if (aop->type == AOP_REG)
682 if (loffset < aop->size)
683 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
685 emitcode ("clrx", ""); /* TODO: handle sign extension */
689 char * l = aopAdrStr (aop, loffset, FALSE);
690 if (!strcmp (l, zero))
691 emitcode ("clrx", "");
693 emitcode ("ldx", "%s", l);
698 char * l = aopAdrStr (aop, loffset, FALSE);
699 if (!strcmp (l, zero))
701 emitcode ("clrh", "");
705 if (hc08_reg_a->isFree)
707 loadRegFromAop (hc08_reg_a, aop, loffset);
708 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
710 else if (hc08_reg_x->isFree)
712 loadRegFromAop (hc08_reg_x, aop, loffset);
713 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
717 pushReg (hc08_reg_a, TRUE);
718 loadRegFromAop (hc08_reg_a, aop, loffset);
719 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
720 pullReg (hc08_reg_a);
726 else if (IS_AOP_XA(aop))
727 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
728 else if ((aop->type == AOP_DIR))
730 if (aop->size>(loffset+1))
731 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
734 loadRegFromAop (hc08_reg_x, aop, loffset);
735 loadRegFromConst (hc08_reg_h, zero);
738 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
740 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
745 needpula = pushRegIfUsed (hc08_reg_a);
746 loadRegFromAop (hc08_reg_a, aop, loffset+1);
747 loadRegFromAop (hc08_reg_x, aop, loffset);
748 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
749 pullOrFreeReg (hc08_reg_a, needpula);
755 else if (IS_AOP_HX(aop))
756 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
759 loadRegFromAop (hc08_reg_a, aop, loffset);
760 loadRegFromAop (hc08_reg_x, aop, loffset+1);
765 // ignore caching for now
768 reg->aopofs = loffset;
773 /*--------------------------------------------------------------------------*/
774 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
775 /* freeAsmop is called with aop, the stacked data will */
776 /* be copied to the original aop location. */
777 /*--------------------------------------------------------------------------*/
779 forceStackedAop (asmop *aop, bool copyOrig)
783 asmop *newaop = newAsmop (aop->type);
784 memcpy (newaop, aop, sizeof(*newaop));
786 DD(emitcode("", "; forcedStackAop %s", aopName(aop)));
788 if (copyOrig && hc08_reg_a->isFree)
790 else if (copyOrig && hc08_reg_x->isFree)
795 for (loffset=0; loffset < newaop->size; loffset++)
797 asmop *aopsof = newAsmop (AOP_SOF);
801 loadRegFromAop (reg, aop, loffset);
802 aopsof->aopu.aop_stk = pushReg (reg, FALSE);
806 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
808 aopsof->op = aop->op;
809 newaop->stk_aop[loffset] = aopsof;
813 if (!reg && copyOrig)
815 for (loffset=0; loffset < newaop->size; loffset++)
817 transferAopAop (aop, loffset, newaop, loffset);
825 /*--------------------------------------------------------------------------*/
826 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
827 /*--------------------------------------------------------------------------*/
829 storeRegToAop (regs *reg, asmop *aop, int loffset)
831 int regidx = reg->rIdx;
837 DD(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
838 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
840 if ((reg->rIdx == HX_IDX) && aop->stacked
841 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
843 storeRegToAop (hc08_reg_h, aop, loffset+1);
844 storeRegToAop (hc08_reg_x, aop, loffset);
848 if ((reg->rIdx == XA_IDX) && aop->stacked
849 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
851 storeRegToAop (hc08_reg_x, aop, loffset+1);
852 storeRegToAop (hc08_reg_a, aop, loffset);
856 if (aop->stacked && aop->stk_aop[loffset])
858 storeRegToAop (reg, aop->stk_aop[loffset], 0);
862 if (aop->type == AOP_STR)
865 transferRegReg (reg, hc08_reg_x, FALSE);
867 transferRegReg (reg, hc08_reg_h, FALSE);
871 if (aop->type == AOP_DUMMY)
874 if (aop->type == AOP_CRY) /* This can only happen if IFX was optimized */
875 return; /* away, so just toss the result */
880 if ((aop->type == AOP_REG) && (loffset < aop->size))
881 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
883 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
886 if ((aop->type == AOP_REG) && (loffset < aop->size))
887 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
889 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
892 if (hc08_reg_a->isFree)
894 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
895 storeRegToAop (hc08_reg_a, aop, loffset);
896 hc08_freeReg (hc08_reg_a);
898 else if (hc08_reg_x->isFree)
900 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
901 storeRegToAop (hc08_reg_x, aop, loffset);
902 hc08_freeReg (hc08_reg_x);
906 pushReg (hc08_reg_a, TRUE);
907 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
908 storeRegToAop (hc08_reg_a, aop, loffset);
909 pullReg (hc08_reg_a);
913 if ((aop->type == AOP_DIR) )
915 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
917 else if (IS_AOP_XA(aop))
918 transferRegReg(reg, hc08_reg_xa, FALSE);
919 else if (IS_AOP_HX(aop))
924 needpula = pushRegIfUsed (hc08_reg_a);
925 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
926 storeRegToAop (hc08_reg_a, aop, loffset+1);
927 storeRegToAop (hc08_reg_x, aop, loffset);
928 pullOrFreeReg (hc08_reg_a, needpula);
933 transferRegReg(reg, hc08_reg_hx, FALSE);
934 else if (IS_AOP_XA(aop))
938 storeRegToAop (hc08_reg_a, aop, loffset);
939 storeRegToAop (hc08_reg_x, aop, loffset+1);
944 /* Disable the register tracking for now */
946 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
949 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
951 otherreg=hc08_regWithIdx(otheridx);
952 if (otherreg && otherreg->aop
953 && otherreg->aop->op && aop->op
954 && operandsEqu(otherreg->aop->op,aop->op)
955 && (otherreg->aopofs == loffset))
957 DD(emitcode("","; marking %s stale", otherreg->name));
961 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
963 hc08_reg_hx->aop = NULL;
964 DD(emitcode("","; marking hx stale"));
966 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
968 hc08_reg_xa->aop = NULL;
969 DD(emitcode("","; marking xa stale"));
973 reg->aopofs = loffset;
978 /*--------------------------------------------------------------------------*/
979 /* loadRegFromConst - Load register reg from constant c. */
980 /*--------------------------------------------------------------------------*/
982 loadRegFromConst (regs *reg, char *c)
988 emitcode ("clra", "");
990 emitcode ("lda", "%s", c);
994 emitcode ("clrx", "");
996 emitcode ("ldx", "%s", c);
1000 emitcode ("clrh", "");
1001 else if (hc08_reg_a->isFree)
1003 loadRegFromConst (hc08_reg_a, c);
1004 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
1006 else if (hc08_reg_x->isFree)
1008 loadRegFromConst (hc08_reg_x, c);
1009 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
1013 pushReg (hc08_reg_a, TRUE);
1014 loadRegFromConst (hc08_reg_a, c);
1015 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
1016 pullReg (hc08_reg_a);
1020 emitcode ("ldhx", "%s", c);
1023 emitcode ("lda", "%s", c);
1024 emitcode ("ldx", "%s >> 8", c);
1027 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1028 "Bad rIdx in loadRegFromConst");
1035 /*--------------------------------------------------------------------------*/
1036 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
1037 /*--------------------------------------------------------------------------*/
1039 storeConstToAop (char *c, asmop *aop, int loffset)
1041 if (aop->stacked && aop->stk_aop[loffset])
1043 storeConstToAop (c, aop->stk_aop[loffset], 0);
1050 if (!strcmp(c,zero))
1051 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
1053 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
1056 if (loffset>(aop->size-1))
1058 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
1063 if (hc08_reg_a->isFree)
1065 loadRegFromConst (hc08_reg_a, c);
1066 storeRegToAop( hc08_reg_a, aop, loffset);
1067 hc08_freeReg (hc08_reg_a);
1069 else if (hc08_reg_x->isFree)
1071 loadRegFromConst (hc08_reg_x, c);
1072 storeRegToAop( hc08_reg_x, aop, loffset);
1073 hc08_freeReg (hc08_reg_x);
1077 pushReg (hc08_reg_a, TRUE);
1078 loadRegFromConst (hc08_reg_a, c);
1079 storeRegToAop( hc08_reg_a, aop, loffset);
1080 pullReg (hc08_reg_a);
1086 /*--------------------------------------------------------------------------*/
1087 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
1088 /* reg is extended to fill logical offsets loffset */
1089 /* and above of asmop aop. Otherwise, logical */
1090 /* offsets loffset and above of asmop aop are */
1091 /* zeroed. reg must be an 8-bit register. */
1092 /*--------------------------------------------------------------------------*/
1094 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
1096 // int regidx = reg->rIdx;
1097 int size = aop->size;
1105 while (loffset<size)
1106 storeConstToAop(zero, aop, loffset++);
1111 transferRegReg (reg, hc08_reg_a, FALSE);
1112 emitcode ("rola","");
1113 emitcode ("clra","");
1114 emitcode ("sbc", "#0");
1115 hc08_useReg (hc08_reg_a);
1116 while (loffset<size)
1117 storeRegToAop (hc08_reg_a, aop, loffset++);
1118 hc08_freeReg (hc08_reg_a);
1122 /*--------------------------------------------------------------------------*/
1123 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1124 /* padding and/or truncation as needed. If isSigned is */
1125 /* true, sign extension will take place in the padding. */
1126 /*--------------------------------------------------------------------------*/
1128 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1130 int regidx = reg->rIdx;
1131 int size = aop->size;
1138 storeRegToAop (reg, aop, 0);
1139 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1144 storeRegToAop (hc08_reg_x, aop, 0);
1148 storeRegToAop (reg, aop, 0);
1149 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1155 storeRegToAop (hc08_reg_a, aop, 0);
1159 storeRegToAop (reg, aop, 0);
1160 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1166 /*--------------------------------------------------------------------------*/
1167 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1168 /* srcaop to logical offset dstofs of asmop dstaop. */
1169 /*--------------------------------------------------------------------------*/
1171 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1173 bool needpula = FALSE;
1176 bool keepreg = FALSE;
1178 /* ignore transfers at the same byte, unless its volatile */
1179 if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
1180 && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
1181 && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs
1182 && dstaop->type == srcaop->type)
1185 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1187 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1191 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1193 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1197 // DD(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1198 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1199 // DD(emitcode ("", "; srcaop->type = %d", srcaop->type));
1200 // DD(emitcode ("", "; dstaop->type = %d", dstaop->type));
1202 if (dstofs >= dstaop->size)
1205 if ((dstaop->type == AOP_DIR)
1206 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1208 if (srcaop->type == AOP_LIT)
1211 unsigned long bytemask;
1213 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1214 bytemask = (lit >> (srcofs*8)) & 0xff;
1218 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1223 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1224 aopAdrStr(dstaop, dstofs, FALSE));
1228 if (dstaop->type == AOP_REG)
1230 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1231 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1233 reg = dstaop->aopu.aop_reg[dstofs];
1238 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1240 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1241 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1243 reg = srcaop->aopu.aop_reg[srcofs];
1250 if (hc08_reg_a->isFree)
1252 else if (hc08_reg_x->isFree)
1256 pushReg (hc08_reg_a, TRUE);
1262 loadRegFromAop (reg, srcaop, srcofs);
1263 storeRegToAop (reg, dstaop, dstofs);
1266 pullOrFreeReg (hc08_reg_a, needpula);
1270 /*--------------------------------------------------------------------------*/
1271 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1272 /* parameter param. */
1273 /*--------------------------------------------------------------------------*/
1275 accopWithMisc (char *accop, char *param)
1277 emitcode (accop, "%s", param);
1278 hc08_dirtyReg (hc08_reg_a, FALSE);
1281 /*--------------------------------------------------------------------------*/
1282 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1283 /* byte at logical offset loffset of asmop aop. */
1284 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1285 /*--------------------------------------------------------------------------*/
1287 accopWithAop (char *accop, asmop *aop, int loffset)
1289 if (aop->stacked && aop->stk_aop[loffset])
1291 accopWithAop (accop, aop->stk_aop[loffset], 0);
1295 if (aop->type == AOP_DUMMY)
1298 if (aop->type == AOP_REG)
1300 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1301 emitcode (accop, "1,s");
1305 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1307 hc08_dirtyReg (hc08_reg_a, FALSE);
1311 /*--------------------------------------------------------------------------*/
1312 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1313 /* byte at logical offset loffset of asmop aop. Register reg */
1314 /* must be 8-bit. */
1315 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1316 /*--------------------------------------------------------------------------*/
1318 rmwWithReg (char *rmwop, regs *reg)
1321 char *rmwaop = rmwbuf;
1323 if (reg->rIdx == A_IDX)
1325 sprintf(rmwaop,"%sa", rmwop);
1326 emitcode (rmwaop, "");
1327 hc08_dirtyReg (hc08_reg_a, FALSE);
1329 else if (reg->rIdx == X_IDX)
1331 sprintf(rmwaop,"%sx", rmwop);
1332 emitcode (rmwaop, "");
1333 hc08_dirtyReg (hc08_reg_a, FALSE);
1335 else if (hc08_reg_a->isFree)
1337 transferRegReg(reg, hc08_reg_a, FALSE);
1338 sprintf(rmwaop,"%sa", rmwop);
1339 emitcode (rmwaop, "");
1340 hc08_dirtyReg (hc08_reg_a, FALSE);
1341 transferRegReg(hc08_reg_a, reg, TRUE);
1345 pushReg (reg, FALSE);
1346 emitcode (rmwop, "1,s");
1348 hc08_dirtyReg (reg, FALSE);
1352 /*--------------------------------------------------------------------------*/
1353 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1354 /* logical offset loffset of asmop aop. */
1355 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1356 /*--------------------------------------------------------------------------*/
1358 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1360 bool needpula = FALSE;
1362 if (aop->stacked && aop->stk_aop[loffset])
1364 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1371 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1374 needpula = pushRegIfUsed (hc08_reg_a);
1375 loadRegFromAop (hc08_reg_a, aop, loffset);
1376 rmwWithReg (rmwop, hc08_reg_a);
1377 if (strcmp ("tst", rmwop))
1378 storeRegToAop (hc08_reg_a, aop, loffset);
1379 pullOrFreeReg (hc08_reg_a, needpula);
1384 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1390 /*-----------------------------------------------------------------*/
1391 /* newAsmop - creates a new asmOp */
1392 /*-----------------------------------------------------------------*/
1394 newAsmop (short type)
1398 aop = Safe_calloc (1, sizeof (asmop));
1405 /*-----------------------------------------------------------------*/
1406 /* pointerCode - returns the code for a pointer type */
1407 /*-----------------------------------------------------------------*/
1409 pointerCode (sym_link * etype)
1412 return PTR_TYPE (SPEC_OCLS (etype));
1417 /*-----------------------------------------------------------------*/
1418 /* aopForSym - for a true symbol */
1419 /*-----------------------------------------------------------------*/
1421 aopForSym (iCode * ic, symbol * sym, bool result)
1426 wassertl (ic != NULL, "Got a null iCode");
1427 wassertl (sym != NULL, "Got a null symbol");
1429 // printf("in aopForSym for symbol %s\n", sym->name);
1431 space = SPEC_OCLS (sym->etype);
1433 /* if already has one */
1439 /* special case for a function */
1440 if (IS_FUNC (sym->type))
1442 sym->aop = aop = newAsmop (AOP_IMMD);
1443 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1444 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1445 aop->size = FPTRSIZE;
1449 /* if it is in direct space */
1450 if (IN_DIRSPACE (space))
1452 sym->aop = aop = newAsmop (AOP_DIR);
1453 aop->aopu.aop_dir = sym->rname;
1454 aop->size = getSize (sym->type);
1458 /* if it is in far space */
1459 if (IN_FARSPACE (space))
1461 sym->aop = aop = newAsmop (AOP_EXT);
1462 aop->aopu.aop_dir = sym->rname;
1463 aop->size = getSize (sym->type);
1467 if (IN_STACK (sym->etype))
1469 sym->aop = aop = newAsmop (AOP_SOF);
1470 aop->aopu.aop_dir = sym->rname;
1471 aop->size = getSize (sym->type);
1472 aop->aopu.aop_stk = sym->stack;
1478 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1479 "aopForSym should never reach here");
1483 /* if it is in code space */
1484 if (IN_CODESPACE (space))
1490 /*-----------------------------------------------------------------*/
1491 /* aopForRemat - rematerialzes an object */
1492 /*-----------------------------------------------------------------*/
1494 aopForRemat (symbol * sym)
1496 iCode *ic = sym->rematiCode;
1504 val += (int) operandLitValue (IC_RIGHT (ic));
1505 else if (ic->op == '-')
1506 val -= (int) operandLitValue (IC_RIGHT (ic));
1507 else if (IS_CAST_ICODE(ic)) {
1508 sym_link *from_type = operandType(IC_RIGHT(ic));
1509 aop->aopu.aop_immd.from_cast_remat = 1;
1510 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1511 ptr_type = DCL_TYPE(from_type);
1512 if (ptr_type == IPOINTER) {
1519 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1522 if (ic->op == ADDRESS_OF)
1525 sprintf (buffer, "(%s %c 0x%04x)",
1526 OP_SYMBOL (IC_LEFT (ic))->rname,
1527 val >= 0 ? '+' : '-',
1528 abs (val) & 0xffff);
1530 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1532 aop = newAsmop (AOP_IMMD);
1533 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1534 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1535 /* set immd2 field if required */
1536 if (aop->aopu.aop_immd.from_cast_remat)
1538 sprintf(buffer,"#0x%02x",ptr_type);
1539 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1540 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1543 else if (ic->op == '=')
1545 val += (int) operandLitValue (IC_RIGHT (ic));
1547 sprintf (buffer, "0x%04x", val);
1548 aop = newAsmop (AOP_LIT);
1549 aop->aopu.aop_lit = constVal (buffer);
1552 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1553 "unexpected rematerialization");
1560 /*-----------------------------------------------------------------*/
1561 /* regsInCommon - two operands have some registers in common */
1562 /*-----------------------------------------------------------------*/
1564 regsInCommon (operand * op1, operand * op2)
1566 symbol *sym1, *sym2;
1569 /* if they have registers in common */
1570 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1573 sym1 = OP_SYMBOL (op1);
1574 sym2 = OP_SYMBOL (op2);
1576 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1579 for (i = 0; i < sym1->nRegs; i++)
1585 for (j = 0; j < sym2->nRegs; j++)
1590 if (sym2->regs[j] == sym1->regs[i])
1598 /*-----------------------------------------------------------------*/
1599 /* operandsEqu - equivalent */
1600 /*-----------------------------------------------------------------*/
1602 operandsEqu (operand * op1, operand * op2)
1604 symbol *sym1, *sym2;
1606 /* if they not symbols */
1607 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1610 sym1 = OP_SYMBOL (op1);
1611 sym2 = OP_SYMBOL (op2);
1613 /* if both are itemps & one is spilt
1614 and the other is not then false */
1615 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1616 sym1->isspilt != sym2->isspilt)
1619 /* if they are the same */
1623 if (sym1->rname[0] && sym2->rname[0]
1624 && strcmp (sym1->rname, sym2->rname) == 0)
1627 /* if left is a tmp & right is not */
1628 if (IS_ITEMP (op1) &&
1631 (sym1->usl.spillLoc == sym2))
1634 if (IS_ITEMP (op2) &&
1638 (sym2->usl.spillLoc == sym1))
1644 /*-----------------------------------------------------------------*/
1645 /* sameRegs - two asmops have the same registers */
1646 /*-----------------------------------------------------------------*/
1648 sameRegs (asmop * aop1, asmop * aop2)
1655 // if (aop1->size != aop2->size)
1658 if (aop1->type == aop2->type)
1663 for (i = 0; i < aop1->size; i++)
1664 if (aop1->aopu.aop_reg[i] !=
1665 aop2->aopu.aop_reg[i])
1669 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1672 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1679 /*-----------------------------------------------------------------*/
1680 /* aopOp - allocates an asmop for an operand : */
1681 /*-----------------------------------------------------------------*/
1683 aopOp (operand * op, iCode * ic, bool result)
1692 // Is this a pointer set result?
1694 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1698 // printf("checking literal\n");
1699 /* if this a literal */
1700 if (IS_OP_LITERAL (op))
1702 op->aop = aop = newAsmop (AOP_LIT);
1703 aop->aopu.aop_lit = op->operand.valOperand;
1704 aop->size = getSize (operandType (op));
1706 aop->isaddr = op->isaddr;
1710 // printf("checking pre-existing\n");
1711 /* if already has a asmop then continue */
1715 op->aop->isaddr = op->isaddr;
1719 // printf("checking underlying sym\n");
1720 /* if the underlying symbol has a aop */
1721 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1723 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1724 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1725 //op->aop = aop = OP_SYMBOL (op)->aop;
1726 aop->size = getSize( operandType (op));
1727 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1728 //printf (" with size = %d\n", aop->size);
1731 aop->isaddr = op->isaddr;
1732 /* if (aop->isaddr & IS_ITEMP (op))
1734 aop->psize=aop->size;
1735 aop->size = getSize( operandType (op)->next);
1740 // printf("checking true sym\n");
1741 /* if this is a true symbol */
1742 if (IS_TRUE_SYMOP (op))
1744 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1746 aop->isaddr = op->isaddr;
1747 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1748 //printf (" with size = %d\n", aop->size);
1752 /* this is a temporary : this has
1758 e) can be a return use only */
1760 sym = OP_SYMBOL (op);
1762 // printf("checking conditional\n");
1763 /* if the type is a conditional */
1764 if (sym->regType == REG_CND)
1766 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1769 aop->isaddr = op->isaddr;
1773 // printf("checking spilt\n");
1774 /* if it is spilt then two situations
1776 b) has a spill location */
1777 if (sym->isspilt || sym->nRegs == 0)
1780 // printf("checking remat\n");
1781 /* rematerialize it NOW */
1784 sym->aop = op->aop = aop =
1786 aop->size = getSize (sym->type);
1788 aop->isaddr = op->isaddr;
1789 /* if (aop->isaddr & IS_ITEMP (op))
1791 aop->psize=aop->size;
1792 aop->size = getSize( operandType (op)->next);
1797 // printf("checking accuse\n");
1800 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1801 aop->size = getSize (sym->type);
1802 switch (sym->accuse)
1805 aop->aopu.aop_reg[0] = hc08_reg_a;
1806 aop->aopu.aop_reg[1] = hc08_reg_x;
1809 aop->aopu.aop_reg[0] = hc08_reg_x;
1810 aop->aopu.aop_reg[1] = hc08_reg_h;
1814 aop->isaddr = op->isaddr;
1818 // printf("checking ruonly\n");
1824 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1825 aop->size = getSize (sym->type);
1826 for (i = 0; i < fReturnSizeHC08; i++)
1827 aop->aopu.aop_str[i] = fReturn2[i];
1829 aop->isaddr = op->isaddr;
1833 /* else spill location */
1834 if (sym->usl.spillLoc)
1836 asmop *oldAsmOp = NULL;
1838 if (sym->usl.spillLoc->aop
1839 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1841 /* force a new aop if sizes differ */
1842 oldAsmOp = sym->usl.spillLoc->aop;
1843 sym->usl.spillLoc->aop = NULL;
1844 //printf ("forcing new aop\n");
1846 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1847 if (sym->usl.spillLoc->aop->size != getSize (sym->type))
1849 /* Don't reuse the new aop, go with the last one */
1850 sym->usl.spillLoc->aop = oldAsmOp;
1852 aop->size = getSize (sym->type);
1854 aop->isaddr = op->isaddr;
1855 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1856 //printf (" with size = %d\n", aop->size);
1860 /* else must be a dummy iTemp */
1861 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1862 aop->size = getSize (sym->type);
1866 // printf("assuming register\n");
1867 /* must be in a register */
1868 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1869 aop->size = sym->nRegs;
1870 for (i = 0; i < sym->nRegs; i++)
1871 aop->aopu.aop_reg[i] = sym->regs[i];
1873 aop->isaddr = op->isaddr;
1877 /*-----------------------------------------------------------------*/
1878 /* freeAsmop - free up the asmop given to an operand */
1879 /*----------------------------------------------------------------*/
1881 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1903 DD(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1906 for (loffset=0; loffset<aop->size; loffset++)
1907 if (aop->stk_aop[loffset])
1909 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1912 pullNull (stackAdjust);
1916 /* all other cases just dealloc */
1922 OP_SYMBOL (op)->aop = NULL;
1923 /* if the symbol has a spill */
1925 SPIL_LOC (op)->aop = NULL;
1931 /*-----------------------------------------------------------------*/
1932 /* aopDerefAop - treating the aop parameter as a pointer, return */
1933 /* an asmop for the object it references */
1934 /*-----------------------------------------------------------------*/
1936 aopDerefAop (asmop *aop)
1941 asmop *newaop = NULL;
1942 sym_link *type, *etype;
1945 DD(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1949 type = operandType (aop->op);
1950 etype = getSpec (type);
1951 /* if op is of type of pointer then it is simple */
1952 if (IS_PTR (type) && !IS_FUNC (type->next))
1953 p_type = DCL_TYPE (type);
1956 /* we have to go by the storage class */
1957 p_type = PTR_TYPE (SPEC_OCLS (etype));
1966 if (p_type == POINTER)
1967 newaop = newAsmop (AOP_DIR);
1969 newaop = newAsmop (AOP_EXT);
1970 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1973 adr = (int) floatFromVal (aop->aopu.aop_lit);
1974 if (p_type == POINTER)
1979 newaop = newAsmop (AOP_DIR);
1980 sprintf (s, "0x%02x",adr);
1984 newaop = newAsmop (AOP_EXT);
1985 sprintf (s, "0x%04x",adr);
1987 rs = Safe_calloc (1, strlen (s) + 1);
1989 newaop->aopu.aop_dir = rs;
1992 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1993 "unsupported asmop");
2003 /*-----------------------------------------------------------------*/
2004 /* aopAdrStr - for referencing the address of the aop */
2005 /*-----------------------------------------------------------------*/
2007 aopAdrStr (asmop * aop, int loffset, bool bit16)
2011 int offset = aop->size - 1 - loffset;
2014 /* offset is greater than
2016 if (loffset > (aop->size - 1) &&
2017 aop->type != AOP_LIT)
2020 /* depending on type */
2028 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
2029 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
2031 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
2035 sprintf (s, "#(%s >> %d)",
2036 aop->aopu.aop_immd.aop_immd1,
2040 aop->aopu.aop_immd.aop_immd1);
2044 aop->aopu.aop_immd.aop_immd1);
2045 rs = Safe_calloc (1, strlen (s) + 1);
2051 sprintf (s, "*(%s + %d)",
2055 sprintf (s, "*%s", aop->aopu.aop_dir);
2056 rs = Safe_calloc (1, strlen (s) + 1);
2062 sprintf (s, "(%s + %d)",
2066 sprintf (s, "%s", aop->aopu.aop_dir);
2067 rs = Safe_calloc (1, strlen (s) + 1);
2072 return aop->aopu.aop_reg[loffset]->name;
2076 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2078 return aopLiteral (aop->aopu.aop_lit, loffset);
2082 return aop->aopu.aop_str[loffset];
2085 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2087 rs = Safe_calloc (1, strlen (s) + 1);
2093 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2094 "aopAdrStr got unsupported aop->type");
2103 /*-----------------------------------------------------------------*/
2104 /* opIsGptr: returns non-zero if the passed operand is */
2105 /* a generic pointer type. */
2106 /*-----------------------------------------------------------------*/
2108 opIsGptr (operand * op)
2110 sym_link *type = operandType (op);
2112 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2120 /*-----------------------------------------------------------------*/
2121 /* getDataSize - get the operand data size */
2122 /*-----------------------------------------------------------------*/
2124 getDataSize (operand * op)
2127 size = AOP_SIZE (op);
2132 /*-----------------------------------------------------------------*/
2133 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2134 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2135 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2136 /*-----------------------------------------------------------------*/
2138 asmopToBool (asmop *aop, bool resultInA)
2140 symbol *tlbl, *tlbl1;
2141 int size = aop->size;
2142 bool needpula = FALSE;
2143 bool flagsonly = TRUE;
2148 hc08_freeReg(hc08_reg_a);
2155 emitcode ("tsta", "");
2158 else if (IS_AOP_X(aop))
2159 emitcode ("tstx", "");
2160 else if (IS_AOP_H(aop))
2162 if (hc08_reg_a->isFree)
2164 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2165 emitcode ("tsta", "");
2167 hc08_freeReg(hc08_reg_a);
2169 else if (hc08_reg_x->isFree)
2171 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2172 emitcode ("tstx", "");
2173 hc08_freeReg(hc08_reg_x);
2177 emitcode ("pshh", "");
2178 emitcode ("tst", "1,s");
2179 emitcode ("ais", "#1");
2182 else if (IS_AOP_HX(aop))
2183 emitcode ("cphx", zero);
2184 else if (IS_AOP_XA(aop))
2186 symbol *tlbl = newiTempLabel (NULL);
2187 emitcode ("tsta", "");
2188 emitcode ("bne", "%05d$", (tlbl->key + 100));
2189 emitcode ("tstx", "");
2190 emitcode ("", "%05d$:", (tlbl->key + 100));
2194 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2195 "Bad rIdx in asmToBool");
2203 needpula = pushRegIfUsed (hc08_reg_a);
2204 loadRegFromAop (hc08_reg_a, aop, 0);
2205 for (offset=1; offset<size; offset++)
2206 accopWithAop ("ora", aop, offset);
2208 pullReg (hc08_reg_a);
2211 hc08_freeReg (hc08_reg_a);
2216 /* Higher levels should optimize this case away but let's be safe */
2217 if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
2218 loadRegFromConst (hc08_reg_a, one);
2220 loadRegFromConst (hc08_reg_a, zero);
2221 hc08_freeReg(hc08_reg_a);
2228 loadRegFromAop (hc08_reg_a, aop, 0);
2229 hc08_freeReg (hc08_reg_a);
2233 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2238 if (hc08_reg_a->isFree)
2240 loadRegFromAop (hc08_reg_a, aop, 0);
2241 accopWithAop ("ora", aop, 1);
2242 hc08_freeReg (hc08_reg_a);
2247 tlbl = newiTempLabel (NULL);
2248 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2249 emitcode ("bne", "%05d$", (tlbl->key + 100));
2250 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2251 emitcode ("", "%05d$:", (tlbl->key + 100));
2257 needpula = pushRegIfUsed (hc08_reg_a);
2258 loadRegFromAop (hc08_reg_a, aop, 0);
2259 for (offset=1; offset<size; offset++)
2260 accopWithAop ("ora", aop, offset);
2262 pullReg (hc08_reg_a);
2265 hc08_freeReg (hc08_reg_a);
2273 tlbl = newiTempLabel (NULL);
2277 tlbl1 = newiTempLabel (NULL);
2278 emitBranch ("bne", tlbl1);
2279 loadRegFromConst (hc08_reg_a, zero);
2280 emitBranch ("bra", tlbl);
2282 loadRegFromConst (hc08_reg_a, one);
2286 emitBranch ("beq", tlbl);
2287 loadRegFromConst (hc08_reg_a, one);
2290 hc08_useReg (hc08_reg_a);
2296 /*-----------------------------------------------------------------*/
2297 /* genNot - generate code for ! operation */
2298 /*-----------------------------------------------------------------*/
2302 D(emitcode ("; genNot",""));
2304 /* assign asmOps to operand & result */
2305 aopOp (IC_LEFT (ic), ic, FALSE);
2306 aopOp (IC_RESULT (ic), ic, TRUE);
2308 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2309 emitcode ("eor", one);
2310 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2312 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2313 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2317 /*-----------------------------------------------------------------*/
2318 /* genCpl - generate code for complement */
2319 /*-----------------------------------------------------------------*/
2325 regs* reg = hc08_reg_a;
2329 D(emitcode ("; genCpl",""));
2331 /* assign asmOps to operand & result */
2332 aopOp (IC_LEFT (ic), ic, FALSE);
2333 aopOp (IC_RESULT (ic), ic, TRUE);
2335 size = AOP_SIZE (IC_RESULT (ic));
2338 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2339 rmwWithReg ("com", reg);
2341 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2346 /* release the aops */
2347 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2348 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2351 /*-----------------------------------------------------------------*/
2352 /* genUminusFloat - unary minus for floating points */
2353 /*-----------------------------------------------------------------*/
2355 genUminusFloat (operand * op, operand * result)
2357 int size, offset = 0;
2360 D(emitcode ("; genUminusFloat",""));
2362 /* for this we just copy and then flip the bit */
2364 size = AOP_SIZE (op) - 1;
2368 transferAopAop (AOP (op), offset, AOP (result), offset);
2372 needpula = pushRegIfUsed (hc08_reg_a);
2373 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2374 emitcode ("eor", "#0x80");
2375 hc08_useReg (hc08_reg_a);
2376 storeRegToAop (hc08_reg_a, AOP (result), offset);
2377 pullOrFreeReg (hc08_reg_a, needpula);
2380 /*-----------------------------------------------------------------*/
2381 /* genUminus - unary minus code generation */
2382 /*-----------------------------------------------------------------*/
2384 genUminus (iCode * ic)
2387 sym_link *optype, *rtype;
2392 D(emitcode ("; genUminus",""));
2395 aopOp (IC_LEFT (ic), ic, FALSE);
2396 aopOp (IC_RESULT (ic), ic, TRUE);
2398 optype = operandType (IC_LEFT (ic));
2399 rtype = operandType (IC_RESULT (ic));
2401 /* if float then do float stuff */
2402 if (IS_FLOAT (optype))
2404 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2408 /* otherwise subtract from zero */
2409 size = AOP_SIZE (IC_LEFT (ic));
2414 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2415 needpula = pushRegIfUsed (hc08_reg_a);
2418 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2419 emitcode ("nega", "");
2420 hc08_freeReg (hc08_reg_a);
2421 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2422 SPEC_USIGN (operandType (IC_LEFT (ic))));
2423 pullOrFreeReg (hc08_reg_a, needpula);
2427 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2428 result = forceStackedAop (AOP (IC_RESULT (ic)), FALSE);
2430 result = AOP (IC_RESULT (ic));
2432 needpula = pushRegIfUsed (hc08_reg_a);
2436 loadRegFromConst (hc08_reg_a, zero);
2437 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2438 storeRegToAop (hc08_reg_a, result, offset++);
2441 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2442 SPEC_USIGN (operandType (IC_LEFT (ic))));
2443 pullOrFreeReg (hc08_reg_a, needpula);
2445 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2446 freeAsmop (NULL, result, ic, TRUE);
2452 /* release the aops */
2453 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2454 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2457 /*-----------------------------------------------------------------*/
2458 /* saveRegisters - will look for a call and save the registers */
2459 /*-----------------------------------------------------------------*/
2461 saveRegisters (iCode * lic)
2468 for (ic = lic; ic; ic = ic->next)
2469 if (ic->op == CALL || ic->op == PCALL)
2474 fprintf (stderr, "found parameter push with no function call\n");
2478 /* if the registers have been saved already or don't need to be then
2482 if (IS_SYMOP(IC_LEFT(ic)) &&
2483 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2484 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2487 /* safe the registers in use at this time but skip the
2488 ones for the result */
2489 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2490 hc08_rUmaskForOp (IC_RESULT(ic)));
2493 for (i = 0; i < hc08_nRegs; i++)
2495 if (bitVectBitValue (rsave, i))
2496 pushReg ( hc08_regWithIdx (i), FALSE);
2500 /*-----------------------------------------------------------------*/
2501 /* unsaveRegisters - pop the pushed registers */
2502 /*-----------------------------------------------------------------*/
2504 unsaveRegisters (iCode * ic)
2509 /* restore the registers in use at this time but skip the
2510 ones for the result */
2511 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2512 hc08_rUmaskForOp (IC_RESULT(ic)));
2514 for (i = hc08_nRegs; i >= 0; i--)
2516 if (bitVectBitValue (rsave, i))
2517 pullReg ( hc08_regWithIdx (i));
2523 /*-----------------------------------------------------------------*/
2525 /*-----------------------------------------------------------------*/
2527 pushSide (operand * oper, int size)
2532 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2533 pushReg ( hc08_reg_a, TRUE);
2537 /*-----------------------------------------------------------------*/
2538 /* assignResultValue - */
2539 /*-----------------------------------------------------------------*/
2541 assignResultValue (operand * oper)
2543 int size = AOP_SIZE (oper);
2547 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2548 if (hc08_aop_pass[offset]->type == AOP_REG)
2549 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2556 /*-----------------------------------------------------------------*/
2557 /* genIpush - genrate code for pushing this gets a little complex */
2558 /*-----------------------------------------------------------------*/
2560 genIpush (iCode * ic)
2562 int size, offset = 0;
2565 D(emitcode ("; genIpush",""));
2567 /* if this is not a parm push : ie. it is spill push
2568 and spill push is always done on the local stack */
2572 /* and the item is spilt then do nothing */
2573 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2576 aopOp (IC_LEFT (ic), ic, FALSE);
2577 size = AOP_SIZE (IC_LEFT (ic));
2579 /* push it on the stack */
2582 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2583 pushReg ( hc08_reg_a, TRUE);
2589 /* this is a paramter push: in this case we call
2590 the routine to find the call and save those
2591 registers that need to be saved */
2594 /* then do the push */
2595 aopOp (IC_LEFT (ic), ic, FALSE);
2598 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2599 size = AOP_SIZE (IC_LEFT (ic));
2602 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2603 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2605 if ((size==2) && hc08_reg_hx->isFree)
2607 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2608 pushReg (hc08_reg_hx, TRUE);
2615 // printf("loading %d\n", offset);
2616 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2617 // printf("pushing \n");
2618 pushReg (hc08_reg_a, TRUE);
2622 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2625 /*-----------------------------------------------------------------*/
2626 /* genIpop - recover the registers: can happen only for spilling */
2627 /*-----------------------------------------------------------------*/
2629 genIpop (iCode * ic)
2633 D(emitcode ("; genIpop",""));
2635 /* if the temp was not pushed then */
2636 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2639 aopOp (IC_LEFT (ic), ic, FALSE);
2640 size = AOP_SIZE (IC_LEFT (ic));
2644 pullReg (hc08_reg_a);
2645 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2647 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2651 /*-----------------------------------------------------------------*/
2652 /* genSend - gen code for SEND */
2653 /*-----------------------------------------------------------------*/
2654 static void genSend(set *sendSet)
2658 for (sic = setFirstItem (sendSet); sic;
2659 sic = setNextItem (sendSet)) {
2660 int size, offset = 0;
2661 aopOp (IC_LEFT (sic), sic, FALSE);
2662 size = AOP_SIZE (IC_LEFT (sic));
2667 transferAopAop( AOP (IC_LEFT (sic)), offset,
2668 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2672 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2676 /*-----------------------------------------------------------------*/
2677 /* genCall - generates a call statement */
2678 /*-----------------------------------------------------------------*/
2680 genCall (iCode * ic)
2683 // bool restoreBank = FALSE;
2684 // bool swapBanks = FALSE;
2686 D(emitcode("; genCall",""));
2688 dtype = operandType (IC_LEFT (ic));
2689 /* if send set is not empty then assign */
2692 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2693 genSend(reverseSet(_G.sendSet));
2695 genSend(_G.sendSet);
2701 /* if caller saves & we have not saved then */
2707 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2708 OP_SYMBOL (IC_LEFT (ic))->rname :
2709 OP_SYMBOL (IC_LEFT (ic))->name));
2712 /* if we need assign a result value */
2713 if ((IS_ITEMP (IC_RESULT (ic)) &&
2714 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2715 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2716 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2717 IS_TRUE_SYMOP (IC_RESULT (ic)))
2721 aopOp (IC_RESULT (ic), ic, FALSE);
2724 assignResultValue (IC_RESULT (ic));
2726 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2729 /* adjust the stack for parameters if
2733 pullNull (ic->parmBytes);
2736 /* if we had saved some registers then unsave them */
2737 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2738 unsaveRegisters (ic);
2742 /*-----------------------------------------------------------------*/
2743 /* -10l - generates a call by pointer statement */
2744 /*-----------------------------------------------------------------*/
2746 genPcall (iCode * ic)
2749 symbol *rlbl = newiTempLabel (NULL);
2750 symbol *tlbl = newiTempLabel (NULL);
2751 // bool restoreBank=FALSE;
2752 // bool swapBanks = FALSE;
2754 D(emitcode("; genPCall",""));
2756 /* if caller saves & we have not saved then */
2760 /* if we are calling a not _naked function that is not using
2761 the same register bank then we need to save the
2762 destination registers on the stack */
2763 dtype = operandType (IC_LEFT (ic))->next;
2765 /* now push the calling address */
2766 emitBranch ("bsr", tlbl);
2767 emitBranch ("bra", rlbl);
2769 _G.stackPushes += 2; /* account for the bsr return address now on stack */
2772 /* Push the function's address */
2773 aopOp (IC_LEFT (ic), ic, FALSE);
2774 pushSide (IC_LEFT (ic), FPTRSIZE);
2775 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2777 /* if send set is not empty the assign */
2780 genSend(reverseSet(_G.sendSet));
2786 emitcode ("rts", "");
2789 _G.stackPushes -= 4; /* account for rts here & in called function */
2793 /* if we need assign a result value */
2794 if ((IS_ITEMP (IC_RESULT (ic)) &&
2795 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2796 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2797 IS_TRUE_SYMOP (IC_RESULT (ic)))
2801 aopOp (IC_RESULT (ic), ic, FALSE);
2804 assignResultValue (IC_RESULT (ic));
2806 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2809 /* adjust the stack for parameters if
2813 pullNull (ic->parmBytes);
2816 /* if we hade saved some registers then
2818 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2819 unsaveRegisters (ic);
2822 /*-----------------------------------------------------------------*/
2823 /* resultRemat - result is rematerializable */
2824 /*-----------------------------------------------------------------*/
2826 resultRemat (iCode * ic)
2828 if (SKIP_IC (ic) || ic->op == IFX)
2831 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2833 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2834 if (sym->remat && !POINTER_SET (ic))
2841 #if defined(__BORLANDC__) || defined(_MSC_VER)
2842 #define STRCASECMP stricmp
2844 #define STRCASECMP strcasecmp
2847 /*-----------------------------------------------------------------*/
2848 /* inExcludeList - return 1 if the string is in exclude Reg list */
2849 /*-----------------------------------------------------------------*/
2851 regsCmp(void *p1, void *p2)
2853 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2857 inExcludeList (char *s)
2859 const char *p = setFirstItem(options.excludeRegsSet);
2861 if (p == NULL || STRCASECMP(p, "none") == 0)
2865 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2868 /*-----------------------------------------------------------------*/
2869 /* genFunction - generated code for function entry */
2870 /*-----------------------------------------------------------------*/
2872 genFunction (iCode * ic)
2874 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2876 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2877 int stackAdjust = sym->stack;
2878 int accIsFree = sym->recvSize == 0;
2882 /* create the function header */
2883 emitcode (";", "-----------------------------------------");
2884 emitcode (";", " function %s", sym->name);
2885 emitcode (";", "-----------------------------------------");
2887 emitcode ("", "%s:", sym->rname);
2888 ftype = operandType (IC_LEFT (ic));
2892 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2894 if (IFFUNC_ISNAKED(ftype))
2896 emitcode(";", "naked function: no prologue.");
2900 /* if this is an interrupt service routine then
2902 if (IFFUNC_ISISR (sym->type))
2905 if (!inExcludeList ("h"))
2906 pushReg (hc08_reg_h, FALSE);
2909 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2910 /* before setting up the stack frame completely. */
2911 while (ric && ric->next && ric->next->op == RECEIVE)
2913 while (ric && IC_RESULT (ric))
2915 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2916 int rsymSize = rsym ? getSize(rsym->type) : 0;
2920 if (rsym && rsym->regType == REG_CND)
2922 if (rsym && (rsym->accuse || rsym->ruonly))
2924 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2925 rsym = rsym->usl.spillLoc;
2928 /* If the RECEIVE operand immediately spills to the first entry on the */
2929 /* stack, we can push it directly rather than use an sp relative store. */
2930 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2934 _G.current_iCode = ric;
2935 D(emitcode ("; genReceive",""));
2936 for (ofs=0; ofs < rsymSize; ofs++)
2938 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2939 pushReg (reg, TRUE);
2940 if (reg->rIdx == A_IDX)
2944 _G.current_iCode = ic;
2947 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2950 /* adjust the stack for the function */
2953 adjustStack (-stackAdjust);
2955 _G.stackOfs = sym->stack;
2958 /* if critical function then turn interrupts off */
2959 if (IFFUNC_ISCRITICAL (ftype))
2963 /* Function was passed parameters, so make sure A is preserved */
2964 pushReg (hc08_reg_a, FALSE);
2965 pushReg (hc08_reg_a, FALSE);
2966 emitcode ("tpa", "");
2967 emitcode ("sta", "2,s");
2968 emitcode ("sei", "");
2969 pullReg (hc08_reg_a);
2973 /* No passed parameters, so A can be freely modified */
2974 emitcode ("tpa", "");
2975 pushReg (hc08_reg_a, TRUE);
2976 emitcode ("sei", "");
2982 /*-----------------------------------------------------------------*/
2983 /* genEndFunction - generates epilogue for functions */
2984 /*-----------------------------------------------------------------*/
2986 genEndFunction (iCode * ic)
2988 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2990 if (IFFUNC_ISNAKED(sym->type))
2992 emitcode(";", "naked function: no epilogue.");
2993 if (options.debug && currFunc)
2994 debugFile->writeEndFunction (currFunc, ic, 0);
2998 if (IFFUNC_ISCRITICAL (sym->type))
3000 if (!IS_VOID(sym->type->next))
3002 /* Function has return value, so make sure A is preserved */
3003 pushReg (hc08_reg_a, FALSE);
3004 emitcode ("lda", "2,s");
3005 emitcode ("tap", "");
3006 pullReg (hc08_reg_a);
3011 /* Function returns void, so A can be freely modified */
3012 pullReg (hc08_reg_a);
3013 emitcode ("tap", "");
3017 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3023 _G.stackPushes += sym->stack;
3024 adjustStack (sym->stack);
3028 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3032 if (IFFUNC_ISISR (sym->type))
3035 if (!inExcludeList ("h"))
3036 pullReg (hc08_reg_h);
3039 /* if debug then send end of function */
3040 if (options.debug && currFunc)
3042 debugFile->writeEndFunction (currFunc, ic, 1);
3045 emitcode ("rti", "");
3049 if (IFFUNC_CALLEESAVES(sym->type))
3053 /* if any registers used */
3056 /* save the registers used */
3057 for (i = sym->regsUsed->size; i >= 0; i--)
3059 if (bitVectBitValue (sym->regsUsed, i) ||
3060 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3061 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3067 /* if debug then send end of function */
3068 if (options.debug && currFunc)
3070 debugFile->writeEndFunction (currFunc, ic, 1);
3073 emitcode ("rts", "");
3078 /*-----------------------------------------------------------------*/
3079 /* genRet - generate code for return statement */
3080 /*-----------------------------------------------------------------*/
3084 int size, offset = 0;
3087 D(emitcode ("; genRet",""));
3089 /* if we have no return value then
3090 just generate the "ret" */
3094 /* we have something to return then
3095 move the return value into place */
3096 aopOp (IC_LEFT (ic), ic, FALSE);
3097 size = AOP_SIZE (IC_LEFT (ic));
3103 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3110 /* 4 byte return: store value in the global return variable */
3114 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3115 STA (fReturn2[offset--], FALSE);
3116 hc08_freeReg (hc08_reg_a);
3120 /* 2 byte return: store value in x:a */
3121 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3122 hc08_freeReg (hc08_reg_xa);
3125 /* 1 byte return: store value in a */
3126 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3127 hc08_freeReg (hc08_reg_a);
3132 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3135 /* generate a jump to the return label
3136 if the next is not the return statement */
3137 if (!(ic->next && ic->next->op == LABEL &&
3138 IC_LABEL (ic->next) == returnLabel))
3140 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3144 /*-----------------------------------------------------------------*/
3145 /* genLabel - generates a label */
3146 /*-----------------------------------------------------------------*/
3148 genLabel (iCode * ic)
3153 /* For the high level labels we cannot depend on any */
3154 /* register's contents. Amnesia time. */
3155 for (i=A_IDX;i<=XA_IDX;i++)
3157 reg = hc08_regWithIdx(i);
3162 /* special case never generate */
3163 if (IC_LABEL (ic) == entryLabel)
3166 debugFile->writeLabel(IC_LABEL (ic), ic);
3168 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3172 /*-----------------------------------------------------------------*/
3173 /* genGoto - generates a jmp */
3174 /*-----------------------------------------------------------------*/
3176 genGoto (iCode * ic)
3178 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3182 /*-----------------------------------------------------------------*/
3183 /* findLabelBackwards: walks back through the iCode chain looking */
3184 /* for the given label. Returns number of iCode instructions */
3185 /* between that label and given ic. */
3186 /* Returns zero if label not found. */
3187 /*-----------------------------------------------------------------*/
3189 findLabelBackwards (iCode * ic, int key)
3198 /* If we have any pushes or pops, we cannot predict the distance.
3199 I don't like this at all, this should be dealt with in the
3201 if (ic->op == IPUSH || ic->op == IPOP) {
3205 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3215 /*-----------------------------------------------------------------*/
3216 /* genPlusIncr :- does addition with increment if possible */
3217 /*-----------------------------------------------------------------*/
3219 genPlusIncr (iCode * ic)
3227 unsigned int size = getDataSize (IC_RESULT (ic));
3228 unsigned int offset;
3229 symbol *tlbl = NULL;
3231 left = IC_LEFT (ic);
3232 result = IC_RESULT (ic);
3234 /* will try to generate an increment */
3235 /* if the right side is not a literal
3237 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3240 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3242 DD(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3244 if ((IS_AOP_HX (AOP (left)) ||
3245 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3247 && (icount>=-128) && (icount<=127) && (size==2))
3249 if (!IS_AOP_HX (AOP (left)))
3251 needpulx = pushRegIfUsed (hc08_reg_x);
3252 needpulh = pushRegIfUsed (hc08_reg_h);
3259 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3260 emitcode ("aix","#%d", icount);
3261 hc08_dirtyReg (hc08_reg_hx, FALSE);
3262 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3263 pullOrFreeReg (hc08_reg_h, needpulh);
3264 pullOrFreeReg (hc08_reg_x, needpulx);
3268 DD(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3269 sameRegs (AOP (left), AOP (result))));
3271 if ((icount > 255) || (icount<0))
3274 if (!sameRegs (AOP (left), AOP (result)))
3277 D(emitcode ("; genPlusIncr",""));
3280 tlbl = newiTempLabel (NULL);
3285 rmwWithAop ("inc", AOP (result), 0);
3287 emitBranch ("bne", tlbl);
3291 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3292 needpula = pushRegIfUsed (hc08_reg_a);
3295 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3296 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3297 hc08_useReg (hc08_reg_a);
3298 storeRegToAop (hc08_reg_a, AOP (result), 0);
3299 hc08_freeReg (hc08_reg_a);
3301 emitBranch ("bcc", tlbl);
3303 for (offset=1; offset<size; offset++)
3305 rmwWithAop ("inc", AOP (result), offset);
3306 if ((offset+1)<size)
3307 emitBranch ("bne", tlbl);
3313 pullOrFreeReg (hc08_reg_a, needpula);
3320 /*-----------------------------------------------------------------*/
3321 /* genPlus - generates code for addition */
3322 /*-----------------------------------------------------------------*/
3324 genPlus (iCode * ic)
3326 int size, offset = 0;
3328 asmop *leftOp, *rightOp;
3330 /* special cases :- */
3332 D(emitcode ("; genPlus",""));
3334 aopOp (IC_LEFT (ic), ic, FALSE);
3335 aopOp (IC_RIGHT (ic), ic, FALSE);
3336 aopOp (IC_RESULT (ic), ic, TRUE);
3338 /* we want registers on the left and literals on the right */
3339 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3340 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3342 operand *t = IC_RIGHT (ic);
3343 IC_RIGHT (ic) = IC_LEFT (ic);
3348 /* if I can do an increment instead
3349 of add then GOOD for ME */
3350 if (genPlusIncr (ic) == TRUE)
3353 DD(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3354 DD(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3355 DD(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3357 size = getDataSize (IC_RESULT (ic));
3359 leftOp = AOP(IC_LEFT(ic));
3360 rightOp = AOP(IC_RIGHT(ic));
3366 loadRegFromAop (hc08_reg_a, leftOp, offset);
3367 accopWithAop(add, rightOp, offset);
3368 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3369 hc08_freeReg (hc08_reg_a);
3370 add = "adc"; /* further adds must propagate carry */
3374 // adjustArithmeticResult (ic);
3377 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3378 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3379 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3382 /*-----------------------------------------------------------------*/
3383 /* genMinusDec :- does subtraction with decrement if possible */
3384 /*-----------------------------------------------------------------*/
3386 genMinusDec (iCode * ic)
3388 unsigned int icount;
3393 unsigned int size = getDataSize (IC_RESULT (ic));
3397 left = IC_LEFT (ic);
3398 result = IC_RESULT (ic);
3400 /* will try to generate an increment */
3401 /* if the right side is not a literal
3403 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3406 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3408 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3409 && (icount>=-127) && (icount<=128) && (size==2))
3411 if (!IS_AOP_HX (AOP (left)))
3413 needpulx = pushRegIfUsed (hc08_reg_x);
3414 needpulh = pushRegIfUsed (hc08_reg_h);
3421 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3422 emitcode ("aix","#%d", -icount);
3423 hc08_dirtyReg (hc08_reg_hx, FALSE);
3424 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3425 pullOrFreeReg (hc08_reg_h, needpulh);
3426 pullOrFreeReg (hc08_reg_x, needpulx);
3430 if ((icount > 1) || (icount<0))
3433 if (!sameRegs (AOP (left), AOP (result)))
3439 D(emitcode ("; genMinusDec",""));
3441 rmwWithAop ("dec", AOP (result), 0);
3446 /*-----------------------------------------------------------------*/
3447 /* addSign - complete with sign */
3448 /*-----------------------------------------------------------------*/
3450 addSign (operand * result, int offset, int sign)
3452 int size = (getDataSize (result) - offset);
3457 emitcode ("rola", "");
3458 emitcode ("clra", "");
3459 emitcode ("sbc", zero);
3461 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3465 storeConstToAop (zero, AOP (result), offset++);
3470 /*-----------------------------------------------------------------*/
3471 /* genMinus - generates code for subtraction */
3472 /*-----------------------------------------------------------------*/
3474 genMinus (iCode * ic)
3477 int size, offset = 0;
3479 asmop *leftOp, *rightOp;
3481 D(emitcode ("; genMinus",""));
3483 aopOp (IC_LEFT (ic), ic, FALSE);
3484 aopOp (IC_RIGHT (ic), ic, FALSE);
3485 aopOp (IC_RESULT (ic), ic, TRUE);
3487 /* special cases :- */
3488 /* if I can do an decrement instead
3489 of subtract then GOOD for ME */
3490 if (genMinusDec (ic) == TRUE)
3493 size = getDataSize (IC_RESULT (ic));
3496 leftOp = AOP(IC_LEFT(ic));
3497 rightOp = AOP(IC_RIGHT(ic));
3501 if (IS_AOP_A (rightOp))
3503 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3504 accopWithAop (sub, leftOp, offset);
3505 accopWithMisc ("nega", "");
3506 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3512 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3513 accopWithAop (sub, rightOp, offset);
3514 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3519 // adjustArithmeticResult (ic);
3522 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3523 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3524 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3529 /*-----------------------------------------------------------------*/
3530 /* genMultOneByte : 8*8=8/16 bit multiplication */
3531 /*-----------------------------------------------------------------*/
3533 genMultOneByte (operand * left,
3537 /* sym_link *opetype = operandType (result); */
3538 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3539 int size=AOP_SIZE(result);
3540 bool negLiteral = FALSE;
3541 bool lUnsigned, rUnsigned;
3543 D(emitcode ("; genMultOneByte",""));
3545 if (size<1 || size>2) {
3546 // this should never happen
3547 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3548 AOP_SIZE(result), __FILE__, lineno);
3552 /* (if two literals: the value is computed before) */
3553 /* if one literal, literal on the right */
3554 if (AOP_TYPE (left) == AOP_LIT)
3560 /* if an operand is in A, make sure it is on the left */
3561 if (IS_AOP_A (AOP (right)))
3568 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3569 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3571 /* lUnsigned rUnsigned negLiteral negate case */
3572 /* false false false odd 3 */
3573 /* false false true even 3 */
3574 /* false true false odd 3 */
3575 /* false true true impossible */
3576 /* true false false odd 3 */
3577 /* true false true always 2 */
3578 /* true true false never 1 */
3579 /* true true true impossible */
3583 || (lUnsigned && rUnsigned))
3585 // just an unsigned 8*8=8/16 multiply
3586 //DD(emitcode (";","unsigned"));
3588 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3589 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3590 emitcode ("mul", "");
3591 hc08_dirtyReg (hc08_reg_xa, FALSE);
3592 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3593 hc08_freeReg (hc08_reg_xa);
3598 // we have to do a signed multiply
3601 /* left unsigned, right signed literal -- literal determines sign handling */
3602 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3604 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3606 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3608 emitcode ("ldx", "#0x%02x", -val);
3610 emitcode ("ldx", "#0x%02x", val);
3612 emitcode ("mul", "");
3616 rmwWithReg ("neg", hc08_reg_a);
3617 tlbl4 = newiTempLabel (NULL);
3618 emitBranch ("bcc", tlbl4);
3619 rmwWithReg ("inc", hc08_reg_x);
3621 rmwWithReg ("neg", hc08_reg_x);
3624 hc08_dirtyReg (hc08_reg_xa, FALSE);
3625 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3626 hc08_freeReg (hc08_reg_xa);
3633 emitcode ("clr", "1,s");
3635 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3638 tlbl1 = newiTempLabel (NULL);
3639 emitcode ("tsta","");
3640 emitBranch ("bpl", tlbl1);
3641 emitcode ("inc", "1,s");
3642 rmwWithReg ("neg", hc08_reg_a);
3646 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3648 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3649 /* AND literal negative */
3651 emitcode ("ldx", "#0x%02x", -val);
3654 emitcode ("ldx", "#0x%02x", val);
3656 hc08_useReg (hc08_reg_x);
3660 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3663 tlbl2 = newiTempLabel (NULL);
3664 emitcode ("tstx", "");
3665 emitBranch ("bpl", tlbl2);
3666 emitcode ("inc", "1,s");
3667 rmwWithReg ("neg", hc08_reg_x);
3672 emitcode ("mul", "");
3673 hc08_dirtyReg (hc08_reg_xa, FALSE);
3675 tlbl3 = newiTempLabel (NULL);
3676 emitcode ("dec", "1,s");
3677 if (!lUnsigned && !rUnsigned && negLiteral)
3678 emitBranch ("beq", tlbl3);
3680 emitBranch ("bne", tlbl3);
3682 rmwWithReg ("neg", hc08_reg_a);
3683 tlbl4 = newiTempLabel (NULL);
3684 emitBranch ("bcc", tlbl4);
3685 rmwWithReg ("inc", hc08_reg_x);
3687 rmwWithReg ("neg", hc08_reg_x);
3691 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3692 hc08_freeReg (hc08_reg_xa);
3696 /*-----------------------------------------------------------------*/
3697 /* genMult - generates code for multiplication */
3698 /*-----------------------------------------------------------------*/
3700 genMult (iCode * ic)
3702 operand *left = IC_LEFT (ic);
3703 operand *right = IC_RIGHT (ic);
3704 operand *result = IC_RESULT (ic);
3706 D(emitcode ("; genMult",""));
3708 /* assign the amsops */
3709 aopOp (left, ic, FALSE);
3710 aopOp (right, ic, FALSE);
3711 aopOp (result, ic, TRUE);
3713 /* special cases first */
3714 /* if both are of size == 1 */
3715 // if (getSize(operandType(left)) == 1 &&
3716 // getSize(operandType(right)) == 1)
3717 if (AOP_SIZE (left) == 1 &&
3718 AOP_SIZE (right) == 1)
3720 genMultOneByte (left, right, result);
3724 /* should have been converted to function call */
3725 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3726 getSize(OP_SYMBOL(right)->type));
3727 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3732 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3733 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3734 freeAsmop (result, NULL, ic, TRUE);
3737 /*-----------------------------------------------------------------*/
3738 /* genDivOneByte : 8 bit division */
3739 /*-----------------------------------------------------------------*/
3741 genDivOneByte (operand * left,
3745 symbol *tlbl1, *tlbl2, *tlbl3;
3748 bool lUnsigned, rUnsigned;
3749 bool runtimeSign, compiletimeSign;
3751 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3752 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3754 D(emitcode ("; genDivOneByte",""));
3756 size = AOP_SIZE (result);
3757 /* signed or unsigned */
3758 if (lUnsigned && rUnsigned)
3760 /* unsigned is easy */
3761 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3762 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3763 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3764 emitcode ("div", "");
3765 hc08_dirtyReg (hc08_reg_a, FALSE);
3766 hc08_dirtyReg (hc08_reg_h, FALSE);
3767 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3768 hc08_freeReg (hc08_reg_a);
3769 hc08_freeReg (hc08_reg_x);
3770 hc08_freeReg (hc08_reg_h);
3774 /* signed is a little bit more difficult */
3776 /* now sign adjust for both left & right */
3778 /* let's see what's needed: */
3779 /* apply negative sign during runtime */
3780 runtimeSign = FALSE;
3781 /* negative sign from literals */
3782 compiletimeSign = FALSE;
3786 if (AOP_TYPE(left) == AOP_LIT)
3788 /* signed literal */
3789 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3791 compiletimeSign = TRUE;
3794 /* signed but not literal */
3800 if (AOP_TYPE(right) == AOP_LIT)
3802 /* signed literal */
3803 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3805 compiletimeSign ^= TRUE;
3808 /* signed but not literal */
3812 /* initialize the runtime sign */
3815 if (compiletimeSign)
3816 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3818 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3819 pushReg (hc08_reg_x, TRUE);
3822 /* save the signs of the operands */
3823 if (AOP_TYPE(right) == AOP_LIT)
3825 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3827 if (!rUnsigned && val < 0)
3828 emitcode ("ldx", "#0x%02x", -val);
3830 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3832 else /* ! literal */
3834 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3837 tlbl1 = newiTempLabel (NULL);
3838 emitcode ("tstx", "");
3839 emitBranch ("bpl", tlbl1);
3840 emitcode ("inc", "1,s");
3841 rmwWithReg ("neg", hc08_reg_x);
3846 if (AOP_TYPE(left) == AOP_LIT)
3848 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3850 if (!lUnsigned && val < 0)
3851 emitcode ("lda", "#0x%02x", -val);
3853 emitcode ("lda", "#0x%02x", (unsigned char) val);
3855 else /* ! literal */
3857 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3860 tlbl2 = newiTempLabel (NULL);
3861 emitcode ("tsta", "");
3862 emitBranch ("bpl", tlbl2);
3863 emitcode ("inc", "1,s");
3864 rmwWithReg ("neg", hc08_reg_a);
3869 loadRegFromConst (hc08_reg_h, zero);
3870 emitcode ("div", "");
3871 hc08_dirtyReg (hc08_reg_x, FALSE);
3872 hc08_dirtyReg (hc08_reg_a, FALSE);
3873 hc08_dirtyReg (hc08_reg_h, FALSE);
3875 if (runtimeSign || compiletimeSign)
3877 tlbl3 = newiTempLabel (NULL);
3880 pullReg (hc08_reg_x);
3881 rmwWithReg ("lsr", hc08_reg_x);
3882 rmwWithReg ("ror", hc08_reg_x);
3883 emitBranch ("bpl", tlbl3);
3886 rmwWithReg ("neg", hc08_reg_a);
3890 storeRegToAop (hc08_reg_a, AOP (result), 0);
3894 /* msb is 0x00 or 0xff depending on the sign */
3897 rmwWithReg ("lsl", hc08_reg_x);
3898 emitcode ("clra", "");
3899 emitcode ("sbc", "#0");
3901 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3903 else /* compiletimeSign */
3905 storeConstToAop ("#0xff", AOP (result), ++offset);
3910 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3913 hc08_freeReg (hc08_reg_a);
3914 hc08_freeReg (hc08_reg_x);
3915 hc08_freeReg (hc08_reg_h);
3918 /*-----------------------------------------------------------------*/
3919 /* genDiv - generates code for division */
3920 /*-----------------------------------------------------------------*/
3924 operand *left = IC_LEFT (ic);
3925 operand *right = IC_RIGHT (ic);
3926 operand *result = IC_RESULT (ic);
3928 D(emitcode ("; genDiv",""));
3930 /* assign the amsops */
3931 aopOp (left, ic, FALSE);
3932 aopOp (right, ic, FALSE);
3933 aopOp (result, ic, TRUE);
3935 /* special cases first */
3936 /* if both are of size == 1 */
3937 if (AOP_SIZE (left) <= 2 &&
3938 AOP_SIZE (right) == 1)
3940 genDivOneByte (left, right, result);
3944 /* should have been converted to function call */
3947 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3948 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3949 freeAsmop (result, NULL, ic, TRUE);
3952 /*-----------------------------------------------------------------*/
3953 /* genModOneByte : 8 bit modulus */
3954 /*-----------------------------------------------------------------*/
3956 genModOneByte (operand * left,
3960 symbol *tlbl1, *tlbl2, *tlbl3;
3963 bool lUnsigned, rUnsigned;
3964 bool runtimeSign, compiletimeSign;
3966 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3967 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3969 D(emitcode ("; genModOneByte",""));
3971 size = AOP_SIZE (result);
3973 if (lUnsigned && rUnsigned)
3975 /* unsigned is easy */
3976 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3977 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3978 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3979 emitcode ("div", "");
3980 hc08_freeReg (hc08_reg_a);
3981 hc08_freeReg (hc08_reg_x);
3982 hc08_dirtyReg (hc08_reg_h, FALSE);
3983 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3984 hc08_freeReg (hc08_reg_h);
3988 /* signed is a little bit more difficult */
3990 if (AOP_TYPE(right) == AOP_LIT)
3992 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3994 if (!rUnsigned && val < 0)
3995 emitcode ("ldx", "#0x%02x", -val);
3997 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3999 else /* ! literal */
4001 loadRegFromAop (hc08_reg_x, AOP (right), 0);
4004 tlbl1 = newiTempLabel (NULL);
4005 emitcode ("tstx", "");
4006 emitBranch ("bpl", tlbl1);
4007 rmwWithReg ("neg", hc08_reg_x);
4012 /* let's see what's needed: */
4013 /* apply negative sign during runtime */
4014 runtimeSign = FALSE;
4015 /* negative sign from literals */
4016 compiletimeSign = FALSE;
4018 /* sign adjust left side */
4019 if (AOP_TYPE(left) == AOP_LIT)
4021 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4023 if (!lUnsigned && val < 0)
4025 compiletimeSign = TRUE; /* set sign flag */
4026 emitcode ("lda", "#0x%02x", -val);
4029 emitcode ("lda", "#0x%02x", (unsigned char) val);
4031 else /* ! literal */
4034 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4039 emitcode ("clr", "1,s");
4041 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4042 tlbl2 = newiTempLabel (NULL);
4043 emitcode ("tsta", "");
4044 emitBranch ("bpl", tlbl2);
4045 emitcode ("inc", "1,s");
4046 rmwWithReg ("neg", hc08_reg_a);
4051 loadRegFromConst (hc08_reg_h, zero);
4052 emitcode ("div", "");
4053 hc08_freeReg (hc08_reg_a);
4054 hc08_freeReg (hc08_reg_x);
4055 hc08_dirtyReg (hc08_reg_h, FALSE);
4057 if (runtimeSign || compiletimeSign)
4059 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4060 tlbl3 = newiTempLabel (NULL);
4063 pullReg (hc08_reg_x);
4064 rmwWithReg ("lsr", hc08_reg_x);
4065 rmwWithReg ("ror", hc08_reg_x);
4066 emitBranch ("bpl", tlbl3);
4069 rmwWithReg ("neg", hc08_reg_a);
4073 storeRegToAop (hc08_reg_a, AOP (result), 0);
4077 /* msb is 0x00 or 0xff depending on the sign */
4080 rmwWithReg ("lsl", hc08_reg_x);
4081 emitcode ("clra", "");
4082 emitcode ("sbc", "#0");
4084 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4086 else /* compiletimeSign */
4088 storeConstToAop ("#0xff", AOP (result), ++offset);
4093 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4096 hc08_freeReg (hc08_reg_a);
4097 hc08_freeReg (hc08_reg_x);
4098 hc08_freeReg (hc08_reg_h);
4101 /*-----------------------------------------------------------------*/
4102 /* genMod - generates code for division */
4103 /*-----------------------------------------------------------------*/
4107 operand *left = IC_LEFT (ic);
4108 operand *right = IC_RIGHT (ic);
4109 operand *result = IC_RESULT (ic);
4111 D(emitcode ("; genMod",""));
4113 /* assign the amsops */
4114 aopOp (left, ic, FALSE);
4115 aopOp (right, ic, FALSE);
4116 aopOp (result, ic, TRUE);
4118 /* special cases first */
4119 /* if both are of size == 1 */
4120 if (AOP_SIZE (left) <= 2 &&
4121 AOP_SIZE (right) == 1)
4123 genModOneByte (left, right, result);
4127 /* should have been converted to function call */
4131 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4132 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4133 freeAsmop (result, NULL, ic, TRUE);
4136 /*-----------------------------------------------------------------*/
4137 /* genIfxJump :- will create a jump depending on the ifx */
4138 /*-----------------------------------------------------------------*/
4140 genIfxJump (iCode * ic, char *jval)
4143 symbol *tlbl = newiTempLabel (NULL);
4146 D(emitcode ("; genIfxJump",""));
4148 /* if true label then we jump if condition
4152 jlbl = IC_TRUE (ic);
4153 if (!strcmp (jval, "a"))
4155 else if (!strcmp (jval, "c"))
4162 /* false label is present */
4163 jlbl = IC_FALSE (ic);
4164 if (!strcmp (jval, "a"))
4166 else if (!strcmp (jval, "c"))
4171 emitBranch (inst, tlbl);
4172 emitBranch ("jmp", jlbl);
4175 /* mark the icode as generated */
4180 /*-----------------------------------------------------------------*/
4181 /* exchangedCmp : returns the opcode need if the two operands are */
4182 /* exchanged in a comparison */
4183 /*-----------------------------------------------------------------*/
4185 exchangedCmp (int opcode)
4202 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4203 "opcode not a comparison");
4205 return EQ_OP; /* shouldn't happen, but need to return something */
4208 /*------------------------------------------------------------------*/
4209 /* negatedCmp : returns the equivalent opcode for when a comparison */
4211 /*------------------------------------------------------------------*/
4213 negatedCmp (int opcode)
4230 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4231 "opcode not a comparison");
4233 return EQ_OP; /* shouldn't happen, but need to return something */
4236 /* compile only if the debugging macro D is enabled */
4239 nameCmp (int opcode)
4261 /*------------------------------------------------------------------*/
4262 /* branchInstCmp : returns the conditional branch instruction that */
4263 /* will branch if the comparison is true */
4264 /*------------------------------------------------------------------*/
4266 branchInstCmp (int opcode, int sign)
4274 return "bcs"; /* same as blo */
4289 return "bcc"; /* same as bhs */
4295 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4296 "opcode not a comparison");
4302 /*------------------------------------------------------------------*/
4303 /* genCmp :- greater or less than (and maybe with equal) comparison */
4304 /*------------------------------------------------------------------*/
4306 genCmp (iCode * ic, iCode * ifx)
4308 operand *left, *right, *result;
4309 sym_link *letype, *retype;
4311 int size, offset = 0;
4312 unsigned long lit = 0L;
4314 symbol *jlbl = NULL;
4318 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4320 result = IC_RESULT (ic);
4321 left = IC_LEFT (ic);
4322 right = IC_RIGHT (ic);
4324 letype = getSpec (operandType (left));
4325 retype = getSpec (operandType (right));
4326 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4327 /* assign the amsops */
4328 aopOp (left, ic, FALSE);
4329 aopOp (right, ic, FALSE);
4330 aopOp (result, ic, TRUE);
4332 /* need register operand on left, prefer literal operand on right */
4333 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4335 operand *temp = left;
4338 opcode = exchangedCmp (opcode);
4345 jlbl = IC_TRUE (ifx);
4346 opcode = negatedCmp (opcode);
4350 /* false label is present */
4351 jlbl = IC_FALSE (ifx);
4355 size = max (AOP_SIZE (left), AOP_SIZE (right));
4358 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4359 && ((AOP_TYPE (right) == AOP_LIT) ||
4360 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4361 && hc08_reg_hx->isFree)
4363 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4364 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4365 hc08_freeReg (hc08_reg_hx);
4376 /* These conditions depend on the Z flag bit, but Z is */
4377 /* only valid for the last byte of the comparison, not */
4378 /* the whole value. So exchange the operands to get a */
4379 /* comparison that doesn't depend on Z. (This is safe */
4380 /* to do here since ralloc won't assign multi-byte */
4381 /* operands to registers for comparisons) */
4382 if ((opcode == '>') || (opcode == LE_OP))
4384 operand *temp = left;
4387 opcode = exchangedCmp (opcode);
4390 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4392 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4393 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4402 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4403 accopWithAop (sub, AOP (right), offset);
4404 hc08_freeReg (hc08_reg_a);
4409 freeAsmop (right, NULL, ic, FALSE);
4410 freeAsmop (left, NULL, ic, FALSE);
4414 symbol *tlbl = newiTempLabel (NULL);
4417 freeAsmop (result, NULL, ic, TRUE);
4419 inst = branchInstCmp (opcode, sign);
4420 emitBranch (inst, tlbl);
4421 emitBranch ("jmp", jlbl);
4424 /* mark the icode as generated */
4429 symbol *tlbl1 = newiTempLabel (NULL);
4430 symbol *tlbl2 = newiTempLabel (NULL);
4432 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4433 loadRegFromConst (hc08_reg_a, zero);
4434 emitBranch ("bra", tlbl2);
4436 loadRegFromConst (hc08_reg_a, one);
4438 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4439 freeAsmop (result, NULL, ic, TRUE);
4444 /*-----------------------------------------------------------------*/
4445 /* genCmpEQorNE - equal or not equal comparison */
4446 /*-----------------------------------------------------------------*/
4448 genCmpEQorNE (iCode * ic, iCode * ifx)
4450 operand *left, *right, *result;
4451 sym_link *letype, *retype;
4453 int size, offset = 0;
4455 symbol *jlbl = NULL;
4456 symbol *tlbl_NE = NULL;
4457 symbol *tlbl_EQ = NULL;
4461 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4463 result = IC_RESULT (ic);
4464 left = IC_LEFT (ic);
4465 right = IC_RIGHT (ic);
4467 letype = getSpec (operandType (left));
4468 retype = getSpec (operandType (right));
4469 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4470 /* assign the amsops */
4471 aopOp (left, ic, FALSE);
4472 aopOp (right, ic, FALSE);
4473 aopOp (result, ic, TRUE);
4475 /* need register operand on left, prefer literal operand on right */
4476 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4478 operand *temp = left;
4481 opcode = exchangedCmp (opcode);
4488 jlbl = IC_TRUE (ifx);
4489 opcode = negatedCmp (opcode);
4493 /* false label is present */
4494 jlbl = IC_FALSE (ifx);
4498 size = max (AOP_SIZE (left), AOP_SIZE (right));
4501 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4502 && ((AOP_TYPE (right) == AOP_LIT) ||
4503 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4504 && hc08_reg_hx->isFree)
4506 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4507 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4508 hc08_freeReg (hc08_reg_hx);
4516 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4517 accopWithAop (sub, AOP (right), offset);
4521 tlbl_NE = newiTempLabel (NULL);
4522 emitBranch ("bne", tlbl_NE);
4524 hc08_freeReg (hc08_reg_a);
4528 freeAsmop (right, NULL, ic, FALSE);
4529 freeAsmop (left, NULL, ic, FALSE);
4533 freeAsmop (result, NULL, ic, TRUE);
4535 if (opcode == EQ_OP)
4538 tlbl_EQ = newiTempLabel (NULL);
4539 emitBranch ("beq", tlbl_EQ);
4541 emitLabel (tlbl_NE);
4542 emitBranch ("jmp", jlbl);
4543 emitLabel (tlbl_EQ);
4548 tlbl_NE = newiTempLabel (NULL);
4549 emitBranch ("bne", tlbl_NE);
4550 emitBranch ("jmp", jlbl);
4551 emitLabel (tlbl_NE);
4554 /* mark the icode as generated */
4559 symbol *tlbl = newiTempLabel (NULL);
4561 if (opcode == EQ_OP)
4564 tlbl_EQ = newiTempLabel (NULL);
4565 emitBranch ("beq", tlbl_EQ);
4567 emitLabel (tlbl_NE);
4568 loadRegFromConst (hc08_reg_a, zero);
4569 emitBranch ("bra", tlbl);
4570 emitLabel (tlbl_EQ);
4571 loadRegFromConst (hc08_reg_a, one);
4576 tlbl_NE = newiTempLabel (NULL);
4577 emitBranch ("bne", tlbl_NE);
4578 loadRegFromConst (hc08_reg_a, zero);
4579 emitBranch ("bra", tlbl);
4580 emitLabel (tlbl_NE);
4581 loadRegFromConst (hc08_reg_a, one);
4585 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4586 freeAsmop (result, NULL, ic, TRUE);
4592 /*-----------------------------------------------------------------*/
4593 /* ifxForOp - returns the icode containing the ifx for operand */
4594 /*-----------------------------------------------------------------*/
4596 ifxForOp (operand * op, iCode * ic)
4598 /* if true symbol then needs to be assigned */
4599 if (IS_TRUE_SYMOP (op))
4602 /* if this has register type condition and
4603 the next instruction is ifx with the same operand
4604 and live to of the operand is upto the ifx only then */
4606 ic->next->op == IFX &&
4607 IC_COND (ic->next)->key == op->key &&
4608 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4615 genPointerGetSetOfs (iCode *ic)
4617 iCode *lic = ic->next;
4623 /* Make sure we have a next iCode */
4624 DD(emitcode("","; checking lic"));
4628 /* Make sure the result of the addition is an iCode */
4629 DD(emitcode("","; checking IS_ITEMP"));
4630 if (!IS_ITEMP (IC_RESULT (ic)))
4633 /* Make sure the next iCode is a pointer set or get */
4634 pset = POINTER_SET(lic);
4635 pget = POINTER_GET(lic);
4636 DD(emitcode("","; pset=%d, pget=%d",pset,pget));
4640 /* Make sure this is the only use of the pointer */
4641 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4644 DD(emitcode("", "; checking pset operandsEqu"));
4645 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4648 DD(emitcode("", "; checking pget operandsEqu"));
4649 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4652 DD(emitcode("", "; checking IS_SYMOP"));
4653 if (!IS_SYMOP (IC_LEFT (ic)))
4656 DD(emitcode("", "; checking !IS_TRUE_SYMOP"));
4657 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4660 sym = OP_SYMBOL (IC_LEFT (ic));
4662 DD(emitcode("", "; checking remat"));
4669 D(emitcode ("; genPointerGetOfs",""));
4670 aopOp (IC_LEFT(ic), ic, FALSE);
4671 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4672 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4674 aopOp (IC_RIGHT(ic), ic, FALSE);
4675 aopOp (IC_RESULT(lic), lic, FALSE);
4677 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4679 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4681 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4682 loadRegFromConst (hc08_reg_h, zero);
4686 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4687 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4688 emitcode ("rola","");
4689 emitcode ("clra","");
4690 emitcode ("sbc", "#0");
4691 hc08_useReg (hc08_reg_a);
4692 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4696 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4697 size = AOP_SIZE (IC_RESULT(lic));
4698 derefaop->size = size;
4702 emitcode ("lda", "%s,x",
4703 aopAdrStr (derefaop, size, TRUE));
4704 hc08_useReg (hc08_reg_a);
4705 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4706 hc08_freeReg (hc08_reg_a);
4710 hc08_freeReg (hc08_reg_hx);
4712 freeAsmop (NULL, derefaop, ic, TRUE);
4713 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4714 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4721 D(emitcode ("; genPointerSetOfs",""));
4722 aopOp (IC_LEFT(ic), ic, FALSE);
4723 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4724 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4726 aopOp (IC_RIGHT(ic), ic, FALSE);
4727 aopOp (IC_RIGHT(lic), lic, FALSE);
4729 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4731 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4733 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4734 loadRegFromConst (hc08_reg_h, zero);
4738 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4739 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4740 emitcode ("rola","");
4741 emitcode ("clra","");
4742 emitcode ("sbc", "#0");
4743 hc08_useReg (hc08_reg_a);
4744 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4748 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4749 size = AOP_SIZE (IC_RIGHT(lic));
4750 derefaop->size = size;
4754 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4755 emitcode ("sta", "%s,x",
4756 aopAdrStr (derefaop, size, TRUE));
4757 hc08_freeReg (hc08_reg_a);
4761 hc08_freeReg (hc08_reg_hx);
4763 freeAsmop (NULL, derefaop, ic, TRUE);
4764 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4765 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4774 /*-----------------------------------------------------------------*/
4775 /* hasInc - operand is incremented before any other use */
4776 /*-----------------------------------------------------------------*/
4778 hasInc (operand *op, iCode *ic,int osize)
4780 sym_link *type = operandType(op);
4781 sym_link *retype = getSpec (type);
4782 iCode *lic = ic->next;
4785 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4786 if (!IS_SYMOP(op)) return NULL;
4788 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4789 if (IS_AGGREGATE(type->next)) return NULL;
4790 if (osize != (isize = getSize(type->next))) return NULL;
4793 /* if operand of the form op = op + <sizeof *op> */
4794 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4795 isOperandEqual(IC_RESULT(lic),op) &&
4796 isOperandLiteral(IC_RIGHT(lic)) &&
4797 operandLitValue(IC_RIGHT(lic)) == isize) {
4800 /* if the operand used or deffed */
4801 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4804 /* if GOTO or IFX */
4805 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4811 /*-----------------------------------------------------------------*/
4812 /* genAndOp - for && operation */
4813 /*-----------------------------------------------------------------*/
4815 genAndOp (iCode * ic)
4817 operand *left, *right, *result;
4818 symbol *tlbl, *tlbl0;
4820 D(emitcode ("; genAndOp",""));
4822 /* note here that && operations that are in an
4823 if statement are taken away by backPatchLabels
4824 only those used in arthmetic operations remain */
4825 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4826 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4827 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4829 tlbl = newiTempLabel (NULL);
4830 tlbl0 = newiTempLabel (NULL);
4832 asmopToBool (AOP (left), FALSE);
4833 emitBranch ("beq", tlbl0);
4834 asmopToBool (AOP (right), FALSE);
4835 emitBranch ("beq", tlbl0);
4836 loadRegFromConst (hc08_reg_a,one);
4837 emitBranch ("bra", tlbl);
4839 loadRegFromConst (hc08_reg_a,zero);
4842 hc08_useReg (hc08_reg_a);
4843 hc08_freeReg (hc08_reg_a);
4845 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4847 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4848 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849 freeAsmop (result, NULL, ic, TRUE);
4853 /*-----------------------------------------------------------------*/
4854 /* genOrOp - for || operation */
4855 /*-----------------------------------------------------------------*/
4857 genOrOp (iCode * ic)
4859 operand *left, *right, *result;
4860 symbol *tlbl, *tlbl0;
4862 D(emitcode ("; genOrOp",""));
4864 /* note here that || operations that are in an
4865 if statement are taken away by backPatchLabels
4866 only those used in arthmetic operations remain */
4867 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4868 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4869 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4871 tlbl = newiTempLabel (NULL);
4872 tlbl0 = newiTempLabel (NULL);
4874 asmopToBool (AOP (left), FALSE);
4875 emitBranch ("bne", tlbl0);
4876 asmopToBool (AOP (right), FALSE);
4877 emitBranch ("bne", tlbl0);
4878 loadRegFromConst (hc08_reg_a,zero);
4879 emitBranch ("bra", tlbl);
4881 loadRegFromConst (hc08_reg_a,one);
4884 hc08_useReg (hc08_reg_a);
4885 hc08_freeReg (hc08_reg_a);
4887 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4890 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4891 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4892 freeAsmop (result, NULL, ic, TRUE);
4895 /*-----------------------------------------------------------------*/
4896 /* isLiteralBit - test if lit == 2^n */
4897 /*-----------------------------------------------------------------*/
4899 isLiteralBit (unsigned long lit)
4901 unsigned long pw[32] =
4902 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4903 0x100L, 0x200L, 0x400L, 0x800L,
4904 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4905 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4906 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4907 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4908 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4911 for (idx = 0; idx < 32; idx++)
4918 /*-----------------------------------------------------------------*/
4919 /* continueIfTrue - */
4920 /*-----------------------------------------------------------------*/
4922 continueIfTrue (iCode * ic)
4925 emitBranch ("jmp", IC_TRUE (ic));
4929 /*-----------------------------------------------------------------*/
4931 /*-----------------------------------------------------------------*/
4933 jumpIfTrue (iCode * ic)
4936 emitBranch ("jmp", IC_FALSE (ic));
4940 /*-----------------------------------------------------------------*/
4941 /* jmpTrueOrFalse - */
4942 /*-----------------------------------------------------------------*/
4944 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4946 // ugly but optimized by peephole
4949 symbol *nlbl = newiTempLabel (NULL);
4950 emitBranch ("bra", nlbl);
4952 emitBranch ("jmp", IC_TRUE (ic));
4957 emitBranch ("jmp", IC_FALSE (ic));
4964 /*-----------------------------------------------------------------*/
4965 /* genAnd - code for and */
4966 /*-----------------------------------------------------------------*/
4968 genAnd (iCode * ic, iCode * ifx)
4970 operand *left, *right, *result;
4971 int size, offset = 0;
4972 unsigned long lit = 0L;
4973 unsigned long litinv;
4974 unsigned char bytemask;
4980 D(emitcode ("; genAnd",""));
4982 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4983 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4984 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4987 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4989 AOP_TYPE (left), AOP_TYPE (right)));
4990 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4992 AOP_SIZE (left), AOP_SIZE (right)));
4995 /* if left is a literal & right is not then exchange them */
4996 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4998 operand *tmp = right;
5003 /* if right is accumulator & left is not then exchange them */
5004 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5006 operand *tmp = right;
5011 if (AOP_TYPE (right) == AOP_LIT)
5012 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5014 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5016 if (AOP_TYPE (result) == AOP_CRY
5018 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5020 /* this generates ugly code, but meets volatility requirements */
5021 loadRegFromConst (hc08_reg_a, zero);
5022 pushReg (hc08_reg_a, TRUE);
5027 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5028 accopWithAop ("and", AOP (right), offset);
5029 emitcode ("ora", "1,s");
5030 emitcode ("sta", "1,s");
5034 pullReg (hc08_reg_a);
5035 emitcode ("tsta", "");
5036 genIfxJump (ifx, "a");
5040 if (AOP_TYPE (result) == AOP_CRY)
5042 symbol *tlbl = NULL;
5043 wassertl (ifx, "AOP_CRY result without ifx");
5048 bytemask = (lit >> (offset*8)) & 0xff;
5050 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5054 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5056 rmwWithAop ("tst", AOP (left), offset);
5060 tlbl = newiTempLabel (NULL);
5061 emitBranch ("bne", tlbl);
5066 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5067 accopWithAop ("and", AOP (right), offset);
5068 hc08_freeReg( hc08_reg_a);
5072 tlbl = newiTempLabel (NULL);
5073 emitBranch ("bne", tlbl);
5080 genIfxJump (ifx, "a");
5084 size = AOP_SIZE (result);
5086 if (AOP_TYPE (right) == AOP_LIT)
5088 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5089 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5090 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5092 int bitpos = isLiteralBit(litinv)-1;
5093 emitcode ("bclr","#%d,%s",bitpos & 7,
5094 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5102 bytemask = (lit >> (offset*8)) & 0xff;
5104 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5106 if (isOperandVolatile (left, FALSE))
5108 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5109 hc08_freeReg( hc08_reg_a);
5111 storeConstToAop (zero, AOP (result), offset);
5113 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5115 transferAopAop (AOP (left), offset, AOP (result), offset);
5119 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5120 accopWithAop ("and", AOP (right), offset);
5121 storeRegToAop (hc08_reg_a, AOP (result), offset);
5122 hc08_freeReg (hc08_reg_a);
5128 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5129 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5130 freeAsmop (result, NULL, ic, TRUE);
5133 /*-----------------------------------------------------------------*/
5134 /* genOr - code for or */
5135 /*-----------------------------------------------------------------*/
5137 genOr (iCode * ic, iCode * ifx)
5139 operand *left, *right, *result;
5140 int size, offset = 0;
5141 unsigned long lit = 0L;
5142 unsigned char bytemask;
5144 D(emitcode ("; genOr",""));
5146 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5147 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5148 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5151 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5153 AOP_TYPE (left), AOP_TYPE (right)));
5154 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5156 AOP_SIZE (left), AOP_SIZE (right)));
5159 /* if left is a literal & right is not then exchange them */
5160 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5162 operand *tmp = right;
5167 /* if left is accumulator & right is not then exchange them */
5168 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5170 operand *tmp = right;
5175 if (AOP_TYPE (right) == AOP_LIT)
5176 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5178 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5180 if (AOP_TYPE (result) == AOP_CRY
5182 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5184 /* this generates ugly code, but meets volatility requirements */
5185 loadRegFromConst (hc08_reg_a, zero);
5186 pushReg (hc08_reg_a, TRUE);
5191 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5192 accopWithAop ("ora", AOP (right), offset);
5193 emitcode ("ora", "1,s");
5194 emitcode ("sta", "1,s");
5198 pullReg (hc08_reg_a);
5199 emitcode ("tsta", "");
5200 genIfxJump (ifx, "a");
5204 if (AOP_TYPE (result) == AOP_CRY)
5206 symbol *tlbl = NULL;
5207 wassertl (ifx, "AOP_CRY result without ifx");
5212 bytemask = (lit >> (offset*8)) & 0xff;
5214 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5216 rmwWithAop ("tst", AOP (left), offset);
5220 tlbl = newiTempLabel (NULL);
5221 emitBranch ("bne", tlbl);
5226 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5227 accopWithAop ("ora", AOP (right), offset);
5228 hc08_freeReg( hc08_reg_a);
5232 tlbl = newiTempLabel (NULL);
5233 emitBranch ("bne", tlbl);
5240 genIfxJump (ifx, "a");
5243 if (AOP_TYPE (right) == AOP_LIT)
5244 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5246 size = AOP_SIZE (result);
5248 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5249 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5250 (AOP_TYPE (left) == AOP_DIR))
5252 int bitpos = isLiteralBit(lit)-1;
5253 emitcode ("bset","#%d,%s",bitpos & 7,
5254 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5261 bytemask = (lit >> (offset*8)) & 0xff;
5263 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5265 if (isOperandVolatile (left, FALSE))
5267 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5268 hc08_freeReg( hc08_reg_a);
5270 transferAopAop (AOP (right), offset, AOP (result), offset);
5272 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5274 transferAopAop (AOP (left), offset, AOP (result), offset);
5278 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5279 accopWithAop ("ora", AOP (right), offset);
5280 storeRegToAop (hc08_reg_a, AOP (result), offset);
5281 hc08_freeReg (hc08_reg_a);
5288 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5289 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5290 freeAsmop (result, NULL, ic, TRUE);
5293 /*-----------------------------------------------------------------*/
5294 /* genXor - code for xclusive or */
5295 /*-----------------------------------------------------------------*/
5297 genXor (iCode * ic, iCode * ifx)
5299 operand *left, *right, *result;
5300 int size, offset = 0;
5301 unsigned long lit = 0L;
5303 D(emitcode ("; genXor",""));
5305 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5306 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5307 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5310 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5312 AOP_TYPE (left), AOP_TYPE (right)));
5313 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5315 AOP_SIZE (left), AOP_SIZE (right)));
5318 /* if left is a literal & right is not ||
5319 if left needs acc & right does not */
5320 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5322 operand *tmp = right;
5327 /* if left is accumulator & right is not then exchange them */
5328 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5330 operand *tmp = right;
5335 if (AOP_TYPE (result) == AOP_CRY)
5338 wassertl (ifx, "AOP_CPY result without ifx");
5340 tlbl = newiTempLabel (NULL);
5341 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5345 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5346 if ((AOP_TYPE (right) == AOP_LIT)
5347 && (((lit >> (offset*8)) & 0xff) == 0))
5348 emitcode ("tsta","");
5350 accopWithAop ("eor", AOP (right), offset);
5351 hc08_freeReg( hc08_reg_a);
5353 emitBranch ("bne", tlbl);
5357 genIfxJump (ifx, "a");
5363 if (AOP_TYPE (right) == AOP_LIT)
5364 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5366 size = AOP_SIZE (result);
5370 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5371 accopWithAop ("eor", AOP (right), offset);
5372 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5373 hc08_freeReg( hc08_reg_a);
5377 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5378 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5379 freeAsmop (result, NULL, ic, TRUE);
5383 emitinline (iCode * ic, char *inlin)
5389 symbol *sym, *tempsym;
5398 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5402 //printf("Found possible symbol '%s'\n",symname);
5403 tempsym = newSymbol (symname, ic->level);
5404 tempsym->block = ic->block;
5405 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5414 aop = aopForSym (ic, sym, FALSE);
5415 l = aopAdrStr (aop, aop->size - 1, TRUE);
5419 if (sym->level && !sym->allocreq && !sym->ismyparm)
5421 werror (E_ID_UNDEF, sym->name);
5423 " Add 'volatile' to the variable declaration so that it\n"
5424 " can be referenced within inline assembly");
5426 //printf("Replacing with '%s'\n",l);
5430 if ((2+bp-buffer)>sizeof(buffer))
5439 if ((2+bp-buffer)>sizeof(buffer))
5446 if ((2+bp-buffer)>sizeof(buffer))
5447 fprintf(stderr, "Inline assembly buffer overflow\n");
5449 //printf("%s\n",buffer);
5450 emitcode (buffer,"");
5454 /*-----------------------------------------------------------------*/
5455 /* genInline - write the inline code out */
5456 /*-----------------------------------------------------------------*/
5458 genInline (iCode * ic)
5460 char *buffer, *bp, *bp1;
5462 D(emitcode ("; genInline",""));
5464 _G.inLine += (!options.asmpeep);
5466 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5467 strcpy (buffer, IC_INLINE (ic));
5469 /* emit each line as a code */
5475 /* emitcode (bp1, ""); */
5476 emitinline (ic, bp1);
5495 /* emitcode (bp1, ""); */
5496 emitinline (ic, bp1);
5498 /* emitcode("",buffer); */
5499 _G.inLine -= (!options.asmpeep);
5502 /*-----------------------------------------------------------------*/
5503 /* genRRC - rotate right with carry */
5504 /*-----------------------------------------------------------------*/
5508 operand *left, *result;
5509 int size, offset = 0;
5510 bool needpula = FALSE;
5511 bool resultInA = FALSE;
5514 D(emitcode ("; genRRC",""));
5516 /* rotate right with carry */
5517 left = IC_LEFT (ic);
5518 result = IC_RESULT (ic);
5519 aopOp (left, ic, FALSE);
5520 aopOp (result, ic, FALSE);
5522 if ((AOP_TYPE (result) == AOP_REG)
5523 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5526 size = AOP_SIZE (result);
5530 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5534 rmwWithAop (shift, AOP (result), offset--);
5542 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5543 rmwWithReg (shift, hc08_reg_a);
5544 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5545 hc08_freeReg (hc08_reg_a);
5550 if ((!hc08_reg_a->isFree) || resultInA)
5552 pushReg (hc08_reg_a, TRUE);
5556 /* now we need to put the carry into the
5557 highest order byte of the result */
5558 offset = AOP_SIZE (result) - 1;
5559 emitcode ("clra","");
5560 emitcode ("rora","");
5561 hc08_dirtyReg (hc08_reg_a, FALSE);
5564 emitcode ("ora", "1,s");
5565 emitcode ("ais", "#1");
5566 hc08_dirtyReg (hc08_reg_a, FALSE);
5570 accopWithAop ("ora", AOP (result), offset);
5571 storeRegToAop (hc08_reg_a, AOP (result), offset);
5573 pullOrFreeReg (hc08_reg_a, needpula);
5575 freeAsmop (left, NULL, ic, TRUE);
5576 freeAsmop (result, NULL, ic, TRUE);
5579 /*-----------------------------------------------------------------*/
5580 /* genRLC - generate code for rotate left with carry */
5581 /*-----------------------------------------------------------------*/
5585 operand *left, *result;
5586 int size, offset = 0;
5588 bool resultInA = FALSE;
5589 bool needpula = FALSE;
5591 D(emitcode ("; genRLC",""));
5593 /* rotate right with carry */
5594 left = IC_LEFT (ic);
5595 result = IC_RESULT (ic);
5596 aopOp (left, ic, FALSE);
5597 aopOp (result, ic, FALSE);
5599 if ((AOP_TYPE (result) == AOP_REG)
5600 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5603 size = AOP_SIZE (result);
5607 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5611 rmwWithAop (shift, AOP (result), offset--);
5619 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5620 rmwWithReg (shift, hc08_reg_a);
5621 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5622 hc08_freeReg (hc08_reg_a);
5627 if ((!hc08_reg_a->isFree) || resultInA)
5629 pushReg (hc08_reg_a, TRUE);
5633 /* now we need to put the carry into the
5634 lowest order byte of the result */
5636 emitcode ("clra","");
5637 emitcode ("rola","");
5638 hc08_dirtyReg (hc08_reg_a, FALSE);
5641 emitcode ("ora", "1,s");
5642 emitcode ("ais", "#1");
5643 hc08_dirtyReg (hc08_reg_a, FALSE);
5647 accopWithAop ("ora", AOP (result), offset);
5648 storeRegToAop (hc08_reg_a, AOP (result), offset);
5650 pullOrFreeReg (hc08_reg_a, needpula);
5652 freeAsmop (left, NULL, ic, TRUE);
5653 freeAsmop (result, NULL, ic, TRUE);
5656 /*-----------------------------------------------------------------*/
5657 /* genGetHbit - generates code get highest order bit */
5658 /*-----------------------------------------------------------------*/
5660 genGetHbit (iCode * ic)
5662 operand *left, *result;
5664 D(emitcode ("; genGetHbit",""));
5666 left = IC_LEFT (ic);
5667 result = IC_RESULT (ic);
5668 aopOp (left, ic, FALSE);
5669 aopOp (result, ic, FALSE);
5671 /* get the highest order byte into a */
5672 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5673 emitcode ("rola", "");
5674 emitcode ("clra", "");
5675 emitcode ("rola", "");
5676 hc08_dirtyReg (hc08_reg_a, FALSE);
5677 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5678 hc08_freeReg (hc08_reg_a);
5680 freeAsmop (left, NULL, ic, TRUE);
5681 freeAsmop (result, NULL, ic, TRUE);
5684 /*-----------------------------------------------------------------*/
5685 /* genSwap - generates code to swap nibbles or bytes */
5686 /*-----------------------------------------------------------------*/
5688 genSwap (iCode * ic)
5690 operand *left, *result;
5692 D(emitcode ("; genSwap",""));
5694 left = IC_LEFT (ic);
5695 result = IC_RESULT (ic);
5696 aopOp (left, ic, FALSE);
5697 aopOp (result, ic, FALSE);
5699 switch (AOP_SIZE (left))
5701 case 1: /* swap nibbles in byte */
5702 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5703 emitcode ("nsa", "");
5704 hc08_dirtyReg (hc08_reg_a, FALSE);
5705 storeRegToAop (hc08_reg_a, AOP (result), 0);
5706 hc08_freeReg (hc08_reg_a);
5708 case 2: /* swap bytes in a word */
5709 if (operandsEqu (left, result))
5711 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5712 hc08_useReg (hc08_reg_a);
5713 transferAopAop (AOP (left), 1, AOP (result), 0);
5714 storeRegToAop (hc08_reg_a, AOP (result), 1);
5715 hc08_freeReg (hc08_reg_a);
5719 transferAopAop (AOP (left), 0, AOP (result), 1);
5720 transferAopAop (AOP (left), 1, AOP (result), 0);
5724 wassertl(FALSE, "unsupported SWAP operand size");
5727 freeAsmop (left, NULL, ic, TRUE);
5728 freeAsmop (result, NULL, ic, TRUE);
5732 /*-----------------------------------------------------------------*/
5733 /* AccRol - rotate left accumulator by known count */
5734 /*-----------------------------------------------------------------*/
5736 AccRol (int shCount)
5738 shCount &= 0x0007; // shCount : 0..7
5745 emitcode ("rola", ""); /* 1 cycle */
5748 emitcode ("rola", ""); /* 1 cycle */
5749 emitcode ("rola", ""); /* 1 cycle */
5752 emitcode ("nsa", "");
5753 emitcode ("rora", "");
5756 emitcode ("nsa", ""); /* 3 cycles */
5759 emitcode ("nsa", ""); /* 3 cycles */
5760 emitcode ("rola", ""); /* 1 cycle */
5763 emitcode ("nsa", ""); /* 3 cycles */
5764 emitcode ("rola", ""); /* 1 cycle */
5765 emitcode ("rola", ""); /* 1 cycle */
5768 emitcode ("nsa", ""); /* 3 cycles */
5769 emitcode ("rola", ""); /* 1 cycle */
5770 emitcode ("rola", ""); /* 1 cycle */
5771 emitcode ("rola", ""); /* 1 cycle */
5778 /*-----------------------------------------------------------------*/
5779 /* AccLsh - left shift accumulator by known count */
5780 /*-----------------------------------------------------------------*/
5782 AccLsh (int shCount)
5786 shCount &= 0x0007; // shCount : 0..7
5788 /* Shift counts of 4 and 5 are currently optimized for code size. */
5789 /* Falling through to the unrolled loop would be optimal for code speed. */
5790 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5794 if (optimize.codeSpeed)
5796 accopWithMisc ("nsa", "");
5797 accopWithMisc ("and", "#0xf0");
5798 /* total: 5 cycles, 3 bytes */
5801 if (optimize.codeSpeed)
5803 accopWithMisc ("nsa", "");
5804 accopWithMisc ("and", "#0xf0");
5805 accopWithMisc ("lsla", "");
5806 /* total: 6 cycles, 4 bytes */
5809 accopWithMisc ("rora", "");
5810 accopWithMisc ("rora", "");
5811 accopWithMisc ("rora", "");
5812 accopWithMisc ("and", "#0xc0");
5813 /* total: 5 cycles, 5 bytes */
5816 accopWithMisc ("rora", "");
5817 accopWithMisc ("clra", "");
5818 accopWithMisc ("rora", "");
5819 /* total: 3 cycles, 3 bytes */
5823 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5824 /* the fastest (shCount<6) and shortest (shCount<4). */
5825 for (i=0;i<shCount;i++)
5826 accopWithMisc ("lsla", "");
5830 /*-----------------------------------------------------------------*/
5831 /* AccSRsh - signed right shift accumulator by known count */
5832 /*-----------------------------------------------------------------*/
5834 AccSRsh (int shCount)
5838 shCount &= 0x0007; // shCount : 0..7
5842 accopWithMisc ("rola", "");
5843 accopWithMisc ("clra", "");
5844 accopWithMisc ("sbc", zero);
5845 /* total: 4 cycles, 4 bytes */
5849 for (i=0;i<shCount;i++)
5850 accopWithMisc ("asra", "");
5853 /*-----------------------------------------------------------------*/
5854 /* AccRsh - right shift accumulator by known count */
5855 /*-----------------------------------------------------------------*/
5857 AccRsh (int shCount, bool sign)
5867 shCount &= 0x0007; // shCount : 0..7
5869 /* Shift counts of 4 and 5 are currently optimized for code size. */
5870 /* Falling through to the unrolled loop would be optimal for code speed. */
5871 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5875 if (optimize.codeSpeed)
5877 accopWithMisc ("nsa", "");
5878 accopWithMisc ("and", "#0x0f");
5879 /* total: 5 cycles, 3 bytes */
5882 if (optimize.codeSpeed)
5884 accopWithMisc ("nsa", "");
5885 accopWithMisc ("and", "#0x0f");
5886 accopWithMisc ("lsra", "");
5887 /* total: 6 cycles, 4 bytes */
5890 accopWithMisc ("rola", "");
5891 accopWithMisc ("rola", "");
5892 accopWithMisc ("rola", "");
5893 accopWithMisc ("and", "#0x03");
5894 /* total: 5 cycles, 5 bytes */
5897 accopWithMisc ("rola", "");
5898 accopWithMisc ("clra", "");
5899 accopWithMisc ("rola", "");
5900 /* total: 3 cycles, 3 bytes */
5904 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5905 /* the fastest (shCount<6) and shortest (shCount<4). */
5906 for (i=0;i<shCount;i++)
5907 accopWithMisc ("lsra", "");
5911 /*-----------------------------------------------------------------*/
5912 /* XAccLsh - left shift register pair XA by known count */
5913 /*-----------------------------------------------------------------*/
5915 XAccLsh (int shCount)
5919 shCount &= 0x000f; // shCount : 0..15
5924 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5925 loadRegFromConst (hc08_reg_a, zero);
5929 /* if we can beat 2n cycles or bytes for some special case, do it here */
5933 /* bytes cycles reg x reg a carry
5934 ** abcd efgh ijkl mnop ?
5935 ** lsrx 1 1 0abc defg ijkl mnop h
5936 ** rora 1 1 0abc defg hijk lmno p
5937 ** tax 1 1 hijk lmno hijk lmno p
5938 ** clra 1 1 hijk lmno 0000 0000 p
5939 ** rora 1 1 hijk lmno p000 0000 0
5940 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5942 rmwWithReg ("lsr", hc08_reg_x);
5943 rmwWithReg ("ror", hc08_reg_a);
5944 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5945 loadRegFromConst (hc08_reg_a, zero);
5946 rmwWithReg ("ror", hc08_reg_a);
5953 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5954 /* the fastest and shortest. */
5955 for (i=0;i<shCount;i++)
5957 rmwWithReg ("lsl", hc08_reg_a);
5958 rmwWithReg ("rol", hc08_reg_x);
5962 /*-----------------------------------------------------------------*/
5963 /* XAccSRsh - signed right shift register pair XA by known count */
5964 /*-----------------------------------------------------------------*/
5966 XAccSRsh (int shCount)
5970 shCount &= 0x000f; // shCount : 0..7
5972 /* if we can beat 2n cycles or bytes for some special case, do it here */
5976 /* bytes cycles reg x reg a carry
5977 ** abcd efgh ijkl mnop ?
5978 ** lslx 1 1 bcde fgh0 ijkl mnop a
5979 ** clra 1 1 bcde fgh0 0000 0000 a
5980 ** rola 1 1 bcde fgh0 0000 000a 0
5981 ** nega 1 1 bcde fgh0 aaaa aaaa a
5982 ** tax 1 1 aaaa aaaa aaaa aaaa a
5983 ** total: 5 cycles, 5 bytes
5985 rmwWithReg ("lsl", hc08_reg_x);
5986 loadRegFromConst (hc08_reg_a, zero);
5987 rmwWithReg ("rol", hc08_reg_a);
5988 rmwWithReg ("neg", hc08_reg_a);
5989 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5999 /* bytes cycles reg x reg a carry
6000 ** abcd efgh ijkl mnop ?
6001 ** txa 1 1 abcd efgh abcd efgh ?
6002 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
6003 ** lsla 1 1 abcd efgh ???? ???? a
6004 ** clrx 1 1 0000 0000 ???? ???? a
6005 ** rolx 1 1 0000 000a ???? ???? 0
6006 ** negx 1 1 aaaa aaaa ???? ???? a
6007 ** rora 1 1 aaaa aaaa LSBresult 0
6008 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
6010 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6011 AccSRsh (shCount-8);
6012 rmwWithReg ("lsl", hc08_reg_a);
6013 loadRegFromConst (hc08_reg_x, zero);
6014 rmwWithReg ("rol", hc08_reg_x);
6015 rmwWithReg ("neg", hc08_reg_x);
6016 rmwWithReg ("ror", hc08_reg_a);
6023 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6024 /* the fastest and shortest. */
6025 for (i=0;i<shCount;i++)
6027 rmwWithReg ("asr", hc08_reg_x);
6028 rmwWithReg ("ror", hc08_reg_a);
6032 /*-----------------------------------------------------------------*/
6033 /* XAccRsh - right shift register pair XA by known count */
6034 /*-----------------------------------------------------------------*/
6036 XAccRsh (int shCount, bool sign)
6046 shCount &= 0x000f; // shCount : 0..f
6048 /* if we can beat 2n cycles or bytes for some special case, do it here */
6052 /* bytes cycles reg x reg a carry
6053 ** abcd efgh ijkl mnop ?
6054 ** clra 1 1 abcd efgh 0000 0000 a
6055 ** lslx 1 1 bcde fgh0 0000 0000 a
6056 ** rola 1 1 bcde fgh0 0000 000a 0
6057 ** clrx 1 1 0000 0000 0000 000a 0
6058 ** total: 4 cycles, 4 bytes
6060 loadRegFromConst (hc08_reg_x, zero);
6061 rmwWithReg ("lsl", hc08_reg_x);
6062 rmwWithReg ("rol", hc08_reg_a);
6063 loadRegFromConst (hc08_reg_a, zero);
6067 /* bytes cycles reg x reg a carry
6068 ** abcd efgh ijkl mnop ?
6069 ** clra 1 1 abcd efgh 0000 0000 a
6070 ** lslx 1 1 bcde fgh0 0000 0000 a
6071 ** rola 1 1 bcde fgh0 0000 000a 0
6072 ** lslx 1 1 cdef gh00 0000 000a b
6073 ** rola 1 1 cdef gh00 0000 00ab 0
6074 ** clrx 1 1 0000 0000 0000 00ab 0
6075 ** total: 6 cycles, 6 bytes
6077 loadRegFromConst (hc08_reg_x, zero);
6078 rmwWithReg ("lsl", hc08_reg_x);
6079 rmwWithReg ("rol", hc08_reg_a);
6080 rmwWithReg ("lsl", hc08_reg_x);
6081 rmwWithReg ("rol", hc08_reg_a);
6082 loadRegFromConst (hc08_reg_a, zero);
6091 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6092 AccRsh (shCount-8, FALSE);
6093 loadRegFromConst (hc08_reg_x, zero);
6097 /* bytes cycles reg x reg a carry
6098 ** abcd efgh ijkl mnop ?
6099 ** lsla 1 1 abcd efgh jklm nop0 i
6100 ** txa 1 1 abcd efgh abcd efgh i
6101 ** rola 1 1 abcd efgh bcde fghi a
6102 ** clrx 1 1 0000 0000 bcde fghi a
6103 ** rolx 1 1 0000 000a bcde fghi 0
6104 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6106 rmwWithReg ("lsl", hc08_reg_a);
6107 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6108 rmwWithReg ("rol", hc08_reg_a);
6109 loadRegFromConst (hc08_reg_x, zero);
6110 rmwWithReg ("rol", hc08_reg_x);
6113 /* bytes cycles reg x reg a carry
6114 ** abcd efgh ijkl mnop ?
6115 ** lsla 1 1 abcd efgh jklm nop0 i
6116 ** rolx 1 1 bcde fghi jklm nop0 a
6117 ** rola 1 1 bcde fghi klmn op0a j
6118 ** rolx 1 1 cdef ghij klmn op0a b
6119 ** rola 1 1 cdef ghij lmno p0ab k
6120 ** and #3 2 2 cdef ghij 0000 00ab k
6121 ** psha 1 2 cdef ghij 0000 00ab k
6122 ** txa 1 1 cdef ghij cdef ghij k
6123 ** pula 1 2 0000 00ab cdef ghij k
6124 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6130 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6131 /* the fastest and shortest. */
6132 for (i=0;i<shCount;i++)
6134 rmwWithReg ("lsr", hc08_reg_x);
6135 rmwWithReg ("ror", hc08_reg_a);
6142 /*-----------------------------------------------------------------*/
6143 /* shiftR1Left2Result - shift right one byte from left to result */
6144 /*-----------------------------------------------------------------*/
6146 shiftR1Left2Result (operand * left, int offl,
6147 operand * result, int offr,
6148 int shCount, int sign)
6150 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6151 /* shift right accumulator */
6152 AccRsh (shCount, sign);
6153 storeRegToAop (hc08_reg_a, AOP (result), offr);
6157 /*-----------------------------------------------------------------*/
6158 /* shiftL1Left2Result - shift left one byte from left to result */
6159 /*-----------------------------------------------------------------*/
6161 shiftL1Left2Result (operand * left, int offl,
6162 operand * result, int offr, int shCount)
6164 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6165 /* shift left accumulator */
6167 storeRegToAop (hc08_reg_a, AOP (result), offr);
6170 /*-----------------------------------------------------------------*/
6171 /* movLeft2Result - move byte from left to result */
6172 /*-----------------------------------------------------------------*/
6174 movLeft2Result (operand * left, int offl,
6175 operand * result, int offr, int sign)
6177 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6179 transferAopAop (AOP (left), offl, AOP (result), offr);
6184 /*-----------------------------------------------------------------*/
6185 /* shiftL2Left2Result - shift left two bytes from left to result */
6186 /*-----------------------------------------------------------------*/
6188 shiftL2Left2Result (operand * left, int offl,
6189 operand * result, int offr, int shCount)
6192 bool needpula = FALSE;
6193 bool needpulx = FALSE;
6195 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6196 needpula = pushRegIfUsed (hc08_reg_a);
6199 if (!IS_AOP_XA (AOP (left)))
6200 needpulx = pushRegIfUsed (hc08_reg_x);
6204 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6209 rmwWithReg ("lsr", hc08_reg_x);
6210 rmwWithReg ("ror", hc08_reg_a);
6211 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6212 rmwWithReg ("clr", hc08_reg_a);
6213 rmwWithReg ("ror", hc08_reg_a);
6216 for (i=0; i<shCount; i++)
6218 rmwWithReg ("lsl", hc08_reg_a);
6219 rmwWithReg ("rol", hc08_reg_x);
6222 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6224 pullOrFreeReg (hc08_reg_x, needpulx);
6225 pullOrFreeReg (hc08_reg_a, needpula);
6231 /*-----------------------------------------------------------------*/
6232 /* shiftR2Left2Result - shift right two bytes from left to result */
6233 /*-----------------------------------------------------------------*/
6235 shiftR2Left2Result (operand * left, int offl,
6236 operand * result, int offr,
6237 int shCount, int sign)
6240 bool needpula = FALSE;
6241 bool needpulx = FALSE;
6243 needpula = pushRegIfUsed (hc08_reg_a);
6244 needpulx = pushRegIfUsed (hc08_reg_x);
6246 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6247 for (i=0; i<shCount; i++)
6250 rmwWithReg ("asr", hc08_reg_x);
6252 rmwWithReg ("lsr", hc08_reg_x);
6253 rmwWithReg ("ror", hc08_reg_a);
6255 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6257 pullOrFreeReg (hc08_reg_x, needpulx);
6258 pullOrFreeReg (hc08_reg_a, needpula);
6263 /*-----------------------------------------------------------------*/
6264 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6265 /*-----------------------------------------------------------------*/
6267 shiftLLeftOrResult (operand * left, int offl,
6268 operand * result, int offr, int shCount)
6270 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6271 /* shift left accumulator */
6273 /* or with result */
6274 accopWithAop ("ora", AOP (result), offr);
6275 /* back to result */
6276 storeRegToAop (hc08_reg_a, AOP (result), offr);
6277 hc08_freeReg (hc08_reg_a);
6281 /*-----------------------------------------------------------------*/
6282 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6283 /*-----------------------------------------------------------------*/
6285 shiftRLeftOrResult (operand * left, int offl,
6286 operand * result, int offr, int shCount)
6288 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6289 /* shift left accumulator */
6290 AccRsh (shCount, FALSE);
6291 /* or with result */
6292 accopWithAop ("ora", AOP (result), offr);
6293 /* back to result */
6294 storeRegToAop (hc08_reg_a, AOP (result), offr);
6295 hc08_freeReg (hc08_reg_a);
6298 /*-----------------------------------------------------------------*/
6299 /* genlshOne - left shift a one byte quantity by known count */
6300 /*-----------------------------------------------------------------*/
6302 genlshOne (operand * result, operand * left, int shCount)
6304 D(emitcode ("; genlshOne",""));
6306 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6309 /*-----------------------------------------------------------------*/
6310 /* genlshTwo - left shift two bytes by known amount != 0 */
6311 /*-----------------------------------------------------------------*/
6313 genlshTwo (operand * result, operand * left, int shCount)
6317 D(emitcode ("; genlshTwo",""));
6320 size = getDataSize (result);
6322 /* if shCount >= 8 */
6329 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6331 storeRegToAop (hc08_reg_a, AOP (result), 1);
6333 storeConstToAop(zero, AOP (result), LSB);
6336 /* 1 <= shCount <= 7 */
6339 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6341 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6345 /*-----------------------------------------------------------------*/
6346 /* shiftLLong - shift left one long from left to result */
6347 /* offr = LSB or MSB16 */
6348 /*-----------------------------------------------------------------*/
6350 shiftLLong (operand * left, operand * result, int offr)
6353 // int size = AOP_SIZE (result);
6355 bool needpula = FALSE;
6356 bool needpulx = FALSE;
6358 needpula = pushRegIfUsed (hc08_reg_a);
6359 needpulx = pushRegIfUsed (hc08_reg_x);
6361 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6362 rmwWithReg ("lsl", hc08_reg_a);
6363 rmwWithReg ("rol", hc08_reg_x);
6367 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6368 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6369 rmwWithReg ("rol", hc08_reg_a);
6370 rmwWithReg ("rol", hc08_reg_x);
6371 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6373 else if (offr==MSB16)
6375 storeRegToAop (hc08_reg_a, AOP (result), offr);
6376 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6377 storeRegToAop (hc08_reg_x, AOP (result), offr+1);
6378 rmwWithReg ("rol", hc08_reg_a);
6379 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6380 storeConstToAop (zero, AOP (result), 0);
6383 pullOrFreeReg (hc08_reg_x, needpulx);
6384 pullOrFreeReg (hc08_reg_a, needpula);
6387 /*-----------------------------------------------------------------*/
6388 /* genlshFour - shift four byte by a known amount != 0 */
6389 /*-----------------------------------------------------------------*/
6391 genlshFour (operand * result, operand * left, int shCount)
6395 D(emitcode ("; genlshFour",""));
6397 size = AOP_SIZE (result);
6399 /* TODO: deal with the &result == &left case */
6401 /* if shifting more that 3 bytes */
6406 /* lowest order of left goes to the highest
6407 order of the destination */
6408 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6410 movLeft2Result (left, LSB, result, MSB32, 0);
6411 storeConstToAop (zero, AOP (result), LSB);
6412 storeConstToAop (zero, AOP (result), MSB16);
6413 storeConstToAop (zero, AOP (result), MSB24);
6417 /* more than two bytes */
6418 else if (shCount >= 16)
6420 /* lower order two bytes goes to higher order two bytes */
6422 /* if some more remaining */
6424 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6427 movLeft2Result (left, MSB16, result, MSB32, 0);
6428 movLeft2Result (left, LSB, result, MSB24, 0);
6430 storeConstToAop (zero, AOP (result), LSB);
6431 storeConstToAop (zero, AOP (result), MSB16);
6435 /* if more than 1 byte */
6436 else if (shCount >= 8)
6438 /* lower order three bytes goes to higher order three bytes */
6443 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6445 movLeft2Result (left, LSB, result, MSB16, 0);
6451 movLeft2Result (left, MSB24, result, MSB32, 0);
6452 movLeft2Result (left, MSB16, result, MSB24, 0);
6453 movLeft2Result (left, LSB, result, MSB16, 0);
6454 storeConstToAop (zero, AOP (result), LSB);
6456 else if (shCount == 1)
6457 shiftLLong (left, result, MSB16);
6460 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6461 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6462 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6463 storeConstToAop (zero, AOP (result), LSB);
6468 /* 1 <= shCount <= 7 */
6469 else if (shCount <= 2)
6471 shiftLLong (left, result, LSB);
6473 shiftLLong (result, result, LSB);
6475 /* 3 <= shCount <= 7, optimize */
6478 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6479 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6480 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6484 /*-----------------------------------------------------------------*/
6485 /* genLeftShiftLiteral - left shifting by known count */
6486 /*-----------------------------------------------------------------*/
6488 genLeftShiftLiteral (operand * left,
6493 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6496 D(emitcode ("; genLeftShiftLiteral",""));
6498 freeAsmop (right, NULL, ic, TRUE);
6500 aopOp (left, ic, FALSE);
6501 aopOp (result, ic, FALSE);
6503 // size = getSize (operandType (result));
6504 size = AOP_SIZE (result);
6507 DD(emitcode ("; shift left ", "result %d, left %d", size,
6514 transferAopAop( AOP(left), size, AOP(result), size);
6516 else if (shCount >= (size * 8))
6519 storeConstToAop (zero, AOP (result), size);
6526 genlshOne (result, left, shCount);
6530 genlshTwo (result, left, shCount);
6534 genlshFour (result, left, shCount);
6537 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6538 "*** ack! mystery literal shift!\n");
6542 freeAsmop (left, NULL, ic, TRUE);
6543 freeAsmop (result, NULL, ic, TRUE);
6546 /*-----------------------------------------------------------------*/
6547 /* genLeftShift - generates code for left shifting */
6548 /*-----------------------------------------------------------------*/
6550 genLeftShift (iCode * ic)
6552 operand *left, *right, *result;
6554 symbol *tlbl, *tlbl1;
6558 D(emitcode ("; genLeftShift",""));
6560 right = IC_RIGHT (ic);
6561 left = IC_LEFT (ic);
6562 result = IC_RESULT (ic);
6564 aopOp (right, ic, FALSE);
6566 /* if the shift count is known then do it
6567 as efficiently as possible */
6568 if (AOP_TYPE (right) == AOP_LIT)
6570 genLeftShiftLiteral (left, right, result, ic);
6574 /* shift count is unknown then we have to form
6575 a loop get the loop count in X : Note: we take
6576 only the lower order byte since shifting
6577 more that 32 bits make no sense anyway, ( the
6578 largest size of an object can be only 32 bits ) */
6580 aopOp (result, ic, FALSE);
6581 aopOp (left, ic, FALSE);
6582 aopResult = AOP (result);
6584 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6585 || isOperandVolatile (result, FALSE))
6586 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6588 /* now move the left to the result if they are not the
6590 if (!sameRegs (AOP (left), aopResult))
6592 size = AOP_SIZE (result);
6596 transferAopAop (AOP (left), offset, aopResult, offset);
6600 freeAsmop (left, NULL, ic, TRUE);
6601 AOP (result) = aopResult;
6603 tlbl = newiTempLabel (NULL);
6604 size = AOP_SIZE (result);
6606 tlbl1 = newiTempLabel (NULL);
6608 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6609 emitcode ("tstx", "");
6610 emitBranch ("beq", tlbl1);
6614 for (offset=0;offset<size;offset++)
6616 rmwWithAop (shift, AOP (result), offset);
6619 rmwWithReg ("dec", hc08_reg_x);
6620 emitBranch ("bne", tlbl);
6622 hc08_freeReg (hc08_reg_x);
6624 freeAsmop (result, NULL, ic, TRUE);
6625 freeAsmop (right, NULL, ic, TRUE);
6628 /*-----------------------------------------------------------------*/
6629 /* genrshOne - right shift a one byte quantity by known count */
6630 /*-----------------------------------------------------------------*/
6632 genrshOne (operand * result, operand * left,
6633 int shCount, int sign)
6635 D(emitcode ("; genrshOne",""));
6637 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6638 AccRsh (shCount, sign);
6639 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6642 /*-----------------------------------------------------------------*/
6643 /* genrshTwo - right shift two bytes by known amount != 0 */
6644 /*-----------------------------------------------------------------*/
6646 genrshTwo (operand * result, operand * left,
6647 int shCount, int sign)
6649 D(emitcode ("; genrshTwo",""));
6651 /* if shCount >= 8 */
6654 if (shCount || sign)
6656 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6657 AccRsh (shCount-8, sign);
6658 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6662 transferAopAop (AOP (left), 1, AOP (result), 0);
6663 storeConstToAop (zero, AOP (result), 1);
6667 /* 1 <= shCount <= 7 */
6670 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6671 XAccRsh (shCount, sign);
6672 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6676 /*-----------------------------------------------------------------*/
6677 /* shiftRLong - shift right one long from left to result */
6678 /* offl = LSB or MSB16 */
6679 /*-----------------------------------------------------------------*/
6681 shiftRLong (operand * left, int offl,
6682 operand * result, int sign)
6685 // int size = AOP_SIZE (result);
6687 bool needpula = FALSE;
6688 bool needpulx = FALSE;
6690 needpula = pushRegIfUsed (hc08_reg_a);
6691 needpulx = pushRegIfUsed (hc08_reg_x);
6695 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6697 rmwWithReg ("asr", hc08_reg_x);
6699 rmwWithReg ("lsr", hc08_reg_x);
6700 rmwWithReg ("ror", hc08_reg_a);
6701 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6702 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6704 else if (offl==MSB16)
6706 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6708 rmwWithReg ("asr", hc08_reg_a);
6710 rmwWithReg ("lsr", hc08_reg_a);
6711 loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
6712 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6713 loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
6716 rmwWithReg ("ror", hc08_reg_x);
6717 rmwWithReg ("ror", hc08_reg_a);
6718 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6724 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6725 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6729 storeConstToAop (zero, AOP (result), MSB32);
6733 pullOrFreeReg (hc08_reg_x, needpulx);
6734 pullOrFreeReg (hc08_reg_a, needpula);
6737 /*-----------------------------------------------------------------*/
6738 /* genrshFour - shift four byte by a known amount != 0 */
6739 /*-----------------------------------------------------------------*/
6741 genrshFour (operand * result, operand * left,
6742 int shCount, int sign)
6744 /* TODO: handle cases where left == result */
6746 D(emitcode ("; genrshFour",""));
6748 /* if shifting more that 3 bytes */
6751 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6752 AccRsh (shCount-24, sign);
6753 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6756 else if (shCount >= 16)
6758 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6759 XAccRsh (shCount-16, sign);
6760 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6763 else if (shCount >= 8)
6766 shiftRLong (left, MSB16, result, sign);
6767 else if (shCount == 8)
6769 transferAopAop (AOP (left), 1, AOP (result), 0);
6770 transferAopAop (AOP (left), 2, AOP (result), 1);
6771 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6772 storeRegToAop (hc08_reg_a, AOP (result), 2);
6773 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6775 else if (shCount == 9)
6777 shiftRLong (left, MSB16, result, sign);
6781 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6782 XAccRsh (shCount-8, FALSE);
6783 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6784 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6785 loadRegFromConst (hc08_reg_a, zero);
6786 XAccRsh (shCount-8, sign);
6787 accopWithAop ("ora", AOP (result), 1);
6788 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6789 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6793 { /* 1 <= shCount <= 7 */
6796 shiftRLong (left, LSB, result, sign);
6800 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6801 XAccRsh (shCount, FALSE);
6802 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6803 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6805 accopWithAop ("ora", AOP (result), 1);
6806 storeRegToAop (hc08_reg_a, AOP (result), 1);
6807 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6808 XAccRsh (shCount, sign);
6809 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6814 /*-----------------------------------------------------------------*/
6815 /* genRightShiftLiteral - right shifting by known count */
6816 /*-----------------------------------------------------------------*/
6818 genRightShiftLiteral (operand * left,
6824 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6827 D(emitcode ("; genRightShiftLiteral",""));
6829 freeAsmop (right, NULL, ic, TRUE);
6831 aopOp (left, ic, FALSE);
6832 aopOp (result, ic, FALSE);
6835 DD(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6839 size = getDataSize (left);
6840 /* test the LEFT size !!! */
6842 /* I suppose that the left size >= result size */
6845 size = getDataSize (result);
6847 transferAopAop (AOP (left), size, AOP(result), size);
6849 else if (shCount >= (size * 8))
6852 /* get sign in acc.7 */
6853 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6855 addSign (result, LSB, sign);
6862 genrshOne (result, left, shCount, sign);
6866 genrshTwo (result, left, shCount, sign);
6870 genrshFour (result, left, shCount, sign);
6876 freeAsmop (left, NULL, ic, TRUE);
6877 freeAsmop (result, NULL, ic, TRUE);
6881 /*-----------------------------------------------------------------*/
6882 /* genRightShift - generate code for right shifting */
6883 /*-----------------------------------------------------------------*/
6885 genRightShift (iCode * ic)
6887 operand *right, *left, *result;
6890 symbol *tlbl, *tlbl1;
6895 D(emitcode ("; genRightShift",""));
6897 /* if signed then we do it the hard way preserve the
6898 sign bit moving it inwards */
6899 retype = getSpec (operandType (IC_RESULT (ic)));
6900 sign = !SPEC_USIGN (retype);
6902 /* signed & unsigned types are treated the same : i.e. the
6903 signed is NOT propagated inwards : quoting from the
6904 ANSI - standard : "for E1 >> E2, is equivalent to division
6905 by 2**E2 if unsigned or if it has a non-negative value,
6906 otherwise the result is implementation defined ", MY definition
6907 is that the sign does not get propagated */
6909 right = IC_RIGHT (ic);
6910 left = IC_LEFT (ic);
6911 result = IC_RESULT (ic);
6913 aopOp (right, ic, FALSE);
6915 /* if the shift count is known then do it
6916 as efficiently as possible */
6917 if (AOP_TYPE (right) == AOP_LIT)
6919 genRightShiftLiteral (left, right, result, ic, sign);
6923 /* shift count is unknown then we have to form
6924 a loop get the loop count in X : Note: we take
6925 only the lower order byte since shifting
6926 more that 32 bits make no sense anyway, ( the
6927 largest size of an object can be only 32 bits ) */
6929 aopOp (result, ic, FALSE);
6930 aopOp (left, ic, FALSE);
6931 aopResult = AOP (result);
6933 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6934 || isOperandVolatile (result, FALSE))
6935 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6937 /* now move the left to the result if they are not the
6939 if (!sameRegs (AOP (left), aopResult))
6941 size = AOP_SIZE (result);
6945 transferAopAop (AOP (left), offset, aopResult, offset);
6949 freeAsmop (left, NULL, ic, TRUE);
6950 AOP (result) = aopResult;
6952 tlbl = newiTempLabel (NULL);
6953 size = AOP_SIZE (result);
6955 tlbl1 = newiTempLabel (NULL);
6957 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6958 emitcode ("tstx", "");
6959 emitBranch ("beq", tlbl1);
6962 shift= sign ? "asr" : "lsr";
6963 for (offset=size-1;offset>=0;offset--)
6965 rmwWithAop (shift, AOP (result), offset);
6968 rmwWithReg ("dec", hc08_reg_x);
6969 emitBranch ("bne", tlbl);
6971 hc08_freeReg (hc08_reg_x);
6973 freeAsmop (result, NULL, ic, TRUE);
6974 freeAsmop (right, NULL, ic, TRUE);
6978 /*-----------------------------------------------------------------*/
6979 /* genUnpackBits - generates code for unpacking bits */
6980 /*-----------------------------------------------------------------*/
6982 genUnpackBits (operand * result, iCode *ifx)
6984 int offset = 0; /* result byte offset */
6985 int rsize; /* result size */
6986 int rlen = 0; /* remaining bitfield length */
6987 sym_link *etype; /* bitfield type information */
6988 int blen; /* bitfield length */
6989 int bstr; /* bitfield starting bit within byte */
6991 D(emitcode ("; genUnpackBits",""));
6993 etype = getSpec (operandType (result));
6994 rsize = getSize (operandType (result));
6995 blen = SPEC_BLEN (etype);
6996 bstr = SPEC_BSTR (etype);
6998 if (ifx && blen <= 8)
7000 emitcode ("lda", ",x");
7001 hc08_dirtyReg (hc08_reg_a, FALSE);
7004 emitcode ("and", "#0x%02x",
7005 (((unsigned char) -1) >> (8 - blen)) << bstr);
7007 genIfxJump (ifx, "a");
7012 /* If the bitfield length is less than a byte */
7015 emitcode ("lda", ",x");
7016 hc08_dirtyReg (hc08_reg_a, FALSE);
7017 AccRsh (bstr, FALSE);
7018 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7019 if (!SPEC_USIGN (etype))
7021 /* signed bitfield */
7022 symbol *tlbl = newiTempLabel (NULL);
7024 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7025 emitcode ("beq", "%05d$", tlbl->key + 100);
7026 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7029 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7033 /* Bit field did not fit in a byte. Copy all
7034 but the partial byte at the end. */
7035 for (rlen=blen;rlen>=8;rlen-=8)
7037 emitcode ("lda", ",x");
7038 hc08_dirtyReg (hc08_reg_a, FALSE);
7039 storeRegToAop (hc08_reg_a, AOP (result), offset);
7042 emitcode ("aix", "#1");
7045 /* Handle the partial byte at the end */
7048 emitcode ("lda", ",x");
7049 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7050 if (!SPEC_USIGN (etype))
7052 /* signed bitfield */
7053 symbol *tlbl = newiTempLabel (NULL);
7055 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7056 emitcode ("beq", "%05d$", tlbl->key + 100);
7057 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7060 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7067 if (SPEC_USIGN (etype))
7070 storeConstToAop (zero, AOP (result), offset++);
7074 /* signed bitfield: sign extension with 0x00 or 0xff */
7075 emitcode ("rola", "");
7076 emitcode ("clra", "");
7077 emitcode ("sbc", zero);
7080 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7086 /*-----------------------------------------------------------------*/
7087 /* genUnpackBitsImmed - generates code for unpacking bits */
7088 /*-----------------------------------------------------------------*/
7090 genUnpackBitsImmed (operand * left,
7096 int offset = 0; /* result byte offset */
7097 int rsize; /* result size */
7098 int rlen = 0; /* remaining bitfield length */
7099 sym_link *etype; /* bitfield type information */
7100 int blen; /* bitfield length */
7101 int bstr; /* bitfield starting bit within byte */
7104 D(emitcode ("; genUnpackBitsImmed",""));
7106 aopOp (result, ic, TRUE);
7107 size = AOP_SIZE (result);
7109 derefaop = aopDerefAop (AOP (left));
7110 freeAsmop (left, NULL, ic, TRUE);
7111 derefaop->size = size;
7113 etype = getSpec (operandType (result));
7114 rsize = getSize (operandType (result));
7115 blen = SPEC_BLEN (etype);
7116 bstr = SPEC_BSTR (etype);
7118 /* if the bitfield is a single bit in the direct page */
7119 if (blen == 1 && derefaop->type == AOP_DIR)
7123 symbol *tlbl = newiTempLabel (NULL);
7125 loadRegFromConst (hc08_reg_a, zero);
7126 emitcode ("brclr", "#%d,%s,%05d$",
7127 bstr, aopAdrStr (derefaop, 0, FALSE),
7129 if (SPEC_USIGN (etype))
7130 rmwWithReg ("inc", hc08_reg_a);
7132 rmwWithReg ("dec", hc08_reg_a);
7134 storeRegToAop (hc08_reg_a, AOP (result), offset);
7135 hc08_freeReg (hc08_reg_a);
7141 symbol *tlbl = newiTempLabel (NULL);
7147 jlbl = IC_TRUE (ifx);
7152 jlbl = IC_FALSE (ifx);
7155 emitcode (inst, "#%d,%s,%05d$",
7156 bstr, aopAdrStr (derefaop, 0, FALSE),
7158 emitBranch ("jmp", jlbl);
7166 /* If the bitfield length is less than a byte */
7169 loadRegFromAop (hc08_reg_a, derefaop, 0);
7172 AccRsh (bstr, FALSE);
7173 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7174 hc08_dirtyReg (hc08_reg_a, FALSE);
7175 if (!SPEC_USIGN (etype))
7177 /* signed bitfield */
7178 symbol *tlbl = newiTempLabel (NULL);
7180 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7181 emitcode ("beq", "%05d$", tlbl->key + 100);
7182 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7185 storeRegToAop (hc08_reg_a, AOP (result), offset);
7189 emitcode ("and", "#0x%02x",
7190 (((unsigned char) -1) >> (8 - blen)) << bstr);
7191 hc08_dirtyReg (hc08_reg_a, FALSE);
7197 /* Bit field did not fit in a byte. Copy all
7198 but the partial byte at the end. */
7199 for (rlen=blen;rlen>=8;rlen-=8)
7201 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7203 storeRegToAop (hc08_reg_a, AOP (result), offset);
7205 emitcode ("tsta", "");
7209 /* Handle the partial byte at the end */
7212 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7213 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7214 if (!SPEC_USIGN (etype))
7216 /* signed bitfield */
7217 symbol *tlbl = newiTempLabel (NULL);
7219 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7220 emitcode ("beq", "%05d$", tlbl->key + 100);
7221 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7224 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7231 if (SPEC_USIGN (etype))
7234 storeConstToAop (zero, AOP (result), offset++);
7238 /* signed bitfield: sign extension with 0x00 or 0xff */
7239 emitcode ("rola", "");
7240 emitcode ("clra", "");
7241 emitcode ("sbc", zero);
7244 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7248 freeAsmop (NULL, derefaop, ic, TRUE);
7249 freeAsmop (result, NULL, ic, TRUE);
7251 if (ifx && !ifx->generated)
7253 genIfxJump (ifx, "a");
7258 /*-----------------------------------------------------------------*/
7259 /* genDataPointerGet - generates code when ptr offset is known */
7260 /*-----------------------------------------------------------------*/
7262 genDataPointerGet (operand * left,
7270 D(emitcode ("; genDataPointerGet",""));
7272 aopOp (result, ic, TRUE);
7273 size = AOP_SIZE (result);
7275 derefaop = aopDerefAop (AOP (left));
7276 freeAsmop (left, NULL, ic, TRUE);
7277 derefaop->size = size;
7282 transferAopAop (derefaop, size, AOP (result), size);
7284 loadRegFromAop (hc08_reg_a, derefaop, size);
7287 freeAsmop (NULL, derefaop, ic, TRUE);
7288 freeAsmop (result, NULL, ic, TRUE);
7290 if (ifx && !ifx->generated)
7292 genIfxJump (ifx, "a");
7297 /*-----------------------------------------------------------------*/
7298 /* genPointerGet - generate code for pointer get */
7299 /*-----------------------------------------------------------------*/
7301 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7303 operand *left = IC_LEFT (ic);
7304 operand *result = IC_RESULT (ic);
7306 sym_link *retype = getSpec (operandType (result));
7308 D(emitcode ("; genPointerGet",""));
7310 if (getSize (operandType (result))>1)
7313 aopOp (left, ic, FALSE);
7315 /* if left is rematerialisable and
7316 result is not bit variable type */
7317 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7319 if (!IS_BITVAR (retype))
7321 genDataPointerGet (left, result, ic, ifx);
7326 genUnpackBitsImmed (left, result, ic, ifx);
7331 /* if the operand is already in hx
7332 then we do nothing else we move the value to hx */
7333 if (AOP_TYPE (left) != AOP_STR)
7335 /* if this is remateriazable */
7336 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7339 /* so hx now contains the address */
7340 aopOp (result, ic, FALSE);
7342 /* if bit then unpack */
7343 if (IS_BITVAR (retype))
7344 genUnpackBits (result, ifx);
7347 size = AOP_SIZE (result);
7352 accopWithMisc ("lda", ",x");
7355 emitcode ("aix", "#1");
7356 hc08_dirtyReg (hc08_reg_hx, FALSE);
7359 storeRegToAop (hc08_reg_a, AOP (result), offset);
7361 hc08_freeReg (hc08_reg_a);
7365 freeAsmop (left, NULL, ic, TRUE);
7366 freeAsmop (result, NULL, ic, TRUE);
7369 aopOp (IC_RESULT (pi), pi, FALSE);
7370 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7371 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7375 if (ifx && !ifx->generated)
7377 genIfxJump (ifx, "a");
7380 hc08_freeReg (hc08_reg_hx);
7384 /*-----------------------------------------------------------------*/
7385 /* genPackBits - generates code for packed bit storage */
7386 /*-----------------------------------------------------------------*/
7388 genPackBits (sym_link * etype,
7391 int offset = 0; /* source byte offset */
7392 int rlen = 0; /* remaining bitfield length */
7393 int blen; /* bitfield length */
7394 int bstr; /* bitfield starting bit within byte */
7395 int litval; /* source literal value (if AOP_LIT) */
7396 unsigned char mask; /* bitmask within current byte */
7399 D(emitcode ("; genPackBits",""));
7401 blen = SPEC_BLEN (etype);
7402 bstr = SPEC_BSTR (etype);
7404 /* If the bitfield length is less than a byte */
7407 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7408 (unsigned char) (0xFF >> (8 - bstr)));
7410 if (AOP_TYPE (right) == AOP_LIT)
7412 /* Case with a bitfield length <8 and literal source
7414 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7416 litval &= (~mask) & 0xff;
7418 emitcode ("lda", ",x");
7419 if ((mask|litval)!=0xff)
7420 emitcode ("and","#0x%02x", mask);
7422 emitcode ("ora","#0x%02x", litval);
7423 hc08_dirtyReg (hc08_reg_a, FALSE);
7424 emitcode ("sta", ",x");
7426 hc08_freeReg (hc08_reg_a);
7430 /* Case with a bitfield length < 8 and arbitrary source
7432 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7433 /* shift and mask source value */
7435 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7436 hc08_dirtyReg (hc08_reg_a, FALSE);
7437 pushReg (hc08_reg_a, TRUE);
7439 emitcode ("lda", ",x");
7440 emitcode ("and", "#0x%02x", mask);
7441 emitcode ("ora", "1,s");
7442 emitcode ("sta", ",x");
7443 pullReg (hc08_reg_a);
7445 hc08_freeReg (hc08_reg_a);
7449 /* Bit length is greater than 7 bits. In this case, copy */
7450 /* all except the partial byte at the end */
7451 for (rlen=blen;rlen>=8;rlen-=8)
7453 if (AOP (right)->type == AOP_DIR)
7455 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7460 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7461 emitcode ("sta", "%d,x", offset);
7466 /* If there was a partial byte at the end */
7469 mask = (((unsigned char) -1 << rlen) & 0xff);
7471 if (AOP_TYPE (right) == AOP_LIT)
7473 /* Case with partial byte and literal source
7475 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7476 litval >>= (blen-rlen);
7477 litval &= (~mask) & 0xff;
7478 emitcode ("lda", "%d,x", offset - xoffset);
7479 hc08_dirtyReg (hc08_reg_a, FALSE);
7480 if ((mask|litval)!=0xff)
7481 emitcode ("and","#0x%02x", mask);
7483 emitcode ("ora","#0x%02x", litval);
7484 emitcode ("sta", "%d,x", offset - xoffset);
7485 hc08_dirtyReg (hc08_reg_a, FALSE);
7486 hc08_freeReg (hc08_reg_a);
7490 /* Case with partial byte and arbitrary source
7492 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7493 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7494 hc08_dirtyReg (hc08_reg_a, FALSE);
7495 pushReg (hc08_reg_a, TRUE);
7497 emitcode ("lda", "%d,x", offset - xoffset);
7498 emitcode ("and", "#0x%02x", mask);
7499 emitcode ("ora", "1,s");
7500 emitcode ("sta", "%d,x", offset - xoffset);
7501 pullReg (hc08_reg_a);
7504 hc08_freeReg (hc08_reg_a);
7507 /*-----------------------------------------------------------------*/
7508 /* genPackBitsImmed - generates code for packed bit storage */
7509 /*-----------------------------------------------------------------*/
7511 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7515 int offset = 0; /* source byte offset */
7516 int rlen = 0; /* remaining bitfield length */
7517 int blen; /* bitfield length */
7518 int bstr; /* bitfield starting bit within byte */
7519 int litval; /* source literal value (if AOP_LIT) */
7520 unsigned char mask; /* bitmask within current byte */
7522 D(emitcode ("; genPackBitsImmed",""));
7524 blen = SPEC_BLEN (etype);
7525 bstr = SPEC_BSTR (etype);
7527 aopOp (right, ic, FALSE);
7528 size = AOP_SIZE (right);
7530 derefaop = aopDerefAop (AOP (result));
7531 freeAsmop (result, NULL, ic, TRUE);
7532 derefaop->size = size;
7534 /* if the bitfield is a single bit in the direct page */
7535 if (blen == 1 && derefaop->type == AOP_DIR)
7537 if (AOP_TYPE (right) == AOP_LIT)
7539 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7541 emitcode ((litval & 1) ? "bset" : "bclr",
7542 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7546 symbol *tlbl1 = newiTempLabel (NULL);
7547 symbol *tlbl2 = newiTempLabel (NULL);
7549 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7550 emitcode ("bit", "#1");
7551 emitBranch ("bne", tlbl1);
7552 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7553 emitBranch ("bra", tlbl2);
7555 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7557 hc08_freeReg (hc08_reg_a);
7562 /* If the bitfield length is less than a byte */
7565 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7566 (unsigned char) (0xFF >> (8 - bstr)));
7568 if (AOP_TYPE (right) == AOP_LIT)
7570 /* Case with a bitfield length <8 and literal source
7572 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7574 litval &= (~mask) & 0xff;
7576 loadRegFromAop (hc08_reg_a, derefaop, 0);
7577 if ((mask|litval)!=0xff)
7578 emitcode ("and","#0x%02x", mask);
7580 emitcode ("ora","#0x%02x", litval);
7581 hc08_dirtyReg (hc08_reg_a, FALSE);
7582 storeRegToAop (hc08_reg_a, derefaop, 0);
7584 hc08_freeReg (hc08_reg_a);
7588 /* Case with a bitfield length < 8 and arbitrary source
7590 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7591 /* shift and mask source value */
7593 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7594 hc08_dirtyReg (hc08_reg_a, FALSE);
7595 pushReg (hc08_reg_a, TRUE);
7597 loadRegFromAop (hc08_reg_a, derefaop, 0);
7598 emitcode ("and", "#0x%02x", mask);
7599 emitcode ("ora", "1,s");
7600 storeRegToAop (hc08_reg_a, derefaop, 0);
7601 pullReg (hc08_reg_a);
7603 hc08_freeReg (hc08_reg_a);
7607 /* Bit length is greater than 7 bits. In this case, copy */
7608 /* all except the partial byte at the end */
7609 for (rlen=blen;rlen>=8;rlen-=8)
7611 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7615 /* If there was a partial byte at the end */
7618 mask = (((unsigned char) -1 << rlen) & 0xff);
7620 if (AOP_TYPE (right) == AOP_LIT)
7622 /* Case with partial byte and literal source
7624 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7625 litval >>= (blen-rlen);
7626 litval &= (~mask) & 0xff;
7627 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7628 if ((mask|litval)!=0xff)
7629 emitcode ("and","#0x%02x", mask);
7631 emitcode ("ora","#0x%02x", litval);
7632 hc08_dirtyReg (hc08_reg_a, FALSE);
7633 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7634 hc08_dirtyReg (hc08_reg_a, FALSE);
7635 hc08_freeReg (hc08_reg_a);
7639 /* Case with partial byte and arbitrary source
7641 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7642 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7643 hc08_dirtyReg (hc08_reg_a, FALSE);
7644 pushReg (hc08_reg_a, TRUE);
7646 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7647 emitcode ("and", "#0x%02x", mask);
7648 emitcode ("ora", "1,s");
7649 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7650 pullReg (hc08_reg_a);
7653 hc08_freeReg (hc08_reg_a);
7656 freeAsmop (right, NULL, ic, TRUE);
7657 freeAsmop (NULL, derefaop, ic, TRUE);
7660 /*-----------------------------------------------------------------*/
7661 /* genDataPointerSet - remat pointer to data space */
7662 /*-----------------------------------------------------------------*/
7664 genDataPointerSet (operand * right,
7671 D(emitcode ("; genDataPointerSet",""));
7673 aopOp (right, ic, FALSE);
7674 size = AOP_SIZE (right);
7676 derefaop = aopDerefAop (AOP (result));
7677 freeAsmop (result, NULL, ic, TRUE);
7678 derefaop->size = size;
7682 transferAopAop (AOP (right), size, derefaop, size);
7685 freeAsmop (right, NULL, ic, TRUE);
7686 freeAsmop (NULL, derefaop, ic, TRUE);
7690 /*-----------------------------------------------------------------*/
7691 /* genPointerSet - stores the value into a pointer location */
7692 /*-----------------------------------------------------------------*/
7694 genPointerSet (iCode * ic, iCode *pi)
7696 operand *right = IC_RIGHT (ic);
7697 operand *result = IC_RESULT (ic);
7698 sym_link *type, *etype;
7700 sym_link *retype = getSpec (operandType (right));
7701 sym_link *letype = getSpec (operandType (result));
7703 D(emitcode ("; genPointerSet",""));
7705 type = operandType (result);
7706 etype = getSpec (type);
7708 aopOp (result, ic, FALSE);
7710 /* if the result is rematerializable */
7711 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7713 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7715 genDataPointerSet (right, result, ic);
7720 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7725 /* if the operand is already in hx
7726 then we do nothing else we move the value to hx */
7727 if (AOP_TYPE (result) != AOP_STR)
7729 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7731 /* so hx now contains the address */
7732 aopOp (right, ic, FALSE);
7734 /* if bit then unpack */
7735 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7736 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7739 size = AOP_SIZE (right);
7744 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7745 accopWithMisc ("sta", ",x");
7748 emitcode ("aix", "#1");
7750 hc08_freeReg (hc08_reg_a);
7754 freeAsmop (result, NULL, ic, TRUE);
7755 freeAsmop (right, NULL, ic, TRUE);
7758 aopOp (IC_RESULT (pi), pi, FALSE);
7759 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7760 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7764 hc08_freeReg (hc08_reg_hx);
7768 /*-----------------------------------------------------------------*/
7769 /* genIfx - generate code for Ifx statement */
7770 /*-----------------------------------------------------------------*/
7772 genIfx (iCode * ic, iCode * popIc)
7774 operand *cond = IC_COND (ic);
7777 D(emitcode ("; genIfx",""));
7779 aopOp (cond, ic, FALSE);
7781 /* If the condition is a literal, we can just do an unconditional */
7782 /* branch or no branch */
7783 if (AOP_TYPE (cond) == AOP_LIT)
7785 unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
7786 freeAsmop (cond, NULL, ic, TRUE);
7788 /* if there was something to be popped then do it */
7794 emitBranch ("jmp", IC_TRUE (ic));
7799 emitBranch ("jmp", IC_FALSE (ic));
7805 /* get the value into acc */
7806 if (AOP_TYPE (cond) != AOP_CRY)
7807 asmopToBool (AOP (cond), FALSE);
7810 /* the result is now in the accumulator */
7811 freeAsmop (cond, NULL, ic, TRUE);
7813 /* if there was something to be popped then do it */
7817 /* if the condition is a bit variable */
7818 if (isbit && IS_ITEMP (cond) &&
7820 genIfxJump (ic, SPIL_LOC (cond)->rname);
7821 else if (isbit && !IS_ITEMP (cond))
7822 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7824 genIfxJump (ic, "a");
7829 /*-----------------------------------------------------------------*/
7830 /* genAddrOf - generates code for address of */
7831 /*-----------------------------------------------------------------*/
7833 genAddrOf (iCode * ic)
7835 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7838 D(emitcode ("; genAddrOf",""));
7840 aopOp (IC_RESULT (ic), ic, FALSE);
7842 /* if the operand is on the stack then we
7843 need to get the stack offset of this
7847 /* if it has an offset then we need to compute it */
7848 offset = _G.stackOfs + _G.stackPushes + sym->stack;
7849 hc08_useReg (hc08_reg_hx);
7850 emitcode ("tsx", "");
7851 while (offset > 127)
7853 emitcode ("aix", "#127");
7856 while (offset < -128)
7858 emitcode ("aix", "#-128");
7861 emitcode ("aix", "#%d", offset);
7862 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7863 hc08_freeReg (hc08_reg_hx);
7868 /* object not on stack then we need the name */
7869 size = AOP_SIZE (IC_RESULT (ic));
7874 char s[SDCC_NAME_MAX+10];
7877 sprintf (s, "#%s", sym->rname);
7880 sprintf (s, "#>%s", sym->rname);
7883 sprintf (s, "#(%s >> %d)",
7887 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7891 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7895 /*-----------------------------------------------------------------*/
7896 /* genAssign - generate code for assignment */
7897 /*-----------------------------------------------------------------*/
7899 genAssign (iCode * ic)
7901 operand *result, *right;
7903 // unsigned long lit = 0L;
7905 D(emitcode("; genAssign",""));
7907 result = IC_RESULT (ic);
7908 right = IC_RIGHT (ic);
7910 /* if they are the same */
7911 if (operandsEqu (result, right)) {
7915 aopOp (right, ic, FALSE);
7916 aopOp (result, ic, TRUE);
7918 /* if they are the same registers */
7919 if (sameRegs (AOP (right), AOP (result)))
7922 if ((AOP_TYPE (right) == AOP_LIT)
7923 && (IS_AOP_HX(AOP(result))))
7925 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7930 size = AOP_SIZE (result);
7933 transferAopAop (AOP (right), size, AOP (result), size);
7937 freeAsmop (right, NULL, ic, TRUE);
7938 freeAsmop (result, NULL, ic, TRUE);
7941 /*-----------------------------------------------------------------*/
7942 /* genJumpTab - generates code for jump table */
7943 /*-----------------------------------------------------------------*/
7945 genJumpTab (iCode * ic)
7948 symbol *jtablo = newiTempLabel (NULL);
7949 symbol *jtabhi = newiTempLabel (NULL);
7951 D(emitcode ("; genJumpTab",""));
7953 aopOp (IC_JTCOND (ic), ic, FALSE);
7955 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7957 /* get the condition into x */
7958 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7959 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7960 loadRegFromConst (hc08_reg_h, zero);
7962 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7963 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7964 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7965 emitcode ("jmp", ",x");
7967 hc08_dirtyReg (hc08_reg_a, TRUE);
7968 hc08_dirtyReg (hc08_reg_hx, TRUE);
7973 pushReg(hc08_reg_hx, TRUE);
7975 /* get the condition into x */
7976 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7977 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7978 loadRegFromConst (hc08_reg_h, zero);
7980 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7981 emitcode ("sta", "3,s");
7982 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7983 emitcode ("sta", "4,s");
7985 pullReg(hc08_reg_hx);
7986 emitcode ("rts", "");
7987 _G.stackPushes += 2;
7991 /* now generate the jump labels */
7993 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7994 jtab = setNextItem (IC_JTLABELS (ic)))
7995 emitcode (".db", "%05d$", jtab->key + 100);
7997 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7998 jtab = setNextItem (IC_JTLABELS (ic)))
7999 emitcode (".db", ">%05d$", jtab->key + 100);
8003 /*-----------------------------------------------------------------*/
8004 /* genCast - gen code for casting */
8005 /*-----------------------------------------------------------------*/
8007 genCast (iCode * ic)
8009 operand *result = IC_RESULT (ic);
8010 sym_link *ctype = operandType (IC_LEFT (ic));
8011 sym_link *rtype = operandType (IC_RIGHT (ic));
8012 operand *right = IC_RIGHT (ic);
8015 D(emitcode("; genCast",""));
8017 /* if they are equivalent then do nothing */
8018 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8021 aopOp (right, ic, FALSE);
8022 aopOp (result, ic, FALSE);
8025 /* if they are the same size : or less */
8026 if (AOP_SIZE (result) <= AOP_SIZE (right))
8029 /* if they are in the same place */
8031 if (sameRegs (AOP (right), AOP (result)))
8035 /* if they in different places then copy */
8036 size = AOP_SIZE (result);
8040 transferAopAop(AOP (right), offset, AOP (result), offset);
8047 /* if the result is of type pointer */
8052 sym_link *type = operandType (right);
8053 sym_link *etype = getSpec (type);
8055 /* pointer to generic pointer */
8056 if (IS_GENPTR (ctype))
8059 p_type = DCL_TYPE (type);
8062 if (SPEC_SCLS(etype)==S_REGISTER) {
8063 // let's assume it is a generic pointer
8066 /* we have to go by the storage class */
8067 p_type = PTR_TYPE (SPEC_OCLS (etype));
8071 /* the first two bytes are known */
8072 size = GPTRSIZE - 1;
8076 transferAopAop(AOP (right), offset, AOP (result), offset);
8079 /* the last byte depending on type */
8082 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8087 // pointerTypeToGPByte will have bitched.
8091 sprintf(gpValStr, "#0x%x", gpVal);
8092 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8098 /* just copy the pointers */
8099 size = AOP_SIZE (result);
8103 transferAopAop(AOP (right), offset, AOP (result), offset);
8109 /* so we now know that the size of destination is greater
8110 than the size of the source */
8111 /* we move to result for the size of source */
8112 size = AOP_SIZE (right);
8116 transferAopAop(AOP (right), offset, AOP (result), offset);
8120 /* now depending on the sign of the source && destination */
8121 size = AOP_SIZE (result) - AOP_SIZE (right);
8122 /* if unsigned or not an integral type */
8123 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8126 storeConstToAop (zero, AOP (result), offset++);
8130 /* we need to extend the sign :{ */
8131 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8132 accopWithMisc ("rola", "");
8133 accopWithMisc ("clra", "");
8134 accopWithMisc ("sbc", zero);
8136 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8139 /* we are done hurray !!!! */
8142 freeAsmop (right, NULL, ic, TRUE);
8143 freeAsmop (result, NULL, ic, TRUE);
8147 /*-----------------------------------------------------------------*/
8148 /* genDjnz - generate decrement & jump if not zero instrucion */
8149 /*-----------------------------------------------------------------*/
8151 genDjnz (iCode * ic, iCode * ifx)
8157 D(emitcode ("; genDjnz",""));
8159 /* if the if condition has a false label
8160 then we cannot save */
8164 /* if the minus is not of the form
8166 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8167 !IS_OP_LITERAL (IC_RIGHT (ic)))
8170 if (operandLitValue (IC_RIGHT (ic)) != 1)
8173 /* dbnz doesn't support extended mode */
8174 if (isOperandInFarSpace (IC_RESULT (ic)))
8177 /* if the size of this greater than one then no
8179 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8181 aopOp (IC_RESULT (ic), ic, FALSE);
8182 if (AOP_SIZE (IC_RESULT (ic))>1)
8184 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8188 /* otherwise we can save BIG */
8189 lbl = newiTempLabel (NULL);
8190 lbl1 = newiTempLabel (NULL);
8193 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8196 emitBranch ("bra", lbl1);
8198 emitBranch ("jmp", IC_TRUE (ifx));
8201 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8206 /*-----------------------------------------------------------------*/
8207 /* genReceive - generate code for a receive iCode */
8208 /*-----------------------------------------------------------------*/
8210 genReceive (iCode * ic)
8214 D(emitcode ("; genReceive",""));
8216 aopOp (IC_RESULT (ic), ic, FALSE);
8217 size = AOP_SIZE (IC_RESULT (ic));
8222 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8223 AOP (IC_RESULT (ic)), offset);
8224 if (hc08_aop_pass[offset]->type == AOP_REG)
8225 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8230 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8233 /*-----------------------------------------------------------------*/
8234 /* genDummyRead - generate code for dummy read of volatiles */
8235 /*-----------------------------------------------------------------*/
8237 genDummyRead (iCode * ic)
8242 D(emitcode("; genDummyRead",""));
8245 if (op && IS_SYMOP (op))
8248 aopOp (op, ic, FALSE);
8250 size = AOP_SIZE (op);
8255 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8256 hc08_freeReg (hc08_reg_a);
8260 freeAsmop (op, NULL, ic, TRUE);
8263 if (op && IS_SYMOP (op))
8266 aopOp (op, ic, FALSE);
8268 size = AOP_SIZE (op);
8273 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8274 hc08_freeReg (hc08_reg_a);
8278 freeAsmop (op, NULL, ic, TRUE);
8282 /*-----------------------------------------------------------------*/
8283 /* genCritical - generate code for start of a critical sequence */
8284 /*-----------------------------------------------------------------*/
8286 genCritical (iCode *ic)
8288 D(emitcode("; genCritical",""));
8291 aopOp (IC_RESULT (ic), ic, TRUE);
8293 emitcode ("tpa", "");
8294 hc08_dirtyReg (hc08_reg_a, FALSE);
8295 emitcode ("sei", "");
8298 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8300 pushReg (hc08_reg_a, FALSE);
8302 hc08_freeReg (hc08_reg_a);
8304 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8307 /*-----------------------------------------------------------------*/
8308 /* genEndCritical - generate code for end of a critical sequence */
8309 /*-----------------------------------------------------------------*/
8311 genEndCritical (iCode *ic)
8313 D(emitcode("; genEndCritical",""));
8317 aopOp (IC_RIGHT (ic), ic, FALSE);
8318 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8319 emitcode ("tap", "");
8320 hc08_freeReg (hc08_reg_a);
8321 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8325 pullReg (hc08_reg_a);
8326 emitcode ("tap", "");
8332 /*-----------------------------------------------------------------*/
8333 /* genhc08Code - generate code for HC08 based controllers */
8334 /*-----------------------------------------------------------------*/
8336 genhc08Code (iCode * lic)
8343 lineHead = lineCurr = NULL;
8345 /* print the allocation information */
8346 if (allocInfo && currFunc)
8347 printAllocInfo (currFunc, codeOutFile);
8348 /* if debug information required */
8349 if (options.debug && currFunc)
8351 debugFile->writeFunction (currFunc, lic);
8354 if (IS_STATIC (currFunc->etype))
8355 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8357 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8361 /* stack pointer name */
8362 if (options.useXstack)
8367 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8369 hc08_aop_pass[0] = newAsmop (AOP_REG);
8370 hc08_aop_pass[0]->size=1;
8371 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8372 hc08_aop_pass[1] = newAsmop (AOP_REG);
8373 hc08_aop_pass[1]->size=1;
8374 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8375 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8376 hc08_aop_pass[2]->size=1;
8377 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8378 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8379 hc08_aop_pass[3]->size=1;
8380 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8382 for (ic = lic; ic; ic = ic->next)
8385 _G.current_iCode = ic;
8387 if (ic->level != clevel || ic->block != cblock)
8391 debugFile->writeScope(ic);
8397 if (ic->lineno && cln != ic->lineno)
8401 debugFile->writeCLine(ic);
8404 emitcode ("", "C$%s$%d$%d$%d ==.",
8405 FileBaseName (ic->filename), ic->lineno,
8406 ic->level, ic->block);
8410 if (!options.noCcodeInAsm) {
8411 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8412 printCLine(ic->filename, ic->lineno));
8416 if (options.iCodeInAsm) {
8420 for (i=0; i<6; i++) {
8421 sprintf (®sInUse[i],
8422 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8425 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8427 /* if the result is marked as
8428 spilt and rematerializable or code for
8429 this has already been generated then
8431 if (resultRemat (ic) || ic->generated)
8439 for (i=A_IDX;i<=XA_IDX;i++)
8441 reg = hc08_regWithIdx(i);
8443 emitcode("","; %s = %s offset %d", reg->name,
8444 aopName(reg->aop), reg->aopofs);
8447 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8449 sym = OP_SYMBOL (IC_LEFT (ic));
8450 if (sym->accuse == ACCUSE_HX)
8452 hc08_reg_h->isFree = FALSE;
8453 hc08_reg_x->isFree = FALSE;
8455 else if (sym->accuse == ACCUSE_XA)
8457 hc08_reg_a->isFree = FALSE;
8459 hc08_reg_x->isFree = FALSE;
8462 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8464 sym = OP_SYMBOL (IC_RIGHT (ic));
8465 if (sym->accuse == ACCUSE_HX)
8467 hc08_reg_h->isFree = FALSE;
8468 hc08_reg_x->isFree = FALSE;
8470 else if (sym->accuse == ACCUSE_XA)
8472 hc08_reg_a->isFree = FALSE;
8474 hc08_reg_x->isFree = FALSE;
8479 /* depending on the operation */
8499 /* IPOP happens only when trying to restore a
8500 spilt live range, if there is an ifx statement
8501 following this pop then the if statement might
8502 be using some of the registers being popped which
8503 would destory the contents of the register so
8504 we need to check for this condition and handle it */
8506 ic->next->op == IFX &&
8507 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8508 genIfx (ic->next, ic);
8526 genEndFunction (ic);
8542 if (!genPointerGetSetOfs (ic))
8547 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8567 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8572 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8584 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8588 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8592 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8619 case GET_VALUE_AT_ADDRESS:
8621 hasInc (IC_LEFT (ic), ic,
8622 getSize (operandType (IC_RESULT (ic)))),
8623 ifxForOp (IC_RESULT (ic), ic) );
8627 if (POINTER_SET (ic))
8628 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8654 addSet (&_G.sendSet, ic);
8657 case DUMMY_READ_VOLATILE:
8666 genEndCritical (ic);
8677 if (!hc08_reg_a->isFree)
8678 DD(emitcode("","; forgot to free a"));
8679 if (!hc08_reg_x->isFree)
8680 DD(emitcode("","; forgot to free x"));
8681 if (!hc08_reg_h->isFree)
8682 DD(emitcode("","; forgot to free h"));
8683 if (!hc08_reg_hx->isFree)
8684 DD(emitcode("","; forgot to free hx"));
8685 if (!hc08_reg_xa->isFree)
8686 DD(emitcode("","; forgot to free xa"));
8689 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8692 /* now we are ready to call the
8693 peep hole optimizer */
8694 if (!options.nopeep)
8695 peepHole (&lineHead);
8697 /* now do the actual printing */
8698 printLine (lineHead, codeOutFile);