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);
49 static char *zero = "#0x00";
50 static char *one = "#0x01";
54 {"a", "x", "_ret2", "_ret3"};
55 unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */
56 char **fReturn2 = fReturnhc08;
74 static asmop *hc08_aop_pass[4];
76 extern int hc08_ptrRegReq;
77 extern int hc08_nRegs;
78 extern FILE *codeOutFile;
79 //static void saveRBank (int, iCode *, bool);
80 static bool operandsEqu (operand * op1, operand * op2);
81 static void loadRegFromConst (regs *reg, char *c);
82 static char *aopName (asmop *aop);
83 static asmop * newAsmop (short type);
84 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
85 #define RESULTONSTACK(x) \
86 (IC_RESULT(x) && IC_RESULT(x)->aop && \
87 IC_RESULT(x)->aop->type == AOP_STK )
89 #define IS_AOP_HX(x) \
90 (((x)->type == AOP_REG) \
91 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
92 && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
94 #define IS_AOP_XA(x) \
95 (((x)->type == AOP_REG) \
96 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
97 && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
100 (((x)->type == AOP_REG) \
101 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
102 && ((x)->size == 1) )
104 #define IS_AOP_X(x) \
105 (((x)->type == AOP_REG) \
106 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
107 && ((x)->size == 1) )
109 #define IS_AOP_H(x) \
110 (((x)->type == AOP_REG) \
111 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
112 && ((x)->size == 1) )
114 #define CLRC emitcode("clc","")
116 static lineNode *lineHead = NULL;
117 static lineNode *lineCurr = NULL;
120 static unsigned char SLMask[] =
121 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char SRMask[] =
124 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
125 0x07, 0x03, 0x01, 0x00};
133 #define AOP(op) op->aop
134 #define AOP_TYPE(op) AOP(op)->type
135 #define AOP_SIZE(op) AOP(op)->size
136 #define AOP_OP(aop) aop->op
139 /*-----------------------------------------------------------------*/
140 /* emitcode - writes the code into a file : for now it is simple */
141 /*-----------------------------------------------------------------*/
143 emitcode (char *inst, char *fmt,...)
146 char lb[INITIAL_INLINEASM];
154 sprintf (lb, "%s\t", inst);
156 sprintf (lb, "%s", inst);
157 vsprintf (lb + (strlen (lb)), fmt, ap);
160 vsprintf (lb, fmt, ap);
162 while (isspace (*lbp))
166 lineCurr = (lineCurr ?
167 connectLine (lineCurr, newLineNode (lb)) :
168 (lineHead = newLineNode (lb)));
169 lineCurr->isInline = _G.inLine;
170 lineCurr->isDebug = _G.debugLine;
172 //printf("%s\n", lb);
177 emitBranch (char *branchop, symbol *tlbl)
179 emitcode (branchop, "%05d$", (tlbl->key + 100));
183 emitLabel (symbol *tlbl)
185 emitcode ("", "%05d$:", (tlbl->key +100));
190 /*--------------------------------------------------------------------------*/
191 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
192 /* freesrc is true, sreg is marked free and available for */
193 /* reuse. sreg and dreg must be of equal size */
194 /*--------------------------------------------------------------------------*/
196 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
202 /* Nothing to do if no destination. */
206 /* But it's definately an error if there's no source. */
209 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
210 "NULL sreg in transferRegReg");
214 D(emitcode ("", "; transferRegReg(%s,%s)",
215 sreg->name, dreg->name));
228 case H_IDX: /* H to A */
229 emitcode ("pshh", "");
230 emitcode ("pula", "");
232 case X_IDX: /* X to A */
233 emitcode ("txa", "");
242 case A_IDX: /* A to H */
243 emitcode ("psha", "");
244 emitcode ("pulh", "");
246 case X_IDX: /* X to H */
247 emitcode ("pshx", "");
248 emitcode ("pulh", "");
257 case A_IDX: /* A to X */
258 emitcode ("tax", "");
260 case H_IDX: /* H to X */
261 emitcode ("pshh", "");
262 emitcode ("pulx", "");
271 case XA_IDX: /* XA to HX */
272 emitcode ("pshx", "");
273 emitcode ("pulh", "");
274 emitcode ("tax", "");
283 case HX_IDX: /* HX to XA */
284 emitcode ("txa", "");
285 emitcode ("pshh", "");
286 emitcode ("pulx", "");
296 wassertl (!error, "bad combo in transferRegReg");
301 dreg->aop = sreg->aop;
302 dreg->aopofs = sreg->aopofs;
303 dreg->isFree = FALSE;
307 /*--------------------------------------------------------------------------*/
308 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
309 /* marked free and available for reuse. */
310 /*--------------------------------------------------------------------------*/
312 pushReg (regs *reg, bool freereg)
314 int regidx = reg->rIdx;
319 emitcode ("psha", "");
323 emitcode ("pshx", "");
327 emitcode ("pshh", "");
331 emitcode ("pshx", "");
332 emitcode ("pshh", "");
336 emitcode ("psha", "");
337 emitcode ("pshx", "");
345 return -_G.stackOfs-_G.stackPushes;
348 /*--------------------------------------------------------------------------*/
349 /* pullReg - Pull register reg off the stack. */
350 /*--------------------------------------------------------------------------*/
354 int regidx = reg->rIdx;
359 emitcode ("pula", "");
363 emitcode ("pulx", "");
367 emitcode ("pulh", "");
371 emitcode ("pulx", "");
372 emitcode ("pulh", "");
376 emitcode ("pula", "");
377 emitcode ("pulx", "");
384 hc08_dirtyReg(reg, FALSE);
387 /*--------------------------------------------------------------------------*/
388 /* pullNull - Discard n bytes off the top of the stack */
389 /*--------------------------------------------------------------------------*/
395 emitcode("ais","#%d",n);
400 /*--------------------------------------------------------------------------*/
401 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
402 /* push was performed, false otherwise. */
403 /*--------------------------------------------------------------------------*/
405 pushRegIfUsed (regs *reg)
416 /*--------------------------------------------------------------------------*/
417 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
418 /* stack. Otherwise register reg is marked as free. */
419 /*--------------------------------------------------------------------------*/
421 pullOrFreeReg (regs *reg, bool needpull)
429 /*--------------------------------------------------------------------------*/
430 /* adjustStack - Adjust the stack pointer by n bytes. */
431 /*--------------------------------------------------------------------------*/
440 emitcode ("ais","#127");
445 emitcode ("ais","#-128");
450 emitcode ("ais", "#%d", n);
457 /*--------------------------------------------------------------------------*/
458 /* aopName - Return a string with debugging information about an asmop. */
459 /*--------------------------------------------------------------------------*/
463 static char buffer[256];
467 return "(asmop*)NULL";
472 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
475 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
478 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
481 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
484 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
487 sprintf (buf, "REG(%s,%s,%s,%s)",
488 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
489 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
490 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
491 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
498 sprintf (buf,"?%d", aop->type);
506 /*--------------------------------------------------------------------------*/
507 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
508 /*--------------------------------------------------------------------------*/
510 loadRegFromAop (regs *reg, asmop *aop, int loffset)
512 int regidx = reg->rIdx;
514 if (aop->stacked && aop->stk_aop[loffset])
516 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
521 printf("loadRegFromAop called\n");
524 printf(" reg = NULL\n");
527 printf(" reg = %s\n", reg->name);
530 printf(" aop = NULL\n");
533 printf(" aop->type = %d\n", aop->type);
534 printf(" loffset = %d\n", loffset);
537 printf(" aop has operand link\n");
539 printf(" aop missing operand link\n");
541 printf(" reg has operand link\n");
543 printf(" reg missing operand link\n");
546 D(emitcode ("", "; loadRegFromAop (%s, %s, %d)",
547 reg->name, aopName (aop), loffset));
549 /* If operand is volatile, we cannot optimize. */
550 if (!aop->op || isOperandVolatile (aop->op, FALSE))
554 /* If this register already has this offset of the operand
555 then we need only mark it as in use. */
556 if (reg->aop && reg->aop->op && aop->op
557 && operandsEqu(reg->aop->op,aop->op)
558 && (reg->aopofs == loffset))
561 D(emitcode ("","; already had correct value for %s", reg->name));
565 /* TODO: check to see if we can transfer from another register */
567 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
568 && operandsEqu(hc08_reg_h->aop->op,aop->op)
569 && (hc08_reg_h->aopofs == loffset))
571 D(emitcode ("","; found correct value for %s in h", reg->name));
572 transferRegReg (hc08_reg_h, reg, FALSE);
578 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
579 && operandsEqu(hc08_reg_x->aop->op,aop->op)
580 && (hc08_reg_x->aopofs == loffset))
582 D(emitcode ("","; found correct value for %s in x", reg->name));
583 transferRegReg (hc08_reg_x, reg, FALSE);
588 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
589 && operandsEqu(hc08_reg_a->aop->op,aop->op)
590 && (hc08_reg_a->aopofs == loffset))
592 D(emitcode ("","; found correct value for %s in a", reg->name));
593 transferRegReg (hc08_reg_a, reg, FALSE);
603 if (aop->type == AOP_REG)
605 if (loffset < aop->size)
606 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
608 emitcode ("clra", ""); /* TODO: handle sign extension */
611 emitcode ("lda","%s", aopAdrStr (aop, loffset, FALSE));
614 if (aop->type == AOP_REG)
616 if (loffset < aop->size)
617 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
619 emitcode ("clrx", ""); /* TODO: handle sign extension */
622 emitcode ("ldx","%s", aopAdrStr (aop, loffset, FALSE));
625 if (hc08_reg_a->isFree)
627 loadRegFromAop (hc08_reg_a, aop, loffset);
628 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
630 else if (hc08_reg_x->isFree)
632 loadRegFromAop (hc08_reg_x, aop, loffset);
633 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
637 pushReg (hc08_reg_a, TRUE);
638 loadRegFromAop (hc08_reg_a, aop, loffset);
639 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
640 pullReg (hc08_reg_a);
646 else if (IS_AOP_XA(aop))
647 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
648 else if ((aop->type == AOP_DIR))
650 if (aop->size>(loffset+1))
651 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
654 loadRegFromAop (hc08_reg_x, aop, loffset);
655 loadRegFromConst (hc08_reg_h, zero);
658 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
660 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
665 needpula = pushRegIfUsed (hc08_reg_a);
666 loadRegFromAop (hc08_reg_a, aop, loffset+1);
667 loadRegFromAop (hc08_reg_x, aop, loffset);
668 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
669 pullOrFreeReg (hc08_reg_a, needpula);
675 else if (IS_AOP_HX(aop))
676 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
679 loadRegFromAop (hc08_reg_a, aop, loffset);
680 loadRegFromAop (hc08_reg_x, aop, loffset+1);
685 // ignore caching for now
688 reg->aopofs = loffset;
693 /*--------------------------------------------------------------------------*/
694 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
695 /* freeAsmop is called with aop, the stacked data will */
696 /* be copied to the original aop location and */
697 /*--------------------------------------------------------------------------*/
699 forceStackedAop (asmop *aop)
702 asmop *newaop = newAsmop (aop->type);
703 memcpy (newaop, aop, sizeof(*newaop));
705 D(emitcode("", "; forcedStackAop %s", aopName(aop)));
706 for (loffset=0; loffset < newaop->size; loffset++)
708 asmop *aopsof = newAsmop (AOP_SOF);
710 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
711 aopsof->op = aop->op;
712 newaop->stk_aop[loffset] = aopsof;
719 /*--------------------------------------------------------------------------*/
720 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
721 /*--------------------------------------------------------------------------*/
723 storeRegToAop (regs *reg, asmop *aop, int loffset)
725 int regidx = reg->rIdx;
731 D(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
732 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
734 if ((reg->rIdx == HX_IDX) && aop->stacked
735 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
737 storeRegToAop (hc08_reg_h, aop, loffset+1);
738 storeRegToAop (hc08_reg_x, aop, loffset);
742 if ((reg->rIdx == XA_IDX) && aop->stacked
743 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
745 storeRegToAop (hc08_reg_x, aop, loffset+1);
746 storeRegToAop (hc08_reg_a, aop, loffset);
750 if (aop->stacked && aop->stk_aop[loffset])
752 storeRegToAop (reg, aop->stk_aop[loffset], 0);
756 if (aop->type == AOP_STR)
759 transferRegReg (reg, hc08_reg_x, FALSE);
761 transferRegReg (reg, hc08_reg_h, FALSE);
765 if (aop->type == AOP_DUMMY)
771 if ((aop->type == AOP_REG) && (loffset < aop->size))
772 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
774 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
777 if ((aop->type == AOP_REG) && (loffset < aop->size))
778 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
780 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
783 if (hc08_reg_a->isFree)
785 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
786 storeRegToAop (hc08_reg_a, aop, loffset);
787 hc08_freeReg (hc08_reg_a);
789 else if (hc08_reg_x->isFree)
791 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
792 storeRegToAop (hc08_reg_x, aop, loffset);
793 hc08_freeReg (hc08_reg_x);
797 pushReg (hc08_reg_a, TRUE);
798 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
799 storeRegToAop (hc08_reg_a, aop, loffset);
800 pullReg (hc08_reg_a);
804 if ((aop->type == AOP_DIR) )
806 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
808 else if (IS_AOP_XA(aop))
809 transferRegReg(reg, hc08_reg_xa, FALSE);
810 else if (IS_AOP_HX(aop))
815 needpula = pushRegIfUsed (hc08_reg_a);
816 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
817 storeRegToAop (hc08_reg_a, aop, loffset+1);
818 storeRegToAop (hc08_reg_x, aop, loffset);
819 pullOrFreeReg (hc08_reg_a, needpula);
824 transferRegReg(reg, hc08_reg_hx, FALSE);
825 else if (IS_AOP_XA(aop))
829 storeRegToAop (hc08_reg_a, aop, loffset);
830 storeRegToAop (hc08_reg_x, aop, loffset+1);
835 /* Disable the register tracking for now */
837 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
840 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
842 otherreg=hc08_regWithIdx(otheridx);
843 if (otherreg && otherreg->aop
844 && otherreg->aop->op && aop->op
845 && operandsEqu(otherreg->aop->op,aop->op)
846 && (otherreg->aopofs == loffset))
848 D(emitcode("","; marking %s stale", otherreg->name));
852 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
854 hc08_reg_hx->aop = NULL;
855 D(emitcode("","; marking hx stale"));
857 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
859 hc08_reg_xa->aop = NULL;
860 D(emitcode("","; marking xa stale"));
864 reg->aopofs = loffset;
869 /*--------------------------------------------------------------------------*/
870 /* loadRegFromConst - Load register reg from constant c. */
871 /*--------------------------------------------------------------------------*/
873 loadRegFromConst (regs *reg, char *c)
879 emitcode ("clra", "");
881 emitcode ("lda", "%s", c);
885 emitcode ("clrx", "");
887 emitcode ("ldx", "%s", c);
891 emitcode ("clrh", "");
892 else if (hc08_reg_a->isFree)
894 loadRegFromConst (hc08_reg_a, c);
895 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
897 else if (hc08_reg_x->isFree)
899 loadRegFromConst (hc08_reg_x, c);
900 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
904 pushReg (hc08_reg_a, TRUE);
905 loadRegFromConst (hc08_reg_a, c);
906 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
907 pullReg (hc08_reg_a);
911 emitcode ("ldhx", "%s", c);
914 emitcode ("lda", "%s", c);
915 emitcode ("ldx", "%s >> 8", c);
918 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
919 "Bad rIdx in loadRegFromConst");
926 /*--------------------------------------------------------------------------*/
927 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
928 /*--------------------------------------------------------------------------*/
930 storeConstToAop (char *c, asmop *aop, int loffset)
932 if (aop->stacked && aop->stk_aop[loffset])
934 storeConstToAop (c, aop->stk_aop[loffset], 0);
942 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
944 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
947 if (loffset>(aop->size-1))
949 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
954 if (hc08_reg_a->isFree)
956 loadRegFromConst (hc08_reg_a, c);
957 storeRegToAop( hc08_reg_a, aop, loffset);
958 hc08_freeReg (hc08_reg_a);
960 else if (hc08_reg_x->isFree)
962 loadRegFromConst (hc08_reg_x, c);
963 storeRegToAop( hc08_reg_x, aop, loffset);
964 hc08_freeReg (hc08_reg_x);
968 pushReg (hc08_reg_a, TRUE);
969 loadRegFromConst (hc08_reg_a, c);
970 storeRegToAop( hc08_reg_a, aop, loffset);
971 pullReg (hc08_reg_a);
977 /*--------------------------------------------------------------------------*/
978 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
979 /* reg is extended to fill logical offsets loffset */
980 /* and above of asmop aop. Otherwise, logical */
981 /* offsets loffset and above of asmop aop are */
982 /* zeroed. reg must be an 8-bit register. */
983 /*--------------------------------------------------------------------------*/
985 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
987 // int regidx = reg->rIdx;
988 int size = aop->size;
997 storeConstToAop(zero, aop, loffset++);
1002 transferRegReg (reg, hc08_reg_a, FALSE);
1003 emitcode ("rola","");
1004 emitcode ("clra","");
1005 emitcode ("sbc", "#0");
1006 hc08_useReg (hc08_reg_a);
1007 while (loffset<size)
1008 storeRegToAop (hc08_reg_a, aop, loffset++);
1009 hc08_freeReg (hc08_reg_a);
1013 /*--------------------------------------------------------------------------*/
1014 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1015 /* padding and/or truncation as needed. If isSigned is */
1016 /* true, sign extension will take place in the padding. */
1017 /*--------------------------------------------------------------------------*/
1019 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1021 int regidx = reg->rIdx;
1022 int size = aop->size;
1029 storeRegToAop (reg, aop, 0);
1030 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1035 storeRegToAop (hc08_reg_x, aop, 0);
1039 storeRegToAop (reg, aop, 0);
1040 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1046 storeRegToAop (hc08_reg_a, aop, 0);
1050 storeRegToAop (reg, aop, 0);
1051 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1057 /*--------------------------------------------------------------------------*/
1058 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1059 /* srcaop to logical offset dstofs of asmop dstofs. */
1060 /*--------------------------------------------------------------------------*/
1062 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1064 bool needpula = FALSE;
1067 bool keepreg = FALSE;
1069 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1071 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1075 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1077 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1081 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1082 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1083 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1084 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1086 if (dstofs >= dstaop->size)
1089 if ((dstaop->type == AOP_DIR)
1090 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1092 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1093 aopAdrStr(dstaop, dstofs, FALSE));
1097 if (dstaop->type == AOP_REG)
1099 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1100 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1102 reg = dstaop->aopu.aop_reg[dstofs];
1107 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1109 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1110 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1112 reg = srcaop->aopu.aop_reg[srcofs];
1119 if (hc08_reg_a->isFree)
1121 else if (hc08_reg_x->isFree)
1125 pushReg (hc08_reg_a, TRUE);
1131 loadRegFromAop (reg, srcaop, srcofs);
1132 storeRegToAop (reg, dstaop, dstofs);
1135 pullOrFreeReg (hc08_reg_a, needpula);
1139 /*--------------------------------------------------------------------------*/
1140 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1141 /* parameter param. */
1142 /*--------------------------------------------------------------------------*/
1144 accopWithMisc (char *accop, char *param)
1146 emitcode (accop, "%s", param);
1147 hc08_dirtyReg (hc08_reg_a, FALSE);
1150 /*--------------------------------------------------------------------------*/
1151 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1152 /* byte at logical offset loffset of asmop aop. */
1153 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1154 /*--------------------------------------------------------------------------*/
1156 accopWithAop (char *accop, asmop *aop, int loffset)
1158 if (aop->stacked && aop->stk_aop[loffset])
1160 accopWithAop (accop, aop->stk_aop[loffset], 0);
1164 if (aop->type == AOP_DUMMY)
1167 if (aop->type == AOP_REG)
1169 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1170 emitcode (accop, "1,s");
1174 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1176 hc08_dirtyReg (hc08_reg_a, FALSE);
1180 /*--------------------------------------------------------------------------*/
1181 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1182 /* byte at logical offset loffset of asmop aop. Register reg */
1183 /* must be 8-bit. */
1184 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1185 /*--------------------------------------------------------------------------*/
1187 rmwWithReg (char *rmwop, regs *reg)
1190 char *rmwaop = rmwbuf;
1192 if (reg->rIdx == A_IDX)
1194 sprintf(rmwaop,"%sa", rmwop);
1195 emitcode (rmwaop, "");
1196 hc08_dirtyReg (hc08_reg_a, FALSE);
1198 else if (reg->rIdx == X_IDX)
1200 sprintf(rmwaop,"%sx", rmwop);
1201 emitcode (rmwaop, "");
1202 hc08_dirtyReg (hc08_reg_a, FALSE);
1204 else if (hc08_reg_a->isFree)
1206 transferRegReg(reg, hc08_reg_a, FALSE);
1207 sprintf(rmwaop,"%sa", rmwop);
1208 emitcode (rmwaop, "");
1209 hc08_dirtyReg (hc08_reg_a, FALSE);
1210 transferRegReg(hc08_reg_a, reg, TRUE);
1214 pushReg (reg, FALSE);
1215 emitcode (rmwop, "1,s");
1217 hc08_dirtyReg (reg, FALSE);
1221 /*--------------------------------------------------------------------------*/
1222 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1223 /* logical offset loffset of asmop aop. */
1224 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1225 /*--------------------------------------------------------------------------*/
1227 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1229 bool needpula = FALSE;
1231 if (aop->stacked && aop->stk_aop[loffset])
1233 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1240 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1243 needpula = pushRegIfUsed (hc08_reg_a);
1244 loadRegFromAop (hc08_reg_a, aop, loffset);
1245 rmwWithReg (rmwop, hc08_reg_a);
1246 storeRegToAop (hc08_reg_a, aop, loffset);
1247 pullOrFreeReg (hc08_reg_a, needpula);
1252 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1258 /*-----------------------------------------------------------------*/
1259 /* newAsmop - creates a new asmOp */
1260 /*-----------------------------------------------------------------*/
1262 newAsmop (short type)
1266 aop = Safe_calloc (1, sizeof (asmop));
1273 /*-----------------------------------------------------------------*/
1274 /* pointerCode - returns the code for a pointer type */
1275 /*-----------------------------------------------------------------*/
1277 pointerCode (sym_link * etype)
1280 return PTR_TYPE (SPEC_OCLS (etype));
1285 /*-----------------------------------------------------------------*/
1286 /* aopForSym - for a true symbol */
1287 /*-----------------------------------------------------------------*/
1289 aopForSym (iCode * ic, symbol * sym, bool result)
1294 wassertl (ic != NULL, "Got a null iCode");
1295 wassertl (sym != NULL, "Got a null symbol");
1297 // printf("in aopForSym for symbol %s\n", sym->name);
1299 space = SPEC_OCLS (sym->etype);
1301 /* if already has one */
1307 /* special case for a function */
1308 if (IS_FUNC (sym->type))
1310 sym->aop = aop = newAsmop (AOP_IMMD);
1311 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1312 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1313 aop->size = FPTRSIZE;
1317 /* if it is in direct space */
1318 if (IN_DIRSPACE (space))
1320 sym->aop = aop = newAsmop (AOP_DIR);
1321 aop->aopu.aop_dir = sym->rname;
1322 aop->size = getSize (sym->type);
1326 /* if it is in far space */
1327 if (IN_FARSPACE (space))
1329 sym->aop = aop = newAsmop (AOP_EXT);
1330 aop->aopu.aop_dir = sym->rname;
1331 aop->size = getSize (sym->type);
1335 if (IN_STACK (sym->etype))
1337 sym->aop = aop = newAsmop (AOP_SOF);
1338 aop->aopu.aop_dir = sym->rname;
1339 aop->size = getSize (sym->type);
1340 aop->aopu.aop_stk = sym->stack;
1346 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1347 "aopForSym should never reach here");
1351 /* if it is in code space */
1352 if (IN_CODESPACE (space))
1358 /*-----------------------------------------------------------------*/
1359 /* aopForRemat - rematerialzes an object */
1360 /*-----------------------------------------------------------------*/
1362 aopForRemat (symbol * sym)
1364 iCode *ic = sym->rematiCode;
1372 val += (int) operandLitValue (IC_RIGHT (ic));
1373 else if (ic->op == '-')
1374 val -= (int) operandLitValue (IC_RIGHT (ic));
1375 else if (IS_CAST_ICODE(ic)) {
1376 sym_link *from_type = operandType(IC_RIGHT(ic));
1377 aop->aopu.aop_immd.from_cast_remat = 1;
1378 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1379 ptr_type = DCL_TYPE(from_type);
1380 if (ptr_type == IPOINTER) {
1387 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1390 if (ic->op == ADDRESS_OF)
1393 sprintf (buffer, "(%s %c 0x%04x)",
1394 OP_SYMBOL (IC_LEFT (ic))->rname,
1395 val >= 0 ? '+' : '-',
1396 abs (val) & 0xffff);
1398 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1400 aop = newAsmop (AOP_IMMD);
1401 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1402 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1403 /* set immd2 field if required */
1404 if (aop->aopu.aop_immd.from_cast_remat)
1406 sprintf(buffer,"#0x%02x",ptr_type);
1407 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1408 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1411 else if (ic->op == '=')
1413 val += (int) operandLitValue (IC_RIGHT (ic));
1415 sprintf (buffer, "0x%04x", val);
1416 aop = newAsmop (AOP_LIT);
1417 aop->aopu.aop_lit = constVal (buffer);
1420 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1421 "unexpected rematerialization");
1428 /*-----------------------------------------------------------------*/
1429 /* regsInCommon - two operands have some registers in common */
1430 /*-----------------------------------------------------------------*/
1432 regsInCommon (operand * op1, operand * op2)
1434 symbol *sym1, *sym2;
1437 /* if they have registers in common */
1438 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1441 sym1 = OP_SYMBOL (op1);
1442 sym2 = OP_SYMBOL (op2);
1444 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1447 for (i = 0; i < sym1->nRegs; i++)
1453 for (j = 0; j < sym2->nRegs; j++)
1458 if (sym2->regs[j] == sym1->regs[i])
1466 /*-----------------------------------------------------------------*/
1467 /* operandsEqu - equivalent */
1468 /*-----------------------------------------------------------------*/
1470 operandsEqu (operand * op1, operand * op2)
1472 symbol *sym1, *sym2;
1474 /* if they not symbols */
1475 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1478 sym1 = OP_SYMBOL (op1);
1479 sym2 = OP_SYMBOL (op2);
1481 /* if both are itemps & one is spilt
1482 and the other is not then false */
1483 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1484 sym1->isspilt != sym2->isspilt)
1487 /* if they are the same */
1491 if (strcmp (sym1->rname, sym2->rname) == 0)
1495 /* if left is a tmp & right is not */
1496 if (IS_ITEMP (op1) &&
1499 (sym1->usl.spillLoc == sym2))
1502 if (IS_ITEMP (op2) &&
1506 (sym2->usl.spillLoc == sym1))
1512 /*-----------------------------------------------------------------*/
1513 /* sameRegs - two asmops have the same registers */
1514 /*-----------------------------------------------------------------*/
1516 sameRegs (asmop * aop1, asmop * aop2)
1523 // if (aop1->size != aop2->size)
1526 if (aop1->type == aop2->type)
1531 for (i = 0; i < aop1->size; i++)
1532 if (aop1->aopu.aop_reg[i] !=
1533 aop2->aopu.aop_reg[i])
1537 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1540 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1547 /*-----------------------------------------------------------------*/
1548 /* aopOp - allocates an asmop for an operand : */
1549 /*-----------------------------------------------------------------*/
1551 aopOp (operand * op, iCode * ic, bool result)
1560 // Is this a pointer set result?
1562 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1566 // printf("checking literal\n");
1567 /* if this a literal */
1568 if (IS_OP_LITERAL (op))
1570 op->aop = aop = newAsmop (AOP_LIT);
1571 aop->aopu.aop_lit = op->operand.valOperand;
1572 aop->size = getSize (operandType (op));
1574 aop->isaddr = op->isaddr;
1578 // printf("checking pre-existing\n");
1579 /* if already has a asmop then continue */
1583 op->aop->isaddr = op->isaddr;
1587 // printf("checking underlying sym\n");
1588 /* if the underlying symbol has a aop */
1589 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1591 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1592 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1593 //op->aop = aop = OP_SYMBOL (op)->aop;
1594 aop->size = getSize( operandType (op));
1595 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1596 //printf (" with size = %d\n", aop->size);
1599 aop->isaddr = op->isaddr;
1600 /* if (aop->isaddr & IS_ITEMP (op))
1602 aop->psize=aop->size;
1603 aop->size = getSize( operandType (op)->next);
1608 // printf("checking true sym\n");
1609 /* if this is a true symbol */
1610 if (IS_TRUE_SYMOP (op))
1612 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1614 aop->isaddr = op->isaddr;
1615 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1616 //printf (" with size = %d\n", aop->size);
1620 /* this is a temporary : this has
1626 e) can be a return use only */
1628 sym = OP_SYMBOL (op);
1630 // printf("checking conditional\n");
1631 /* if the type is a conditional */
1632 if (sym->regType == REG_CND)
1634 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1637 aop->isaddr = op->isaddr;
1641 // printf("checking spilt\n");
1642 /* if it is spilt then two situations
1644 b) has a spill location */
1645 if (sym->isspilt || sym->nRegs == 0)
1648 // printf("checking remat\n");
1649 /* rematerialize it NOW */
1652 sym->aop = op->aop = aop =
1654 aop->size = getSize (sym->type);
1656 aop->isaddr = op->isaddr;
1657 /* if (aop->isaddr & IS_ITEMP (op))
1659 aop->psize=aop->size;
1660 aop->size = getSize( operandType (op)->next);
1665 // printf("checking accuse\n");
1668 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1669 aop->size = getSize (sym->type);
1670 switch (sym->accuse)
1673 aop->aopu.aop_reg[0] = hc08_reg_a;
1674 aop->aopu.aop_reg[1] = hc08_reg_x;
1677 aop->aopu.aop_reg[0] = hc08_reg_x;
1678 aop->aopu.aop_reg[1] = hc08_reg_h;
1682 aop->isaddr = op->isaddr;
1686 // printf("checking ruonly\n");
1692 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1693 aop->size = getSize (sym->type);
1694 for (i = 0; i < fReturnSizeHC08; i++)
1695 aop->aopu.aop_str[i] = fReturn2[i];
1697 aop->isaddr = op->isaddr;
1701 /* else spill location */
1702 if (sym->usl.spillLoc)
1704 if (sym->usl.spillLoc->aop
1705 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1707 /* force a new aop if sizes differ */
1708 sym->usl.spillLoc->aop = NULL;
1709 //printf ("forcing new aop\n");
1711 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1712 aop->size = getSize (sym->type);
1714 aop->isaddr = op->isaddr;
1715 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1716 //printf (" with size = %d\n", aop->size);
1720 /* else must be a dummy iTemp */
1721 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1722 aop->size = getSize (sym->type);
1726 // printf("assuming register\n");
1727 /* must be in a register */
1728 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1729 aop->size = sym->nRegs;
1730 for (i = 0; i < sym->nRegs; i++)
1731 aop->aopu.aop_reg[i] = sym->regs[i];
1733 aop->isaddr = op->isaddr;
1737 /*-----------------------------------------------------------------*/
1738 /* freeAsmop - free up the asmop given to an operand */
1739 /*----------------------------------------------------------------*/
1741 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1763 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1766 for (loffset=0; loffset<aop->size; loffset++)
1767 if (aop->stk_aop[loffset])
1769 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1772 pullNull (stackAdjust);
1776 /* all other cases just dealloc */
1782 OP_SYMBOL (op)->aop = NULL;
1783 /* if the symbol has a spill */
1785 SPIL_LOC (op)->aop = NULL;
1791 /*-----------------------------------------------------------------*/
1792 /* aopDerefAop - treating the aop parameter as a pointer, return */
1793 /* an asmop for the object it references */
1794 /*-----------------------------------------------------------------*/
1796 aopDerefAop (asmop *aop)
1801 asmop *newaop = NULL;
1802 sym_link *type, *etype;
1805 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1809 type = operandType (aop->op);
1810 etype = getSpec (type);
1811 /* if op is of type of pointer then it is simple */
1812 if (IS_PTR (type) && !IS_FUNC (type->next))
1813 p_type = DCL_TYPE (type);
1816 /* we have to go by the storage class */
1817 p_type = PTR_TYPE (SPEC_OCLS (etype));
1826 if (p_type == POINTER)
1827 newaop = newAsmop (AOP_DIR);
1829 newaop = newAsmop (AOP_EXT);
1830 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1833 adr = (int) floatFromVal (aop->aopu.aop_lit);
1834 if (p_type == POINTER)
1839 newaop = newAsmop (AOP_DIR);
1840 sprintf (s, "0x%02x",adr);
1844 newaop = newAsmop (AOP_EXT);
1845 sprintf (s, "0x%04x",adr);
1847 rs = Safe_calloc (1, strlen (s) + 1);
1849 newaop->aopu.aop_dir = rs;
1852 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1853 "unsupported asmop");
1863 /*-----------------------------------------------------------------*/
1864 /* aopAdrStr - for referencing the address of the aop */
1865 /*-----------------------------------------------------------------*/
1867 aopAdrStr (asmop * aop, int loffset, bool bit16)
1871 int offset = aop->size - 1 - loffset;
1874 /* offset is greater than
1876 if (loffset > (aop->size - 1) &&
1877 aop->type != AOP_LIT)
1880 /* depending on type */
1888 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1889 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1891 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1895 sprintf (s, "#(%s >> %d)",
1896 aop->aopu.aop_immd.aop_immd1,
1900 aop->aopu.aop_immd.aop_immd1);
1904 aop->aopu.aop_immd.aop_immd1);
1905 rs = Safe_calloc (1, strlen (s) + 1);
1911 sprintf (s, "*(%s + %d)",
1915 sprintf (s, "*%s", aop->aopu.aop_dir);
1916 rs = Safe_calloc (1, strlen (s) + 1);
1922 sprintf (s, "(%s + %d)",
1926 sprintf (s, "%s", aop->aopu.aop_dir);
1927 rs = Safe_calloc (1, strlen (s) + 1);
1932 return aop->aopu.aop_reg[loffset]->name;
1936 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
1938 return aopLiteral (aop->aopu.aop_lit, loffset);
1942 return aop->aopu.aop_str[loffset];
1945 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
1947 rs = Safe_calloc (1, strlen (s) + 1);
1953 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1954 "aopAdrStr got unsupported aop->type");
1963 /*-----------------------------------------------------------------*/
1964 /* opIsGptr: returns non-zero if the passed operand is */
1965 /* a generic pointer type. */
1966 /*-----------------------------------------------------------------*/
1968 opIsGptr (operand * op)
1970 sym_link *type = operandType (op);
1972 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1980 /*-----------------------------------------------------------------*/
1981 /* getDataSize - get the operand data size */
1982 /*-----------------------------------------------------------------*/
1984 getDataSize (operand * op)
1987 size = AOP_SIZE (op);
1991 /*-----------------------------------------------------------------*/
1992 /* outAcc - output Acc */
1993 /*-----------------------------------------------------------------*/
1995 outAcc (operand * result)
1998 size = getDataSize (result);
2001 storeRegToAop (hc08_reg_a, AOP (result), 0);
2004 /* unsigned or positive */
2007 storeConstToAop (zero, AOP (result), offset++);
2012 /*-----------------------------------------------------------------*/
2013 /* outBitC - output a bit C */
2014 /*-----------------------------------------------------------------*/
2016 outBitC (operand * result)
2020 /* if the result is bit */
2021 if (AOP_TYPE (result) == AOP_CRY)
2022 aopPut (AOP (result), "c", 0);
2026 emitcode ("clra", "");
2027 emitcode ("rola", "");
2032 /*-----------------------------------------------------------------*/
2033 /* outBitNV - output a bit N^V */
2034 /*-----------------------------------------------------------------*/
2036 outBitNV (operand * result)
2038 symbol *tlbl, *tlbl1;
2040 tlbl = newiTempLabel (NULL);
2041 tlbl1 = newiTempLabel (NULL);
2043 emitBranch ("blt", tlbl);
2044 loadRegFromConst (hc08_reg_a, zero);
2045 emitBranch ("bra", tlbl1);
2047 loadRegFromConst (hc08_reg_a, one);
2053 /*-----------------------------------------------------------------*/
2054 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2055 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2056 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2057 /*-----------------------------------------------------------------*/
2059 asmopToBool (asmop *aop, bool resultInA)
2061 symbol *tlbl, *tlbl1;
2062 int size = aop->size;
2063 bool needpula = FALSE;
2064 bool flagsonly = TRUE;
2069 hc08_freeReg(hc08_reg_a);
2076 emitcode ("tsta", "");
2079 else if (IS_AOP_X(aop))
2080 emitcode ("tstx", "");
2081 else if (IS_AOP_H(aop))
2083 if (hc08_reg_a->isFree)
2085 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2086 emitcode ("tsta", "");
2088 hc08_freeReg(hc08_reg_a);
2090 else if (hc08_reg_x->isFree)
2092 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2093 emitcode ("tstx", "");
2094 hc08_freeReg(hc08_reg_x);
2098 emitcode ("pshh", "");
2099 emitcode ("tst", "1,s");
2100 emitcode ("ais", "#1");
2103 else if (IS_AOP_HX(aop))
2104 emitcode ("cphx", zero);
2105 else if (IS_AOP_XA(aop))
2107 symbol *tlbl = newiTempLabel (NULL);
2108 emitcode ("tsta", "");
2109 emitcode ("bne", "%05d$", (tlbl->key + 100));
2110 emitcode ("tstx", "");
2111 emitcode ("", "%05d$:", (tlbl->key + 100));
2115 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2116 "Bad rIdx in asmToBool");
2124 needpula = pushRegIfUsed (hc08_reg_a);
2125 loadRegFromAop (hc08_reg_a, aop, 0);
2126 for (offset=1; offset<size; offset++)
2127 accopWithAop ("ora", aop, offset);
2129 pullReg (hc08_reg_a);
2132 hc08_freeReg (hc08_reg_a);
2141 loadRegFromAop (hc08_reg_a, aop, 0);
2142 hc08_freeReg (hc08_reg_a);
2146 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2151 if (hc08_reg_a->isFree)
2153 loadRegFromAop (hc08_reg_a, aop, 0);
2154 accopWithAop ("ora", aop, 1);
2155 hc08_freeReg (hc08_reg_a);
2160 tlbl = newiTempLabel (NULL);
2161 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2162 emitcode ("bne", "%05d$", (tlbl->key + 100));
2163 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2164 emitcode ("", "%05d$:", (tlbl->key + 100));
2170 needpula = pushRegIfUsed (hc08_reg_a);
2171 loadRegFromAop (hc08_reg_a, aop, 0);
2172 for (offset=1; offset<size; offset++)
2173 accopWithAop ("ora", aop, offset);
2175 pullReg (hc08_reg_a);
2178 hc08_freeReg (hc08_reg_a);
2186 tlbl = newiTempLabel (NULL);
2190 tlbl1 = newiTempLabel (NULL);
2191 emitBranch ("bne", tlbl1);
2192 loadRegFromConst (hc08_reg_a, zero);
2193 emitBranch ("bra", tlbl);
2195 loadRegFromConst (hc08_reg_a, one);
2199 emitBranch ("beq", tlbl);
2200 loadRegFromConst (hc08_reg_a, one);
2203 hc08_useReg (hc08_reg_a);
2209 /*-----------------------------------------------------------------*/
2210 /* genNot - generate code for ! operation */
2211 /*-----------------------------------------------------------------*/
2215 D(emitcode ("; genNot",""));
2217 /* assign asmOps to operand & result */
2218 aopOp (IC_LEFT (ic), ic, FALSE);
2219 aopOp (IC_RESULT (ic), ic, TRUE);
2221 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2222 emitcode ("eor", one);
2223 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2225 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2226 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2230 /*-----------------------------------------------------------------*/
2231 /* genCpl - generate code for complement */
2232 /*-----------------------------------------------------------------*/
2238 regs* reg = hc08_reg_a;
2242 D(emitcode ("; genCpl",""));
2244 /* assign asmOps to operand & result */
2245 aopOp (IC_LEFT (ic), ic, FALSE);
2246 aopOp (IC_RESULT (ic), ic, TRUE);
2248 size = AOP_SIZE (IC_RESULT (ic));
2251 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2252 rmwWithReg ("com", reg);
2254 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2258 /* release the aops */
2259 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2260 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2263 /*-----------------------------------------------------------------*/
2264 /* genUminusFloat - unary minus for floating points */
2265 /*-----------------------------------------------------------------*/
2267 genUminusFloat (operand * op, operand * result)
2269 int size, offset = 0;
2272 D(emitcode ("; genUminusFloat",""));
2274 /* for this we just copy and then flip the bit */
2276 size = AOP_SIZE (op) - 1;
2282 needpula = pushRegIfUsed (hc08_reg_a);
2283 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2284 emitcode ("eor", "#0x80");
2285 hc08_useReg (hc08_reg_a);
2286 storeRegToAop (hc08_reg_a, AOP (result), offset);
2287 pullOrFreeReg (hc08_reg_a, needpula);
2290 transferAopAop (AOP (op), offset, AOP (result), offset);
2296 /*-----------------------------------------------------------------*/
2297 /* genUminus - unary minus code generation */
2298 /*-----------------------------------------------------------------*/
2300 genUminus (iCode * ic)
2303 sym_link *optype, *rtype;
2308 D(emitcode ("; genUminus",""));
2311 aopOp (IC_LEFT (ic), ic, FALSE);
2312 aopOp (IC_RESULT (ic), ic, TRUE);
2314 optype = operandType (IC_LEFT (ic));
2315 rtype = operandType (IC_RESULT (ic));
2317 /* if float then do float stuff */
2318 if (IS_FLOAT (optype))
2320 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2324 /* otherwise subtract from zero */
2325 size = AOP_SIZE (IC_LEFT (ic));
2330 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2331 needpula = pushRegIfUsed (hc08_reg_a);
2334 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2335 emitcode ("nega", "");
2336 hc08_freeReg (hc08_reg_a);
2337 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2338 SPEC_USIGN (operandType (IC_LEFT (ic))));
2339 pullOrFreeReg (hc08_reg_a, needpula);
2343 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2344 result = forceStackedAop (AOP (IC_RESULT (ic)));
2346 result = AOP (IC_RESULT (ic));
2348 needpula = pushRegIfUsed (hc08_reg_a);
2352 loadRegFromConst (hc08_reg_a, zero);
2353 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2354 storeRegToAop (hc08_reg_a, result, offset++);
2357 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2358 SPEC_USIGN (operandType (IC_LEFT (ic))));
2359 pullOrFreeReg (hc08_reg_a, needpula);
2361 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2362 freeAsmop (NULL, result, ic, TRUE);
2368 /* release the aops */
2369 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2370 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2373 /*-----------------------------------------------------------------*/
2374 /* saveRegisters - will look for a call and save the registers */
2375 /*-----------------------------------------------------------------*/
2377 saveRegisters (iCode * lic)
2384 for (ic = lic; ic; ic = ic->next)
2385 if (ic->op == CALL || ic->op == PCALL)
2390 fprintf (stderr, "found parameter push with no function call\n");
2394 /* if the registers have been saved already or don't need to be then
2398 if (IS_SYMOP(IC_LEFT(ic)) &&
2399 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2400 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2403 /* safe the registers in use at this time but skip the
2404 ones for the result */
2405 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2406 hc08_rUmaskForOp (IC_RESULT(ic)));
2409 for (i = 0; i < hc08_nRegs; i++)
2411 if (bitVectBitValue (rsave, i))
2412 pushReg ( hc08_regWithIdx (i), FALSE);
2416 /*-----------------------------------------------------------------*/
2417 /* unsaveRegisters - pop the pushed registers */
2418 /*-----------------------------------------------------------------*/
2420 unsaveRegisters (iCode * ic)
2425 /* restore the registers in use at this time but skip the
2426 ones for the result */
2427 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2428 hc08_rUmaskForOp (IC_RESULT(ic)));
2430 for (i = hc08_nRegs; i >= 0; i--)
2432 if (bitVectBitValue (rsave, i))
2433 pullReg ( hc08_regWithIdx (i));
2439 /*-----------------------------------------------------------------*/
2441 /*-----------------------------------------------------------------*/
2443 pushSide (operand * oper, int size)
2448 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2449 pushReg ( hc08_reg_a, TRUE);
2453 /*-----------------------------------------------------------------*/
2454 /* assignResultValue - */
2455 /*-----------------------------------------------------------------*/
2457 assignResultValue (operand * oper)
2459 int size = AOP_SIZE (oper);
2463 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2464 if (hc08_aop_pass[offset]->type == AOP_REG)
2465 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2472 /*-----------------------------------------------------------------*/
2473 /* genIpush - genrate code for pushing this gets a little complex */
2474 /*-----------------------------------------------------------------*/
2476 genIpush (iCode * ic)
2478 int size, offset = 0;
2481 D(emitcode ("; genIpush",""));
2483 /* if this is not a parm push : ie. it is spill push
2484 and spill push is always done on the local stack */
2488 /* and the item is spilt then do nothing */
2489 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2492 aopOp (IC_LEFT (ic), ic, FALSE);
2493 size = AOP_SIZE (IC_LEFT (ic));
2495 /* push it on the stack */
2498 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2499 pushReg ( hc08_reg_a, TRUE);
2505 /* this is a paramter push: in this case we call
2506 the routine to find the call and save those
2507 registers that need to be saved */
2510 /* then do the push */
2511 aopOp (IC_LEFT (ic), ic, FALSE);
2514 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2515 size = AOP_SIZE (IC_LEFT (ic));
2518 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2519 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2521 if ((size==2) && hc08_reg_hx->isFree)
2523 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2524 pushReg (hc08_reg_hx, TRUE);
2531 // printf("loading %d\n", offset);
2532 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2533 // printf("pushing \n");
2534 pushReg (hc08_reg_a, TRUE);
2538 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2541 /*-----------------------------------------------------------------*/
2542 /* genIpop - recover the registers: can happen only for spilling */
2543 /*-----------------------------------------------------------------*/
2545 genIpop (iCode * ic)
2549 D(emitcode ("; genIpop",""));
2551 /* if the temp was not pushed then */
2552 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2555 aopOp (IC_LEFT (ic), ic, FALSE);
2556 size = AOP_SIZE (IC_LEFT (ic));
2560 pullReg (hc08_reg_a);
2561 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2563 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2567 /*-----------------------------------------------------------------*/
2568 /* genSend - gen code for SEND */
2569 /*-----------------------------------------------------------------*/
2570 static void genSend(set *sendSet)
2574 for (sic = setFirstItem (_G.sendSet); sic;
2575 sic = setNextItem (_G.sendSet)) {
2576 int size, offset = 0;
2577 aopOp (IC_LEFT (sic), sic, FALSE);
2578 size = AOP_SIZE (IC_LEFT (sic));
2583 transferAopAop( AOP (IC_LEFT (sic)), offset,
2584 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2588 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2592 /*-----------------------------------------------------------------*/
2593 /* genCall - generates a call statement */
2594 /*-----------------------------------------------------------------*/
2596 genCall (iCode * ic)
2599 // bool restoreBank = FALSE;
2600 // bool swapBanks = FALSE;
2602 D(emitcode("; genCall",""));
2604 dtype = operandType (IC_LEFT (ic));
2605 /* if send set is not empty the assign */
2608 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2609 genSend(reverseSet(_G.sendSet));
2611 genSend(_G.sendSet);
2617 /* if caller saves & we have not saved then */
2623 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2624 OP_SYMBOL (IC_LEFT (ic))->rname :
2625 OP_SYMBOL (IC_LEFT (ic))->name));
2628 /* if we need assign a result value */
2629 if ((IS_ITEMP (IC_RESULT (ic)) &&
2630 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2631 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2632 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2633 IS_TRUE_SYMOP (IC_RESULT (ic)))
2637 aopOp (IC_RESULT (ic), ic, FALSE);
2640 assignResultValue (IC_RESULT (ic));
2642 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2645 /* adjust the stack for parameters if
2649 pullNull (ic->parmBytes);
2652 /* if we had saved some registers then unsave them */
2653 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2654 unsaveRegisters (ic);
2658 /*-----------------------------------------------------------------*/
2659 /* -10l - generates a call by pointer statement */
2660 /*-----------------------------------------------------------------*/
2662 genPcall (iCode * ic)
2665 symbol *rlbl = newiTempLabel (NULL);
2666 symbol *tlbl = newiTempLabel (NULL);
2667 // bool restoreBank=FALSE;
2668 // bool swapBanks = FALSE;
2670 D(emitcode("; genPCall",""));
2672 /* if caller saves & we have not saved then */
2676 /* if we are calling a not _naked function that is not using
2677 the same register bank then we need to save the
2678 destination registers on the stack */
2679 dtype = operandType (IC_LEFT (ic))->next;
2681 /* now push the calling address */
2682 emitBranch ("bsr", tlbl);
2683 emitBranch ("bra", rlbl);
2686 /* Push the function's address */
2687 aopOp (IC_LEFT (ic), ic, FALSE);
2688 pushSide (IC_LEFT (ic), FPTRSIZE);
2689 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2691 /* if send set is not empty the assign */
2694 genSend(reverseSet(_G.sendSet));
2700 emitcode ("rts", "");
2705 /* if we need assign a result value */
2706 if ((IS_ITEMP (IC_RESULT (ic)) &&
2707 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2708 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2709 IS_TRUE_SYMOP (IC_RESULT (ic)))
2713 aopOp (IC_RESULT (ic), ic, FALSE);
2716 assignResultValue (IC_RESULT (ic));
2718 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2721 /* adjust the stack for parameters if
2725 pullNull (ic->parmBytes);
2728 /* if we hade saved some registers then
2730 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2731 unsaveRegisters (ic);
2734 /*-----------------------------------------------------------------*/
2735 /* resultRemat - result is rematerializable */
2736 /*-----------------------------------------------------------------*/
2738 resultRemat (iCode * ic)
2740 if (SKIP_IC (ic) || ic->op == IFX)
2743 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2745 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2746 if (sym->remat && !POINTER_SET (ic))
2753 #if defined(__BORLANDC__) || defined(_MSC_VER)
2754 #define STRCASECMP stricmp
2756 #define STRCASECMP strcasecmp
2759 /*-----------------------------------------------------------------*/
2760 /* inExcludeList - return 1 if the string is in exclude Reg list */
2761 /*-----------------------------------------------------------------*/
2763 regsCmp(void *p1, void *p2)
2765 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2769 inExcludeList (char *s)
2771 const char *p = setFirstItem(options.excludeRegsSet);
2773 if (p == NULL || STRCASECMP(p, "none") == 0)
2777 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2780 /*-----------------------------------------------------------------*/
2781 /* genFunction - generated code for function entry */
2782 /*-----------------------------------------------------------------*/
2784 genFunction (iCode * ic)
2788 int calleesaves_saved_register = -1;
2792 /* create the function header */
2793 emitcode (";", "-----------------------------------------");
2794 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2795 emitcode (";", "-----------------------------------------");
2797 emitcode ("", "%s:", sym->rname);
2798 ftype = operandType (IC_LEFT (ic));
2800 if (IFFUNC_ISNAKED(ftype))
2802 emitcode(";", "naked function: no prologue.");
2808 /* if this is an interrupt service routine then
2810 if (IFFUNC_ISISR (sym->type))
2813 if (!inExcludeList ("h"))
2814 emitcode ("pshh", "");
2818 /* if callee-save to be used for this function
2819 then save the registers being used in this function */
2820 if (IFFUNC_CALLEESAVES(sym->type))
2824 /* if any registers used */
2827 /* save the registers used */
2828 for (i = 0; i < sym->regsUsed->size; i++)
2830 if (bitVectBitValue (sym->regsUsed, i))
2832 /* remember one saved register for later usage */
2833 if (calleesaves_saved_register < 0)
2834 calleesaves_saved_register = i;
2835 pushReg (hc08_regWithIdx (i), FALSE);
2843 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2848 /* adjust the stack for the function */
2854 // werror (W_STACK_OVERFLOW, sym->name);
2858 _G.stackOfs = sym->stack;
2861 /* if critical function then turn interrupts off */
2862 if (IFFUNC_ISCRITICAL (ftype))
2864 if (IFFUNC_ARGS (ftype))
2866 /* Function was passed parameters, so make sure A is preserved */
2867 pushReg (hc08_reg_a, FALSE);
2868 pushReg (hc08_reg_a, FALSE);
2869 emitcode ("tpa", "");
2870 emitcode ("sta", "2,s");
2871 emitcode ("sei", "");
2872 pullReg (hc08_reg_a);
2876 /* No passed parameters, so A can be freely modified */
2877 emitcode ("tpa", "");
2878 pushReg (hc08_reg_a, TRUE);
2879 emitcode ("sei", "");
2885 /*-----------------------------------------------------------------*/
2886 /* genEndFunction - generates epilogue for functions */
2887 /*-----------------------------------------------------------------*/
2889 genEndFunction (iCode * ic)
2891 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2893 if (IFFUNC_ISNAKED(sym->type))
2895 emitcode(";", "naked function: no epilogue.");
2899 if (IFFUNC_ISCRITICAL (sym->type))
2901 if (!IS_VOID(sym->type->next))
2903 /* Function has return value, so make sure A is preserved */
2904 pushReg (hc08_reg_a, FALSE);
2905 emitcode ("lda", "2,s");
2906 emitcode ("tap", "");
2907 pullReg (hc08_reg_a);
2912 /* Function returns void, so A can be freely modified */
2913 pullReg (hc08_reg_a);
2914 emitcode ("tap", "");
2918 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2924 _G.stackPushes += sym->stack;
2925 adjustStack (sym->stack);
2929 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2933 if (IFFUNC_ISISR (sym->type))
2936 if (!inExcludeList ("h"))
2937 emitcode ("pulh", "");
2940 /* if debug then send end of function */
2941 if (options.debug && currFunc)
2944 emitcode ("", "C$%s$%d$%d$%d ==.",
2945 FileBaseName (ic->filename), currFunc->lastLine,
2946 ic->level, ic->block);
2947 if (IS_STATIC (currFunc->etype))
2948 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2950 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2954 emitcode ("rti", "");
2958 if (IFFUNC_CALLEESAVES(sym->type))
2962 /* if any registers used */
2965 /* save the registers used */
2966 for (i = sym->regsUsed->size; i >= 0; i--)
2968 if (bitVectBitValue (sym->regsUsed, i) ||
2969 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
2970 emitcode ("pop", "%s", hc08_regWithIdx (i)->dname);
2976 /* if debug then send end of function */
2977 if (options.debug && currFunc)
2980 emitcode ("", "C$%s$%d$%d$%d ==.",
2981 FileBaseName (ic->filename), currFunc->lastLine,
2982 ic->level, ic->block);
2983 if (IS_STATIC (currFunc->etype))
2984 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2986 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2990 emitcode ("rts", "");
2995 /*-----------------------------------------------------------------*/
2996 /* genRet - generate code for return statement */
2997 /*-----------------------------------------------------------------*/
3001 int size, offset = 0;
3004 D(emitcode ("; genRet",""));
3006 /* if we have no return value then
3007 just generate the "ret" */
3011 /* we have something to return then
3012 move the return value into place */
3013 aopOp (IC_LEFT (ic), ic, FALSE);
3014 size = AOP_SIZE (IC_LEFT (ic));
3020 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3027 /* 4 byte return: store value in the global return variable */
3031 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3032 STA (fReturn2[offset--], FALSE);
3033 hc08_freeReg (hc08_reg_a);
3037 /* 2 byte return: store value in x:a */
3038 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3039 hc08_freeReg (hc08_reg_xa);
3042 /* 1 byte return: store value in a */
3043 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3044 hc08_freeReg (hc08_reg_a);
3049 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3052 /* generate a jump to the return label
3053 if the next is not the return statement */
3054 if (!(ic->next && ic->next->op == LABEL &&
3055 IC_LABEL (ic->next) == returnLabel))
3057 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3061 /*-----------------------------------------------------------------*/
3062 /* genLabel - generates a label */
3063 /*-----------------------------------------------------------------*/
3065 genLabel (iCode * ic)
3070 /* For the high level labels we cannot depend on any */
3071 /* register's contents. Amnesia time. */
3072 for (i=A_IDX;i<=XA_IDX;i++)
3074 reg = hc08_regWithIdx(i);
3079 /* special case never generate */
3080 if (IC_LABEL (ic) == entryLabel)
3083 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3087 /*-----------------------------------------------------------------*/
3088 /* genGoto - generates a jmp */
3089 /*-----------------------------------------------------------------*/
3091 genGoto (iCode * ic)
3093 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3097 /*-----------------------------------------------------------------*/
3098 /* findLabelBackwards: walks back through the iCode chain looking */
3099 /* for the given label. Returns number of iCode instructions */
3100 /* between that label and given ic. */
3101 /* Returns zero if label not found. */
3102 /*-----------------------------------------------------------------*/
3104 findLabelBackwards (iCode * ic, int key)
3113 /* If we have any pushes or pops, we cannot predict the distance.
3114 I don't like this at all, this should be dealt with in the
3116 if (ic->op == IPUSH || ic->op == IPOP) {
3120 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3130 /*-----------------------------------------------------------------*/
3131 /* genPlusIncr :- does addition with increment if possible */
3132 /*-----------------------------------------------------------------*/
3134 genPlusIncr (iCode * ic)
3142 unsigned int size = getDataSize (IC_RESULT (ic));
3144 symbol *tlbl = NULL;
3146 left = IC_LEFT (ic);
3147 result = IC_RESULT (ic);
3149 /* will try to generate an increment */
3150 /* if the right side is not a literal
3152 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3155 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3157 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3159 if ((IS_AOP_HX (AOP (left)) ||
3160 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3162 && (icount>=-128) && (icount<=127) && (size==2))
3164 if (!IS_AOP_HX (AOP (left)))
3166 needpulx = pushRegIfUsed (hc08_reg_x);
3167 needpulh = pushRegIfUsed (hc08_reg_h);
3174 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3175 emitcode ("aix","#%d", icount);
3176 hc08_dirtyReg (hc08_reg_hx, FALSE);
3177 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3178 pullOrFreeReg (hc08_reg_h, needpulh);
3179 pullOrFreeReg (hc08_reg_x, needpulx);
3183 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3184 sameRegs (AOP (left), AOP (result))));
3186 if ((icount > 255) || (icount<0))
3189 if (!sameRegs (AOP (left), AOP (result)))
3192 D(emitcode ("; genPlusIncr",""));
3195 tlbl = newiTempLabel (NULL);
3200 rmwWithAop ("inc", AOP (result), 0);
3202 emitBranch ("bne", tlbl);
3206 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3207 needpula = pushRegIfUsed (hc08_reg_a);
3210 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3211 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3212 hc08_useReg (hc08_reg_a);
3213 storeRegToAop (hc08_reg_a, AOP (result), 0);
3214 hc08_freeReg (hc08_reg_a);
3216 emitBranch ("bcc", tlbl);
3218 for (offset=1; offset<size; offset++)
3220 rmwWithAop ("inc", AOP (result), offset);
3221 if ((offset+1)<size)
3222 emitBranch ("bne", tlbl);
3228 pullOrFreeReg (hc08_reg_a, needpula);
3235 /*-----------------------------------------------------------------*/
3236 /* genPlus - generates code for addition */
3237 /*-----------------------------------------------------------------*/
3239 genPlus (iCode * ic)
3241 int size, offset = 0;
3243 asmop *leftOp, *rightOp;
3245 /* special cases :- */
3247 D(emitcode ("; genPlus",""));
3249 aopOp (IC_LEFT (ic), ic, FALSE);
3250 aopOp (IC_RIGHT (ic), ic, FALSE);
3251 aopOp (IC_RESULT (ic), ic, TRUE);
3253 /* we want registers on the left and literals on the right */
3254 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3255 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3257 operand *t = IC_RIGHT (ic);
3258 IC_RIGHT (ic) = IC_LEFT (ic);
3263 /* if I can do an increment instead
3264 of add then GOOD for ME */
3265 if (genPlusIncr (ic) == TRUE)
3268 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3269 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3270 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3272 size = getDataSize (IC_RESULT (ic));
3274 leftOp = AOP(IC_LEFT(ic));
3275 rightOp = AOP(IC_RIGHT(ic));
3281 loadRegFromAop (hc08_reg_a, leftOp, offset);
3282 accopWithAop(add, rightOp, offset);
3283 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3284 hc08_freeReg (hc08_reg_a);
3285 add = "adc"; /* further adds must propagate carry */
3289 // adjustArithmeticResult (ic);
3292 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3293 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3294 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3297 /*-----------------------------------------------------------------*/
3298 /* genMinusDec :- does subtraction with deccrement if possible */
3299 /*-----------------------------------------------------------------*/
3301 genMinusDec (iCode * ic)
3303 unsigned int icount;
3308 unsigned int size = getDataSize (IC_RESULT (ic));
3312 left = IC_LEFT (ic);
3313 result = IC_RESULT (ic);
3315 /* will try to generate an increment */
3316 /* if the right side is not a literal
3318 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3321 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3323 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3324 && (icount>=-127) && (icount<=128) && (size==2))
3326 if (!IS_AOP_HX (AOP (left)))
3328 needpulx = pushRegIfUsed (hc08_reg_x);
3329 needpulh = pushRegIfUsed (hc08_reg_h);
3336 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3337 emitcode ("aix","#%d", -icount);
3338 hc08_dirtyReg (hc08_reg_hx, FALSE);
3339 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3340 pullOrFreeReg (hc08_reg_h, needpulh);
3341 pullOrFreeReg (hc08_reg_x, needpulx);
3345 if ((icount > 1) || (icount<0))
3348 if (!sameRegs (AOP (left), AOP (result)))
3354 D(emitcode ("; genMinusDec",""));
3356 rmwWithAop ("dec", AOP (result), 0);
3361 /*-----------------------------------------------------------------*/
3362 /* addSign - complete with sign */
3363 /*-----------------------------------------------------------------*/
3365 addSign (operand * result, int offset, int sign)
3367 int size = (getDataSize (result) - offset);
3372 emitcode ("rola", "");
3373 emitcode ("clra", "");
3374 emitcode ("sbc", zero);
3376 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3380 storeConstToAop (zero, AOP (result), offset++);
3385 /*-----------------------------------------------------------------*/
3386 /* genMinus - generates code for subtraction */
3387 /*-----------------------------------------------------------------*/
3389 genMinus (iCode * ic)
3392 int size, offset = 0;
3394 asmop *leftOp, *rightOp;
3396 D(emitcode ("; genMinus",""));
3398 aopOp (IC_LEFT (ic), ic, FALSE);
3399 aopOp (IC_RIGHT (ic), ic, FALSE);
3400 aopOp (IC_RESULT (ic), ic, TRUE);
3402 /* special cases :- */
3403 /* if I can do an decrement instead
3404 of subtract then GOOD for ME */
3405 if (genMinusDec (ic) == TRUE)
3408 size = getDataSize (IC_RESULT (ic));
3411 leftOp = AOP(IC_LEFT(ic));
3412 rightOp = AOP(IC_RIGHT(ic));
3418 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3419 accopWithAop(sub, rightOp, offset);
3420 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3425 // adjustArithmeticResult (ic);
3428 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3429 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3430 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3435 /*-----------------------------------------------------------------*/
3436 /* genMultOneByte : 8*8=8/16 bit multiplication */
3437 /*-----------------------------------------------------------------*/
3439 genMultOneByte (operand * left,
3443 /* sym_link *opetype = operandType (result); */
3444 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3445 int size=AOP_SIZE(result);
3446 bool negLiteral = FALSE;
3448 D(emitcode ("; genMultOneByte",""));
3450 if (size<1 || size>2) {
3451 // this should never happen
3452 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3453 AOP_SIZE(result), __FILE__, lineno);
3457 /* (if two literals: the value is computed before) */
3458 /* if one literal, literal on the right */
3459 if (AOP_TYPE (left) == AOP_LIT)
3464 //D(emitcode (";", "swapped left and right"));
3468 || (SPEC_USIGN(operandType(left)) &&
3469 SPEC_USIGN(operandType(right))))
3471 // just an unsigned 8*8=8/16 multiply
3472 //D(emitcode (";","unsigned"));
3474 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3475 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3476 emitcode ("mul", "");
3477 hc08_dirtyReg (hc08_reg_xa, FALSE);
3478 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3479 hc08_freeReg (hc08_reg_xa);
3484 // we have to do a signed multiply
3487 //D(emitcode (";", "signed"));
3489 emitcode ("clr", "1,s");
3491 tlbl1 = newiTempLabel (NULL);
3492 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3493 emitcode ("tsta","");
3494 emitBranch ("bpl", tlbl1);
3495 emitcode ("inc", "1,s");
3496 rmwWithReg ("neg", hc08_reg_a);
3499 if (AOP_TYPE(right)==AOP_LIT)
3501 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3502 /* AND literal negative */
3504 emitcode ("ldx", "#0x%02x", -val);
3507 emitcode ("ldx", "#0x%02x", val);
3509 hc08_useReg (hc08_reg_x);
3513 tlbl2 = newiTempLabel (NULL);
3514 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3515 emitcode ("tstx", "");
3516 emitBranch ("bpl", tlbl2);
3517 emitcode ("inc", "1,s");
3518 rmwWithReg ("neg", hc08_reg_x);
3522 emitcode ("mul", "");
3523 hc08_dirtyReg (hc08_reg_xa, FALSE);
3525 tlbl3 = newiTempLabel (NULL);
3526 emitcode ("dec", "1,s");
3528 emitBranch ("bne", tlbl3);
3530 emitBranch ("beq", tlbl3);
3532 rmwWithReg ("neg", hc08_reg_a);
3535 tlbl4 = newiTempLabel (NULL);
3536 emitBranch ("bcc", tlbl4);
3537 rmwWithReg ("inc", hc08_reg_x);
3539 rmwWithReg ("neg", hc08_reg_x);
3544 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3545 hc08_freeReg (hc08_reg_xa);
3549 /*-----------------------------------------------------------------*/
3550 /* genMult - generates code for multiplication */
3551 /*-----------------------------------------------------------------*/
3553 genMult (iCode * ic)
3555 operand *left = IC_LEFT (ic);
3556 operand *right = IC_RIGHT (ic);
3557 operand *result = IC_RESULT (ic);
3559 D(emitcode ("; genMult",""));
3561 /* assign the amsops */
3562 aopOp (left, ic, FALSE);
3563 aopOp (right, ic, FALSE);
3564 aopOp (result, ic, TRUE);
3566 /* special cases first */
3567 /* if both are of size == 1 */
3568 // if (getSize(operandType(left)) == 1 &&
3569 // getSize(operandType(right)) == 1)
3570 if (AOP_SIZE (left) == 1 &&
3571 AOP_SIZE (right) == 1)
3573 genMultOneByte (left, right, result);
3577 /* should have been converted to function call */
3578 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3579 getSize(OP_SYMBOL(right)->type));
3580 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3585 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3586 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3587 freeAsmop (result, NULL, ic, TRUE);
3590 /*-----------------------------------------------------------------*/
3591 /* genDivOneByte : 8 bit division */
3592 /*-----------------------------------------------------------------*/
3594 genDivOneByte (operand * left,
3598 sym_link *opetype = operandType (result);
3600 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3602 bool negLiteral = FALSE;
3604 D(emitcode ("; genDivOneByte",""));
3606 size = AOP_SIZE (result);
3607 /* signed or unsigned */
3608 if (SPEC_USIGN (opetype))
3610 /* unsigned is easy */
3611 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3612 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3613 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3614 emitcode ("div", "");
3615 hc08_dirtyReg (hc08_reg_a, FALSE);
3616 hc08_dirtyReg (hc08_reg_h, FALSE);
3617 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3618 hc08_freeReg (hc08_reg_a);
3619 hc08_freeReg (hc08_reg_x);
3620 hc08_freeReg (hc08_reg_h);
3624 /* signed is a little bit more difficult */
3627 emitcode ("clr", "1,s");
3629 tlbl1 = newiTempLabel (NULL);
3630 tlbl2 = newiTempLabel (NULL);
3631 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3632 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3633 emitBranch ("bpl", tlbl1);
3634 emitcode ("inc", "1,s");
3635 rmwWithReg ("neg", hc08_reg_a);
3636 emitBranch ("bcc", tlbl2);
3637 rmwWithReg ("inc", hc08_reg_x);
3639 rmwWithReg ("neg", hc08_reg_x);
3640 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3643 if (AOP_TYPE(right)==AOP_LIT)
3645 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3646 /* AND literal negative */
3648 emitcode ("ldx", "#0x%02x", -val);
3651 emitcode ("ldx", "#0x%02x", val);
3653 hc08_useReg (hc08_reg_x);
3657 tlbl3 = newiTempLabel (NULL);
3658 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3659 emitBranch ("bpl", tlbl3);
3660 emitcode ("inc", "1,s");
3661 rmwWithReg ("neg", hc08_reg_x);
3665 emitcode ("div", "");
3666 hc08_dirtyReg (hc08_reg_x, FALSE);
3667 hc08_dirtyReg (hc08_reg_a, FALSE);
3668 hc08_dirtyReg (hc08_reg_h, FALSE);
3670 tlbl4 = newiTempLabel (NULL);
3671 emitcode ("dec", "1,s");
3673 emitBranch ("bne", tlbl4);
3675 emitBranch ("beq", tlbl4);
3676 rmwWithReg ("neg", hc08_reg_a);
3680 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3681 hc08_freeReg (hc08_reg_a);
3682 hc08_freeReg (hc08_reg_x);
3683 hc08_freeReg (hc08_reg_h);
3688 /*-----------------------------------------------------------------*/
3689 /* genDiv - generates code for division */
3690 /*-----------------------------------------------------------------*/
3694 operand *left = IC_LEFT (ic);
3695 operand *right = IC_RIGHT (ic);
3696 operand *result = IC_RESULT (ic);
3698 D(emitcode ("; genDiv",""));
3700 /* assign the amsops */
3701 aopOp (left, ic, FALSE);
3702 aopOp (right, ic, FALSE);
3703 aopOp (result, ic, TRUE);
3705 /* special cases first */
3706 /* if both are of size == 1 */
3707 if (AOP_SIZE (left) <= 2 &&
3708 AOP_SIZE (right) == 1)
3710 genDivOneByte (left, right, result);
3714 /* should have been converted to function call */
3717 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3718 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3719 freeAsmop (result, NULL, ic, TRUE);
3722 /*-----------------------------------------------------------------*/
3723 /* genModOneByte : 8 bit modulus */
3724 /*-----------------------------------------------------------------*/
3726 genModOneByte (operand * left,
3730 sym_link *opetype = operandType (result);
3732 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3734 bool negLiteral = FALSE;
3736 D(emitcode ("; genModOneByte",""));
3738 size = AOP_SIZE (result);
3739 /* signed or unsigned */
3740 if (SPEC_USIGN (opetype))
3742 /* unsigned is easy */
3743 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3744 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3745 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3746 emitcode ("div", "");
3747 hc08_dirtyReg (hc08_reg_a, FALSE);
3748 hc08_dirtyReg (hc08_reg_h, FALSE);
3749 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3750 hc08_freeReg (hc08_reg_a);
3751 hc08_freeReg (hc08_reg_x);
3752 hc08_freeReg (hc08_reg_h);
3756 /* signed is a little bit more difficult */
3759 emitcode ("clr", "1,s");
3761 tlbl1 = newiTempLabel (NULL);
3762 tlbl2 = newiTempLabel (NULL);
3763 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3764 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3765 emitBranch ("bpl", tlbl1);
3766 emitcode ("inc", "1,s");
3767 rmwWithReg ("neg", hc08_reg_a);
3768 emitBranch ("bcc", tlbl2);
3769 rmwWithReg ("inc", hc08_reg_x);
3771 rmwWithReg ("neg", hc08_reg_x);
3772 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3775 if (AOP_TYPE(right)==AOP_LIT)
3777 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3778 /* AND literal negative */
3780 emitcode ("ldx", "#0x%02x", -val);
3783 emitcode ("ldx", "#0x%02x", val);
3785 hc08_useReg (hc08_reg_x);
3789 tlbl3 = newiTempLabel (NULL);
3790 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3791 emitBranch ("bpl", tlbl3);
3792 emitcode ("inc", "1,s");
3793 rmwWithReg ("neg", hc08_reg_x);
3797 emitcode ("div", "");
3798 hc08_dirtyReg (hc08_reg_x, FALSE);
3799 hc08_dirtyReg (hc08_reg_a, FALSE);
3800 hc08_dirtyReg (hc08_reg_h, FALSE);
3802 tlbl4 = newiTempLabel (NULL);
3803 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3804 emitcode ("dec", "1,s");
3806 emitBranch ("bne", tlbl4);
3808 emitBranch ("beq", tlbl4);
3809 rmwWithReg ("neg", hc08_reg_a);
3813 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3814 hc08_freeReg (hc08_reg_a);
3815 hc08_freeReg (hc08_reg_x);
3816 hc08_freeReg (hc08_reg_h);
3820 /*-----------------------------------------------------------------*/
3821 /* genMod - generates code for division */
3822 /*-----------------------------------------------------------------*/
3826 operand *left = IC_LEFT (ic);
3827 operand *right = IC_RIGHT (ic);
3828 operand *result = IC_RESULT (ic);
3830 D(emitcode ("; genMod",""));
3832 /* assign the amsops */
3833 aopOp (left, ic, FALSE);
3834 aopOp (right, ic, FALSE);
3835 aopOp (result, ic, TRUE);
3837 /* special cases first */
3838 /* if both are of size == 1 */
3839 if (AOP_SIZE (left) <= 2 &&
3840 AOP_SIZE (right) == 1)
3842 genModOneByte (left, right, result);
3846 /* should have been converted to function call */
3850 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3851 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3852 freeAsmop (result, NULL, ic, TRUE);
3855 /*-----------------------------------------------------------------*/
3856 /* genIfxJump :- will create a jump depending on the ifx */
3857 /*-----------------------------------------------------------------*/
3859 genIfxJump (iCode * ic, char *jval)
3862 symbol *tlbl = newiTempLabel (NULL);
3865 D(emitcode ("; genIfxJump",""));
3867 /* if true label then we jump if condition
3871 jlbl = IC_TRUE (ic);
3872 if (!strcmp (jval, "a"))
3874 else if (!strcmp (jval, "c"))
3881 /* false label is present */
3882 jlbl = IC_FALSE (ic);
3883 if (!strcmp (jval, "a"))
3885 else if (!strcmp (jval, "c"))
3890 emitBranch (inst, tlbl);
3891 emitBranch ("jmp", jlbl);
3894 /* mark the icode as generated */
3898 /*-----------------------------------------------------------------*/
3899 /* genCmp :- greater or less than comparison */
3900 /*-----------------------------------------------------------------*/
3902 genCmp (operand * left, operand * right,
3903 operand * result, iCode * ifx, int sign, iCode *ic)
3905 int size, offset = 0;
3906 unsigned long lit = 0L;
3908 bool needpula = FALSE;
3910 D(emitcode ("; genCmp",""));
3912 /* subtract right from left if at the
3913 end the carry flag is set then we know that
3914 left is greater than right */
3915 size = max (AOP_SIZE (left), AOP_SIZE (right));
3917 if (AOP_TYPE (right) == AOP_LIT)
3919 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3920 /* optimize if(x < 0) or if(x >= 0) */
3929 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3930 emitcode ("rola", "");
3931 hc08_useReg (hc08_reg_a);
3939 && ((AOP_TYPE (right) == AOP_LIT) ||
3940 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3941 && hc08_reg_hx->isFree)
3943 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3944 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3945 hc08_freeReg (hc08_reg_hx);
3956 loadRegFromAop (hc08_reg_a, AOP (left), offset);
3957 accopWithAop (sub, AOP (right), offset);
3958 hc08_freeReg (hc08_reg_a);
3964 freeAsmop (right, NULL, ic, TRUE);
3965 freeAsmop (left, NULL, ic, TRUE);
3966 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3972 /* if the result is used in the next
3973 ifx conditional branch then generate
3974 code a little differently */
3977 pullOrFreeReg(hc08_reg_a,needpula);
3978 genIfxJump (ifx, sign ? "s" : "c");
3985 pullOrFreeReg(hc08_reg_a,needpula);
3989 /*-----------------------------------------------------------------*/
3990 /* genCmpGt :- greater than comparison */
3991 /*-----------------------------------------------------------------*/
3993 genCmpGt (iCode * ic, iCode * ifx)
3995 operand *left, *right, *result;
3996 sym_link *letype, *retype;
3999 D(emitcode ("; genCmpGt",""));
4001 result = IC_RESULT (ic);
4002 left = IC_LEFT (ic);
4003 right = IC_RIGHT (ic);
4005 letype = getSpec (operandType (left));
4006 retype = getSpec (operandType (right));
4007 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4008 /* assign the amsops */
4009 aopOp (left, ic, FALSE);
4010 aopOp (right, ic, FALSE);
4011 aopOp (result, ic, TRUE);
4013 genCmp (right, left, result, ifx, sign,ic);
4015 freeAsmop (result, NULL, ic, TRUE);
4018 /*-----------------------------------------------------------------*/
4019 /* genCmpLt - less than comparisons */
4020 /*-----------------------------------------------------------------*/
4022 genCmpLt (iCode * ic, iCode * ifx)
4024 operand *left, *right, *result;
4025 sym_link *letype, *retype;
4028 D(emitcode ("; genCmpLt",""));
4030 result = IC_RESULT (ic);
4031 left = IC_LEFT (ic);
4032 right = IC_RIGHT (ic);
4034 letype = getSpec (operandType (left));
4035 retype = getSpec (operandType (right));
4036 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4038 /* assign the amsops */
4039 aopOp (left, ic, FALSE);
4040 aopOp (right, ic, FALSE);
4041 aopOp (result, ic, TRUE);
4043 genCmp (left, right, result, ifx, sign,ic);
4045 freeAsmop (result, NULL, ic, TRUE);
4048 /*-----------------------------------------------------------------*/
4049 /* - compare and branch if not equal */
4050 /*-----------------------------------------------------------------*/
4052 gencbneshort (operand * left, operand * right, symbol * lbl)
4054 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4056 unsigned long lit = 0L;
4058 /* if the left side is a literal or
4059 if the right is in a pointer register and left
4061 if (AOP_TYPE (left) == AOP_LIT)
4067 if (AOP_TYPE (right) == AOP_LIT)
4068 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4072 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4073 accopWithAop ("cmp", AOP (right), offset);
4074 hc08_useReg (hc08_reg_a);
4075 hc08_freeReg (hc08_reg_a);
4076 emitBranch ("bne", lbl);
4082 /*-----------------------------------------------------------------*/
4083 /* gencjne - compare and jump if not equal */
4084 /*-----------------------------------------------------------------*/
4086 gencjne (operand * left, operand * right, symbol * lbl)
4088 symbol *tlbl = newiTempLabel (NULL);
4090 gencbneshort (left, right, lbl);
4092 loadRegFromConst (hc08_reg_a, one);
4093 emitBranch ("bra", tlbl);
4095 loadRegFromConst (hc08_reg_a, zero);
4098 hc08_useReg(hc08_reg_a);
4099 hc08_freeReg(hc08_reg_a);
4102 /*-----------------------------------------------------------------*/
4103 /* genCmpEq - generates code for equal to */
4104 /*-----------------------------------------------------------------*/
4106 genCmpEq (iCode * ic, iCode * ifx)
4108 operand *left, *right, *result;
4110 D(emitcode ("; genCmpEq",""));
4112 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4113 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4114 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4116 /* if literal, literal on the right or
4117 if the right is in a pointer register and left
4119 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4121 operand *t = IC_RIGHT (ic);
4122 IC_RIGHT (ic) = IC_LEFT (ic);
4126 if (ifx && !AOP_SIZE (result))
4129 tlbl = newiTempLabel (NULL);
4130 gencbneshort (left, right, tlbl);
4133 emitBranch ("jmp", IC_TRUE (ifx));
4138 symbol *lbl = newiTempLabel (NULL);
4139 emitBranch ("bra", lbl);
4141 emitBranch ("jmp", IC_FALSE (ifx));
4145 /* mark the icode as generated */
4150 gencjne (left, right, newiTempLabel (NULL));
4151 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4153 storeRegToAop (hc08_reg_a, AOP (result), 0);
4158 genIfxJump (ifx, "a");
4161 /* if the result is used in an arithmetic operation
4162 then put the result in place */
4163 if (AOP_TYPE (result) != AOP_CRY)
4167 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4168 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4169 freeAsmop (result, NULL, ic, TRUE);
4172 /*-----------------------------------------------------------------*/
4173 /* ifxForOp - returns the icode containing the ifx for operand */
4174 /*-----------------------------------------------------------------*/
4176 ifxForOp (operand * op, iCode * ic)
4178 /* if true symbol then needs to be assigned */
4179 if (IS_TRUE_SYMOP (op))
4182 /* if this has register type condition and
4183 the next instruction is ifx with the same operand
4184 and live to of the operand is upto the ifx only then */
4186 ic->next->op == IFX &&
4187 IC_COND (ic->next)->key == op->key &&
4188 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4195 genPointerGetSetOfs (iCode *ic)
4197 iCode *lic = ic->next;
4203 /* Make sure we have a next iCode */
4204 D(emitcode("","; checking lic"));
4208 /* Make sure the result of the addition is an iCode */
4209 D(emitcode("","; checking IS_ITEMP"));
4210 if (!IS_ITEMP (IC_RESULT (ic)))
4213 /* Make sure the next iCode is a pointer set or get */
4214 pset = POINTER_SET(lic);
4215 pget = POINTER_GET(lic);
4216 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4220 D(emitcode("", "; checking pset operandsEqu"));
4221 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4224 D(emitcode("", "; checking pget operandsEqu"));
4225 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4228 D(emitcode("", "; checking IS_SYMOP"));
4229 if (!IS_SYMOP (IC_LEFT (ic)))
4232 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4233 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4236 sym = OP_SYMBOL (IC_LEFT (ic));
4238 D(emitcode("", "; checking remat"));
4245 D(emitcode ("; genPointerGetOfs",""));
4246 aopOp (IC_LEFT(ic), ic, FALSE);
4247 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4248 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4250 aopOp (IC_RIGHT(ic), ic, FALSE);
4251 aopOp (IC_RESULT(lic), lic, FALSE);
4253 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4255 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4257 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4258 loadRegFromConst (hc08_reg_h, zero);
4262 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4263 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4264 emitcode ("rola","");
4265 emitcode ("clra","");
4266 emitcode ("sbc", "#0");
4267 hc08_useReg (hc08_reg_a);
4268 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4272 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4273 size = AOP_SIZE (IC_RESULT(lic));
4274 derefaop->size = size;
4279 emitcode ("lda", "%s,x",
4280 aopAdrStr (derefaop, offset, TRUE));
4281 hc08_useReg (hc08_reg_a);
4282 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4283 hc08_freeReg (hc08_reg_a);
4287 hc08_freeReg (hc08_reg_hx);
4289 freeAsmop (NULL, derefaop, ic, TRUE);
4290 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4291 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4298 D(emitcode ("; genPointerSetOfs",""));
4299 aopOp (IC_LEFT(ic), ic, FALSE);
4300 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4301 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4303 aopOp (IC_RIGHT(ic), ic, FALSE);
4304 aopOp (IC_RIGHT(lic), lic, FALSE);
4306 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4308 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4310 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4311 loadRegFromConst (hc08_reg_h, zero);
4315 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4316 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4317 emitcode ("rola","");
4318 emitcode ("clra","");
4319 emitcode ("sbc", "#0");
4320 hc08_useReg (hc08_reg_a);
4321 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4325 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4326 size = AOP_SIZE (IC_RIGHT(lic));
4327 derefaop->size = size;
4332 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4333 emitcode ("sta", "%s,x",
4334 aopAdrStr (derefaop, offset, TRUE));
4335 hc08_freeReg (hc08_reg_a);
4340 hc08_freeReg (hc08_reg_hx);
4342 freeAsmop (NULL, derefaop, ic, TRUE);
4343 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4344 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4353 /*-----------------------------------------------------------------*/
4354 /* hasInc - operand is incremented before any other use */
4355 /*-----------------------------------------------------------------*/
4357 hasInc (operand *op, iCode *ic,int osize)
4359 sym_link *type = operandType(op);
4360 sym_link *retype = getSpec (type);
4361 iCode *lic = ic->next;
4364 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4365 if (!IS_SYMOP(op)) return NULL;
4367 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4368 if (IS_AGGREGATE(type->next)) return NULL;
4369 if (osize != (isize = getSize(type->next))) return NULL;
4372 /* if operand of the form op = op + <sizeof *op> */
4373 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4374 isOperandEqual(IC_RESULT(lic),op) &&
4375 isOperandLiteral(IC_RIGHT(lic)) &&
4376 operandLitValue(IC_RIGHT(lic)) == isize) {
4379 /* if the operand used or deffed */
4380 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4383 /* if GOTO or IFX */
4384 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4390 /*-----------------------------------------------------------------*/
4391 /* genAndOp - for && operation */
4392 /*-----------------------------------------------------------------*/
4394 genAndOp (iCode * ic)
4396 operand *left, *right, *result;
4397 symbol *tlbl, *tlbl0;
4399 D(emitcode ("; genAndOp",""));
4401 /* note here that && operations that are in an
4402 if statement are taken away by backPatchLabels
4403 only those used in arthmetic operations remain */
4404 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4405 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4406 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4408 tlbl = newiTempLabel (NULL);
4409 tlbl0 = newiTempLabel (NULL);
4411 asmopToBool (AOP (left), FALSE);
4412 emitBranch ("beq", tlbl0);
4413 asmopToBool (AOP (right), FALSE);
4414 emitBranch ("beq", tlbl0);
4415 loadRegFromConst (hc08_reg_a,one);
4416 emitBranch ("bra", tlbl);
4418 loadRegFromConst (hc08_reg_a,zero);
4421 hc08_useReg (hc08_reg_a);
4422 hc08_freeReg (hc08_reg_a);
4424 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4426 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4427 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4428 freeAsmop (result, NULL, ic, TRUE);
4432 /*-----------------------------------------------------------------*/
4433 /* genOrOp - for || operation */
4434 /*-----------------------------------------------------------------*/
4436 genOrOp (iCode * ic)
4438 operand *left, *right, *result;
4439 symbol *tlbl, *tlbl0;
4441 D(emitcode ("; genOrOp",""));
4443 /* note here that || operations that are in an
4444 if statement are taken away by backPatchLabels
4445 only those used in arthmetic operations remain */
4446 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4447 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4448 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4450 tlbl = newiTempLabel (NULL);
4451 tlbl0 = newiTempLabel (NULL);
4453 asmopToBool (AOP (left), FALSE);
4454 emitBranch ("bne", tlbl0);
4455 asmopToBool (AOP (right), FALSE);
4456 emitBranch ("bne", tlbl0);
4457 loadRegFromConst (hc08_reg_a,zero);
4458 emitBranch ("bra", tlbl);
4460 loadRegFromConst (hc08_reg_a,one);
4463 hc08_useReg (hc08_reg_a);
4464 hc08_freeReg (hc08_reg_a);
4466 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4469 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4470 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4471 freeAsmop (result, NULL, ic, TRUE);
4474 /*-----------------------------------------------------------------*/
4475 /* isLiteralBit - test if lit == 2^n */
4476 /*-----------------------------------------------------------------*/
4478 isLiteralBit (unsigned long lit)
4480 unsigned long pw[32] =
4481 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4482 0x100L, 0x200L, 0x400L, 0x800L,
4483 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4484 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4485 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4486 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4487 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4490 for (idx = 0; idx < 32; idx++)
4497 /*-----------------------------------------------------------------*/
4498 /* continueIfTrue - */
4499 /*-----------------------------------------------------------------*/
4501 continueIfTrue (iCode * ic)
4504 emitBranch ("jmp", IC_TRUE (ic));
4508 /*-----------------------------------------------------------------*/
4510 /*-----------------------------------------------------------------*/
4512 jumpIfTrue (iCode * ic)
4515 emitBranch ("jmp", IC_FALSE (ic));
4519 /*-----------------------------------------------------------------*/
4520 /* jmpTrueOrFalse - */
4521 /*-----------------------------------------------------------------*/
4523 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4525 // ugly but optimized by peephole
4528 symbol *nlbl = newiTempLabel (NULL);
4529 emitBranch ("bra", nlbl);
4531 emitBranch ("jmp", IC_TRUE (ic));
4536 emitBranch ("jmp", IC_FALSE (ic));
4543 /*-----------------------------------------------------------------*/
4544 /* genAnd - code for and */
4545 /*-----------------------------------------------------------------*/
4547 genAnd (iCode * ic, iCode * ifx)
4549 operand *left, *right, *result;
4550 int size, offset = 0;
4551 unsigned long lit = 0L;
4552 unsigned long litinv;
4558 D(emitcode ("; genAnd",""));
4560 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4561 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4562 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4565 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4567 AOP_TYPE (left), AOP_TYPE (right)));
4568 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4570 AOP_SIZE (left), AOP_SIZE (right)));
4573 /* if left is a literal & right is not then exchange them */
4574 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4576 operand *tmp = right;
4581 /* if left is accumulator & right is not then exchange them */
4582 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4584 operand *tmp = right;
4590 if (AOP_TYPE (result) == AOP_CRY)
4593 wassertl (ifx, "AOP_CPY result without ifx");
4595 tlbl = newiTempLabel (NULL);
4596 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4600 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4601 if ((AOP_TYPE (right) == AOP_LIT)
4602 && (((lit >> (offset*8)) & 0xff) == 0xff))
4603 emitcode ("tsta","");
4605 accopWithAop ("and", AOP (right), offset);
4606 hc08_freeReg( hc08_reg_a);
4608 emitBranch ("bne", tlbl);
4612 genIfxJump (ifx, "a");
4618 size = AOP_SIZE (result);
4620 if (AOP_TYPE (right) == AOP_LIT)
4622 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4623 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4625 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4626 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4628 int bitpos = isLiteralBit(litinv)-1;
4629 emitcode ("bclr","#%d,%s",bitpos & 7,
4630 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4638 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4639 if ((AOP_TYPE (right) != AOP_LIT)
4640 || (((lit >> (offset*8)) & 0xff) != 0xff))
4641 accopWithAop ("and", AOP (right), offset);
4642 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4643 hc08_freeReg( hc08_reg_a);
4647 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4648 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4649 freeAsmop (result, NULL, ic, TRUE);
4652 /*-----------------------------------------------------------------*/
4653 /* genOr - code for or */
4654 /*-----------------------------------------------------------------*/
4656 genOr (iCode * ic, iCode * ifx)
4658 operand *left, *right, *result;
4659 int size, offset = 0;
4660 unsigned long lit = 0L;
4662 D(emitcode ("; genOr",""));
4664 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4665 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4666 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4669 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4671 AOP_TYPE (left), AOP_TYPE (right)));
4672 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4674 AOP_SIZE (left), AOP_SIZE (right)));
4677 /* if left is a literal & right is not then exchange them */
4678 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4680 operand *tmp = right;
4685 /* if left is accumulator & right is not then exchange them */
4686 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4688 operand *tmp = right;
4693 if (AOP_TYPE (result) == AOP_CRY)
4696 wassertl (ifx, "AOP_CPY result without ifx");
4698 tlbl = newiTempLabel (NULL);
4699 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4703 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4704 if ((AOP_TYPE (right) == AOP_LIT)
4705 && (((lit >> (offset*8)) & 0xff) == 0))
4706 emitcode ("tsta","");
4708 accopWithAop ("ora", AOP (right), offset);
4709 hc08_freeReg( hc08_reg_a);
4711 emitBranch ("bne", tlbl);
4715 genIfxJump (ifx, "a");
4721 if (AOP_TYPE (right) == AOP_LIT)
4722 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4724 size = AOP_SIZE (result);
4726 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4727 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4728 (AOP_TYPE (left) == AOP_DIR))
4730 int bitpos = isLiteralBit(lit)-1;
4731 emitcode ("bset","#%d,%s",bitpos & 7,
4732 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4739 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4740 accopWithAop ("ora", AOP (right), offset);
4741 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4742 hc08_freeReg( hc08_reg_a);
4747 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4748 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4749 freeAsmop (result, NULL, ic, TRUE);
4752 /*-----------------------------------------------------------------*/
4753 /* genXor - code for xclusive or */
4754 /*-----------------------------------------------------------------*/
4756 genXor (iCode * ic, iCode * ifx)
4758 operand *left, *right, *result;
4759 int size, offset = 0;
4760 unsigned long lit = 0L;
4762 D(emitcode ("; genXor",""));
4764 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4765 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4766 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4769 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4771 AOP_TYPE (left), AOP_TYPE (right)));
4772 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4774 AOP_SIZE (left), AOP_SIZE (right)));
4777 /* if left is a literal & right is not ||
4778 if left needs acc & right does not */
4779 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4781 operand *tmp = right;
4786 /* if left is accumulator & right is not then exchange them */
4787 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4789 operand *tmp = right;
4794 if (AOP_TYPE (result) == AOP_CRY)
4797 wassertl (ifx, "AOP_CPY result without ifx");
4799 tlbl = newiTempLabel (NULL);
4800 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4804 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4805 if ((AOP_TYPE (right) == AOP_LIT)
4806 && (((lit >> (offset*8)) & 0xff) == 0))
4807 emitcode ("tsta","");
4809 accopWithAop ("eor", AOP (right), offset);
4810 hc08_freeReg( hc08_reg_a);
4812 emitBranch ("bne", tlbl);
4816 genIfxJump (ifx, "a");
4822 if (AOP_TYPE (right) == AOP_LIT)
4823 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4825 size = AOP_SIZE (result);
4829 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4830 accopWithAop ("eor", AOP (right), offset);
4831 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4832 hc08_freeReg( hc08_reg_a);
4836 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4837 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4838 freeAsmop (result, NULL, ic, TRUE);
4842 emitinline (iCode * ic, char *inlin)
4848 symbol *sym, *tempsym;
4857 while (isalnum(*inlin) || (*inlin == '_'))
4861 //printf("Found possible symbol '%s'\n",symname);
4862 tempsym = newSymbol (symname, ic->level);
4863 tempsym->block = ic->block;
4864 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4873 aop = aopForSym (ic, sym, FALSE);
4874 l = aopAdrStr (aop, aop->size - 1, TRUE);
4878 if (!sym->allocreq && !sym->ismyparm)
4880 werror (E_ID_UNDEF, sym->name);
4882 " Add 'volatile' to the variable declaration so that it\n"
4883 " can be referenced within inline assembly");
4885 //printf("Replacing with '%s'\n",l);
4889 if ((2+bp-buffer)>sizeof(buffer))
4898 if ((2+bp-buffer)>sizeof(buffer))
4905 if ((2+bp-buffer)>sizeof(buffer))
4906 fprintf(stderr, "Inline assembly buffer overflow\n");
4908 //printf("%s\n",buffer);
4909 emitcode (buffer,"");
4913 /*-----------------------------------------------------------------*/
4914 /* genInline - write the inline code out */
4915 /*-----------------------------------------------------------------*/
4917 genInline (iCode * ic)
4919 char *buffer, *bp, *bp1;
4921 D(emitcode ("; genInline",""));
4923 _G.inLine += (!options.asmpeep);
4925 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4926 strcpy (buffer, IC_INLINE (ic));
4928 /* emit each line as a code */
4934 /* emitcode (bp1, ""); */
4935 emitinline (ic, bp1);
4954 /* emitcode (bp1, ""); */
4955 emitinline (ic, bp1);
4957 /* emitcode("",buffer); */
4958 _G.inLine -= (!options.asmpeep);
4961 /*-----------------------------------------------------------------*/
4962 /* genRRC - rotate right with carry */
4963 /*-----------------------------------------------------------------*/
4967 operand *left, *result;
4968 int size, offset = 0;
4969 bool needpula = FALSE;
4970 bool resultInA = FALSE;
4973 D(emitcode ("; genRRC",""));
4975 /* rotate right with carry */
4976 left = IC_LEFT (ic);
4977 result = IC_RESULT (ic);
4978 aopOp (left, ic, FALSE);
4979 aopOp (result, ic, FALSE);
4981 if ((AOP_TYPE (result) == AOP_REG)
4982 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4985 size = AOP_SIZE (result);
4989 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4993 rmwWithAop (shift, AOP (result), offset--);
5001 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5002 rmwWithReg (shift, hc08_reg_a);
5003 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5004 hc08_freeReg (hc08_reg_a);
5009 if ((!hc08_reg_a->isFree) || resultInA)
5011 pushReg (hc08_reg_a, TRUE);
5015 /* now we need to put the carry into the
5016 highest order byte of the result */
5017 offset = AOP_SIZE (result) - 1;
5018 emitcode ("clra","");
5019 emitcode ("rora","");
5020 hc08_dirtyReg (hc08_reg_a, FALSE);
5023 emitcode ("ora", "1,s");
5024 emitcode ("ais", "#1");
5025 hc08_dirtyReg (hc08_reg_a, FALSE);
5029 accopWithAop ("ora", AOP (result), offset);
5030 storeRegToAop (hc08_reg_a, AOP (result), offset);
5032 pullOrFreeReg (hc08_reg_a, needpula);
5034 freeAsmop (left, NULL, ic, TRUE);
5035 freeAsmop (result, NULL, ic, TRUE);
5038 /*-----------------------------------------------------------------*/
5039 /* genRLC - generate code for rotate left with carry */
5040 /*-----------------------------------------------------------------*/
5044 operand *left, *result;
5045 int size, offset = 0;
5047 bool resultInA = FALSE;
5048 bool needpula = FALSE;
5050 D(emitcode ("; genRLC",""));
5052 /* rotate right with carry */
5053 left = IC_LEFT (ic);
5054 result = IC_RESULT (ic);
5055 aopOp (left, ic, FALSE);
5056 aopOp (result, ic, FALSE);
5058 if ((AOP_TYPE (result) == AOP_REG)
5059 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5062 size = AOP_SIZE (result);
5066 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5070 rmwWithAop (shift, AOP (result), offset--);
5078 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5079 rmwWithReg (shift, hc08_reg_a);
5080 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5081 hc08_freeReg (hc08_reg_a);
5086 if ((!hc08_reg_a->isFree) || resultInA)
5088 pushReg (hc08_reg_a, TRUE);
5092 /* now we need to put the carry into the
5093 lowest order byte of the result */
5095 emitcode ("clra","");
5096 emitcode ("rola","");
5097 hc08_dirtyReg (hc08_reg_a, FALSE);
5100 emitcode ("ora", "1,s");
5101 emitcode ("ais", "#1");
5102 hc08_dirtyReg (hc08_reg_a, FALSE);
5106 accopWithAop ("ora", AOP (result), offset);
5107 storeRegToAop (hc08_reg_a, AOP (result), offset);
5109 pullOrFreeReg (hc08_reg_a, needpula);
5111 freeAsmop (left, NULL, ic, TRUE);
5112 freeAsmop (result, NULL, ic, TRUE);
5115 /*-----------------------------------------------------------------*/
5116 /* genGetHbit - generates code get highest order bit */
5117 /*-----------------------------------------------------------------*/
5119 genGetHbit (iCode * ic)
5121 operand *left, *result;
5123 D(emitcode ("; genGetHbit",""));
5125 left = IC_LEFT (ic);
5126 result = IC_RESULT (ic);
5127 aopOp (left, ic, FALSE);
5128 aopOp (result, ic, FALSE);
5130 /* get the highest order byte into a */
5131 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5132 emitcode ("rola", "");
5133 emitcode ("clra", "");
5134 emitcode ("rola", "");
5135 hc08_dirtyReg (hc08_reg_a, FALSE);
5136 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5137 hc08_freeReg (hc08_reg_a);
5139 freeAsmop (left, NULL, ic, TRUE);
5140 freeAsmop (result, NULL, ic, TRUE);
5143 /*-----------------------------------------------------------------*/
5144 /* genSwap - generates code to swap nibbles or bytes */
5145 /*-----------------------------------------------------------------*/
5147 genSwap (iCode * ic)
5149 operand *left, *result;
5151 D(emitcode ("; genSwap",""));
5153 left = IC_LEFT (ic);
5154 result = IC_RESULT (ic);
5155 aopOp (left, ic, FALSE);
5156 aopOp (result, ic, FALSE);
5158 switch (AOP_SIZE (left))
5160 case 1: /* swap nibbles in byte */
5161 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5162 emitcode ("nsa", "");
5163 hc08_dirtyReg (hc08_reg_a, FALSE);
5164 storeRegToAop (hc08_reg_a, AOP (result), 0);
5165 hc08_freeReg (hc08_reg_a);
5167 case 2: /* swap bytes in a word */
5168 if (operandsEqu (left, result))
5170 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5171 hc08_useReg (hc08_reg_a);
5172 transferAopAop (AOP (left), 1, AOP (result), 0);
5173 storeRegToAop (hc08_reg_a, AOP (result), 1);
5174 hc08_freeReg (hc08_reg_a);
5178 transferAopAop (AOP (left), 0, AOP (result), 1);
5179 transferAopAop (AOP (left), 1, AOP (result), 0);
5183 wassertl(FALSE, "unsupported SWAP operand size");
5186 freeAsmop (left, NULL, ic, TRUE);
5187 freeAsmop (result, NULL, ic, TRUE);
5191 /*-----------------------------------------------------------------*/
5192 /* AccRol - rotate left accumulator by known count */
5193 /*-----------------------------------------------------------------*/
5195 AccRol (int shCount)
5197 shCount &= 0x0007; // shCount : 0..7
5204 emitcode ("rola", ""); /* 1 cycle */
5207 emitcode ("rola", ""); /* 1 cycle */
5208 emitcode ("rola", ""); /* 1 cycle */
5211 emitcode ("nsa", "");
5212 emitcode ("rora", "");
5215 emitcode ("nsa", ""); /* 3 cycles */
5218 emitcode ("nsa", ""); /* 3 cycles */
5219 emitcode ("rola", ""); /* 1 cycle */
5222 emitcode ("nsa", ""); /* 3 cycles */
5223 emitcode ("rola", ""); /* 1 cycle */
5224 emitcode ("rola", ""); /* 1 cycle */
5227 emitcode ("nsa", ""); /* 3 cycles */
5228 emitcode ("rola", ""); /* 1 cycle */
5229 emitcode ("rola", ""); /* 1 cycle */
5230 emitcode ("rola", ""); /* 1 cycle */
5237 /*-----------------------------------------------------------------*/
5238 /* AccLsh - left shift accumulator by known count */
5239 /*-----------------------------------------------------------------*/
5241 AccLsh (int shCount)
5245 shCount &= 0x0007; // shCount : 0..7
5247 /* Shift counts of 4 and 5 are currently optimized for code size. */
5248 /* Falling through to the unrolled loop would be optimal for code speed. */
5249 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5253 accopWithMisc ("nsa", "");
5254 accopWithMisc ("and", "#0xf0");
5255 /* total: 5 cycles, 3 bytes */
5258 accopWithMisc ("nsa", "");
5259 accopWithMisc ("and", "#0xf0");
5260 accopWithMisc ("lsla", "");
5261 /* total: 6 cycles, 4 bytes */
5264 accopWithMisc ("rora", "");
5265 accopWithMisc ("rora", "");
5266 accopWithMisc ("rora", "");
5267 accopWithMisc ("and", "#0xc0");
5268 /* total: 5 cycles, 5 bytes */
5271 accopWithMisc ("rora", "");
5272 accopWithMisc ("clra", "");
5273 accopWithMisc ("rora", "");
5274 /* total: 3 cycles, 3 bytes */
5278 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5279 /* the fastest (shCount<6) and shortest (shCount<4). */
5280 for (i=0;i<shCount;i++)
5281 accopWithMisc ("lsla", "");
5285 /*-----------------------------------------------------------------*/
5286 /* AccSRsh - signed right shift accumulator by known count */
5287 /*-----------------------------------------------------------------*/
5289 AccSRsh (int shCount)
5293 shCount &= 0x0007; // shCount : 0..7
5297 accopWithMisc ("rola", "");
5298 accopWithMisc ("clra", "");
5299 accopWithMisc ("sbc", zero);
5300 /* total: 4 cycles, 4 bytes */
5304 for (i=0;i<shCount;i++)
5305 accopWithMisc ("asra", "");
5308 /*-----------------------------------------------------------------*/
5309 /* AccRsh - right shift accumulator by known count */
5310 /*-----------------------------------------------------------------*/
5312 AccRsh (int shCount, bool sign)
5322 shCount &= 0x0007; // shCount : 0..7
5324 /* Shift counts of 4 and 5 are currently optimized for code size. */
5325 /* Falling through to the unrolled loop would be optimal for code speed. */
5326 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5330 accopWithMisc ("nsa", "");
5331 accopWithMisc ("and", "#0x0f");
5332 /* total: 5 cycles, 3 bytes */
5335 accopWithMisc ("nsa", "");
5336 accopWithMisc ("and", "#0x0f");
5337 accopWithMisc ("lsra", "");
5338 /* total: 6 cycles, 4 bytes */
5341 accopWithMisc ("rola", "");
5342 accopWithMisc ("rola", "");
5343 accopWithMisc ("rola", "");
5344 accopWithMisc ("and", "#0x03");
5345 /* total: 5 cycles, 5 bytes */
5348 accopWithMisc ("rola", "");
5349 accopWithMisc ("clra", "");
5350 accopWithMisc ("rola", "");
5351 /* total: 3 cycles, 3 bytes */
5355 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5356 /* the fastest (shCount<6) and shortest (shCount<4). */
5357 for (i=0;i<shCount;i++)
5358 accopWithMisc ("lsra", "");
5362 /*-----------------------------------------------------------------*/
5363 /* XAccLsh - left shift register pair XA by known count */
5364 /*-----------------------------------------------------------------*/
5366 XAccLsh (int shCount)
5370 shCount &= 0x000f; // shCount : 0..15
5375 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5376 loadRegFromConst (hc08_reg_a, zero);
5380 /* if we can beat 2n cycles or bytes for some special case, do it here */
5384 /* bytes cycles reg x reg a carry
5385 ** abcd efgh ijkl mnop ?
5386 ** lsrx 1 1 0abc defg ijkl mnop h
5387 ** rora 1 1 0abc defg hijk lmno p
5388 ** tax 1 1 hijk lmno hijk lmno p
5389 ** clra 1 1 hijk lmno 0000 0000 p
5390 ** rora 1 1 hijk lmno p000 0000 0
5391 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5393 rmwWithReg ("lsr", hc08_reg_x);
5394 rmwWithReg ("ror", hc08_reg_a);
5395 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5396 loadRegFromConst (hc08_reg_a, zero);
5397 rmwWithReg ("ror", hc08_reg_a);
5404 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5405 /* the fastest and shortest. */
5406 for (i=0;i<shCount;i++)
5408 rmwWithReg ("lsl", hc08_reg_a);
5409 rmwWithReg ("rol", hc08_reg_x);
5413 /*-----------------------------------------------------------------*/
5414 /* XAccSRsh - signed right shift register pair XA by known count */
5415 /*-----------------------------------------------------------------*/
5417 XAccSRsh (int shCount)
5421 shCount &= 0x000f; // shCount : 0..7
5423 /* if we can beat 2n cycles or bytes for some special case, do it here */
5427 /* bytes cycles reg x reg a carry
5428 ** abcd efgh ijkl mnop ?
5429 ** lslx 1 1 bcde fgh0 ijkl mnop a
5430 ** clra 1 1 bcde fgh0 0000 0000 a
5431 ** rola 1 1 bcde fgh0 0000 000a 0
5432 ** nega 1 1 bcde fgh0 aaaa aaaa a
5433 ** tax 1 1 aaaa aaaa aaaa aaaa a
5434 ** total: 5 cycles, 5 bytes
5436 rmwWithReg ("lsl", hc08_reg_x);
5437 loadRegFromConst (hc08_reg_a, zero);
5438 rmwWithReg ("rol", hc08_reg_a);
5439 rmwWithReg ("neg", hc08_reg_a);
5440 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5450 /* bytes cycles reg x reg a carry
5451 ** abcd efgh ijkl mnop ?
5452 ** txa 1 1 abcd efgh abcd efgh ?
5453 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5454 ** lsla 1 1 abcd efgh ???? ???? a
5455 ** clrx 1 1 0000 0000 ???? ???? a
5456 ** rolx 1 1 0000 000a ???? ???? 0
5457 ** negx 1 1 aaaa aaaa ???? ???? a
5458 ** rora 1 1 aaaa aaaa LSBresult 0
5459 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5461 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5462 AccSRsh (shCount-8);
5463 rmwWithReg ("lsl", hc08_reg_a);
5464 loadRegFromConst (hc08_reg_x, zero);
5465 rmwWithReg ("rol", hc08_reg_x);
5466 rmwWithReg ("neg", hc08_reg_x);
5467 rmwWithReg ("ror", hc08_reg_a);
5474 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5475 /* the fastest and shortest. */
5476 for (i=0;i<shCount;i++)
5478 rmwWithReg ("asr", hc08_reg_x);
5479 rmwWithReg ("ror", hc08_reg_a);
5483 /*-----------------------------------------------------------------*/
5484 /* XAccRsh - right shift register pair XA by known count */
5485 /*-----------------------------------------------------------------*/
5487 XAccRsh (int shCount, bool sign)
5497 shCount &= 0x000f; // shCount : 0..f
5499 /* if we can beat 2n cycles or bytes for some special case, do it here */
5503 /* bytes cycles reg x reg a carry
5504 ** abcd efgh ijkl mnop ?
5505 ** clra 1 1 abcd efgh 0000 0000 a
5506 ** lslx 1 1 bcde fgh0 0000 0000 a
5507 ** rola 1 1 bcde fgh0 0000 000a 0
5508 ** clrx 1 1 0000 0000 0000 000a 0
5509 ** total: 4 cycles, 4 bytes
5511 loadRegFromConst (hc08_reg_x, zero);
5512 rmwWithReg ("lsl", hc08_reg_x);
5513 rmwWithReg ("rol", hc08_reg_a);
5514 loadRegFromConst (hc08_reg_a, zero);
5518 /* bytes cycles reg x reg a carry
5519 ** abcd efgh ijkl mnop ?
5520 ** clra 1 1 abcd efgh 0000 0000 a
5521 ** lslx 1 1 bcde fgh0 0000 0000 a
5522 ** rola 1 1 bcde fgh0 0000 000a 0
5523 ** lslx 1 1 cdef gh00 0000 000a b
5524 ** rola 1 1 cdef gh00 0000 00ab 0
5525 ** clrx 1 1 0000 0000 0000 00ab 0
5526 ** total: 6 cycles, 6 bytes
5528 loadRegFromConst (hc08_reg_x, zero);
5529 rmwWithReg ("lsl", hc08_reg_x);
5530 rmwWithReg ("rol", hc08_reg_a);
5531 rmwWithReg ("lsl", hc08_reg_x);
5532 rmwWithReg ("rol", hc08_reg_a);
5533 loadRegFromConst (hc08_reg_a, zero);
5542 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5543 AccRsh (shCount-8, FALSE);
5544 loadRegFromConst (hc08_reg_x, zero);
5548 /* bytes cycles reg x reg a carry
5549 ** abcd efgh ijkl mnop ?
5550 ** lsla 1 1 abcd efgh jklm nop0 i
5551 ** txa 1 1 abcd efgh abcd efgh i
5552 ** rola 1 1 abcd efgh bcde fghi a
5553 ** clrx 1 1 0000 0000 bcde fghi a
5554 ** rolx 1 1 0000 000a bcde fghi 0
5555 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5557 rmwWithReg ("lsl", hc08_reg_a);
5558 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5559 rmwWithReg ("rol", hc08_reg_a);
5560 loadRegFromConst (hc08_reg_x, zero);
5561 rmwWithReg ("rol", hc08_reg_x);
5564 /* bytes cycles reg x reg a carry
5565 ** abcd efgh ijkl mnop ?
5566 ** lsla 1 1 abcd efgh jklm nop0 i
5567 ** rolx 1 1 bcde fghi jklm nop0 a
5568 ** rola 1 1 bcde fghi klmn op0a j
5569 ** rolx 1 1 cdef ghij klmn op0a b
5570 ** rola 1 1 cdef ghij lmno p0ab k
5571 ** and #3 2 2 cdef ghij 0000 00ab k
5572 ** psha 1 2 cdef ghij 0000 00ab k
5573 ** txa 1 1 cdef ghij cdef ghij k
5574 ** pula 1 2 0000 00ab cdef ghij k
5575 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5581 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5582 /* the fastest and shortest. */
5583 for (i=0;i<shCount;i++)
5585 rmwWithReg ("lsr", hc08_reg_x);
5586 rmwWithReg ("ror", hc08_reg_a);
5593 /*-----------------------------------------------------------------*/
5594 /* shiftR1Left2Result - shift right one byte from left to result */
5595 /*-----------------------------------------------------------------*/
5597 shiftR1Left2Result (operand * left, int offl,
5598 operand * result, int offr,
5599 int shCount, int sign)
5601 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5602 /* shift right accumulator */
5603 AccRsh (shCount, sign);
5604 storeRegToAop (hc08_reg_a, AOP (result), offr);
5608 /*-----------------------------------------------------------------*/
5609 /* shiftL1Left2Result - shift left one byte from left to result */
5610 /*-----------------------------------------------------------------*/
5612 shiftL1Left2Result (operand * left, int offl,
5613 operand * result, int offr, int shCount)
5615 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5616 /* shift left accumulator */
5618 storeRegToAop (hc08_reg_a, AOP (result), offr);
5621 /*-----------------------------------------------------------------*/
5622 /* movLeft2Result - move byte from left to result */
5623 /*-----------------------------------------------------------------*/
5625 movLeft2Result (operand * left, int offl,
5626 operand * result, int offr, int sign)
5628 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5630 transferAopAop (AOP (left), offl, AOP (result), offr);
5635 /*-----------------------------------------------------------------*/
5636 /* shiftL2Left2Result - shift left two bytes from left to result */
5637 /*-----------------------------------------------------------------*/
5639 shiftL2Left2Result (operand * left, int offl,
5640 operand * result, int offr, int shCount)
5643 bool needpula = FALSE;
5644 bool needpulx = FALSE;
5646 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
5647 needpula = pushRegIfUsed (hc08_reg_a);
5650 if (!IS_AOP_XA (AOP (left)))
5651 needpulx = pushRegIfUsed (hc08_reg_x);
5655 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5660 rmwWithReg ("lsr", hc08_reg_x);
5661 rmwWithReg ("ror", hc08_reg_a);
5662 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5663 rmwWithReg ("clr", hc08_reg_a);
5664 rmwWithReg ("ror", hc08_reg_a);
5667 for (i=0; i<shCount; i++)
5669 rmwWithReg ("lsl", hc08_reg_a);
5670 rmwWithReg ("rol", hc08_reg_x);
5673 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5675 pullOrFreeReg (hc08_reg_x, needpulx);
5676 pullOrFreeReg (hc08_reg_a, needpula);
5682 /*-----------------------------------------------------------------*/
5683 /* shiftR2Left2Result - shift right two bytes from left to result */
5684 /*-----------------------------------------------------------------*/
5686 shiftR2Left2Result (operand * left, int offl,
5687 operand * result, int offr,
5688 int shCount, int sign)
5691 bool needpula = FALSE;
5692 bool needpulx = FALSE;
5694 needpula = pushRegIfUsed (hc08_reg_a);
5695 needpulx = pushRegIfUsed (hc08_reg_x);
5697 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5698 for (i=0; i<shCount; i++)
5701 rmwWithReg ("asr", hc08_reg_x);
5703 rmwWithReg ("lsr", hc08_reg_x);
5704 rmwWithReg ("ror", hc08_reg_a);
5706 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5708 pullOrFreeReg (hc08_reg_x, needpulx);
5709 pullOrFreeReg (hc08_reg_a, needpula);
5714 /*-----------------------------------------------------------------*/
5715 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5716 /*-----------------------------------------------------------------*/
5718 shiftLLeftOrResult (operand * left, int offl,
5719 operand * result, int offr, int shCount)
5721 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5722 /* shift left accumulator */
5724 /* or with result */
5725 accopWithAop ("ora", AOP (result), offr);
5726 /* back to result */
5727 storeRegToAop (hc08_reg_a, AOP (result), offr);
5728 hc08_freeReg (hc08_reg_a);
5732 /*-----------------------------------------------------------------*/
5733 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5734 /*-----------------------------------------------------------------*/
5736 shiftRLeftOrResult (operand * left, int offl,
5737 operand * result, int offr, int shCount)
5739 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5740 /* shift left accumulator */
5741 AccRsh (shCount, FALSE);
5742 /* or with result */
5743 accopWithAop ("ora", AOP (result), offr);
5744 /* back to result */
5745 storeRegToAop (hc08_reg_a, AOP (result), offr);
5746 hc08_freeReg (hc08_reg_a);
5749 /*-----------------------------------------------------------------*/
5750 /* genlshOne - left shift a one byte quantity by known count */
5751 /*-----------------------------------------------------------------*/
5753 genlshOne (operand * result, operand * left, int shCount)
5755 D(emitcode ("; genlshOne",""));
5757 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5760 /*-----------------------------------------------------------------*/
5761 /* genlshTwo - left shift two bytes by known amount != 0 */
5762 /*-----------------------------------------------------------------*/
5764 genlshTwo (operand * result, operand * left, int shCount)
5768 D(emitcode ("; genlshTwo",""));
5771 size = getDataSize (result);
5773 /* if shCount >= 8 */
5780 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5782 storeRegToAop (hc08_reg_a, AOP (result), 1);
5784 storeConstToAop(zero, AOP (result), LSB);
5787 /* 1 <= shCount <= 7 */
5790 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5792 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5796 /*-----------------------------------------------------------------*/
5797 /* shiftLLong - shift left one long from left to result */
5798 /* offl = LSB or MSB16 */
5799 /*-----------------------------------------------------------------*/
5801 shiftLLong (operand * left, operand * result, int offr)
5804 // int size = AOP_SIZE (result);
5806 bool needpula = FALSE;
5807 bool needpulx = FALSE;
5809 needpula = pushRegIfUsed (hc08_reg_a);
5810 needpulx = pushRegIfUsed (hc08_reg_x);
5812 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5813 rmwWithReg ("lsl", hc08_reg_a);
5814 rmwWithReg ("rol", hc08_reg_x);
5815 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5819 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5820 rmwWithReg ("rol", hc08_reg_a);
5821 rmwWithReg ("rol", hc08_reg_x);
5822 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5824 else if (offr==MSB16)
5826 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5827 rmwWithReg ("rol", hc08_reg_a);
5828 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5831 pullOrFreeReg (hc08_reg_x, needpulx);
5832 pullOrFreeReg (hc08_reg_a, needpula);
5835 /*-----------------------------------------------------------------*/
5836 /* genlshFour - shift four byte by a known amount != 0 */
5837 /*-----------------------------------------------------------------*/
5839 genlshFour (operand * result, operand * left, int shCount)
5843 D(emitcode ("; genlshFour",""));
5845 size = AOP_SIZE (result);
5847 /* TODO: deal with the &result == &left case */
5849 /* if shifting more that 3 bytes */
5854 /* lowest order of left goes to the highest
5855 order of the destination */
5856 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5858 movLeft2Result (left, LSB, result, MSB32, 0);
5859 storeConstToAop (zero, AOP (result), LSB);
5860 storeConstToAop (zero, AOP (result), MSB16);
5861 storeConstToAop (zero, AOP (result), MSB24);
5865 /* more than two bytes */
5866 else if (shCount >= 16)
5868 /* lower order two bytes goes to higher order two bytes */
5870 /* if some more remaining */
5872 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5875 movLeft2Result (left, MSB16, result, MSB32, 0);
5876 movLeft2Result (left, LSB, result, MSB24, 0);
5878 storeConstToAop (zero, AOP (result), LSB);
5879 storeConstToAop (zero, AOP (result), MSB16);
5883 /* if more than 1 byte */
5884 else if (shCount >= 8)
5886 /* lower order three bytes goes to higher order three bytes */
5891 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5893 movLeft2Result (left, LSB, result, MSB16, 0);
5899 movLeft2Result (left, MSB24, result, MSB32, 0);
5900 movLeft2Result (left, MSB16, result, MSB24, 0);
5901 movLeft2Result (left, LSB, result, MSB16, 0);
5902 storeConstToAop (zero, AOP (result), LSB);
5904 else if (shCount == 1)
5905 shiftLLong (left, result, MSB16);
5908 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5909 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5910 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5911 storeConstToAop (zero, AOP (result), LSB);
5916 /* 1 <= shCount <= 7 */
5917 else if (shCount <= 2)
5919 shiftLLong (left, result, LSB);
5921 shiftLLong (result, result, LSB);
5923 /* 3 <= shCount <= 7, optimize */
5926 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5927 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5928 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5932 /*-----------------------------------------------------------------*/
5933 /* genLeftShiftLiteral - left shifting by known count */
5934 /*-----------------------------------------------------------------*/
5936 genLeftShiftLiteral (operand * left,
5941 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5944 D(emitcode ("; genLeftShiftLiteral",""));
5946 freeAsmop (right, NULL, ic, TRUE);
5948 aopOp (left, ic, FALSE);
5949 aopOp (result, ic, FALSE);
5951 // size = getSize (operandType (result));
5952 size = AOP_SIZE (result);
5955 D(emitcode ("; shift left ", "result %d, left %d", size,
5962 transferAopAop( AOP(left), size, AOP(result), size);
5964 else if (shCount >= (size * 8))
5967 storeConstToAop (zero, AOP (result), size);
5974 genlshOne (result, left, shCount);
5978 genlshTwo (result, left, shCount);
5982 genlshFour (result, left, shCount);
5985 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5986 "*** ack! mystery literal shift!\n");
5990 freeAsmop (left, NULL, ic, TRUE);
5991 freeAsmop (result, NULL, ic, TRUE);
5994 /*-----------------------------------------------------------------*/
5995 /* genLeftShift - generates code for left shifting */
5996 /*-----------------------------------------------------------------*/
5998 genLeftShift (iCode * ic)
6000 operand *left, *right, *result;
6002 symbol *tlbl, *tlbl1;
6007 D(emitcode ("; genLeftShift",""));
6009 right = IC_RIGHT (ic);
6010 left = IC_LEFT (ic);
6011 result = IC_RESULT (ic);
6013 aopOp (right, ic, FALSE);
6015 /* if the shift count is known then do it
6016 as efficiently as possible */
6017 if (AOP_TYPE (right) == AOP_LIT)
6019 genLeftShiftLiteral (left, right, result, ic);
6023 /* shift count is unknown then we have to form
6024 a loop get the loop count in A : Note: we take
6025 only the lower order byte since shifting
6026 more that 32 bits make no sense anyway, ( the
6027 largest size of an object can be only 32 bits ) */
6029 aopOp (left, ic, FALSE);
6030 aopOp (result, ic, FALSE);
6032 /* now move the left to the result if they are not the
6034 if (!sameRegs (AOP (left), AOP (result)))
6037 size = AOP_SIZE (result);
6041 transferAopAop (AOP (left), offset, AOP (result), offset);
6045 freeAsmop (left, NULL, ic, TRUE);
6047 tlbl = newiTempLabel (NULL);
6048 size = AOP_SIZE (result);
6050 tlbl1 = newiTempLabel (NULL);
6054 loadRegFromAop (reg, AOP (right), 0);
6055 freeAsmop (right, NULL, ic, TRUE);
6056 emitBranch ("beq", tlbl1);
6060 for (offset=0;offset<size;offset++)
6062 rmwWithAop (shift, AOP (result), offset);
6065 rmwWithReg ("dec", reg);
6066 emitBranch ("bne", tlbl);
6070 freeAsmop (result, NULL, ic, TRUE);
6073 /*-----------------------------------------------------------------*/
6074 /* genrshOne - right shift a one byte quantity by known count */
6075 /*-----------------------------------------------------------------*/
6077 genrshOne (operand * result, operand * left,
6078 int shCount, int sign)
6080 D(emitcode ("; genrshOne",""));
6082 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6083 AccRsh (shCount, sign);
6084 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6087 /*-----------------------------------------------------------------*/
6088 /* genrshTwo - right shift two bytes by known amount != 0 */
6089 /*-----------------------------------------------------------------*/
6091 genrshTwo (operand * result, operand * left,
6092 int shCount, int sign)
6094 D(emitcode ("; genrshTwo",""));
6096 /* if shCount >= 8 */
6099 if (shCount || sign)
6101 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6102 AccRsh (shCount-8, sign);
6103 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6107 transferAopAop (AOP (left), 1, AOP (result), 0);
6108 storeConstToAop (zero, AOP (result), 1);
6112 /* 1 <= shCount <= 7 */
6115 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6116 XAccRsh (shCount, sign);
6117 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6121 /*-----------------------------------------------------------------*/
6122 /* shiftRLong - shift right one long from left to result */
6123 /* offl = LSB or MSB16 */
6124 /*-----------------------------------------------------------------*/
6126 shiftRLong (operand * left, int offl,
6127 operand * result, int sign)
6130 // int size = AOP_SIZE (result);
6132 bool needpula = FALSE;
6133 bool needpulx = FALSE;
6135 needpula = pushRegIfUsed (hc08_reg_a);
6136 needpulx = pushRegIfUsed (hc08_reg_x);
6140 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6142 rmwWithReg ("asr", hc08_reg_x);
6144 rmwWithReg ("lsr", hc08_reg_x);
6145 rmwWithReg ("rol", hc08_reg_a);
6146 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6148 else if (offl==MSB16)
6150 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6152 rmwWithReg ("asr", hc08_reg_a);
6154 rmwWithReg ("lsr", hc08_reg_a);
6155 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6158 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6159 rmwWithReg ("ror", hc08_reg_x);
6160 rmwWithReg ("ror", hc08_reg_a);
6161 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6164 pullOrFreeReg (hc08_reg_x, needpulx);
6165 pullOrFreeReg (hc08_reg_a, needpula);
6168 /*-----------------------------------------------------------------*/
6169 /* genrshFour - shift four byte by a known amount != 0 */
6170 /*-----------------------------------------------------------------*/
6172 genrshFour (operand * result, operand * left,
6173 int shCount, int sign)
6175 /* TODO: handle cases where left == result */
6177 D(emitcode ("; genrshFour",""));
6179 /* if shifting more that 3 bytes */
6182 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6183 AccRsh (shCount-24, sign);
6184 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6187 else if (shCount >= 16)
6189 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6190 XAccRsh (shCount-16, sign);
6191 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6194 else if (shCount >= 8)
6197 shiftRLong (left, MSB16, result, sign);
6198 else if (shCount == 8)
6200 transferAopAop (AOP (left), 1, AOP (result), 0);
6201 transferAopAop (AOP (left), 2, AOP (result), 1);
6202 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6203 storeRegToAop (hc08_reg_a, AOP (result), 2);
6204 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6206 else if (shCount == 9)
6208 shiftRLong (left, MSB16, result, sign);
6212 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6213 XAccRsh (shCount-8, FALSE);
6214 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6215 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6216 loadRegFromConst (hc08_reg_a, zero);
6217 XAccRsh (shCount-8, sign);
6218 accopWithAop ("ora", AOP (result), 1);
6219 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6223 { /* 1 <= shCount <= 7 */
6226 shiftRLong (left, LSB, result, sign);
6230 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6231 XAccRsh (shCount, FALSE);
6232 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6233 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6235 accopWithAop ("ora", AOP (result), 1);
6236 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6237 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6238 XAccRsh (shCount, sign);
6239 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6244 /*-----------------------------------------------------------------*/
6245 /* genRightShiftLiteral - right shifting by known count */
6246 /*-----------------------------------------------------------------*/
6248 genRightShiftLiteral (operand * left,
6254 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6257 D(emitcode ("; genRightShiftLiteral",""));
6259 freeAsmop (right, NULL, ic, TRUE);
6261 aopOp (left, ic, FALSE);
6262 aopOp (result, ic, FALSE);
6265 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6269 size = getDataSize (left);
6270 /* test the LEFT size !!! */
6272 /* I suppose that the left size >= result size */
6275 size = getDataSize (result);
6277 transferAopAop (AOP (left), size, AOP(result), size);
6279 else if (shCount >= (size * 8))
6282 /* get sign in acc.7 */
6283 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6285 addSign (result, LSB, sign);
6292 genrshOne (result, left, shCount, sign);
6296 genrshTwo (result, left, shCount, sign);
6300 genrshFour (result, left, shCount, sign);
6306 freeAsmop (left, NULL, ic, TRUE);
6307 freeAsmop (result, NULL, ic, TRUE);
6311 /*-----------------------------------------------------------------*/
6312 /* genRightShift - generate code for right shifting */
6313 /*-----------------------------------------------------------------*/
6315 genRightShift (iCode * ic)
6317 operand *right, *left, *result;
6321 symbol *tlbl, *tlbl1;
6325 D(emitcode ("; genRightShift",""));
6327 /* if signed then we do it the hard way preserve the
6328 sign bit moving it inwards */
6329 retype = getSpec (operandType (IC_RESULT (ic)));
6330 sign = !SPEC_USIGN (retype);
6332 /* signed & unsigned types are treated the same : i.e. the
6333 signed is NOT propagated inwards : quoting from the
6334 ANSI - standard : "for E1 >> E2, is equivalent to division
6335 by 2**E2 if unsigned or if it has a non-negative value,
6336 otherwise the result is implementation defined ", MY definition
6337 is that the sign does not get propagated */
6339 right = IC_RIGHT (ic);
6340 left = IC_LEFT (ic);
6341 result = IC_RESULT (ic);
6343 aopOp (right, ic, FALSE);
6345 /* if the shift count is known then do it
6346 as efficiently as possible */
6347 if (AOP_TYPE (right) == AOP_LIT)
6349 genRightShiftLiteral (left, right, result, ic, sign);
6353 /* shift count is unknown then we have to form
6354 a loop get the loop count in X : Note: we take
6355 only the lower order byte since shifting
6356 more that 32 bits make no sense anyway, ( the
6357 largest size of an object can be only 32 bits ) */
6359 aopOp (left, ic, FALSE);
6360 aopOp (result, ic, FALSE);
6362 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6363 AOP (result) = forceStackedAop (AOP (result));
6365 size = AOP_SIZE (result);
6369 transferAopAop (AOP (left), offset, AOP (result), offset);
6373 tlbl = newiTempLabel (NULL);
6374 size = AOP_SIZE (result);
6376 tlbl1 = newiTempLabel (NULL);
6378 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6379 emitcode ("tstx", "");
6380 emitcode ("beq", "%05d$", tlbl1->key + 100);
6381 emitcode ("", "%05d$:", tlbl->key + 100);
6382 shift= sign ? "asr" : "lsr";
6383 for (offset=size-1;offset>=0;offset--)
6385 rmwWithAop (shift, AOP (result), offset);
6388 rmwWithReg ("dec", hc08_reg_x);
6389 emitcode ("bne","%05d$", tlbl->key + 100);
6390 emitcode ("", "%05d$:", tlbl1->key + 100);
6392 freeAsmop (result, NULL, ic, TRUE);
6393 freeAsmop (left, NULL, ic, TRUE);
6394 freeAsmop (right, NULL, ic, TRUE);
6397 /*-----------------------------------------------------------------*/
6398 /* genUnpackBits - generates code for unpacking bits */
6399 /*-----------------------------------------------------------------*/
6401 genUnpackBits (operand * result)
6403 int offset = 0; /* result byte offset */
6404 int rsize; /* result size */
6405 int rlen = 0; /* remaining bitfield length */
6406 sym_link *etype; /* bitfield type information */
6407 int blen; /* bitfield length */
6408 int bstr; /* bitfield starting bit within byte */
6410 D(emitcode ("; genUnpackBits",""));
6412 etype = getSpec (operandType (result));
6413 rsize = getSize (operandType (result));
6414 blen = SPEC_BLEN (etype);
6415 bstr = SPEC_BSTR (etype);
6417 /* If the bitfield length is less than a byte */
6420 emitcode ("lda", ",x");
6421 hc08_dirtyReg (hc08_reg_a, FALSE);
6422 AccRsh (bstr, FALSE);
6423 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6424 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6428 /* Bit field did not fit in a byte. Copy all
6429 but the partial byte at the end. */
6430 for (rlen=blen;rlen>=8;rlen-=8)
6432 emitcode ("lda", ",x");
6433 hc08_dirtyReg (hc08_reg_a, FALSE);
6434 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6436 emitcode ("aix", "#1");
6439 /* Handle the partial byte at the end */
6442 emitcode ("lda", ",x");
6443 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6444 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6452 storeConstToAop (zero, AOP (result), offset++);
6457 /*-----------------------------------------------------------------*/
6458 /* genDataPointerGet - generates code when ptr offset is known */
6459 /*-----------------------------------------------------------------*/
6461 genDataPointerGet (operand * left,
6465 int size, offset = 0;
6468 D(emitcode ("; genDataPointerGet",""));
6470 aopOp (result, ic, TRUE);
6471 size = AOP_SIZE (result);
6473 derefaop = aopDerefAop (AOP (left));
6474 freeAsmop (left, NULL, ic, TRUE);
6475 derefaop->size = size;
6479 transferAopAop(derefaop, offset, AOP (result), offset);
6483 freeAsmop (NULL, derefaop, ic, TRUE);
6484 freeAsmop (result, NULL, ic, TRUE);
6488 /*-----------------------------------------------------------------*/
6489 /* genNearPointerGet - emitcode for near pointer fetch */
6490 /*-----------------------------------------------------------------*/
6492 genNearPointerGet (operand * left,
6498 sym_link *retype = getSpec (operandType (result));
6500 D(emitcode ("; genNearPointerGet",""));
6502 aopOp (left, ic, FALSE);
6504 /* if left is rematerialisable and
6505 result is not bit variable type and
6506 the left is pointer to data space i.e
6507 lower 128 bytes of space */
6508 if ((AOP_TYPE (left) == AOP_IMMD)
6509 || (AOP_TYPE (left) == AOP_LIT)
6510 /* !IS_BITVAR (retype) */
6511 /* && DCL_TYPE (ltype) == POINTER */ )
6513 genDataPointerGet (left, result, ic);
6517 /* if the operand is already in hx
6518 then we do nothing else we move the value to hx */
6519 if (AOP_TYPE (left) != AOP_STR)
6521 /* if this is remateriazable */
6522 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6523 loadRegFromConst (hc08_reg_h, zero);
6526 /* so hx now contains the address */
6527 aopOp (result, ic, FALSE);
6529 /* if bit then unpack */
6530 if (IS_BITVAR (retype))
6531 genUnpackBits (result);
6534 size = AOP_SIZE (result);
6539 accopWithMisc ("lda", ",x");
6542 rmwWithReg ("inc", hc08_reg_x);
6544 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6545 hc08_freeReg (hc08_reg_a);
6549 freeAsmop (left, NULL, ic, TRUE);
6550 freeAsmop (result, NULL, ic, TRUE);
6552 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6553 aopOp (IC_RESULT (pi), pi, FALSE);
6554 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6555 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6559 hc08_freeReg (hc08_reg_hx);
6563 /*-----------------------------------------------------------------*/
6564 /* genFarPointerGet - get value from far space */
6565 /*-----------------------------------------------------------------*/
6567 genFarPointerGet (operand * left,
6568 operand * result, iCode * ic, iCode * pi)
6571 sym_link *retype = getSpec (operandType (result));
6573 D(emitcode ("; genFarPointerGet",""));
6575 aopOp (left, ic, FALSE);
6577 /* if left is rematerialisable and
6578 result is not bit variable type and
6579 the left is pointer to data space i.e
6580 lower 128 bytes of space */
6581 if (AOP_TYPE (left) == AOP_IMMD &&
6583 /* && DCL_TYPE (ltype) == POINTER */ )
6585 genDataPointerGet (left, result, ic);
6589 /* if the operand is already in hx
6590 then we do nothing else we move the value to hx */
6591 if (AOP_TYPE (left) != AOP_STR)
6593 /* if this is remateriazable */
6594 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6597 /* so hx now contains the address */
6598 aopOp (result, ic, FALSE);
6600 /* if bit then unpack */
6601 if (IS_BITVAR (retype))
6602 genUnpackBits (result);
6605 size = AOP_SIZE (result);
6610 accopWithMisc ("lda", ",x");
6613 emitcode ("aix", "#1");
6614 hc08_dirtyReg (hc08_reg_hx, FALSE);
6616 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6617 hc08_freeReg (hc08_reg_a);
6621 freeAsmop (left, NULL, ic, TRUE);
6622 freeAsmop (result, NULL, ic, TRUE);
6624 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6625 aopOp (IC_RESULT (pi), pi, FALSE);
6626 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6627 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6631 hc08_freeReg (hc08_reg_hx);
6637 /*-----------------------------------------------------------------*/
6638 /* genPointerGet - generate code for pointer get */
6639 /*-----------------------------------------------------------------*/
6641 genPointerGet (iCode * ic, iCode *pi)
6643 operand *left, *result;
6644 sym_link *type, *etype;
6647 D(emitcode ("; genPointerGet",""));
6649 left = IC_LEFT (ic);
6650 result = IC_RESULT (ic);
6652 /* depending on the type of pointer we need to
6653 move it to the correct pointer register */
6654 type = operandType (left);
6655 etype = getSpec (type);
6656 /* if left is of type of pointer then it is simple */
6657 if (IS_PTR (type) && !IS_FUNC (type->next))
6658 p_type = DCL_TYPE (type);
6661 /* we have to go by the storage class */
6662 p_type = PTR_TYPE (SPEC_OCLS (etype));
6665 /* special case when cast remat */
6666 if (p_type == GPOINTER && IS_SYMOP(left) && OP_SYMBOL(left)->remat &&
6667 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6668 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6669 type = operandType (left);
6670 p_type = DCL_TYPE (type);
6672 /* now that we have the pointer type we assign
6673 the pointer values */
6680 genNearPointerGet (left, result, ic, pi);
6686 genFarPointerGet (left, result, ic, pi);
6693 /*-----------------------------------------------------------------*/
6694 /* genPackBits - generates code for packed bit storage */
6695 /*-----------------------------------------------------------------*/
6697 genPackBits (sym_link * etype,
6700 int offset = 0; /* source byte offset */
6701 int rlen = 0; /* remaining bitfield length */
6702 int blen; /* bitfield length */
6703 int bstr; /* bitfield starting bit within byte */
6704 int litval; /* source literal value (if AOP_LIT) */
6705 unsigned char mask; /* bitmask within current byte */
6707 D(emitcode ("; genPackBits",""));
6709 blen = SPEC_BLEN (etype);
6710 bstr = SPEC_BSTR (etype);
6712 /* If the bitfield length is less than a byte */
6715 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6716 (unsigned char) (0xFF >> (8 - bstr)));
6718 if (AOP_TYPE (right) == AOP_LIT)
6720 /* Case with a bitfield length <8 and literal source
6722 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6724 litval &= (~mask) & 0xff;
6726 emitcode ("lda", ",x");
6727 if ((mask|litval)!=0xff)
6728 emitcode ("and","#0x%02x", mask);
6730 emitcode ("ora","#0x%02x", litval);
6731 hc08_dirtyReg (hc08_reg_a, FALSE);
6732 emitcode ("sta", ",x");
6734 hc08_freeReg (hc08_reg_a);
6738 /* Case with a bitfield length < 8 and arbitrary source
6740 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6741 /* shift and mask source value */
6743 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6744 hc08_dirtyReg (hc08_reg_a, FALSE);
6745 pushReg (hc08_reg_a, TRUE);
6747 emitcode ("lda", ",x");
6748 emitcode ("and", "#0x%02x", mask);
6749 emitcode ("ora", "1,s");
6750 emitcode ("sta", ",x");
6751 pullReg (hc08_reg_a);
6753 hc08_freeReg (hc08_reg_a);
6757 /* Bit length is greater than 7 bits. In this case, copy */
6758 /* all except the partial byte at the end */
6759 for (rlen=blen;rlen>=8;rlen-=8)
6761 if (AOP (right)->type == AOP_DIR)
6763 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6767 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6768 emitcode ("sta", "%d,x", offset);
6773 /* If there was a partial byte at the end */
6776 mask = (((unsigned char) -1 << rlen) & 0xff);
6778 if (AOP_TYPE (right) == AOP_LIT)
6780 /* Case with partial byte and literal source
6782 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6783 litval >>= (blen-rlen);
6784 litval &= (~mask) & 0xff;
6785 emitcode ("lda", "%d,x", offset);
6786 hc08_dirtyReg (hc08_reg_a, FALSE);
6787 if ((mask|litval)!=0xff)
6788 emitcode ("and","#0x%02x", mask);
6790 emitcode ("ora","#0x%02x", litval);
6791 emitcode ("sta", "%d,x", offset);
6792 hc08_dirtyReg (hc08_reg_a, FALSE);
6793 hc08_freeReg (hc08_reg_a);
6797 /* Case with partial byte and arbitrary source
6799 loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6800 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6801 hc08_dirtyReg (hc08_reg_a, FALSE);
6802 pushReg (hc08_reg_a, TRUE);
6804 emitcode ("lda", ",x");
6805 emitcode ("and", "#0x%02x", mask);
6806 emitcode ("ora", "1,s");
6807 emitcode ("sta", ",x");
6808 pullReg (hc08_reg_a);
6811 hc08_freeReg (hc08_reg_a);
6814 /*-----------------------------------------------------------------*/
6815 /* genDataPointerSet - remat pointer to data space */
6816 /*-----------------------------------------------------------------*/
6818 genDataPointerSet (operand * right,
6822 int size, offset = 0;
6825 D(emitcode ("; genDataPointerSet",""));
6827 aopOp (right, ic, FALSE);
6828 size = AOP_SIZE (right);
6830 derefaop = aopDerefAop (AOP (result));
6831 freeAsmop (result, NULL, ic, TRUE);
6832 derefaop->size = size;
6836 transferAopAop (AOP (right), offset, derefaop, offset);
6840 freeAsmop (right, NULL, ic, TRUE);
6841 freeAsmop (NULL, derefaop, ic, TRUE);
6845 /*-----------------------------------------------------------------*/
6846 /* genNearPointerSet - emitcode for near pointer put */
6847 /*-----------------------------------------------------------------*/
6849 genNearPointerSet (operand * right,
6855 sym_link *retype = getSpec (operandType (right));
6856 sym_link *letype = getSpec (operandType (result));
6858 D(emitcode ("; genNearPointerSet",""));
6860 aopOp (result, ic, FALSE);
6862 /* if the result is rematerializable &
6863 in data space & not a bit variable */
6864 if (AOP_TYPE (result) == AOP_IMMD &&
6865 /* DCL_TYPE (ptype) == POINTER && */
6866 !IS_BITVAR (retype) &&
6867 !IS_BITVAR (letype))
6869 genDataPointerSet (right, result, ic);
6873 /* if the operand is already in hx
6874 then we do nothing else we move the value to hx */
6875 if (AOP_TYPE (result) != AOP_STR)
6877 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6878 loadRegFromConst (hc08_reg_h, zero);
6880 /* so hx now contains the address */
6881 aopOp (right, ic, FALSE);
6883 /* if bit then unpack */
6884 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6885 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6888 size = AOP_SIZE (right);
6893 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6894 accopWithMisc ("sta", ",x");
6897 rmwWithReg ("inc", hc08_reg_x);
6899 hc08_freeReg (hc08_reg_a);
6903 freeAsmop (result, NULL, ic, TRUE);
6904 freeAsmop (right, NULL, ic, TRUE);
6906 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6907 aopOp (IC_RESULT (pi), pi, FALSE);
6908 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6909 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6913 hc08_freeReg (hc08_reg_hx);
6918 /*-----------------------------------------------------------------*/
6919 /* genFarPointerSet - set value from far space */
6920 /*-----------------------------------------------------------------*/
6922 genFarPointerSet (operand * right,
6923 operand * result, iCode * ic, iCode * pi)
6926 sym_link *retype = getSpec (operandType (right));
6927 sym_link *letype = getSpec (operandType (result));
6929 D(emitcode ("; genFarPointerSet",""));
6931 aopOp (result, ic, FALSE);
6933 /* if the result is rematerializable &
6934 in data space & not a bit variable */
6935 if (AOP_TYPE (result) == AOP_IMMD &&
6936 /* DCL_TYPE (ptype) == POINTER && */
6937 !IS_BITVAR (retype) &&
6938 !IS_BITVAR (letype))
6940 genDataPointerSet (right, result, ic);
6944 /* if the operand is already in hx
6945 then we do nothing else we move the value to hx */
6946 if (AOP_TYPE (result) != AOP_STR)
6948 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6950 /* so hx now contains the address */
6951 aopOp (right, ic, FALSE);
6953 /* if bit then unpack */
6954 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6955 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6958 size = AOP_SIZE (right);
6963 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6964 accopWithMisc ("sta", ",x");
6967 emitcode ("aix", "#1");
6969 hc08_freeReg (hc08_reg_a);
6973 freeAsmop (result, NULL, ic, TRUE);
6974 freeAsmop (right, NULL, ic, TRUE);
6976 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6977 aopOp (IC_RESULT (pi), pi, FALSE);
6978 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6979 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6983 hc08_freeReg (hc08_reg_hx);
6989 /*-----------------------------------------------------------------*/
6990 /* genPointerSet - stores the value into a pointer location */
6991 /*-----------------------------------------------------------------*/
6993 genPointerSet (iCode * ic, iCode *pi)
6995 operand *right, *result;
6996 sym_link *type, *etype;
6999 D(emitcode ("; genPointerSet",""));
7001 right = IC_RIGHT (ic);
7002 result = IC_RESULT (ic);
7004 /* depending on the type of pointer we need to
7005 move it to the correct pointer register */
7006 type = operandType (result);
7007 etype = getSpec (type);
7008 /* if left is of type of pointer then it is simple */
7009 if (IS_PTR (type) && !IS_FUNC (type->next))
7011 p_type = DCL_TYPE (type);
7015 /* we have to go by the storage class */
7016 p_type = PTR_TYPE (SPEC_OCLS (etype));
7019 /* special case when cast remat */
7020 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
7021 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
7022 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
7023 type = operandType (result);
7024 p_type = DCL_TYPE (type);
7026 /* now that we have the pointer type we assign
7027 the pointer values */
7034 genNearPointerSet (right, result, ic, pi);
7040 genFarPointerSet (right, result, ic, pi);
7044 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7045 "genPointerSet: illegal pointer type");
7050 /*-----------------------------------------------------------------*/
7051 /* genIfx - generate code for Ifx statement */
7052 /*-----------------------------------------------------------------*/
7054 genIfx (iCode * ic, iCode * popIc)
7056 operand *cond = IC_COND (ic);
7059 D(emitcode ("; genIfx",""));
7061 aopOp (cond, ic, FALSE);
7063 /* get the value into acc */
7064 if (AOP_TYPE (cond) != AOP_CRY)
7065 asmopToBool (AOP (cond), FALSE);
7068 /* the result is now in the accumulator */
7069 freeAsmop (cond, NULL, ic, TRUE);
7071 /* if there was something to be popped then do it */
7075 /* if the condition is a bit variable */
7076 if (isbit && IS_ITEMP (cond) &&
7078 genIfxJump (ic, SPIL_LOC (cond)->rname);
7079 else if (isbit && !IS_ITEMP (cond))
7080 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7082 genIfxJump (ic, "a");
7087 /*-----------------------------------------------------------------*/
7088 /* genAddrOf - generates code for address of */
7089 /*-----------------------------------------------------------------*/
7091 genAddrOf (iCode * ic)
7093 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7096 D(emitcode ("; genAddrOf",""));
7098 aopOp (IC_RESULT (ic), ic, FALSE);
7100 /* if the operand is on the stack then we
7101 need to get the stack offset of this
7105 /* if it has an offset then we need to compute
7107 hc08_useReg (hc08_reg_hx);
7108 emitcode ("tsx", "");
7109 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7110 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7111 hc08_freeReg (hc08_reg_hx);
7116 /* object not on stack then we need the name */
7117 size = AOP_SIZE (IC_RESULT (ic));
7122 char s[SDCC_NAME_MAX+10];
7125 sprintf (s, "#%s", sym->rname);
7128 sprintf (s, "#>%s", sym->rname);
7131 sprintf (s, "#(%s >> %d)",
7135 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7139 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7143 /*-----------------------------------------------------------------*/
7144 /* genAssign - generate code for assignment */
7145 /*-----------------------------------------------------------------*/
7147 genAssign (iCode * ic)
7149 operand *result, *right;
7151 // unsigned long lit = 0L;
7153 D(emitcode("; genAssign",""));
7155 result = IC_RESULT (ic);
7156 right = IC_RIGHT (ic);
7158 /* if they are the same */
7159 if (operandsEqu (result, right)) {
7163 aopOp (right, ic, FALSE);
7164 aopOp (result, ic, TRUE);
7166 /* if they are the same registers */
7167 if (sameRegs (AOP (right), AOP (result)))
7170 if ((AOP_TYPE (right) == AOP_LIT)
7171 && (IS_AOP_HX(AOP(result))))
7173 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7178 size = AOP_SIZE (result);
7183 transferAopAop (AOP (right), offset, AOP (result), offset);
7188 freeAsmop (right, NULL, ic, TRUE);
7189 freeAsmop (result, NULL, ic, TRUE);
7192 /*-----------------------------------------------------------------*/
7193 /* genJumpTab - genrates code for jump table */
7194 /*-----------------------------------------------------------------*/
7196 genJumpTab (iCode * ic)
7201 D(emitcode ("; genJumpTab",""));
7203 aopOp (IC_JTCOND (ic), ic, FALSE);
7204 /* get the condition into accumulator */
7205 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7206 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7207 /* multiply by three */
7208 pushReg (hc08_reg_a, FALSE);
7209 emitcode ("lsla", "");
7210 emitcode ("add","1,s");
7211 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7212 loadRegFromConst (hc08_reg_h, zero);
7214 jtab = newiTempLabel (NULL);
7215 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7216 emitcode ("", "%05d$:", jtab->key + 100);
7217 /* now generate the jump labels */
7218 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7219 jtab = setNextItem (IC_JTLABELS (ic)))
7220 emitcode ("jmp", "%05d$", jtab->key + 100);
7222 hc08_dirtyReg (hc08_reg_a, TRUE);
7223 hc08_dirtyReg (hc08_reg_hx, TRUE);
7226 /*-----------------------------------------------------------------*/
7227 /* genCast - gen code for casting */
7228 /*-----------------------------------------------------------------*/
7230 genCast (iCode * ic)
7232 operand *result = IC_RESULT (ic);
7233 sym_link *ctype = operandType (IC_LEFT (ic));
7234 sym_link *rtype = operandType (IC_RIGHT (ic));
7235 operand *right = IC_RIGHT (ic);
7238 D(emitcode("; genCast",""));
7240 /* if they are equivalent then do nothing */
7241 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7244 aopOp (right, ic, FALSE);
7245 aopOp (result, ic, FALSE);
7248 /* if they are the same size : or less */
7249 if (AOP_SIZE (result) <= AOP_SIZE (right))
7252 /* if they are in the same place */
7254 if (sameRegs (AOP (right), AOP (result)))
7258 /* if they in different places then copy */
7259 size = AOP_SIZE (result);
7263 transferAopAop(AOP (right), offset, AOP (result), offset);
7270 /* if the result is of type pointer */
7275 sym_link *type = operandType (right);
7276 sym_link *etype = getSpec (type);
7278 /* pointer to generic pointer */
7279 if (IS_GENPTR (ctype))
7282 p_type = DCL_TYPE (type);
7285 if (SPEC_SCLS(etype)==S_REGISTER) {
7286 // let's assume it is a generic pointer
7289 /* we have to go by the storage class */
7290 p_type = PTR_TYPE (SPEC_OCLS (etype));
7294 /* the first two bytes are known */
7295 size = GPTRSIZE - 1;
7299 transferAopAop(AOP (right), offset, AOP (result), offset);
7302 /* the last byte depending on type */
7305 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7310 // pointerTypeToGPByte will have bitched.
7314 sprintf(gpValStr, "#0x%d", gpVal);
7315 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7321 /* just copy the pointers */
7322 size = AOP_SIZE (result);
7326 transferAopAop(AOP (right), offset, AOP (result), offset);
7332 /* so we now know that the size of destination is greater
7333 than the size of the source */
7334 /* we move to result for the size of source */
7335 size = AOP_SIZE (right);
7339 transferAopAop(AOP (right), offset, AOP (result), offset);
7343 /* now depending on the sign of the source && destination */
7344 size = AOP_SIZE (result) - AOP_SIZE (right);
7345 /* if unsigned or not an integral type */
7346 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7349 storeConstToAop (zero, AOP (result), offset++);
7353 /* we need to extend the sign :{ */
7354 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7355 accopWithMisc ("rola", "");
7356 accopWithMisc ("clra", "");
7357 accopWithMisc ("sbc", zero);
7359 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7362 /* we are done hurray !!!! */
7365 freeAsmop (right, NULL, ic, TRUE);
7366 freeAsmop (result, NULL, ic, TRUE);
7370 /*-----------------------------------------------------------------*/
7371 /* genDjnz - generate decrement & jump if not zero instrucion */
7372 /*-----------------------------------------------------------------*/
7374 genDjnz (iCode * ic, iCode * ifx)
7380 D(emitcode ("; genDjnz",""));
7382 /* if the if condition has a false label
7383 then we cannot save */
7387 /* if the minus is not of the form
7389 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7390 !IS_OP_LITERAL (IC_RIGHT (ic)))
7393 if (operandLitValue (IC_RIGHT (ic)) != 1)
7396 /* dbnz doesn't support extended mode */
7397 if (isOperandInFarSpace (IC_RESULT (ic)))
7400 /* if the size of this greater than one then no
7402 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7404 aopOp (IC_RESULT (ic), ic, FALSE);
7405 if (AOP_SIZE (IC_RESULT (ic))>1)
7407 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7411 /* otherwise we can save BIG */
7412 lbl = newiTempLabel (NULL);
7413 lbl1 = newiTempLabel (NULL);
7416 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7419 emitBranch ("bra", lbl1);
7421 emitBranch ("jmp", IC_TRUE (ifx));
7424 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7429 /*-----------------------------------------------------------------*/
7430 /* genReceive - generate code for a receive iCode */
7431 /*-----------------------------------------------------------------*/
7433 genReceive (iCode * ic)
7437 D(emitcode ("; genReceive",""));
7439 aopOp (IC_RESULT (ic), ic, FALSE);
7440 size = AOP_SIZE (IC_RESULT (ic));
7445 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7446 AOP (IC_RESULT (ic)), offset);
7447 if (hc08_aop_pass[offset]->type == AOP_REG)
7448 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7453 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7456 /*-----------------------------------------------------------------*/
7457 /* genDummyRead - generate code for dummy read of volatiles */
7458 /*-----------------------------------------------------------------*/
7460 genDummyRead (iCode * ic)
7465 D(emitcode("; genDummyRead",""));
7468 if (op && IS_SYMOP (op))
7471 aopOp (op, ic, FALSE);
7473 size = AOP_SIZE (op);
7478 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7479 hc08_freeReg (hc08_reg_a);
7483 freeAsmop (op, NULL, ic, TRUE);
7486 if (op && IS_SYMOP (op))
7489 aopOp (op, ic, FALSE);
7491 size = AOP_SIZE (op);
7496 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7497 hc08_freeReg (hc08_reg_a);
7501 freeAsmop (op, NULL, ic, TRUE);
7505 /*-----------------------------------------------------------------*/
7506 /* genCritical - generate code for start of a critical sequence */
7507 /*-----------------------------------------------------------------*/
7509 genCritical (iCode *ic)
7511 D(emitcode("; genCritical",""));
7514 aopOp (IC_RESULT (ic), ic, TRUE);
7516 emitcode ("tpa", "");
7517 hc08_dirtyReg (hc08_reg_a, FALSE);
7518 emitcode ("sei", "");
7521 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7523 pushReg (hc08_reg_a, FALSE);
7525 hc08_freeReg (hc08_reg_a);
7527 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7530 /*-----------------------------------------------------------------*/
7531 /* genEndCritical - generate code for end of a critical sequence */
7532 /*-----------------------------------------------------------------*/
7534 genEndCritical (iCode *ic)
7536 D(emitcode("; genEndCritical",""));
7540 aopOp (IC_RIGHT (ic), ic, FALSE);
7541 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7542 emitcode ("tap", "");
7543 hc08_freeReg (hc08_reg_a);
7544 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7548 pullReg (hc08_reg_a);
7549 emitcode ("tap", "");
7554 /*-----------------------------------------------------------------*/
7555 /* genhc08Code - generate code for HC08 based controllers */
7556 /*-----------------------------------------------------------------*/
7558 genhc08Code (iCode * lic)
7563 lineHead = lineCurr = NULL;
7565 /* print the allocation information */
7566 if (allocInfo && currFunc)
7567 printAllocInfo (currFunc, codeOutFile);
7568 /* if debug information required */
7569 if (options.debug && currFunc)
7571 debugFile->writeFunction(currFunc);
7573 if (IS_STATIC (currFunc->etype))
7574 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7576 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7579 /* stack pointer name */
7580 if (options.useXstack)
7585 hc08_aop_pass[0] = newAsmop (AOP_REG);
7586 hc08_aop_pass[0]->size=1;
7587 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7588 hc08_aop_pass[1] = newAsmop (AOP_REG);
7589 hc08_aop_pass[1]->size=1;
7590 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7591 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7592 hc08_aop_pass[2]->size=1;
7593 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7594 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7595 hc08_aop_pass[3]->size=1;
7596 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7598 for (ic = lic; ic; ic = ic->next)
7601 if (ic->lineno && cln != ic->lineno)
7606 emitcode ("", "C$%s$%d$%d$%d ==.",
7607 FileBaseName (ic->filename), ic->lineno,
7608 ic->level, ic->block);
7611 if (!options.noCcodeInAsm) {
7612 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7613 printCLine(ic->filename, ic->lineno));
7617 if (options.iCodeInAsm) {
7621 for (i=0; i<6; i++) {
7622 sprintf (®sInUse[i],
7623 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7626 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7628 /* if the result is marked as
7629 spilt and rematerializable or code for
7630 this has already been generated then
7632 if (resultRemat (ic) || ic->generated)
7640 for (i=A_IDX;i<=XA_IDX;i++)
7642 reg = hc08_regWithIdx(i);
7644 emitcode("","; %s = %s offset %d", reg->name,
7645 aopName(reg->aop), reg->aopofs);
7648 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7650 sym = OP_SYMBOL (IC_LEFT (ic));
7651 if (sym->accuse == ACCUSE_HX)
7653 hc08_reg_h->isFree = FALSE;
7654 hc08_reg_x->isFree = FALSE;
7656 else if (sym->accuse == ACCUSE_XA)
7658 hc08_reg_a->isFree = FALSE;
7660 hc08_reg_x->isFree = FALSE;
7663 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7665 sym = OP_SYMBOL (IC_RIGHT (ic));
7666 if (sym->accuse == ACCUSE_HX)
7668 hc08_reg_h->isFree = FALSE;
7669 hc08_reg_x->isFree = FALSE;
7671 else if (sym->accuse == ACCUSE_XA)
7673 hc08_reg_a->isFree = FALSE;
7675 hc08_reg_x->isFree = FALSE;
7680 /* depending on the operation */
7700 /* IPOP happens only when trying to restore a
7701 spilt live range, if there is an ifx statement
7702 following this pop then the if statement might
7703 be using some of the registers being popped which
7704 would destory the contents of the register so
7705 we need to check for this condition and handle it */
7707 ic->next->op == IFX &&
7708 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7709 genIfx (ic->next, ic);
7727 genEndFunction (ic);
7743 if (!genPointerGetSetOfs (ic))
7748 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7765 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7769 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7776 /* note these two are xlated by algebraic equivalence
7777 during parsing SDCC.y */
7778 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7779 "got '>=' or '<=' shouldn't have come here");
7783 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7795 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7799 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7803 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7830 case GET_VALUE_AT_ADDRESS:
7831 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7835 if (POINTER_SET (ic))
7836 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7862 addSet (&_G.sendSet, ic);
7865 case DUMMY_READ_VOLATILE:
7874 genEndCritical (ic);
7885 if (!hc08_reg_a->isFree)
7886 D(emitcode("","; forgot to free a"));
7887 if (!hc08_reg_x->isFree)
7888 D(emitcode("","; forgot to free x"));
7889 if (!hc08_reg_h->isFree)
7890 D(emitcode("","; forgot to free h"));
7891 if (!hc08_reg_hx->isFree)
7892 D(emitcode("","; forgot to free hx"));
7893 if (!hc08_reg_xa->isFree)
7894 D(emitcode("","; forgot to free xa"));
7898 /* now we are ready to call the
7899 peep hole optimizer */
7900 if (!options.nopeep)
7901 peepHole (&lineHead);
7903 /* now do the actual printing */
7904 printLine (lineHead, codeOutFile);