1 /* The only ops for now are:
9 /*-------------------------------------------------------------------------
10 SDCCgen51.c - source file for code generation for 8051
12 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
13 and - Jean-Louis VERN.jlvern@writeme.com (1999)
14 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
16 This program is free software; you can redistribute it and/or modify it
17 under the terms of the GNU General Public License as published by the
18 Free Software Foundation; either version 2, or (at your option) any
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 In other words, you are welcome to use, share and improve this program.
31 You are forbidden to forbid anyone else to use, share and improve
32 what you give them. Help stamp out software-hoarding!
35 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
36 Made everything static
37 -------------------------------------------------------------------------*/
46 #include "SDCCglobl.h"
49 #ifdef HAVE_SYS_ISA_DEFS_H
50 #include <sys/isa_defs.h>
52 #ifdef HAVE_MACHINE_ENDIAN_H
53 #include <machine/endian.h>
58 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
59 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
60 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
67 #include "SDCCpeeph.h"
71 #if defined(__BORLANDC__) || defined(_MSC_VER)
72 #define STRCASECMP stricmp
74 #define STRCASECMP strcasecmp
79 /* this is the down and dirty file with all kinds of
80 kludgy & hacky stuff. This is what it is all about
81 CODE GENERATION for a specific MCU . some of the
82 routines may be reusable, will have to see */
93 extern int xa51_ptrRegReq;
94 extern int xa51_nRegs;
95 extern FILE *codeOutFile;
97 static lineNode *lineHead = NULL;
98 static lineNode *lineCurr = NULL;
105 static char *MOVB="mov.b";
106 static char *MOVW="mov.w";
107 static char *MOVCB="movc.b";
108 static char *MOVCW="movc.w";
110 void bailOut (char *mesg) {
111 fprintf (stderr, "%s: bailing out\n", mesg);
115 /*-----------------------------------------------------------------*/
116 /* emitcode - writes the code into a file : for now it is simple */
117 /*-----------------------------------------------------------------*/
118 static void emitcode (char *inst, char *fmt,...) {
120 char lb[INITIAL_INLINEASM];
128 sprintf (lb, "%s\t", inst);
130 sprintf (lb, "%s", inst);
131 vsprintf (lb + (strlen (lb)), fmt, ap);
134 vsprintf (lb, fmt, ap);
136 while (isspace ((int)*lbp))
140 lineCurr = (lineCurr ?
141 connectLine (lineCurr, newLineNode (lb)) :
142 (lineHead = newLineNode (lb)));
143 lineCurr->isInline = _G.inLine;
144 lineCurr->isDebug = _G.debugLine;
148 char *getStackOffset(int stack) {
149 static char gsoBuf[1024];
150 // dit slaat natuurlijk nergens op
151 sprintf (gsoBuf, "r7+(%+d+0%+d%+d)", stack,
152 FUNC_ISISR(currFunc->type) ?
153 port->stack.isr_overhead : port->stack.call_overhead,
158 /*-----------------------------------------------------------------*/
159 /* newAsmop - creates a new asmOp */
160 /*-----------------------------------------------------------------*/
162 newAsmop (short type)
166 aop = Safe_calloc (1, sizeof (asmop));
171 char *aopTypeName(asmop *aop) {
174 case AOP_LIT: return "lit";
175 case AOP_REG: return "reg";
176 case AOP_DIR: return "dir";
177 case AOP_FAR: return "far";
178 case AOP_CODE: return "code";
179 case AOP_STK: return "stack";
180 case AOP_IMMD: return "imm";
181 case AOP_CRY: return "bit";
186 /*-----------------------------------------------------------------*/
187 /* aopForSym - for a true symbol */
188 /*-----------------------------------------------------------------*/
189 static asmop *aopForSym(symbol *sym, bool result) {
193 sym->aop = aop = newAsmop(0);
194 size=aop->size=getSize(sym->type);
196 // if the sym has registers
197 if (sym->nRegs && sym->regs[0]) {
199 sprintf (aop->name[0], sym->regs[0]->name);
201 sprintf (aop->name[1], sym->regs[1]->name);
209 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
211 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
216 // if it has a spillLoc
217 if (sym->usl.spillLoc) {
218 return aopForSym (sym->usl.spillLoc, result);
222 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
224 sprintf (aop->name[0], sym->rname);
228 // if in direct space
229 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
231 sprintf (aop->name[0], sym->rname);
233 sprintf (aop->name[0], "%s+2", sym->rname);
239 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
241 bailOut("aopForSym: result can not be in code space");
244 emitcode ("mov", "r0,#%s", sym->rname);
245 sprintf (aop->name[0], "[r0]");
247 sprintf (aop->name[1], "[r0+1]");
253 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
255 emitcode ("mov", "r0,#%s", sym->rname);
256 sprintf (aop->name[0], "[r0]");
258 sprintf (aop->name[1], "[r0+1]");
263 bailOut("aopForSym");
267 /*-----------------------------------------------------------------*/
268 /* aopForVal - for a value */
269 /*-----------------------------------------------------------------*/
270 static asmop *aopForVal(operand *op) {
272 long v=(long long)floatFromVal(OP_VALUE(op));
274 if (IS_OP_LITERAL(op)) {
275 op->aop = aop = newAsmop (AOP_LIT);
276 switch ((aop->size=getSize(operandType(op))))
279 sprintf (aop->name[0], "#0x%02lx", v);
282 sprintf (aop->name[0], "#0x%04lx", v);
285 sprintf (aop->name[0], "#(0x%08lx >> 16)", v);
286 sprintf (aop->name[1], "#(0x%08lx & 0xffff)", v);
289 bailOut("aopForVal");
296 op->aop = aop = newAsmop (AOP_IMMD);
297 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
301 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
303 case 3: // generic pointer
304 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
305 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
309 bailOut ("aopForVal: unknown type");
313 static void aopOp(operand *op, bool result) {
316 op->aop=aopForSym (OP_SYMBOL(op), result);
321 bailOut("aopOp: result can not be a value");
327 bailOut("aopOp: unexpected operand");
330 char *opRegName(operand *op, int offset, char *opName) {
333 if (OP_SYMBOL(op)->onStack) {
334 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
337 if (IS_TRUE_SYMOP(op))
338 return OP_SYMBOL(op)->rname;
339 else if (OP_SYMBOL(op)->regs[offset])
340 return OP_SYMBOL(op)->regs[offset]->name;
342 bailOut("opRegName: unknown regs");
346 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
349 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
350 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
351 bailOut("opRegName: invalid bit value");
355 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
358 if (SPEC_LONG(OP_VALUE(op)->type)) {
359 sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
361 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
365 sprintf (opName, "#%f", SPEC_CVAL(OP_VALUE(op)->type).v_float);
368 bailOut("opRegName: unexpected noun");
372 bailOut("opRegName: unexpected operand type");
376 char * printOp (operand *op) {
377 static char line[132];
378 sym_link *optype=operandType(op);
379 bool isPtr = IS_PTR(optype);
382 symbol *sym=OP_SYMBOL(op);
383 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
384 sym=SYM_SPIL_LOC(sym);
388 if (DCL_TYPE(optype)==FPOINTER)
389 strcat (line, "far * ");
390 else if (DCL_TYPE(optype)==CPOINTER)
391 strcat (line, "code * ");
392 else if (DCL_TYPE(optype)==GPOINTER)
393 strcat (line, "gen * ");
394 else if (DCL_TYPE(optype)==POINTER)
395 strcat (line, "near * ");
397 strcat (line, "unknown * ");
399 strcat (line, nounName(sym->etype));
401 strcat (line, sym->name);
404 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
407 strcat (line, sym->regs[0]->name);
410 strcat (line, sym->regs[1]->name);
415 sprintf (line+strlen(line), "stack%+d", sym->stack);
418 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
419 strcat (line, "far");
422 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
423 strcat (line, "bit");
426 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
427 strcat (line, "dir");
430 strcat (line, "unknown");
432 } else if (IS_VALOP(op)) {
433 opRegName(op, 0, line);
434 } else if (IS_TYPOP(op)) {
437 if (DCL_TYPE(optype)==FPOINTER)
438 strcat (line, "far * ");
439 else if (DCL_TYPE(optype)==CPOINTER)
440 strcat (line, "code * ");
441 else if (DCL_TYPE(optype)==GPOINTER)
442 strcat (line, "gen * ");
443 else if (DCL_TYPE(optype)==POINTER)
444 strcat (line, "near * ");
446 strcat (line, "unknown * ");
448 // forget about static, volatile, ... for now
449 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
450 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
451 strcat (line, nounName(operandType(op)));
454 bailOut("printOp: unexpected operand type");
459 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
462 sprintf (line, "%s(%d)", op, ic->lineno);
464 strcat (line, " result=");
465 strcat (line, printOp (IC_RESULT(ic)));
468 strcat (line, " left=");
469 strcat (line, printOp (IC_LEFT(ic)));
472 strcat (line, " right=");
473 strcat (line, printOp (IC_RIGHT(ic)));
475 emitcode (";", line);
478 /*-----------------------------------------------------------------*/
479 /* toBoolean - return carry for operand!=0 */
480 /*-----------------------------------------------------------------*/
481 static char *toBoolean (operand * op) {
482 switch (AOP_SIZE(op))
486 emitcode ("cmp", "%s,#0", AOP_NAME(op));
487 emitcode ("mov", "c,z");
491 bailOut("toBoolean: unknown size");
495 /*-----------------------------------------------------------------*/
496 /* regsInCommon - two operands have some registers in common */
497 /*-----------------------------------------------------------------*/
498 static bool regsInCommon (operand * op1, operand * op2) {
502 /* if they have registers in common */
503 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
506 sym1 = OP_SYMBOL (op1);
507 sym2 = OP_SYMBOL (op2);
509 if (sym1->nRegs == 0 || sym2->nRegs == 0)
512 for (i = 0; i < sym1->nRegs; i++)
518 for (j = 0; j < sym2->nRegs; j++)
523 if (sym2->regs[j] == sym1->regs[i])
531 /*-----------------------------------------------------------------*/
532 /* resultRemat - result is rematerializable */
533 /*-----------------------------------------------------------------*/
534 static int resultRemat (iCode * ic) {
535 if (SKIP_IC (ic) || ic->op == IFX)
538 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
540 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
541 if (sym->remat && !POINTER_SET (ic))
548 /*-----------------------------------------------------------------*/
549 /* genNot - generate code for ! operation */
550 /*-----------------------------------------------------------------*/
551 static void genNot (iCode * ic) {
552 printIc("genNot:", ic, 1,1,0);
555 /*-----------------------------------------------------------------*/
556 /* genCpl - generate code for complement */
557 /*-----------------------------------------------------------------*/
558 static void genCpl (iCode * ic) {
559 printIc("genCpl", ic, 1,1,0);
562 /*-----------------------------------------------------------------*/
563 /* genUminus - unary minus code generation */
564 /*-----------------------------------------------------------------*/
565 static void genUminus (iCode * ic) {
566 printIc("genUminus", ic, 1,1,0);
569 /*-----------------------------------------------------------------*/
570 /* genIpush - genrate code for pushing this gets a little complex */
571 /*-----------------------------------------------------------------*/
572 static void genIpush (iCode * ic) {
573 printIc ("genIpush", ic, 0,1,0);
576 /*-----------------------------------------------------------------*/
577 /* genIpop - recover the registers: can happen only for spilling */
578 /*-----------------------------------------------------------------*/
579 static void genIpop (iCode * ic) {
580 printIc ("genIpop", ic, 0,1,0);
583 /*-----------------------------------------------------------------*/
584 /* genCall - generates a call statement */
585 /*-----------------------------------------------------------------*/
586 static void genCall (iCode * ic) {
587 emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
588 printOp (IC_RESULT(ic)));
591 /*-----------------------------------------------------------------*/
592 /* genPcall - generates a call by pointer statement */
593 /*-----------------------------------------------------------------*/
595 genPcall (iCode * ic)
597 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
600 /*-----------------------------------------------------------------*/
601 /* genFunction - generated code for function entry */
602 /*-----------------------------------------------------------------*/
603 static void genFunction (iCode * ic) {
604 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
605 sym_link *type=sym->type;
607 emitcode (";", "-----------------------------------------");
608 emitcode (";", " function %s", sym->name);
609 emitcode (";", "-----------------------------------------");
611 emitcode ("", "%s:", sym->rname);
613 if (IFFUNC_ISNAKED(type))
615 emitcode(";", "naked function: no prologue.");
619 /* if critical function then turn interrupts off */
620 if (IFFUNC_ISCRITICAL (type))
621 emitcode ("clr", "ea");
625 /*-----------------------------------------------------------------*/
626 /* genEndFunction - generates epilogue for functions */
627 /*-----------------------------------------------------------------*/
629 genEndFunction (iCode * ic)
631 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
633 if (IFFUNC_ISNAKED(sym->type))
635 emitcode(";", "naked function: no epilogue.");
639 printIc ("genEndFunction", ic, 0,0,0);
642 /*-----------------------------------------------------------------*/
643 /* genRet - generate code for return statement */
644 /*-----------------------------------------------------------------*/
645 static void genRet (iCode * ic) {
647 printIc ("genRet", ic, 0,1,0);
649 aopOp(IC_LEFT(ic),FALSE);
651 switch (AOP_SIZE(IC_LEFT(ic)))
654 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
655 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
658 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
661 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
664 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
670 /*-----------------------------------------------------------------*/
671 /* genLabel - generates a label */
672 /*-----------------------------------------------------------------*/
673 static void genLabel (iCode * ic) {
674 /* special case never generate */
675 if (IC_LABEL (ic) == entryLabel)
678 emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
679 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
682 /*-----------------------------------------------------------------*/
683 /* genGoto - generates a jmp */
684 /*-----------------------------------------------------------------*/
685 static void genGoto (iCode * ic) {
686 emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
687 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
690 /*-----------------------------------------------------------------*/
691 /* genPlus - generates code for addition */
692 /*-----------------------------------------------------------------*/
693 static void genPlus (iCode * ic) {
694 printIc ("genPlus", ic, 1,1,1);
697 /*-----------------------------------------------------------------*/
698 /* genMinus - generates code for subtraction */
699 /*-----------------------------------------------------------------*/
700 static void genMinus (iCode * ic) {
701 printIc ("genMinus", ic, 1,1,1);
705 /*-----------------------------------------------------------------*/
706 /* genMult - generates code for multiplication */
707 /*-----------------------------------------------------------------*/
708 static void genMult (iCode * ic) {
709 printIc ("genMult", ic, 1,1,1);
712 /*-----------------------------------------------------------------*/
713 /* genDiv - generates code for division */
714 /*-----------------------------------------------------------------*/
715 static void genDiv (iCode * ic) {
716 printIc ("genDiv", ic, 1,1,1);
719 /*-----------------------------------------------------------------*/
720 /* genMod - generates code for division */
721 /*-----------------------------------------------------------------*/
722 static void genMod (iCode * ic) {
723 printIc ("genMod", ic, 1,1,1);
726 /*-----------------------------------------------------------------*/
727 /* genCmpGt :- greater than comparison */
728 /*-----------------------------------------------------------------*/
729 static void genCmpGt (iCode * ic) {
730 printIc ("genCmpGt", ic, 1,1,1);
732 /*-----------------------------------------------------------------*/
733 /* genCmpGt :- greater than comparison */
734 /*-----------------------------------------------------------------*/
735 static void genCmpLe (iCode * ic) {
736 printIc ("genCmpGt", ic, 1,1,1);
738 /*-----------------------------------------------------------------*/
739 /* genCmpGt :- greater than comparison */
740 /*-----------------------------------------------------------------*/
741 static void genCmpGe (iCode * ic) {
742 printIc ("genCmpGt", ic, 1,1,1);
744 /*-----------------------------------------------------------------*/
745 /* genCmpGt :- greater than comparison */
746 /*-----------------------------------------------------------------*/
747 static void genCmpNe (iCode * ic) {
748 printIc ("genCmpGt", ic, 1,1,1);
750 /*-----------------------------------------------------------------*/
751 /* genCmpLt - less than comparisons */
752 /*-----------------------------------------------------------------*/
753 static void genCmpLt (iCode * ic) {
754 printIc ("genCmpLt", ic, 1,1,1);
756 /*-----------------------------------------------------------------*/
757 /* genCmpEq - generates code for equal to */
758 /*-----------------------------------------------------------------*/
759 static void genCmpEq (iCode * ic) {
760 printIc ("genCmpEq", ic, 1,1,1);
763 /*-----------------------------------------------------------------*/
764 /* ifxForOp - returns the icode containing the ifx for operand */
765 /*-----------------------------------------------------------------*/
766 static iCode *ifxForOp (operand * op, iCode * ic) {
767 /* if true symbol then needs to be assigned */
768 if (IS_TRUE_SYMOP (op))
771 /* if this has register type condition and
772 the next instruction is ifx with the same operand
773 and live to of the operand is upto the ifx only then */
775 ic->next->op == IFX &&
776 IC_COND (ic->next)->key == op->key &&
777 OP_SYMBOL (op)->liveTo <= ic->next->seq)
783 /*-----------------------------------------------------------------*/
784 /* hasInc - operand is incremented before any other use */
785 /*-----------------------------------------------------------------*/
786 static iCode *hasInc (operand *op, iCode *ic, int osize) {
787 sym_link *type = operandType(op);
788 sym_link *retype = getSpec (type);
789 iCode *lic = ic->next;
792 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
793 if (!IS_SYMOP(op)) return NULL;
795 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
796 if (IS_AGGREGATE(type->next)) return NULL;
797 if (osize != (isize = getSize(type->next))) return NULL;
800 /* if operand of the form op = op + <sizeof *op> */
801 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
802 isOperandEqual(IC_RESULT(lic),op) &&
803 isOperandLiteral(IC_RIGHT(lic)) &&
804 operandLitValue(IC_RIGHT(lic)) == isize) {
807 /* if the operand used or deffed */
808 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
812 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
818 /*-----------------------------------------------------------------*/
819 /* genAndOp - for && operation */
820 /*-----------------------------------------------------------------*/
821 static void genAndOp (iCode * ic) {
822 printIc ("genAndOp(&&)", ic, 1,1,1);
825 /*-----------------------------------------------------------------*/
826 /* genOrOp - for || operation */
827 /*-----------------------------------------------------------------*/
828 static void genOrOp (iCode * ic) {
829 printIc ("genOrOp(||)", ic, 1,1,1);
832 /*-----------------------------------------------------------------*/
833 /* genAnd - code for and */
834 /*-----------------------------------------------------------------*/
835 static void genAnd (iCode * ic, iCode * ifx) {
836 printIc ("genAnd", ic, 1,1,1);
839 /*-----------------------------------------------------------------*/
840 /* genOr - code for or */
841 /*-----------------------------------------------------------------*/
842 static void genOr (iCode * ic, iCode * ifx) {
843 printIc ("genOr", ic, 1,1,1);
846 /*-----------------------------------------------------------------*/
847 /* genXor - code for xclusive or */
848 /*-----------------------------------------------------------------*/
849 static void genXor (iCode * ic, iCode * ifx) {
850 printIc ("genXor", ic, 1,1,1);
853 /*-----------------------------------------------------------------*/
854 /* genInline - write the inline code out */
855 /*-----------------------------------------------------------------*/
856 static void genInline (iCode * ic) {
857 printIc ("genInline", ic, 0,0,0);
860 /*-----------------------------------------------------------------*/
861 /* genRRC - rotate right with carry */
862 /*-----------------------------------------------------------------*/
863 static void genRRC (iCode * ic) {
864 printIc ("genRRC", ic, 1,1,0);
867 /*-----------------------------------------------------------------*/
868 /* genRLC - generate code for rotate left with carry */
869 /*-----------------------------------------------------------------*/
870 static void genRLC (iCode * ic) {
871 printIc ("genRLC", ic, 1,1,0);
874 /*-----------------------------------------------------------------*/
875 /* genGetHbit - generates code get highest order bit */
876 /*-----------------------------------------------------------------*/
877 static void genGetHbit (iCode * ic) {
878 printIc ("genGetHbit", ic, 1,1,0);
881 /*-----------------------------------------------------------------*/
882 /* genLeftShift - generates code for left shifting */
883 /*-----------------------------------------------------------------*/
884 static void genLeftShift (iCode * ic) {
885 printIc ("genLeftShift", ic, 1,1,1);
888 /*-----------------------------------------------------------------*/
889 /* genRightShift - generate code for right shifting */
890 /*-----------------------------------------------------------------*/
891 static void genRightShift (iCode * ic) {
892 printIc ("genRightShift", ic, 1,1,1);
895 /*-----------------------------------------------------------------*/
896 /* genPointerGet - generate code for pointer get */
897 /*-----------------------------------------------------------------*/
898 static void genPointerGet (iCode * ic, iCode *pi) {
901 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
903 printIc ("genPointerGet", ic, 1,1,0);
905 if (!IS_PTR(operandType(left))) {
906 bailOut ("genPointerGet: pointer required");
912 if (IS_GENPTR(operandType(left))) {
913 emitcode (";", "INLINE\t_gptrget ; %s %s = [%s %s]",
914 AOP_NAME(result)[0], AOP_NAME(result)[1],
915 AOP_NAME(left)[0], AOP_NAME(left)[1]);
919 switch (AOP_TYPE(left))
922 if (AOP_SIZE(result)==1) {
927 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
928 if (AOP_SIZE(result) > 2) {
929 if (AOP_SIZE(result)==3) {
934 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
938 if (AOP_SIZE(result)==1) {
943 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
944 if (AOP_SIZE(result) > 2) {
945 if (AOP_SIZE(result)==3) {
950 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
954 if (AOP_SIZE(result)==1) {
959 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
960 if (AOP_SIZE(result) > 2) {
961 if (AOP_SIZE(result)==3) {
966 emitcode (instr, "%s,%s+2", AOP_NAME(result)[1], AOP_NAME(left)[0]);
970 if (AOP_SIZE(result)==1) {
975 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
976 if (AOP_SIZE(result) > 2) {
977 // result is generic pointer
978 sym_link *optype=operandType(left);
979 sym_link *opetype=getSpec(optype);
980 if (IS_PTR(optype) && !IS_GENPTR(optype)) {
981 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(result)[1],
982 PTR_TYPE(SPEC_OCLS(opetype)));
984 emitcode ("mov.b", "%s,[%s]", AOP_NAME(result)[1], AOP_NAME(left)[1]);
990 if (AOP_TYPE(result)==AOP_STK) {
991 if (AOP_SIZE(result)==1) {
992 emitcode ("mov", "r0l,%s", AOP_NAME(left)[0]);
993 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
995 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
996 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
999 if (AOP_SIZE(result)==3) {
1000 emitcode ("mov.b", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1002 emitcode ("mov.w", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1005 if (AOP_SIZE(result) > 2) {
1006 if (AOP_TYPE(result)==AOP_STK) {
1007 if (AOP_SIZE(result)==3) {
1008 emitcode ("mov", "r0l,%s", AOP_NAME(left)[1]);
1009 emitcode ("mov", "%s,r0l", AOP_NAME(result)[1]);
1011 emitcode ("mov", "r0,%s", AOP_NAME(left)[1]);
1012 emitcode ("mov", "%s,r0", AOP_NAME(result)[1]);
1015 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1020 bailOut ("genPointerGet: unknown pointer");
1023 /*-----------------------------------------------------------------*/
1024 /* genPointerSet - stores the value into a pointer location */
1025 /*-----------------------------------------------------------------*/
1026 static void genPointerSet (iCode * ic, iCode *pi) {
1029 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1031 printIc ("genPointerSet", ic, 1,0,1);
1033 if (!IS_PTR(operandType(result))) {
1034 bailOut ("genPointerSet: pointer required");
1040 if (IS_GENPTR(operandType(result))) {
1041 emitcode (";", "INLINE _gptrset ; [%s %s]= %s %s",
1042 AOP_NAME(result)[0], AOP_NAME(result)[1],
1043 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1047 switch (AOP_TYPE(result))
1053 if (AOP_SIZE(result)==1) {
1058 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1059 if (AOP_SIZE(result) > 2) {
1060 if (AOP_SIZE(result)==3) {
1065 emitcode (instr, "[%s],%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1069 bailOut ("genPointerSet: unknown pointer");
1072 /*-----------------------------------------------------------------*/
1073 /* genIfx - generate code for Ifx statement */
1074 /*-----------------------------------------------------------------*/
1075 static void genIfx (iCode * ic, iCode * popIc) {
1078 symbol *jlbl, *tlbl;
1079 operand *cond=IC_COND(ic);
1081 emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s",
1083 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1084 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1096 switch (AOP_TYPE(cond) )
1099 emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$",
1100 AOP_NAME(cond)[0], jlbl->key+100);
1106 tlbl=newiTempLabel(NULL);
1107 if (AOP_SIZE(cond)==1) {
1112 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1113 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1114 if (AOP_SIZE(cond) > 2) {
1115 if (AOP_SIZE(cond)==3) {
1120 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1121 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1123 emitcode ("jmp", "%05d$", jlbl->key+100);
1124 emitcode ("", "%05d$:", tlbl->key+100);
1130 /*-----------------------------------------------------------------*/
1131 /* genAddrOf - generates code for address of */
1132 /*-----------------------------------------------------------------*/
1133 static void genAddrOf (iCode * ic) {
1134 operand *left=IC_LEFT(ic);
1136 printIc ("genAddrOf", ic, 1,1,0);
1138 aopOp (IC_RESULT(ic),TRUE);
1140 if (isOperandOnStack(left)) {
1141 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1142 getStackOffset(OP_SYMBOL(left)->stack));
1143 if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1144 // this must be a generic pointer
1145 emitcode ("mov", "%s,#0x01", AOP_NAME(IC_RESULT(ic))[1]);
1150 if (isOperandInDirSpace(left) ||
1151 isOperandInFarSpace(left) ||
1152 isOperandInCodeSpace(left)) {
1153 emitcode ("mov", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1155 if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1156 // this must be a generic pointer
1157 int space=0; // dir space
1158 if (isOperandInFarSpace(left)) {
1160 } else if (isOperandInCodeSpace(left)) {
1163 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1168 bailOut("genAddrOf");
1171 /*-----------------------------------------------------------------*/
1172 /* genAssign - generate code for assignment */
1173 /*-----------------------------------------------------------------*/
1174 static void genAssign (iCode * ic) {
1175 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1179 printIc ("genAssign", ic, 1,0,1);
1181 if (!IS_SYMOP(result)) {
1182 bailOut("genAssign: result is not a symbol");
1185 aopOp(right, FALSE);
1186 aopOp(result, TRUE);
1187 size=AOP_SIZE(result);
1189 if (result->aop->type==AOP_REG ||
1190 right->aop->type==AOP_REG ||
1191 right->aop->type==AOP_LIT ||
1192 right->aop->type==AOP_STK ||
1193 right->aop->type==AOP_IMMD) {
1194 // everything will do
1196 // they have to match
1197 if (result->aop->type != right->aop->type) {
1198 fprintf (stderr, "genAssign: types don't match (%s!=%s)\n",
1199 aopTypeName(result->aop), aopTypeName(right->aop));
1204 /* if result is a bit */
1205 if (AOP_TYPE(result) == AOP_CRY) {
1206 /* if right is literal, we know what the value is */
1207 if (AOP_TYPE(right) == AOP_LIT) {
1208 if (operandLitValue(right)) {
1209 emitcode ("setb", AOP_NAME(result)[0]);
1211 emitcode ("clr", AOP_NAME(result)[0]);
1215 /* if right is also a bit */
1216 if (AOP_TYPE(right) == AOP_CRY) {
1217 emitcode ("mov", "c,%s", AOP_NAME(right));
1218 emitcode ("mov", "%s,c", AOP_NAME(result));
1222 emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
1232 emitcode (instr, "%s,%s",
1233 result->aop->name[0], right->aop->name[0]);
1234 if (AOP_SIZE(result) > 2) {
1240 emitcode (instr, "%s,%s",
1241 result->aop->name[1], right->aop->name[1]);
1246 /*-----------------------------------------------------------------*/
1247 /* genJumpTab - genrates code for jump table */
1248 /*-----------------------------------------------------------------*/
1249 static void genJumpTab (iCode * ic) {
1250 printIc ("genJumpTab", ic, 0,0,0);
1253 /*-----------------------------------------------------------------*/
1254 /* genCast - gen code for casting */
1255 /*-----------------------------------------------------------------*/
1256 static void genCast (iCode * ic) {
1257 printIc ("genCast", ic, 1,1,1);
1260 /*-----------------------------------------------------------------*/
1261 /* genDjnz - generate decrement & jump if not zero instrucion */
1262 /*-----------------------------------------------------------------*/
1263 static bool genDjnz (iCode * ic, iCode * ifx) {
1269 /* if the if condition has a false label
1270 then we cannot save */
1274 /* if the minus is not of the form
1276 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1277 !IS_OP_LITERAL (IC_RIGHT (ic)))
1280 if (operandLitValue (IC_RIGHT (ic)) != 1)
1283 /* if the size of this greater than two then no
1285 if (getSize (operandType (IC_RESULT (ic))) > 2)
1288 printIc ("genDjnz", ic, 1,1,1);
1290 /* otherwise we can save BIG */
1291 lbl = newiTempLabel (NULL);
1292 lbl1 = newiTempLabel (NULL);
1294 aopOp (IC_RESULT (ic), TRUE);
1296 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1297 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1298 emitcode ("bra", "%05d$", lbl1->key + 100);
1299 emitcode ("", "%05d$:", lbl->key + 100);
1300 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1301 emitcode ("", "%05d$:", lbl1->key + 100);
1304 bailOut("genDjnz: aop type");
1308 /*-----------------------------------------------------------------*/
1309 /* genReceive - generate code for a receive iCode */
1310 /*-----------------------------------------------------------------*/
1311 static void genReceive (iCode * ic) {
1312 printIc ("genReceive", ic, 1,0,0);
1315 /*-----------------------------------------------------------------*/
1316 /* gen51Code - generate code for 8051 based controllers */
1317 /*-----------------------------------------------------------------*/
1318 void genXA51Code (iCode * lic) {
1322 fprintf (stderr, "genXA51Code\n");
1323 lineHead = lineCurr = NULL;
1325 /* print the allocation information */
1327 printAllocInfo (currFunc, codeOutFile);
1329 /* if debug information required */
1330 if (options.debug && currFunc)
1332 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1334 if (IS_STATIC (currFunc->etype))
1335 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1337 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1341 for (ic = lic; ic; ic = ic->next) {
1342 if (cln != ic->lineno) {
1343 if (options.debug) {
1345 emitcode ("", "C$%s$%d$%d$%d ==.",
1346 FileBaseName (ic->filename), ic->lineno,
1347 ic->level, ic->block);
1350 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1351 printCLine(ic->filename, ic->lineno));
1354 /* if the result is marked as
1355 spilt and rematerializable or code for
1356 this has already been generated then
1358 if (resultRemat (ic) || ic->generated)
1361 /* depending on the operation */
1381 /* IPOP happens only when trying to restore a
1382 spilt live range, if there is an ifx statement
1383 following this pop then the if statement might
1384 be using some of the registers being popped which
1385 would destory the contents of the register so
1386 we need to check for this condition and handle it */
1388 ic->next->op == IFX &&
1389 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1390 genIfx (ic->next, ic);
1408 genEndFunction (ic);
1428 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1477 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1481 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1485 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1512 case GET_VALUE_AT_ADDRESS:
1513 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
1517 if (POINTER_SET (ic))
1518 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1544 addSet (&_G.sendSet, ic);
1553 /* now we are ready to call the
1554 peep hole optimizer */
1555 if (!options.nopeep)
1556 peepHole (&lineHead);
1558 /* now do the actual printing */
1559 printLine (lineHead, codeOutFile);