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);
768 if ((aop->type == AOP_REG) && (loffset < aop->size))
769 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
771 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
774 if ((aop->type == AOP_REG) && (loffset < aop->size))
775 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
777 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
780 if (hc08_reg_a->isFree)
782 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
783 storeRegToAop (hc08_reg_a, aop, loffset);
784 hc08_freeReg (hc08_reg_a);
786 else if (hc08_reg_x->isFree)
788 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
789 storeRegToAop (hc08_reg_x, aop, loffset);
790 hc08_freeReg (hc08_reg_x);
794 pushReg (hc08_reg_a, TRUE);
795 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
796 storeRegToAop (hc08_reg_a, aop, loffset);
797 pullReg (hc08_reg_a);
801 if ((aop->type == AOP_DIR) )
803 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
805 else if (IS_AOP_XA(aop))
806 transferRegReg(reg, hc08_reg_xa, FALSE);
807 else if (IS_AOP_HX(aop))
812 needpula = pushRegIfUsed (hc08_reg_a);
813 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
814 storeRegToAop (hc08_reg_a, aop, loffset+1);
815 storeRegToAop (hc08_reg_x, aop, loffset);
816 pullOrFreeReg (hc08_reg_a, needpula);
821 transferRegReg(reg, hc08_reg_hx, FALSE);
822 else if (IS_AOP_XA(aop))
826 storeRegToAop (hc08_reg_a, aop, loffset);
827 storeRegToAop (hc08_reg_x, aop, loffset+1);
832 /* Disable the register tracking for now */
834 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
837 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
839 otherreg=hc08_regWithIdx(otheridx);
840 if (otherreg && otherreg->aop
841 && otherreg->aop->op && aop->op
842 && operandsEqu(otherreg->aop->op,aop->op)
843 && (otherreg->aopofs == loffset))
845 emitcode("","; marking %s stale", otherreg->name);
849 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
851 hc08_reg_hx->aop = NULL;
852 emitcode("","; marking hx stale");
854 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
856 hc08_reg_xa->aop = NULL;
857 emitcode("","; marking xa stale");
861 reg->aopofs = loffset;
866 /*--------------------------------------------------------------------------*/
867 /* loadRegFromConst - Load register reg from constant c. */
868 /*--------------------------------------------------------------------------*/
870 loadRegFromConst (regs *reg, char *c)
876 emitcode ("clra", "");
878 emitcode ("lda", "%s", c);
882 emitcode ("clrx", "");
884 emitcode ("ldx", "%s", c);
888 emitcode ("clrh", "");
889 else if (hc08_reg_a->isFree)
891 loadRegFromConst (hc08_reg_a, c);
892 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
894 else if (hc08_reg_x->isFree)
896 loadRegFromConst (hc08_reg_x, c);
897 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
901 pushReg (hc08_reg_a, TRUE);
902 loadRegFromConst (hc08_reg_a, c);
903 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
904 pullReg (hc08_reg_a);
908 emitcode ("ldhx", "%s", c);
911 emitcode ("lda", "%s", c);
912 emitcode ("ldx", "%s >> 8", c);
915 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
916 "Bad rIdx in loadRegFromConst");
923 /*--------------------------------------------------------------------------*/
924 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
925 /*--------------------------------------------------------------------------*/
927 storeConstToAop (char *c, asmop *aop, int loffset)
929 if (aop->stacked && aop->stk_aop[loffset])
931 storeConstToAop (c, aop->stk_aop[loffset], 0);
939 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
941 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
944 if (loffset>(aop->size-1))
946 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
949 if (hc08_reg_a->isFree)
951 loadRegFromConst (hc08_reg_a, c);
952 storeRegToAop( hc08_reg_a, aop, loffset);
953 hc08_freeReg (hc08_reg_a);
955 else if (hc08_reg_x->isFree)
957 loadRegFromConst (hc08_reg_x, c);
958 storeRegToAop( hc08_reg_x, aop, loffset);
959 hc08_freeReg (hc08_reg_x);
963 pushReg (hc08_reg_a, TRUE);
964 loadRegFromConst (hc08_reg_a, c);
965 storeRegToAop( hc08_reg_a, aop, loffset);
966 pullReg (hc08_reg_a);
972 /*--------------------------------------------------------------------------*/
973 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
974 /* reg is extended to fill logical offsets loffset */
975 /* and above of asmop aop. Otherwise, logical */
976 /* offsets loffset and above of asmop aop are */
977 /* zeroed. reg must be an 8-bit register. */
978 /*--------------------------------------------------------------------------*/
980 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
982 // int regidx = reg->rIdx;
983 int size = aop->size;
992 storeConstToAop(zero, aop, loffset++);
997 transferRegReg (reg, hc08_reg_a, FALSE);
998 emitcode ("rola","");
999 emitcode ("clra","");
1000 emitcode ("sbc", "#0");
1001 hc08_useReg (hc08_reg_a);
1002 while (loffset<size)
1003 storeRegToAop (hc08_reg_a, aop, loffset++);
1004 hc08_freeReg (hc08_reg_a);
1008 /*--------------------------------------------------------------------------*/
1009 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1010 /* padding and/or truncation as needed. If isSigned is */
1011 /* true, sign extension will take place in the padding. */
1012 /*--------------------------------------------------------------------------*/
1014 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1016 int regidx = reg->rIdx;
1017 int size = aop->size;
1024 storeRegToAop (reg, aop, 0);
1025 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1030 storeRegToAop (hc08_reg_x, aop, 0);
1034 storeRegToAop (reg, aop, 0);
1035 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1041 storeRegToAop (hc08_reg_a, aop, 0);
1045 storeRegToAop (reg, aop, 0);
1046 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1052 /*--------------------------------------------------------------------------*/
1053 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1054 /* srcaop to logical offset dstofs of asmop dstofs. */
1055 /*--------------------------------------------------------------------------*/
1057 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1059 bool needpula = FALSE;
1062 bool keepreg = FALSE;
1064 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1066 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1070 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1072 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1076 // emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1077 // aopName (srcaop), srcofs, aopName (dstaop), dstofs);
1078 // emitcode ("", "; srcaop->type = %d", srcaop->type);
1079 // emitcode ("", "; dstaop->type = %d", dstaop->type);
1081 if (dstofs >= dstaop->size)
1084 if ((dstaop->type == AOP_DIR)
1085 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1087 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1088 aopAdrStr(dstaop, dstofs, FALSE));
1092 if (dstaop->type == AOP_REG)
1094 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1095 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1097 reg = dstaop->aopu.aop_reg[dstofs];
1102 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1104 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1105 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1107 reg = srcaop->aopu.aop_reg[srcofs];
1114 if (hc08_reg_a->isFree)
1116 else if (hc08_reg_x->isFree)
1120 pushReg (hc08_reg_a, TRUE);
1126 loadRegFromAop (reg, srcaop, srcofs);
1127 storeRegToAop (reg, dstaop, dstofs);
1130 pullOrFreeReg (hc08_reg_a, needpula);
1134 /*--------------------------------------------------------------------------*/
1135 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1136 /* parameter param. */
1137 /*--------------------------------------------------------------------------*/
1139 accopWithMisc (char *accop, char *param)
1141 emitcode (accop, "%s", param);
1142 hc08_dirtyReg (hc08_reg_a, FALSE);
1145 /*--------------------------------------------------------------------------*/
1146 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1147 /* byte at logical offset loffset of asmop aop. */
1148 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1149 /*--------------------------------------------------------------------------*/
1151 accopWithAop (char *accop, asmop *aop, int loffset)
1153 if (aop->stacked && aop->stk_aop[loffset])
1155 accopWithAop (accop, aop->stk_aop[loffset], 0);
1159 if (aop->type == AOP_REG)
1161 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1162 emitcode (accop, "1,s");
1166 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1168 hc08_dirtyReg (hc08_reg_a, FALSE);
1172 /*--------------------------------------------------------------------------*/
1173 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1174 /* byte at logical offset loffset of asmop aop. Register reg */
1175 /* must be 8-bit. */
1176 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1177 /*--------------------------------------------------------------------------*/
1179 rmwWithReg (char *rmwop, regs *reg)
1182 char *rmwaop = rmwbuf;
1184 if (reg->rIdx == A_IDX)
1186 sprintf(rmwaop,"%sa", rmwop);
1187 emitcode (rmwaop, "");
1188 hc08_dirtyReg (hc08_reg_a, FALSE);
1190 else if (reg->rIdx == X_IDX)
1192 sprintf(rmwaop,"%sx", rmwop);
1193 emitcode (rmwaop, "");
1194 hc08_dirtyReg (hc08_reg_a, FALSE);
1196 else if (hc08_reg_a->isFree)
1198 transferRegReg(reg, hc08_reg_a, FALSE);
1199 sprintf(rmwaop,"%sa", rmwop);
1200 emitcode (rmwaop, "");
1201 hc08_dirtyReg (hc08_reg_a, FALSE);
1202 transferRegReg(hc08_reg_a, reg, TRUE);
1206 pushReg (reg, FALSE);
1207 emitcode (rmwop, "1,s");
1209 hc08_dirtyReg (reg, FALSE);
1213 /*--------------------------------------------------------------------------*/
1214 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1215 /* logical offset loffset of asmop aop. */
1216 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1217 /*--------------------------------------------------------------------------*/
1219 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1221 bool needpula = FALSE;
1223 if (aop->stacked && aop->stk_aop[loffset])
1225 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1232 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1235 needpula = pushRegIfUsed (hc08_reg_a);
1236 loadRegFromAop (hc08_reg_a, aop, loffset);
1237 rmwWithReg (rmwop, hc08_reg_a);
1238 storeRegToAop (hc08_reg_a, aop, loffset);
1239 pullOrFreeReg (hc08_reg_a, needpula);
1242 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1248 /*-----------------------------------------------------------------*/
1249 /* newAsmop - creates a new asmOp */
1250 /*-----------------------------------------------------------------*/
1252 newAsmop (short type)
1256 aop = Safe_calloc (1, sizeof (asmop));
1263 /*-----------------------------------------------------------------*/
1264 /* pointerCode - returns the code for a pointer type */
1265 /*-----------------------------------------------------------------*/
1267 pointerCode (sym_link * etype)
1270 return PTR_TYPE (SPEC_OCLS (etype));
1275 /*-----------------------------------------------------------------*/
1276 /* aopForSym - for a true symbol */
1277 /*-----------------------------------------------------------------*/
1279 aopForSym (iCode * ic, symbol * sym, bool result)
1284 wassertl (ic != NULL, "Got a null iCode");
1285 wassertl (sym != NULL, "Got a null symbol");
1287 // printf("in aopForSym for symbol %s\n", sym->name);
1289 space = SPEC_OCLS (sym->etype);
1291 /* if already has one */
1297 /* special case for a function */
1298 if (IS_FUNC (sym->type))
1300 sym->aop = aop = newAsmop (AOP_IMMD);
1301 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1302 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1303 aop->size = FPTRSIZE;
1307 /* if it is in direct space */
1308 if (IN_DIRSPACE (space))
1310 sym->aop = aop = newAsmop (AOP_DIR);
1311 aop->aopu.aop_dir = sym->rname;
1312 aop->size = getSize (sym->type);
1316 /* if it is in far space */
1317 if (IN_FARSPACE (space))
1319 sym->aop = aop = newAsmop (AOP_EXT);
1320 aop->aopu.aop_dir = sym->rname;
1321 aop->size = getSize (sym->type);
1325 if (IN_STACK (sym->etype))
1327 sym->aop = aop = newAsmop (AOP_SOF);
1328 aop->aopu.aop_dir = sym->rname;
1329 aop->size = getSize (sym->type);
1330 aop->aopu.aop_stk = sym->stack;
1336 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1337 "aopForSym should never reach here");
1341 /* if it is in code space */
1342 if (IN_CODESPACE (space))
1348 /*-----------------------------------------------------------------*/
1349 /* aopForRemat - rematerialzes an object */
1350 /*-----------------------------------------------------------------*/
1352 aopForRemat (symbol * sym)
1354 iCode *ic = sym->rematiCode;
1362 val += (int) operandLitValue (IC_RIGHT (ic));
1363 else if (ic->op == '-')
1364 val -= (int) operandLitValue (IC_RIGHT (ic));
1365 else if (IS_CAST_ICODE(ic)) {
1366 sym_link *from_type = operandType(IC_RIGHT(ic));
1367 aop->aopu.aop_immd.from_cast_remat = 1;
1368 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1369 ptr_type = DCL_TYPE(from_type);
1370 if (ptr_type == IPOINTER) {
1377 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1380 if (ic->op == ADDRESS_OF)
1383 sprintf (buffer, "(%s %c 0x%04x)",
1384 OP_SYMBOL (IC_LEFT (ic))->rname,
1385 val >= 0 ? '+' : '-',
1386 abs (val) & 0xffff);
1388 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1390 aop = newAsmop (AOP_IMMD);
1391 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1392 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1393 /* set immd2 field if required */
1394 if (aop->aopu.aop_immd.from_cast_remat)
1396 sprintf(buffer,"#0x%02x",ptr_type);
1397 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1398 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1401 else if (ic->op == '=')
1403 val += (int) operandLitValue (IC_RIGHT (ic));
1405 sprintf (buffer, "0x%04x", val);
1406 aop = newAsmop (AOP_LIT);
1407 aop->aopu.aop_lit = constVal (buffer);
1410 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1411 "unexpected rematerialization");
1418 /*-----------------------------------------------------------------*/
1419 /* regsInCommon - two operands have some registers in common */
1420 /*-----------------------------------------------------------------*/
1422 regsInCommon (operand * op1, operand * op2)
1424 symbol *sym1, *sym2;
1427 /* if they have registers in common */
1428 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1431 sym1 = OP_SYMBOL (op1);
1432 sym2 = OP_SYMBOL (op2);
1434 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1437 for (i = 0; i < sym1->nRegs; i++)
1443 for (j = 0; j < sym2->nRegs; j++)
1448 if (sym2->regs[j] == sym1->regs[i])
1456 /*-----------------------------------------------------------------*/
1457 /* operandsEqu - equivalent */
1458 /*-----------------------------------------------------------------*/
1460 operandsEqu (operand * op1, operand * op2)
1462 symbol *sym1, *sym2;
1464 /* if they not symbols */
1465 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1468 sym1 = OP_SYMBOL (op1);
1469 sym2 = OP_SYMBOL (op2);
1471 /* if both are itemps & one is spilt
1472 and the other is not then false */
1473 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1474 sym1->isspilt != sym2->isspilt)
1477 /* if they are the same */
1481 if (strcmp (sym1->rname, sym2->rname) == 0)
1485 /* if left is a tmp & right is not */
1486 if (IS_ITEMP (op1) &&
1489 (sym1->usl.spillLoc == sym2))
1492 if (IS_ITEMP (op2) &&
1496 (sym2->usl.spillLoc == sym1))
1502 /*-----------------------------------------------------------------*/
1503 /* sameRegs - two asmops have the same registers */
1504 /*-----------------------------------------------------------------*/
1506 sameRegs (asmop * aop1, asmop * aop2)
1513 // if (aop1->size != aop2->size)
1516 if (aop1->type == aop2->type)
1521 for (i = 0; i < aop1->size; i++)
1522 if (aop1->aopu.aop_reg[i] !=
1523 aop2->aopu.aop_reg[i])
1527 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1530 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1537 /*-----------------------------------------------------------------*/
1538 /* aopOp - allocates an asmop for an operand : */
1539 /*-----------------------------------------------------------------*/
1541 aopOp (operand * op, iCode * ic, bool result)
1550 // Is this a pointer set result?
1552 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1556 // printf("checking literal\n");
1557 /* if this a literal */
1558 if (IS_OP_LITERAL (op))
1560 op->aop = aop = newAsmop (AOP_LIT);
1561 aop->aopu.aop_lit = op->operand.valOperand;
1562 aop->size = getSize (operandType (op));
1564 aop->isaddr = op->isaddr;
1568 // printf("checking pre-existing\n");
1569 /* if already has a asmop then continue */
1573 op->aop->isaddr = op->isaddr;
1577 // printf("checking underlying sym\n");
1578 /* if the underlying symbol has a aop */
1579 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1581 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1582 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1583 //op->aop = aop = OP_SYMBOL (op)->aop;
1584 aop->size = getSize( operandType (op));
1585 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1586 //printf (" with size = %d\n", aop->size);
1589 aop->isaddr = op->isaddr;
1590 /* if (aop->isaddr & IS_ITEMP (op))
1592 aop->psize=aop->size;
1593 aop->size = getSize( operandType (op)->next);
1598 // printf("checking true sym\n");
1599 /* if this is a true symbol */
1600 if (IS_TRUE_SYMOP (op))
1602 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1604 aop->isaddr = op->isaddr;
1605 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1606 //printf (" with size = %d\n", aop->size);
1610 /* this is a temporary : this has
1616 e) can be a return use only */
1618 sym = OP_SYMBOL (op);
1620 // printf("checking conditional\n");
1621 /* if the type is a conditional */
1622 if (sym->regType == REG_CND)
1624 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1627 aop->isaddr = op->isaddr;
1631 // printf("checking spilt\n");
1632 /* if it is spilt then two situations
1634 b) has a spill location */
1635 if (sym->isspilt || sym->nRegs == 0)
1638 // printf("checking remat\n");
1639 /* rematerialize it NOW */
1642 sym->aop = op->aop = aop =
1644 aop->size = getSize (sym->type);
1646 aop->isaddr = op->isaddr;
1647 /* if (aop->isaddr & IS_ITEMP (op))
1649 aop->psize=aop->size;
1650 aop->size = getSize( operandType (op)->next);
1655 // printf("checking accuse\n");
1658 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1659 aop->size = getSize (sym->type);
1660 switch (sym->accuse)
1663 aop->aopu.aop_reg[0] = hc08_reg_a;
1664 aop->aopu.aop_reg[1] = hc08_reg_x;
1667 aop->aopu.aop_reg[0] = hc08_reg_x;
1668 aop->aopu.aop_reg[1] = hc08_reg_h;
1672 aop->isaddr = op->isaddr;
1676 // printf("checking ruonly\n");
1682 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1683 aop->size = getSize (sym->type);
1684 for (i = 0; i < fReturnSizeHC08; i++)
1685 aop->aopu.aop_str[i] = fReturn2[i];
1687 aop->isaddr = op->isaddr;
1691 /* else spill location */
1692 // printf("checking spill loc\n");
1693 // if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1694 if (sym->usl.spillLoc && sym->usl.spillLoc->aop
1695 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1697 /* force a new aop if sizes differ */
1698 sym->usl.spillLoc->aop = NULL;
1699 //printf ("forcing new aop\n");
1701 sym->aop = op->aop = aop =
1702 aopForSym (ic, sym->usl.spillLoc, result);
1703 aop->size = getSize (sym->type);
1705 aop->isaddr = op->isaddr;
1706 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1707 //printf (" with size = %d\n", aop->size);
1708 /* if (aop->isaddr & IS_ITEMP (op))
1710 aop->psize=aop->size;
1711 aop->size = getSize( operandType (op)->next);
1716 // printf("assuming register\n");
1717 /* must be in a register */
1718 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1719 aop->size = sym->nRegs;
1720 for (i = 0; i < sym->nRegs; i++)
1721 aop->aopu.aop_reg[i] = sym->regs[i];
1723 aop->isaddr = op->isaddr;
1727 /*-----------------------------------------------------------------*/
1728 /* freeAsmop - free up the asmop given to an operand */
1729 /*----------------------------------------------------------------*/
1731 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1753 emitcode ("","; freeAsmop restoring stacked %s", aopName(aop));
1756 for (loffset=0; loffset<aop->size; loffset++)
1757 if (aop->stk_aop[loffset])
1759 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1762 pullNull (stackAdjust);
1766 /* all other cases just dealloc */
1772 OP_SYMBOL (op)->aop = NULL;
1773 /* if the symbol has a spill */
1775 SPIL_LOC (op)->aop = NULL;
1781 /*-----------------------------------------------------------------*/
1782 /* aopDerefAop - treating the aop parameter as a pointer, return */
1783 /* an asmop for the object it references */
1784 /*-----------------------------------------------------------------*/
1786 aopDerefAop (asmop *aop)
1791 asmop *newaop = NULL;
1792 sym_link *type, *etype;
1795 emitcode ("", "; aopDerefAop(%s)", aopName(aop));
1799 type = operandType (aop->op);
1800 etype = getSpec (type);
1801 /* if op is of type of pointer then it is simple */
1802 if (IS_PTR (type) && !IS_FUNC (type->next))
1803 p_type = DCL_TYPE (type);
1806 /* we have to go by the storage class */
1807 p_type = PTR_TYPE (SPEC_OCLS (etype));
1816 if (p_type == POINTER)
1817 newaop = newAsmop (AOP_DIR);
1819 newaop = newAsmop (AOP_EXT);
1820 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1823 adr = (int) floatFromVal (aop->aopu.aop_lit);
1824 if (p_type == POINTER)
1829 newaop = newAsmop (AOP_DIR);
1830 sprintf (s, "0x%02x",adr);
1834 newaop = newAsmop (AOP_EXT);
1835 sprintf (s, "0x%04x",adr);
1837 rs = Safe_calloc (1, strlen (s) + 1);
1839 newaop->aopu.aop_dir = rs;
1842 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1843 "unsupported asmop");
1853 /*-----------------------------------------------------------------*/
1854 /* aopAdrStr - for referencing the address of the aop */
1855 /*-----------------------------------------------------------------*/
1857 aopAdrStr (asmop * aop, int loffset, bool bit16)
1861 int offset = aop->size - 1 - loffset;
1864 /* offset is greater than
1866 if (loffset > (aop->size - 1) &&
1867 aop->type != AOP_LIT)
1870 /* depending on type */
1875 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1876 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1878 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1882 sprintf (s, "#(%s >> %d)",
1883 aop->aopu.aop_immd.aop_immd1,
1887 aop->aopu.aop_immd.aop_immd1);
1891 aop->aopu.aop_immd.aop_immd1);
1892 rs = Safe_calloc (1, strlen (s) + 1);
1898 sprintf (s, "*(%s + %d)",
1902 sprintf (s, "*%s", aop->aopu.aop_dir);
1903 rs = Safe_calloc (1, strlen (s) + 1);
1909 sprintf (s, "(%s + %d)",
1913 sprintf (s, "%s", aop->aopu.aop_dir);
1914 rs = Safe_calloc (1, strlen (s) + 1);
1919 return aop->aopu.aop_reg[loffset]->name;
1923 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
1925 return aopLiteral (aop->aopu.aop_lit, loffset);
1929 return aop->aopu.aop_str[loffset];
1932 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
1934 rs = Safe_calloc (1, strlen (s) + 1);
1940 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1941 "aopAdrStr got unsupported aop->type");
1950 /*-----------------------------------------------------------------*/
1951 /* opIsGptr: returns non-zero if the passed operand is */
1952 /* a generic pointer type. */
1953 /*-----------------------------------------------------------------*/
1955 opIsGptr (operand * op)
1957 sym_link *type = operandType (op);
1959 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1967 /*-----------------------------------------------------------------*/
1968 /* getDataSize - get the operand data size */
1969 /*-----------------------------------------------------------------*/
1971 getDataSize (operand * op)
1974 size = AOP_SIZE (op);
1978 /*-----------------------------------------------------------------*/
1979 /* outAcc - output Acc */
1980 /*-----------------------------------------------------------------*/
1982 outAcc (operand * result)
1985 size = getDataSize (result);
1988 storeRegToAop (hc08_reg_a, AOP (result), 0);
1991 /* unsigned or positive */
1994 storeConstToAop (zero, AOP (result), offset++);
1999 /*-----------------------------------------------------------------*/
2000 /* outBitC - output a bit C */
2001 /*-----------------------------------------------------------------*/
2003 outBitC (operand * result)
2007 /* if the result is bit */
2008 if (AOP_TYPE (result) == AOP_CRY)
2009 aopPut (AOP (result), "c", 0);
2013 emitcode ("clra", "");
2014 emitcode ("rola", "");
2019 /*-----------------------------------------------------------------*/
2020 /* outBitNV - output a bit N^V */
2021 /*-----------------------------------------------------------------*/
2023 outBitNV (operand * result)
2025 symbol *tlbl, *tlbl1;
2027 tlbl = newiTempLabel (NULL);
2028 tlbl1 = newiTempLabel (NULL);
2030 emitBranch ("blt", tlbl);
2031 loadRegFromConst (hc08_reg_a, zero);
2032 emitBranch ("bra", tlbl1);
2034 loadRegFromConst (hc08_reg_a, one);
2040 /*-----------------------------------------------------------------*/
2041 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2042 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2043 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2044 /*-----------------------------------------------------------------*/
2046 asmopToBool (asmop *aop, bool resultInA)
2048 symbol *tlbl, *tlbl1;
2049 int size = aop->size;
2050 bool needpula = FALSE;
2051 bool flagsonly = TRUE;
2056 hc08_freeReg(hc08_reg_a);
2063 emitcode ("tsta", "");
2066 else if (IS_AOP_X(aop))
2067 emitcode ("tstx", "");
2068 else if (IS_AOP_H(aop))
2070 if (hc08_reg_a->isFree)
2072 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2073 emitcode ("tsta", "");
2075 hc08_freeReg(hc08_reg_a);
2077 else if (hc08_reg_x->isFree)
2079 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2080 emitcode ("tstx", "");
2081 hc08_freeReg(hc08_reg_x);
2085 emitcode ("pshh", "");
2086 emitcode ("tst", "1,s");
2087 emitcode ("ais", "#1");
2090 else if (IS_AOP_HX(aop))
2091 emitcode ("cphx", zero);
2092 else if (IS_AOP_XA(aop))
2094 symbol *tlbl = newiTempLabel (NULL);
2095 emitcode ("tsta", "");
2096 emitcode ("bne", "%05d$", (tlbl->key + 100));
2097 emitcode ("tstx", "");
2098 emitcode ("", "%05d$:", (tlbl->key + 100));
2102 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2103 "Bad rIdx in asmToBool");
2111 needpula = pushRegIfUsed (hc08_reg_a);
2112 loadRegFromAop (hc08_reg_a, aop, 0);
2113 for (offset=1; offset<size; offset++)
2114 accopWithAop ("ora", aop, offset);
2116 pullReg (hc08_reg_a);
2119 hc08_freeReg (hc08_reg_a);
2128 loadRegFromAop (hc08_reg_a, aop, 0);
2129 hc08_freeReg (hc08_reg_a);
2133 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2138 if (hc08_reg_a->isFree)
2140 loadRegFromAop (hc08_reg_a, aop, 0);
2141 accopWithAop ("ora", aop, 1);
2142 hc08_freeReg (hc08_reg_a);
2147 tlbl = newiTempLabel (NULL);
2148 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2149 emitcode ("bne", "%05d$", (tlbl->key + 100));
2150 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2151 emitcode ("", "%05d$:", (tlbl->key + 100));
2157 needpula = pushRegIfUsed (hc08_reg_a);
2158 loadRegFromAop (hc08_reg_a, aop, 0);
2159 for (offset=1; offset<size; offset++)
2160 accopWithAop ("ora", aop, offset);
2162 pullReg (hc08_reg_a);
2165 hc08_freeReg (hc08_reg_a);
2173 tlbl = newiTempLabel (NULL);
2177 tlbl1 = newiTempLabel (NULL);
2178 emitBranch ("bne", tlbl1);
2179 loadRegFromConst (hc08_reg_a, zero);
2180 emitBranch ("bra", tlbl);
2182 loadRegFromConst (hc08_reg_a, one);
2186 emitBranch ("beq", tlbl);
2187 loadRegFromConst (hc08_reg_a, one);
2190 hc08_useReg (hc08_reg_a);
2196 /*-----------------------------------------------------------------*/
2197 /* genNot - generate code for ! operation */
2198 /*-----------------------------------------------------------------*/
2202 D(emitcode ("; genNot",""));
2204 /* assign asmOps to operand & result */
2205 aopOp (IC_LEFT (ic), ic, FALSE);
2206 aopOp (IC_RESULT (ic), ic, TRUE);
2208 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2209 emitcode ("eor", one);
2210 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2212 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2213 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2217 /*-----------------------------------------------------------------*/
2218 /* genCpl - generate code for complement */
2219 /*-----------------------------------------------------------------*/
2225 regs* reg = hc08_reg_a;
2229 D(emitcode ("; genCpl",""));
2231 /* assign asmOps to operand & result */
2232 aopOp (IC_LEFT (ic), ic, FALSE);
2233 aopOp (IC_RESULT (ic), ic, TRUE);
2235 size = AOP_SIZE (IC_RESULT (ic));
2238 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2239 rmwWithReg ("com", reg);
2241 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2245 /* release the aops */
2246 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2247 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2250 /*-----------------------------------------------------------------*/
2251 /* genUminusFloat - unary minus for floating points */
2252 /*-----------------------------------------------------------------*/
2254 genUminusFloat (operand * op, operand * result)
2256 int size, offset = 0;
2259 D(emitcode ("; genUminusFloat",""));
2261 /* for this we just copy and then flip the bit */
2263 size = AOP_SIZE (op) - 1;
2269 needpula = pushRegIfUsed (hc08_reg_a);
2270 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2271 emitcode ("eor", "#0x80");
2272 hc08_useReg (hc08_reg_a);
2273 storeRegToAop (hc08_reg_a, AOP (result), offset);
2274 pullOrFreeReg (hc08_reg_a, needpula);
2277 transferAopAop (AOP (op), offset, AOP (result), offset);
2283 /*-----------------------------------------------------------------*/
2284 /* genUminus - unary minus code generation */
2285 /*-----------------------------------------------------------------*/
2287 genUminus (iCode * ic)
2290 sym_link *optype, *rtype;
2295 D(emitcode ("; genUminus",""));
2298 aopOp (IC_LEFT (ic), ic, FALSE);
2299 aopOp (IC_RESULT (ic), ic, TRUE);
2301 optype = operandType (IC_LEFT (ic));
2302 rtype = operandType (IC_RESULT (ic));
2304 /* if float then do float stuff */
2305 if (IS_FLOAT (optype))
2307 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2311 /* otherwise subtract from zero */
2312 size = AOP_SIZE (IC_LEFT (ic));
2317 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2318 needpula = pushRegIfUsed (hc08_reg_a);
2321 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2322 emitcode ("nega", "");
2323 hc08_freeReg (hc08_reg_a);
2324 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2325 SPEC_USIGN (operandType (IC_LEFT (ic))));
2326 pullOrFreeReg (hc08_reg_a, needpula);
2330 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2331 result = forceStackedAop (AOP (IC_RESULT (ic)));
2333 result = AOP (IC_RESULT (ic));
2335 needpula = pushRegIfUsed (hc08_reg_a);
2339 loadRegFromConst (hc08_reg_a, zero);
2340 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2341 storeRegToAop (hc08_reg_a, result, offset++);
2344 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2345 SPEC_USIGN (operandType (IC_LEFT (ic))));
2346 pullOrFreeReg (hc08_reg_a, needpula);
2348 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2349 freeAsmop (NULL, result, ic, TRUE);
2355 /* release the aops */
2356 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2357 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2360 /*-----------------------------------------------------------------*/
2361 /* saveRegisters - will look for a call and save the registers */
2362 /*-----------------------------------------------------------------*/
2364 saveRegisters (iCode * lic)
2371 for (ic = lic; ic; ic = ic->next)
2372 if (ic->op == CALL || ic->op == PCALL)
2377 fprintf (stderr, "found parameter push with no function call\n");
2381 /* if the registers have been saved already or don't need to be then
2385 if (IS_SYMOP(IC_LEFT(ic)) &&
2386 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2387 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2390 /* safe the registers in use at this time but skip the
2391 ones for the result */
2392 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2393 hc08_rUmaskForOp (IC_RESULT(ic)));
2396 for (i = 0; i < hc08_nRegs; i++)
2398 if (bitVectBitValue (rsave, i))
2399 pushReg ( hc08_regWithIdx (i), FALSE);
2403 /*-----------------------------------------------------------------*/
2404 /* unsaveRegisters - pop the pushed registers */
2405 /*-----------------------------------------------------------------*/
2407 unsaveRegisters (iCode * ic)
2412 /* restore the registers in use at this time but skip the
2413 ones for the result */
2414 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2415 hc08_rUmaskForOp (IC_RESULT(ic)));
2417 for (i = hc08_nRegs; i >= 0; i--)
2419 if (bitVectBitValue (rsave, i))
2420 pullReg ( hc08_regWithIdx (i));
2426 /*-----------------------------------------------------------------*/
2428 /*-----------------------------------------------------------------*/
2430 pushSide (operand * oper, int size)
2435 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2436 pushReg ( hc08_reg_a, TRUE);
2440 /*-----------------------------------------------------------------*/
2441 /* assignResultValue - */
2442 /*-----------------------------------------------------------------*/
2444 assignResultValue (operand * oper)
2446 int size = AOP_SIZE (oper);
2450 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2451 if (hc08_aop_pass[offset]->type == AOP_REG)
2452 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2459 /*-----------------------------------------------------------------*/
2460 /* genIpush - genrate code for pushing this gets a little complex */
2461 /*-----------------------------------------------------------------*/
2463 genIpush (iCode * ic)
2465 int size, offset = 0;
2468 D(emitcode ("; genIpush",""));
2470 /* if this is not a parm push : ie. it is spill push
2471 and spill push is always done on the local stack */
2475 /* and the item is spilt then do nothing */
2476 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2479 aopOp (IC_LEFT (ic), ic, FALSE);
2480 size = AOP_SIZE (IC_LEFT (ic));
2482 /* push it on the stack */
2485 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2486 pushReg ( hc08_reg_a, TRUE);
2492 /* this is a paramter push: in this case we call
2493 the routine to find the call and save those
2494 registers that need to be saved */
2497 /* then do the push */
2498 aopOp (IC_LEFT (ic), ic, FALSE);
2501 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2502 size = AOP_SIZE (IC_LEFT (ic));
2505 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2506 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2508 if ((size==2) && hc08_reg_hx->isFree)
2510 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2511 pushReg (hc08_reg_hx, TRUE);
2518 // printf("loading %d\n", offset);
2519 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2520 // printf("pushing \n");
2521 pushReg (hc08_reg_a, TRUE);
2525 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2528 /*-----------------------------------------------------------------*/
2529 /* genIpop - recover the registers: can happen only for spilling */
2530 /*-----------------------------------------------------------------*/
2532 genIpop (iCode * ic)
2536 D(emitcode ("; genIpop",""));
2538 /* if the temp was not pushed then */
2539 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2542 aopOp (IC_LEFT (ic), ic, FALSE);
2543 size = AOP_SIZE (IC_LEFT (ic));
2547 pullReg (hc08_reg_a);
2548 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2550 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2554 /*-----------------------------------------------------------------*/
2555 /* genSend - gen code for SEND */
2556 /*-----------------------------------------------------------------*/
2557 static void genSend(set *sendSet)
2561 for (sic = setFirstItem (_G.sendSet); sic;
2562 sic = setNextItem (_G.sendSet)) {
2563 int size, offset = 0;
2564 aopOp (IC_LEFT (sic), sic, FALSE);
2565 size = AOP_SIZE (IC_LEFT (sic));
2570 transferAopAop( AOP (IC_LEFT (sic)), offset,
2571 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2575 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2579 /*-----------------------------------------------------------------*/
2580 /* genCall - generates a call statement */
2581 /*-----------------------------------------------------------------*/
2583 genCall (iCode * ic)
2586 // bool restoreBank = FALSE;
2587 // bool swapBanks = FALSE;
2589 D(emitcode("; genCall",""));
2591 dtype = operandType (IC_LEFT (ic));
2592 /* if send set is not empty the assign */
2595 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2596 genSend(reverseSet(_G.sendSet));
2598 genSend(_G.sendSet);
2604 /* if caller saves & we have not saved then */
2610 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2611 OP_SYMBOL (IC_LEFT (ic))->rname :
2612 OP_SYMBOL (IC_LEFT (ic))->name));
2615 /* if we need assign a result value */
2616 if ((IS_ITEMP (IC_RESULT (ic)) &&
2617 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2618 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2619 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2620 IS_TRUE_SYMOP (IC_RESULT (ic)))
2624 aopOp (IC_RESULT (ic), ic, FALSE);
2627 assignResultValue (IC_RESULT (ic));
2629 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2632 /* adjust the stack for parameters if
2636 pullNull (ic->parmBytes);
2639 /* if we had saved some registers then unsave them */
2640 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2641 unsaveRegisters (ic);
2645 /*-----------------------------------------------------------------*/
2646 /* -10l - generates a call by pointer statement */
2647 /*-----------------------------------------------------------------*/
2649 genPcall (iCode * ic)
2652 symbol *rlbl = newiTempLabel (NULL);
2653 symbol *tlbl = newiTempLabel (NULL);
2654 // bool restoreBank=FALSE;
2655 // bool swapBanks = FALSE;
2657 D(emitcode("; genPCall",""));
2659 /* if caller saves & we have not saved then */
2663 /* if we are calling a not _naked function that is not using
2664 the same register bank then we need to save the
2665 destination registers on the stack */
2666 dtype = operandType (IC_LEFT (ic))->next;
2668 /* now push the calling address */
2669 emitBranch ("bsr", tlbl);
2670 emitBranch ("bra", rlbl);
2673 /* Push the function's address */
2674 aopOp (IC_LEFT (ic), ic, FALSE);
2675 pushSide (IC_LEFT (ic), FPTRSIZE);
2676 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2678 /* if send set is not empty the assign */
2681 genSend(reverseSet(_G.sendSet));
2687 emitcode ("rts", "");
2692 /* if we need assign a result value */
2693 if ((IS_ITEMP (IC_RESULT (ic)) &&
2694 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2695 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2696 IS_TRUE_SYMOP (IC_RESULT (ic)))
2700 aopOp (IC_RESULT (ic), ic, FALSE);
2703 assignResultValue (IC_RESULT (ic));
2705 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2708 /* adjust the stack for parameters if
2712 pullNull (ic->parmBytes);
2715 /* if we hade saved some registers then
2717 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2718 unsaveRegisters (ic);
2721 /*-----------------------------------------------------------------*/
2722 /* resultRemat - result is rematerializable */
2723 /*-----------------------------------------------------------------*/
2725 resultRemat (iCode * ic)
2727 if (SKIP_IC (ic) || ic->op == IFX)
2730 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2732 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2733 if (sym->remat && !POINTER_SET (ic))
2740 #if defined(__BORLANDC__) || defined(_MSC_VER)
2741 #define STRCASECMP stricmp
2743 #define STRCASECMP strcasecmp
2746 /*-----------------------------------------------------------------*/
2747 /* inExcludeList - return 1 if the string is in exclude Reg list */
2748 /*-----------------------------------------------------------------*/
2750 regsCmp(void *p1, void *p2)
2752 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2756 inExcludeList (char *s)
2758 const char *p = setFirstItem(options.excludeRegsSet);
2760 if (p == NULL || STRCASECMP(p, "none") == 0)
2764 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2767 /*-----------------------------------------------------------------*/
2768 /* genFunction - generated code for function entry */
2769 /*-----------------------------------------------------------------*/
2771 genFunction (iCode * ic)
2775 int calleesaves_saved_register = -1;
2779 /* create the function header */
2780 emitcode (";", "-----------------------------------------");
2781 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2782 emitcode (";", "-----------------------------------------");
2784 emitcode ("", "%s:", sym->rname);
2785 ftype = operandType (IC_LEFT (ic));
2787 if (IFFUNC_ISNAKED(ftype))
2789 emitcode(";", "naked function: no prologue.");
2795 /* if this is an interrupt service routine then
2797 if (IFFUNC_ISISR (sym->type))
2800 if (!inExcludeList ("h"))
2801 emitcode ("pshh", "");
2805 /* if callee-save to be used for this function
2806 then save the registers being used in this function */
2807 if (IFFUNC_CALLEESAVES(sym->type))
2811 /* if any registers used */
2814 /* save the registers used */
2815 for (i = 0; i < sym->regsUsed->size; i++)
2817 if (bitVectBitValue (sym->regsUsed, i))
2819 /* remember one saved register for later usage */
2820 if (calleesaves_saved_register < 0)
2821 calleesaves_saved_register = i;
2822 pushReg (hc08_regWithIdx (i), FALSE);
2830 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2835 /* adjust the stack for the function */
2841 // werror (W_STACK_OVERFLOW, sym->name);
2845 _G.stackOfs = sym->stack;
2848 /* if critical function then turn interrupts off */
2849 if (IFFUNC_ISCRITICAL (ftype))
2851 if (IFFUNC_ARGS (ftype))
2853 /* Function was passed parameters, so make sure A is preserved */
2854 pushReg (hc08_reg_a, FALSE);
2855 pushReg (hc08_reg_a, FALSE);
2856 emitcode ("tpa", "");
2857 emitcode ("sta", "2,s");
2858 emitcode ("sei", "");
2859 pullReg (hc08_reg_a);
2863 /* No passed parameters, so A can be freely modified */
2864 emitcode ("tpa", "");
2865 pushReg (hc08_reg_a, TRUE);
2866 emitcode ("sei", "");
2872 /*-----------------------------------------------------------------*/
2873 /* genEndFunction - generates epilogue for functions */
2874 /*-----------------------------------------------------------------*/
2876 genEndFunction (iCode * ic)
2878 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2880 if (IFFUNC_ISNAKED(sym->type))
2882 emitcode(";", "naked function: no epilogue.");
2886 if (IFFUNC_ISCRITICAL (sym->type))
2888 if (!IS_VOID(sym->type->next))
2890 /* Function has return value, so make sure A is preserved */
2891 pushReg (hc08_reg_a, FALSE);
2892 emitcode ("lda", "2,s");
2893 emitcode ("tap", "");
2894 pullReg (hc08_reg_a);
2899 /* Function returns void, so A can be freely modified */
2900 pullReg (hc08_reg_a);
2901 emitcode ("tap", "");
2905 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2911 _G.stackPushes += sym->stack;
2912 adjustStack (sym->stack);
2916 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2920 if (IFFUNC_ISISR (sym->type))
2923 if (!inExcludeList ("h"))
2924 emitcode ("pulh", "");
2927 /* if debug then send end of function */
2928 if (options.debug && currFunc)
2931 emitcode ("", "C$%s$%d$%d$%d ==.",
2932 FileBaseName (ic->filename), currFunc->lastLine,
2933 ic->level, ic->block);
2934 if (IS_STATIC (currFunc->etype))
2935 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2937 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2941 emitcode ("rti", "");
2945 if (IFFUNC_CALLEESAVES(sym->type))
2949 /* if any registers used */
2952 /* save the registers used */
2953 for (i = sym->regsUsed->size; i >= 0; i--)
2955 if (bitVectBitValue (sym->regsUsed, i) ||
2956 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
2957 emitcode ("pop", "%s", hc08_regWithIdx (i)->dname);
2963 /* if debug then send end of function */
2964 if (options.debug && currFunc)
2967 emitcode ("", "C$%s$%d$%d$%d ==.",
2968 FileBaseName (ic->filename), currFunc->lastLine,
2969 ic->level, ic->block);
2970 if (IS_STATIC (currFunc->etype))
2971 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2973 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2977 emitcode ("rts", "");
2982 /*-----------------------------------------------------------------*/
2983 /* genRet - generate code for return statement */
2984 /*-----------------------------------------------------------------*/
2988 int size, offset = 0;
2991 D(emitcode ("; genRet",""));
2993 /* if we have no return value then
2994 just generate the "ret" */
2998 /* we have something to return then
2999 move the return value into place */
3000 aopOp (IC_LEFT (ic), ic, FALSE);
3001 size = AOP_SIZE (IC_LEFT (ic));
3007 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3014 /* 4 byte return: store value in the global return variable */
3018 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3019 STA (fReturn2[offset--], FALSE);
3020 hc08_freeReg (hc08_reg_a);
3024 /* 2 byte return: store value in x:a */
3025 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3026 hc08_freeReg (hc08_reg_xa);
3029 /* 1 byte return: store value in a */
3030 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3031 hc08_freeReg (hc08_reg_a);
3036 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3039 /* generate a jump to the return label
3040 if the next is not the return statement */
3041 if (!(ic->next && ic->next->op == LABEL &&
3042 IC_LABEL (ic->next) == returnLabel))
3044 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3048 /*-----------------------------------------------------------------*/
3049 /* genLabel - generates a label */
3050 /*-----------------------------------------------------------------*/
3052 genLabel (iCode * ic)
3057 /* For the high level labels we cannot depend on any */
3058 /* register's contents. Amnesia time. */
3059 for (i=A_IDX;i<=XA_IDX;i++)
3061 reg = hc08_regWithIdx(i);
3066 /* special case never generate */
3067 if (IC_LABEL (ic) == entryLabel)
3070 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3074 /*-----------------------------------------------------------------*/
3075 /* genGoto - generates a jmp */
3076 /*-----------------------------------------------------------------*/
3078 genGoto (iCode * ic)
3080 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3084 /*-----------------------------------------------------------------*/
3085 /* findLabelBackwards: walks back through the iCode chain looking */
3086 /* for the given label. Returns number of iCode instructions */
3087 /* between that label and given ic. */
3088 /* Returns zero if label not found. */
3089 /*-----------------------------------------------------------------*/
3091 findLabelBackwards (iCode * ic, int key)
3100 /* If we have any pushes or pops, we cannot predict the distance.
3101 I don't like this at all, this should be dealt with in the
3103 if (ic->op == IPUSH || ic->op == IPOP) {
3107 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3117 /*-----------------------------------------------------------------*/
3118 /* genPlusIncr :- does addition with increment if possible */
3119 /*-----------------------------------------------------------------*/
3121 genPlusIncr (iCode * ic)
3129 unsigned int size = getDataSize (IC_RESULT (ic));
3131 symbol *tlbl = NULL;
3133 left = IC_LEFT (ic);
3134 result = IC_RESULT (ic);
3136 /* will try to generate an increment */
3137 /* if the right side is not a literal
3139 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3142 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3144 emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left)));
3146 if ((IS_AOP_HX (AOP (left)) ||
3147 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3149 && (icount>=-128) && (icount<=127) && (size==2))
3151 if (!IS_AOP_HX (AOP (left)))
3153 needpulx = pushRegIfUsed (hc08_reg_x);
3154 needpulh = pushRegIfUsed (hc08_reg_h);
3161 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3162 emitcode ("aix","#%d", icount);
3163 hc08_dirtyReg (hc08_reg_hx, FALSE);
3164 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3165 pullOrFreeReg (hc08_reg_h, needpulh);
3166 pullOrFreeReg (hc08_reg_x, needpulx);
3170 emitcode ("", "; icount = %d, sameRegs=%d", icount,
3171 sameRegs (AOP (left), AOP (result)));
3173 if ((icount > 255) || (icount<0))
3176 if (!sameRegs (AOP (left), AOP (result)))
3179 D(emitcode ("; genPlusIncr",""));
3182 tlbl = newiTempLabel (NULL);
3187 rmwWithAop ("inc", AOP (result), 0);
3189 emitBranch ("bne", tlbl);
3193 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3194 needpula = pushRegIfUsed (hc08_reg_a);
3197 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3198 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3199 hc08_useReg (hc08_reg_a);
3200 storeRegToAop (hc08_reg_a, AOP (result), 0);
3201 hc08_freeReg (hc08_reg_a);
3203 emitBranch ("bcc", tlbl);
3205 for (offset=1; offset<size; offset++)
3207 rmwWithAop ("inc", AOP (result), offset);
3208 if ((offset+1)<size)
3209 emitBranch ("bne", tlbl);
3215 pullOrFreeReg (hc08_reg_a, needpula);
3222 /*-----------------------------------------------------------------*/
3223 /* genPlus - generates code for addition */
3224 /*-----------------------------------------------------------------*/
3226 genPlus (iCode * ic)
3228 int size, offset = 0;
3230 asmop *leftOp, *rightOp;
3232 /* special cases :- */
3234 D(emitcode ("; genPlus",""));
3236 aopOp (IC_LEFT (ic), ic, FALSE);
3237 aopOp (IC_RIGHT (ic), ic, FALSE);
3238 aopOp (IC_RESULT (ic), ic, TRUE);
3240 /* we want registers on the left and literals on the right */
3241 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3242 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3244 operand *t = IC_RIGHT (ic);
3245 IC_RIGHT (ic) = IC_LEFT (ic);
3250 /* if I can do an increment instead
3251 of add then GOOD for ME */
3252 if (genPlusIncr (ic) == TRUE)
3255 emitcode("","; left size = %d", getDataSize (IC_LEFT(ic)));
3256 emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic)));
3257 emitcode("","; result size = %d", getDataSize (IC_RESULT(ic)));
3259 size = getDataSize (IC_RESULT (ic));
3261 leftOp = AOP(IC_LEFT(ic));
3262 rightOp = AOP(IC_RIGHT(ic));
3268 loadRegFromAop (hc08_reg_a, leftOp, offset);
3269 accopWithAop(add, rightOp, offset);
3270 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3271 hc08_freeReg (hc08_reg_a);
3272 add = "adc"; /* further adds must propagate carry */
3276 // adjustArithmeticResult (ic);
3279 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3280 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3281 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3284 /*-----------------------------------------------------------------*/
3285 /* genMinusDec :- does subtraction with deccrement if possible */
3286 /*-----------------------------------------------------------------*/
3288 genMinusDec (iCode * ic)
3290 unsigned int icount;
3295 unsigned int size = getDataSize (IC_RESULT (ic));
3299 left = IC_LEFT (ic);
3300 result = IC_RESULT (ic);
3302 /* will try to generate an increment */
3303 /* if the right side is not a literal
3305 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3308 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3310 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3311 && (icount>=-127) && (icount<=128) && (size==2))
3313 if (!IS_AOP_HX (AOP (left)))
3315 needpulx = pushRegIfUsed (hc08_reg_x);
3316 needpulh = pushRegIfUsed (hc08_reg_h);
3323 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3324 emitcode ("aix","#%d", -icount);
3325 hc08_dirtyReg (hc08_reg_hx, FALSE);
3326 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3327 pullOrFreeReg (hc08_reg_h, needpulh);
3328 pullOrFreeReg (hc08_reg_x, needpulx);
3332 if ((icount > 1) || (icount<0))
3335 if (!sameRegs (AOP (left), AOP (result)))
3341 D(emitcode ("; genMinusDec",""));
3343 rmwWithAop ("dec", AOP (result), 0);
3348 /*-----------------------------------------------------------------*/
3349 /* addSign - complete with sign */
3350 /*-----------------------------------------------------------------*/
3352 addSign (operand * result, int offset, int sign)
3354 int size = (getDataSize (result) - offset);
3359 emitcode ("rola", "");
3360 emitcode ("clra", "");
3361 emitcode ("sbc", zero);
3363 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3367 storeConstToAop (zero, AOP (result), offset++);
3372 /*-----------------------------------------------------------------*/
3373 /* genMinus - generates code for subtraction */
3374 /*-----------------------------------------------------------------*/
3376 genMinus (iCode * ic)
3379 int size, offset = 0;
3381 asmop *leftOp, *rightOp;
3383 D(emitcode ("; genMinus",""));
3385 aopOp (IC_LEFT (ic), ic, FALSE);
3386 aopOp (IC_RIGHT (ic), ic, FALSE);
3387 aopOp (IC_RESULT (ic), ic, TRUE);
3389 /* special cases :- */
3390 /* if I can do an decrement instead
3391 of subtract then GOOD for ME */
3392 if (genMinusDec (ic) == TRUE)
3395 size = getDataSize (IC_RESULT (ic));
3398 leftOp = AOP(IC_LEFT(ic));
3399 rightOp = AOP(IC_RIGHT(ic));
3405 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3406 accopWithAop(sub, rightOp, offset);
3407 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3412 // adjustArithmeticResult (ic);
3415 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3416 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3417 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3422 /*-----------------------------------------------------------------*/
3423 /* genMultOneByte : 8*8=8/16 bit multiplication */
3424 /*-----------------------------------------------------------------*/
3426 genMultOneByte (operand * left,
3430 sym_link *opetype = operandType (result);
3431 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3432 int size=AOP_SIZE(result);
3433 bool negLiteral = FALSE;
3435 D(emitcode ("; genMultOneByte",""));
3437 if (size<1 || size>2) {
3438 // this should never happen
3439 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3440 AOP_SIZE(result), __FILE__, lineno);
3444 /* (if two literals: the value is computed before) */
3445 /* if one literal, literal on the right */
3446 if (AOP_TYPE (left) == AOP_LIT)
3451 //emitcode (";", "swapped left and right");
3454 if (SPEC_USIGN(opetype)
3455 || (SPEC_USIGN(operandType(left)) &&
3456 SPEC_USIGN(operandType(right))))
3458 // just an unsigned 8*8=8/16 multiply
3459 //emitcode (";","unsigned");
3461 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3462 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3463 emitcode ("mul", "");
3464 hc08_dirtyReg (hc08_reg_xa, FALSE);
3465 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3466 hc08_freeReg (hc08_reg_xa);
3471 // we have to do a signed multiply
3474 //emitcode (";", "signed");
3476 emitcode ("clr", "1,s");
3478 tlbl1 = newiTempLabel (NULL);
3479 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3480 emitcode ("tsta","");
3481 emitBranch ("bpl", tlbl1);
3482 emitcode ("inc", "1,s");
3483 rmwWithReg ("neg", hc08_reg_a);
3486 if (AOP_TYPE(right)==AOP_LIT)
3488 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3489 /* AND literal negative */
3491 emitcode ("ldx", "#0x%02x", -val);
3494 emitcode ("ldx", "#0x%02x", val);
3496 hc08_useReg (hc08_reg_x);
3500 tlbl2 = newiTempLabel (NULL);
3501 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3502 emitcode ("tstx", "");
3503 emitBranch ("bpl", tlbl2);
3504 emitcode ("inc", "1,s");
3505 rmwWithReg ("neg", hc08_reg_x);
3509 emitcode ("mul", "");
3510 hc08_dirtyReg (hc08_reg_xa, FALSE);
3512 tlbl3 = newiTempLabel (NULL);
3513 emitcode ("dec", "1,s");
3515 emitBranch ("bne", tlbl3);
3517 emitBranch ("beq", tlbl3);
3519 rmwWithReg ("neg", hc08_reg_a);
3522 tlbl4 = newiTempLabel (NULL);
3523 emitBranch ("bcc", tlbl4);
3524 rmwWithReg ("inc", hc08_reg_x);
3526 rmwWithReg ("neg", hc08_reg_x);
3531 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3532 hc08_freeReg (hc08_reg_xa);
3536 /*-----------------------------------------------------------------*/
3537 /* genMult - generates code for multiplication */
3538 /*-----------------------------------------------------------------*/
3540 genMult (iCode * ic)
3542 operand *left = IC_LEFT (ic);
3543 operand *right = IC_RIGHT (ic);
3544 operand *result = IC_RESULT (ic);
3546 D(emitcode ("; genMult",""));
3548 /* assign the amsops */
3549 aopOp (left, ic, FALSE);
3550 aopOp (right, ic, FALSE);
3551 aopOp (result, ic, TRUE);
3553 /* special cases first */
3554 /* if both are of size == 1 */
3555 // if (getSize(operandType(left)) == 1 &&
3556 // getSize(operandType(right)) == 1)
3557 if (AOP_SIZE (left) == 1 &&
3558 AOP_SIZE (right) == 1)
3560 genMultOneByte (left, right, result);
3564 /* should have been converted to function call */
3565 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3566 getSize(OP_SYMBOL(right)->type));
3567 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3572 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3573 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3574 freeAsmop (result, NULL, ic, TRUE);
3577 /*-----------------------------------------------------------------*/
3578 /* genDivOneByte : 8 bit division */
3579 /*-----------------------------------------------------------------*/
3581 genDivOneByte (operand * left,
3585 sym_link *opetype = operandType (result);
3587 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3589 bool negLiteral = FALSE;
3591 D(emitcode ("; genDivOneByte",""));
3593 size = AOP_SIZE (result);
3594 /* signed or unsigned */
3595 if (SPEC_USIGN (opetype))
3597 /* unsigned is easy */
3598 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3599 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3600 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3601 emitcode ("div", "");
3602 hc08_dirtyReg (hc08_reg_a, FALSE);
3603 hc08_dirtyReg (hc08_reg_h, FALSE);
3604 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3605 hc08_freeReg (hc08_reg_a);
3606 hc08_freeReg (hc08_reg_x);
3607 hc08_freeReg (hc08_reg_h);
3611 /* signed is a little bit more difficult */
3614 emitcode ("clr", "1,s");
3616 tlbl1 = newiTempLabel (NULL);
3617 tlbl2 = newiTempLabel (NULL);
3618 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3619 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3620 emitBranch ("bpl", tlbl1);
3621 emitcode ("inc", "1,s");
3622 rmwWithReg ("neg", hc08_reg_a);
3623 emitBranch ("bcc", tlbl2);
3624 rmwWithReg ("inc", hc08_reg_x);
3626 rmwWithReg ("neg", hc08_reg_x);
3627 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3630 if (AOP_TYPE(right)==AOP_LIT)
3632 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3633 /* AND literal negative */
3635 emitcode ("ldx", "#0x%02x", -val);
3638 emitcode ("ldx", "#0x%02x", val);
3640 hc08_useReg (hc08_reg_x);
3644 tlbl3 = newiTempLabel (NULL);
3645 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3646 emitBranch ("bpl", tlbl3);
3647 emitcode ("inc", "1,s");
3648 rmwWithReg ("neg", hc08_reg_x);
3652 emitcode ("div", "");
3653 hc08_dirtyReg (hc08_reg_x, FALSE);
3654 hc08_dirtyReg (hc08_reg_a, FALSE);
3655 hc08_dirtyReg (hc08_reg_h, FALSE);
3657 tlbl4 = newiTempLabel (NULL);
3658 emitcode ("dec", "1,s");
3660 emitBranch ("bne", tlbl4);
3662 emitBranch ("beq", tlbl4);
3663 rmwWithReg ("neg", hc08_reg_a);
3667 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3668 hc08_freeReg (hc08_reg_a);
3669 hc08_freeReg (hc08_reg_x);
3670 hc08_freeReg (hc08_reg_h);
3675 /*-----------------------------------------------------------------*/
3676 /* genDiv - generates code for division */
3677 /*-----------------------------------------------------------------*/
3681 operand *left = IC_LEFT (ic);
3682 operand *right = IC_RIGHT (ic);
3683 operand *result = IC_RESULT (ic);
3685 D(emitcode ("; genDiv",""));
3687 /* assign the amsops */
3688 aopOp (left, ic, FALSE);
3689 aopOp (right, ic, FALSE);
3690 aopOp (result, ic, TRUE);
3692 /* special cases first */
3693 /* if both are of size == 1 */
3694 if (AOP_SIZE (left) <= 2 &&
3695 AOP_SIZE (right) == 1)
3697 genDivOneByte (left, right, result);
3701 /* should have been converted to function call */
3704 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3705 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3706 freeAsmop (result, NULL, ic, TRUE);
3709 /*-----------------------------------------------------------------*/
3710 /* genModOneByte : 8 bit modulus */
3711 /*-----------------------------------------------------------------*/
3713 genModOneByte (operand * left,
3717 sym_link *opetype = operandType (result);
3719 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3721 bool negLiteral = FALSE;
3723 D(emitcode ("; genModOneByte",""));
3725 size = AOP_SIZE (result);
3726 /* signed or unsigned */
3727 if (SPEC_USIGN (opetype))
3729 /* unsigned is easy */
3730 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3731 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3732 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3733 emitcode ("div", "");
3734 hc08_dirtyReg (hc08_reg_a, FALSE);
3735 hc08_dirtyReg (hc08_reg_h, FALSE);
3736 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3737 hc08_freeReg (hc08_reg_a);
3738 hc08_freeReg (hc08_reg_x);
3739 hc08_freeReg (hc08_reg_h);
3743 /* signed is a little bit more difficult */
3746 emitcode ("clr", "1,s");
3748 tlbl1 = newiTempLabel (NULL);
3749 tlbl2 = newiTempLabel (NULL);
3750 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3751 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3752 emitBranch ("bpl", tlbl1);
3753 emitcode ("inc", "1,s");
3754 rmwWithReg ("neg", hc08_reg_a);
3755 emitBranch ("bcc", tlbl2);
3756 rmwWithReg ("inc", hc08_reg_x);
3758 rmwWithReg ("neg", hc08_reg_x);
3759 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3762 if (AOP_TYPE(right)==AOP_LIT)
3764 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3765 /* AND literal negative */
3767 emitcode ("ldx", "#0x%02x", -val);
3770 emitcode ("ldx", "#0x%02x", val);
3772 hc08_useReg (hc08_reg_x);
3776 tlbl3 = newiTempLabel (NULL);
3777 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3778 emitBranch ("bpl", tlbl3);
3779 emitcode ("inc", "1,s");
3780 rmwWithReg ("neg", hc08_reg_x);
3784 emitcode ("div", "");
3785 hc08_dirtyReg (hc08_reg_x, FALSE);
3786 hc08_dirtyReg (hc08_reg_a, FALSE);
3787 hc08_dirtyReg (hc08_reg_h, FALSE);
3789 tlbl4 = newiTempLabel (NULL);
3790 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3791 emitcode ("dec", "1,s");
3793 emitBranch ("bne", tlbl4);
3795 emitBranch ("beq", tlbl4);
3796 rmwWithReg ("neg", hc08_reg_a);
3800 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3801 hc08_freeReg (hc08_reg_a);
3802 hc08_freeReg (hc08_reg_x);
3803 hc08_freeReg (hc08_reg_h);
3807 /*-----------------------------------------------------------------*/
3808 /* genMod - generates code for division */
3809 /*-----------------------------------------------------------------*/
3813 operand *left = IC_LEFT (ic);
3814 operand *right = IC_RIGHT (ic);
3815 operand *result = IC_RESULT (ic);
3817 D(emitcode ("; genMod",""));
3819 /* assign the amsops */
3820 aopOp (left, ic, FALSE);
3821 aopOp (right, ic, FALSE);
3822 aopOp (result, ic, TRUE);
3824 /* special cases first */
3825 /* if both are of size == 1 */
3826 if (AOP_SIZE (left) <= 2 &&
3827 AOP_SIZE (right) == 1)
3829 genModOneByte (left, right, result);
3833 /* should have been converted to function call */
3837 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3838 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3839 freeAsmop (result, NULL, ic, TRUE);
3842 /*-----------------------------------------------------------------*/
3843 /* genIfxJump :- will create a jump depending on the ifx */
3844 /*-----------------------------------------------------------------*/
3846 genIfxJump (iCode * ic, char *jval)
3849 symbol *tlbl = newiTempLabel (NULL);
3852 D(emitcode ("; genIfxJump",""));
3854 /* if true label then we jump if condition
3858 jlbl = IC_TRUE (ic);
3859 if (!strcmp (jval, "a"))
3861 else if (!strcmp (jval, "c"))
3868 /* false label is present */
3869 jlbl = IC_FALSE (ic);
3870 if (!strcmp (jval, "a"))
3872 else if (!strcmp (jval, "c"))
3877 emitBranch (inst, tlbl);
3878 emitBranch ("jmp", jlbl);
3881 /* mark the icode as generated */
3885 /*-----------------------------------------------------------------*/
3886 /* genCmp :- greater or less than comparison */
3887 /*-----------------------------------------------------------------*/
3889 genCmp (operand * left, operand * right,
3890 operand * result, iCode * ifx, int sign, iCode *ic)
3892 int size, offset = 0;
3893 unsigned long lit = 0L;
3895 bool needpula = FALSE;
3897 D(emitcode ("; genCmp",""));
3899 /* subtract right from left if at the
3900 end the carry flag is set then we know that
3901 left is greater than right */
3902 size = max (AOP_SIZE (left), AOP_SIZE (right));
3904 if (AOP_TYPE (right) == AOP_LIT)
3906 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3907 /* optimize if(x < 0) or if(x >= 0) */
3916 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3917 emitcode ("rola", "");
3918 hc08_useReg (hc08_reg_a);
3926 && ((AOP_TYPE (right) == AOP_LIT) ||
3927 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3928 && hc08_reg_hx->isFree)
3930 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3931 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3932 hc08_freeReg (hc08_reg_hx);
3943 loadRegFromAop (hc08_reg_a, AOP (left), offset);
3944 accopWithAop (sub, AOP (right), offset);
3945 hc08_freeReg (hc08_reg_a);
3951 freeAsmop (right, NULL, ic, TRUE);
3952 freeAsmop (left, NULL, ic, TRUE);
3953 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3959 /* if the result is used in the next
3960 ifx conditional branch then generate
3961 code a little differently */
3964 pullOrFreeReg(hc08_reg_a,needpula);
3965 genIfxJump (ifx, sign ? "s" : "c");
3972 pullOrFreeReg(hc08_reg_a,needpula);
3976 /*-----------------------------------------------------------------*/
3977 /* genCmpGt :- greater than comparison */
3978 /*-----------------------------------------------------------------*/
3980 genCmpGt (iCode * ic, iCode * ifx)
3982 operand *left, *right, *result;
3983 sym_link *letype, *retype;
3986 D(emitcode ("; genCmpGt",""));
3988 result = IC_RESULT (ic);
3989 left = IC_LEFT (ic);
3990 right = IC_RIGHT (ic);
3992 letype = getSpec (operandType (left));
3993 retype = getSpec (operandType (right));
3994 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3995 /* assign the amsops */
3996 aopOp (left, ic, FALSE);
3997 aopOp (right, ic, FALSE);
3998 aopOp (result, ic, TRUE);
4000 genCmp (right, left, result, ifx, sign,ic);
4002 freeAsmop (result, NULL, ic, TRUE);
4005 /*-----------------------------------------------------------------*/
4006 /* genCmpLt - less than comparisons */
4007 /*-----------------------------------------------------------------*/
4009 genCmpLt (iCode * ic, iCode * ifx)
4011 operand *left, *right, *result;
4012 sym_link *letype, *retype;
4015 D(emitcode ("; genCmpLt",""));
4017 result = IC_RESULT (ic);
4018 left = IC_LEFT (ic);
4019 right = IC_RIGHT (ic);
4021 letype = getSpec (operandType (left));
4022 retype = getSpec (operandType (right));
4023 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4025 /* assign the amsops */
4026 aopOp (left, ic, FALSE);
4027 aopOp (right, ic, FALSE);
4028 aopOp (result, ic, TRUE);
4030 genCmp (left, right, result, ifx, sign,ic);
4032 freeAsmop (result, NULL, ic, TRUE);
4035 /*-----------------------------------------------------------------*/
4036 /* - compare and branch if not equal */
4037 /*-----------------------------------------------------------------*/
4039 gencbneshort (operand * left, operand * right, symbol * lbl)
4041 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4043 unsigned long lit = 0L;
4045 /* if the left side is a literal or
4046 if the right is in a pointer register and left
4048 if (AOP_TYPE (left) == AOP_LIT)
4054 if (AOP_TYPE (right) == AOP_LIT)
4055 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4059 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4060 accopWithAop ("cmp", AOP (right), offset);
4061 hc08_useReg (hc08_reg_a);
4062 hc08_freeReg (hc08_reg_a);
4063 emitBranch ("bne", lbl);
4069 /*-----------------------------------------------------------------*/
4070 /* gencjne - compare and jump if not equal */
4071 /*-----------------------------------------------------------------*/
4073 gencjne (operand * left, operand * right, symbol * lbl)
4075 symbol *tlbl = newiTempLabel (NULL);
4077 gencbneshort (left, right, lbl);
4079 loadRegFromConst (hc08_reg_a, one);
4080 emitBranch ("bra", tlbl);
4082 loadRegFromConst (hc08_reg_a, zero);
4085 hc08_useReg(hc08_reg_a);
4086 hc08_freeReg(hc08_reg_a);
4089 /*-----------------------------------------------------------------*/
4090 /* genCmpEq - generates code for equal to */
4091 /*-----------------------------------------------------------------*/
4093 genCmpEq (iCode * ic, iCode * ifx)
4095 operand *left, *right, *result;
4097 D(emitcode ("; genCmpEq",""));
4099 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4100 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4101 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4103 /* if literal, literal on the right or
4104 if the right is in a pointer register and left
4106 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4108 operand *t = IC_RIGHT (ic);
4109 IC_RIGHT (ic) = IC_LEFT (ic);
4113 if (ifx && !AOP_SIZE (result))
4116 tlbl = newiTempLabel (NULL);
4117 gencbneshort (left, right, tlbl);
4120 emitBranch ("jmp", IC_TRUE (ifx));
4125 symbol *lbl = newiTempLabel (NULL);
4126 emitBranch ("bra", lbl);
4128 emitBranch ("jmp", IC_FALSE (ifx));
4132 /* mark the icode as generated */
4137 gencjne (left, right, newiTempLabel (NULL));
4138 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4140 storeRegToAop (hc08_reg_a, AOP (result), 0);
4145 genIfxJump (ifx, "a");
4148 /* if the result is used in an arithmetic operation
4149 then put the result in place */
4150 if (AOP_TYPE (result) != AOP_CRY)
4154 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4155 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4156 freeAsmop (result, NULL, ic, TRUE);
4159 /*-----------------------------------------------------------------*/
4160 /* ifxForOp - returns the icode containing the ifx for operand */
4161 /*-----------------------------------------------------------------*/
4163 ifxForOp (operand * op, iCode * ic)
4165 /* if true symbol then needs to be assigned */
4166 if (IS_TRUE_SYMOP (op))
4169 /* if this has register type condition and
4170 the next instruction is ifx with the same operand
4171 and live to of the operand is upto the ifx only then */
4173 ic->next->op == IFX &&
4174 IC_COND (ic->next)->key == op->key &&
4175 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4182 genPointerGetSetOfs (iCode *ic)
4184 iCode *lic = ic->next;
4190 /* Make sure we have a next iCode */
4191 emitcode("","; checking lic");
4195 /* Make sure the result of the addition is an iCode */
4196 emitcode("","; checking IS_ITEMP");
4197 if (!IS_ITEMP (IC_RESULT (ic)))
4200 /* Make sure the next iCode is a pointer set or get */
4201 pset = POINTER_SET(lic);
4202 pget = POINTER_GET(lic);
4203 emitcode("","; pset=%d, pget=%d",pset,pget);
4207 emitcode("", "; checking pset operandsEqu");
4208 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4211 emitcode("", "; checking pget operandsEqu");
4212 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4215 emitcode("", "; checking IS_SYMOP");
4216 if (!IS_SYMOP (IC_LEFT (ic)))
4219 emitcode("", "; checking !IS_TRUE_SYMOP");
4220 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4223 sym = OP_SYMBOL (IC_LEFT (ic));
4225 emitcode("", "; checking remat");
4231 D(emitcode ("; genPointerGetOfs",""));
4232 aopOp (IC_LEFT(ic), ic, FALSE);
4233 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4234 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4236 aopOp (IC_RIGHT(ic), ic, FALSE);
4237 aopOp (IC_RESULT(lic), lic, FALSE);
4240 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4241 size = AOP_SIZE (IC_RESULT(lic));
4242 derefaop->size = size;
4247 emitcode ("lda", "%s,x",
4248 aopAdrStr (derefaop, offset, TRUE));
4249 hc08_useReg (hc08_reg_a);
4250 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4251 hc08_freeReg (hc08_reg_a);
4255 hc08_freeReg (hc08_reg_hx);
4257 freeAsmop (NULL, derefaop, ic, TRUE);
4258 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4259 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4266 D(emitcode ("; genPointerSetOfs",""));
4267 aopOp (IC_LEFT(ic), ic, FALSE);
4268 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4269 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4271 aopOp (IC_RIGHT(ic), ic, FALSE);
4272 aopOp (IC_RIGHT(lic), lic, FALSE);
4275 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4276 size = AOP_SIZE (IC_RIGHT(lic));
4277 derefaop->size = size;
4282 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4283 emitcode ("sta", "%s,x",
4284 aopAdrStr (derefaop, offset, TRUE));
4285 hc08_freeReg (hc08_reg_a);
4290 hc08_freeReg (hc08_reg_hx);
4292 freeAsmop (NULL, derefaop, ic, TRUE);
4293 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4294 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4303 /*-----------------------------------------------------------------*/
4304 /* hasInc - operand is incremented before any other use */
4305 /*-----------------------------------------------------------------*/
4307 hasInc (operand *op, iCode *ic,int osize)
4309 sym_link *type = operandType(op);
4310 sym_link *retype = getSpec (type);
4311 iCode *lic = ic->next;
4314 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4315 if (!IS_SYMOP(op)) return NULL;
4317 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4318 if (IS_AGGREGATE(type->next)) return NULL;
4319 if (osize != (isize = getSize(type->next))) return NULL;
4322 /* if operand of the form op = op + <sizeof *op> */
4323 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4324 isOperandEqual(IC_RESULT(lic),op) &&
4325 isOperandLiteral(IC_RIGHT(lic)) &&
4326 operandLitValue(IC_RIGHT(lic)) == isize) {
4329 /* if the operand used or deffed */
4330 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4333 /* if GOTO or IFX */
4334 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4340 /*-----------------------------------------------------------------*/
4341 /* genAndOp - for && operation */
4342 /*-----------------------------------------------------------------*/
4344 genAndOp (iCode * ic)
4346 operand *left, *right, *result;
4347 symbol *tlbl, *tlbl0;
4349 D(emitcode ("; genAndOp",""));
4351 /* note here that && operations that are in an
4352 if statement are taken away by backPatchLabels
4353 only those used in arthmetic operations remain */
4354 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4355 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4356 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4358 tlbl = newiTempLabel (NULL);
4359 tlbl0 = newiTempLabel (NULL);
4361 asmopToBool (AOP (left), FALSE);
4362 emitBranch ("beq", tlbl0);
4363 asmopToBool (AOP (right), FALSE);
4364 emitBranch ("beq", tlbl0);
4365 loadRegFromConst (hc08_reg_a,one);
4366 emitBranch ("bra", tlbl);
4368 loadRegFromConst (hc08_reg_a,zero);
4371 hc08_useReg (hc08_reg_a);
4372 hc08_freeReg (hc08_reg_a);
4374 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4376 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4377 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4378 freeAsmop (result, NULL, ic, TRUE);
4382 /*-----------------------------------------------------------------*/
4383 /* genOrOp - for || operation */
4384 /*-----------------------------------------------------------------*/
4386 genOrOp (iCode * ic)
4388 operand *left, *right, *result;
4389 symbol *tlbl, *tlbl0;
4391 D(emitcode ("; genOrOp",""));
4393 /* note here that || operations that are in an
4394 if statement are taken away by backPatchLabels
4395 only those used in arthmetic operations remain */
4396 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4397 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4398 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4400 tlbl = newiTempLabel (NULL);
4401 tlbl0 = newiTempLabel (NULL);
4403 asmopToBool (AOP (left), FALSE);
4404 emitBranch ("bne", tlbl0);
4405 asmopToBool (AOP (right), FALSE);
4406 emitBranch ("bne", tlbl0);
4407 loadRegFromConst (hc08_reg_a,zero);
4408 emitBranch ("bra", tlbl);
4410 loadRegFromConst (hc08_reg_a,one);
4413 hc08_useReg (hc08_reg_a);
4414 hc08_freeReg (hc08_reg_a);
4416 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4419 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4420 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4421 freeAsmop (result, NULL, ic, TRUE);
4424 /*-----------------------------------------------------------------*/
4425 /* isLiteralBit - test if lit == 2^n */
4426 /*-----------------------------------------------------------------*/
4428 isLiteralBit (unsigned long lit)
4430 unsigned long pw[32] =
4431 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4432 0x100L, 0x200L, 0x400L, 0x800L,
4433 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4434 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4435 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4436 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4437 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4440 for (idx = 0; idx < 32; idx++)
4447 /*-----------------------------------------------------------------*/
4448 /* continueIfTrue - */
4449 /*-----------------------------------------------------------------*/
4451 continueIfTrue (iCode * ic)
4454 emitBranch ("jmp", IC_TRUE (ic));
4458 /*-----------------------------------------------------------------*/
4460 /*-----------------------------------------------------------------*/
4462 jumpIfTrue (iCode * ic)
4465 emitBranch ("jmp", IC_FALSE (ic));
4469 /*-----------------------------------------------------------------*/
4470 /* jmpTrueOrFalse - */
4471 /*-----------------------------------------------------------------*/
4473 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4475 // ugly but optimized by peephole
4478 symbol *nlbl = newiTempLabel (NULL);
4479 emitBranch ("bra", nlbl);
4481 emitBranch ("jmp", IC_TRUE (ic));
4486 emitBranch ("jmp", IC_FALSE (ic));
4493 /*-----------------------------------------------------------------*/
4494 /* genAnd - code for and */
4495 /*-----------------------------------------------------------------*/
4497 genAnd (iCode * ic, iCode * ifx)
4499 operand *left, *right, *result;
4500 int size, offset = 0;
4501 unsigned long lit = 0L;
4502 unsigned long litinv;
4508 D(emitcode ("; genAnd",""));
4510 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4511 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4512 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4515 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4517 AOP_TYPE (left), AOP_TYPE (right));
4518 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4520 AOP_SIZE (left), AOP_SIZE (right));
4523 /* if left is a literal & right is not then exchange them */
4524 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4526 operand *tmp = right;
4531 /* if left is accumulator & right is not then exchange them */
4532 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4534 operand *tmp = right;
4540 if (AOP_TYPE (result) == AOP_CRY)
4543 wassertl (ifx, "AOP_CPY result without ifx");
4545 tlbl = newiTempLabel (NULL);
4546 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4550 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4551 if ((AOP_TYPE (right) == AOP_LIT)
4552 && (((lit >> (offset*8)) & 0xff) == 0xff))
4553 emitcode ("tsta","");
4555 accopWithAop ("and", AOP (right), offset);
4556 hc08_freeReg( hc08_reg_a);
4558 emitBranch ("bne", tlbl);
4562 genIfxJump (ifx, "a");
4568 size = AOP_SIZE (result);
4570 if (AOP_TYPE (right) == AOP_LIT)
4572 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4573 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4575 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4576 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4578 int bitpos = isLiteralBit(litinv)-1;
4579 emitcode ("bclr","#%d,%s",bitpos & 7,
4580 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4588 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4589 if ((AOP_TYPE (right) != AOP_LIT)
4590 || (((lit >> (offset*8)) & 0xff) != 0xff))
4591 accopWithAop ("and", AOP (right), offset);
4592 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4593 hc08_freeReg( hc08_reg_a);
4597 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4599 freeAsmop (result, NULL, ic, TRUE);
4602 /*-----------------------------------------------------------------*/
4603 /* genOr - code for or */
4604 /*-----------------------------------------------------------------*/
4606 genOr (iCode * ic, iCode * ifx)
4608 operand *left, *right, *result;
4609 int size, offset = 0;
4610 unsigned long lit = 0L;
4612 D(emitcode ("; genOr",""));
4614 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4615 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4616 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4619 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4621 AOP_TYPE (left), AOP_TYPE (right));
4622 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4624 AOP_SIZE (left), AOP_SIZE (right));
4627 /* if left is a literal & right is not then exchange them */
4628 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4630 operand *tmp = right;
4635 /* if left is accumulator & right is not then exchange them */
4636 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4638 operand *tmp = right;
4643 if (AOP_TYPE (result) == AOP_CRY)
4646 wassertl (ifx, "AOP_CPY result without ifx");
4648 tlbl = newiTempLabel (NULL);
4649 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4653 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4654 if ((AOP_TYPE (right) == AOP_LIT)
4655 && (((lit >> (offset*8)) & 0xff) == 0))
4656 emitcode ("tsta","");
4658 accopWithAop ("ora", AOP (right), offset);
4659 hc08_freeReg( hc08_reg_a);
4661 emitBranch ("bne", tlbl);
4665 genIfxJump (ifx, "a");
4671 if (AOP_TYPE (right) == AOP_LIT)
4672 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4674 size = AOP_SIZE (result);
4676 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4677 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4678 (AOP_TYPE (left) == AOP_DIR))
4680 int bitpos = isLiteralBit(lit)-1;
4681 emitcode ("bset","#%d,%s",bitpos & 7,
4682 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4689 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4690 accopWithAop ("ora", AOP (right), offset);
4691 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4692 hc08_freeReg( hc08_reg_a);
4697 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4698 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4699 freeAsmop (result, NULL, ic, TRUE);
4702 /*-----------------------------------------------------------------*/
4703 /* genXor - code for xclusive or */
4704 /*-----------------------------------------------------------------*/
4706 genXor (iCode * ic, iCode * ifx)
4708 operand *left, *right, *result;
4709 int size, offset = 0;
4710 unsigned long lit = 0L;
4712 D(emitcode ("; genXor",""));
4714 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4715 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4716 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4719 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4721 AOP_TYPE (left), AOP_TYPE (right));
4722 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4724 AOP_SIZE (left), AOP_SIZE (right));
4727 /* if left is a literal & right is not ||
4728 if left needs acc & right does not */
4729 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4731 operand *tmp = right;
4736 /* if left is accumulator & right is not then exchange them */
4737 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4739 operand *tmp = right;
4744 if (AOP_TYPE (result) == AOP_CRY)
4747 wassertl (ifx, "AOP_CPY result without ifx");
4749 tlbl = newiTempLabel (NULL);
4750 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4754 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4755 if ((AOP_TYPE (right) == AOP_LIT)
4756 && (((lit >> (offset*8)) & 0xff) == 0))
4757 emitcode ("tsta","");
4759 accopWithAop ("eor", AOP (right), offset);
4760 hc08_freeReg( hc08_reg_a);
4762 emitBranch ("bne", tlbl);
4766 genIfxJump (ifx, "a");
4772 if (AOP_TYPE (right) == AOP_LIT)
4773 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4775 size = AOP_SIZE (result);
4779 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4780 accopWithAop ("eor", AOP (right), offset);
4781 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4782 hc08_freeReg( hc08_reg_a);
4786 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4787 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4788 freeAsmop (result, NULL, ic, TRUE);
4792 emitinline (iCode * ic, char *inlin)
4798 symbol *sym, *tempsym;
4807 while (isalnum(*inlin) || (*inlin == '_'))
4811 //printf("Found possible symbol '%s'\n",symname);
4812 tempsym = newSymbol (symname, ic->level);
4813 tempsym->block = ic->block;
4814 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4823 aop = aopForSym (ic, sym, FALSE);
4824 l = aopAdrStr (aop, aop->size - 1, TRUE);
4828 if (!sym->allocreq && !sym->ismyparm)
4830 werror (E_ID_UNDEF, sym->name);
4832 " Add 'volatile' to the variable declaration so that it\n"
4833 " can be referenced within inline assembly");
4835 //printf("Replacing with '%s'\n",l);
4839 if ((2+bp-buffer)>sizeof(buffer))
4848 if ((2+bp-buffer)>sizeof(buffer))
4855 if ((2+bp-buffer)>sizeof(buffer))
4856 fprintf(stderr, "Inline assembly buffer overflow\n");
4858 //printf("%s\n",buffer);
4859 emitcode (buffer,"");
4863 /*-----------------------------------------------------------------*/
4864 /* genInline - write the inline code out */
4865 /*-----------------------------------------------------------------*/
4867 genInline (iCode * ic)
4869 char *buffer, *bp, *bp1;
4871 D(emitcode ("; genInline",""));
4873 _G.inLine += (!options.asmpeep);
4875 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4876 strcpy (buffer, IC_INLINE (ic));
4878 /* emit each line as a code */
4884 /* emitcode (bp1, ""); */
4885 emitinline (ic, bp1);
4904 /* emitcode (bp1, ""); */
4905 emitinline (ic, bp1);
4907 /* emitcode("",buffer); */
4908 _G.inLine -= (!options.asmpeep);
4911 /*-----------------------------------------------------------------*/
4912 /* genRRC - rotate right with carry */
4913 /*-----------------------------------------------------------------*/
4917 operand *left, *result;
4918 int size, offset = 0;
4919 bool needpula = FALSE;
4920 bool resultInA = FALSE;
4923 D(emitcode ("; genRRC",""));
4925 /* rotate right with carry */
4926 left = IC_LEFT (ic);
4927 result = IC_RESULT (ic);
4928 aopOp (left, ic, FALSE);
4929 aopOp (result, ic, FALSE);
4931 if ((AOP_TYPE (result) == AOP_REG)
4932 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4935 size = AOP_SIZE (result);
4939 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4943 rmwWithAop (shift, AOP (result), offset--);
4951 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4952 rmwWithReg (shift, hc08_reg_a);
4953 storeRegToAop (hc08_reg_a, AOP (result), offset--);
4954 hc08_freeReg (hc08_reg_a);
4959 if ((!hc08_reg_a->isFree) || resultInA)
4961 pushReg (hc08_reg_a, TRUE);
4965 /* now we need to put the carry into the
4966 highest order byte of the result */
4967 offset = AOP_SIZE (result) - 1;
4968 emitcode ("clra","");
4969 emitcode ("rora","");
4970 hc08_dirtyReg (hc08_reg_a, FALSE);
4973 emitcode ("ora", "1,s");
4974 emitcode ("ais", "#1");
4975 hc08_dirtyReg (hc08_reg_a, FALSE);
4979 accopWithAop ("ora", AOP (result), offset);
4980 storeRegToAop (hc08_reg_a, AOP (result), offset);
4982 pullOrFreeReg (hc08_reg_a, needpula);
4984 freeAsmop (left, NULL, ic, TRUE);
4985 freeAsmop (result, NULL, ic, TRUE);
4988 /*-----------------------------------------------------------------*/
4989 /* genRLC - generate code for rotate left with carry */
4990 /*-----------------------------------------------------------------*/
4994 operand *left, *result;
4995 int size, offset = 0;
4997 bool resultInA = FALSE;
4998 bool needpula = FALSE;
5000 D(emitcode ("; genRLC",""));
5002 /* rotate right with carry */
5003 left = IC_LEFT (ic);
5004 result = IC_RESULT (ic);
5005 aopOp (left, ic, FALSE);
5006 aopOp (result, ic, FALSE);
5008 if ((AOP_TYPE (result) == AOP_REG)
5009 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5012 size = AOP_SIZE (result);
5016 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5020 rmwWithAop (shift, AOP (result), offset--);
5028 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5029 rmwWithReg (shift, hc08_reg_a);
5030 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5031 hc08_freeReg (hc08_reg_a);
5036 if ((!hc08_reg_a->isFree) || resultInA)
5038 pushReg (hc08_reg_a, TRUE);
5042 /* now we need to put the carry into the
5043 lowest order byte of the result */
5045 emitcode ("clra","");
5046 emitcode ("rola","");
5047 hc08_dirtyReg (hc08_reg_a, FALSE);
5050 emitcode ("ora", "1,s");
5051 emitcode ("ais", "#1");
5052 hc08_dirtyReg (hc08_reg_a, FALSE);
5056 accopWithAop ("ora", AOP (result), offset);
5057 storeRegToAop (hc08_reg_a, AOP (result), offset);
5059 pullOrFreeReg (hc08_reg_a, needpula);
5061 freeAsmop (left, NULL, ic, TRUE);
5062 freeAsmop (result, NULL, ic, TRUE);
5065 /*-----------------------------------------------------------------*/
5066 /* genGetHbit - generates code get highest order bit */
5067 /*-----------------------------------------------------------------*/
5069 genGetHbit (iCode * ic)
5071 operand *left, *result;
5073 D(emitcode ("; genGetHbit",""));
5075 left = IC_LEFT (ic);
5076 result = IC_RESULT (ic);
5077 aopOp (left, ic, FALSE);
5078 aopOp (result, ic, FALSE);
5080 /* get the highest order byte into a */
5081 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5082 emitcode ("rola", "");
5083 emitcode ("clra", "");
5084 emitcode ("rola", "");
5085 hc08_dirtyReg (hc08_reg_a, FALSE);
5086 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5087 hc08_freeReg (hc08_reg_a);
5089 freeAsmop (left, NULL, ic, TRUE);
5090 freeAsmop (result, NULL, ic, TRUE);
5093 /*-----------------------------------------------------------------*/
5094 /* genSwap - generates code to swap nibbles or bytes */
5095 /*-----------------------------------------------------------------*/
5097 genSwap (iCode * ic)
5099 operand *left, *result;
5101 D(emitcode ("; genSwap",""));
5103 left = IC_LEFT (ic);
5104 result = IC_RESULT (ic);
5105 aopOp (left, ic, FALSE);
5106 aopOp (result, ic, FALSE);
5108 switch (AOP_SIZE (left))
5110 case 1: /* swap nibbles in byte */
5111 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5112 emitcode ("nsa", "");
5113 hc08_dirtyReg (hc08_reg_a, FALSE);
5114 storeRegToAop (hc08_reg_a, AOP (result), 0);
5115 hc08_freeReg (hc08_reg_a);
5117 case 2: /* swap bytes in a word */
5118 if (operandsEqu (left, result))
5120 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5121 hc08_useReg (hc08_reg_a);
5122 transferAopAop (AOP (left), 1, AOP (result), 0);
5123 storeRegToAop (hc08_reg_a, AOP (result), 1);
5124 hc08_freeReg (hc08_reg_a);
5128 transferAopAop (AOP (left), 0, AOP (result), 1);
5129 transferAopAop (AOP (left), 1, AOP (result), 0);
5133 wassertl(FALSE, "unsupported SWAP operand size");
5136 freeAsmop (left, NULL, ic, TRUE);
5137 freeAsmop (result, NULL, ic, TRUE);
5141 /*-----------------------------------------------------------------*/
5142 /* AccRol - rotate left accumulator by known count */
5143 /*-----------------------------------------------------------------*/
5145 AccRol (int shCount)
5147 shCount &= 0x0007; // shCount : 0..7
5154 emitcode ("rola", ""); /* 1 cycle */
5157 emitcode ("rola", ""); /* 1 cycle */
5158 emitcode ("rola", ""); /* 1 cycle */
5161 emitcode ("nsa", "");
5162 emitcode ("rora", "");
5165 emitcode ("nsa", ""); /* 3 cycles */
5168 emitcode ("nsa", ""); /* 3 cycles */
5169 emitcode ("rola", ""); /* 1 cycle */
5172 emitcode ("nsa", ""); /* 3 cycles */
5173 emitcode ("rola", ""); /* 1 cycle */
5174 emitcode ("rola", ""); /* 1 cycle */
5177 emitcode ("nsa", ""); /* 3 cycles */
5178 emitcode ("rola", ""); /* 1 cycle */
5179 emitcode ("rola", ""); /* 1 cycle */
5180 emitcode ("rola", ""); /* 1 cycle */
5187 /*-----------------------------------------------------------------*/
5188 /* AccLsh - left shift accumulator by known count */
5189 /*-----------------------------------------------------------------*/
5191 AccLsh (int shCount)
5195 shCount &= 0x0007; // shCount : 0..7
5197 /* Shift counts of 4 and 5 are currently optimized for code size. */
5198 /* Falling through to the unrolled loop would be optimal for code speed. */
5199 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5203 accopWithMisc ("nsa", "");
5204 accopWithMisc ("and", "#0xf0");
5205 /* total: 5 cycles, 3 bytes */
5208 accopWithMisc ("nsa", "");
5209 accopWithMisc ("and", "#0xf0");
5210 accopWithMisc ("lsla", "");
5211 /* total: 6 cycles, 4 bytes */
5214 accopWithMisc ("rora", "");
5215 accopWithMisc ("rora", "");
5216 accopWithMisc ("rora", "");
5217 accopWithMisc ("and", "#0xc0");
5218 /* total: 5 cycles, 5 bytes */
5221 accopWithMisc ("rora", "");
5222 accopWithMisc ("clra", "");
5223 accopWithMisc ("rora", "");
5224 /* total: 3 cycles, 3 bytes */
5228 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5229 /* the fastest (shCount<6) and shortest (shCount<4). */
5230 for (i=0;i<shCount;i++)
5231 accopWithMisc ("lsla", "");
5235 /*-----------------------------------------------------------------*/
5236 /* AccSRsh - signed right shift accumulator by known count */
5237 /*-----------------------------------------------------------------*/
5239 AccSRsh (int shCount)
5243 shCount &= 0x0007; // shCount : 0..7
5247 accopWithMisc ("rola", "");
5248 accopWithMisc ("clra", "");
5249 accopWithMisc ("sbc", zero);
5250 /* total: 4 cycles, 4 bytes */
5254 for (i=0;i<shCount;i++)
5255 accopWithMisc ("asra", "");
5258 /*-----------------------------------------------------------------*/
5259 /* AccRsh - right shift accumulator by known count */
5260 /*-----------------------------------------------------------------*/
5262 AccRsh (int shCount, bool sign)
5272 shCount &= 0x0007; // shCount : 0..7
5274 /* Shift counts of 4 and 5 are currently optimized for code size. */
5275 /* Falling through to the unrolled loop would be optimal for code speed. */
5276 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5280 accopWithMisc ("nsa", "");
5281 accopWithMisc ("and", "#0x0f");
5282 /* total: 5 cycles, 3 bytes */
5285 accopWithMisc ("nsa", "");
5286 accopWithMisc ("and", "#0x0f");
5287 accopWithMisc ("lsra", "");
5288 /* total: 6 cycles, 4 bytes */
5291 accopWithMisc ("rola", "");
5292 accopWithMisc ("rola", "");
5293 accopWithMisc ("rola", "");
5294 accopWithMisc ("and", "#0x03");
5295 /* total: 5 cycles, 5 bytes */
5298 accopWithMisc ("rola", "");
5299 accopWithMisc ("clra", "");
5300 accopWithMisc ("rola", "");
5301 /* total: 3 cycles, 3 bytes */
5305 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5306 /* the fastest (shCount<6) and shortest (shCount<4). */
5307 for (i=0;i<shCount;i++)
5308 accopWithMisc ("lsra", "");
5312 /*-----------------------------------------------------------------*/
5313 /* XAccLsh - left shift register pair XA by known count */
5314 /*-----------------------------------------------------------------*/
5316 XAccLsh (int shCount)
5320 shCount &= 0x000f; // shCount : 0..15
5325 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5326 loadRegFromConst (hc08_reg_a, zero);
5330 /* if we can beat 2n cycles or bytes for some special case, do it here */
5334 /* bytes cycles reg x reg a carry
5335 ** abcd efgh ijkl mnop ?
5336 ** lsrx 1 1 0abc defg ijkl mnop h
5337 ** rora 1 1 0abc defg hijk lmno p
5338 ** tax 1 1 hijk lmno hijk lmno p
5339 ** clra 1 1 hijk lmno 0000 0000 p
5340 ** rora 1 1 hijk lmno p000 0000 0
5341 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5343 rmwWithReg ("lsr", hc08_reg_x);
5344 rmwWithReg ("ror", hc08_reg_a);
5345 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5346 loadRegFromConst (hc08_reg_a, zero);
5347 rmwWithReg ("ror", hc08_reg_a);
5354 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5355 /* the fastest and shortest. */
5356 for (i=0;i<shCount;i++)
5358 rmwWithReg ("lsl", hc08_reg_a);
5359 rmwWithReg ("rol", hc08_reg_x);
5363 /*-----------------------------------------------------------------*/
5364 /* XAccSRsh - signed right shift register pair XA by known count */
5365 /*-----------------------------------------------------------------*/
5367 XAccSRsh (int shCount)
5371 shCount &= 0x000f; // shCount : 0..7
5373 /* if we can beat 2n cycles or bytes for some special case, do it here */
5377 /* bytes cycles reg x reg a carry
5378 ** abcd efgh ijkl mnop ?
5379 ** lslx 1 1 bcde fgh0 ijkl mnop a
5380 ** clra 1 1 bcde fgh0 0000 0000 a
5381 ** rola 1 1 bcde fgh0 0000 000a 0
5382 ** nega 1 1 bcde fgh0 aaaa aaaa a
5383 ** tax 1 1 aaaa aaaa aaaa aaaa a
5384 ** total: 5 cycles, 5 bytes
5386 rmwWithReg ("lsl", hc08_reg_x);
5387 loadRegFromConst (hc08_reg_a, zero);
5388 rmwWithReg ("rol", hc08_reg_a);
5389 rmwWithReg ("neg", hc08_reg_a);
5390 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5400 /* bytes cycles reg x reg a carry
5401 ** abcd efgh ijkl mnop ?
5402 ** txa 1 1 abcd efgh abcd efgh ?
5403 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5404 ** lsla 1 1 abcd efgh ???? ???? a
5405 ** clrx 1 1 0000 0000 ???? ???? a
5406 ** rolx 1 1 0000 000a ???? ???? 0
5407 ** negx 1 1 aaaa aaaa ???? ???? a
5408 ** rora 1 1 aaaa aaaa LSBresult 0
5409 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5411 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5412 AccSRsh (shCount-8);
5413 rmwWithReg ("lsl", hc08_reg_a);
5414 loadRegFromConst (hc08_reg_x, zero);
5415 rmwWithReg ("rol", hc08_reg_x);
5416 rmwWithReg ("neg", hc08_reg_x);
5417 rmwWithReg ("ror", hc08_reg_a);
5424 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5425 /* the fastest and shortest. */
5426 for (i=0;i<shCount;i++)
5428 rmwWithReg ("asr", hc08_reg_x);
5429 rmwWithReg ("ror", hc08_reg_a);
5433 /*-----------------------------------------------------------------*/
5434 /* XAccRsh - right shift register pair XA by known count */
5435 /*-----------------------------------------------------------------*/
5437 XAccRsh (int shCount, bool sign)
5447 shCount &= 0x000f; // shCount : 0..f
5449 /* if we can beat 2n cycles or bytes for some special case, do it here */
5453 /* bytes cycles reg x reg a carry
5454 ** abcd efgh ijkl mnop ?
5455 ** clra 1 1 abcd efgh 0000 0000 a
5456 ** lslx 1 1 bcde fgh0 0000 0000 a
5457 ** rola 1 1 bcde fgh0 0000 000a 0
5458 ** clrx 1 1 0000 0000 0000 000a 0
5459 ** total: 4 cycles, 4 bytes
5461 loadRegFromConst (hc08_reg_x, zero);
5462 rmwWithReg ("lsl", hc08_reg_x);
5463 rmwWithReg ("rol", hc08_reg_a);
5464 loadRegFromConst (hc08_reg_a, zero);
5468 /* bytes cycles reg x reg a carry
5469 ** abcd efgh ijkl mnop ?
5470 ** clra 1 1 abcd efgh 0000 0000 a
5471 ** lslx 1 1 bcde fgh0 0000 0000 a
5472 ** rola 1 1 bcde fgh0 0000 000a 0
5473 ** lslx 1 1 cdef gh00 0000 000a b
5474 ** rola 1 1 cdef gh00 0000 00ab 0
5475 ** clrx 1 1 0000 0000 0000 00ab 0
5476 ** total: 6 cycles, 6 bytes
5478 loadRegFromConst (hc08_reg_x, zero);
5479 rmwWithReg ("lsl", hc08_reg_x);
5480 rmwWithReg ("rol", hc08_reg_a);
5481 rmwWithReg ("lsl", hc08_reg_x);
5482 rmwWithReg ("rol", hc08_reg_a);
5483 loadRegFromConst (hc08_reg_a, zero);
5492 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5493 AccRsh (shCount-8, FALSE);
5494 loadRegFromConst (hc08_reg_x, zero);
5498 /* bytes cycles reg x reg a carry
5499 ** abcd efgh ijkl mnop ?
5500 ** lsla 1 1 abcd efgh jklm nop0 i
5501 ** txa 1 1 abcd efgh abcd efgh i
5502 ** rola 1 1 abcd efgh bcde fghi a
5503 ** clrx 1 1 0000 0000 bcde fghi a
5504 ** rolx 1 1 0000 000a bcde fghi 0
5505 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5507 rmwWithReg ("lsl", hc08_reg_a);
5508 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5509 rmwWithReg ("rol", hc08_reg_a);
5510 loadRegFromConst (hc08_reg_x, zero);
5511 rmwWithReg ("rol", hc08_reg_x);
5514 /* bytes cycles reg x reg a carry
5515 ** abcd efgh ijkl mnop ?
5516 ** lsla 1 1 abcd efgh jklm nop0 i
5517 ** rolx 1 1 bcde fghi jklm nop0 a
5518 ** rola 1 1 bcde fghi klmn op0a j
5519 ** rolx 1 1 cdef ghij klmn op0a b
5520 ** rola 1 1 cdef ghij lmno p0ab k
5521 ** and #3 2 2 cdef ghij 0000 00ab k
5522 ** psha 1 2 cdef ghij 0000 00ab k
5523 ** txa 1 1 cdef ghij cdef ghij k
5524 ** pula 1 2 0000 00ab cdef ghij k
5525 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5531 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5532 /* the fastest and shortest. */
5533 for (i=0;i<shCount;i++)
5535 rmwWithReg ("lsr", hc08_reg_x);
5536 rmwWithReg ("ror", hc08_reg_a);
5543 /*-----------------------------------------------------------------*/
5544 /* shiftR1Left2Result - shift right one byte from left to result */
5545 /*-----------------------------------------------------------------*/
5547 shiftR1Left2Result (operand * left, int offl,
5548 operand * result, int offr,
5549 int shCount, int sign)
5551 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5552 /* shift right accumulator */
5553 AccRsh (shCount, sign);
5554 storeRegToAop (hc08_reg_a, AOP (result), offr);
5558 /*-----------------------------------------------------------------*/
5559 /* shiftL1Left2Result - shift left one byte from left to result */
5560 /*-----------------------------------------------------------------*/
5562 shiftL1Left2Result (operand * left, int offl,
5563 operand * result, int offr, int shCount)
5565 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5566 /* shift left accumulator */
5568 storeRegToAop (hc08_reg_a, AOP (result), offr);
5571 /*-----------------------------------------------------------------*/
5572 /* movLeft2Result - move byte from left to result */
5573 /*-----------------------------------------------------------------*/
5575 movLeft2Result (operand * left, int offl,
5576 operand * result, int offr, int sign)
5578 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5580 transferAopAop (AOP (left), offl, AOP (result), offr);
5585 /*-----------------------------------------------------------------*/
5586 /* shiftL2Left2Result - shift left two bytes from left to result */
5587 /*-----------------------------------------------------------------*/
5589 shiftL2Left2Result (operand * left, int offl,
5590 operand * result, int offr, int shCount)
5593 bool needpula = FALSE;
5594 bool needpulx = FALSE;
5596 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
5597 needpula = pushRegIfUsed (hc08_reg_a);
5600 if (!IS_AOP_XA (AOP (left)))
5601 needpulx = pushRegIfUsed (hc08_reg_x);
5605 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5610 rmwWithReg ("lsr", hc08_reg_x);
5611 rmwWithReg ("ror", hc08_reg_a);
5612 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5613 rmwWithReg ("clr", hc08_reg_a);
5614 rmwWithReg ("ror", hc08_reg_a);
5617 for (i=0; i<shCount; i++)
5619 rmwWithReg ("lsl", hc08_reg_a);
5620 rmwWithReg ("rol", hc08_reg_x);
5623 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5625 pullOrFreeReg (hc08_reg_x, needpulx);
5626 pullOrFreeReg (hc08_reg_a, needpula);
5632 /*-----------------------------------------------------------------*/
5633 /* shiftR2Left2Result - shift right two bytes from left to result */
5634 /*-----------------------------------------------------------------*/
5636 shiftR2Left2Result (operand * left, int offl,
5637 operand * result, int offr,
5638 int shCount, int sign)
5641 bool needpula = FALSE;
5642 bool needpulx = FALSE;
5644 needpula = pushRegIfUsed (hc08_reg_a);
5645 needpulx = pushRegIfUsed (hc08_reg_x);
5647 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5648 for (i=0; i<shCount; i++)
5651 rmwWithReg ("asr", hc08_reg_x);
5653 rmwWithReg ("lsr", hc08_reg_x);
5654 rmwWithReg ("ror", hc08_reg_a);
5656 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5658 pullOrFreeReg (hc08_reg_x, needpulx);
5659 pullOrFreeReg (hc08_reg_a, needpula);
5664 /*-----------------------------------------------------------------*/
5665 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5666 /*-----------------------------------------------------------------*/
5668 shiftLLeftOrResult (operand * left, int offl,
5669 operand * result, int offr, int shCount)
5671 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5672 /* shift left accumulator */
5674 /* or with result */
5675 accopWithAop ("ora", AOP (result), offr);
5676 /* back to result */
5677 storeRegToAop (hc08_reg_a, AOP (result), offr);
5678 hc08_freeReg (hc08_reg_a);
5682 /*-----------------------------------------------------------------*/
5683 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5684 /*-----------------------------------------------------------------*/
5686 shiftRLeftOrResult (operand * left, int offl,
5687 operand * result, int offr, int shCount)
5689 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5690 /* shift left accumulator */
5691 AccRsh (shCount, FALSE);
5692 /* or with result */
5693 accopWithAop ("ora", AOP (result), offr);
5694 /* back to result */
5695 storeRegToAop (hc08_reg_a, AOP (result), offr);
5696 hc08_freeReg (hc08_reg_a);
5699 /*-----------------------------------------------------------------*/
5700 /* genlshOne - left shift a one byte quantity by known count */
5701 /*-----------------------------------------------------------------*/
5703 genlshOne (operand * result, operand * left, int shCount)
5705 D(emitcode ("; genlshOne",""));
5707 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5710 /*-----------------------------------------------------------------*/
5711 /* genlshTwo - left shift two bytes by known amount != 0 */
5712 /*-----------------------------------------------------------------*/
5714 genlshTwo (operand * result, operand * left, int shCount)
5718 D(emitcode ("; genlshTwo",""));
5721 size = getDataSize (result);
5723 /* if shCount >= 8 */
5730 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5732 storeRegToAop (hc08_reg_a, AOP (result), 1);
5734 storeConstToAop(zero, AOP (result), LSB);
5737 /* 1 <= shCount <= 7 */
5740 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5742 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5746 /*-----------------------------------------------------------------*/
5747 /* shiftLLong - shift left one long from left to result */
5748 /* offl = LSB or MSB16 */
5749 /*-----------------------------------------------------------------*/
5751 shiftLLong (operand * left, operand * result, int offr)
5754 // int size = AOP_SIZE (result);
5756 bool needpula = FALSE;
5757 bool needpulx = FALSE;
5759 needpula = pushRegIfUsed (hc08_reg_a);
5760 needpulx = pushRegIfUsed (hc08_reg_x);
5762 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5763 rmwWithReg ("lsl", hc08_reg_a);
5764 rmwWithReg ("rol", hc08_reg_x);
5765 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5769 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5770 rmwWithReg ("rol", hc08_reg_a);
5771 rmwWithReg ("rol", hc08_reg_x);
5772 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5774 else if (offr==MSB16)
5776 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5777 rmwWithReg ("rol", hc08_reg_a);
5778 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5781 pullOrFreeReg (hc08_reg_x, needpulx);
5782 pullOrFreeReg (hc08_reg_a, needpula);
5785 /*-----------------------------------------------------------------*/
5786 /* genlshFour - shift four byte by a known amount != 0 */
5787 /*-----------------------------------------------------------------*/
5789 genlshFour (operand * result, operand * left, int shCount)
5793 D(emitcode ("; genlshFour",""));
5795 size = AOP_SIZE (result);
5797 /* TODO: deal with the &result == &left case */
5799 /* if shifting more that 3 bytes */
5804 /* lowest order of left goes to the highest
5805 order of the destination */
5806 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5808 movLeft2Result (left, LSB, result, MSB32, 0);
5809 storeConstToAop (zero, AOP (result), LSB);
5810 storeConstToAop (zero, AOP (result), MSB16);
5811 storeConstToAop (zero, AOP (result), MSB24);
5815 /* more than two bytes */
5816 else if (shCount >= 16)
5818 /* lower order two bytes goes to higher order two bytes */
5820 /* if some more remaining */
5822 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5825 movLeft2Result (left, MSB16, result, MSB32, 0);
5826 movLeft2Result (left, LSB, result, MSB24, 0);
5828 storeConstToAop (zero, AOP (result), LSB);
5829 storeConstToAop (zero, AOP (result), MSB16);
5833 /* if more than 1 byte */
5834 else if (shCount >= 8)
5836 /* lower order three bytes goes to higher order three bytes */
5841 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5843 movLeft2Result (left, LSB, result, MSB16, 0);
5849 movLeft2Result (left, MSB24, result, MSB32, 0);
5850 movLeft2Result (left, MSB16, result, MSB24, 0);
5851 movLeft2Result (left, LSB, result, MSB16, 0);
5852 storeConstToAop (zero, AOP (result), LSB);
5854 else if (shCount == 1)
5855 shiftLLong (left, result, MSB16);
5858 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5859 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5860 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5861 storeConstToAop (zero, AOP (result), LSB);
5866 /* 1 <= shCount <= 7 */
5867 else if (shCount <= 2)
5869 shiftLLong (left, result, LSB);
5871 shiftLLong (result, result, LSB);
5873 /* 3 <= shCount <= 7, optimize */
5876 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5877 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5878 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5882 /*-----------------------------------------------------------------*/
5883 /* genLeftShiftLiteral - left shifting by known count */
5884 /*-----------------------------------------------------------------*/
5886 genLeftShiftLiteral (operand * left,
5891 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5894 D(emitcode ("; genLeftShiftLiteral",""));
5896 freeAsmop (right, NULL, ic, TRUE);
5898 aopOp (left, ic, FALSE);
5899 aopOp (result, ic, FALSE);
5901 // size = getSize (operandType (result));
5902 size = AOP_SIZE (result);
5905 emitcode ("; shift left ", "result %d, left %d", size,
5912 transferAopAop( AOP(left), size, AOP(result), size);
5914 else if (shCount >= (size * 8))
5917 storeConstToAop (zero, AOP (result), size);
5924 genlshOne (result, left, shCount);
5928 genlshTwo (result, left, shCount);
5932 genlshFour (result, left, shCount);
5935 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5936 "*** ack! mystery literal shift!\n");
5940 freeAsmop (left, NULL, ic, TRUE);
5941 freeAsmop (result, NULL, ic, TRUE);
5944 /*-----------------------------------------------------------------*/
5945 /* genLeftShift - generates code for left shifting */
5946 /*-----------------------------------------------------------------*/
5948 genLeftShift (iCode * ic)
5950 operand *left, *right, *result;
5952 symbol *tlbl, *tlbl1;
5957 D(emitcode ("; genLeftShift",""));
5959 right = IC_RIGHT (ic);
5960 left = IC_LEFT (ic);
5961 result = IC_RESULT (ic);
5963 aopOp (right, ic, FALSE);
5965 /* if the shift count is known then do it
5966 as efficiently as possible */
5967 if (AOP_TYPE (right) == AOP_LIT)
5969 genLeftShiftLiteral (left, right, result, ic);
5973 /* shift count is unknown then we have to form
5974 a loop get the loop count in A : Note: we take
5975 only the lower order byte since shifting
5976 more that 32 bits make no sense anyway, ( the
5977 largest size of an object can be only 32 bits ) */
5979 aopOp (left, ic, FALSE);
5980 aopOp (result, ic, FALSE);
5982 /* now move the left to the result if they are not the
5984 if (!sameRegs (AOP (left), AOP (result)))
5987 size = AOP_SIZE (result);
5991 transferAopAop (AOP (left), offset, AOP (result), offset);
5995 freeAsmop (left, NULL, ic, TRUE);
5997 tlbl = newiTempLabel (NULL);
5998 size = AOP_SIZE (result);
6000 tlbl1 = newiTempLabel (NULL);
6004 loadRegFromAop (reg, AOP (right), 0);
6005 freeAsmop (right, NULL, ic, TRUE);
6006 emitBranch ("beq", tlbl1);
6010 for (offset=0;offset<size;offset++)
6012 rmwWithAop (shift, AOP (result), offset);
6015 rmwWithReg ("dec", reg);
6016 emitBranch ("bne", tlbl);
6020 freeAsmop (result, NULL, ic, TRUE);
6023 /*-----------------------------------------------------------------*/
6024 /* genrshOne - right shift a one byte quantity by known count */
6025 /*-----------------------------------------------------------------*/
6027 genrshOne (operand * result, operand * left,
6028 int shCount, int sign)
6030 D(emitcode ("; genrshOne",""));
6032 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6033 AccRsh (shCount, sign);
6034 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6037 /*-----------------------------------------------------------------*/
6038 /* genrshTwo - right shift two bytes by known amount != 0 */
6039 /*-----------------------------------------------------------------*/
6041 genrshTwo (operand * result, operand * left,
6042 int shCount, int sign)
6044 D(emitcode ("; genrshTwo",""));
6046 /* if shCount >= 8 */
6049 if (shCount || sign)
6051 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6052 AccRsh (shCount-8, sign);
6053 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6057 transferAopAop (AOP (left), 1, AOP (result), 0);
6058 storeConstToAop (zero, AOP (result), 1);
6062 /* 1 <= shCount <= 7 */
6065 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6066 XAccRsh (shCount, sign);
6067 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6071 /*-----------------------------------------------------------------*/
6072 /* shiftRLong - shift right one long from left to result */
6073 /* offl = LSB or MSB16 */
6074 /*-----------------------------------------------------------------*/
6076 shiftRLong (operand * left, int offl,
6077 operand * result, int sign)
6080 // int size = AOP_SIZE (result);
6082 bool needpula = FALSE;
6083 bool needpulx = FALSE;
6085 needpula = pushRegIfUsed (hc08_reg_a);
6086 needpulx = pushRegIfUsed (hc08_reg_x);
6090 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6092 rmwWithReg ("asr", hc08_reg_x);
6094 rmwWithReg ("lsr", hc08_reg_x);
6095 rmwWithReg ("rol", hc08_reg_a);
6096 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6098 else if (offl==MSB16)
6100 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6102 rmwWithReg ("asr", hc08_reg_a);
6104 rmwWithReg ("lsr", hc08_reg_a);
6105 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6108 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6109 rmwWithReg ("ror", hc08_reg_x);
6110 rmwWithReg ("ror", hc08_reg_a);
6111 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6114 pullOrFreeReg (hc08_reg_x, needpulx);
6115 pullOrFreeReg (hc08_reg_a, needpula);
6118 /*-----------------------------------------------------------------*/
6119 /* genrshFour - shift four byte by a known amount != 0 */
6120 /*-----------------------------------------------------------------*/
6122 genrshFour (operand * result, operand * left,
6123 int shCount, int sign)
6125 /* TODO: handle cases where left == result */
6127 D(emitcode ("; genrshFour",""));
6129 /* if shifting more that 3 bytes */
6132 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6133 AccRsh (shCount-24, sign);
6134 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6137 else if (shCount >= 16)
6139 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6140 XAccRsh (shCount-16, sign);
6141 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6144 else if (shCount >= 8)
6147 shiftRLong (left, MSB16, result, sign);
6148 else if (shCount == 8)
6150 transferAopAop (AOP (left), 1, AOP (result), 0);
6151 transferAopAop (AOP (left), 2, AOP (result), 1);
6152 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6153 storeRegToAop (hc08_reg_a, AOP (result), 2);
6154 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6156 else if (shCount == 9)
6158 shiftRLong (left, MSB16, result, sign);
6162 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6163 XAccRsh (shCount-8, FALSE);
6164 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6165 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6166 loadRegFromConst (hc08_reg_a, zero);
6167 XAccRsh (shCount-8, sign);
6168 accopWithAop ("ora", AOP (result), 1);
6169 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6173 { /* 1 <= shCount <= 7 */
6176 shiftRLong (left, LSB, result, sign);
6180 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6181 XAccRsh (shCount, FALSE);
6182 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6183 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6185 accopWithAop ("ora", AOP (result), 1);
6186 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6187 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6188 XAccRsh (shCount, sign);
6189 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6194 /*-----------------------------------------------------------------*/
6195 /* genRightShiftLiteral - right shifting by known count */
6196 /*-----------------------------------------------------------------*/
6198 genRightShiftLiteral (operand * left,
6204 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6207 D(emitcode ("; genRightShiftLiteral",""));
6209 freeAsmop (right, NULL, ic, TRUE);
6211 aopOp (left, ic, FALSE);
6212 aopOp (result, ic, FALSE);
6215 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6219 size = getDataSize (left);
6220 /* test the LEFT size !!! */
6222 /* I suppose that the left size >= result size */
6225 size = getDataSize (result);
6227 transferAopAop (AOP (left), size, AOP(result), size);
6229 else if (shCount >= (size * 8))
6232 /* get sign in acc.7 */
6233 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6235 addSign (result, LSB, sign);
6242 genrshOne (result, left, shCount, sign);
6246 genrshTwo (result, left, shCount, sign);
6250 genrshFour (result, left, shCount, sign);
6256 freeAsmop (left, NULL, ic, TRUE);
6257 freeAsmop (result, NULL, ic, TRUE);
6261 /*-----------------------------------------------------------------*/
6262 /* genRightShift - generate code for right shifting */
6263 /*-----------------------------------------------------------------*/
6265 genRightShift (iCode * ic)
6267 operand *right, *left, *result;
6271 symbol *tlbl, *tlbl1;
6275 D(emitcode ("; genRightShift",""));
6277 /* if signed then we do it the hard way preserve the
6278 sign bit moving it inwards */
6279 retype = getSpec (operandType (IC_RESULT (ic)));
6280 sign = !SPEC_USIGN (retype);
6282 /* signed & unsigned types are treated the same : i.e. the
6283 signed is NOT propagated inwards : quoting from the
6284 ANSI - standard : "for E1 >> E2, is equivalent to division
6285 by 2**E2 if unsigned or if it has a non-negative value,
6286 otherwise the result is implementation defined ", MY definition
6287 is that the sign does not get propagated */
6289 right = IC_RIGHT (ic);
6290 left = IC_LEFT (ic);
6291 result = IC_RESULT (ic);
6293 aopOp (right, ic, FALSE);
6295 /* if the shift count is known then do it
6296 as efficiently as possible */
6297 if (AOP_TYPE (right) == AOP_LIT)
6299 genRightShiftLiteral (left, right, result, ic, sign);
6303 /* shift count is unknown then we have to form
6304 a loop get the loop count in X : Note: we take
6305 only the lower order byte since shifting
6306 more that 32 bits make no sense anyway, ( the
6307 largest size of an object can be only 32 bits ) */
6309 aopOp (left, ic, FALSE);
6310 aopOp (result, ic, FALSE);
6312 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6313 AOP (result) = forceStackedAop (AOP (result));
6315 size = AOP_SIZE (result);
6319 transferAopAop (AOP (left), offset, AOP (result), offset);
6323 tlbl = newiTempLabel (NULL);
6324 size = AOP_SIZE (result);
6326 tlbl1 = newiTempLabel (NULL);
6328 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6329 emitcode ("tstx", "");
6330 emitcode ("beq", "%05d$", tlbl1->key + 100);
6331 emitcode ("", "%05d$:", tlbl->key + 100);
6332 shift= sign ? "asr" : "lsr";
6333 for (offset=size-1;offset>=0;offset--)
6335 rmwWithAop (shift, AOP (result), offset);
6338 rmwWithReg ("dec", hc08_reg_x);
6339 emitcode ("bne","%05d$", tlbl->key + 100);
6340 emitcode ("", "%05d$:", tlbl1->key + 100);
6342 freeAsmop (result, NULL, ic, TRUE);
6343 freeAsmop (left, NULL, ic, TRUE);
6344 freeAsmop (right, NULL, ic, TRUE);
6347 /*-----------------------------------------------------------------*/
6348 /* genUnpackBits - generates code for unpacking bits */
6349 /*-----------------------------------------------------------------*/
6351 genUnpackBits (operand * result)
6353 int offset = 0; /* result byte offset */
6354 int rsize; /* result size */
6355 int rlen = 0; /* remaining bitfield length */
6356 sym_link *etype; /* bitfield type information */
6357 int blen; /* bitfield length */
6358 int bstr; /* bitfield starting bit within byte */
6360 D(emitcode ("; genUnpackBits",""));
6362 etype = getSpec (operandType (result));
6363 rsize = getSize (operandType (result));
6364 blen = SPEC_BLEN (etype);
6365 bstr = SPEC_BSTR (etype);
6367 /* If the bitfield length is less than a byte */
6370 emitcode ("lda", ",x");
6371 hc08_dirtyReg (hc08_reg_a, FALSE);
6372 AccRsh (bstr, FALSE);
6373 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6374 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6378 /* Bit field did not fit in a byte. Copy all
6379 but the partial byte at the end. */
6380 for (rlen=blen;rlen>=8;rlen-=8)
6382 emitcode ("lda", ",x");
6383 hc08_dirtyReg (hc08_reg_a, FALSE);
6384 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6386 emitcode ("aix", "#1");
6389 /* Handle the partial byte at the end */
6392 emitcode ("lda", ",x");
6393 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6394 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6402 storeConstToAop (zero, AOP (result), offset++);
6407 /*-----------------------------------------------------------------*/
6408 /* genDataPointerGet - generates code when ptr offset is known */
6409 /*-----------------------------------------------------------------*/
6411 genDataPointerGet (operand * left,
6415 int size, offset = 0;
6418 D(emitcode ("; genDataPointerGet",""));
6420 aopOp (result, ic, TRUE);
6421 size = AOP_SIZE (result);
6423 derefaop = aopDerefAop (AOP (left));
6424 freeAsmop (left, NULL, ic, TRUE);
6425 derefaop->size = size;
6429 transferAopAop(derefaop, offset, AOP (result), offset);
6433 freeAsmop (NULL, derefaop, ic, TRUE);
6434 freeAsmop (result, NULL, ic, TRUE);
6438 /*-----------------------------------------------------------------*/
6439 /* genNearPointerGet - emitcode for near pointer fetch */
6440 /*-----------------------------------------------------------------*/
6442 genNearPointerGet (operand * left,
6448 sym_link *retype = getSpec (operandType (result));
6450 D(emitcode ("; genNearPointerGet",""));
6452 aopOp (left, ic, FALSE);
6454 /* if left is rematerialisable and
6455 result is not bit variable type and
6456 the left is pointer to data space i.e
6457 lower 128 bytes of space */
6458 if ((AOP_TYPE (left) == AOP_IMMD)
6459 || (AOP_TYPE (left) == AOP_LIT)
6460 /* !IS_BITVAR (retype) */
6461 /* && DCL_TYPE (ltype) == POINTER */ )
6463 genDataPointerGet (left, result, ic);
6467 /* if the operand is already in hx
6468 then we do nothing else we move the value to hx */
6469 if (AOP_TYPE (left) != AOP_STR)
6471 /* if this is remateriazable */
6472 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6473 loadRegFromConst (hc08_reg_h, zero);
6476 /* so hx now contains the address */
6477 aopOp (result, ic, FALSE);
6479 /* if bit then unpack */
6480 if (IS_BITVAR (retype))
6481 genUnpackBits (result);
6484 size = AOP_SIZE (result);
6489 accopWithMisc ("lda", ",x");
6492 rmwWithReg ("inc", hc08_reg_x);
6494 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6495 hc08_freeReg (hc08_reg_a);
6499 freeAsmop (left, NULL, ic, TRUE);
6500 freeAsmop (result, NULL, ic, TRUE);
6502 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6503 aopOp (IC_RESULT (pi), pi, FALSE);
6504 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6505 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6509 hc08_freeReg (hc08_reg_hx);
6513 /*-----------------------------------------------------------------*/
6514 /* genFarPointerGet - get value from far space */
6515 /*-----------------------------------------------------------------*/
6517 genFarPointerGet (operand * left,
6518 operand * result, iCode * ic, iCode * pi)
6521 sym_link *retype = getSpec (operandType (result));
6523 D(emitcode ("; genFarPointerGet",""));
6525 aopOp (left, ic, FALSE);
6527 /* if left is rematerialisable and
6528 result is not bit variable type and
6529 the left is pointer to data space i.e
6530 lower 128 bytes of space */
6531 if (AOP_TYPE (left) == AOP_IMMD &&
6533 /* && DCL_TYPE (ltype) == POINTER */ )
6535 genDataPointerGet (left, result, ic);
6539 /* if the operand is already in hx
6540 then we do nothing else we move the value to hx */
6541 if (AOP_TYPE (left) != AOP_STR)
6543 /* if this is remateriazable */
6544 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6547 /* so hx now contains the address */
6548 aopOp (result, ic, FALSE);
6550 /* if bit then unpack */
6551 if (IS_BITVAR (retype))
6552 genUnpackBits (result);
6555 size = AOP_SIZE (result);
6560 accopWithMisc ("lda", ",x");
6563 emitcode ("aix", "#1");
6564 hc08_dirtyReg (hc08_reg_hx, FALSE);
6566 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6567 hc08_freeReg (hc08_reg_a);
6571 freeAsmop (left, NULL, ic, TRUE);
6572 freeAsmop (result, NULL, ic, TRUE);
6574 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6575 aopOp (IC_RESULT (pi), pi, FALSE);
6576 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6577 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6581 hc08_freeReg (hc08_reg_hx);
6587 /*-----------------------------------------------------------------*/
6588 /* genPointerGet - generate code for pointer get */
6589 /*-----------------------------------------------------------------*/
6591 genPointerGet (iCode * ic, iCode *pi)
6593 operand *left, *result;
6594 sym_link *type, *etype;
6597 D(emitcode ("; genPointerGet",""));
6599 left = IC_LEFT (ic);
6600 result = IC_RESULT (ic);
6602 /* depending on the type of pointer we need to
6603 move it to the correct pointer register */
6604 type = operandType (left);
6605 etype = getSpec (type);
6606 /* if left is of type of pointer then it is simple */
6607 if (IS_PTR (type) && !IS_FUNC (type->next))
6608 p_type = DCL_TYPE (type);
6611 /* we have to go by the storage class */
6612 p_type = PTR_TYPE (SPEC_OCLS (etype));
6615 /* special case when cast remat */
6616 if (p_type == GPOINTER && IS_SYMOP(left) && OP_SYMBOL(left)->remat &&
6617 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6618 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6619 type = operandType (left);
6620 p_type = DCL_TYPE (type);
6622 /* now that we have the pointer type we assign
6623 the pointer values */
6630 genNearPointerGet (left, result, ic, pi);
6636 genFarPointerGet (left, result, ic, pi);
6643 /*-----------------------------------------------------------------*/
6644 /* genPackBits - generates code for packed bit storage */
6645 /*-----------------------------------------------------------------*/
6647 genPackBits (sym_link * etype,
6650 int offset = 0; /* source byte offset */
6651 int rlen = 0; /* remaining bitfield length */
6652 int blen; /* bitfield length */
6653 int bstr; /* bitfield starting bit within byte */
6654 int litval; /* source literal value (if AOP_LIT) */
6655 unsigned char mask; /* bitmask within current byte */
6657 D(emitcode ("; genPackBits",""));
6659 blen = SPEC_BLEN (etype);
6660 bstr = SPEC_BSTR (etype);
6662 /* If the bitfield length is less than a byte */
6665 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6666 (unsigned char) (0xFF >> (8 - bstr)));
6668 if (AOP_TYPE (right) == AOP_LIT)
6670 /* Case with a bitfield length <8 and literal source
6672 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6674 litval &= (~mask) & 0xff;
6676 emitcode ("lda", ",x");
6677 if ((mask|litval)!=0xff)
6678 emitcode ("and","#0x%02x", mask);
6680 emitcode ("ora","#0x%02x", litval);
6681 hc08_dirtyReg (hc08_reg_a, FALSE);
6682 emitcode ("sta", ",x");
6684 hc08_freeReg (hc08_reg_a);
6688 /* Case with a bitfield length < 8 and arbitrary source
6690 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6691 /* shift and mask source value */
6693 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6694 hc08_dirtyReg (hc08_reg_a, FALSE);
6695 pushReg (hc08_reg_a, TRUE);
6697 emitcode ("lda", ",x");
6698 emitcode ("and", "#0x%02x", mask);
6699 emitcode ("ora", "1,s");
6700 emitcode ("sta", ",x");
6701 pullReg (hc08_reg_a);
6703 hc08_freeReg (hc08_reg_a);
6707 /* Bit length is greater than 7 bits. In this case, copy */
6708 /* all except the partial byte at the end */
6709 for (rlen=blen;rlen>=8;rlen-=8)
6711 if (AOP (right)->type == AOP_DIR)
6713 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6717 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6718 emitcode ("sta", "%d,x", offset);
6723 /* If there was a partial byte at the end */
6726 mask = (((unsigned char) -1 << rlen) & 0xff);
6728 if (AOP_TYPE (right) == AOP_LIT)
6730 /* Case with partial byte and literal source
6732 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6733 litval >>= (blen-rlen);
6734 litval &= (~mask) & 0xff;
6735 emitcode ("lda", "%d,x", offset);
6736 hc08_dirtyReg (hc08_reg_a, FALSE);
6737 if ((mask|litval)!=0xff)
6738 emitcode ("and","#0x%02x", mask);
6740 emitcode ("ora","#0x%02x", litval);
6741 emitcode ("sta", "%d,x", offset);
6742 hc08_dirtyReg (hc08_reg_a, FALSE);
6743 hc08_freeReg (hc08_reg_a);
6747 /* Case with partial byte and arbitrary source
6749 loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6750 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6751 hc08_dirtyReg (hc08_reg_a, FALSE);
6752 pushReg (hc08_reg_a, TRUE);
6754 emitcode ("lda", ",x");
6755 emitcode ("and", "#0x%02x", mask);
6756 emitcode ("ora", "1,s");
6757 emitcode ("sta", ",x");
6758 pullReg (hc08_reg_a);
6761 hc08_freeReg (hc08_reg_a);
6764 /*-----------------------------------------------------------------*/
6765 /* genDataPointerSet - remat pointer to data space */
6766 /*-----------------------------------------------------------------*/
6768 genDataPointerSet (operand * right,
6772 int size, offset = 0;
6775 D(emitcode ("; genDataPointerSet",""));
6777 aopOp (right, ic, FALSE);
6778 size = AOP_SIZE (right);
6780 derefaop = aopDerefAop (AOP (result));
6781 freeAsmop (result, NULL, ic, TRUE);
6782 derefaop->size = size;
6786 transferAopAop (AOP (right), offset, derefaop, offset);
6790 freeAsmop (right, NULL, ic, TRUE);
6791 freeAsmop (NULL, derefaop, ic, TRUE);
6795 /*-----------------------------------------------------------------*/
6796 /* genNearPointerSet - emitcode for near pointer put */
6797 /*-----------------------------------------------------------------*/
6799 genNearPointerSet (operand * right,
6805 sym_link *retype = getSpec (operandType (right));
6806 sym_link *letype = getSpec (operandType (result));
6808 D(emitcode ("; genNearPointerSet",""));
6810 aopOp (result, ic, FALSE);
6812 /* if the result is rematerializable &
6813 in data space & not a bit variable */
6814 if (AOP_TYPE (result) == AOP_IMMD &&
6815 /* DCL_TYPE (ptype) == POINTER && */
6816 !IS_BITVAR (retype) &&
6817 !IS_BITVAR (letype))
6819 genDataPointerSet (right, result, ic);
6823 /* if the operand is already in hx
6824 then we do nothing else we move the value to hx */
6825 if (AOP_TYPE (result) != AOP_STR)
6827 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6828 loadRegFromConst (hc08_reg_h, zero);
6830 /* so hx now contains the address */
6831 aopOp (right, ic, FALSE);
6833 /* if bit then unpack */
6834 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6835 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6838 size = AOP_SIZE (right);
6843 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6844 accopWithMisc ("sta", ",x");
6847 rmwWithReg ("inc", hc08_reg_x);
6849 hc08_freeReg (hc08_reg_a);
6853 freeAsmop (result, NULL, ic, TRUE);
6854 freeAsmop (right, NULL, ic, TRUE);
6856 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6857 aopOp (IC_RESULT (pi), pi, FALSE);
6858 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6859 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6863 hc08_freeReg (hc08_reg_hx);
6868 /*-----------------------------------------------------------------*/
6869 /* genFarPointerSet - set value from far space */
6870 /*-----------------------------------------------------------------*/
6872 genFarPointerSet (operand * right,
6873 operand * result, iCode * ic, iCode * pi)
6876 sym_link *retype = getSpec (operandType (right));
6877 sym_link *letype = getSpec (operandType (result));
6879 D(emitcode ("; genFarPointerSet",""));
6881 aopOp (result, ic, FALSE);
6883 /* if the result is rematerializable &
6884 in data space & not a bit variable */
6885 if (AOP_TYPE (result) == AOP_IMMD &&
6886 /* DCL_TYPE (ptype) == POINTER && */
6887 !IS_BITVAR (retype) &&
6888 !IS_BITVAR (letype))
6890 genDataPointerSet (right, result, ic);
6894 /* if the operand is already in hx
6895 then we do nothing else we move the value to hx */
6896 if (AOP_TYPE (result) != AOP_STR)
6898 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6900 /* so hx now contains the address */
6901 aopOp (right, ic, FALSE);
6903 /* if bit then unpack */
6904 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6905 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6908 size = AOP_SIZE (right);
6913 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6914 accopWithMisc ("sta", ",x");
6917 emitcode ("aix", "#1");
6919 hc08_freeReg (hc08_reg_a);
6923 freeAsmop (result, NULL, ic, TRUE);
6924 freeAsmop (right, NULL, ic, TRUE);
6926 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6927 aopOp (IC_RESULT (pi), pi, FALSE);
6928 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6929 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6933 hc08_freeReg (hc08_reg_hx);
6939 /*-----------------------------------------------------------------*/
6940 /* genPointerSet - stores the value into a pointer location */
6941 /*-----------------------------------------------------------------*/
6943 genPointerSet (iCode * ic, iCode *pi)
6945 operand *right, *result;
6946 sym_link *type, *etype;
6949 D(emitcode ("; genPointerSet",""));
6951 right = IC_RIGHT (ic);
6952 result = IC_RESULT (ic);
6954 /* depending on the type of pointer we need to
6955 move it to the correct pointer register */
6956 type = operandType (result);
6957 etype = getSpec (type);
6958 /* if left is of type of pointer then it is simple */
6959 if (IS_PTR (type) && !IS_FUNC (type->next))
6961 p_type = DCL_TYPE (type);
6965 /* we have to go by the storage class */
6966 p_type = PTR_TYPE (SPEC_OCLS (etype));
6969 /* special case when cast remat */
6970 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
6971 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
6972 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
6973 type = operandType (result);
6974 p_type = DCL_TYPE (type);
6976 /* now that we have the pointer type we assign
6977 the pointer values */
6984 genNearPointerSet (right, result, ic, pi);
6990 genFarPointerSet (right, result, ic, pi);
6994 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6995 "genPointerSet: illegal pointer type");
7000 /*-----------------------------------------------------------------*/
7001 /* genIfx - generate code for Ifx statement */
7002 /*-----------------------------------------------------------------*/
7004 genIfx (iCode * ic, iCode * popIc)
7006 operand *cond = IC_COND (ic);
7009 D(emitcode ("; genIfx",""));
7011 aopOp (cond, ic, FALSE);
7013 /* get the value into acc */
7014 if (AOP_TYPE (cond) != AOP_CRY)
7015 asmopToBool (AOP (cond), FALSE);
7018 /* the result is now in the accumulator */
7019 freeAsmop (cond, NULL, ic, TRUE);
7021 /* if there was something to be popped then do it */
7025 /* if the condition is a bit variable */
7026 if (isbit && IS_ITEMP (cond) &&
7028 genIfxJump (ic, SPIL_LOC (cond)->rname);
7029 else if (isbit && !IS_ITEMP (cond))
7030 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7032 genIfxJump (ic, "a");
7037 /*-----------------------------------------------------------------*/
7038 /* genAddrOf - generates code for address of */
7039 /*-----------------------------------------------------------------*/
7041 genAddrOf (iCode * ic)
7043 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7046 D(emitcode ("; genAddrOf",""));
7048 aopOp (IC_RESULT (ic), ic, FALSE);
7050 /* if the operand is on the stack then we
7051 need to get the stack offset of this
7055 /* if it has an offset then we need to compute
7057 hc08_useReg (hc08_reg_hx);
7058 emitcode ("tsx", "");
7059 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7060 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7061 hc08_freeReg (hc08_reg_hx);
7066 /* object not on stack then we need the name */
7067 size = AOP_SIZE (IC_RESULT (ic));
7072 char s[SDCC_NAME_MAX+10];
7075 sprintf (s, "#%s", sym->rname);
7078 sprintf (s, "#>%s", sym->rname);
7081 sprintf (s, "#(%s >> %d)",
7085 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7089 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7093 /*-----------------------------------------------------------------*/
7094 /* genAssign - generate code for assignment */
7095 /*-----------------------------------------------------------------*/
7097 genAssign (iCode * ic)
7099 operand *result, *right;
7101 // unsigned long lit = 0L;
7103 D(emitcode("; genAssign",""));
7105 result = IC_RESULT (ic);
7106 right = IC_RIGHT (ic);
7108 /* if they are the same */
7109 if (operandsEqu (result, right)) {
7113 aopOp (right, ic, FALSE);
7114 aopOp (result, ic, TRUE);
7116 /* if they are the same registers */
7117 if (sameRegs (AOP (right), AOP (result)))
7120 if ((AOP_TYPE (right) == AOP_LIT)
7121 && (IS_AOP_HX(AOP(result))))
7123 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7128 size = AOP_SIZE (result);
7133 transferAopAop (AOP (right), offset, AOP (result), offset);
7138 freeAsmop (right, NULL, ic, TRUE);
7139 freeAsmop (result, NULL, ic, TRUE);
7142 /*-----------------------------------------------------------------*/
7143 /* genJumpTab - genrates code for jump table */
7144 /*-----------------------------------------------------------------*/
7146 genJumpTab (iCode * ic)
7151 D(emitcode ("; genJumpTab",""));
7153 aopOp (IC_JTCOND (ic), ic, FALSE);
7154 /* get the condition into accumulator */
7155 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7156 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7157 /* multiply by three */
7158 pushReg (hc08_reg_a, FALSE);
7159 emitcode ("lsla", "");
7160 emitcode ("add","1,s");
7161 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7162 loadRegFromConst (hc08_reg_h, zero);
7164 jtab = newiTempLabel (NULL);
7165 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7166 emitcode ("", "%05d$:", jtab->key + 100);
7167 /* now generate the jump labels */
7168 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7169 jtab = setNextItem (IC_JTLABELS (ic)))
7170 emitcode ("jmp", "%05d$", jtab->key + 100);
7172 hc08_dirtyReg (hc08_reg_a, TRUE);
7173 hc08_dirtyReg (hc08_reg_hx, TRUE);
7176 /*-----------------------------------------------------------------*/
7177 /* genCast - gen code for casting */
7178 /*-----------------------------------------------------------------*/
7180 genCast (iCode * ic)
7182 operand *result = IC_RESULT (ic);
7183 sym_link *ctype = operandType (IC_LEFT (ic));
7184 sym_link *rtype = operandType (IC_RIGHT (ic));
7185 operand *right = IC_RIGHT (ic);
7188 D(emitcode("; genCast",""));
7190 /* if they are equivalent then do nothing */
7191 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7194 aopOp (right, ic, FALSE);
7195 aopOp (result, ic, FALSE);
7198 /* if they are the same size : or less */
7199 if (AOP_SIZE (result) <= AOP_SIZE (right))
7202 /* if they are in the same place */
7204 if (sameRegs (AOP (right), AOP (result)))
7208 /* if they in different places then copy */
7209 size = AOP_SIZE (result);
7213 transferAopAop(AOP (right), offset, AOP (result), offset);
7220 /* if the result is of type pointer */
7225 sym_link *type = operandType (right);
7226 sym_link *etype = getSpec (type);
7228 /* pointer to generic pointer */
7229 if (IS_GENPTR (ctype))
7232 p_type = DCL_TYPE (type);
7235 if (SPEC_SCLS(etype)==S_REGISTER) {
7236 // let's assume it is a generic pointer
7239 /* we have to go by the storage class */
7240 p_type = PTR_TYPE (SPEC_OCLS (etype));
7244 /* the first two bytes are known */
7245 size = GPTRSIZE - 1;
7249 transferAopAop(AOP (right), offset, AOP (result), offset);
7252 /* the last byte depending on type */
7255 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7260 // pointerTypeToGPByte will have bitched.
7264 sprintf(gpValStr, "#0x%d", gpVal);
7265 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7271 /* just copy the pointers */
7272 size = AOP_SIZE (result);
7276 transferAopAop(AOP (right), offset, AOP (result), offset);
7282 /* so we now know that the size of destination is greater
7283 than the size of the source */
7284 /* we move to result for the size of source */
7285 size = AOP_SIZE (right);
7289 transferAopAop(AOP (right), offset, AOP (result), offset);
7293 /* now depending on the sign of the source && destination */
7294 size = AOP_SIZE (result) - AOP_SIZE (right);
7295 /* if unsigned or not an integral type */
7296 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7299 storeConstToAop (zero, AOP (result), offset++);
7303 /* we need to extend the sign :{ */
7304 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7305 accopWithMisc ("rola", "");
7306 accopWithMisc ("clra", "");
7307 accopWithMisc ("sbc", zero);
7309 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7312 /* we are done hurray !!!! */
7315 freeAsmop (right, NULL, ic, TRUE);
7316 freeAsmop (result, NULL, ic, TRUE);
7320 /*-----------------------------------------------------------------*/
7321 /* genDjnz - generate decrement & jump if not zero instrucion */
7322 /*-----------------------------------------------------------------*/
7324 genDjnz (iCode * ic, iCode * ifx)
7330 D(emitcode ("; genDjnz",""));
7332 /* if the if condition has a false label
7333 then we cannot save */
7337 /* if the minus is not of the form
7339 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7340 !IS_OP_LITERAL (IC_RIGHT (ic)))
7343 if (operandLitValue (IC_RIGHT (ic)) != 1)
7346 /* dbnz doesn't support extended mode */
7347 if (isOperandInFarSpace (IC_RESULT (ic)))
7350 /* if the size of this greater than one then no
7352 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7354 aopOp (IC_RESULT (ic), ic, FALSE);
7355 if (AOP_SIZE (IC_RESULT (ic))>1)
7357 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7361 /* otherwise we can save BIG */
7362 lbl = newiTempLabel (NULL);
7363 lbl1 = newiTempLabel (NULL);
7366 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7369 emitBranch ("bra", lbl1);
7371 emitBranch ("jmp", IC_TRUE (ifx));
7374 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7379 /*-----------------------------------------------------------------*/
7380 /* genReceive - generate code for a receive iCode */
7381 /*-----------------------------------------------------------------*/
7383 genReceive (iCode * ic)
7387 D(emitcode ("; genReceive",""));
7389 aopOp (IC_RESULT (ic), ic, FALSE);
7390 size = AOP_SIZE (IC_RESULT (ic));
7395 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7396 AOP (IC_RESULT (ic)), offset);
7397 if (hc08_aop_pass[offset]->type == AOP_REG)
7398 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7403 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7406 /*-----------------------------------------------------------------*/
7407 /* genDummyRead - generate code for dummy read of volatiles */
7408 /*-----------------------------------------------------------------*/
7410 genDummyRead (iCode * ic)
7415 D(emitcode("; genDummyRead",""));
7418 if (op && IS_SYMOP (op))
7421 aopOp (op, ic, FALSE);
7423 size = AOP_SIZE (op);
7428 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7429 hc08_freeReg (hc08_reg_a);
7433 freeAsmop (op, NULL, ic, TRUE);
7436 if (op && IS_SYMOP (op))
7439 aopOp (op, ic, FALSE);
7441 size = AOP_SIZE (op);
7446 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7447 hc08_freeReg (hc08_reg_a);
7451 freeAsmop (op, NULL, ic, TRUE);
7455 /*-----------------------------------------------------------------*/
7456 /* genCritical - generate code for start of a critical sequence */
7457 /*-----------------------------------------------------------------*/
7459 genCritical (iCode *ic)
7461 D(emitcode("; genCritical",""));
7464 aopOp (IC_RESULT (ic), ic, TRUE);
7466 emitcode ("tpa", "");
7467 hc08_dirtyReg (hc08_reg_a, FALSE);
7468 emitcode ("sei", "");
7471 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7473 pushReg (hc08_reg_a, FALSE);
7475 hc08_freeReg (hc08_reg_a);
7477 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7480 /*-----------------------------------------------------------------*/
7481 /* genEndCritical - generate code for end of a critical sequence */
7482 /*-----------------------------------------------------------------*/
7484 genEndCritical (iCode *ic)
7486 D(emitcode("; genEndCritical",""));
7490 aopOp (IC_RIGHT (ic), ic, FALSE);
7491 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7492 emitcode ("tap", "");
7493 hc08_freeReg (hc08_reg_a);
7494 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7498 pullReg (hc08_reg_a);
7499 emitcode ("tap", "");
7504 /*-----------------------------------------------------------------*/
7505 /* genhc08Code - generate code for HC08 based controllers */
7506 /*-----------------------------------------------------------------*/
7508 genhc08Code (iCode * lic)
7513 lineHead = lineCurr = NULL;
7515 /* print the allocation information */
7516 if (allocInfo && currFunc)
7517 printAllocInfo (currFunc, codeOutFile);
7518 /* if debug information required */
7519 if (options.debug && currFunc)
7521 debugFile->writeFunction(currFunc);
7523 if (IS_STATIC (currFunc->etype))
7524 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7526 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7529 /* stack pointer name */
7530 if (options.useXstack)
7535 hc08_aop_pass[0] = newAsmop (AOP_REG);
7536 hc08_aop_pass[0]->size=1;
7537 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7538 hc08_aop_pass[1] = newAsmop (AOP_REG);
7539 hc08_aop_pass[1]->size=1;
7540 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7541 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7542 hc08_aop_pass[2]->size=1;
7543 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7544 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7545 hc08_aop_pass[3]->size=1;
7546 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7548 for (ic = lic; ic; ic = ic->next)
7551 if (ic->lineno && cln != ic->lineno)
7556 emitcode ("", "C$%s$%d$%d$%d ==.",
7557 FileBaseName (ic->filename), ic->lineno,
7558 ic->level, ic->block);
7561 if (!options.noCcodeInAsm) {
7562 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7563 printCLine(ic->filename, ic->lineno));
7567 if (options.iCodeInAsm) {
7571 for (i=0; i<6; i++) {
7572 sprintf (®sInUse[i],
7573 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7576 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7578 /* if the result is marked as
7579 spilt and rematerializable or code for
7580 this has already been generated then
7582 if (resultRemat (ic) || ic->generated)
7590 for (i=A_IDX;i<=XA_IDX;i++)
7592 reg = hc08_regWithIdx(i);
7594 emitcode("","; %s = %s offset %d", reg->name,
7595 aopName(reg->aop), reg->aopofs);
7598 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7600 sym = OP_SYMBOL (IC_LEFT (ic));
7601 if (sym->accuse == ACCUSE_HX)
7603 hc08_reg_h->isFree = FALSE;
7604 hc08_reg_x->isFree = FALSE;
7606 else if (sym->accuse == ACCUSE_XA)
7608 hc08_reg_a->isFree = FALSE;
7610 hc08_reg_x->isFree = FALSE;
7613 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7615 sym = OP_SYMBOL (IC_RIGHT (ic));
7616 if (sym->accuse == ACCUSE_HX)
7618 hc08_reg_h->isFree = FALSE;
7619 hc08_reg_x->isFree = FALSE;
7621 else if (sym->accuse == ACCUSE_XA)
7623 hc08_reg_a->isFree = FALSE;
7625 hc08_reg_x->isFree = FALSE;
7630 /* depending on the operation */
7650 /* IPOP happens only when trying to restore a
7651 spilt live range, if there is an ifx statement
7652 following this pop then the if statement might
7653 be using some of the registers being popped which
7654 would destory the contents of the register so
7655 we need to check for this condition and handle it */
7657 ic->next->op == IFX &&
7658 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7659 genIfx (ic->next, ic);
7677 genEndFunction (ic);
7693 if (!genPointerGetSetOfs (ic))
7698 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7715 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7719 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7726 /* note these two are xlated by algebraic equivalence
7727 during parsing SDCC.y */
7728 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7729 "got '>=' or '<=' shouldn't have come here");
7733 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7745 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7749 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7753 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7780 case GET_VALUE_AT_ADDRESS:
7781 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7785 if (POINTER_SET (ic))
7786 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7812 addSet (&_G.sendSet, ic);
7815 case DUMMY_READ_VOLATILE:
7824 genEndCritical (ic);
7835 if (!hc08_reg_a->isFree)
7836 emitcode("","; forgot to free a");
7837 if (!hc08_reg_x->isFree)
7838 emitcode("","; forgot to free x");
7839 if (!hc08_reg_h->isFree)
7840 emitcode("","; forgot to free h");
7841 if (!hc08_reg_hx->isFree)
7842 emitcode("","; forgot to free hx");
7843 if (!hc08_reg_xa->isFree)
7844 emitcode("","; forgot to free xa");
7848 /* now we are ready to call the
7849 peep hole optimizer */
7850 if (!options.nopeep)
7851 peepHole (&lineHead);
7853 /* now do the actual printing */
7854 printLine (lineHead, codeOutFile);