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 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 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 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 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 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 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 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 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 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 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 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 // emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1082 // aopName (srcaop), srcofs, aopName (dstaop), dstofs);
1083 // emitcode ("", "; srcaop->type = %d", srcaop->type);
1084 // 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 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 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 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 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 emitcode("","; left size = %d", getDataSize (IC_LEFT(ic)));
3269 emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic)));
3270 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 //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 //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 //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 emitcode("","; checking lic");
4208 /* Make sure the result of the addition is an iCode */
4209 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 emitcode("","; pset=%d, pget=%d",pset,pget);
4220 emitcode("", "; checking pset operandsEqu");
4221 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4224 emitcode("", "; checking pget operandsEqu");
4225 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4228 emitcode("", "; checking IS_SYMOP");
4229 if (!IS_SYMOP (IC_LEFT (ic)))
4232 emitcode("", "; checking !IS_TRUE_SYMOP");
4233 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4236 sym = OP_SYMBOL (IC_LEFT (ic));
4238 emitcode("", "; checking remat");
4244 D(emitcode ("; genPointerGetOfs",""));
4245 aopOp (IC_LEFT(ic), ic, FALSE);
4246 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4247 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4249 aopOp (IC_RIGHT(ic), ic, FALSE);
4250 aopOp (IC_RESULT(lic), lic, FALSE);
4253 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4254 size = AOP_SIZE (IC_RESULT(lic));
4255 derefaop->size = size;
4260 emitcode ("lda", "%s,x",
4261 aopAdrStr (derefaop, offset, TRUE));
4262 hc08_useReg (hc08_reg_a);
4263 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4264 hc08_freeReg (hc08_reg_a);
4268 hc08_freeReg (hc08_reg_hx);
4270 freeAsmop (NULL, derefaop, ic, TRUE);
4271 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4272 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4279 D(emitcode ("; genPointerSetOfs",""));
4280 aopOp (IC_LEFT(ic), ic, FALSE);
4281 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4282 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4284 aopOp (IC_RIGHT(ic), ic, FALSE);
4285 aopOp (IC_RIGHT(lic), lic, FALSE);
4288 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4289 size = AOP_SIZE (IC_RIGHT(lic));
4290 derefaop->size = size;
4295 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4296 emitcode ("sta", "%s,x",
4297 aopAdrStr (derefaop, offset, TRUE));
4298 hc08_freeReg (hc08_reg_a);
4303 hc08_freeReg (hc08_reg_hx);
4305 freeAsmop (NULL, derefaop, ic, TRUE);
4306 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4307 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4316 /*-----------------------------------------------------------------*/
4317 /* hasInc - operand is incremented before any other use */
4318 /*-----------------------------------------------------------------*/
4320 hasInc (operand *op, iCode *ic,int osize)
4322 sym_link *type = operandType(op);
4323 sym_link *retype = getSpec (type);
4324 iCode *lic = ic->next;
4327 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4328 if (!IS_SYMOP(op)) return NULL;
4330 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4331 if (IS_AGGREGATE(type->next)) return NULL;
4332 if (osize != (isize = getSize(type->next))) return NULL;
4335 /* if operand of the form op = op + <sizeof *op> */
4336 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4337 isOperandEqual(IC_RESULT(lic),op) &&
4338 isOperandLiteral(IC_RIGHT(lic)) &&
4339 operandLitValue(IC_RIGHT(lic)) == isize) {
4342 /* if the operand used or deffed */
4343 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4346 /* if GOTO or IFX */
4347 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4353 /*-----------------------------------------------------------------*/
4354 /* genAndOp - for && operation */
4355 /*-----------------------------------------------------------------*/
4357 genAndOp (iCode * ic)
4359 operand *left, *right, *result;
4360 symbol *tlbl, *tlbl0;
4362 D(emitcode ("; genAndOp",""));
4364 /* note here that && operations that are in an
4365 if statement are taken away by backPatchLabels
4366 only those used in arthmetic operations remain */
4367 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4368 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4369 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4371 tlbl = newiTempLabel (NULL);
4372 tlbl0 = newiTempLabel (NULL);
4374 asmopToBool (AOP (left), FALSE);
4375 emitBranch ("beq", tlbl0);
4376 asmopToBool (AOP (right), FALSE);
4377 emitBranch ("beq", tlbl0);
4378 loadRegFromConst (hc08_reg_a,one);
4379 emitBranch ("bra", tlbl);
4381 loadRegFromConst (hc08_reg_a,zero);
4384 hc08_useReg (hc08_reg_a);
4385 hc08_freeReg (hc08_reg_a);
4387 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4389 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4390 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4391 freeAsmop (result, NULL, ic, TRUE);
4395 /*-----------------------------------------------------------------*/
4396 /* genOrOp - for || operation */
4397 /*-----------------------------------------------------------------*/
4399 genOrOp (iCode * ic)
4401 operand *left, *right, *result;
4402 symbol *tlbl, *tlbl0;
4404 D(emitcode ("; genOrOp",""));
4406 /* note here that || operations that are in an
4407 if statement are taken away by backPatchLabels
4408 only those used in arthmetic operations remain */
4409 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4410 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4411 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4413 tlbl = newiTempLabel (NULL);
4414 tlbl0 = newiTempLabel (NULL);
4416 asmopToBool (AOP (left), FALSE);
4417 emitBranch ("bne", tlbl0);
4418 asmopToBool (AOP (right), FALSE);
4419 emitBranch ("bne", tlbl0);
4420 loadRegFromConst (hc08_reg_a,zero);
4421 emitBranch ("bra", tlbl);
4423 loadRegFromConst (hc08_reg_a,one);
4426 hc08_useReg (hc08_reg_a);
4427 hc08_freeReg (hc08_reg_a);
4429 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4432 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4433 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4434 freeAsmop (result, NULL, ic, TRUE);
4437 /*-----------------------------------------------------------------*/
4438 /* isLiteralBit - test if lit == 2^n */
4439 /*-----------------------------------------------------------------*/
4441 isLiteralBit (unsigned long lit)
4443 unsigned long pw[32] =
4444 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4445 0x100L, 0x200L, 0x400L, 0x800L,
4446 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4447 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4448 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4449 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4450 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4453 for (idx = 0; idx < 32; idx++)
4460 /*-----------------------------------------------------------------*/
4461 /* continueIfTrue - */
4462 /*-----------------------------------------------------------------*/
4464 continueIfTrue (iCode * ic)
4467 emitBranch ("jmp", IC_TRUE (ic));
4471 /*-----------------------------------------------------------------*/
4473 /*-----------------------------------------------------------------*/
4475 jumpIfTrue (iCode * ic)
4478 emitBranch ("jmp", IC_FALSE (ic));
4482 /*-----------------------------------------------------------------*/
4483 /* jmpTrueOrFalse - */
4484 /*-----------------------------------------------------------------*/
4486 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4488 // ugly but optimized by peephole
4491 symbol *nlbl = newiTempLabel (NULL);
4492 emitBranch ("bra", nlbl);
4494 emitBranch ("jmp", IC_TRUE (ic));
4499 emitBranch ("jmp", IC_FALSE (ic));
4506 /*-----------------------------------------------------------------*/
4507 /* genAnd - code for and */
4508 /*-----------------------------------------------------------------*/
4510 genAnd (iCode * ic, iCode * ifx)
4512 operand *left, *right, *result;
4513 int size, offset = 0;
4514 unsigned long lit = 0L;
4515 unsigned long litinv;
4521 D(emitcode ("; genAnd",""));
4523 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4524 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4525 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4528 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4530 AOP_TYPE (left), AOP_TYPE (right));
4531 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4533 AOP_SIZE (left), AOP_SIZE (right));
4536 /* if left is a literal & right is not then exchange them */
4537 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4539 operand *tmp = right;
4544 /* if left is accumulator & right is not then exchange them */
4545 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4547 operand *tmp = right;
4553 if (AOP_TYPE (result) == AOP_CRY)
4556 wassertl (ifx, "AOP_CPY result without ifx");
4558 tlbl = newiTempLabel (NULL);
4559 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4563 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4564 if ((AOP_TYPE (right) == AOP_LIT)
4565 && (((lit >> (offset*8)) & 0xff) == 0xff))
4566 emitcode ("tsta","");
4568 accopWithAop ("and", AOP (right), offset);
4569 hc08_freeReg( hc08_reg_a);
4571 emitBranch ("bne", tlbl);
4575 genIfxJump (ifx, "a");
4581 size = AOP_SIZE (result);
4583 if (AOP_TYPE (right) == AOP_LIT)
4585 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4586 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4588 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4589 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4591 int bitpos = isLiteralBit(litinv)-1;
4592 emitcode ("bclr","#%d,%s",bitpos & 7,
4593 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4601 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4602 if ((AOP_TYPE (right) != AOP_LIT)
4603 || (((lit >> (offset*8)) & 0xff) != 0xff))
4604 accopWithAop ("and", AOP (right), offset);
4605 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4606 hc08_freeReg( hc08_reg_a);
4610 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4611 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4612 freeAsmop (result, NULL, ic, TRUE);
4615 /*-----------------------------------------------------------------*/
4616 /* genOr - code for or */
4617 /*-----------------------------------------------------------------*/
4619 genOr (iCode * ic, iCode * ifx)
4621 operand *left, *right, *result;
4622 int size, offset = 0;
4623 unsigned long lit = 0L;
4625 D(emitcode ("; genOr",""));
4627 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4628 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4629 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4632 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4634 AOP_TYPE (left), AOP_TYPE (right));
4635 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4637 AOP_SIZE (left), AOP_SIZE (right));
4640 /* if left is a literal & right is not then exchange them */
4641 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4643 operand *tmp = right;
4648 /* if left is accumulator & right is not then exchange them */
4649 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4651 operand *tmp = right;
4656 if (AOP_TYPE (result) == AOP_CRY)
4659 wassertl (ifx, "AOP_CPY result without ifx");
4661 tlbl = newiTempLabel (NULL);
4662 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4666 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4667 if ((AOP_TYPE (right) == AOP_LIT)
4668 && (((lit >> (offset*8)) & 0xff) == 0))
4669 emitcode ("tsta","");
4671 accopWithAop ("ora", AOP (right), offset);
4672 hc08_freeReg( hc08_reg_a);
4674 emitBranch ("bne", tlbl);
4678 genIfxJump (ifx, "a");
4684 if (AOP_TYPE (right) == AOP_LIT)
4685 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4687 size = AOP_SIZE (result);
4689 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4690 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4691 (AOP_TYPE (left) == AOP_DIR))
4693 int bitpos = isLiteralBit(lit)-1;
4694 emitcode ("bset","#%d,%s",bitpos & 7,
4695 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4702 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4703 accopWithAop ("ora", AOP (right), offset);
4704 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4705 hc08_freeReg( hc08_reg_a);
4710 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4711 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4712 freeAsmop (result, NULL, ic, TRUE);
4715 /*-----------------------------------------------------------------*/
4716 /* genXor - code for xclusive or */
4717 /*-----------------------------------------------------------------*/
4719 genXor (iCode * ic, iCode * ifx)
4721 operand *left, *right, *result;
4722 int size, offset = 0;
4723 unsigned long lit = 0L;
4725 D(emitcode ("; genXor",""));
4727 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4728 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4729 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4732 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4734 AOP_TYPE (left), AOP_TYPE (right));
4735 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4737 AOP_SIZE (left), AOP_SIZE (right));
4740 /* if left is a literal & right is not ||
4741 if left needs acc & right does not */
4742 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4744 operand *tmp = right;
4749 /* if left is accumulator & right is not then exchange them */
4750 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4752 operand *tmp = right;
4757 if (AOP_TYPE (result) == AOP_CRY)
4760 wassertl (ifx, "AOP_CPY result without ifx");
4762 tlbl = newiTempLabel (NULL);
4763 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4767 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4768 if ((AOP_TYPE (right) == AOP_LIT)
4769 && (((lit >> (offset*8)) & 0xff) == 0))
4770 emitcode ("tsta","");
4772 accopWithAop ("eor", AOP (right), offset);
4773 hc08_freeReg( hc08_reg_a);
4775 emitBranch ("bne", tlbl);
4779 genIfxJump (ifx, "a");
4785 if (AOP_TYPE (right) == AOP_LIT)
4786 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4788 size = AOP_SIZE (result);
4792 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4793 accopWithAop ("eor", AOP (right), offset);
4794 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4795 hc08_freeReg( hc08_reg_a);
4799 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4800 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4801 freeAsmop (result, NULL, ic, TRUE);
4805 emitinline (iCode * ic, char *inlin)
4811 symbol *sym, *tempsym;
4820 while (isalnum(*inlin) || (*inlin == '_'))
4824 //printf("Found possible symbol '%s'\n",symname);
4825 tempsym = newSymbol (symname, ic->level);
4826 tempsym->block = ic->block;
4827 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4836 aop = aopForSym (ic, sym, FALSE);
4837 l = aopAdrStr (aop, aop->size - 1, TRUE);
4841 if (!sym->allocreq && !sym->ismyparm)
4843 werror (E_ID_UNDEF, sym->name);
4845 " Add 'volatile' to the variable declaration so that it\n"
4846 " can be referenced within inline assembly");
4848 //printf("Replacing with '%s'\n",l);
4852 if ((2+bp-buffer)>sizeof(buffer))
4861 if ((2+bp-buffer)>sizeof(buffer))
4868 if ((2+bp-buffer)>sizeof(buffer))
4869 fprintf(stderr, "Inline assembly buffer overflow\n");
4871 //printf("%s\n",buffer);
4872 emitcode (buffer,"");
4876 /*-----------------------------------------------------------------*/
4877 /* genInline - write the inline code out */
4878 /*-----------------------------------------------------------------*/
4880 genInline (iCode * ic)
4882 char *buffer, *bp, *bp1;
4884 D(emitcode ("; genInline",""));
4886 _G.inLine += (!options.asmpeep);
4888 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4889 strcpy (buffer, IC_INLINE (ic));
4891 /* emit each line as a code */
4897 /* emitcode (bp1, ""); */
4898 emitinline (ic, bp1);
4917 /* emitcode (bp1, ""); */
4918 emitinline (ic, bp1);
4920 /* emitcode("",buffer); */
4921 _G.inLine -= (!options.asmpeep);
4924 /*-----------------------------------------------------------------*/
4925 /* genRRC - rotate right with carry */
4926 /*-----------------------------------------------------------------*/
4930 operand *left, *result;
4931 int size, offset = 0;
4932 bool needpula = FALSE;
4933 bool resultInA = FALSE;
4936 D(emitcode ("; genRRC",""));
4938 /* rotate right with carry */
4939 left = IC_LEFT (ic);
4940 result = IC_RESULT (ic);
4941 aopOp (left, ic, FALSE);
4942 aopOp (result, ic, FALSE);
4944 if ((AOP_TYPE (result) == AOP_REG)
4945 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4948 size = AOP_SIZE (result);
4952 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4956 rmwWithAop (shift, AOP (result), offset--);
4964 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4965 rmwWithReg (shift, hc08_reg_a);
4966 storeRegToAop (hc08_reg_a, AOP (result), offset--);
4967 hc08_freeReg (hc08_reg_a);
4972 if ((!hc08_reg_a->isFree) || resultInA)
4974 pushReg (hc08_reg_a, TRUE);
4978 /* now we need to put the carry into the
4979 highest order byte of the result */
4980 offset = AOP_SIZE (result) - 1;
4981 emitcode ("clra","");
4982 emitcode ("rora","");
4983 hc08_dirtyReg (hc08_reg_a, FALSE);
4986 emitcode ("ora", "1,s");
4987 emitcode ("ais", "#1");
4988 hc08_dirtyReg (hc08_reg_a, FALSE);
4992 accopWithAop ("ora", AOP (result), offset);
4993 storeRegToAop (hc08_reg_a, AOP (result), offset);
4995 pullOrFreeReg (hc08_reg_a, needpula);
4997 freeAsmop (left, NULL, ic, TRUE);
4998 freeAsmop (result, NULL, ic, TRUE);
5001 /*-----------------------------------------------------------------*/
5002 /* genRLC - generate code for rotate left with carry */
5003 /*-----------------------------------------------------------------*/
5007 operand *left, *result;
5008 int size, offset = 0;
5010 bool resultInA = FALSE;
5011 bool needpula = FALSE;
5013 D(emitcode ("; genRLC",""));
5015 /* rotate right with carry */
5016 left = IC_LEFT (ic);
5017 result = IC_RESULT (ic);
5018 aopOp (left, ic, FALSE);
5019 aopOp (result, ic, FALSE);
5021 if ((AOP_TYPE (result) == AOP_REG)
5022 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5025 size = AOP_SIZE (result);
5029 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5033 rmwWithAop (shift, AOP (result), offset--);
5041 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5042 rmwWithReg (shift, hc08_reg_a);
5043 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5044 hc08_freeReg (hc08_reg_a);
5049 if ((!hc08_reg_a->isFree) || resultInA)
5051 pushReg (hc08_reg_a, TRUE);
5055 /* now we need to put the carry into the
5056 lowest order byte of the result */
5058 emitcode ("clra","");
5059 emitcode ("rola","");
5060 hc08_dirtyReg (hc08_reg_a, FALSE);
5063 emitcode ("ora", "1,s");
5064 emitcode ("ais", "#1");
5065 hc08_dirtyReg (hc08_reg_a, FALSE);
5069 accopWithAop ("ora", AOP (result), offset);
5070 storeRegToAop (hc08_reg_a, AOP (result), offset);
5072 pullOrFreeReg (hc08_reg_a, needpula);
5074 freeAsmop (left, NULL, ic, TRUE);
5075 freeAsmop (result, NULL, ic, TRUE);
5078 /*-----------------------------------------------------------------*/
5079 /* genGetHbit - generates code get highest order bit */
5080 /*-----------------------------------------------------------------*/
5082 genGetHbit (iCode * ic)
5084 operand *left, *result;
5086 D(emitcode ("; genGetHbit",""));
5088 left = IC_LEFT (ic);
5089 result = IC_RESULT (ic);
5090 aopOp (left, ic, FALSE);
5091 aopOp (result, ic, FALSE);
5093 /* get the highest order byte into a */
5094 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5095 emitcode ("rola", "");
5096 emitcode ("clra", "");
5097 emitcode ("rola", "");
5098 hc08_dirtyReg (hc08_reg_a, FALSE);
5099 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5100 hc08_freeReg (hc08_reg_a);
5102 freeAsmop (left, NULL, ic, TRUE);
5103 freeAsmop (result, NULL, ic, TRUE);
5106 /*-----------------------------------------------------------------*/
5107 /* genSwap - generates code to swap nibbles or bytes */
5108 /*-----------------------------------------------------------------*/
5110 genSwap (iCode * ic)
5112 operand *left, *result;
5114 D(emitcode ("; genSwap",""));
5116 left = IC_LEFT (ic);
5117 result = IC_RESULT (ic);
5118 aopOp (left, ic, FALSE);
5119 aopOp (result, ic, FALSE);
5121 switch (AOP_SIZE (left))
5123 case 1: /* swap nibbles in byte */
5124 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5125 emitcode ("nsa", "");
5126 hc08_dirtyReg (hc08_reg_a, FALSE);
5127 storeRegToAop (hc08_reg_a, AOP (result), 0);
5128 hc08_freeReg (hc08_reg_a);
5130 case 2: /* swap bytes in a word */
5131 if (operandsEqu (left, result))
5133 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5134 hc08_useReg (hc08_reg_a);
5135 transferAopAop (AOP (left), 1, AOP (result), 0);
5136 storeRegToAop (hc08_reg_a, AOP (result), 1);
5137 hc08_freeReg (hc08_reg_a);
5141 transferAopAop (AOP (left), 0, AOP (result), 1);
5142 transferAopAop (AOP (left), 1, AOP (result), 0);
5146 wassertl(FALSE, "unsupported SWAP operand size");
5149 freeAsmop (left, NULL, ic, TRUE);
5150 freeAsmop (result, NULL, ic, TRUE);
5154 /*-----------------------------------------------------------------*/
5155 /* AccRol - rotate left accumulator by known count */
5156 /*-----------------------------------------------------------------*/
5158 AccRol (int shCount)
5160 shCount &= 0x0007; // shCount : 0..7
5167 emitcode ("rola", ""); /* 1 cycle */
5170 emitcode ("rola", ""); /* 1 cycle */
5171 emitcode ("rola", ""); /* 1 cycle */
5174 emitcode ("nsa", "");
5175 emitcode ("rora", "");
5178 emitcode ("nsa", ""); /* 3 cycles */
5181 emitcode ("nsa", ""); /* 3 cycles */
5182 emitcode ("rola", ""); /* 1 cycle */
5185 emitcode ("nsa", ""); /* 3 cycles */
5186 emitcode ("rola", ""); /* 1 cycle */
5187 emitcode ("rola", ""); /* 1 cycle */
5190 emitcode ("nsa", ""); /* 3 cycles */
5191 emitcode ("rola", ""); /* 1 cycle */
5192 emitcode ("rola", ""); /* 1 cycle */
5193 emitcode ("rola", ""); /* 1 cycle */
5200 /*-----------------------------------------------------------------*/
5201 /* AccLsh - left shift accumulator by known count */
5202 /*-----------------------------------------------------------------*/
5204 AccLsh (int shCount)
5208 shCount &= 0x0007; // shCount : 0..7
5210 /* Shift counts of 4 and 5 are currently optimized for code size. */
5211 /* Falling through to the unrolled loop would be optimal for code speed. */
5212 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5216 accopWithMisc ("nsa", "");
5217 accopWithMisc ("and", "#0xf0");
5218 /* total: 5 cycles, 3 bytes */
5221 accopWithMisc ("nsa", "");
5222 accopWithMisc ("and", "#0xf0");
5223 accopWithMisc ("lsla", "");
5224 /* total: 6 cycles, 4 bytes */
5227 accopWithMisc ("rora", "");
5228 accopWithMisc ("rora", "");
5229 accopWithMisc ("rora", "");
5230 accopWithMisc ("and", "#0xc0");
5231 /* total: 5 cycles, 5 bytes */
5234 accopWithMisc ("rora", "");
5235 accopWithMisc ("clra", "");
5236 accopWithMisc ("rora", "");
5237 /* total: 3 cycles, 3 bytes */
5241 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5242 /* the fastest (shCount<6) and shortest (shCount<4). */
5243 for (i=0;i<shCount;i++)
5244 accopWithMisc ("lsla", "");
5248 /*-----------------------------------------------------------------*/
5249 /* AccSRsh - signed right shift accumulator by known count */
5250 /*-----------------------------------------------------------------*/
5252 AccSRsh (int shCount)
5256 shCount &= 0x0007; // shCount : 0..7
5260 accopWithMisc ("rola", "");
5261 accopWithMisc ("clra", "");
5262 accopWithMisc ("sbc", zero);
5263 /* total: 4 cycles, 4 bytes */
5267 for (i=0;i<shCount;i++)
5268 accopWithMisc ("asra", "");
5271 /*-----------------------------------------------------------------*/
5272 /* AccRsh - right shift accumulator by known count */
5273 /*-----------------------------------------------------------------*/
5275 AccRsh (int shCount, bool sign)
5285 shCount &= 0x0007; // shCount : 0..7
5287 /* Shift counts of 4 and 5 are currently optimized for code size. */
5288 /* Falling through to the unrolled loop would be optimal for code speed. */
5289 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5293 accopWithMisc ("nsa", "");
5294 accopWithMisc ("and", "#0x0f");
5295 /* total: 5 cycles, 3 bytes */
5298 accopWithMisc ("nsa", "");
5299 accopWithMisc ("and", "#0x0f");
5300 accopWithMisc ("lsra", "");
5301 /* total: 6 cycles, 4 bytes */
5304 accopWithMisc ("rola", "");
5305 accopWithMisc ("rola", "");
5306 accopWithMisc ("rola", "");
5307 accopWithMisc ("and", "#0x03");
5308 /* total: 5 cycles, 5 bytes */
5311 accopWithMisc ("rola", "");
5312 accopWithMisc ("clra", "");
5313 accopWithMisc ("rola", "");
5314 /* total: 3 cycles, 3 bytes */
5318 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5319 /* the fastest (shCount<6) and shortest (shCount<4). */
5320 for (i=0;i<shCount;i++)
5321 accopWithMisc ("lsra", "");
5325 /*-----------------------------------------------------------------*/
5326 /* XAccLsh - left shift register pair XA by known count */
5327 /*-----------------------------------------------------------------*/
5329 XAccLsh (int shCount)
5333 shCount &= 0x000f; // shCount : 0..15
5338 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5339 loadRegFromConst (hc08_reg_a, zero);
5343 /* if we can beat 2n cycles or bytes for some special case, do it here */
5347 /* bytes cycles reg x reg a carry
5348 ** abcd efgh ijkl mnop ?
5349 ** lsrx 1 1 0abc defg ijkl mnop h
5350 ** rora 1 1 0abc defg hijk lmno p
5351 ** tax 1 1 hijk lmno hijk lmno p
5352 ** clra 1 1 hijk lmno 0000 0000 p
5353 ** rora 1 1 hijk lmno p000 0000 0
5354 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5356 rmwWithReg ("lsr", hc08_reg_x);
5357 rmwWithReg ("ror", hc08_reg_a);
5358 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5359 loadRegFromConst (hc08_reg_a, zero);
5360 rmwWithReg ("ror", hc08_reg_a);
5367 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5368 /* the fastest and shortest. */
5369 for (i=0;i<shCount;i++)
5371 rmwWithReg ("lsl", hc08_reg_a);
5372 rmwWithReg ("rol", hc08_reg_x);
5376 /*-----------------------------------------------------------------*/
5377 /* XAccSRsh - signed right shift register pair XA by known count */
5378 /*-----------------------------------------------------------------*/
5380 XAccSRsh (int shCount)
5384 shCount &= 0x000f; // shCount : 0..7
5386 /* if we can beat 2n cycles or bytes for some special case, do it here */
5390 /* bytes cycles reg x reg a carry
5391 ** abcd efgh ijkl mnop ?
5392 ** lslx 1 1 bcde fgh0 ijkl mnop a
5393 ** clra 1 1 bcde fgh0 0000 0000 a
5394 ** rola 1 1 bcde fgh0 0000 000a 0
5395 ** nega 1 1 bcde fgh0 aaaa aaaa a
5396 ** tax 1 1 aaaa aaaa aaaa aaaa a
5397 ** total: 5 cycles, 5 bytes
5399 rmwWithReg ("lsl", hc08_reg_x);
5400 loadRegFromConst (hc08_reg_a, zero);
5401 rmwWithReg ("rol", hc08_reg_a);
5402 rmwWithReg ("neg", hc08_reg_a);
5403 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5413 /* bytes cycles reg x reg a carry
5414 ** abcd efgh ijkl mnop ?
5415 ** txa 1 1 abcd efgh abcd efgh ?
5416 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5417 ** lsla 1 1 abcd efgh ???? ???? a
5418 ** clrx 1 1 0000 0000 ???? ???? a
5419 ** rolx 1 1 0000 000a ???? ???? 0
5420 ** negx 1 1 aaaa aaaa ???? ???? a
5421 ** rora 1 1 aaaa aaaa LSBresult 0
5422 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5424 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5425 AccSRsh (shCount-8);
5426 rmwWithReg ("lsl", hc08_reg_a);
5427 loadRegFromConst (hc08_reg_x, zero);
5428 rmwWithReg ("rol", hc08_reg_x);
5429 rmwWithReg ("neg", hc08_reg_x);
5430 rmwWithReg ("ror", hc08_reg_a);
5437 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5438 /* the fastest and shortest. */
5439 for (i=0;i<shCount;i++)
5441 rmwWithReg ("asr", hc08_reg_x);
5442 rmwWithReg ("ror", hc08_reg_a);
5446 /*-----------------------------------------------------------------*/
5447 /* XAccRsh - right shift register pair XA by known count */
5448 /*-----------------------------------------------------------------*/
5450 XAccRsh (int shCount, bool sign)
5460 shCount &= 0x000f; // shCount : 0..f
5462 /* if we can beat 2n cycles or bytes for some special case, do it here */
5466 /* bytes cycles reg x reg a carry
5467 ** abcd efgh ijkl mnop ?
5468 ** clra 1 1 abcd efgh 0000 0000 a
5469 ** lslx 1 1 bcde fgh0 0000 0000 a
5470 ** rola 1 1 bcde fgh0 0000 000a 0
5471 ** clrx 1 1 0000 0000 0000 000a 0
5472 ** total: 4 cycles, 4 bytes
5474 loadRegFromConst (hc08_reg_x, zero);
5475 rmwWithReg ("lsl", hc08_reg_x);
5476 rmwWithReg ("rol", hc08_reg_a);
5477 loadRegFromConst (hc08_reg_a, zero);
5481 /* bytes cycles reg x reg a carry
5482 ** abcd efgh ijkl mnop ?
5483 ** clra 1 1 abcd efgh 0000 0000 a
5484 ** lslx 1 1 bcde fgh0 0000 0000 a
5485 ** rola 1 1 bcde fgh0 0000 000a 0
5486 ** lslx 1 1 cdef gh00 0000 000a b
5487 ** rola 1 1 cdef gh00 0000 00ab 0
5488 ** clrx 1 1 0000 0000 0000 00ab 0
5489 ** total: 6 cycles, 6 bytes
5491 loadRegFromConst (hc08_reg_x, zero);
5492 rmwWithReg ("lsl", hc08_reg_x);
5493 rmwWithReg ("rol", hc08_reg_a);
5494 rmwWithReg ("lsl", hc08_reg_x);
5495 rmwWithReg ("rol", hc08_reg_a);
5496 loadRegFromConst (hc08_reg_a, zero);
5505 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5506 AccRsh (shCount-8, FALSE);
5507 loadRegFromConst (hc08_reg_x, zero);
5511 /* bytes cycles reg x reg a carry
5512 ** abcd efgh ijkl mnop ?
5513 ** lsla 1 1 abcd efgh jklm nop0 i
5514 ** txa 1 1 abcd efgh abcd efgh i
5515 ** rola 1 1 abcd efgh bcde fghi a
5516 ** clrx 1 1 0000 0000 bcde fghi a
5517 ** rolx 1 1 0000 000a bcde fghi 0
5518 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5520 rmwWithReg ("lsl", hc08_reg_a);
5521 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5522 rmwWithReg ("rol", hc08_reg_a);
5523 loadRegFromConst (hc08_reg_x, zero);
5524 rmwWithReg ("rol", hc08_reg_x);
5527 /* bytes cycles reg x reg a carry
5528 ** abcd efgh ijkl mnop ?
5529 ** lsla 1 1 abcd efgh jklm nop0 i
5530 ** rolx 1 1 bcde fghi jklm nop0 a
5531 ** rola 1 1 bcde fghi klmn op0a j
5532 ** rolx 1 1 cdef ghij klmn op0a b
5533 ** rola 1 1 cdef ghij lmno p0ab k
5534 ** and #3 2 2 cdef ghij 0000 00ab k
5535 ** psha 1 2 cdef ghij 0000 00ab k
5536 ** txa 1 1 cdef ghij cdef ghij k
5537 ** pula 1 2 0000 00ab cdef ghij k
5538 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5544 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5545 /* the fastest and shortest. */
5546 for (i=0;i<shCount;i++)
5548 rmwWithReg ("lsr", hc08_reg_x);
5549 rmwWithReg ("ror", hc08_reg_a);
5556 /*-----------------------------------------------------------------*/
5557 /* shiftR1Left2Result - shift right one byte from left to result */
5558 /*-----------------------------------------------------------------*/
5560 shiftR1Left2Result (operand * left, int offl,
5561 operand * result, int offr,
5562 int shCount, int sign)
5564 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5565 /* shift right accumulator */
5566 AccRsh (shCount, sign);
5567 storeRegToAop (hc08_reg_a, AOP (result), offr);
5571 /*-----------------------------------------------------------------*/
5572 /* shiftL1Left2Result - shift left one byte from left to result */
5573 /*-----------------------------------------------------------------*/
5575 shiftL1Left2Result (operand * left, int offl,
5576 operand * result, int offr, int shCount)
5578 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5579 /* shift left accumulator */
5581 storeRegToAop (hc08_reg_a, AOP (result), offr);
5584 /*-----------------------------------------------------------------*/
5585 /* movLeft2Result - move byte from left to result */
5586 /*-----------------------------------------------------------------*/
5588 movLeft2Result (operand * left, int offl,
5589 operand * result, int offr, int sign)
5591 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5593 transferAopAop (AOP (left), offl, AOP (result), offr);
5598 /*-----------------------------------------------------------------*/
5599 /* shiftL2Left2Result - shift left two bytes from left to result */
5600 /*-----------------------------------------------------------------*/
5602 shiftL2Left2Result (operand * left, int offl,
5603 operand * result, int offr, int shCount)
5606 bool needpula = FALSE;
5607 bool needpulx = FALSE;
5609 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
5610 needpula = pushRegIfUsed (hc08_reg_a);
5613 if (!IS_AOP_XA (AOP (left)))
5614 needpulx = pushRegIfUsed (hc08_reg_x);
5618 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5623 rmwWithReg ("lsr", hc08_reg_x);
5624 rmwWithReg ("ror", hc08_reg_a);
5625 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5626 rmwWithReg ("clr", hc08_reg_a);
5627 rmwWithReg ("ror", hc08_reg_a);
5630 for (i=0; i<shCount; i++)
5632 rmwWithReg ("lsl", hc08_reg_a);
5633 rmwWithReg ("rol", hc08_reg_x);
5636 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5638 pullOrFreeReg (hc08_reg_x, needpulx);
5639 pullOrFreeReg (hc08_reg_a, needpula);
5645 /*-----------------------------------------------------------------*/
5646 /* shiftR2Left2Result - shift right two bytes from left to result */
5647 /*-----------------------------------------------------------------*/
5649 shiftR2Left2Result (operand * left, int offl,
5650 operand * result, int offr,
5651 int shCount, int sign)
5654 bool needpula = FALSE;
5655 bool needpulx = FALSE;
5657 needpula = pushRegIfUsed (hc08_reg_a);
5658 needpulx = pushRegIfUsed (hc08_reg_x);
5660 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5661 for (i=0; i<shCount; i++)
5664 rmwWithReg ("asr", hc08_reg_x);
5666 rmwWithReg ("lsr", hc08_reg_x);
5667 rmwWithReg ("ror", hc08_reg_a);
5669 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5671 pullOrFreeReg (hc08_reg_x, needpulx);
5672 pullOrFreeReg (hc08_reg_a, needpula);
5677 /*-----------------------------------------------------------------*/
5678 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5679 /*-----------------------------------------------------------------*/
5681 shiftLLeftOrResult (operand * left, int offl,
5682 operand * result, int offr, int shCount)
5684 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5685 /* shift left accumulator */
5687 /* or with result */
5688 accopWithAop ("ora", AOP (result), offr);
5689 /* back to result */
5690 storeRegToAop (hc08_reg_a, AOP (result), offr);
5691 hc08_freeReg (hc08_reg_a);
5695 /*-----------------------------------------------------------------*/
5696 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5697 /*-----------------------------------------------------------------*/
5699 shiftRLeftOrResult (operand * left, int offl,
5700 operand * result, int offr, int shCount)
5702 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5703 /* shift left accumulator */
5704 AccRsh (shCount, FALSE);
5705 /* or with result */
5706 accopWithAop ("ora", AOP (result), offr);
5707 /* back to result */
5708 storeRegToAop (hc08_reg_a, AOP (result), offr);
5709 hc08_freeReg (hc08_reg_a);
5712 /*-----------------------------------------------------------------*/
5713 /* genlshOne - left shift a one byte quantity by known count */
5714 /*-----------------------------------------------------------------*/
5716 genlshOne (operand * result, operand * left, int shCount)
5718 D(emitcode ("; genlshOne",""));
5720 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5723 /*-----------------------------------------------------------------*/
5724 /* genlshTwo - left shift two bytes by known amount != 0 */
5725 /*-----------------------------------------------------------------*/
5727 genlshTwo (operand * result, operand * left, int shCount)
5731 D(emitcode ("; genlshTwo",""));
5734 size = getDataSize (result);
5736 /* if shCount >= 8 */
5743 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5745 storeRegToAop (hc08_reg_a, AOP (result), 1);
5747 storeConstToAop(zero, AOP (result), LSB);
5750 /* 1 <= shCount <= 7 */
5753 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5755 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5759 /*-----------------------------------------------------------------*/
5760 /* shiftLLong - shift left one long from left to result */
5761 /* offl = LSB or MSB16 */
5762 /*-----------------------------------------------------------------*/
5764 shiftLLong (operand * left, operand * result, int offr)
5767 // int size = AOP_SIZE (result);
5769 bool needpula = FALSE;
5770 bool needpulx = FALSE;
5772 needpula = pushRegIfUsed (hc08_reg_a);
5773 needpulx = pushRegIfUsed (hc08_reg_x);
5775 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5776 rmwWithReg ("lsl", hc08_reg_a);
5777 rmwWithReg ("rol", hc08_reg_x);
5778 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5782 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5783 rmwWithReg ("rol", hc08_reg_a);
5784 rmwWithReg ("rol", hc08_reg_x);
5785 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5787 else if (offr==MSB16)
5789 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5790 rmwWithReg ("rol", hc08_reg_a);
5791 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5794 pullOrFreeReg (hc08_reg_x, needpulx);
5795 pullOrFreeReg (hc08_reg_a, needpula);
5798 /*-----------------------------------------------------------------*/
5799 /* genlshFour - shift four byte by a known amount != 0 */
5800 /*-----------------------------------------------------------------*/
5802 genlshFour (operand * result, operand * left, int shCount)
5806 D(emitcode ("; genlshFour",""));
5808 size = AOP_SIZE (result);
5810 /* TODO: deal with the &result == &left case */
5812 /* if shifting more that 3 bytes */
5817 /* lowest order of left goes to the highest
5818 order of the destination */
5819 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5821 movLeft2Result (left, LSB, result, MSB32, 0);
5822 storeConstToAop (zero, AOP (result), LSB);
5823 storeConstToAop (zero, AOP (result), MSB16);
5824 storeConstToAop (zero, AOP (result), MSB24);
5828 /* more than two bytes */
5829 else if (shCount >= 16)
5831 /* lower order two bytes goes to higher order two bytes */
5833 /* if some more remaining */
5835 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5838 movLeft2Result (left, MSB16, result, MSB32, 0);
5839 movLeft2Result (left, LSB, result, MSB24, 0);
5841 storeConstToAop (zero, AOP (result), LSB);
5842 storeConstToAop (zero, AOP (result), MSB16);
5846 /* if more than 1 byte */
5847 else if (shCount >= 8)
5849 /* lower order three bytes goes to higher order three bytes */
5854 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5856 movLeft2Result (left, LSB, result, MSB16, 0);
5862 movLeft2Result (left, MSB24, result, MSB32, 0);
5863 movLeft2Result (left, MSB16, result, MSB24, 0);
5864 movLeft2Result (left, LSB, result, MSB16, 0);
5865 storeConstToAop (zero, AOP (result), LSB);
5867 else if (shCount == 1)
5868 shiftLLong (left, result, MSB16);
5871 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5872 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5873 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5874 storeConstToAop (zero, AOP (result), LSB);
5879 /* 1 <= shCount <= 7 */
5880 else if (shCount <= 2)
5882 shiftLLong (left, result, LSB);
5884 shiftLLong (result, result, LSB);
5886 /* 3 <= shCount <= 7, optimize */
5889 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5890 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5891 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5895 /*-----------------------------------------------------------------*/
5896 /* genLeftShiftLiteral - left shifting by known count */
5897 /*-----------------------------------------------------------------*/
5899 genLeftShiftLiteral (operand * left,
5904 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5907 D(emitcode ("; genLeftShiftLiteral",""));
5909 freeAsmop (right, NULL, ic, TRUE);
5911 aopOp (left, ic, FALSE);
5912 aopOp (result, ic, FALSE);
5914 // size = getSize (operandType (result));
5915 size = AOP_SIZE (result);
5918 emitcode ("; shift left ", "result %d, left %d", size,
5925 transferAopAop( AOP(left), size, AOP(result), size);
5927 else if (shCount >= (size * 8))
5930 storeConstToAop (zero, AOP (result), size);
5937 genlshOne (result, left, shCount);
5941 genlshTwo (result, left, shCount);
5945 genlshFour (result, left, shCount);
5948 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5949 "*** ack! mystery literal shift!\n");
5953 freeAsmop (left, NULL, ic, TRUE);
5954 freeAsmop (result, NULL, ic, TRUE);
5957 /*-----------------------------------------------------------------*/
5958 /* genLeftShift - generates code for left shifting */
5959 /*-----------------------------------------------------------------*/
5961 genLeftShift (iCode * ic)
5963 operand *left, *right, *result;
5965 symbol *tlbl, *tlbl1;
5970 D(emitcode ("; genLeftShift",""));
5972 right = IC_RIGHT (ic);
5973 left = IC_LEFT (ic);
5974 result = IC_RESULT (ic);
5976 aopOp (right, ic, FALSE);
5978 /* if the shift count is known then do it
5979 as efficiently as possible */
5980 if (AOP_TYPE (right) == AOP_LIT)
5982 genLeftShiftLiteral (left, right, result, ic);
5986 /* shift count is unknown then we have to form
5987 a loop get the loop count in A : Note: we take
5988 only the lower order byte since shifting
5989 more that 32 bits make no sense anyway, ( the
5990 largest size of an object can be only 32 bits ) */
5992 aopOp (left, ic, FALSE);
5993 aopOp (result, ic, FALSE);
5995 /* now move the left to the result if they are not the
5997 if (!sameRegs (AOP (left), AOP (result)))
6000 size = AOP_SIZE (result);
6004 transferAopAop (AOP (left), offset, AOP (result), offset);
6008 freeAsmop (left, NULL, ic, TRUE);
6010 tlbl = newiTempLabel (NULL);
6011 size = AOP_SIZE (result);
6013 tlbl1 = newiTempLabel (NULL);
6017 loadRegFromAop (reg, AOP (right), 0);
6018 freeAsmop (right, NULL, ic, TRUE);
6019 emitBranch ("beq", tlbl1);
6023 for (offset=0;offset<size;offset++)
6025 rmwWithAop (shift, AOP (result), offset);
6028 rmwWithReg ("dec", reg);
6029 emitBranch ("bne", tlbl);
6033 freeAsmop (result, NULL, ic, TRUE);
6036 /*-----------------------------------------------------------------*/
6037 /* genrshOne - right shift a one byte quantity by known count */
6038 /*-----------------------------------------------------------------*/
6040 genrshOne (operand * result, operand * left,
6041 int shCount, int sign)
6043 D(emitcode ("; genrshOne",""));
6045 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6046 AccRsh (shCount, sign);
6047 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6050 /*-----------------------------------------------------------------*/
6051 /* genrshTwo - right shift two bytes by known amount != 0 */
6052 /*-----------------------------------------------------------------*/
6054 genrshTwo (operand * result, operand * left,
6055 int shCount, int sign)
6057 D(emitcode ("; genrshTwo",""));
6059 /* if shCount >= 8 */
6062 if (shCount || sign)
6064 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6065 AccRsh (shCount-8, sign);
6066 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6070 transferAopAop (AOP (left), 1, AOP (result), 0);
6071 storeConstToAop (zero, AOP (result), 1);
6075 /* 1 <= shCount <= 7 */
6078 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6079 XAccRsh (shCount, sign);
6080 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6084 /*-----------------------------------------------------------------*/
6085 /* shiftRLong - shift right one long from left to result */
6086 /* offl = LSB or MSB16 */
6087 /*-----------------------------------------------------------------*/
6089 shiftRLong (operand * left, int offl,
6090 operand * result, int sign)
6093 // int size = AOP_SIZE (result);
6095 bool needpula = FALSE;
6096 bool needpulx = FALSE;
6098 needpula = pushRegIfUsed (hc08_reg_a);
6099 needpulx = pushRegIfUsed (hc08_reg_x);
6103 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6105 rmwWithReg ("asr", hc08_reg_x);
6107 rmwWithReg ("lsr", hc08_reg_x);
6108 rmwWithReg ("rol", hc08_reg_a);
6109 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6111 else if (offl==MSB16)
6113 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6115 rmwWithReg ("asr", hc08_reg_a);
6117 rmwWithReg ("lsr", hc08_reg_a);
6118 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6121 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6122 rmwWithReg ("ror", hc08_reg_x);
6123 rmwWithReg ("ror", hc08_reg_a);
6124 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6127 pullOrFreeReg (hc08_reg_x, needpulx);
6128 pullOrFreeReg (hc08_reg_a, needpula);
6131 /*-----------------------------------------------------------------*/
6132 /* genrshFour - shift four byte by a known amount != 0 */
6133 /*-----------------------------------------------------------------*/
6135 genrshFour (operand * result, operand * left,
6136 int shCount, int sign)
6138 /* TODO: handle cases where left == result */
6140 D(emitcode ("; genrshFour",""));
6142 /* if shifting more that 3 bytes */
6145 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6146 AccRsh (shCount-24, sign);
6147 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6150 else if (shCount >= 16)
6152 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6153 XAccRsh (shCount-16, sign);
6154 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6157 else if (shCount >= 8)
6160 shiftRLong (left, MSB16, result, sign);
6161 else if (shCount == 8)
6163 transferAopAop (AOP (left), 1, AOP (result), 0);
6164 transferAopAop (AOP (left), 2, AOP (result), 1);
6165 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6166 storeRegToAop (hc08_reg_a, AOP (result), 2);
6167 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6169 else if (shCount == 9)
6171 shiftRLong (left, MSB16, result, sign);
6175 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6176 XAccRsh (shCount-8, FALSE);
6177 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6178 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6179 loadRegFromConst (hc08_reg_a, zero);
6180 XAccRsh (shCount-8, sign);
6181 accopWithAop ("ora", AOP (result), 1);
6182 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6186 { /* 1 <= shCount <= 7 */
6189 shiftRLong (left, LSB, result, sign);
6193 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6194 XAccRsh (shCount, FALSE);
6195 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6196 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6198 accopWithAop ("ora", AOP (result), 1);
6199 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6200 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6201 XAccRsh (shCount, sign);
6202 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6207 /*-----------------------------------------------------------------*/
6208 /* genRightShiftLiteral - right shifting by known count */
6209 /*-----------------------------------------------------------------*/
6211 genRightShiftLiteral (operand * left,
6217 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6220 D(emitcode ("; genRightShiftLiteral",""));
6222 freeAsmop (right, NULL, ic, TRUE);
6224 aopOp (left, ic, FALSE);
6225 aopOp (result, ic, FALSE);
6228 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6232 size = getDataSize (left);
6233 /* test the LEFT size !!! */
6235 /* I suppose that the left size >= result size */
6238 size = getDataSize (result);
6240 transferAopAop (AOP (left), size, AOP(result), size);
6242 else if (shCount >= (size * 8))
6245 /* get sign in acc.7 */
6246 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6248 addSign (result, LSB, sign);
6255 genrshOne (result, left, shCount, sign);
6259 genrshTwo (result, left, shCount, sign);
6263 genrshFour (result, left, shCount, sign);
6269 freeAsmop (left, NULL, ic, TRUE);
6270 freeAsmop (result, NULL, ic, TRUE);
6274 /*-----------------------------------------------------------------*/
6275 /* genRightShift - generate code for right shifting */
6276 /*-----------------------------------------------------------------*/
6278 genRightShift (iCode * ic)
6280 operand *right, *left, *result;
6284 symbol *tlbl, *tlbl1;
6288 D(emitcode ("; genRightShift",""));
6290 /* if signed then we do it the hard way preserve the
6291 sign bit moving it inwards */
6292 retype = getSpec (operandType (IC_RESULT (ic)));
6293 sign = !SPEC_USIGN (retype);
6295 /* signed & unsigned types are treated the same : i.e. the
6296 signed is NOT propagated inwards : quoting from the
6297 ANSI - standard : "for E1 >> E2, is equivalent to division
6298 by 2**E2 if unsigned or if it has a non-negative value,
6299 otherwise the result is implementation defined ", MY definition
6300 is that the sign does not get propagated */
6302 right = IC_RIGHT (ic);
6303 left = IC_LEFT (ic);
6304 result = IC_RESULT (ic);
6306 aopOp (right, ic, FALSE);
6308 /* if the shift count is known then do it
6309 as efficiently as possible */
6310 if (AOP_TYPE (right) == AOP_LIT)
6312 genRightShiftLiteral (left, right, result, ic, sign);
6316 /* shift count is unknown then we have to form
6317 a loop get the loop count in X : Note: we take
6318 only the lower order byte since shifting
6319 more that 32 bits make no sense anyway, ( the
6320 largest size of an object can be only 32 bits ) */
6322 aopOp (left, ic, FALSE);
6323 aopOp (result, ic, FALSE);
6325 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6326 AOP (result) = forceStackedAop (AOP (result));
6328 size = AOP_SIZE (result);
6332 transferAopAop (AOP (left), offset, AOP (result), offset);
6336 tlbl = newiTempLabel (NULL);
6337 size = AOP_SIZE (result);
6339 tlbl1 = newiTempLabel (NULL);
6341 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6342 emitcode ("tstx", "");
6343 emitcode ("beq", "%05d$", tlbl1->key + 100);
6344 emitcode ("", "%05d$:", tlbl->key + 100);
6345 shift= sign ? "asr" : "lsr";
6346 for (offset=size-1;offset>=0;offset--)
6348 rmwWithAop (shift, AOP (result), offset);
6351 rmwWithReg ("dec", hc08_reg_x);
6352 emitcode ("bne","%05d$", tlbl->key + 100);
6353 emitcode ("", "%05d$:", tlbl1->key + 100);
6355 freeAsmop (result, NULL, ic, TRUE);
6356 freeAsmop (left, NULL, ic, TRUE);
6357 freeAsmop (right, NULL, ic, TRUE);
6360 /*-----------------------------------------------------------------*/
6361 /* genUnpackBits - generates code for unpacking bits */
6362 /*-----------------------------------------------------------------*/
6364 genUnpackBits (operand * result)
6366 int offset = 0; /* result byte offset */
6367 int rsize; /* result size */
6368 int rlen = 0; /* remaining bitfield length */
6369 sym_link *etype; /* bitfield type information */
6370 int blen; /* bitfield length */
6371 int bstr; /* bitfield starting bit within byte */
6373 D(emitcode ("; genUnpackBits",""));
6375 etype = getSpec (operandType (result));
6376 rsize = getSize (operandType (result));
6377 blen = SPEC_BLEN (etype);
6378 bstr = SPEC_BSTR (etype);
6380 /* If the bitfield length is less than a byte */
6383 emitcode ("lda", ",x");
6384 hc08_dirtyReg (hc08_reg_a, FALSE);
6385 AccRsh (bstr, FALSE);
6386 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6387 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6391 /* Bit field did not fit in a byte. Copy all
6392 but the partial byte at the end. */
6393 for (rlen=blen;rlen>=8;rlen-=8)
6395 emitcode ("lda", ",x");
6396 hc08_dirtyReg (hc08_reg_a, FALSE);
6397 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6399 emitcode ("aix", "#1");
6402 /* Handle the partial byte at the end */
6405 emitcode ("lda", ",x");
6406 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6407 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6415 storeConstToAop (zero, AOP (result), offset++);
6420 /*-----------------------------------------------------------------*/
6421 /* genDataPointerGet - generates code when ptr offset is known */
6422 /*-----------------------------------------------------------------*/
6424 genDataPointerGet (operand * left,
6428 int size, offset = 0;
6431 D(emitcode ("; genDataPointerGet",""));
6433 aopOp (result, ic, TRUE);
6434 size = AOP_SIZE (result);
6436 derefaop = aopDerefAop (AOP (left));
6437 freeAsmop (left, NULL, ic, TRUE);
6438 derefaop->size = size;
6442 transferAopAop(derefaop, offset, AOP (result), offset);
6446 freeAsmop (NULL, derefaop, ic, TRUE);
6447 freeAsmop (result, NULL, ic, TRUE);
6451 /*-----------------------------------------------------------------*/
6452 /* genNearPointerGet - emitcode for near pointer fetch */
6453 /*-----------------------------------------------------------------*/
6455 genNearPointerGet (operand * left,
6461 sym_link *retype = getSpec (operandType (result));
6463 D(emitcode ("; genNearPointerGet",""));
6465 aopOp (left, ic, FALSE);
6467 /* if left is rematerialisable and
6468 result is not bit variable type and
6469 the left is pointer to data space i.e
6470 lower 128 bytes of space */
6471 if ((AOP_TYPE (left) == AOP_IMMD)
6472 || (AOP_TYPE (left) == AOP_LIT)
6473 /* !IS_BITVAR (retype) */
6474 /* && DCL_TYPE (ltype) == POINTER */ )
6476 genDataPointerGet (left, result, ic);
6480 /* if the operand is already in hx
6481 then we do nothing else we move the value to hx */
6482 if (AOP_TYPE (left) != AOP_STR)
6484 /* if this is remateriazable */
6485 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6486 loadRegFromConst (hc08_reg_h, zero);
6489 /* so hx now contains the address */
6490 aopOp (result, ic, FALSE);
6492 /* if bit then unpack */
6493 if (IS_BITVAR (retype))
6494 genUnpackBits (result);
6497 size = AOP_SIZE (result);
6502 accopWithMisc ("lda", ",x");
6505 rmwWithReg ("inc", hc08_reg_x);
6507 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6508 hc08_freeReg (hc08_reg_a);
6512 freeAsmop (left, NULL, ic, TRUE);
6513 freeAsmop (result, NULL, ic, TRUE);
6515 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6516 aopOp (IC_RESULT (pi), pi, FALSE);
6517 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6518 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6522 hc08_freeReg (hc08_reg_hx);
6526 /*-----------------------------------------------------------------*/
6527 /* genFarPointerGet - get value from far space */
6528 /*-----------------------------------------------------------------*/
6530 genFarPointerGet (operand * left,
6531 operand * result, iCode * ic, iCode * pi)
6534 sym_link *retype = getSpec (operandType (result));
6536 D(emitcode ("; genFarPointerGet",""));
6538 aopOp (left, ic, FALSE);
6540 /* if left is rematerialisable and
6541 result is not bit variable type and
6542 the left is pointer to data space i.e
6543 lower 128 bytes of space */
6544 if (AOP_TYPE (left) == AOP_IMMD &&
6546 /* && DCL_TYPE (ltype) == POINTER */ )
6548 genDataPointerGet (left, result, ic);
6552 /* if the operand is already in hx
6553 then we do nothing else we move the value to hx */
6554 if (AOP_TYPE (left) != AOP_STR)
6556 /* if this is remateriazable */
6557 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6560 /* so hx now contains the address */
6561 aopOp (result, ic, FALSE);
6563 /* if bit then unpack */
6564 if (IS_BITVAR (retype))
6565 genUnpackBits (result);
6568 size = AOP_SIZE (result);
6573 accopWithMisc ("lda", ",x");
6576 emitcode ("aix", "#1");
6577 hc08_dirtyReg (hc08_reg_hx, FALSE);
6579 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6580 hc08_freeReg (hc08_reg_a);
6584 freeAsmop (left, NULL, ic, TRUE);
6585 freeAsmop (result, NULL, ic, TRUE);
6587 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6588 aopOp (IC_RESULT (pi), pi, FALSE);
6589 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6590 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6594 hc08_freeReg (hc08_reg_hx);
6600 /*-----------------------------------------------------------------*/
6601 /* genPointerGet - generate code for pointer get */
6602 /*-----------------------------------------------------------------*/
6604 genPointerGet (iCode * ic, iCode *pi)
6606 operand *left, *result;
6607 sym_link *type, *etype;
6610 D(emitcode ("; genPointerGet",""));
6612 left = IC_LEFT (ic);
6613 result = IC_RESULT (ic);
6615 /* depending on the type of pointer we need to
6616 move it to the correct pointer register */
6617 type = operandType (left);
6618 etype = getSpec (type);
6619 /* if left is of type of pointer then it is simple */
6620 if (IS_PTR (type) && !IS_FUNC (type->next))
6621 p_type = DCL_TYPE (type);
6624 /* we have to go by the storage class */
6625 p_type = PTR_TYPE (SPEC_OCLS (etype));
6628 /* special case when cast remat */
6629 if (p_type == GPOINTER && IS_SYMOP(left) && OP_SYMBOL(left)->remat &&
6630 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6631 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6632 type = operandType (left);
6633 p_type = DCL_TYPE (type);
6635 /* now that we have the pointer type we assign
6636 the pointer values */
6643 genNearPointerGet (left, result, ic, pi);
6649 genFarPointerGet (left, result, ic, pi);
6656 /*-----------------------------------------------------------------*/
6657 /* genPackBits - generates code for packed bit storage */
6658 /*-----------------------------------------------------------------*/
6660 genPackBits (sym_link * etype,
6663 int offset = 0; /* source byte offset */
6664 int rlen = 0; /* remaining bitfield length */
6665 int blen; /* bitfield length */
6666 int bstr; /* bitfield starting bit within byte */
6667 int litval; /* source literal value (if AOP_LIT) */
6668 unsigned char mask; /* bitmask within current byte */
6670 D(emitcode ("; genPackBits",""));
6672 blen = SPEC_BLEN (etype);
6673 bstr = SPEC_BSTR (etype);
6675 /* If the bitfield length is less than a byte */
6678 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6679 (unsigned char) (0xFF >> (8 - bstr)));
6681 if (AOP_TYPE (right) == AOP_LIT)
6683 /* Case with a bitfield length <8 and literal source
6685 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6687 litval &= (~mask) & 0xff;
6689 emitcode ("lda", ",x");
6690 if ((mask|litval)!=0xff)
6691 emitcode ("and","#0x%02x", mask);
6693 emitcode ("ora","#0x%02x", litval);
6694 hc08_dirtyReg (hc08_reg_a, FALSE);
6695 emitcode ("sta", ",x");
6697 hc08_freeReg (hc08_reg_a);
6701 /* Case with a bitfield length < 8 and arbitrary source
6703 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6704 /* shift and mask source value */
6706 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6707 hc08_dirtyReg (hc08_reg_a, FALSE);
6708 pushReg (hc08_reg_a, TRUE);
6710 emitcode ("lda", ",x");
6711 emitcode ("and", "#0x%02x", mask);
6712 emitcode ("ora", "1,s");
6713 emitcode ("sta", ",x");
6714 pullReg (hc08_reg_a);
6716 hc08_freeReg (hc08_reg_a);
6720 /* Bit length is greater than 7 bits. In this case, copy */
6721 /* all except the partial byte at the end */
6722 for (rlen=blen;rlen>=8;rlen-=8)
6724 if (AOP (right)->type == AOP_DIR)
6726 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6730 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6731 emitcode ("sta", "%d,x", offset);
6736 /* If there was a partial byte at the end */
6739 mask = (((unsigned char) -1 << rlen) & 0xff);
6741 if (AOP_TYPE (right) == AOP_LIT)
6743 /* Case with partial byte and literal source
6745 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6746 litval >>= (blen-rlen);
6747 litval &= (~mask) & 0xff;
6748 emitcode ("lda", "%d,x", offset);
6749 hc08_dirtyReg (hc08_reg_a, FALSE);
6750 if ((mask|litval)!=0xff)
6751 emitcode ("and","#0x%02x", mask);
6753 emitcode ("ora","#0x%02x", litval);
6754 emitcode ("sta", "%d,x", offset);
6755 hc08_dirtyReg (hc08_reg_a, FALSE);
6756 hc08_freeReg (hc08_reg_a);
6760 /* Case with partial byte and arbitrary source
6762 loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6763 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6764 hc08_dirtyReg (hc08_reg_a, FALSE);
6765 pushReg (hc08_reg_a, TRUE);
6767 emitcode ("lda", ",x");
6768 emitcode ("and", "#0x%02x", mask);
6769 emitcode ("ora", "1,s");
6770 emitcode ("sta", ",x");
6771 pullReg (hc08_reg_a);
6774 hc08_freeReg (hc08_reg_a);
6777 /*-----------------------------------------------------------------*/
6778 /* genDataPointerSet - remat pointer to data space */
6779 /*-----------------------------------------------------------------*/
6781 genDataPointerSet (operand * right,
6785 int size, offset = 0;
6788 D(emitcode ("; genDataPointerSet",""));
6790 aopOp (right, ic, FALSE);
6791 size = AOP_SIZE (right);
6793 derefaop = aopDerefAop (AOP (result));
6794 freeAsmop (result, NULL, ic, TRUE);
6795 derefaop->size = size;
6799 transferAopAop (AOP (right), offset, derefaop, offset);
6803 freeAsmop (right, NULL, ic, TRUE);
6804 freeAsmop (NULL, derefaop, ic, TRUE);
6808 /*-----------------------------------------------------------------*/
6809 /* genNearPointerSet - emitcode for near pointer put */
6810 /*-----------------------------------------------------------------*/
6812 genNearPointerSet (operand * right,
6818 sym_link *retype = getSpec (operandType (right));
6819 sym_link *letype = getSpec (operandType (result));
6821 D(emitcode ("; genNearPointerSet",""));
6823 aopOp (result, ic, FALSE);
6825 /* if the result is rematerializable &
6826 in data space & not a bit variable */
6827 if (AOP_TYPE (result) == AOP_IMMD &&
6828 /* DCL_TYPE (ptype) == POINTER && */
6829 !IS_BITVAR (retype) &&
6830 !IS_BITVAR (letype))
6832 genDataPointerSet (right, result, ic);
6836 /* if the operand is already in hx
6837 then we do nothing else we move the value to hx */
6838 if (AOP_TYPE (result) != AOP_STR)
6840 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6841 loadRegFromConst (hc08_reg_h, zero);
6843 /* so hx now contains the address */
6844 aopOp (right, ic, FALSE);
6846 /* if bit then unpack */
6847 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6848 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6851 size = AOP_SIZE (right);
6856 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6857 accopWithMisc ("sta", ",x");
6860 rmwWithReg ("inc", hc08_reg_x);
6862 hc08_freeReg (hc08_reg_a);
6866 freeAsmop (result, NULL, ic, TRUE);
6867 freeAsmop (right, NULL, ic, TRUE);
6869 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6870 aopOp (IC_RESULT (pi), pi, FALSE);
6871 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6872 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6876 hc08_freeReg (hc08_reg_hx);
6881 /*-----------------------------------------------------------------*/
6882 /* genFarPointerSet - set value from far space */
6883 /*-----------------------------------------------------------------*/
6885 genFarPointerSet (operand * right,
6886 operand * result, iCode * ic, iCode * pi)
6889 sym_link *retype = getSpec (operandType (right));
6890 sym_link *letype = getSpec (operandType (result));
6892 D(emitcode ("; genFarPointerSet",""));
6894 aopOp (result, ic, FALSE);
6896 /* if the result is rematerializable &
6897 in data space & not a bit variable */
6898 if (AOP_TYPE (result) == AOP_IMMD &&
6899 /* DCL_TYPE (ptype) == POINTER && */
6900 !IS_BITVAR (retype) &&
6901 !IS_BITVAR (letype))
6903 genDataPointerSet (right, result, ic);
6907 /* if the operand is already in hx
6908 then we do nothing else we move the value to hx */
6909 if (AOP_TYPE (result) != AOP_STR)
6911 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6913 /* so hx now contains the address */
6914 aopOp (right, ic, FALSE);
6916 /* if bit then unpack */
6917 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6918 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6921 size = AOP_SIZE (right);
6926 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6927 accopWithMisc ("sta", ",x");
6930 emitcode ("aix", "#1");
6932 hc08_freeReg (hc08_reg_a);
6936 freeAsmop (result, NULL, ic, TRUE);
6937 freeAsmop (right, NULL, ic, TRUE);
6939 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6940 aopOp (IC_RESULT (pi), pi, FALSE);
6941 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6942 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6946 hc08_freeReg (hc08_reg_hx);
6952 /*-----------------------------------------------------------------*/
6953 /* genPointerSet - stores the value into a pointer location */
6954 /*-----------------------------------------------------------------*/
6956 genPointerSet (iCode * ic, iCode *pi)
6958 operand *right, *result;
6959 sym_link *type, *etype;
6962 D(emitcode ("; genPointerSet",""));
6964 right = IC_RIGHT (ic);
6965 result = IC_RESULT (ic);
6967 /* depending on the type of pointer we need to
6968 move it to the correct pointer register */
6969 type = operandType (result);
6970 etype = getSpec (type);
6971 /* if left is of type of pointer then it is simple */
6972 if (IS_PTR (type) && !IS_FUNC (type->next))
6974 p_type = DCL_TYPE (type);
6978 /* we have to go by the storage class */
6979 p_type = PTR_TYPE (SPEC_OCLS (etype));
6982 /* special case when cast remat */
6983 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
6984 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
6985 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
6986 type = operandType (result);
6987 p_type = DCL_TYPE (type);
6989 /* now that we have the pointer type we assign
6990 the pointer values */
6997 genNearPointerSet (right, result, ic, pi);
7003 genFarPointerSet (right, result, ic, pi);
7007 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7008 "genPointerSet: illegal pointer type");
7013 /*-----------------------------------------------------------------*/
7014 /* genIfx - generate code for Ifx statement */
7015 /*-----------------------------------------------------------------*/
7017 genIfx (iCode * ic, iCode * popIc)
7019 operand *cond = IC_COND (ic);
7022 D(emitcode ("; genIfx",""));
7024 aopOp (cond, ic, FALSE);
7026 /* get the value into acc */
7027 if (AOP_TYPE (cond) != AOP_CRY)
7028 asmopToBool (AOP (cond), FALSE);
7031 /* the result is now in the accumulator */
7032 freeAsmop (cond, NULL, ic, TRUE);
7034 /* if there was something to be popped then do it */
7038 /* if the condition is a bit variable */
7039 if (isbit && IS_ITEMP (cond) &&
7041 genIfxJump (ic, SPIL_LOC (cond)->rname);
7042 else if (isbit && !IS_ITEMP (cond))
7043 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7045 genIfxJump (ic, "a");
7050 /*-----------------------------------------------------------------*/
7051 /* genAddrOf - generates code for address of */
7052 /*-----------------------------------------------------------------*/
7054 genAddrOf (iCode * ic)
7056 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7059 D(emitcode ("; genAddrOf",""));
7061 aopOp (IC_RESULT (ic), ic, FALSE);
7063 /* if the operand is on the stack then we
7064 need to get the stack offset of this
7068 /* if it has an offset then we need to compute
7070 hc08_useReg (hc08_reg_hx);
7071 emitcode ("tsx", "");
7072 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7073 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7074 hc08_freeReg (hc08_reg_hx);
7079 /* object not on stack then we need the name */
7080 size = AOP_SIZE (IC_RESULT (ic));
7085 char s[SDCC_NAME_MAX+10];
7088 sprintf (s, "#%s", sym->rname);
7091 sprintf (s, "#>%s", sym->rname);
7094 sprintf (s, "#(%s >> %d)",
7098 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7102 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7106 /*-----------------------------------------------------------------*/
7107 /* genAssign - generate code for assignment */
7108 /*-----------------------------------------------------------------*/
7110 genAssign (iCode * ic)
7112 operand *result, *right;
7114 // unsigned long lit = 0L;
7116 D(emitcode("; genAssign",""));
7118 result = IC_RESULT (ic);
7119 right = IC_RIGHT (ic);
7121 /* if they are the same */
7122 if (operandsEqu (result, right)) {
7126 aopOp (right, ic, FALSE);
7127 aopOp (result, ic, TRUE);
7129 /* if they are the same registers */
7130 if (sameRegs (AOP (right), AOP (result)))
7133 if ((AOP_TYPE (right) == AOP_LIT)
7134 && (IS_AOP_HX(AOP(result))))
7136 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7141 size = AOP_SIZE (result);
7146 transferAopAop (AOP (right), offset, AOP (result), offset);
7151 freeAsmop (right, NULL, ic, TRUE);
7152 freeAsmop (result, NULL, ic, TRUE);
7155 /*-----------------------------------------------------------------*/
7156 /* genJumpTab - genrates code for jump table */
7157 /*-----------------------------------------------------------------*/
7159 genJumpTab (iCode * ic)
7164 D(emitcode ("; genJumpTab",""));
7166 aopOp (IC_JTCOND (ic), ic, FALSE);
7167 /* get the condition into accumulator */
7168 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7169 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7170 /* multiply by three */
7171 pushReg (hc08_reg_a, FALSE);
7172 emitcode ("lsla", "");
7173 emitcode ("add","1,s");
7174 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7175 loadRegFromConst (hc08_reg_h, zero);
7177 jtab = newiTempLabel (NULL);
7178 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7179 emitcode ("", "%05d$:", jtab->key + 100);
7180 /* now generate the jump labels */
7181 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7182 jtab = setNextItem (IC_JTLABELS (ic)))
7183 emitcode ("jmp", "%05d$", jtab->key + 100);
7185 hc08_dirtyReg (hc08_reg_a, TRUE);
7186 hc08_dirtyReg (hc08_reg_hx, TRUE);
7189 /*-----------------------------------------------------------------*/
7190 /* genCast - gen code for casting */
7191 /*-----------------------------------------------------------------*/
7193 genCast (iCode * ic)
7195 operand *result = IC_RESULT (ic);
7196 sym_link *ctype = operandType (IC_LEFT (ic));
7197 sym_link *rtype = operandType (IC_RIGHT (ic));
7198 operand *right = IC_RIGHT (ic);
7201 D(emitcode("; genCast",""));
7203 /* if they are equivalent then do nothing */
7204 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7207 aopOp (right, ic, FALSE);
7208 aopOp (result, ic, FALSE);
7211 /* if they are the same size : or less */
7212 if (AOP_SIZE (result) <= AOP_SIZE (right))
7215 /* if they are in the same place */
7217 if (sameRegs (AOP (right), AOP (result)))
7221 /* if they in different places then copy */
7222 size = AOP_SIZE (result);
7226 transferAopAop(AOP (right), offset, AOP (result), offset);
7233 /* if the result is of type pointer */
7238 sym_link *type = operandType (right);
7239 sym_link *etype = getSpec (type);
7241 /* pointer to generic pointer */
7242 if (IS_GENPTR (ctype))
7245 p_type = DCL_TYPE (type);
7248 if (SPEC_SCLS(etype)==S_REGISTER) {
7249 // let's assume it is a generic pointer
7252 /* we have to go by the storage class */
7253 p_type = PTR_TYPE (SPEC_OCLS (etype));
7257 /* the first two bytes are known */
7258 size = GPTRSIZE - 1;
7262 transferAopAop(AOP (right), offset, AOP (result), offset);
7265 /* the last byte depending on type */
7268 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7273 // pointerTypeToGPByte will have bitched.
7277 sprintf(gpValStr, "#0x%d", gpVal);
7278 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7284 /* just copy the pointers */
7285 size = AOP_SIZE (result);
7289 transferAopAop(AOP (right), offset, AOP (result), offset);
7295 /* so we now know that the size of destination is greater
7296 than the size of the source */
7297 /* we move to result for the size of source */
7298 size = AOP_SIZE (right);
7302 transferAopAop(AOP (right), offset, AOP (result), offset);
7306 /* now depending on the sign of the source && destination */
7307 size = AOP_SIZE (result) - AOP_SIZE (right);
7308 /* if unsigned or not an integral type */
7309 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7312 storeConstToAop (zero, AOP (result), offset++);
7316 /* we need to extend the sign :{ */
7317 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7318 accopWithMisc ("rola", "");
7319 accopWithMisc ("clra", "");
7320 accopWithMisc ("sbc", zero);
7322 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7325 /* we are done hurray !!!! */
7328 freeAsmop (right, NULL, ic, TRUE);
7329 freeAsmop (result, NULL, ic, TRUE);
7333 /*-----------------------------------------------------------------*/
7334 /* genDjnz - generate decrement & jump if not zero instrucion */
7335 /*-----------------------------------------------------------------*/
7337 genDjnz (iCode * ic, iCode * ifx)
7343 D(emitcode ("; genDjnz",""));
7345 /* if the if condition has a false label
7346 then we cannot save */
7350 /* if the minus is not of the form
7352 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7353 !IS_OP_LITERAL (IC_RIGHT (ic)))
7356 if (operandLitValue (IC_RIGHT (ic)) != 1)
7359 /* dbnz doesn't support extended mode */
7360 if (isOperandInFarSpace (IC_RESULT (ic)))
7363 /* if the size of this greater than one then no
7365 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7367 aopOp (IC_RESULT (ic), ic, FALSE);
7368 if (AOP_SIZE (IC_RESULT (ic))>1)
7370 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7374 /* otherwise we can save BIG */
7375 lbl = newiTempLabel (NULL);
7376 lbl1 = newiTempLabel (NULL);
7379 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7382 emitBranch ("bra", lbl1);
7384 emitBranch ("jmp", IC_TRUE (ifx));
7387 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7392 /*-----------------------------------------------------------------*/
7393 /* genReceive - generate code for a receive iCode */
7394 /*-----------------------------------------------------------------*/
7396 genReceive (iCode * ic)
7400 D(emitcode ("; genReceive",""));
7402 aopOp (IC_RESULT (ic), ic, FALSE);
7403 size = AOP_SIZE (IC_RESULT (ic));
7408 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7409 AOP (IC_RESULT (ic)), offset);
7410 if (hc08_aop_pass[offset]->type == AOP_REG)
7411 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7416 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7419 /*-----------------------------------------------------------------*/
7420 /* genDummyRead - generate code for dummy read of volatiles */
7421 /*-----------------------------------------------------------------*/
7423 genDummyRead (iCode * ic)
7428 D(emitcode("; genDummyRead",""));
7431 if (op && IS_SYMOP (op))
7434 aopOp (op, ic, FALSE);
7436 size = AOP_SIZE (op);
7441 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7442 hc08_freeReg (hc08_reg_a);
7446 freeAsmop (op, NULL, ic, TRUE);
7449 if (op && IS_SYMOP (op))
7452 aopOp (op, ic, FALSE);
7454 size = AOP_SIZE (op);
7459 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7460 hc08_freeReg (hc08_reg_a);
7464 freeAsmop (op, NULL, ic, TRUE);
7468 /*-----------------------------------------------------------------*/
7469 /* genCritical - generate code for start of a critical sequence */
7470 /*-----------------------------------------------------------------*/
7472 genCritical (iCode *ic)
7474 D(emitcode("; genCritical",""));
7477 aopOp (IC_RESULT (ic), ic, TRUE);
7479 emitcode ("tpa", "");
7480 hc08_dirtyReg (hc08_reg_a, FALSE);
7481 emitcode ("sei", "");
7484 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7486 pushReg (hc08_reg_a, FALSE);
7488 hc08_freeReg (hc08_reg_a);
7490 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7493 /*-----------------------------------------------------------------*/
7494 /* genEndCritical - generate code for end of a critical sequence */
7495 /*-----------------------------------------------------------------*/
7497 genEndCritical (iCode *ic)
7499 D(emitcode("; genEndCritical",""));
7503 aopOp (IC_RIGHT (ic), ic, FALSE);
7504 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7505 emitcode ("tap", "");
7506 hc08_freeReg (hc08_reg_a);
7507 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7511 pullReg (hc08_reg_a);
7512 emitcode ("tap", "");
7517 /*-----------------------------------------------------------------*/
7518 /* genhc08Code - generate code for HC08 based controllers */
7519 /*-----------------------------------------------------------------*/
7521 genhc08Code (iCode * lic)
7526 lineHead = lineCurr = NULL;
7528 /* print the allocation information */
7529 if (allocInfo && currFunc)
7530 printAllocInfo (currFunc, codeOutFile);
7531 /* if debug information required */
7532 if (options.debug && currFunc)
7534 debugFile->writeFunction(currFunc);
7536 if (IS_STATIC (currFunc->etype))
7537 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7539 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7542 /* stack pointer name */
7543 if (options.useXstack)
7548 hc08_aop_pass[0] = newAsmop (AOP_REG);
7549 hc08_aop_pass[0]->size=1;
7550 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7551 hc08_aop_pass[1] = newAsmop (AOP_REG);
7552 hc08_aop_pass[1]->size=1;
7553 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7554 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7555 hc08_aop_pass[2]->size=1;
7556 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7557 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7558 hc08_aop_pass[3]->size=1;
7559 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7561 for (ic = lic; ic; ic = ic->next)
7564 if (ic->lineno && cln != ic->lineno)
7569 emitcode ("", "C$%s$%d$%d$%d ==.",
7570 FileBaseName (ic->filename), ic->lineno,
7571 ic->level, ic->block);
7574 if (!options.noCcodeInAsm) {
7575 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7576 printCLine(ic->filename, ic->lineno));
7580 if (options.iCodeInAsm) {
7584 for (i=0; i<6; i++) {
7585 sprintf (®sInUse[i],
7586 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7589 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7591 /* if the result is marked as
7592 spilt and rematerializable or code for
7593 this has already been generated then
7595 if (resultRemat (ic) || ic->generated)
7603 for (i=A_IDX;i<=XA_IDX;i++)
7605 reg = hc08_regWithIdx(i);
7607 emitcode("","; %s = %s offset %d", reg->name,
7608 aopName(reg->aop), reg->aopofs);
7611 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7613 sym = OP_SYMBOL (IC_LEFT (ic));
7614 if (sym->accuse == ACCUSE_HX)
7616 hc08_reg_h->isFree = FALSE;
7617 hc08_reg_x->isFree = FALSE;
7619 else if (sym->accuse == ACCUSE_XA)
7621 hc08_reg_a->isFree = FALSE;
7623 hc08_reg_x->isFree = FALSE;
7626 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7628 sym = OP_SYMBOL (IC_RIGHT (ic));
7629 if (sym->accuse == ACCUSE_HX)
7631 hc08_reg_h->isFree = FALSE;
7632 hc08_reg_x->isFree = FALSE;
7634 else if (sym->accuse == ACCUSE_XA)
7636 hc08_reg_a->isFree = FALSE;
7638 hc08_reg_x->isFree = FALSE;
7643 /* depending on the operation */
7663 /* IPOP happens only when trying to restore a
7664 spilt live range, if there is an ifx statement
7665 following this pop then the if statement might
7666 be using some of the registers being popped which
7667 would destory the contents of the register so
7668 we need to check for this condition and handle it */
7670 ic->next->op == IFX &&
7671 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7672 genIfx (ic->next, ic);
7690 genEndFunction (ic);
7706 if (!genPointerGetSetOfs (ic))
7711 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7728 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7732 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7739 /* note these two are xlated by algebraic equivalence
7740 during parsing SDCC.y */
7741 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7742 "got '>=' or '<=' shouldn't have come here");
7746 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7758 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7762 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7766 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7793 case GET_VALUE_AT_ADDRESS:
7794 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7798 if (POINTER_SET (ic))
7799 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7825 addSet (&_G.sendSet, ic);
7828 case DUMMY_READ_VOLATILE:
7837 genEndCritical (ic);
7848 if (!hc08_reg_a->isFree)
7849 emitcode("","; forgot to free a");
7850 if (!hc08_reg_x->isFree)
7851 emitcode("","; forgot to free x");
7852 if (!hc08_reg_h->isFree)
7853 emitcode("","; forgot to free h");
7854 if (!hc08_reg_hx->isFree)
7855 emitcode("","; forgot to free hx");
7856 if (!hc08_reg_xa->isFree)
7857 emitcode("","; forgot to free xa");
7861 /* now we are ready to call the
7862 peep hole optimizer */
7863 if (!options.nopeep)
7864 peepHole (&lineHead);
7866 /* now do the actual printing */
7867 printLine (lineHead, codeOutFile);