1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for the 68HC08
4 Hacked for the 68HC08 by Erik Petrich (2003)
5 Adapted from the 8051 code generator by:
6 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
7 and - Jean-Louis VERN.jlvern@writeme.com (1999)
8 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
28 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 char *aopLiteral (value * val, int offset);
46 char *aopLiteralLong (value * val, int offset, int size);
48 static int pushReg (regs *reg, bool freereg);
49 static void pullReg (regs *reg);
51 static char *zero = "#0x00";
52 static char *one = "#0x01";
56 {"a", "x", "_ret2", "_ret3"};
57 unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */
58 char **fReturn2 = fReturnhc08;
77 static asmop *hc08_aop_pass[4];
79 extern int hc08_ptrRegReq;
80 extern int hc08_nRegs;
81 extern FILE *codeOutFile;
82 //static void saveRBank (int, iCode *, bool);
83 static bool operandsEqu (operand * op1, operand * op2);
84 static void loadRegFromConst (regs *reg, char *c);
85 static char *aopName (asmop *aop);
86 static asmop * newAsmop (short type);
87 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define IS_AOP_HX(x) \
93 (((x)->type == AOP_REG) \
94 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
95 && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
97 #define IS_AOP_XA(x) \
98 (((x)->type == AOP_REG) \
99 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
100 && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
102 #define IS_AOP_A(x) \
103 (((x)->type == AOP_REG) \
104 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
105 && ((x)->size == 1) )
107 #define IS_AOP_X(x) \
108 (((x)->type == AOP_REG) \
109 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
110 && ((x)->size == 1) )
112 #define IS_AOP_H(x) \
113 (((x)->type == AOP_REG) \
114 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
115 && ((x)->size == 1) )
117 #define CLRC emitcode("clc","")
119 static lineNode *lineHead = NULL;
120 static lineNode *lineCurr = NULL;
123 static unsigned char SLMask[] =
124 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
125 0xE0, 0xC0, 0x80, 0x00};
126 static unsigned char SRMask[] =
127 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
128 0x07, 0x03, 0x01, 0x00};
136 #define AOP(op) op->aop
137 #define AOP_TYPE(op) AOP(op)->type
138 #define AOP_SIZE(op) AOP(op)->size
139 #define AOP_OP(aop) aop->op
142 /*-----------------------------------------------------------------*/
143 /* emitcode - writes the code into a file : for now it is simple */
144 /*-----------------------------------------------------------------*/
146 emitcode (char *inst, char *fmt,...)
149 char lb[INITIAL_INLINEASM];
157 sprintf (lb, "%s\t", inst);
159 sprintf (lb, "%s", inst);
160 vsprintf (lb + (strlen (lb)), fmt, ap);
163 vsprintf (lb, fmt, ap);
165 while (isspace ((unsigned char)*lbp))
169 lineCurr = (lineCurr ?
170 connectLine (lineCurr, newLineNode (lb)) :
171 (lineHead = newLineNode (lb)));
172 lineCurr->isInline = _G.inLine;
173 lineCurr->isDebug = _G.debugLine;
174 lineCurr->ic = _G.current_iCode;
175 lineCurr->isComment = (*lbp==';');
177 //printf("%s\n", lb);
182 emitBranch (char *branchop, symbol *tlbl)
184 emitcode (branchop, "%05d$", (tlbl->key + 100));
188 emitLabel (symbol *tlbl)
190 emitcode ("", "%05d$:", (tlbl->key +100));
193 /*-----------------------------------------------------------------*/
194 /* hc08_emitDebuggerSymbol - associate the current code location */
195 /* with a debugger symbol */
196 /*-----------------------------------------------------------------*/
198 hc08_emitDebuggerSymbol (char * debugSym)
201 emitcode ("", "%s ==.", debugSym);
206 /*--------------------------------------------------------------------------*/
207 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
208 /* freesrc is true, sreg is marked free and available for */
209 /* reuse. sreg and dreg must be of equal size */
210 /*--------------------------------------------------------------------------*/
212 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
218 /* Nothing to do if no destination. */
222 /* But it's definately an error if there's no source. */
225 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
226 "NULL sreg in transferRegReg");
230 D(emitcode ("", "; transferRegReg(%s,%s)",
231 sreg->name, dreg->name));
244 case H_IDX: /* H to A */
245 pushReg (hc08_reg_h, FALSE);
246 pullReg (hc08_reg_a);
248 case X_IDX: /* X to A */
249 emitcode ("txa", "");
258 case A_IDX: /* A to H */
259 pushReg (hc08_reg_a, FALSE);
260 pullReg (hc08_reg_h);
262 case X_IDX: /* X to H */
263 pushReg (hc08_reg_x, FALSE);
264 pullReg (hc08_reg_h);
273 case A_IDX: /* A to X */
274 emitcode ("tax", "");
276 case H_IDX: /* H to X */
277 pushReg (hc08_reg_h, FALSE);
278 pullReg (hc08_reg_x);
287 case XA_IDX: /* XA to HX */
288 pushReg (hc08_reg_x, FALSE);
289 pullReg (hc08_reg_h);
290 emitcode ("tax", "");
299 case HX_IDX: /* HX to XA */
300 emitcode ("txa", "");
301 pushReg (hc08_reg_h, FALSE);
302 pullReg (hc08_reg_x);
312 wassertl (!error, "bad combo in transferRegReg");
317 dreg->aop = sreg->aop;
318 dreg->aopofs = sreg->aopofs;
319 dreg->isFree = FALSE;
323 /*--------------------------------------------------------------------------*/
324 /* updateCFA - update the debugger information to reflect the current */
325 /* connonical frame address relative to the stack pointer */
326 /*--------------------------------------------------------------------------*/
330 /* there is no frame unless there is a function */
334 debugFile->writeFrameAddress (NULL, hc08_reg_sp,
335 1 + _G.stackOfs + _G.stackPushes);
338 /*--------------------------------------------------------------------------*/
339 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
340 /* marked free and available for reuse. */
341 /*--------------------------------------------------------------------------*/
343 pushReg (regs *reg, bool freereg)
345 int regidx = reg->rIdx;
350 emitcode ("psha", "");
355 emitcode ("pshx", "");
360 emitcode ("pshh", "");
365 emitcode ("pshx", "");
368 emitcode ("pshh", "");
373 emitcode ("psha", "");
376 emitcode ("pshx", "");
385 return -_G.stackOfs-_G.stackPushes;
388 /*--------------------------------------------------------------------------*/
389 /* pullReg - Pull register reg off the stack. */
390 /*--------------------------------------------------------------------------*/
394 int regidx = reg->rIdx;
399 emitcode ("pula", "");
404 emitcode ("pulx", "");
409 emitcode ("pulh", "");
414 emitcode ("pulh", "");
417 emitcode ("pulx", "");
422 emitcode ("pulx", "");
425 emitcode ("pula", "");
433 hc08_dirtyReg(reg, FALSE);
436 /*--------------------------------------------------------------------------*/
437 /* pullNull - Discard n bytes off the top of the stack */
438 /*--------------------------------------------------------------------------*/
444 emitcode("ais","#%d",n);
450 /*--------------------------------------------------------------------------*/
451 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
452 /* push was performed, false otherwise. */
453 /*--------------------------------------------------------------------------*/
455 pushRegIfUsed (regs *reg)
466 /*--------------------------------------------------------------------------*/
467 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
468 /* stack. Otherwise register reg is marked as free. */
469 /*--------------------------------------------------------------------------*/
471 pullOrFreeReg (regs *reg, bool needpull)
479 /*--------------------------------------------------------------------------*/
480 /* adjustStack - Adjust the stack pointer by n bytes. */
481 /*--------------------------------------------------------------------------*/
489 emitcode ("ais","#127");
491 _G.stackPushes -= 127;
496 emitcode ("ais","#-128");
498 _G.stackPushes += 128;
503 emitcode ("ais", "#%d", n);
512 /*--------------------------------------------------------------------------*/
513 /* aopName - Return a string with debugging information about an asmop. */
514 /*--------------------------------------------------------------------------*/
518 static char buffer[256];
522 return "(asmop*)NULL";
527 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
530 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
533 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
536 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
539 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
542 sprintf (buf, "REG(%s,%s,%s,%s)",
543 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
544 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
545 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
546 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
553 sprintf (buf,"?%d", aop->type);
561 /*--------------------------------------------------------------------------*/
562 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
563 /*--------------------------------------------------------------------------*/
565 loadRegFromAop (regs *reg, asmop *aop, int loffset)
567 int regidx = reg->rIdx;
569 if (aop->stacked && aop->stk_aop[loffset])
571 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
576 printf("loadRegFromAop called\n");
579 printf(" reg = NULL\n");
582 printf(" reg = %s\n", reg->name);
585 printf(" aop = NULL\n");
588 printf(" aop->type = %d\n", aop->type);
589 printf(" loffset = %d\n", loffset);
592 printf(" aop has operand link\n");
594 printf(" aop missing operand link\n");
596 printf(" reg has operand link\n");
598 printf(" reg missing operand link\n");
601 D(emitcode ("", "; loadRegFromAop (%s, %s, %d)",
602 reg->name, aopName (aop), loffset));
604 /* If operand is volatile, we cannot optimize. */
605 if (!aop->op || isOperandVolatile (aop->op, FALSE))
609 /* If this register already has this offset of the operand
610 then we need only mark it as in use. */
611 if (reg->aop && reg->aop->op && aop->op
612 && operandsEqu(reg->aop->op,aop->op)
613 && (reg->aopofs == loffset))
616 D(emitcode ("","; already had correct value for %s", reg->name));
620 /* TODO: check to see if we can transfer from another register */
622 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
623 && operandsEqu(hc08_reg_h->aop->op,aop->op)
624 && (hc08_reg_h->aopofs == loffset))
626 D(emitcode ("","; found correct value for %s in h", reg->name));
627 transferRegReg (hc08_reg_h, reg, FALSE);
633 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
634 && operandsEqu(hc08_reg_x->aop->op,aop->op)
635 && (hc08_reg_x->aopofs == loffset))
637 D(emitcode ("","; found correct value for %s in x", reg->name));
638 transferRegReg (hc08_reg_x, reg, FALSE);
643 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
644 && operandsEqu(hc08_reg_a->aop->op,aop->op)
645 && (hc08_reg_a->aopofs == loffset))
647 D(emitcode ("","; found correct value for %s in a", reg->name));
648 transferRegReg (hc08_reg_a, reg, FALSE);
658 if (aop->type == AOP_REG)
660 if (loffset < aop->size)
661 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
663 emitcode ("clra", ""); /* TODO: handle sign extension */
667 char * l = aopAdrStr (aop, loffset, FALSE);
668 if (!strcmp (l, zero))
669 emitcode ("clra", "");
671 emitcode ("lda", "%s", l);
675 if (aop->type == AOP_REG)
677 if (loffset < aop->size)
678 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
680 emitcode ("clrx", ""); /* TODO: handle sign extension */
684 char * l = aopAdrStr (aop, loffset, FALSE);
685 if (!strcmp (l, zero))
686 emitcode ("clrx", "");
688 emitcode ("ldx", "%s", l);
693 char * l = aopAdrStr (aop, loffset, FALSE);
694 if (!strcmp (l, zero))
696 emitcode ("clrh", "");
700 if (hc08_reg_a->isFree)
702 loadRegFromAop (hc08_reg_a, aop, loffset);
703 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
705 else if (hc08_reg_x->isFree)
707 loadRegFromAop (hc08_reg_x, aop, loffset);
708 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
712 pushReg (hc08_reg_a, TRUE);
713 loadRegFromAop (hc08_reg_a, aop, loffset);
714 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
715 pullReg (hc08_reg_a);
721 else if (IS_AOP_XA(aop))
722 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
723 else if ((aop->type == AOP_DIR))
725 if (aop->size>(loffset+1))
726 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
729 loadRegFromAop (hc08_reg_x, aop, loffset);
730 loadRegFromConst (hc08_reg_h, zero);
733 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
735 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
740 needpula = pushRegIfUsed (hc08_reg_a);
741 loadRegFromAop (hc08_reg_a, aop, loffset+1);
742 loadRegFromAop (hc08_reg_x, aop, loffset);
743 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
744 pullOrFreeReg (hc08_reg_a, needpula);
750 else if (IS_AOP_HX(aop))
751 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
754 loadRegFromAop (hc08_reg_a, aop, loffset);
755 loadRegFromAop (hc08_reg_x, aop, loffset+1);
760 // ignore caching for now
763 reg->aopofs = loffset;
768 /*--------------------------------------------------------------------------*/
769 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
770 /* freeAsmop is called with aop, the stacked data will */
771 /* be copied to the original aop location and */
772 /*--------------------------------------------------------------------------*/
774 forceStackedAop (asmop *aop)
777 asmop *newaop = newAsmop (aop->type);
778 memcpy (newaop, aop, sizeof(*newaop));
780 D(emitcode("", "; forcedStackAop %s", aopName(aop)));
781 for (loffset=0; loffset < newaop->size; loffset++)
783 asmop *aopsof = newAsmop (AOP_SOF);
785 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
786 aopsof->op = aop->op;
787 newaop->stk_aop[loffset] = aopsof;
794 /*--------------------------------------------------------------------------*/
795 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
796 /*--------------------------------------------------------------------------*/
798 storeRegToAop (regs *reg, asmop *aop, int loffset)
800 int regidx = reg->rIdx;
806 D(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
807 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
809 if ((reg->rIdx == HX_IDX) && aop->stacked
810 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
812 storeRegToAop (hc08_reg_h, aop, loffset+1);
813 storeRegToAop (hc08_reg_x, aop, loffset);
817 if ((reg->rIdx == XA_IDX) && aop->stacked
818 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
820 storeRegToAop (hc08_reg_x, aop, loffset+1);
821 storeRegToAop (hc08_reg_a, aop, loffset);
825 if (aop->stacked && aop->stk_aop[loffset])
827 storeRegToAop (reg, aop->stk_aop[loffset], 0);
831 if (aop->type == AOP_STR)
834 transferRegReg (reg, hc08_reg_x, FALSE);
836 transferRegReg (reg, hc08_reg_h, FALSE);
840 if (aop->type == AOP_DUMMY)
843 if (aop->type == AOP_CRY) /* This can only happen if IFX was optimized */
844 return; /* away, so just toss the result */
849 if ((aop->type == AOP_REG) && (loffset < aop->size))
850 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
852 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
855 if ((aop->type == AOP_REG) && (loffset < aop->size))
856 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
858 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
861 if (hc08_reg_a->isFree)
863 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
864 storeRegToAop (hc08_reg_a, aop, loffset);
865 hc08_freeReg (hc08_reg_a);
867 else if (hc08_reg_x->isFree)
869 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
870 storeRegToAop (hc08_reg_x, aop, loffset);
871 hc08_freeReg (hc08_reg_x);
875 pushReg (hc08_reg_a, TRUE);
876 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
877 storeRegToAop (hc08_reg_a, aop, loffset);
878 pullReg (hc08_reg_a);
882 if ((aop->type == AOP_DIR) )
884 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
886 else if (IS_AOP_XA(aop))
887 transferRegReg(reg, hc08_reg_xa, FALSE);
888 else if (IS_AOP_HX(aop))
893 needpula = pushRegIfUsed (hc08_reg_a);
894 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
895 storeRegToAop (hc08_reg_a, aop, loffset+1);
896 storeRegToAop (hc08_reg_x, aop, loffset);
897 pullOrFreeReg (hc08_reg_a, needpula);
902 transferRegReg(reg, hc08_reg_hx, FALSE);
903 else if (IS_AOP_XA(aop))
907 storeRegToAop (hc08_reg_a, aop, loffset);
908 storeRegToAop (hc08_reg_x, aop, loffset+1);
913 /* Disable the register tracking for now */
915 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
918 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
920 otherreg=hc08_regWithIdx(otheridx);
921 if (otherreg && otherreg->aop
922 && otherreg->aop->op && aop->op
923 && operandsEqu(otherreg->aop->op,aop->op)
924 && (otherreg->aopofs == loffset))
926 D(emitcode("","; marking %s stale", otherreg->name));
930 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
932 hc08_reg_hx->aop = NULL;
933 D(emitcode("","; marking hx stale"));
935 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
937 hc08_reg_xa->aop = NULL;
938 D(emitcode("","; marking xa stale"));
942 reg->aopofs = loffset;
947 /*--------------------------------------------------------------------------*/
948 /* loadRegFromConst - Load register reg from constant c. */
949 /*--------------------------------------------------------------------------*/
951 loadRegFromConst (regs *reg, char *c)
957 emitcode ("clra", "");
959 emitcode ("lda", "%s", c);
963 emitcode ("clrx", "");
965 emitcode ("ldx", "%s", c);
969 emitcode ("clrh", "");
970 else if (hc08_reg_a->isFree)
972 loadRegFromConst (hc08_reg_a, c);
973 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
975 else if (hc08_reg_x->isFree)
977 loadRegFromConst (hc08_reg_x, c);
978 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
982 pushReg (hc08_reg_a, TRUE);
983 loadRegFromConst (hc08_reg_a, c);
984 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
985 pullReg (hc08_reg_a);
989 emitcode ("ldhx", "%s", c);
992 emitcode ("lda", "%s", c);
993 emitcode ("ldx", "%s >> 8", c);
996 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
997 "Bad rIdx in loadRegFromConst");
1004 /*--------------------------------------------------------------------------*/
1005 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
1006 /*--------------------------------------------------------------------------*/
1008 storeConstToAop (char *c, asmop *aop, int loffset)
1010 if (aop->stacked && aop->stk_aop[loffset])
1012 storeConstToAop (c, aop->stk_aop[loffset], 0);
1019 if (!strcmp(c,zero))
1020 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
1022 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
1025 if (loffset>(aop->size-1))
1027 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
1032 if (hc08_reg_a->isFree)
1034 loadRegFromConst (hc08_reg_a, c);
1035 storeRegToAop( hc08_reg_a, aop, loffset);
1036 hc08_freeReg (hc08_reg_a);
1038 else if (hc08_reg_x->isFree)
1040 loadRegFromConst (hc08_reg_x, c);
1041 storeRegToAop( hc08_reg_x, aop, loffset);
1042 hc08_freeReg (hc08_reg_x);
1046 pushReg (hc08_reg_a, TRUE);
1047 loadRegFromConst (hc08_reg_a, c);
1048 storeRegToAop( hc08_reg_a, aop, loffset);
1049 pullReg (hc08_reg_a);
1055 /*--------------------------------------------------------------------------*/
1056 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
1057 /* reg is extended to fill logical offsets loffset */
1058 /* and above of asmop aop. Otherwise, logical */
1059 /* offsets loffset and above of asmop aop are */
1060 /* zeroed. reg must be an 8-bit register. */
1061 /*--------------------------------------------------------------------------*/
1063 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
1065 // int regidx = reg->rIdx;
1066 int size = aop->size;
1074 while (loffset<size)
1075 storeConstToAop(zero, aop, loffset++);
1080 transferRegReg (reg, hc08_reg_a, FALSE);
1081 emitcode ("rola","");
1082 emitcode ("clra","");
1083 emitcode ("sbc", "#0");
1084 hc08_useReg (hc08_reg_a);
1085 while (loffset<size)
1086 storeRegToAop (hc08_reg_a, aop, loffset++);
1087 hc08_freeReg (hc08_reg_a);
1091 /*--------------------------------------------------------------------------*/
1092 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1093 /* padding and/or truncation as needed. If isSigned is */
1094 /* true, sign extension will take place in the padding. */
1095 /*--------------------------------------------------------------------------*/
1097 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1099 int regidx = reg->rIdx;
1100 int size = aop->size;
1107 storeRegToAop (reg, aop, 0);
1108 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1113 storeRegToAop (hc08_reg_x, aop, 0);
1117 storeRegToAop (reg, aop, 0);
1118 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1124 storeRegToAop (hc08_reg_a, aop, 0);
1128 storeRegToAop (reg, aop, 0);
1129 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1135 /*--------------------------------------------------------------------------*/
1136 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1137 /* srcaop to logical offset dstofs of asmop dstaop. */
1138 /*--------------------------------------------------------------------------*/
1140 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1142 bool needpula = FALSE;
1145 bool keepreg = FALSE;
1147 /* ignore transfers at the same byte, unless its volatile */
1148 if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
1149 && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
1150 && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs
1151 && dstaop->type == srcaop->type)
1154 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1156 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1160 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1162 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1166 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1167 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1168 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1169 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1171 if (dstofs >= dstaop->size)
1174 if ((dstaop->type == AOP_DIR)
1175 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1177 if (srcaop->type == AOP_LIT)
1180 unsigned long bytemask;
1182 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1183 bytemask = (lit >> (srcofs*8)) & 0xff;
1187 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1192 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1193 aopAdrStr(dstaop, dstofs, FALSE));
1197 if (dstaop->type == AOP_REG)
1199 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1200 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1202 reg = dstaop->aopu.aop_reg[dstofs];
1207 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1209 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1210 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1212 reg = srcaop->aopu.aop_reg[srcofs];
1219 if (hc08_reg_a->isFree)
1221 else if (hc08_reg_x->isFree)
1225 pushReg (hc08_reg_a, TRUE);
1231 loadRegFromAop (reg, srcaop, srcofs);
1232 storeRegToAop (reg, dstaop, dstofs);
1235 pullOrFreeReg (hc08_reg_a, needpula);
1239 /*--------------------------------------------------------------------------*/
1240 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1241 /* parameter param. */
1242 /*--------------------------------------------------------------------------*/
1244 accopWithMisc (char *accop, char *param)
1246 emitcode (accop, "%s", param);
1247 hc08_dirtyReg (hc08_reg_a, FALSE);
1250 /*--------------------------------------------------------------------------*/
1251 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1252 /* byte at logical offset loffset of asmop aop. */
1253 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1254 /*--------------------------------------------------------------------------*/
1256 accopWithAop (char *accop, asmop *aop, int loffset)
1258 if (aop->stacked && aop->stk_aop[loffset])
1260 accopWithAop (accop, aop->stk_aop[loffset], 0);
1264 if (aop->type == AOP_DUMMY)
1267 if (aop->type == AOP_REG)
1269 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1270 emitcode (accop, "1,s");
1274 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1276 hc08_dirtyReg (hc08_reg_a, FALSE);
1280 /*--------------------------------------------------------------------------*/
1281 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1282 /* byte at logical offset loffset of asmop aop. Register reg */
1283 /* must be 8-bit. */
1284 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1285 /*--------------------------------------------------------------------------*/
1287 rmwWithReg (char *rmwop, regs *reg)
1290 char *rmwaop = rmwbuf;
1292 if (reg->rIdx == A_IDX)
1294 sprintf(rmwaop,"%sa", rmwop);
1295 emitcode (rmwaop, "");
1296 hc08_dirtyReg (hc08_reg_a, FALSE);
1298 else if (reg->rIdx == X_IDX)
1300 sprintf(rmwaop,"%sx", rmwop);
1301 emitcode (rmwaop, "");
1302 hc08_dirtyReg (hc08_reg_a, FALSE);
1304 else if (hc08_reg_a->isFree)
1306 transferRegReg(reg, hc08_reg_a, FALSE);
1307 sprintf(rmwaop,"%sa", rmwop);
1308 emitcode (rmwaop, "");
1309 hc08_dirtyReg (hc08_reg_a, FALSE);
1310 transferRegReg(hc08_reg_a, reg, TRUE);
1314 pushReg (reg, FALSE);
1315 emitcode (rmwop, "1,s");
1317 hc08_dirtyReg (reg, FALSE);
1321 /*--------------------------------------------------------------------------*/
1322 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1323 /* logical offset loffset of asmop aop. */
1324 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1325 /*--------------------------------------------------------------------------*/
1327 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1329 bool needpula = FALSE;
1331 if (aop->stacked && aop->stk_aop[loffset])
1333 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1340 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1343 needpula = pushRegIfUsed (hc08_reg_a);
1344 loadRegFromAop (hc08_reg_a, aop, loffset);
1345 rmwWithReg (rmwop, hc08_reg_a);
1346 if (strcmp ("tst", rmwop))
1347 storeRegToAop (hc08_reg_a, aop, loffset);
1348 pullOrFreeReg (hc08_reg_a, needpula);
1353 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1359 /*-----------------------------------------------------------------*/
1360 /* newAsmop - creates a new asmOp */
1361 /*-----------------------------------------------------------------*/
1363 newAsmop (short type)
1367 aop = Safe_calloc (1, sizeof (asmop));
1374 /*-----------------------------------------------------------------*/
1375 /* pointerCode - returns the code for a pointer type */
1376 /*-----------------------------------------------------------------*/
1378 pointerCode (sym_link * etype)
1381 return PTR_TYPE (SPEC_OCLS (etype));
1386 /*-----------------------------------------------------------------*/
1387 /* aopForSym - for a true symbol */
1388 /*-----------------------------------------------------------------*/
1390 aopForSym (iCode * ic, symbol * sym, bool result)
1395 wassertl (ic != NULL, "Got a null iCode");
1396 wassertl (sym != NULL, "Got a null symbol");
1398 // printf("in aopForSym for symbol %s\n", sym->name);
1400 space = SPEC_OCLS (sym->etype);
1402 /* if already has one */
1408 /* special case for a function */
1409 if (IS_FUNC (sym->type))
1411 sym->aop = aop = newAsmop (AOP_IMMD);
1412 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1413 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1414 aop->size = FPTRSIZE;
1418 /* if it is in direct space */
1419 if (IN_DIRSPACE (space))
1421 sym->aop = aop = newAsmop (AOP_DIR);
1422 aop->aopu.aop_dir = sym->rname;
1423 aop->size = getSize (sym->type);
1427 /* if it is in far space */
1428 if (IN_FARSPACE (space))
1430 sym->aop = aop = newAsmop (AOP_EXT);
1431 aop->aopu.aop_dir = sym->rname;
1432 aop->size = getSize (sym->type);
1436 if (IN_STACK (sym->etype))
1438 sym->aop = aop = newAsmop (AOP_SOF);
1439 aop->aopu.aop_dir = sym->rname;
1440 aop->size = getSize (sym->type);
1441 aop->aopu.aop_stk = sym->stack;
1447 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1448 "aopForSym should never reach here");
1452 /* if it is in code space */
1453 if (IN_CODESPACE (space))
1459 /*-----------------------------------------------------------------*/
1460 /* aopForRemat - rematerialzes an object */
1461 /*-----------------------------------------------------------------*/
1463 aopForRemat (symbol * sym)
1465 iCode *ic = sym->rematiCode;
1473 val += (int) operandLitValue (IC_RIGHT (ic));
1474 else if (ic->op == '-')
1475 val -= (int) operandLitValue (IC_RIGHT (ic));
1476 else if (IS_CAST_ICODE(ic)) {
1477 sym_link *from_type = operandType(IC_RIGHT(ic));
1478 aop->aopu.aop_immd.from_cast_remat = 1;
1479 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1480 ptr_type = DCL_TYPE(from_type);
1481 if (ptr_type == IPOINTER) {
1488 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1491 if (ic->op == ADDRESS_OF)
1494 sprintf (buffer, "(%s %c 0x%04x)",
1495 OP_SYMBOL (IC_LEFT (ic))->rname,
1496 val >= 0 ? '+' : '-',
1497 abs (val) & 0xffff);
1499 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1501 aop = newAsmop (AOP_IMMD);
1502 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1503 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1504 /* set immd2 field if required */
1505 if (aop->aopu.aop_immd.from_cast_remat)
1507 sprintf(buffer,"#0x%02x",ptr_type);
1508 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1509 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1512 else if (ic->op == '=')
1514 val += (int) operandLitValue (IC_RIGHT (ic));
1516 sprintf (buffer, "0x%04x", val);
1517 aop = newAsmop (AOP_LIT);
1518 aop->aopu.aop_lit = constVal (buffer);
1521 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1522 "unexpected rematerialization");
1529 /*-----------------------------------------------------------------*/
1530 /* regsInCommon - two operands have some registers in common */
1531 /*-----------------------------------------------------------------*/
1533 regsInCommon (operand * op1, operand * op2)
1535 symbol *sym1, *sym2;
1538 /* if they have registers in common */
1539 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1542 sym1 = OP_SYMBOL (op1);
1543 sym2 = OP_SYMBOL (op2);
1545 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1548 for (i = 0; i < sym1->nRegs; i++)
1554 for (j = 0; j < sym2->nRegs; j++)
1559 if (sym2->regs[j] == sym1->regs[i])
1567 /*-----------------------------------------------------------------*/
1568 /* operandsEqu - equivalent */
1569 /*-----------------------------------------------------------------*/
1571 operandsEqu (operand * op1, operand * op2)
1573 symbol *sym1, *sym2;
1575 /* if they not symbols */
1576 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1579 sym1 = OP_SYMBOL (op1);
1580 sym2 = OP_SYMBOL (op2);
1582 /* if both are itemps & one is spilt
1583 and the other is not then false */
1584 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1585 sym1->isspilt != sym2->isspilt)
1588 /* if they are the same */
1592 if (sym1->rname[0] && sym2->rname[0]
1593 && strcmp (sym1->rname, sym2->rname) == 0)
1596 /* if left is a tmp & right is not */
1597 if (IS_ITEMP (op1) &&
1600 (sym1->usl.spillLoc == sym2))
1603 if (IS_ITEMP (op2) &&
1607 (sym2->usl.spillLoc == sym1))
1613 /*-----------------------------------------------------------------*/
1614 /* sameRegs - two asmops have the same registers */
1615 /*-----------------------------------------------------------------*/
1617 sameRegs (asmop * aop1, asmop * aop2)
1624 // if (aop1->size != aop2->size)
1627 if (aop1->type == aop2->type)
1632 for (i = 0; i < aop1->size; i++)
1633 if (aop1->aopu.aop_reg[i] !=
1634 aop2->aopu.aop_reg[i])
1638 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1641 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1648 /*-----------------------------------------------------------------*/
1649 /* aopOp - allocates an asmop for an operand : */
1650 /*-----------------------------------------------------------------*/
1652 aopOp (operand * op, iCode * ic, bool result)
1661 // Is this a pointer set result?
1663 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1667 // printf("checking literal\n");
1668 /* if this a literal */
1669 if (IS_OP_LITERAL (op))
1671 op->aop = aop = newAsmop (AOP_LIT);
1672 aop->aopu.aop_lit = op->operand.valOperand;
1673 aop->size = getSize (operandType (op));
1675 aop->isaddr = op->isaddr;
1679 // printf("checking pre-existing\n");
1680 /* if already has a asmop then continue */
1684 op->aop->isaddr = op->isaddr;
1688 // printf("checking underlying sym\n");
1689 /* if the underlying symbol has a aop */
1690 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1692 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1693 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1694 //op->aop = aop = OP_SYMBOL (op)->aop;
1695 aop->size = getSize( operandType (op));
1696 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1697 //printf (" with size = %d\n", aop->size);
1700 aop->isaddr = op->isaddr;
1701 /* if (aop->isaddr & IS_ITEMP (op))
1703 aop->psize=aop->size;
1704 aop->size = getSize( operandType (op)->next);
1709 // printf("checking true sym\n");
1710 /* if this is a true symbol */
1711 if (IS_TRUE_SYMOP (op))
1713 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1715 aop->isaddr = op->isaddr;
1716 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1717 //printf (" with size = %d\n", aop->size);
1721 /* this is a temporary : this has
1727 e) can be a return use only */
1729 sym = OP_SYMBOL (op);
1731 // printf("checking conditional\n");
1732 /* if the type is a conditional */
1733 if (sym->regType == REG_CND)
1735 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1738 aop->isaddr = op->isaddr;
1742 // printf("checking spilt\n");
1743 /* if it is spilt then two situations
1745 b) has a spill location */
1746 if (sym->isspilt || sym->nRegs == 0)
1749 // printf("checking remat\n");
1750 /* rematerialize it NOW */
1753 sym->aop = op->aop = aop =
1755 aop->size = getSize (sym->type);
1757 aop->isaddr = op->isaddr;
1758 /* if (aop->isaddr & IS_ITEMP (op))
1760 aop->psize=aop->size;
1761 aop->size = getSize( operandType (op)->next);
1766 // printf("checking accuse\n");
1769 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1770 aop->size = getSize (sym->type);
1771 switch (sym->accuse)
1774 aop->aopu.aop_reg[0] = hc08_reg_a;
1775 aop->aopu.aop_reg[1] = hc08_reg_x;
1778 aop->aopu.aop_reg[0] = hc08_reg_x;
1779 aop->aopu.aop_reg[1] = hc08_reg_h;
1783 aop->isaddr = op->isaddr;
1787 // printf("checking ruonly\n");
1793 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1794 aop->size = getSize (sym->type);
1795 for (i = 0; i < fReturnSizeHC08; i++)
1796 aop->aopu.aop_str[i] = fReturn2[i];
1798 aop->isaddr = op->isaddr;
1802 /* else spill location */
1803 if (sym->usl.spillLoc)
1805 asmop *oldAsmOp = NULL;
1807 if (sym->usl.spillLoc->aop
1808 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1810 /* force a new aop if sizes differ */
1811 oldAsmOp = sym->usl.spillLoc->aop;
1812 sym->usl.spillLoc->aop = NULL;
1813 //printf ("forcing new aop\n");
1815 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1816 if (sym->usl.spillLoc->aop->size != getSize (sym->type))
1818 /* Don't reuse the new aop, go with the last one */
1819 sym->usl.spillLoc->aop = oldAsmOp;
1821 aop->size = getSize (sym->type);
1823 aop->isaddr = op->isaddr;
1824 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1825 //printf (" with size = %d\n", aop->size);
1829 /* else must be a dummy iTemp */
1830 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1831 aop->size = getSize (sym->type);
1835 // printf("assuming register\n");
1836 /* must be in a register */
1837 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1838 aop->size = sym->nRegs;
1839 for (i = 0; i < sym->nRegs; i++)
1840 aop->aopu.aop_reg[i] = sym->regs[i];
1842 aop->isaddr = op->isaddr;
1846 /*-----------------------------------------------------------------*/
1847 /* freeAsmop - free up the asmop given to an operand */
1848 /*----------------------------------------------------------------*/
1850 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1872 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1875 for (loffset=0; loffset<aop->size; loffset++)
1876 if (aop->stk_aop[loffset])
1878 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1881 pullNull (stackAdjust);
1885 /* all other cases just dealloc */
1891 OP_SYMBOL (op)->aop = NULL;
1892 /* if the symbol has a spill */
1894 SPIL_LOC (op)->aop = NULL;
1900 /*-----------------------------------------------------------------*/
1901 /* aopDerefAop - treating the aop parameter as a pointer, return */
1902 /* an asmop for the object it references */
1903 /*-----------------------------------------------------------------*/
1905 aopDerefAop (asmop *aop)
1910 asmop *newaop = NULL;
1911 sym_link *type, *etype;
1914 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1918 type = operandType (aop->op);
1919 etype = getSpec (type);
1920 /* if op is of type of pointer then it is simple */
1921 if (IS_PTR (type) && !IS_FUNC (type->next))
1922 p_type = DCL_TYPE (type);
1925 /* we have to go by the storage class */
1926 p_type = PTR_TYPE (SPEC_OCLS (etype));
1935 if (p_type == POINTER)
1936 newaop = newAsmop (AOP_DIR);
1938 newaop = newAsmop (AOP_EXT);
1939 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1942 adr = (int) floatFromVal (aop->aopu.aop_lit);
1943 if (p_type == POINTER)
1948 newaop = newAsmop (AOP_DIR);
1949 sprintf (s, "0x%02x",adr);
1953 newaop = newAsmop (AOP_EXT);
1954 sprintf (s, "0x%04x",adr);
1956 rs = Safe_calloc (1, strlen (s) + 1);
1958 newaop->aopu.aop_dir = rs;
1961 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1962 "unsupported asmop");
1972 /*-----------------------------------------------------------------*/
1973 /* aopAdrStr - for referencing the address of the aop */
1974 /*-----------------------------------------------------------------*/
1976 aopAdrStr (asmop * aop, int loffset, bool bit16)
1980 int offset = aop->size - 1 - loffset;
1983 /* offset is greater than
1985 if (loffset > (aop->size - 1) &&
1986 aop->type != AOP_LIT)
1989 /* depending on type */
1997 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1998 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
2000 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
2004 sprintf (s, "#(%s >> %d)",
2005 aop->aopu.aop_immd.aop_immd1,
2009 aop->aopu.aop_immd.aop_immd1);
2013 aop->aopu.aop_immd.aop_immd1);
2014 rs = Safe_calloc (1, strlen (s) + 1);
2020 sprintf (s, "*(%s + %d)",
2024 sprintf (s, "*%s", aop->aopu.aop_dir);
2025 rs = Safe_calloc (1, strlen (s) + 1);
2031 sprintf (s, "(%s + %d)",
2035 sprintf (s, "%s", aop->aopu.aop_dir);
2036 rs = Safe_calloc (1, strlen (s) + 1);
2041 return aop->aopu.aop_reg[loffset]->name;
2045 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2047 return aopLiteral (aop->aopu.aop_lit, loffset);
2051 return aop->aopu.aop_str[loffset];
2054 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2056 rs = Safe_calloc (1, strlen (s) + 1);
2062 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2063 "aopAdrStr got unsupported aop->type");
2072 /*-----------------------------------------------------------------*/
2073 /* opIsGptr: returns non-zero if the passed operand is */
2074 /* a generic pointer type. */
2075 /*-----------------------------------------------------------------*/
2077 opIsGptr (operand * op)
2079 sym_link *type = operandType (op);
2081 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2089 /*-----------------------------------------------------------------*/
2090 /* getDataSize - get the operand data size */
2091 /*-----------------------------------------------------------------*/
2093 getDataSize (operand * op)
2096 size = AOP_SIZE (op);
2101 /*-----------------------------------------------------------------*/
2102 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2103 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2104 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2105 /*-----------------------------------------------------------------*/
2107 asmopToBool (asmop *aop, bool resultInA)
2109 symbol *tlbl, *tlbl1;
2110 int size = aop->size;
2111 bool needpula = FALSE;
2112 bool flagsonly = TRUE;
2117 hc08_freeReg(hc08_reg_a);
2124 emitcode ("tsta", "");
2127 else if (IS_AOP_X(aop))
2128 emitcode ("tstx", "");
2129 else if (IS_AOP_H(aop))
2131 if (hc08_reg_a->isFree)
2133 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2134 emitcode ("tsta", "");
2136 hc08_freeReg(hc08_reg_a);
2138 else if (hc08_reg_x->isFree)
2140 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2141 emitcode ("tstx", "");
2142 hc08_freeReg(hc08_reg_x);
2146 emitcode ("pshh", "");
2147 emitcode ("tst", "1,s");
2148 emitcode ("ais", "#1");
2151 else if (IS_AOP_HX(aop))
2152 emitcode ("cphx", zero);
2153 else if (IS_AOP_XA(aop))
2155 symbol *tlbl = newiTempLabel (NULL);
2156 emitcode ("tsta", "");
2157 emitcode ("bne", "%05d$", (tlbl->key + 100));
2158 emitcode ("tstx", "");
2159 emitcode ("", "%05d$:", (tlbl->key + 100));
2163 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2164 "Bad rIdx in asmToBool");
2172 needpula = pushRegIfUsed (hc08_reg_a);
2173 loadRegFromAop (hc08_reg_a, aop, 0);
2174 for (offset=1; offset<size; offset++)
2175 accopWithAop ("ora", aop, offset);
2177 pullReg (hc08_reg_a);
2180 hc08_freeReg (hc08_reg_a);
2185 /* Higher levels should optimize this case away but let's be safe */
2186 if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
2187 loadRegFromConst (hc08_reg_a, one);
2189 loadRegFromConst (hc08_reg_a, zero);
2190 hc08_freeReg(hc08_reg_a);
2197 loadRegFromAop (hc08_reg_a, aop, 0);
2198 hc08_freeReg (hc08_reg_a);
2202 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2207 if (hc08_reg_a->isFree)
2209 loadRegFromAop (hc08_reg_a, aop, 0);
2210 accopWithAop ("ora", aop, 1);
2211 hc08_freeReg (hc08_reg_a);
2216 tlbl = newiTempLabel (NULL);
2217 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2218 emitcode ("bne", "%05d$", (tlbl->key + 100));
2219 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2220 emitcode ("", "%05d$:", (tlbl->key + 100));
2226 needpula = pushRegIfUsed (hc08_reg_a);
2227 loadRegFromAop (hc08_reg_a, aop, 0);
2228 for (offset=1; offset<size; offset++)
2229 accopWithAop ("ora", aop, offset);
2231 pullReg (hc08_reg_a);
2234 hc08_freeReg (hc08_reg_a);
2242 tlbl = newiTempLabel (NULL);
2246 tlbl1 = newiTempLabel (NULL);
2247 emitBranch ("bne", tlbl1);
2248 loadRegFromConst (hc08_reg_a, zero);
2249 emitBranch ("bra", tlbl);
2251 loadRegFromConst (hc08_reg_a, one);
2255 emitBranch ("beq", tlbl);
2256 loadRegFromConst (hc08_reg_a, one);
2259 hc08_useReg (hc08_reg_a);
2265 /*-----------------------------------------------------------------*/
2266 /* genNot - generate code for ! operation */
2267 /*-----------------------------------------------------------------*/
2271 D(emitcode ("; genNot",""));
2273 /* assign asmOps to operand & result */
2274 aopOp (IC_LEFT (ic), ic, FALSE);
2275 aopOp (IC_RESULT (ic), ic, TRUE);
2277 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2278 emitcode ("eor", one);
2279 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2281 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2282 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2286 /*-----------------------------------------------------------------*/
2287 /* genCpl - generate code for complement */
2288 /*-----------------------------------------------------------------*/
2294 regs* reg = hc08_reg_a;
2298 D(emitcode ("; genCpl",""));
2300 /* assign asmOps to operand & result */
2301 aopOp (IC_LEFT (ic), ic, FALSE);
2302 aopOp (IC_RESULT (ic), ic, TRUE);
2304 size = AOP_SIZE (IC_RESULT (ic));
2307 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2308 rmwWithReg ("com", reg);
2310 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2315 /* release the aops */
2316 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2317 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2320 /*-----------------------------------------------------------------*/
2321 /* genUminusFloat - unary minus for floating points */
2322 /*-----------------------------------------------------------------*/
2324 genUminusFloat (operand * op, operand * result)
2326 int size, offset = 0;
2329 D(emitcode ("; genUminusFloat",""));
2331 /* for this we just copy and then flip the bit */
2333 size = AOP_SIZE (op) - 1;
2337 transferAopAop (AOP (op), offset, AOP (result), offset);
2341 needpula = pushRegIfUsed (hc08_reg_a);
2342 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2343 emitcode ("eor", "#0x80");
2344 hc08_useReg (hc08_reg_a);
2345 storeRegToAop (hc08_reg_a, AOP (result), offset);
2346 pullOrFreeReg (hc08_reg_a, needpula);
2349 /*-----------------------------------------------------------------*/
2350 /* genUminus - unary minus code generation */
2351 /*-----------------------------------------------------------------*/
2353 genUminus (iCode * ic)
2356 sym_link *optype, *rtype;
2361 D(emitcode ("; genUminus",""));
2364 aopOp (IC_LEFT (ic), ic, FALSE);
2365 aopOp (IC_RESULT (ic), ic, TRUE);
2367 optype = operandType (IC_LEFT (ic));
2368 rtype = operandType (IC_RESULT (ic));
2370 /* if float then do float stuff */
2371 if (IS_FLOAT (optype))
2373 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2377 /* otherwise subtract from zero */
2378 size = AOP_SIZE (IC_LEFT (ic));
2383 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2384 needpula = pushRegIfUsed (hc08_reg_a);
2387 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2388 emitcode ("nega", "");
2389 hc08_freeReg (hc08_reg_a);
2390 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2391 SPEC_USIGN (operandType (IC_LEFT (ic))));
2392 pullOrFreeReg (hc08_reg_a, needpula);
2396 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2397 result = forceStackedAop (AOP (IC_RESULT (ic)));
2399 result = AOP (IC_RESULT (ic));
2401 needpula = pushRegIfUsed (hc08_reg_a);
2405 loadRegFromConst (hc08_reg_a, zero);
2406 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2407 storeRegToAop (hc08_reg_a, result, offset++);
2410 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2411 SPEC_USIGN (operandType (IC_LEFT (ic))));
2412 pullOrFreeReg (hc08_reg_a, needpula);
2414 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2415 freeAsmop (NULL, result, ic, TRUE);
2421 /* release the aops */
2422 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2423 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2426 /*-----------------------------------------------------------------*/
2427 /* saveRegisters - will look for a call and save the registers */
2428 /*-----------------------------------------------------------------*/
2430 saveRegisters (iCode * lic)
2437 for (ic = lic; ic; ic = ic->next)
2438 if (ic->op == CALL || ic->op == PCALL)
2443 fprintf (stderr, "found parameter push with no function call\n");
2447 /* if the registers have been saved already or don't need to be then
2451 if (IS_SYMOP(IC_LEFT(ic)) &&
2452 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2453 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2456 /* safe the registers in use at this time but skip the
2457 ones for the result */
2458 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2459 hc08_rUmaskForOp (IC_RESULT(ic)));
2462 for (i = 0; i < hc08_nRegs; i++)
2464 if (bitVectBitValue (rsave, i))
2465 pushReg ( hc08_regWithIdx (i), FALSE);
2469 /*-----------------------------------------------------------------*/
2470 /* unsaveRegisters - pop the pushed registers */
2471 /*-----------------------------------------------------------------*/
2473 unsaveRegisters (iCode * ic)
2478 /* restore the registers in use at this time but skip the
2479 ones for the result */
2480 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2481 hc08_rUmaskForOp (IC_RESULT(ic)));
2483 for (i = hc08_nRegs; i >= 0; i--)
2485 if (bitVectBitValue (rsave, i))
2486 pullReg ( hc08_regWithIdx (i));
2492 /*-----------------------------------------------------------------*/
2494 /*-----------------------------------------------------------------*/
2496 pushSide (operand * oper, int size)
2501 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2502 pushReg ( hc08_reg_a, TRUE);
2506 /*-----------------------------------------------------------------*/
2507 /* assignResultValue - */
2508 /*-----------------------------------------------------------------*/
2510 assignResultValue (operand * oper)
2512 int size = AOP_SIZE (oper);
2516 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2517 if (hc08_aop_pass[offset]->type == AOP_REG)
2518 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2525 /*-----------------------------------------------------------------*/
2526 /* genIpush - genrate code for pushing this gets a little complex */
2527 /*-----------------------------------------------------------------*/
2529 genIpush (iCode * ic)
2531 int size, offset = 0;
2534 D(emitcode ("; genIpush",""));
2536 /* if this is not a parm push : ie. it is spill push
2537 and spill push is always done on the local stack */
2541 /* and the item is spilt then do nothing */
2542 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2545 aopOp (IC_LEFT (ic), ic, FALSE);
2546 size = AOP_SIZE (IC_LEFT (ic));
2548 /* push it on the stack */
2551 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2552 pushReg ( hc08_reg_a, TRUE);
2558 /* this is a paramter push: in this case we call
2559 the routine to find the call and save those
2560 registers that need to be saved */
2563 /* then do the push */
2564 aopOp (IC_LEFT (ic), ic, FALSE);
2567 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2568 size = AOP_SIZE (IC_LEFT (ic));
2571 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2572 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2574 if ((size==2) && hc08_reg_hx->isFree)
2576 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2577 pushReg (hc08_reg_hx, TRUE);
2584 // printf("loading %d\n", offset);
2585 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2586 // printf("pushing \n");
2587 pushReg (hc08_reg_a, TRUE);
2591 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2594 /*-----------------------------------------------------------------*/
2595 /* genIpop - recover the registers: can happen only for spilling */
2596 /*-----------------------------------------------------------------*/
2598 genIpop (iCode * ic)
2602 D(emitcode ("; genIpop",""));
2604 /* if the temp was not pushed then */
2605 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2608 aopOp (IC_LEFT (ic), ic, FALSE);
2609 size = AOP_SIZE (IC_LEFT (ic));
2613 pullReg (hc08_reg_a);
2614 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2616 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2620 /*-----------------------------------------------------------------*/
2621 /* genSend - gen code for SEND */
2622 /*-----------------------------------------------------------------*/
2623 static void genSend(set *sendSet)
2627 for (sic = setFirstItem (sendSet); sic;
2628 sic = setNextItem (sendSet)) {
2629 int size, offset = 0;
2630 aopOp (IC_LEFT (sic), sic, FALSE);
2631 size = AOP_SIZE (IC_LEFT (sic));
2636 transferAopAop( AOP (IC_LEFT (sic)), offset,
2637 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2641 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2645 /*-----------------------------------------------------------------*/
2646 /* genCall - generates a call statement */
2647 /*-----------------------------------------------------------------*/
2649 genCall (iCode * ic)
2652 // bool restoreBank = FALSE;
2653 // bool swapBanks = FALSE;
2655 D(emitcode("; genCall",""));
2657 dtype = operandType (IC_LEFT (ic));
2658 /* if send set is not empty then assign */
2661 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2662 genSend(reverseSet(_G.sendSet));
2664 genSend(_G.sendSet);
2670 /* if caller saves & we have not saved then */
2676 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2677 OP_SYMBOL (IC_LEFT (ic))->rname :
2678 OP_SYMBOL (IC_LEFT (ic))->name));
2681 /* if we need assign a result value */
2682 if ((IS_ITEMP (IC_RESULT (ic)) &&
2683 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2684 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2685 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2686 IS_TRUE_SYMOP (IC_RESULT (ic)))
2690 aopOp (IC_RESULT (ic), ic, FALSE);
2693 assignResultValue (IC_RESULT (ic));
2695 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2698 /* adjust the stack for parameters if
2702 pullNull (ic->parmBytes);
2705 /* if we had saved some registers then unsave them */
2706 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2707 unsaveRegisters (ic);
2711 /*-----------------------------------------------------------------*/
2712 /* -10l - generates a call by pointer statement */
2713 /*-----------------------------------------------------------------*/
2715 genPcall (iCode * ic)
2718 symbol *rlbl = newiTempLabel (NULL);
2719 symbol *tlbl = newiTempLabel (NULL);
2720 // bool restoreBank=FALSE;
2721 // bool swapBanks = FALSE;
2723 D(emitcode("; genPCall",""));
2725 /* if caller saves & we have not saved then */
2729 /* if we are calling a not _naked function that is not using
2730 the same register bank then we need to save the
2731 destination registers on the stack */
2732 dtype = operandType (IC_LEFT (ic))->next;
2734 /* now push the calling address */
2735 emitBranch ("bsr", tlbl);
2736 emitBranch ("bra", rlbl);
2739 /* Push the function's address */
2740 aopOp (IC_LEFT (ic), ic, FALSE);
2741 pushSide (IC_LEFT (ic), FPTRSIZE);
2742 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2744 /* if send set is not empty the assign */
2747 genSend(reverseSet(_G.sendSet));
2753 emitcode ("rts", "");
2758 /* if we need assign a result value */
2759 if ((IS_ITEMP (IC_RESULT (ic)) &&
2760 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2761 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2762 IS_TRUE_SYMOP (IC_RESULT (ic)))
2766 aopOp (IC_RESULT (ic), ic, FALSE);
2769 assignResultValue (IC_RESULT (ic));
2771 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2774 /* adjust the stack for parameters if
2778 pullNull (ic->parmBytes);
2781 /* if we hade saved some registers then
2783 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2784 unsaveRegisters (ic);
2787 /*-----------------------------------------------------------------*/
2788 /* resultRemat - result is rematerializable */
2789 /*-----------------------------------------------------------------*/
2791 resultRemat (iCode * ic)
2793 if (SKIP_IC (ic) || ic->op == IFX)
2796 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2798 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2799 if (sym->remat && !POINTER_SET (ic))
2806 #if defined(__BORLANDC__) || defined(_MSC_VER)
2807 #define STRCASECMP stricmp
2809 #define STRCASECMP strcasecmp
2812 /*-----------------------------------------------------------------*/
2813 /* inExcludeList - return 1 if the string is in exclude Reg list */
2814 /*-----------------------------------------------------------------*/
2816 regsCmp(void *p1, void *p2)
2818 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2822 inExcludeList (char *s)
2824 const char *p = setFirstItem(options.excludeRegsSet);
2826 if (p == NULL || STRCASECMP(p, "none") == 0)
2830 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2833 /*-----------------------------------------------------------------*/
2834 /* genFunction - generated code for function entry */
2835 /*-----------------------------------------------------------------*/
2837 genFunction (iCode * ic)
2839 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2841 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2842 int stackAdjust = sym->stack;
2843 int accIsFree = sym->recvSize == 0;
2847 /* create the function header */
2848 emitcode (";", "-----------------------------------------");
2849 emitcode (";", " function %s", sym->name);
2850 emitcode (";", "-----------------------------------------");
2852 emitcode ("", "%s:", sym->rname);
2853 ftype = operandType (IC_LEFT (ic));
2857 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2859 if (IFFUNC_ISNAKED(ftype))
2861 emitcode(";", "naked function: no prologue.");
2865 /* if this is an interrupt service routine then
2867 if (IFFUNC_ISISR (sym->type))
2870 if (!inExcludeList ("h"))
2871 pushReg (hc08_reg_h, FALSE);
2874 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2875 /* before setting up the stack frame completely. */
2876 while (ric && ric->next && ric->next->op == RECEIVE)
2878 while (ric && IC_RESULT (ric))
2880 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2881 int rsymSize = rsym ? getSize(rsym->type) : 0;
2885 if (rsym && rsym->regType == REG_CND)
2887 if (rsym && (rsym->accuse || rsym->ruonly))
2889 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2890 rsym = rsym->usl.spillLoc;
2893 /* If the RECEIVE operand immediately spills to the first entry on the */
2894 /* stack, we can push it directly rather than use an sp relative store. */
2895 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2899 _G.current_iCode = ric;
2900 D(emitcode ("; genReceive",""));
2901 for (ofs=0; ofs < rsymSize; ofs++)
2903 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2904 pushReg (reg, TRUE);
2905 if (reg->rIdx == A_IDX)
2909 _G.current_iCode = ic;
2912 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2915 /* adjust the stack for the function */
2918 adjustStack (-stackAdjust);
2920 _G.stackOfs = sym->stack;
2923 /* if critical function then turn interrupts off */
2924 if (IFFUNC_ISCRITICAL (ftype))
2928 /* Function was passed parameters, so make sure A is preserved */
2929 pushReg (hc08_reg_a, FALSE);
2930 pushReg (hc08_reg_a, FALSE);
2931 emitcode ("tpa", "");
2932 emitcode ("sta", "2,s");
2933 emitcode ("sei", "");
2934 pullReg (hc08_reg_a);
2938 /* No passed parameters, so A can be freely modified */
2939 emitcode ("tpa", "");
2940 pushReg (hc08_reg_a, TRUE);
2941 emitcode ("sei", "");
2947 /*-----------------------------------------------------------------*/
2948 /* genEndFunction - generates epilogue for functions */
2949 /*-----------------------------------------------------------------*/
2951 genEndFunction (iCode * ic)
2953 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2955 if (IFFUNC_ISNAKED(sym->type))
2957 emitcode(";", "naked function: no epilogue.");
2958 if (options.debug && currFunc)
2959 debugFile->writeEndFunction (currFunc, ic, 0);
2963 if (IFFUNC_ISCRITICAL (sym->type))
2965 if (!IS_VOID(sym->type->next))
2967 /* Function has return value, so make sure A is preserved */
2968 pushReg (hc08_reg_a, FALSE);
2969 emitcode ("lda", "2,s");
2970 emitcode ("tap", "");
2971 pullReg (hc08_reg_a);
2976 /* Function returns void, so A can be freely modified */
2977 pullReg (hc08_reg_a);
2978 emitcode ("tap", "");
2982 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2988 _G.stackPushes += sym->stack;
2989 adjustStack (sym->stack);
2993 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2997 if (IFFUNC_ISISR (sym->type))
3000 if (!inExcludeList ("h"))
3001 pullReg (hc08_reg_h);
3004 /* if debug then send end of function */
3005 if (options.debug && currFunc)
3007 debugFile->writeEndFunction (currFunc, ic, 1);
3010 emitcode ("rti", "");
3014 if (IFFUNC_CALLEESAVES(sym->type))
3018 /* if any registers used */
3021 /* save the registers used */
3022 for (i = sym->regsUsed->size; i >= 0; i--)
3024 if (bitVectBitValue (sym->regsUsed, i) ||
3025 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3026 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3032 /* if debug then send end of function */
3033 if (options.debug && currFunc)
3035 debugFile->writeEndFunction (currFunc, ic, 1);
3038 emitcode ("rts", "");
3043 /*-----------------------------------------------------------------*/
3044 /* genRet - generate code for return statement */
3045 /*-----------------------------------------------------------------*/
3049 int size, offset = 0;
3052 D(emitcode ("; genRet",""));
3054 /* if we have no return value then
3055 just generate the "ret" */
3059 /* we have something to return then
3060 move the return value into place */
3061 aopOp (IC_LEFT (ic), ic, FALSE);
3062 size = AOP_SIZE (IC_LEFT (ic));
3068 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3075 /* 4 byte return: store value in the global return variable */
3079 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3080 STA (fReturn2[offset--], FALSE);
3081 hc08_freeReg (hc08_reg_a);
3085 /* 2 byte return: store value in x:a */
3086 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3087 hc08_freeReg (hc08_reg_xa);
3090 /* 1 byte return: store value in a */
3091 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3092 hc08_freeReg (hc08_reg_a);
3097 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3100 /* generate a jump to the return label
3101 if the next is not the return statement */
3102 if (!(ic->next && ic->next->op == LABEL &&
3103 IC_LABEL (ic->next) == returnLabel))
3105 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3109 /*-----------------------------------------------------------------*/
3110 /* genLabel - generates a label */
3111 /*-----------------------------------------------------------------*/
3113 genLabel (iCode * ic)
3118 /* For the high level labels we cannot depend on any */
3119 /* register's contents. Amnesia time. */
3120 for (i=A_IDX;i<=XA_IDX;i++)
3122 reg = hc08_regWithIdx(i);
3127 /* special case never generate */
3128 if (IC_LABEL (ic) == entryLabel)
3131 debugFile->writeLabel(IC_LABEL (ic), ic);
3133 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3137 /*-----------------------------------------------------------------*/
3138 /* genGoto - generates a jmp */
3139 /*-----------------------------------------------------------------*/
3141 genGoto (iCode * ic)
3143 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3147 /*-----------------------------------------------------------------*/
3148 /* findLabelBackwards: walks back through the iCode chain looking */
3149 /* for the given label. Returns number of iCode instructions */
3150 /* between that label and given ic. */
3151 /* Returns zero if label not found. */
3152 /*-----------------------------------------------------------------*/
3154 findLabelBackwards (iCode * ic, int key)
3163 /* If we have any pushes or pops, we cannot predict the distance.
3164 I don't like this at all, this should be dealt with in the
3166 if (ic->op == IPUSH || ic->op == IPOP) {
3170 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3180 /*-----------------------------------------------------------------*/
3181 /* genPlusIncr :- does addition with increment if possible */
3182 /*-----------------------------------------------------------------*/
3184 genPlusIncr (iCode * ic)
3192 unsigned int size = getDataSize (IC_RESULT (ic));
3193 unsigned int offset;
3194 symbol *tlbl = NULL;
3196 left = IC_LEFT (ic);
3197 result = IC_RESULT (ic);
3199 /* will try to generate an increment */
3200 /* if the right side is not a literal
3202 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3205 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3207 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3209 if ((IS_AOP_HX (AOP (left)) ||
3210 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3212 && (icount>=-128) && (icount<=127) && (size==2))
3214 if (!IS_AOP_HX (AOP (left)))
3216 needpulx = pushRegIfUsed (hc08_reg_x);
3217 needpulh = pushRegIfUsed (hc08_reg_h);
3224 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3225 emitcode ("aix","#%d", icount);
3226 hc08_dirtyReg (hc08_reg_hx, FALSE);
3227 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3228 pullOrFreeReg (hc08_reg_h, needpulh);
3229 pullOrFreeReg (hc08_reg_x, needpulx);
3233 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3234 sameRegs (AOP (left), AOP (result))));
3236 if ((icount > 255) || (icount<0))
3239 if (!sameRegs (AOP (left), AOP (result)))
3242 D(emitcode ("; genPlusIncr",""));
3245 tlbl = newiTempLabel (NULL);
3250 rmwWithAop ("inc", AOP (result), 0);
3252 emitBranch ("bne", tlbl);
3256 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3257 needpula = pushRegIfUsed (hc08_reg_a);
3260 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3261 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3262 hc08_useReg (hc08_reg_a);
3263 storeRegToAop (hc08_reg_a, AOP (result), 0);
3264 hc08_freeReg (hc08_reg_a);
3266 emitBranch ("bcc", tlbl);
3268 for (offset=1; offset<size; offset++)
3270 rmwWithAop ("inc", AOP (result), offset);
3271 if ((offset+1)<size)
3272 emitBranch ("bne", tlbl);
3278 pullOrFreeReg (hc08_reg_a, needpula);
3285 /*-----------------------------------------------------------------*/
3286 /* genPlus - generates code for addition */
3287 /*-----------------------------------------------------------------*/
3289 genPlus (iCode * ic)
3291 int size, offset = 0;
3293 asmop *leftOp, *rightOp;
3295 /* special cases :- */
3297 D(emitcode ("; genPlus",""));
3299 aopOp (IC_LEFT (ic), ic, FALSE);
3300 aopOp (IC_RIGHT (ic), ic, FALSE);
3301 aopOp (IC_RESULT (ic), ic, TRUE);
3303 /* we want registers on the left and literals on the right */
3304 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3305 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3307 operand *t = IC_RIGHT (ic);
3308 IC_RIGHT (ic) = IC_LEFT (ic);
3313 /* if I can do an increment instead
3314 of add then GOOD for ME */
3315 if (genPlusIncr (ic) == TRUE)
3318 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3319 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3320 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3322 size = getDataSize (IC_RESULT (ic));
3324 leftOp = AOP(IC_LEFT(ic));
3325 rightOp = AOP(IC_RIGHT(ic));
3331 loadRegFromAop (hc08_reg_a, leftOp, offset);
3332 accopWithAop(add, rightOp, offset);
3333 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3334 hc08_freeReg (hc08_reg_a);
3335 add = "adc"; /* further adds must propagate carry */
3339 // adjustArithmeticResult (ic);
3342 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3343 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3344 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3347 /*-----------------------------------------------------------------*/
3348 /* genMinusDec :- does subtraction with decrement if possible */
3349 /*-----------------------------------------------------------------*/
3351 genMinusDec (iCode * ic)
3353 unsigned int icount;
3358 unsigned int size = getDataSize (IC_RESULT (ic));
3362 left = IC_LEFT (ic);
3363 result = IC_RESULT (ic);
3365 /* will try to generate an increment */
3366 /* if the right side is not a literal
3368 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3371 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3373 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3374 && (icount>=-127) && (icount<=128) && (size==2))
3376 if (!IS_AOP_HX (AOP (left)))
3378 needpulx = pushRegIfUsed (hc08_reg_x);
3379 needpulh = pushRegIfUsed (hc08_reg_h);
3386 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3387 emitcode ("aix","#%d", -icount);
3388 hc08_dirtyReg (hc08_reg_hx, FALSE);
3389 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3390 pullOrFreeReg (hc08_reg_h, needpulh);
3391 pullOrFreeReg (hc08_reg_x, needpulx);
3395 if ((icount > 1) || (icount<0))
3398 if (!sameRegs (AOP (left), AOP (result)))
3404 D(emitcode ("; genMinusDec",""));
3406 rmwWithAop ("dec", AOP (result), 0);
3411 /*-----------------------------------------------------------------*/
3412 /* addSign - complete with sign */
3413 /*-----------------------------------------------------------------*/
3415 addSign (operand * result, int offset, int sign)
3417 int size = (getDataSize (result) - offset);
3422 emitcode ("rola", "");
3423 emitcode ("clra", "");
3424 emitcode ("sbc", zero);
3426 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3430 storeConstToAop (zero, AOP (result), offset++);
3435 /*-----------------------------------------------------------------*/
3436 /* genMinus - generates code for subtraction */
3437 /*-----------------------------------------------------------------*/
3439 genMinus (iCode * ic)
3442 int size, offset = 0;
3444 asmop *leftOp, *rightOp;
3446 D(emitcode ("; genMinus",""));
3448 aopOp (IC_LEFT (ic), ic, FALSE);
3449 aopOp (IC_RIGHT (ic), ic, FALSE);
3450 aopOp (IC_RESULT (ic), ic, TRUE);
3452 /* special cases :- */
3453 /* if I can do an decrement instead
3454 of subtract then GOOD for ME */
3455 if (genMinusDec (ic) == TRUE)
3458 size = getDataSize (IC_RESULT (ic));
3461 leftOp = AOP(IC_LEFT(ic));
3462 rightOp = AOP(IC_RIGHT(ic));
3466 if (IS_AOP_A (rightOp))
3468 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3469 accopWithAop (sub, leftOp, offset);
3470 accopWithMisc ("nega", "");
3471 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3477 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3478 accopWithAop (sub, rightOp, offset);
3479 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3484 // adjustArithmeticResult (ic);
3487 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3488 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3489 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3494 /*-----------------------------------------------------------------*/
3495 /* genMultOneByte : 8*8=8/16 bit multiplication */
3496 /*-----------------------------------------------------------------*/
3498 genMultOneByte (operand * left,
3502 /* sym_link *opetype = operandType (result); */
3503 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3504 int size=AOP_SIZE(result);
3505 bool negLiteral = FALSE;
3506 bool lUnsigned, rUnsigned;
3508 D(emitcode ("; genMultOneByte",""));
3510 if (size<1 || size>2) {
3511 // this should never happen
3512 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3513 AOP_SIZE(result), __FILE__, lineno);
3517 /* (if two literals: the value is computed before) */
3518 /* if one literal, literal on the right */
3519 if (AOP_TYPE (left) == AOP_LIT)
3525 /* if an operand is in A, make sure it is on the left */
3526 if (IS_AOP_A (AOP (right)))
3533 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3534 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3536 /* lUnsigned rUnsigned negLiteral negate case */
3537 /* false false false odd 3 */
3538 /* false false true even 3 */
3539 /* false true false odd 3 */
3540 /* false true true impossible */
3541 /* true false false odd 3 */
3542 /* true false true always 2 */
3543 /* true true false never 1 */
3544 /* true true true impossible */
3548 || (lUnsigned && rUnsigned))
3550 // just an unsigned 8*8=8/16 multiply
3551 //D(emitcode (";","unsigned"));
3553 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3554 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3555 emitcode ("mul", "");
3556 hc08_dirtyReg (hc08_reg_xa, FALSE);
3557 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3558 hc08_freeReg (hc08_reg_xa);
3563 // we have to do a signed multiply
3566 /* left unsigned, right signed literal -- literal determines sign handling */
3567 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3569 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3571 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3573 emitcode ("ldx", "#0x%02x", -val);
3575 emitcode ("ldx", "#0x%02x", val);
3577 emitcode ("mul", "");
3581 rmwWithReg ("neg", hc08_reg_a);
3582 tlbl4 = newiTempLabel (NULL);
3583 emitBranch ("bcc", tlbl4);
3584 rmwWithReg ("inc", hc08_reg_x);
3586 rmwWithReg ("neg", hc08_reg_x);
3589 hc08_dirtyReg (hc08_reg_xa, FALSE);
3590 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3591 hc08_freeReg (hc08_reg_xa);
3598 emitcode ("clr", "1,s");
3600 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3603 tlbl1 = newiTempLabel (NULL);
3604 emitcode ("tsta","");
3605 emitBranch ("bpl", tlbl1);
3606 emitcode ("inc", "1,s");
3607 rmwWithReg ("neg", hc08_reg_a);
3611 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3613 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3614 /* AND literal negative */
3616 emitcode ("ldx", "#0x%02x", -val);
3619 emitcode ("ldx", "#0x%02x", val);
3621 hc08_useReg (hc08_reg_x);
3625 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3628 tlbl2 = newiTempLabel (NULL);
3629 emitcode ("tstx", "");
3630 emitBranch ("bpl", tlbl2);
3631 emitcode ("inc", "1,s");
3632 rmwWithReg ("neg", hc08_reg_x);
3637 emitcode ("mul", "");
3638 hc08_dirtyReg (hc08_reg_xa, FALSE);
3640 tlbl3 = newiTempLabel (NULL);
3641 emitcode ("dec", "1,s");
3642 if (!lUnsigned && !rUnsigned && negLiteral)
3643 emitBranch ("beq", tlbl3);
3645 emitBranch ("bne", tlbl3);
3647 rmwWithReg ("neg", hc08_reg_a);
3648 tlbl4 = newiTempLabel (NULL);
3649 emitBranch ("bcc", tlbl4);
3650 rmwWithReg ("inc", hc08_reg_x);
3652 rmwWithReg ("neg", hc08_reg_x);
3656 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3657 hc08_freeReg (hc08_reg_xa);
3661 /*-----------------------------------------------------------------*/
3662 /* genMult - generates code for multiplication */
3663 /*-----------------------------------------------------------------*/
3665 genMult (iCode * ic)
3667 operand *left = IC_LEFT (ic);
3668 operand *right = IC_RIGHT (ic);
3669 operand *result = IC_RESULT (ic);
3671 D(emitcode ("; genMult",""));
3673 /* assign the amsops */
3674 aopOp (left, ic, FALSE);
3675 aopOp (right, ic, FALSE);
3676 aopOp (result, ic, TRUE);
3678 /* special cases first */
3679 /* if both are of size == 1 */
3680 // if (getSize(operandType(left)) == 1 &&
3681 // getSize(operandType(right)) == 1)
3682 if (AOP_SIZE (left) == 1 &&
3683 AOP_SIZE (right) == 1)
3685 genMultOneByte (left, right, result);
3689 /* should have been converted to function call */
3690 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3691 getSize(OP_SYMBOL(right)->type));
3692 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3697 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3698 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3699 freeAsmop (result, NULL, ic, TRUE);
3702 /*-----------------------------------------------------------------*/
3703 /* genDivOneByte : 8 bit division */
3704 /*-----------------------------------------------------------------*/
3706 genDivOneByte (operand * left,
3710 symbol *tlbl1, *tlbl2, *tlbl3;
3713 bool lUnsigned, rUnsigned;
3714 bool runtimeSign, compiletimeSign;
3716 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3717 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3719 D(emitcode ("; genDivOneByte",""));
3721 size = AOP_SIZE (result);
3722 /* signed or unsigned */
3723 if (lUnsigned && rUnsigned)
3725 /* unsigned is easy */
3726 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3727 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3728 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3729 emitcode ("div", "");
3730 hc08_dirtyReg (hc08_reg_a, FALSE);
3731 hc08_dirtyReg (hc08_reg_h, FALSE);
3732 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3733 hc08_freeReg (hc08_reg_a);
3734 hc08_freeReg (hc08_reg_x);
3735 hc08_freeReg (hc08_reg_h);
3739 /* signed is a little bit more difficult */
3741 /* now sign adjust for both left & right */
3743 /* let's see what's needed: */
3744 /* apply negative sign during runtime */
3745 runtimeSign = FALSE;
3746 /* negative sign from literals */
3747 compiletimeSign = FALSE;
3751 if (AOP_TYPE(left) == AOP_LIT)
3753 /* signed literal */
3754 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3756 compiletimeSign = TRUE;
3759 /* signed but not literal */
3765 if (AOP_TYPE(right) == AOP_LIT)
3767 /* signed literal */
3768 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3770 compiletimeSign ^= TRUE;
3773 /* signed but not literal */
3777 /* initialize the runtime sign */
3780 if (compiletimeSign)
3781 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3783 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3784 pushReg (hc08_reg_x, TRUE);
3787 /* save the signs of the operands */
3788 if (AOP_TYPE(right) == AOP_LIT)
3790 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3792 if (!rUnsigned && val < 0)
3793 emitcode ("ldx", "#0x%02x", -val);
3795 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3797 else /* ! literal */
3799 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3802 tlbl1 = newiTempLabel (NULL);
3803 emitcode ("tstx", "");
3804 emitBranch ("bpl", tlbl1);
3805 emitcode ("inc", "1,s");
3806 rmwWithReg ("neg", hc08_reg_x);
3811 if (AOP_TYPE(left) == AOP_LIT)
3813 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3815 if (!lUnsigned && val < 0)
3816 emitcode ("lda", "#0x%02x", -val);
3818 emitcode ("lda", "#0x%02x", (unsigned char) val);
3820 else /* ! literal */
3822 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3825 tlbl2 = newiTempLabel (NULL);
3826 emitcode ("tsta", "");
3827 emitBranch ("bpl", tlbl2);
3828 emitcode ("inc", "1,s");
3829 rmwWithReg ("neg", hc08_reg_a);
3834 loadRegFromConst (hc08_reg_h, zero);
3835 emitcode ("div", "");
3836 hc08_dirtyReg (hc08_reg_x, FALSE);
3837 hc08_dirtyReg (hc08_reg_a, FALSE);
3838 hc08_dirtyReg (hc08_reg_h, FALSE);
3840 if (runtimeSign || compiletimeSign)
3842 tlbl3 = newiTempLabel (NULL);
3845 pullReg (hc08_reg_x);
3846 rmwWithReg ("lsr", hc08_reg_x);
3847 rmwWithReg ("ror", hc08_reg_x);
3848 emitBranch ("bpl", tlbl3);
3851 rmwWithReg ("neg", hc08_reg_a);
3855 storeRegToAop (hc08_reg_a, AOP (result), 0);
3859 /* msb is 0x00 or 0xff depending on the sign */
3862 rmwWithReg ("lsl", hc08_reg_x);
3863 emitcode ("clra", "");
3864 emitcode ("sbc", "#0");
3866 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3868 else /* compiletimeSign */
3870 storeConstToAop ("#0xff", AOP (result), ++offset);
3875 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3878 hc08_freeReg (hc08_reg_a);
3879 hc08_freeReg (hc08_reg_x);
3880 hc08_freeReg (hc08_reg_h);
3883 /*-----------------------------------------------------------------*/
3884 /* genDiv - generates code for division */
3885 /*-----------------------------------------------------------------*/
3889 operand *left = IC_LEFT (ic);
3890 operand *right = IC_RIGHT (ic);
3891 operand *result = IC_RESULT (ic);
3893 D(emitcode ("; genDiv",""));
3895 /* assign the amsops */
3896 aopOp (left, ic, FALSE);
3897 aopOp (right, ic, FALSE);
3898 aopOp (result, ic, TRUE);
3900 /* special cases first */
3901 /* if both are of size == 1 */
3902 if (AOP_SIZE (left) <= 2 &&
3903 AOP_SIZE (right) == 1)
3905 genDivOneByte (left, right, result);
3909 /* should have been converted to function call */
3912 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3913 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3914 freeAsmop (result, NULL, ic, TRUE);
3917 /*-----------------------------------------------------------------*/
3918 /* genModOneByte : 8 bit modulus */
3919 /*-----------------------------------------------------------------*/
3921 genModOneByte (operand * left,
3925 symbol *tlbl1, *tlbl2, *tlbl3;
3928 bool lUnsigned, rUnsigned;
3929 bool runtimeSign, compiletimeSign;
3931 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3932 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3934 D(emitcode ("; genModOneByte",""));
3936 size = AOP_SIZE (result);
3938 if (lUnsigned && rUnsigned)
3940 /* unsigned is easy */
3941 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3942 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3943 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3944 emitcode ("div", "");
3945 hc08_freeReg (hc08_reg_a);
3946 hc08_freeReg (hc08_reg_x);
3947 hc08_dirtyReg (hc08_reg_h, FALSE);
3948 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3949 hc08_freeReg (hc08_reg_h);
3953 /* signed is a little bit more difficult */
3955 if (AOP_TYPE(right) == AOP_LIT)
3957 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3959 if (!rUnsigned && val < 0)
3960 emitcode ("ldx", "#0x%02x", -val);
3962 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3964 else /* ! literal */
3966 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3969 tlbl1 = newiTempLabel (NULL);
3970 emitcode ("tstx", "");
3971 emitBranch ("bpl", tlbl1);
3972 rmwWithReg ("neg", hc08_reg_x);
3977 /* let's see what's needed: */
3978 /* apply negative sign during runtime */
3979 runtimeSign = FALSE;
3980 /* negative sign from literals */
3981 compiletimeSign = FALSE;
3983 /* sign adjust left side */
3984 if (AOP_TYPE(left) == AOP_LIT)
3986 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3988 if (!lUnsigned && val < 0)
3990 compiletimeSign = TRUE; /* set sign flag */
3991 emitcode ("lda", "#0x%02x", -val);
3994 emitcode ("lda", "#0x%02x", (unsigned char) val);
3996 else /* ! literal */
3999 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4004 emitcode ("clr", "1,s");
4006 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4007 tlbl2 = newiTempLabel (NULL);
4008 emitcode ("tsta", "");
4009 emitBranch ("bpl", tlbl2);
4010 emitcode ("inc", "1,s");
4011 rmwWithReg ("neg", hc08_reg_a);
4016 loadRegFromConst (hc08_reg_h, zero);
4017 emitcode ("div", "");
4018 hc08_freeReg (hc08_reg_a);
4019 hc08_freeReg (hc08_reg_x);
4020 hc08_dirtyReg (hc08_reg_h, FALSE);
4022 if (runtimeSign || compiletimeSign)
4024 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4025 tlbl3 = newiTempLabel (NULL);
4028 pullReg (hc08_reg_x);
4029 rmwWithReg ("lsr", hc08_reg_x);
4030 rmwWithReg ("ror", hc08_reg_x);
4031 emitBranch ("bpl", tlbl3);
4034 rmwWithReg ("neg", hc08_reg_a);
4038 storeRegToAop (hc08_reg_a, AOP (result), 0);
4042 /* msb is 0x00 or 0xff depending on the sign */
4045 rmwWithReg ("lsl", hc08_reg_x);
4046 emitcode ("clra", "");
4047 emitcode ("sbc", "#0");
4049 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4051 else /* compiletimeSign */
4053 storeConstToAop ("#0xff", AOP (result), ++offset);
4058 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4061 hc08_freeReg (hc08_reg_a);
4062 hc08_freeReg (hc08_reg_x);
4063 hc08_freeReg (hc08_reg_h);
4066 /*-----------------------------------------------------------------*/
4067 /* genMod - generates code for division */
4068 /*-----------------------------------------------------------------*/
4072 operand *left = IC_LEFT (ic);
4073 operand *right = IC_RIGHT (ic);
4074 operand *result = IC_RESULT (ic);
4076 D(emitcode ("; genMod",""));
4078 /* assign the amsops */
4079 aopOp (left, ic, FALSE);
4080 aopOp (right, ic, FALSE);
4081 aopOp (result, ic, TRUE);
4083 /* special cases first */
4084 /* if both are of size == 1 */
4085 if (AOP_SIZE (left) <= 2 &&
4086 AOP_SIZE (right) == 1)
4088 genModOneByte (left, right, result);
4092 /* should have been converted to function call */
4096 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4097 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4098 freeAsmop (result, NULL, ic, TRUE);
4101 /*-----------------------------------------------------------------*/
4102 /* genIfxJump :- will create a jump depending on the ifx */
4103 /*-----------------------------------------------------------------*/
4105 genIfxJump (iCode * ic, char *jval)
4108 symbol *tlbl = newiTempLabel (NULL);
4111 D(emitcode ("; genIfxJump",""));
4113 /* if true label then we jump if condition
4117 jlbl = IC_TRUE (ic);
4118 if (!strcmp (jval, "a"))
4120 else if (!strcmp (jval, "c"))
4127 /* false label is present */
4128 jlbl = IC_FALSE (ic);
4129 if (!strcmp (jval, "a"))
4131 else if (!strcmp (jval, "c"))
4136 emitBranch (inst, tlbl);
4137 emitBranch ("jmp", jlbl);
4140 /* mark the icode as generated */
4145 /*-----------------------------------------------------------------*/
4146 /* exchangedCmp : returns the opcode need if the two operands are */
4147 /* exchanged in a comparison */
4148 /*-----------------------------------------------------------------*/
4150 exchangedCmp (int opcode)
4167 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4168 "opcode not a comparison");
4170 return EQ_OP; /* shouldn't happen, but need to return something */
4173 /*------------------------------------------------------------------*/
4174 /* negatedCmp : returns the equivalent opcode for when a comparison */
4176 /*------------------------------------------------------------------*/
4178 negatedCmp (int opcode)
4195 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4196 "opcode not a comparison");
4198 return EQ_OP; /* shouldn't happen, but need to return something */
4201 /* compile only if the debugging macro D is enabled */
4204 nameCmp (int opcode)
4226 /*------------------------------------------------------------------*/
4227 /* branchInstCmp : returns the conditional branch instruction that */
4228 /* will branch if the comparison is true */
4229 /*------------------------------------------------------------------*/
4231 branchInstCmp (int opcode, int sign)
4239 return "bcs"; /* same as blo */
4254 return "bcc"; /* same as bhs */
4260 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4261 "opcode not a comparison");
4267 /*------------------------------------------------------------------*/
4268 /* genCmp :- greater or less than (and maybe with equal) comparison */
4269 /*------------------------------------------------------------------*/
4271 genCmp (iCode * ic, iCode * ifx)
4273 operand *left, *right, *result;
4274 sym_link *letype, *retype;
4276 int size, offset = 0;
4277 unsigned long lit = 0L;
4279 symbol *jlbl = NULL;
4283 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4285 result = IC_RESULT (ic);
4286 left = IC_LEFT (ic);
4287 right = IC_RIGHT (ic);
4289 letype = getSpec (operandType (left));
4290 retype = getSpec (operandType (right));
4291 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4292 /* assign the amsops */
4293 aopOp (left, ic, FALSE);
4294 aopOp (right, ic, FALSE);
4295 aopOp (result, ic, TRUE);
4297 /* need register operand on left, prefer literal operand on right */
4298 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4300 operand *temp = left;
4303 opcode = exchangedCmp (opcode);
4310 jlbl = IC_TRUE (ifx);
4311 opcode = negatedCmp (opcode);
4315 /* false label is present */
4316 jlbl = IC_FALSE (ifx);
4320 size = max (AOP_SIZE (left), AOP_SIZE (right));
4323 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4324 && ((AOP_TYPE (right) == AOP_LIT) ||
4325 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4326 && hc08_reg_hx->isFree)
4328 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4329 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4330 hc08_freeReg (hc08_reg_hx);
4341 /* These conditions depend on the Z flag bit, but Z is */
4342 /* only valid for the last byte of the comparison, not */
4343 /* the whole value. So exchange the operands to get a */
4344 /* comparison that doesn't depend on Z. (This is safe */
4345 /* to do here since ralloc won't assign multi-byte */
4346 /* operands to registers for comparisons) */
4347 if ((opcode == '>') || (opcode == LE_OP))
4349 operand *temp = left;
4352 opcode = exchangedCmp (opcode);
4355 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4357 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4358 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4367 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4368 accopWithAop (sub, AOP (right), offset);
4369 hc08_freeReg (hc08_reg_a);
4374 freeAsmop (right, NULL, ic, FALSE);
4375 freeAsmop (left, NULL, ic, FALSE);
4379 symbol *tlbl = newiTempLabel (NULL);
4382 freeAsmop (result, NULL, ic, TRUE);
4384 inst = branchInstCmp (opcode, sign);
4385 emitBranch (inst, tlbl);
4386 emitBranch ("jmp", jlbl);
4389 /* mark the icode as generated */
4394 symbol *tlbl1 = newiTempLabel (NULL);
4395 symbol *tlbl2 = newiTempLabel (NULL);
4397 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4398 loadRegFromConst (hc08_reg_a, zero);
4399 emitBranch ("bra", tlbl2);
4401 loadRegFromConst (hc08_reg_a, one);
4403 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4404 freeAsmop (result, NULL, ic, TRUE);
4409 /*-----------------------------------------------------------------*/
4410 /* genCmpEQorNE - equal or not equal comparison */
4411 /*-----------------------------------------------------------------*/
4413 genCmpEQorNE (iCode * ic, iCode * ifx)
4415 operand *left, *right, *result;
4416 sym_link *letype, *retype;
4418 int size, offset = 0;
4420 symbol *jlbl = NULL;
4421 symbol *tlbl_NE = NULL;
4422 symbol *tlbl_EQ = NULL;
4426 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4428 result = IC_RESULT (ic);
4429 left = IC_LEFT (ic);
4430 right = IC_RIGHT (ic);
4432 letype = getSpec (operandType (left));
4433 retype = getSpec (operandType (right));
4434 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4435 /* assign the amsops */
4436 aopOp (left, ic, FALSE);
4437 aopOp (right, ic, FALSE);
4438 aopOp (result, ic, TRUE);
4440 /* need register operand on left, prefer literal operand on right */
4441 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4443 operand *temp = left;
4446 opcode = exchangedCmp (opcode);
4453 jlbl = IC_TRUE (ifx);
4454 opcode = negatedCmp (opcode);
4458 /* false label is present */
4459 jlbl = IC_FALSE (ifx);
4463 size = max (AOP_SIZE (left), AOP_SIZE (right));
4466 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4467 && ((AOP_TYPE (right) == AOP_LIT) ||
4468 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4469 && hc08_reg_hx->isFree)
4471 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4472 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4473 hc08_freeReg (hc08_reg_hx);
4481 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4482 accopWithAop (sub, AOP (right), offset);
4486 tlbl_NE = newiTempLabel (NULL);
4487 emitBranch ("bne", tlbl_NE);
4489 hc08_freeReg (hc08_reg_a);
4493 freeAsmop (right, NULL, ic, FALSE);
4494 freeAsmop (left, NULL, ic, FALSE);
4498 freeAsmop (result, NULL, ic, TRUE);
4500 if (opcode == EQ_OP)
4503 tlbl_EQ = newiTempLabel (NULL);
4504 emitBranch ("beq", tlbl_EQ);
4506 emitLabel (tlbl_NE);
4507 emitBranch ("jmp", jlbl);
4508 emitLabel (tlbl_EQ);
4513 tlbl_NE = newiTempLabel (NULL);
4514 emitBranch ("bne", tlbl_NE);
4515 emitBranch ("jmp", jlbl);
4516 emitLabel (tlbl_NE);
4519 /* mark the icode as generated */
4524 symbol *tlbl = newiTempLabel (NULL);
4526 if (opcode == EQ_OP)
4529 tlbl_EQ = newiTempLabel (NULL);
4530 emitBranch ("beq", tlbl_EQ);
4532 emitLabel (tlbl_NE);
4533 loadRegFromConst (hc08_reg_a, zero);
4534 emitBranch ("bra", tlbl);
4535 emitLabel (tlbl_EQ);
4536 loadRegFromConst (hc08_reg_a, one);
4541 tlbl_NE = newiTempLabel (NULL);
4542 emitBranch ("bne", tlbl_NE);
4543 loadRegFromConst (hc08_reg_a, zero);
4544 emitBranch ("bra", tlbl);
4545 emitLabel (tlbl_NE);
4546 loadRegFromConst (hc08_reg_a, one);
4550 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4551 freeAsmop (result, NULL, ic, TRUE);
4557 /*-----------------------------------------------------------------*/
4558 /* ifxForOp - returns the icode containing the ifx for operand */
4559 /*-----------------------------------------------------------------*/
4561 ifxForOp (operand * op, iCode * ic)
4563 /* if true symbol then needs to be assigned */
4564 if (IS_TRUE_SYMOP (op))
4567 /* if this has register type condition and
4568 the next instruction is ifx with the same operand
4569 and live to of the operand is upto the ifx only then */
4571 ic->next->op == IFX &&
4572 IC_COND (ic->next)->key == op->key &&
4573 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4580 genPointerGetSetOfs (iCode *ic)
4582 iCode *lic = ic->next;
4588 /* Make sure we have a next iCode */
4589 D(emitcode("","; checking lic"));
4593 /* Make sure the result of the addition is an iCode */
4594 D(emitcode("","; checking IS_ITEMP"));
4595 if (!IS_ITEMP (IC_RESULT (ic)))
4598 /* Make sure the next iCode is a pointer set or get */
4599 pset = POINTER_SET(lic);
4600 pget = POINTER_GET(lic);
4601 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4605 /* Make sure this is the only use of the pointer */
4606 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4609 D(emitcode("", "; checking pset operandsEqu"));
4610 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4613 D(emitcode("", "; checking pget operandsEqu"));
4614 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4617 D(emitcode("", "; checking IS_SYMOP"));
4618 if (!IS_SYMOP (IC_LEFT (ic)))
4621 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4622 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4625 sym = OP_SYMBOL (IC_LEFT (ic));
4627 D(emitcode("", "; checking remat"));
4634 D(emitcode ("; genPointerGetOfs",""));
4635 aopOp (IC_LEFT(ic), ic, FALSE);
4636 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4637 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4639 aopOp (IC_RIGHT(ic), ic, FALSE);
4640 aopOp (IC_RESULT(lic), lic, FALSE);
4642 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4644 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4646 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4647 loadRegFromConst (hc08_reg_h, zero);
4651 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4652 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4653 emitcode ("rola","");
4654 emitcode ("clra","");
4655 emitcode ("sbc", "#0");
4656 hc08_useReg (hc08_reg_a);
4657 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4661 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4662 size = AOP_SIZE (IC_RESULT(lic));
4663 derefaop->size = size;
4667 emitcode ("lda", "%s,x",
4668 aopAdrStr (derefaop, size, TRUE));
4669 hc08_useReg (hc08_reg_a);
4670 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4671 hc08_freeReg (hc08_reg_a);
4675 hc08_freeReg (hc08_reg_hx);
4677 freeAsmop (NULL, derefaop, ic, TRUE);
4678 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4679 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4686 D(emitcode ("; genPointerSetOfs",""));
4687 aopOp (IC_LEFT(ic), ic, FALSE);
4688 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4689 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4691 aopOp (IC_RIGHT(ic), ic, FALSE);
4692 aopOp (IC_RIGHT(lic), lic, FALSE);
4694 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4696 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4698 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4699 loadRegFromConst (hc08_reg_h, zero);
4703 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4704 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4705 emitcode ("rola","");
4706 emitcode ("clra","");
4707 emitcode ("sbc", "#0");
4708 hc08_useReg (hc08_reg_a);
4709 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4713 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4714 size = AOP_SIZE (IC_RIGHT(lic));
4715 derefaop->size = size;
4719 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4720 emitcode ("sta", "%s,x",
4721 aopAdrStr (derefaop, size, TRUE));
4722 hc08_freeReg (hc08_reg_a);
4726 hc08_freeReg (hc08_reg_hx);
4728 freeAsmop (NULL, derefaop, ic, TRUE);
4729 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4730 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4739 /*-----------------------------------------------------------------*/
4740 /* hasInc - operand is incremented before any other use */
4741 /*-----------------------------------------------------------------*/
4743 hasInc (operand *op, iCode *ic,int osize)
4745 sym_link *type = operandType(op);
4746 sym_link *retype = getSpec (type);
4747 iCode *lic = ic->next;
4750 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4751 if (!IS_SYMOP(op)) return NULL;
4753 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4754 if (IS_AGGREGATE(type->next)) return NULL;
4755 if (osize != (isize = getSize(type->next))) return NULL;
4758 /* if operand of the form op = op + <sizeof *op> */
4759 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4760 isOperandEqual(IC_RESULT(lic),op) &&
4761 isOperandLiteral(IC_RIGHT(lic)) &&
4762 operandLitValue(IC_RIGHT(lic)) == isize) {
4765 /* if the operand used or deffed */
4766 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4769 /* if GOTO or IFX */
4770 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4776 /*-----------------------------------------------------------------*/
4777 /* genAndOp - for && operation */
4778 /*-----------------------------------------------------------------*/
4780 genAndOp (iCode * ic)
4782 operand *left, *right, *result;
4783 symbol *tlbl, *tlbl0;
4785 D(emitcode ("; genAndOp",""));
4787 /* note here that && operations that are in an
4788 if statement are taken away by backPatchLabels
4789 only those used in arthmetic operations remain */
4790 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4791 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4792 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4794 tlbl = newiTempLabel (NULL);
4795 tlbl0 = newiTempLabel (NULL);
4797 asmopToBool (AOP (left), FALSE);
4798 emitBranch ("beq", tlbl0);
4799 asmopToBool (AOP (right), FALSE);
4800 emitBranch ("beq", tlbl0);
4801 loadRegFromConst (hc08_reg_a,one);
4802 emitBranch ("bra", tlbl);
4804 loadRegFromConst (hc08_reg_a,zero);
4807 hc08_useReg (hc08_reg_a);
4808 hc08_freeReg (hc08_reg_a);
4810 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4812 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4813 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4814 freeAsmop (result, NULL, ic, TRUE);
4818 /*-----------------------------------------------------------------*/
4819 /* genOrOp - for || operation */
4820 /*-----------------------------------------------------------------*/
4822 genOrOp (iCode * ic)
4824 operand *left, *right, *result;
4825 symbol *tlbl, *tlbl0;
4827 D(emitcode ("; genOrOp",""));
4829 /* note here that || operations that are in an
4830 if statement are taken away by backPatchLabels
4831 only those used in arthmetic operations remain */
4832 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4833 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4834 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4836 tlbl = newiTempLabel (NULL);
4837 tlbl0 = newiTempLabel (NULL);
4839 asmopToBool (AOP (left), FALSE);
4840 emitBranch ("bne", tlbl0);
4841 asmopToBool (AOP (right), FALSE);
4842 emitBranch ("bne", tlbl0);
4843 loadRegFromConst (hc08_reg_a,zero);
4844 emitBranch ("bra", tlbl);
4846 loadRegFromConst (hc08_reg_a,one);
4849 hc08_useReg (hc08_reg_a);
4850 hc08_freeReg (hc08_reg_a);
4852 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4855 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4856 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4857 freeAsmop (result, NULL, ic, TRUE);
4860 /*-----------------------------------------------------------------*/
4861 /* isLiteralBit - test if lit == 2^n */
4862 /*-----------------------------------------------------------------*/
4864 isLiteralBit (unsigned long lit)
4866 unsigned long pw[32] =
4867 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4868 0x100L, 0x200L, 0x400L, 0x800L,
4869 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4870 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4871 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4872 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4873 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4876 for (idx = 0; idx < 32; idx++)
4883 /*-----------------------------------------------------------------*/
4884 /* continueIfTrue - */
4885 /*-----------------------------------------------------------------*/
4887 continueIfTrue (iCode * ic)
4890 emitBranch ("jmp", IC_TRUE (ic));
4894 /*-----------------------------------------------------------------*/
4896 /*-----------------------------------------------------------------*/
4898 jumpIfTrue (iCode * ic)
4901 emitBranch ("jmp", IC_FALSE (ic));
4905 /*-----------------------------------------------------------------*/
4906 /* jmpTrueOrFalse - */
4907 /*-----------------------------------------------------------------*/
4909 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4911 // ugly but optimized by peephole
4914 symbol *nlbl = newiTempLabel (NULL);
4915 emitBranch ("bra", nlbl);
4917 emitBranch ("jmp", IC_TRUE (ic));
4922 emitBranch ("jmp", IC_FALSE (ic));
4929 /*-----------------------------------------------------------------*/
4930 /* genAnd - code for and */
4931 /*-----------------------------------------------------------------*/
4933 genAnd (iCode * ic, iCode * ifx)
4935 operand *left, *right, *result;
4936 int size, offset = 0;
4937 unsigned long lit = 0L;
4938 unsigned long litinv;
4939 unsigned char bytemask;
4945 D(emitcode ("; genAnd",""));
4947 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4948 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4949 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4952 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4954 AOP_TYPE (left), AOP_TYPE (right)));
4955 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4957 AOP_SIZE (left), AOP_SIZE (right)));
4960 /* if left is a literal & right is not then exchange them */
4961 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4963 operand *tmp = right;
4968 /* if right is accumulator & left is not then exchange them */
4969 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4971 operand *tmp = right;
4976 if (AOP_TYPE (right) == AOP_LIT)
4977 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4979 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4981 if (AOP_TYPE (result) == AOP_CRY
4983 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
4985 /* this generates ugly code, but meets volatility requirements */
4986 loadRegFromConst (hc08_reg_a, zero);
4987 pushReg (hc08_reg_a, TRUE);
4992 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4993 accopWithAop ("and", AOP (right), offset);
4994 emitcode ("ora", "1,s");
4995 emitcode ("sta", "1,s");
4999 pullReg (hc08_reg_a);
5000 emitcode ("tsta", "");
5001 genIfxJump (ifx, "a");
5005 if (AOP_TYPE (result) == AOP_CRY)
5007 symbol *tlbl = NULL;
5008 wassertl (ifx, "AOP_CRY result without ifx");
5013 bytemask = (lit >> (offset*8)) & 0xff;
5015 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5019 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5021 rmwWithAop ("tst", AOP (left), offset);
5025 tlbl = newiTempLabel (NULL);
5026 emitBranch ("bne", tlbl);
5031 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5032 accopWithAop ("and", AOP (right), offset);
5033 hc08_freeReg( hc08_reg_a);
5037 tlbl = newiTempLabel (NULL);
5038 emitBranch ("bne", tlbl);
5045 genIfxJump (ifx, "a");
5049 size = AOP_SIZE (result);
5051 if (AOP_TYPE (right) == AOP_LIT)
5053 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5054 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5055 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5057 int bitpos = isLiteralBit(litinv)-1;
5058 emitcode ("bclr","#%d,%s",bitpos & 7,
5059 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5067 bytemask = (lit >> (offset*8)) & 0xff;
5069 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5071 if (isOperandVolatile (left, FALSE))
5073 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5074 hc08_freeReg( hc08_reg_a);
5076 storeConstToAop (zero, AOP (result), offset);
5078 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5080 transferAopAop (AOP (left), offset, AOP (result), offset);
5084 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5085 accopWithAop ("and", AOP (right), offset);
5086 storeRegToAop (hc08_reg_a, AOP (result), offset);
5087 hc08_freeReg (hc08_reg_a);
5093 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5094 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5095 freeAsmop (result, NULL, ic, TRUE);
5098 /*-----------------------------------------------------------------*/
5099 /* genOr - code for or */
5100 /*-----------------------------------------------------------------*/
5102 genOr (iCode * ic, iCode * ifx)
5104 operand *left, *right, *result;
5105 int size, offset = 0;
5106 unsigned long lit = 0L;
5107 unsigned char bytemask;
5109 D(emitcode ("; genOr",""));
5111 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5112 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5113 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5116 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5118 AOP_TYPE (left), AOP_TYPE (right)));
5119 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5121 AOP_SIZE (left), AOP_SIZE (right)));
5124 /* if left is a literal & right is not then exchange them */
5125 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5127 operand *tmp = right;
5132 /* if left is accumulator & right is not then exchange them */
5133 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5135 operand *tmp = right;
5140 if (AOP_TYPE (right) == AOP_LIT)
5141 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5143 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5145 if (AOP_TYPE (result) == AOP_CRY
5147 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5149 /* this generates ugly code, but meets volatility requirements */
5150 loadRegFromConst (hc08_reg_a, zero);
5151 pushReg (hc08_reg_a, TRUE);
5156 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5157 accopWithAop ("ora", AOP (right), offset);
5158 emitcode ("ora", "1,s");
5159 emitcode ("sta", "1,s");
5163 pullReg (hc08_reg_a);
5164 emitcode ("tsta", "");
5165 genIfxJump (ifx, "a");
5169 if (AOP_TYPE (result) == AOP_CRY)
5171 symbol *tlbl = NULL;
5172 wassertl (ifx, "AOP_CRY result without ifx");
5177 bytemask = (lit >> (offset*8)) & 0xff;
5179 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5181 rmwWithAop ("tst", AOP (left), offset);
5185 tlbl = newiTempLabel (NULL);
5186 emitBranch ("bne", tlbl);
5191 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5192 accopWithAop ("ora", AOP (right), offset);
5193 hc08_freeReg( hc08_reg_a);
5197 tlbl = newiTempLabel (NULL);
5198 emitBranch ("bne", tlbl);
5205 genIfxJump (ifx, "a");
5208 if (AOP_TYPE (right) == AOP_LIT)
5209 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5211 size = AOP_SIZE (result);
5213 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5214 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5215 (AOP_TYPE (left) == AOP_DIR))
5217 int bitpos = isLiteralBit(lit)-1;
5218 emitcode ("bset","#%d,%s",bitpos & 7,
5219 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5226 bytemask = (lit >> (offset*8)) & 0xff;
5228 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5230 if (isOperandVolatile (left, FALSE))
5232 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5233 hc08_freeReg( hc08_reg_a);
5235 transferAopAop (AOP (right), offset, AOP (result), offset);
5237 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5239 transferAopAop (AOP (left), offset, AOP (result), offset);
5243 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5244 accopWithAop ("ora", AOP (right), offset);
5245 storeRegToAop (hc08_reg_a, AOP (result), offset);
5246 hc08_freeReg (hc08_reg_a);
5253 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5254 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5255 freeAsmop (result, NULL, ic, TRUE);
5258 /*-----------------------------------------------------------------*/
5259 /* genXor - code for xclusive or */
5260 /*-----------------------------------------------------------------*/
5262 genXor (iCode * ic, iCode * ifx)
5264 operand *left, *right, *result;
5265 int size, offset = 0;
5266 unsigned long lit = 0L;
5268 D(emitcode ("; genXor",""));
5270 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5271 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5272 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5275 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5277 AOP_TYPE (left), AOP_TYPE (right)));
5278 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5280 AOP_SIZE (left), AOP_SIZE (right)));
5283 /* if left is a literal & right is not ||
5284 if left needs acc & right does not */
5285 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5287 operand *tmp = right;
5292 /* if left is accumulator & right is not then exchange them */
5293 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5295 operand *tmp = right;
5300 if (AOP_TYPE (result) == AOP_CRY)
5303 wassertl (ifx, "AOP_CPY result without ifx");
5305 tlbl = newiTempLabel (NULL);
5306 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5310 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5311 if ((AOP_TYPE (right) == AOP_LIT)
5312 && (((lit >> (offset*8)) & 0xff) == 0))
5313 emitcode ("tsta","");
5315 accopWithAop ("eor", AOP (right), offset);
5316 hc08_freeReg( hc08_reg_a);
5318 emitBranch ("bne", tlbl);
5322 genIfxJump (ifx, "a");
5328 if (AOP_TYPE (right) == AOP_LIT)
5329 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5331 size = AOP_SIZE (result);
5335 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5336 accopWithAop ("eor", AOP (right), offset);
5337 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5338 hc08_freeReg( hc08_reg_a);
5342 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5343 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5344 freeAsmop (result, NULL, ic, TRUE);
5348 emitinline (iCode * ic, char *inlin)
5354 symbol *sym, *tempsym;
5363 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5367 //printf("Found possible symbol '%s'\n",symname);
5368 tempsym = newSymbol (symname, ic->level);
5369 tempsym->block = ic->block;
5370 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5379 aop = aopForSym (ic, sym, FALSE);
5380 l = aopAdrStr (aop, aop->size - 1, TRUE);
5384 if (sym->level && !sym->allocreq && !sym->ismyparm)
5386 werror (E_ID_UNDEF, sym->name);
5388 " Add 'volatile' to the variable declaration so that it\n"
5389 " can be referenced within inline assembly");
5391 //printf("Replacing with '%s'\n",l);
5395 if ((2+bp-buffer)>sizeof(buffer))
5404 if ((2+bp-buffer)>sizeof(buffer))
5411 if ((2+bp-buffer)>sizeof(buffer))
5412 fprintf(stderr, "Inline assembly buffer overflow\n");
5414 //printf("%s\n",buffer);
5415 emitcode (buffer,"");
5419 /*-----------------------------------------------------------------*/
5420 /* genInline - write the inline code out */
5421 /*-----------------------------------------------------------------*/
5423 genInline (iCode * ic)
5425 char *buffer, *bp, *bp1;
5427 D(emitcode ("; genInline",""));
5429 _G.inLine += (!options.asmpeep);
5431 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5432 strcpy (buffer, IC_INLINE (ic));
5434 /* emit each line as a code */
5440 /* emitcode (bp1, ""); */
5441 emitinline (ic, bp1);
5460 /* emitcode (bp1, ""); */
5461 emitinline (ic, bp1);
5463 /* emitcode("",buffer); */
5464 _G.inLine -= (!options.asmpeep);
5467 /*-----------------------------------------------------------------*/
5468 /* genRRC - rotate right with carry */
5469 /*-----------------------------------------------------------------*/
5473 operand *left, *result;
5474 int size, offset = 0;
5475 bool needpula = FALSE;
5476 bool resultInA = FALSE;
5479 D(emitcode ("; genRRC",""));
5481 /* rotate right with carry */
5482 left = IC_LEFT (ic);
5483 result = IC_RESULT (ic);
5484 aopOp (left, ic, FALSE);
5485 aopOp (result, ic, FALSE);
5487 if ((AOP_TYPE (result) == AOP_REG)
5488 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5491 size = AOP_SIZE (result);
5495 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5499 rmwWithAop (shift, AOP (result), offset--);
5507 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5508 rmwWithReg (shift, hc08_reg_a);
5509 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5510 hc08_freeReg (hc08_reg_a);
5515 if ((!hc08_reg_a->isFree) || resultInA)
5517 pushReg (hc08_reg_a, TRUE);
5521 /* now we need to put the carry into the
5522 highest order byte of the result */
5523 offset = AOP_SIZE (result) - 1;
5524 emitcode ("clra","");
5525 emitcode ("rora","");
5526 hc08_dirtyReg (hc08_reg_a, FALSE);
5529 emitcode ("ora", "1,s");
5530 emitcode ("ais", "#1");
5531 hc08_dirtyReg (hc08_reg_a, FALSE);
5535 accopWithAop ("ora", AOP (result), offset);
5536 storeRegToAop (hc08_reg_a, AOP (result), offset);
5538 pullOrFreeReg (hc08_reg_a, needpula);
5540 freeAsmop (left, NULL, ic, TRUE);
5541 freeAsmop (result, NULL, ic, TRUE);
5544 /*-----------------------------------------------------------------*/
5545 /* genRLC - generate code for rotate left with carry */
5546 /*-----------------------------------------------------------------*/
5550 operand *left, *result;
5551 int size, offset = 0;
5553 bool resultInA = FALSE;
5554 bool needpula = FALSE;
5556 D(emitcode ("; genRLC",""));
5558 /* rotate right with carry */
5559 left = IC_LEFT (ic);
5560 result = IC_RESULT (ic);
5561 aopOp (left, ic, FALSE);
5562 aopOp (result, ic, FALSE);
5564 if ((AOP_TYPE (result) == AOP_REG)
5565 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5568 size = AOP_SIZE (result);
5572 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5576 rmwWithAop (shift, AOP (result), offset--);
5584 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5585 rmwWithReg (shift, hc08_reg_a);
5586 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5587 hc08_freeReg (hc08_reg_a);
5592 if ((!hc08_reg_a->isFree) || resultInA)
5594 pushReg (hc08_reg_a, TRUE);
5598 /* now we need to put the carry into the
5599 lowest order byte of the result */
5601 emitcode ("clra","");
5602 emitcode ("rola","");
5603 hc08_dirtyReg (hc08_reg_a, FALSE);
5606 emitcode ("ora", "1,s");
5607 emitcode ("ais", "#1");
5608 hc08_dirtyReg (hc08_reg_a, FALSE);
5612 accopWithAop ("ora", AOP (result), offset);
5613 storeRegToAop (hc08_reg_a, AOP (result), offset);
5615 pullOrFreeReg (hc08_reg_a, needpula);
5617 freeAsmop (left, NULL, ic, TRUE);
5618 freeAsmop (result, NULL, ic, TRUE);
5621 /*-----------------------------------------------------------------*/
5622 /* genGetHbit - generates code get highest order bit */
5623 /*-----------------------------------------------------------------*/
5625 genGetHbit (iCode * ic)
5627 operand *left, *result;
5629 D(emitcode ("; genGetHbit",""));
5631 left = IC_LEFT (ic);
5632 result = IC_RESULT (ic);
5633 aopOp (left, ic, FALSE);
5634 aopOp (result, ic, FALSE);
5636 /* get the highest order byte into a */
5637 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5638 emitcode ("rola", "");
5639 emitcode ("clra", "");
5640 emitcode ("rola", "");
5641 hc08_dirtyReg (hc08_reg_a, FALSE);
5642 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5643 hc08_freeReg (hc08_reg_a);
5645 freeAsmop (left, NULL, ic, TRUE);
5646 freeAsmop (result, NULL, ic, TRUE);
5649 /*-----------------------------------------------------------------*/
5650 /* genSwap - generates code to swap nibbles or bytes */
5651 /*-----------------------------------------------------------------*/
5653 genSwap (iCode * ic)
5655 operand *left, *result;
5657 D(emitcode ("; genSwap",""));
5659 left = IC_LEFT (ic);
5660 result = IC_RESULT (ic);
5661 aopOp (left, ic, FALSE);
5662 aopOp (result, ic, FALSE);
5664 switch (AOP_SIZE (left))
5666 case 1: /* swap nibbles in byte */
5667 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5668 emitcode ("nsa", "");
5669 hc08_dirtyReg (hc08_reg_a, FALSE);
5670 storeRegToAop (hc08_reg_a, AOP (result), 0);
5671 hc08_freeReg (hc08_reg_a);
5673 case 2: /* swap bytes in a word */
5674 if (operandsEqu (left, result))
5676 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5677 hc08_useReg (hc08_reg_a);
5678 transferAopAop (AOP (left), 1, AOP (result), 0);
5679 storeRegToAop (hc08_reg_a, AOP (result), 1);
5680 hc08_freeReg (hc08_reg_a);
5684 transferAopAop (AOP (left), 0, AOP (result), 1);
5685 transferAopAop (AOP (left), 1, AOP (result), 0);
5689 wassertl(FALSE, "unsupported SWAP operand size");
5692 freeAsmop (left, NULL, ic, TRUE);
5693 freeAsmop (result, NULL, ic, TRUE);
5697 /*-----------------------------------------------------------------*/
5698 /* AccRol - rotate left accumulator by known count */
5699 /*-----------------------------------------------------------------*/
5701 AccRol (int shCount)
5703 shCount &= 0x0007; // shCount : 0..7
5710 emitcode ("rola", ""); /* 1 cycle */
5713 emitcode ("rola", ""); /* 1 cycle */
5714 emitcode ("rola", ""); /* 1 cycle */
5717 emitcode ("nsa", "");
5718 emitcode ("rora", "");
5721 emitcode ("nsa", ""); /* 3 cycles */
5724 emitcode ("nsa", ""); /* 3 cycles */
5725 emitcode ("rola", ""); /* 1 cycle */
5728 emitcode ("nsa", ""); /* 3 cycles */
5729 emitcode ("rola", ""); /* 1 cycle */
5730 emitcode ("rola", ""); /* 1 cycle */
5733 emitcode ("nsa", ""); /* 3 cycles */
5734 emitcode ("rola", ""); /* 1 cycle */
5735 emitcode ("rola", ""); /* 1 cycle */
5736 emitcode ("rola", ""); /* 1 cycle */
5743 /*-----------------------------------------------------------------*/
5744 /* AccLsh - left shift accumulator by known count */
5745 /*-----------------------------------------------------------------*/
5747 AccLsh (int shCount)
5751 shCount &= 0x0007; // shCount : 0..7
5753 /* Shift counts of 4 and 5 are currently optimized for code size. */
5754 /* Falling through to the unrolled loop would be optimal for code speed. */
5755 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5759 if (optimize.codeSpeed)
5761 accopWithMisc ("nsa", "");
5762 accopWithMisc ("and", "#0xf0");
5763 /* total: 5 cycles, 3 bytes */
5766 if (optimize.codeSpeed)
5768 accopWithMisc ("nsa", "");
5769 accopWithMisc ("and", "#0xf0");
5770 accopWithMisc ("lsla", "");
5771 /* total: 6 cycles, 4 bytes */
5774 accopWithMisc ("rora", "");
5775 accopWithMisc ("rora", "");
5776 accopWithMisc ("rora", "");
5777 accopWithMisc ("and", "#0xc0");
5778 /* total: 5 cycles, 5 bytes */
5781 accopWithMisc ("rora", "");
5782 accopWithMisc ("clra", "");
5783 accopWithMisc ("rora", "");
5784 /* total: 3 cycles, 3 bytes */
5788 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5789 /* the fastest (shCount<6) and shortest (shCount<4). */
5790 for (i=0;i<shCount;i++)
5791 accopWithMisc ("lsla", "");
5795 /*-----------------------------------------------------------------*/
5796 /* AccSRsh - signed right shift accumulator by known count */
5797 /*-----------------------------------------------------------------*/
5799 AccSRsh (int shCount)
5803 shCount &= 0x0007; // shCount : 0..7
5807 accopWithMisc ("rola", "");
5808 accopWithMisc ("clra", "");
5809 accopWithMisc ("sbc", zero);
5810 /* total: 4 cycles, 4 bytes */
5814 for (i=0;i<shCount;i++)
5815 accopWithMisc ("asra", "");
5818 /*-----------------------------------------------------------------*/
5819 /* AccRsh - right shift accumulator by known count */
5820 /*-----------------------------------------------------------------*/
5822 AccRsh (int shCount, bool sign)
5832 shCount &= 0x0007; // shCount : 0..7
5834 /* Shift counts of 4 and 5 are currently optimized for code size. */
5835 /* Falling through to the unrolled loop would be optimal for code speed. */
5836 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5840 if (optimize.codeSpeed)
5842 accopWithMisc ("nsa", "");
5843 accopWithMisc ("and", "#0x0f");
5844 /* total: 5 cycles, 3 bytes */
5847 if (optimize.codeSpeed)
5849 accopWithMisc ("nsa", "");
5850 accopWithMisc ("and", "#0x0f");
5851 accopWithMisc ("lsra", "");
5852 /* total: 6 cycles, 4 bytes */
5855 accopWithMisc ("rola", "");
5856 accopWithMisc ("rola", "");
5857 accopWithMisc ("rola", "");
5858 accopWithMisc ("and", "#0x03");
5859 /* total: 5 cycles, 5 bytes */
5862 accopWithMisc ("rola", "");
5863 accopWithMisc ("clra", "");
5864 accopWithMisc ("rola", "");
5865 /* total: 3 cycles, 3 bytes */
5869 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5870 /* the fastest (shCount<6) and shortest (shCount<4). */
5871 for (i=0;i<shCount;i++)
5872 accopWithMisc ("lsra", "");
5876 /*-----------------------------------------------------------------*/
5877 /* XAccLsh - left shift register pair XA by known count */
5878 /*-----------------------------------------------------------------*/
5880 XAccLsh (int shCount)
5884 shCount &= 0x000f; // shCount : 0..15
5889 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5890 loadRegFromConst (hc08_reg_a, zero);
5894 /* if we can beat 2n cycles or bytes for some special case, do it here */
5898 /* bytes cycles reg x reg a carry
5899 ** abcd efgh ijkl mnop ?
5900 ** lsrx 1 1 0abc defg ijkl mnop h
5901 ** rora 1 1 0abc defg hijk lmno p
5902 ** tax 1 1 hijk lmno hijk lmno p
5903 ** clra 1 1 hijk lmno 0000 0000 p
5904 ** rora 1 1 hijk lmno p000 0000 0
5905 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5907 rmwWithReg ("lsr", hc08_reg_x);
5908 rmwWithReg ("ror", hc08_reg_a);
5909 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5910 loadRegFromConst (hc08_reg_a, zero);
5911 rmwWithReg ("ror", hc08_reg_a);
5918 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5919 /* the fastest and shortest. */
5920 for (i=0;i<shCount;i++)
5922 rmwWithReg ("lsl", hc08_reg_a);
5923 rmwWithReg ("rol", hc08_reg_x);
5927 /*-----------------------------------------------------------------*/
5928 /* XAccSRsh - signed right shift register pair XA by known count */
5929 /*-----------------------------------------------------------------*/
5931 XAccSRsh (int shCount)
5935 shCount &= 0x000f; // shCount : 0..7
5937 /* if we can beat 2n cycles or bytes for some special case, do it here */
5941 /* bytes cycles reg x reg a carry
5942 ** abcd efgh ijkl mnop ?
5943 ** lslx 1 1 bcde fgh0 ijkl mnop a
5944 ** clra 1 1 bcde fgh0 0000 0000 a
5945 ** rola 1 1 bcde fgh0 0000 000a 0
5946 ** nega 1 1 bcde fgh0 aaaa aaaa a
5947 ** tax 1 1 aaaa aaaa aaaa aaaa a
5948 ** total: 5 cycles, 5 bytes
5950 rmwWithReg ("lsl", hc08_reg_x);
5951 loadRegFromConst (hc08_reg_a, zero);
5952 rmwWithReg ("rol", hc08_reg_a);
5953 rmwWithReg ("neg", hc08_reg_a);
5954 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5964 /* bytes cycles reg x reg a carry
5965 ** abcd efgh ijkl mnop ?
5966 ** txa 1 1 abcd efgh abcd efgh ?
5967 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5968 ** lsla 1 1 abcd efgh ???? ???? a
5969 ** clrx 1 1 0000 0000 ???? ???? a
5970 ** rolx 1 1 0000 000a ???? ???? 0
5971 ** negx 1 1 aaaa aaaa ???? ???? a
5972 ** rora 1 1 aaaa aaaa LSBresult 0
5973 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5975 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5976 AccSRsh (shCount-8);
5977 rmwWithReg ("lsl", hc08_reg_a);
5978 loadRegFromConst (hc08_reg_x, zero);
5979 rmwWithReg ("rol", hc08_reg_x);
5980 rmwWithReg ("neg", hc08_reg_x);
5981 rmwWithReg ("ror", hc08_reg_a);
5988 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5989 /* the fastest and shortest. */
5990 for (i=0;i<shCount;i++)
5992 rmwWithReg ("asr", hc08_reg_x);
5993 rmwWithReg ("ror", hc08_reg_a);
5997 /*-----------------------------------------------------------------*/
5998 /* XAccRsh - right shift register pair XA by known count */
5999 /*-----------------------------------------------------------------*/
6001 XAccRsh (int shCount, bool sign)
6011 shCount &= 0x000f; // shCount : 0..f
6013 /* if we can beat 2n cycles or bytes for some special case, do it here */
6017 /* bytes cycles reg x reg a carry
6018 ** abcd efgh ijkl mnop ?
6019 ** clra 1 1 abcd efgh 0000 0000 a
6020 ** lslx 1 1 bcde fgh0 0000 0000 a
6021 ** rola 1 1 bcde fgh0 0000 000a 0
6022 ** clrx 1 1 0000 0000 0000 000a 0
6023 ** total: 4 cycles, 4 bytes
6025 loadRegFromConst (hc08_reg_x, zero);
6026 rmwWithReg ("lsl", hc08_reg_x);
6027 rmwWithReg ("rol", hc08_reg_a);
6028 loadRegFromConst (hc08_reg_a, zero);
6032 /* bytes cycles reg x reg a carry
6033 ** abcd efgh ijkl mnop ?
6034 ** clra 1 1 abcd efgh 0000 0000 a
6035 ** lslx 1 1 bcde fgh0 0000 0000 a
6036 ** rola 1 1 bcde fgh0 0000 000a 0
6037 ** lslx 1 1 cdef gh00 0000 000a b
6038 ** rola 1 1 cdef gh00 0000 00ab 0
6039 ** clrx 1 1 0000 0000 0000 00ab 0
6040 ** total: 6 cycles, 6 bytes
6042 loadRegFromConst (hc08_reg_x, zero);
6043 rmwWithReg ("lsl", hc08_reg_x);
6044 rmwWithReg ("rol", hc08_reg_a);
6045 rmwWithReg ("lsl", hc08_reg_x);
6046 rmwWithReg ("rol", hc08_reg_a);
6047 loadRegFromConst (hc08_reg_a, zero);
6056 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6057 AccRsh (shCount-8, FALSE);
6058 loadRegFromConst (hc08_reg_x, zero);
6062 /* bytes cycles reg x reg a carry
6063 ** abcd efgh ijkl mnop ?
6064 ** lsla 1 1 abcd efgh jklm nop0 i
6065 ** txa 1 1 abcd efgh abcd efgh i
6066 ** rola 1 1 abcd efgh bcde fghi a
6067 ** clrx 1 1 0000 0000 bcde fghi a
6068 ** rolx 1 1 0000 000a bcde fghi 0
6069 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6071 rmwWithReg ("lsl", hc08_reg_a);
6072 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6073 rmwWithReg ("rol", hc08_reg_a);
6074 loadRegFromConst (hc08_reg_x, zero);
6075 rmwWithReg ("rol", hc08_reg_x);
6078 /* bytes cycles reg x reg a carry
6079 ** abcd efgh ijkl mnop ?
6080 ** lsla 1 1 abcd efgh jklm nop0 i
6081 ** rolx 1 1 bcde fghi jklm nop0 a
6082 ** rola 1 1 bcde fghi klmn op0a j
6083 ** rolx 1 1 cdef ghij klmn op0a b
6084 ** rola 1 1 cdef ghij lmno p0ab k
6085 ** and #3 2 2 cdef ghij 0000 00ab k
6086 ** psha 1 2 cdef ghij 0000 00ab k
6087 ** txa 1 1 cdef ghij cdef ghij k
6088 ** pula 1 2 0000 00ab cdef ghij k
6089 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6095 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6096 /* the fastest and shortest. */
6097 for (i=0;i<shCount;i++)
6099 rmwWithReg ("lsr", hc08_reg_x);
6100 rmwWithReg ("ror", hc08_reg_a);
6107 /*-----------------------------------------------------------------*/
6108 /* shiftR1Left2Result - shift right one byte from left to result */
6109 /*-----------------------------------------------------------------*/
6111 shiftR1Left2Result (operand * left, int offl,
6112 operand * result, int offr,
6113 int shCount, int sign)
6115 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6116 /* shift right accumulator */
6117 AccRsh (shCount, sign);
6118 storeRegToAop (hc08_reg_a, AOP (result), offr);
6122 /*-----------------------------------------------------------------*/
6123 /* shiftL1Left2Result - shift left one byte from left to result */
6124 /*-----------------------------------------------------------------*/
6126 shiftL1Left2Result (operand * left, int offl,
6127 operand * result, int offr, int shCount)
6129 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6130 /* shift left accumulator */
6132 storeRegToAop (hc08_reg_a, AOP (result), offr);
6135 /*-----------------------------------------------------------------*/
6136 /* movLeft2Result - move byte from left to result */
6137 /*-----------------------------------------------------------------*/
6139 movLeft2Result (operand * left, int offl,
6140 operand * result, int offr, int sign)
6142 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6144 transferAopAop (AOP (left), offl, AOP (result), offr);
6149 /*-----------------------------------------------------------------*/
6150 /* shiftL2Left2Result - shift left two bytes from left to result */
6151 /*-----------------------------------------------------------------*/
6153 shiftL2Left2Result (operand * left, int offl,
6154 operand * result, int offr, int shCount)
6157 bool needpula = FALSE;
6158 bool needpulx = FALSE;
6160 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6161 needpula = pushRegIfUsed (hc08_reg_a);
6164 if (!IS_AOP_XA (AOP (left)))
6165 needpulx = pushRegIfUsed (hc08_reg_x);
6169 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6174 rmwWithReg ("lsr", hc08_reg_x);
6175 rmwWithReg ("ror", hc08_reg_a);
6176 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6177 rmwWithReg ("clr", hc08_reg_a);
6178 rmwWithReg ("ror", hc08_reg_a);
6181 for (i=0; i<shCount; i++)
6183 rmwWithReg ("lsl", hc08_reg_a);
6184 rmwWithReg ("rol", hc08_reg_x);
6187 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6189 pullOrFreeReg (hc08_reg_x, needpulx);
6190 pullOrFreeReg (hc08_reg_a, needpula);
6196 /*-----------------------------------------------------------------*/
6197 /* shiftR2Left2Result - shift right two bytes from left to result */
6198 /*-----------------------------------------------------------------*/
6200 shiftR2Left2Result (operand * left, int offl,
6201 operand * result, int offr,
6202 int shCount, int sign)
6205 bool needpula = FALSE;
6206 bool needpulx = FALSE;
6208 needpula = pushRegIfUsed (hc08_reg_a);
6209 needpulx = pushRegIfUsed (hc08_reg_x);
6211 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6212 for (i=0; i<shCount; i++)
6215 rmwWithReg ("asr", hc08_reg_x);
6217 rmwWithReg ("lsr", hc08_reg_x);
6218 rmwWithReg ("ror", hc08_reg_a);
6220 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6222 pullOrFreeReg (hc08_reg_x, needpulx);
6223 pullOrFreeReg (hc08_reg_a, needpula);
6228 /*-----------------------------------------------------------------*/
6229 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6230 /*-----------------------------------------------------------------*/
6232 shiftLLeftOrResult (operand * left, int offl,
6233 operand * result, int offr, int shCount)
6235 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6236 /* shift left accumulator */
6238 /* or with result */
6239 accopWithAop ("ora", AOP (result), offr);
6240 /* back to result */
6241 storeRegToAop (hc08_reg_a, AOP (result), offr);
6242 hc08_freeReg (hc08_reg_a);
6246 /*-----------------------------------------------------------------*/
6247 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6248 /*-----------------------------------------------------------------*/
6250 shiftRLeftOrResult (operand * left, int offl,
6251 operand * result, int offr, int shCount)
6253 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6254 /* shift left accumulator */
6255 AccRsh (shCount, FALSE);
6256 /* or with result */
6257 accopWithAop ("ora", AOP (result), offr);
6258 /* back to result */
6259 storeRegToAop (hc08_reg_a, AOP (result), offr);
6260 hc08_freeReg (hc08_reg_a);
6263 /*-----------------------------------------------------------------*/
6264 /* genlshOne - left shift a one byte quantity by known count */
6265 /*-----------------------------------------------------------------*/
6267 genlshOne (operand * result, operand * left, int shCount)
6269 D(emitcode ("; genlshOne",""));
6271 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6274 /*-----------------------------------------------------------------*/
6275 /* genlshTwo - left shift two bytes by known amount != 0 */
6276 /*-----------------------------------------------------------------*/
6278 genlshTwo (operand * result, operand * left, int shCount)
6282 D(emitcode ("; genlshTwo",""));
6285 size = getDataSize (result);
6287 /* if shCount >= 8 */
6294 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6296 storeRegToAop (hc08_reg_a, AOP (result), 1);
6298 storeConstToAop(zero, AOP (result), LSB);
6301 /* 1 <= shCount <= 7 */
6304 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6306 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6310 /*-----------------------------------------------------------------*/
6311 /* shiftLLong - shift left one long from left to result */
6312 /* offl = LSB or MSB16 */
6313 /*-----------------------------------------------------------------*/
6315 shiftLLong (operand * left, operand * result, int offr)
6318 // int size = AOP_SIZE (result);
6320 bool needpula = FALSE;
6321 bool needpulx = FALSE;
6323 needpula = pushRegIfUsed (hc08_reg_a);
6324 needpulx = pushRegIfUsed (hc08_reg_x);
6326 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6327 rmwWithReg ("lsl", hc08_reg_a);
6328 rmwWithReg ("rol", hc08_reg_x);
6329 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6333 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6334 rmwWithReg ("rol", hc08_reg_a);
6335 rmwWithReg ("rol", hc08_reg_x);
6336 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6338 else if (offr==MSB16)
6340 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6341 rmwWithReg ("rol", hc08_reg_a);
6342 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6343 storeConstToAop (zero, AOP (result), 0);
6346 pullOrFreeReg (hc08_reg_x, needpulx);
6347 pullOrFreeReg (hc08_reg_a, needpula);
6350 /*-----------------------------------------------------------------*/
6351 /* genlshFour - shift four byte by a known amount != 0 */
6352 /*-----------------------------------------------------------------*/
6354 genlshFour (operand * result, operand * left, int shCount)
6358 D(emitcode ("; genlshFour",""));
6360 size = AOP_SIZE (result);
6362 /* TODO: deal with the &result == &left case */
6364 /* if shifting more that 3 bytes */
6369 /* lowest order of left goes to the highest
6370 order of the destination */
6371 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6373 movLeft2Result (left, LSB, result, MSB32, 0);
6374 storeConstToAop (zero, AOP (result), LSB);
6375 storeConstToAop (zero, AOP (result), MSB16);
6376 storeConstToAop (zero, AOP (result), MSB24);
6380 /* more than two bytes */
6381 else if (shCount >= 16)
6383 /* lower order two bytes goes to higher order two bytes */
6385 /* if some more remaining */
6387 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6390 movLeft2Result (left, MSB16, result, MSB32, 0);
6391 movLeft2Result (left, LSB, result, MSB24, 0);
6393 storeConstToAop (zero, AOP (result), LSB);
6394 storeConstToAop (zero, AOP (result), MSB16);
6398 /* if more than 1 byte */
6399 else if (shCount >= 8)
6401 /* lower order three bytes goes to higher order three bytes */
6406 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6408 movLeft2Result (left, LSB, result, MSB16, 0);
6414 movLeft2Result (left, MSB24, result, MSB32, 0);
6415 movLeft2Result (left, MSB16, result, MSB24, 0);
6416 movLeft2Result (left, LSB, result, MSB16, 0);
6417 storeConstToAop (zero, AOP (result), LSB);
6419 else if (shCount == 1)
6420 shiftLLong (left, result, MSB16);
6423 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6424 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6425 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6426 storeConstToAop (zero, AOP (result), LSB);
6431 /* 1 <= shCount <= 7 */
6432 else if (shCount <= 2)
6434 shiftLLong (left, result, LSB);
6436 shiftLLong (result, result, LSB);
6438 /* 3 <= shCount <= 7, optimize */
6441 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6442 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6443 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6447 /*-----------------------------------------------------------------*/
6448 /* genLeftShiftLiteral - left shifting by known count */
6449 /*-----------------------------------------------------------------*/
6451 genLeftShiftLiteral (operand * left,
6456 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6459 D(emitcode ("; genLeftShiftLiteral",""));
6461 freeAsmop (right, NULL, ic, TRUE);
6463 aopOp (left, ic, FALSE);
6464 aopOp (result, ic, FALSE);
6466 // size = getSize (operandType (result));
6467 size = AOP_SIZE (result);
6470 D(emitcode ("; shift left ", "result %d, left %d", size,
6477 transferAopAop( AOP(left), size, AOP(result), size);
6479 else if (shCount >= (size * 8))
6482 storeConstToAop (zero, AOP (result), size);
6489 genlshOne (result, left, shCount);
6493 genlshTwo (result, left, shCount);
6497 genlshFour (result, left, shCount);
6500 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6501 "*** ack! mystery literal shift!\n");
6505 freeAsmop (left, NULL, ic, TRUE);
6506 freeAsmop (result, NULL, ic, TRUE);
6509 /*-----------------------------------------------------------------*/
6510 /* genLeftShift - generates code for left shifting */
6511 /*-----------------------------------------------------------------*/
6513 genLeftShift (iCode * ic)
6515 operand *left, *right, *result;
6517 symbol *tlbl, *tlbl1;
6520 D(emitcode ("; genLeftShift",""));
6522 right = IC_RIGHT (ic);
6523 left = IC_LEFT (ic);
6524 result = IC_RESULT (ic);
6526 aopOp (right, ic, FALSE);
6528 /* if the shift count is known then do it
6529 as efficiently as possible */
6530 if (AOP_TYPE (right) == AOP_LIT)
6532 genLeftShiftLiteral (left, right, result, ic);
6536 /* shift count is unknown then we have to form
6537 a loop get the loop count in A : Note: we take
6538 only the lower order byte since shifting
6539 more that 32 bits make no sense anyway, ( the
6540 largest size of an object can be only 32 bits ) */
6542 aopOp (result, ic, FALSE);
6543 aopOp (left, ic, FALSE);
6545 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6546 AOP (result) = forceStackedAop (AOP (result));
6548 /* now move the left to the result if they are not the
6550 if (!sameRegs (AOP (left), AOP (result)))
6552 size = AOP_SIZE (result);
6556 transferAopAop (AOP (left), offset, AOP (result), offset);
6560 freeAsmop (left, NULL, ic, TRUE);
6562 tlbl = newiTempLabel (NULL);
6563 size = AOP_SIZE (result);
6565 tlbl1 = newiTempLabel (NULL);
6567 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6568 emitcode ("tstx", "");
6569 emitBranch ("beq", tlbl1);
6573 for (offset=0;offset<size;offset++)
6575 rmwWithAop (shift, AOP (result), offset);
6578 rmwWithReg ("dec", hc08_reg_x);
6579 emitBranch ("bne", tlbl);
6581 hc08_freeReg (hc08_reg_x);
6583 freeAsmop (result, NULL, ic, TRUE);
6584 freeAsmop (right, NULL, ic, TRUE);
6587 /*-----------------------------------------------------------------*/
6588 /* genrshOne - right shift a one byte quantity by known count */
6589 /*-----------------------------------------------------------------*/
6591 genrshOne (operand * result, operand * left,
6592 int shCount, int sign)
6594 D(emitcode ("; genrshOne",""));
6596 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6597 AccRsh (shCount, sign);
6598 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6601 /*-----------------------------------------------------------------*/
6602 /* genrshTwo - right shift two bytes by known amount != 0 */
6603 /*-----------------------------------------------------------------*/
6605 genrshTwo (operand * result, operand * left,
6606 int shCount, int sign)
6608 D(emitcode ("; genrshTwo",""));
6610 /* if shCount >= 8 */
6613 if (shCount || sign)
6615 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6616 AccRsh (shCount-8, sign);
6617 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6621 transferAopAop (AOP (left), 1, AOP (result), 0);
6622 storeConstToAop (zero, AOP (result), 1);
6626 /* 1 <= shCount <= 7 */
6629 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6630 XAccRsh (shCount, sign);
6631 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6635 /*-----------------------------------------------------------------*/
6636 /* shiftRLong - shift right one long from left to result */
6637 /* offl = LSB or MSB16 */
6638 /*-----------------------------------------------------------------*/
6640 shiftRLong (operand * left, int offl,
6641 operand * result, int sign)
6644 // int size = AOP_SIZE (result);
6646 bool needpula = FALSE;
6647 bool needpulx = FALSE;
6649 needpula = pushRegIfUsed (hc08_reg_a);
6650 needpulx = pushRegIfUsed (hc08_reg_x);
6654 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6656 rmwWithReg ("asr", hc08_reg_x);
6658 rmwWithReg ("lsr", hc08_reg_x);
6659 rmwWithReg ("ror", hc08_reg_a);
6660 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6662 else if (offl==MSB16)
6664 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6666 rmwWithReg ("asr", hc08_reg_a);
6668 rmwWithReg ("lsr", hc08_reg_a);
6669 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6670 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6673 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6674 rmwWithReg ("ror", hc08_reg_x);
6675 rmwWithReg ("ror", hc08_reg_a);
6676 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6679 pullOrFreeReg (hc08_reg_x, needpulx);
6680 pullOrFreeReg (hc08_reg_a, needpula);
6683 /*-----------------------------------------------------------------*/
6684 /* genrshFour - shift four byte by a known amount != 0 */
6685 /*-----------------------------------------------------------------*/
6687 genrshFour (operand * result, operand * left,
6688 int shCount, int sign)
6690 /* TODO: handle cases where left == result */
6692 D(emitcode ("; genrshFour",""));
6694 /* if shifting more that 3 bytes */
6697 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6698 AccRsh (shCount-24, sign);
6699 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6702 else if (shCount >= 16)
6704 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6705 XAccRsh (shCount-16, sign);
6706 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6709 else if (shCount >= 8)
6712 shiftRLong (left, MSB16, result, sign);
6713 else if (shCount == 8)
6715 transferAopAop (AOP (left), 1, AOP (result), 0);
6716 transferAopAop (AOP (left), 2, AOP (result), 1);
6717 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6718 storeRegToAop (hc08_reg_a, AOP (result), 2);
6719 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6721 else if (shCount == 9)
6723 shiftRLong (left, MSB16, result, sign);
6727 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6728 XAccRsh (shCount-8, FALSE);
6729 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6730 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6731 loadRegFromConst (hc08_reg_a, zero);
6732 XAccRsh (shCount-8, sign);
6733 accopWithAop ("ora", AOP (result), 1);
6734 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6735 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6739 { /* 1 <= shCount <= 7 */
6742 shiftRLong (left, LSB, result, sign);
6746 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6747 XAccRsh (shCount, FALSE);
6748 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6749 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6751 accopWithAop ("ora", AOP (result), 1);
6752 storeRegToAop (hc08_reg_a, AOP (result), 1);
6753 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6754 XAccRsh (shCount, sign);
6755 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6760 /*-----------------------------------------------------------------*/
6761 /* genRightShiftLiteral - right shifting by known count */
6762 /*-----------------------------------------------------------------*/
6764 genRightShiftLiteral (operand * left,
6770 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6773 D(emitcode ("; genRightShiftLiteral",""));
6775 freeAsmop (right, NULL, ic, TRUE);
6777 aopOp (left, ic, FALSE);
6778 aopOp (result, ic, FALSE);
6781 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6785 size = getDataSize (left);
6786 /* test the LEFT size !!! */
6788 /* I suppose that the left size >= result size */
6791 size = getDataSize (result);
6793 transferAopAop (AOP (left), size, AOP(result), size);
6795 else if (shCount >= (size * 8))
6798 /* get sign in acc.7 */
6799 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6801 addSign (result, LSB, sign);
6808 genrshOne (result, left, shCount, sign);
6812 genrshTwo (result, left, shCount, sign);
6816 genrshFour (result, left, shCount, sign);
6822 freeAsmop (left, NULL, ic, TRUE);
6823 freeAsmop (result, NULL, ic, TRUE);
6827 /*-----------------------------------------------------------------*/
6828 /* genRightShift - generate code for right shifting */
6829 /*-----------------------------------------------------------------*/
6831 genRightShift (iCode * ic)
6833 operand *right, *left, *result;
6836 symbol *tlbl, *tlbl1;
6840 D(emitcode ("; genRightShift",""));
6842 /* if signed then we do it the hard way preserve the
6843 sign bit moving it inwards */
6844 retype = getSpec (operandType (IC_RESULT (ic)));
6845 sign = !SPEC_USIGN (retype);
6847 /* signed & unsigned types are treated the same : i.e. the
6848 signed is NOT propagated inwards : quoting from the
6849 ANSI - standard : "for E1 >> E2, is equivalent to division
6850 by 2**E2 if unsigned or if it has a non-negative value,
6851 otherwise the result is implementation defined ", MY definition
6852 is that the sign does not get propagated */
6854 right = IC_RIGHT (ic);
6855 left = IC_LEFT (ic);
6856 result = IC_RESULT (ic);
6858 aopOp (right, ic, FALSE);
6860 /* if the shift count is known then do it
6861 as efficiently as possible */
6862 if (AOP_TYPE (right) == AOP_LIT)
6864 genRightShiftLiteral (left, right, result, ic, sign);
6868 /* shift count is unknown then we have to form
6869 a loop get the loop count in X : Note: we take
6870 only the lower order byte since shifting
6871 more that 32 bits make no sense anyway, ( the
6872 largest size of an object can be only 32 bits ) */
6874 aopOp (result, ic, FALSE);
6875 aopOp (left, ic, FALSE);
6877 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6878 AOP (result) = forceStackedAop (AOP (result));
6880 /* now move the left to the result if they are not the
6882 if (!sameRegs (AOP (left), AOP (result)))
6884 size = AOP_SIZE (result);
6888 transferAopAop (AOP (left), offset, AOP (result), offset);
6892 freeAsmop (left, NULL, ic, TRUE);
6894 tlbl = newiTempLabel (NULL);
6895 size = AOP_SIZE (result);
6897 tlbl1 = newiTempLabel (NULL);
6899 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6900 emitcode ("tstx", "");
6901 emitBranch ("beq", tlbl1);
6904 shift= sign ? "asr" : "lsr";
6905 for (offset=size-1;offset>=0;offset--)
6907 rmwWithAop (shift, AOP (result), offset);
6910 rmwWithReg ("dec", hc08_reg_x);
6911 emitBranch ("bne", tlbl);
6913 hc08_freeReg (hc08_reg_x);
6915 freeAsmop (result, NULL, ic, TRUE);
6916 freeAsmop (right, NULL, ic, TRUE);
6920 /*-----------------------------------------------------------------*/
6921 /* genUnpackBits - generates code for unpacking bits */
6922 /*-----------------------------------------------------------------*/
6924 genUnpackBits (operand * result, iCode *ifx)
6926 int offset = 0; /* result byte offset */
6927 int rsize; /* result size */
6928 int rlen = 0; /* remaining bitfield length */
6929 sym_link *etype; /* bitfield type information */
6930 int blen; /* bitfield length */
6931 int bstr; /* bitfield starting bit within byte */
6933 D(emitcode ("; genUnpackBits",""));
6935 etype = getSpec (operandType (result));
6936 rsize = getSize (operandType (result));
6937 blen = SPEC_BLEN (etype);
6938 bstr = SPEC_BSTR (etype);
6940 if (ifx && blen <= 8)
6942 emitcode ("lda", ",x");
6943 hc08_dirtyReg (hc08_reg_a, FALSE);
6946 emitcode ("and", "#0x%02x",
6947 (((unsigned char) -1) >> (8 - blen)) << bstr);
6949 genIfxJump (ifx, "a");
6954 /* If the bitfield length is less than a byte */
6957 emitcode ("lda", ",x");
6958 hc08_dirtyReg (hc08_reg_a, FALSE);
6959 AccRsh (bstr, FALSE);
6960 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6961 if (!SPEC_USIGN (etype))
6963 /* signed bitfield */
6964 symbol *tlbl = newiTempLabel (NULL);
6966 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
6967 emitcode ("beq", "%05d$", tlbl->key + 100);
6968 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
6971 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6975 /* Bit field did not fit in a byte. Copy all
6976 but the partial byte at the end. */
6977 for (rlen=blen;rlen>=8;rlen-=8)
6979 emitcode ("lda", ",x");
6980 hc08_dirtyReg (hc08_reg_a, FALSE);
6981 storeRegToAop (hc08_reg_a, AOP (result), offset);
6984 emitcode ("aix", "#1");
6987 /* Handle the partial byte at the end */
6990 emitcode ("lda", ",x");
6991 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6992 if (!SPEC_USIGN (etype))
6994 /* signed bitfield */
6995 symbol *tlbl = newiTempLabel (NULL);
6997 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
6998 emitcode ("beq", "%05d$", tlbl->key + 100);
6999 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7002 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7009 if (SPEC_USIGN (etype))
7012 storeConstToAop (zero, AOP (result), offset++);
7016 /* signed bitfield: sign extension with 0x00 or 0xff */
7017 emitcode ("rola", "");
7018 emitcode ("clra", "");
7019 emitcode ("sbc", zero);
7022 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7028 /*-----------------------------------------------------------------*/
7029 /* genUnpackBitsImmed - generates code for unpacking bits */
7030 /*-----------------------------------------------------------------*/
7032 genUnpackBitsImmed (operand * left,
7038 int offset = 0; /* result byte offset */
7039 int rsize; /* result size */
7040 int rlen = 0; /* remaining bitfield length */
7041 sym_link *etype; /* bitfield type information */
7042 int blen; /* bitfield length */
7043 int bstr; /* bitfield starting bit within byte */
7046 D(emitcode ("; genUnpackBitsImmed",""));
7048 aopOp (result, ic, TRUE);
7049 size = AOP_SIZE (result);
7051 derefaop = aopDerefAop (AOP (left));
7052 freeAsmop (left, NULL, ic, TRUE);
7053 derefaop->size = size;
7055 etype = getSpec (operandType (result));
7056 rsize = getSize (operandType (result));
7057 blen = SPEC_BLEN (etype);
7058 bstr = SPEC_BSTR (etype);
7060 /* if the bitfield is a single bit in the direct page */
7061 if (blen == 1 && derefaop->type == AOP_DIR)
7065 symbol *tlbl = newiTempLabel (NULL);
7067 loadRegFromConst (hc08_reg_a, zero);
7068 emitcode ("brclr", "#%d,%s,%05d$",
7069 bstr, aopAdrStr (derefaop, 0, FALSE),
7071 if (SPEC_USIGN (etype))
7072 rmwWithReg ("inc", hc08_reg_a);
7074 rmwWithReg ("dec", hc08_reg_a);
7076 storeRegToAop (hc08_reg_a, AOP (result), offset);
7077 hc08_freeReg (hc08_reg_a);
7083 symbol *tlbl = newiTempLabel (NULL);
7089 jlbl = IC_TRUE (ifx);
7094 jlbl = IC_FALSE (ifx);
7097 emitcode (inst, "#%d,%s,%05d$",
7098 bstr, aopAdrStr (derefaop, 0, FALSE),
7100 emitBranch ("jmp", jlbl);
7108 /* If the bitfield length is less than a byte */
7111 loadRegFromAop (hc08_reg_a, derefaop, 0);
7114 AccRsh (bstr, FALSE);
7115 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7116 hc08_dirtyReg (hc08_reg_a, FALSE);
7117 if (!SPEC_USIGN (etype))
7119 /* signed bitfield */
7120 symbol *tlbl = newiTempLabel (NULL);
7122 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7123 emitcode ("beq", "%05d$", tlbl->key + 100);
7124 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7127 storeRegToAop (hc08_reg_a, AOP (result), offset);
7131 emitcode ("and", "#0x%02x",
7132 (((unsigned char) -1) >> (8 - blen)) << bstr);
7133 hc08_dirtyReg (hc08_reg_a, FALSE);
7139 /* Bit field did not fit in a byte. Copy all
7140 but the partial byte at the end. */
7141 for (rlen=blen;rlen>=8;rlen-=8)
7143 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7145 storeRegToAop (hc08_reg_a, AOP (result), offset);
7147 emitcode ("tsta", "");
7151 /* Handle the partial byte at the end */
7154 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7155 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7156 if (!SPEC_USIGN (etype))
7158 /* signed bitfield */
7159 symbol *tlbl = newiTempLabel (NULL);
7161 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7162 emitcode ("beq", "%05d$", tlbl->key + 100);
7163 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7166 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7173 if (SPEC_USIGN (etype))
7176 storeConstToAop (zero, AOP (result), offset++);
7180 /* signed bitfield: sign extension with 0x00 or 0xff */
7181 emitcode ("rola", "");
7182 emitcode ("clra", "");
7183 emitcode ("sbc", zero);
7186 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7190 freeAsmop (NULL, derefaop, ic, TRUE);
7191 freeAsmop (result, NULL, ic, TRUE);
7193 if (ifx && !ifx->generated)
7195 genIfxJump (ifx, "a");
7200 /*-----------------------------------------------------------------*/
7201 /* genDataPointerGet - generates code when ptr offset is known */
7202 /*-----------------------------------------------------------------*/
7204 genDataPointerGet (operand * left,
7212 D(emitcode ("; genDataPointerGet",""));
7214 aopOp (result, ic, TRUE);
7215 size = AOP_SIZE (result);
7217 derefaop = aopDerefAop (AOP (left));
7218 freeAsmop (left, NULL, ic, TRUE);
7219 derefaop->size = size;
7224 transferAopAop (derefaop, size, AOP (result), size);
7226 loadRegFromAop (hc08_reg_a, derefaop, size);
7229 freeAsmop (NULL, derefaop, ic, TRUE);
7230 freeAsmop (result, NULL, ic, TRUE);
7232 if (ifx && !ifx->generated)
7234 genIfxJump (ifx, "a");
7239 /*-----------------------------------------------------------------*/
7240 /* genPointerGet - generate code for pointer get */
7241 /*-----------------------------------------------------------------*/
7243 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7245 operand *left = IC_LEFT (ic);
7246 operand *result = IC_RESULT (ic);
7248 sym_link *retype = getSpec (operandType (result));
7250 D(emitcode ("; genPointerGet",""));
7252 if (getSize (operandType (result))>1)
7255 aopOp (left, ic, FALSE);
7257 /* if left is rematerialisable and
7258 result is not bit variable type */
7259 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7261 if (!IS_BITVAR (retype))
7263 genDataPointerGet (left, result, ic, ifx);
7268 genUnpackBitsImmed (left, result, ic, ifx);
7273 /* if the operand is already in hx
7274 then we do nothing else we move the value to hx */
7275 if (AOP_TYPE (left) != AOP_STR)
7277 /* if this is remateriazable */
7278 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7281 /* so hx now contains the address */
7282 aopOp (result, ic, FALSE);
7284 /* if bit then unpack */
7285 if (IS_BITVAR (retype))
7286 genUnpackBits (result, ifx);
7289 size = AOP_SIZE (result);
7294 accopWithMisc ("lda", ",x");
7297 emitcode ("aix", "#1");
7298 hc08_dirtyReg (hc08_reg_hx, FALSE);
7301 storeRegToAop (hc08_reg_a, AOP (result), offset);
7303 hc08_freeReg (hc08_reg_a);
7307 freeAsmop (left, NULL, ic, TRUE);
7308 freeAsmop (result, NULL, ic, TRUE);
7311 aopOp (IC_RESULT (pi), pi, FALSE);
7312 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7313 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7317 if (ifx && !ifx->generated)
7319 genIfxJump (ifx, "a");
7322 hc08_freeReg (hc08_reg_hx);
7326 /*-----------------------------------------------------------------*/
7327 /* genPackBits - generates code for packed bit storage */
7328 /*-----------------------------------------------------------------*/
7330 genPackBits (sym_link * etype,
7333 int offset = 0; /* source byte offset */
7334 int rlen = 0; /* remaining bitfield length */
7335 int blen; /* bitfield length */
7336 int bstr; /* bitfield starting bit within byte */
7337 int litval; /* source literal value (if AOP_LIT) */
7338 unsigned char mask; /* bitmask within current byte */
7341 D(emitcode ("; genPackBits",""));
7343 blen = SPEC_BLEN (etype);
7344 bstr = SPEC_BSTR (etype);
7346 /* If the bitfield length is less than a byte */
7349 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7350 (unsigned char) (0xFF >> (8 - bstr)));
7352 if (AOP_TYPE (right) == AOP_LIT)
7354 /* Case with a bitfield length <8 and literal source
7356 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7358 litval &= (~mask) & 0xff;
7360 emitcode ("lda", ",x");
7361 if ((mask|litval)!=0xff)
7362 emitcode ("and","#0x%02x", mask);
7364 emitcode ("ora","#0x%02x", litval);
7365 hc08_dirtyReg (hc08_reg_a, FALSE);
7366 emitcode ("sta", ",x");
7368 hc08_freeReg (hc08_reg_a);
7372 /* Case with a bitfield length < 8 and arbitrary source
7374 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7375 /* shift and mask source value */
7377 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7378 hc08_dirtyReg (hc08_reg_a, FALSE);
7379 pushReg (hc08_reg_a, TRUE);
7381 emitcode ("lda", ",x");
7382 emitcode ("and", "#0x%02x", mask);
7383 emitcode ("ora", "1,s");
7384 emitcode ("sta", ",x");
7385 pullReg (hc08_reg_a);
7387 hc08_freeReg (hc08_reg_a);
7391 /* Bit length is greater than 7 bits. In this case, copy */
7392 /* all except the partial byte at the end */
7393 for (rlen=blen;rlen>=8;rlen-=8)
7395 if (AOP (right)->type == AOP_DIR)
7397 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7402 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7403 emitcode ("sta", "%d,x", offset);
7408 /* If there was a partial byte at the end */
7411 mask = (((unsigned char) -1 << rlen) & 0xff);
7413 if (AOP_TYPE (right) == AOP_LIT)
7415 /* Case with partial byte and literal source
7417 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7418 litval >>= (blen-rlen);
7419 litval &= (~mask) & 0xff;
7420 emitcode ("lda", "%d,x", offset - xoffset);
7421 hc08_dirtyReg (hc08_reg_a, FALSE);
7422 if ((mask|litval)!=0xff)
7423 emitcode ("and","#0x%02x", mask);
7425 emitcode ("ora","#0x%02x", litval);
7426 emitcode ("sta", "%d,x", offset - xoffset);
7427 hc08_dirtyReg (hc08_reg_a, FALSE);
7428 hc08_freeReg (hc08_reg_a);
7432 /* Case with partial byte and arbitrary source
7434 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7435 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7436 hc08_dirtyReg (hc08_reg_a, FALSE);
7437 pushReg (hc08_reg_a, TRUE);
7439 emitcode ("lda", "%d,x", offset - xoffset);
7440 emitcode ("and", "#0x%02x", mask);
7441 emitcode ("ora", "1,s");
7442 emitcode ("sta", "%d,x", offset - xoffset);
7443 pullReg (hc08_reg_a);
7446 hc08_freeReg (hc08_reg_a);
7449 /*-----------------------------------------------------------------*/
7450 /* genPackBitsImmed - generates code for packed bit storage */
7451 /*-----------------------------------------------------------------*/
7453 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7457 int offset = 0; /* source byte offset */
7458 int rlen = 0; /* remaining bitfield length */
7459 int blen; /* bitfield length */
7460 int bstr; /* bitfield starting bit within byte */
7461 int litval; /* source literal value (if AOP_LIT) */
7462 unsigned char mask; /* bitmask within current byte */
7464 D(emitcode ("; genPackBitsImmed",""));
7466 blen = SPEC_BLEN (etype);
7467 bstr = SPEC_BSTR (etype);
7469 aopOp (right, ic, FALSE);
7470 size = AOP_SIZE (right);
7472 derefaop = aopDerefAop (AOP (result));
7473 freeAsmop (result, NULL, ic, TRUE);
7474 derefaop->size = size;
7476 /* if the bitfield is a single bit in the direct page */
7477 if (blen == 1 && derefaop->type == AOP_DIR)
7479 if (AOP_TYPE (right) == AOP_LIT)
7481 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7483 emitcode ((litval & 1) ? "bset" : "bclr",
7484 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7488 symbol *tlbl1 = newiTempLabel (NULL);
7489 symbol *tlbl2 = newiTempLabel (NULL);
7491 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7492 emitcode ("bit", "#1");
7493 emitBranch ("bne", tlbl1);
7494 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7495 emitBranch ("bra", tlbl2);
7497 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7499 hc08_freeReg (hc08_reg_a);
7504 /* If the bitfield length is less than a byte */
7507 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7508 (unsigned char) (0xFF >> (8 - bstr)));
7510 if (AOP_TYPE (right) == AOP_LIT)
7512 /* Case with a bitfield length <8 and literal source
7514 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7516 litval &= (~mask) & 0xff;
7518 loadRegFromAop (hc08_reg_a, derefaop, 0);
7519 if ((mask|litval)!=0xff)
7520 emitcode ("and","#0x%02x", mask);
7522 emitcode ("ora","#0x%02x", litval);
7523 hc08_dirtyReg (hc08_reg_a, FALSE);
7524 storeRegToAop (hc08_reg_a, derefaop, 0);
7526 hc08_freeReg (hc08_reg_a);
7530 /* Case with a bitfield length < 8 and arbitrary source
7532 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7533 /* shift and mask source value */
7535 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7536 hc08_dirtyReg (hc08_reg_a, FALSE);
7537 pushReg (hc08_reg_a, TRUE);
7539 loadRegFromAop (hc08_reg_a, derefaop, 0);
7540 emitcode ("and", "#0x%02x", mask);
7541 emitcode ("ora", "1,s");
7542 storeRegToAop (hc08_reg_a, derefaop, 0);
7543 pullReg (hc08_reg_a);
7545 hc08_freeReg (hc08_reg_a);
7549 /* Bit length is greater than 7 bits. In this case, copy */
7550 /* all except the partial byte at the end */
7551 for (rlen=blen;rlen>=8;rlen-=8)
7553 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7557 /* If there was a partial byte at the end */
7560 mask = (((unsigned char) -1 << rlen) & 0xff);
7562 if (AOP_TYPE (right) == AOP_LIT)
7564 /* Case with partial byte and literal source
7566 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7567 litval >>= (blen-rlen);
7568 litval &= (~mask) & 0xff;
7569 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7570 if ((mask|litval)!=0xff)
7571 emitcode ("and","#0x%02x", mask);
7573 emitcode ("ora","#0x%02x", litval);
7574 hc08_dirtyReg (hc08_reg_a, FALSE);
7575 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7576 hc08_dirtyReg (hc08_reg_a, FALSE);
7577 hc08_freeReg (hc08_reg_a);
7581 /* Case with partial byte and arbitrary source
7583 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7584 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7585 hc08_dirtyReg (hc08_reg_a, FALSE);
7586 pushReg (hc08_reg_a, TRUE);
7588 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7589 emitcode ("and", "#0x%02x", mask);
7590 emitcode ("ora", "1,s");
7591 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7592 pullReg (hc08_reg_a);
7595 hc08_freeReg (hc08_reg_a);
7598 freeAsmop (right, NULL, ic, TRUE);
7599 freeAsmop (NULL, derefaop, ic, TRUE);
7602 /*-----------------------------------------------------------------*/
7603 /* genDataPointerSet - remat pointer to data space */
7604 /*-----------------------------------------------------------------*/
7606 genDataPointerSet (operand * right,
7613 D(emitcode ("; genDataPointerSet",""));
7615 aopOp (right, ic, FALSE);
7616 size = AOP_SIZE (right);
7618 derefaop = aopDerefAop (AOP (result));
7619 freeAsmop (result, NULL, ic, TRUE);
7620 derefaop->size = size;
7624 transferAopAop (AOP (right), size, derefaop, size);
7627 freeAsmop (right, NULL, ic, TRUE);
7628 freeAsmop (NULL, derefaop, ic, TRUE);
7632 /*-----------------------------------------------------------------*/
7633 /* genPointerSet - stores the value into a pointer location */
7634 /*-----------------------------------------------------------------*/
7636 genPointerSet (iCode * ic, iCode *pi)
7638 operand *right = IC_RIGHT (ic);
7639 operand *result = IC_RESULT (ic);
7640 sym_link *type, *etype;
7642 sym_link *retype = getSpec (operandType (right));
7643 sym_link *letype = getSpec (operandType (result));
7645 D(emitcode ("; genPointerSet",""));
7647 type = operandType (result);
7648 etype = getSpec (type);
7650 aopOp (result, ic, FALSE);
7652 /* if the result is rematerializable */
7653 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7655 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7657 genDataPointerSet (right, result, ic);
7662 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7667 /* if the operand is already in hx
7668 then we do nothing else we move the value to hx */
7669 if (AOP_TYPE (result) != AOP_STR)
7671 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7673 /* so hx now contains the address */
7674 aopOp (right, ic, FALSE);
7676 /* if bit then unpack */
7677 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7678 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7681 size = AOP_SIZE (right);
7686 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7687 accopWithMisc ("sta", ",x");
7690 emitcode ("aix", "#1");
7692 hc08_freeReg (hc08_reg_a);
7696 freeAsmop (result, NULL, ic, TRUE);
7697 freeAsmop (right, NULL, ic, TRUE);
7700 aopOp (IC_RESULT (pi), pi, FALSE);
7701 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7702 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7706 hc08_freeReg (hc08_reg_hx);
7710 /*-----------------------------------------------------------------*/
7711 /* genIfx - generate code for Ifx statement */
7712 /*-----------------------------------------------------------------*/
7714 genIfx (iCode * ic, iCode * popIc)
7716 operand *cond = IC_COND (ic);
7719 D(emitcode ("; genIfx",""));
7721 aopOp (cond, ic, FALSE);
7723 /* If the condition is a literal, we can just do an unconditional */
7724 /* branch or no branch */
7725 if (AOP_TYPE (cond) == AOP_LIT)
7727 unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
7728 freeAsmop (cond, NULL, ic, TRUE);
7730 /* if there was something to be popped then do it */
7736 emitBranch ("jmp", IC_TRUE (ic));
7741 emitBranch ("jmp", IC_FALSE (ic));
7747 /* get the value into acc */
7748 if (AOP_TYPE (cond) != AOP_CRY)
7749 asmopToBool (AOP (cond), FALSE);
7752 /* the result is now in the accumulator */
7753 freeAsmop (cond, NULL, ic, TRUE);
7755 /* if there was something to be popped then do it */
7759 /* if the condition is a bit variable */
7760 if (isbit && IS_ITEMP (cond) &&
7762 genIfxJump (ic, SPIL_LOC (cond)->rname);
7763 else if (isbit && !IS_ITEMP (cond))
7764 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7766 genIfxJump (ic, "a");
7771 /*-----------------------------------------------------------------*/
7772 /* genAddrOf - generates code for address of */
7773 /*-----------------------------------------------------------------*/
7775 genAddrOf (iCode * ic)
7777 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7780 D(emitcode ("; genAddrOf",""));
7782 aopOp (IC_RESULT (ic), ic, FALSE);
7784 /* if the operand is on the stack then we
7785 need to get the stack offset of this
7789 /* if it has an offset then we need to compute it */
7790 offset = _G.stackOfs + _G.stackPushes + sym->stack;
7791 hc08_useReg (hc08_reg_hx);
7792 emitcode ("tsx", "");
7793 while (offset > 127)
7795 emitcode ("aix", "#127");
7798 while (offset < -128)
7800 emitcode ("aix", "#-128");
7803 emitcode ("aix", "#%d", offset);
7804 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7805 hc08_freeReg (hc08_reg_hx);
7810 /* object not on stack then we need the name */
7811 size = AOP_SIZE (IC_RESULT (ic));
7816 char s[SDCC_NAME_MAX+10];
7819 sprintf (s, "#%s", sym->rname);
7822 sprintf (s, "#>%s", sym->rname);
7825 sprintf (s, "#(%s >> %d)",
7829 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7833 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7837 /*-----------------------------------------------------------------*/
7838 /* genAssign - generate code for assignment */
7839 /*-----------------------------------------------------------------*/
7841 genAssign (iCode * ic)
7843 operand *result, *right;
7845 // unsigned long lit = 0L;
7847 D(emitcode("; genAssign",""));
7849 result = IC_RESULT (ic);
7850 right = IC_RIGHT (ic);
7852 /* if they are the same */
7853 if (operandsEqu (result, right)) {
7857 aopOp (right, ic, FALSE);
7858 aopOp (result, ic, TRUE);
7860 /* if they are the same registers */
7861 if (sameRegs (AOP (right), AOP (result)))
7864 if ((AOP_TYPE (right) == AOP_LIT)
7865 && (IS_AOP_HX(AOP(result))))
7867 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7872 size = AOP_SIZE (result);
7875 transferAopAop (AOP (right), size, AOP (result), size);
7879 freeAsmop (right, NULL, ic, TRUE);
7880 freeAsmop (result, NULL, ic, TRUE);
7883 /*-----------------------------------------------------------------*/
7884 /* genJumpTab - generates code for jump table */
7885 /*-----------------------------------------------------------------*/
7887 genJumpTab (iCode * ic)
7890 symbol *jtablo = newiTempLabel (NULL);
7891 symbol *jtabhi = newiTempLabel (NULL);
7893 D(emitcode ("; genJumpTab",""));
7895 aopOp (IC_JTCOND (ic), ic, FALSE);
7897 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7899 /* get the condition into x */
7900 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7901 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7902 loadRegFromConst (hc08_reg_h, zero);
7904 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7905 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7906 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7907 emitcode ("jmp", ",x");
7909 hc08_dirtyReg (hc08_reg_a, TRUE);
7910 hc08_dirtyReg (hc08_reg_hx, TRUE);
7915 pushReg(hc08_reg_hx, TRUE);
7917 /* get the condition into x */
7918 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7919 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7920 loadRegFromConst (hc08_reg_h, zero);
7922 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7923 emitcode ("sta", "3,s");
7924 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7925 emitcode ("sta", "4,s");
7927 pullReg(hc08_reg_hx);
7928 emitcode ("rts", "");
7929 _G.stackPushes += 2;
7933 /* now generate the jump labels */
7935 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7936 jtab = setNextItem (IC_JTLABELS (ic)))
7937 emitcode (".db", "%05d$", jtab->key + 100);
7939 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7940 jtab = setNextItem (IC_JTLABELS (ic)))
7941 emitcode (".db", ">%05d$", jtab->key + 100);
7945 /*-----------------------------------------------------------------*/
7946 /* genCast - gen code for casting */
7947 /*-----------------------------------------------------------------*/
7949 genCast (iCode * ic)
7951 operand *result = IC_RESULT (ic);
7952 sym_link *ctype = operandType (IC_LEFT (ic));
7953 sym_link *rtype = operandType (IC_RIGHT (ic));
7954 operand *right = IC_RIGHT (ic);
7957 D(emitcode("; genCast",""));
7959 /* if they are equivalent then do nothing */
7960 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7963 aopOp (right, ic, FALSE);
7964 aopOp (result, ic, FALSE);
7967 /* if they are the same size : or less */
7968 if (AOP_SIZE (result) <= AOP_SIZE (right))
7971 /* if they are in the same place */
7973 if (sameRegs (AOP (right), AOP (result)))
7977 /* if they in different places then copy */
7978 size = AOP_SIZE (result);
7982 transferAopAop(AOP (right), offset, AOP (result), offset);
7989 /* if the result is of type pointer */
7994 sym_link *type = operandType (right);
7995 sym_link *etype = getSpec (type);
7997 /* pointer to generic pointer */
7998 if (IS_GENPTR (ctype))
8001 p_type = DCL_TYPE (type);
8004 if (SPEC_SCLS(etype)==S_REGISTER) {
8005 // let's assume it is a generic pointer
8008 /* we have to go by the storage class */
8009 p_type = PTR_TYPE (SPEC_OCLS (etype));
8013 /* the first two bytes are known */
8014 size = GPTRSIZE - 1;
8018 transferAopAop(AOP (right), offset, AOP (result), offset);
8021 /* the last byte depending on type */
8024 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8029 // pointerTypeToGPByte will have bitched.
8033 sprintf(gpValStr, "#0x%x", gpVal);
8034 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8040 /* just copy the pointers */
8041 size = AOP_SIZE (result);
8045 transferAopAop(AOP (right), offset, AOP (result), offset);
8051 /* so we now know that the size of destination is greater
8052 than the size of the source */
8053 /* we move to result for the size of source */
8054 size = AOP_SIZE (right);
8058 transferAopAop(AOP (right), offset, AOP (result), offset);
8062 /* now depending on the sign of the source && destination */
8063 size = AOP_SIZE (result) - AOP_SIZE (right);
8064 /* if unsigned or not an integral type */
8065 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8068 storeConstToAop (zero, AOP (result), offset++);
8072 /* we need to extend the sign :{ */
8073 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8074 accopWithMisc ("rola", "");
8075 accopWithMisc ("clra", "");
8076 accopWithMisc ("sbc", zero);
8078 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8081 /* we are done hurray !!!! */
8084 freeAsmop (right, NULL, ic, TRUE);
8085 freeAsmop (result, NULL, ic, TRUE);
8089 /*-----------------------------------------------------------------*/
8090 /* genDjnz - generate decrement & jump if not zero instrucion */
8091 /*-----------------------------------------------------------------*/
8093 genDjnz (iCode * ic, iCode * ifx)
8099 D(emitcode ("; genDjnz",""));
8101 /* if the if condition has a false label
8102 then we cannot save */
8106 /* if the minus is not of the form
8108 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8109 !IS_OP_LITERAL (IC_RIGHT (ic)))
8112 if (operandLitValue (IC_RIGHT (ic)) != 1)
8115 /* dbnz doesn't support extended mode */
8116 if (isOperandInFarSpace (IC_RESULT (ic)))
8119 /* if the size of this greater than one then no
8121 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8123 aopOp (IC_RESULT (ic), ic, FALSE);
8124 if (AOP_SIZE (IC_RESULT (ic))>1)
8126 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8130 /* otherwise we can save BIG */
8131 lbl = newiTempLabel (NULL);
8132 lbl1 = newiTempLabel (NULL);
8135 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8138 emitBranch ("bra", lbl1);
8140 emitBranch ("jmp", IC_TRUE (ifx));
8143 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8148 /*-----------------------------------------------------------------*/
8149 /* genReceive - generate code for a receive iCode */
8150 /*-----------------------------------------------------------------*/
8152 genReceive (iCode * ic)
8156 D(emitcode ("; genReceive",""));
8158 aopOp (IC_RESULT (ic), ic, FALSE);
8159 size = AOP_SIZE (IC_RESULT (ic));
8164 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8165 AOP (IC_RESULT (ic)), offset);
8166 if (hc08_aop_pass[offset]->type == AOP_REG)
8167 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8172 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8175 /*-----------------------------------------------------------------*/
8176 /* genDummyRead - generate code for dummy read of volatiles */
8177 /*-----------------------------------------------------------------*/
8179 genDummyRead (iCode * ic)
8184 D(emitcode("; genDummyRead",""));
8187 if (op && IS_SYMOP (op))
8190 aopOp (op, ic, FALSE);
8192 size = AOP_SIZE (op);
8197 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8198 hc08_freeReg (hc08_reg_a);
8202 freeAsmop (op, NULL, ic, TRUE);
8205 if (op && IS_SYMOP (op))
8208 aopOp (op, ic, FALSE);
8210 size = AOP_SIZE (op);
8215 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8216 hc08_freeReg (hc08_reg_a);
8220 freeAsmop (op, NULL, ic, TRUE);
8224 /*-----------------------------------------------------------------*/
8225 /* genCritical - generate code for start of a critical sequence */
8226 /*-----------------------------------------------------------------*/
8228 genCritical (iCode *ic)
8230 D(emitcode("; genCritical",""));
8233 aopOp (IC_RESULT (ic), ic, TRUE);
8235 emitcode ("tpa", "");
8236 hc08_dirtyReg (hc08_reg_a, FALSE);
8237 emitcode ("sei", "");
8240 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8242 pushReg (hc08_reg_a, FALSE);
8244 hc08_freeReg (hc08_reg_a);
8246 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8249 /*-----------------------------------------------------------------*/
8250 /* genEndCritical - generate code for end of a critical sequence */
8251 /*-----------------------------------------------------------------*/
8253 genEndCritical (iCode *ic)
8255 D(emitcode("; genEndCritical",""));
8259 aopOp (IC_RIGHT (ic), ic, FALSE);
8260 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8261 emitcode ("tap", "");
8262 hc08_freeReg (hc08_reg_a);
8263 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8267 pullReg (hc08_reg_a);
8268 emitcode ("tap", "");
8274 /*-----------------------------------------------------------------*/
8275 /* genhc08Code - generate code for HC08 based controllers */
8276 /*-----------------------------------------------------------------*/
8278 genhc08Code (iCode * lic)
8285 lineHead = lineCurr = NULL;
8287 /* print the allocation information */
8288 if (allocInfo && currFunc)
8289 printAllocInfo (currFunc, codeOutFile);
8290 /* if debug information required */
8291 if (options.debug && currFunc)
8293 debugFile->writeFunction (currFunc, lic);
8296 if (IS_STATIC (currFunc->etype))
8297 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8299 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8303 /* stack pointer name */
8304 if (options.useXstack)
8309 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8311 hc08_aop_pass[0] = newAsmop (AOP_REG);
8312 hc08_aop_pass[0]->size=1;
8313 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8314 hc08_aop_pass[1] = newAsmop (AOP_REG);
8315 hc08_aop_pass[1]->size=1;
8316 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8317 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8318 hc08_aop_pass[2]->size=1;
8319 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8320 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8321 hc08_aop_pass[3]->size=1;
8322 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8324 for (ic = lic; ic; ic = ic->next)
8327 _G.current_iCode = ic;
8329 if (ic->level != clevel || ic->block != cblock)
8333 debugFile->writeScope(ic);
8339 if (ic->lineno && cln != ic->lineno)
8343 debugFile->writeCLine(ic);
8346 emitcode ("", "C$%s$%d$%d$%d ==.",
8347 FileBaseName (ic->filename), ic->lineno,
8348 ic->level, ic->block);
8352 if (!options.noCcodeInAsm) {
8353 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8354 printCLine(ic->filename, ic->lineno));
8358 if (options.iCodeInAsm) {
8362 for (i=0; i<6; i++) {
8363 sprintf (®sInUse[i],
8364 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8367 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8369 /* if the result is marked as
8370 spilt and rematerializable or code for
8371 this has already been generated then
8373 if (resultRemat (ic) || ic->generated)
8381 for (i=A_IDX;i<=XA_IDX;i++)
8383 reg = hc08_regWithIdx(i);
8385 emitcode("","; %s = %s offset %d", reg->name,
8386 aopName(reg->aop), reg->aopofs);
8389 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8391 sym = OP_SYMBOL (IC_LEFT (ic));
8392 if (sym->accuse == ACCUSE_HX)
8394 hc08_reg_h->isFree = FALSE;
8395 hc08_reg_x->isFree = FALSE;
8397 else if (sym->accuse == ACCUSE_XA)
8399 hc08_reg_a->isFree = FALSE;
8401 hc08_reg_x->isFree = FALSE;
8404 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8406 sym = OP_SYMBOL (IC_RIGHT (ic));
8407 if (sym->accuse == ACCUSE_HX)
8409 hc08_reg_h->isFree = FALSE;
8410 hc08_reg_x->isFree = FALSE;
8412 else if (sym->accuse == ACCUSE_XA)
8414 hc08_reg_a->isFree = FALSE;
8416 hc08_reg_x->isFree = FALSE;
8421 /* depending on the operation */
8441 /* IPOP happens only when trying to restore a
8442 spilt live range, if there is an ifx statement
8443 following this pop then the if statement might
8444 be using some of the registers being popped which
8445 would destory the contents of the register so
8446 we need to check for this condition and handle it */
8448 ic->next->op == IFX &&
8449 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8450 genIfx (ic->next, ic);
8468 genEndFunction (ic);
8484 if (!genPointerGetSetOfs (ic))
8489 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8509 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8514 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8526 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8530 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8534 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8561 case GET_VALUE_AT_ADDRESS:
8563 hasInc (IC_LEFT (ic), ic,
8564 getSize (operandType (IC_RESULT (ic)))),
8565 ifxForOp (IC_RESULT (ic), ic) );
8569 if (POINTER_SET (ic))
8570 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8596 addSet (&_G.sendSet, ic);
8599 case DUMMY_READ_VOLATILE:
8608 genEndCritical (ic);
8619 if (!hc08_reg_a->isFree)
8620 D(emitcode("","; forgot to free a"));
8621 if (!hc08_reg_x->isFree)
8622 D(emitcode("","; forgot to free x"));
8623 if (!hc08_reg_h->isFree)
8624 D(emitcode("","; forgot to free h"));
8625 if (!hc08_reg_hx->isFree)
8626 D(emitcode("","; forgot to free hx"));
8627 if (!hc08_reg_xa->isFree)
8628 D(emitcode("","; forgot to free xa"));
8631 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8634 /* now we are ready to call the
8635 peep hole optimizer */
8636 if (!options.nopeep)
8637 peepHole (&lineHead);
8639 /* now do the actual printing */
8640 printLine (lineHead, codeOutFile);