1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
59 #include "SDCCpeeph.h"
63 #if defined(__BORLANDC__) || defined(_MSC_VER)
64 #define STRCASECMP stricmp
66 #define STRCASECMP strcasecmp
71 /* this is the down and dirty file with all kinds of
72 kludgy & hacky stuff. This is what it is all about
73 CODE GENERATION for a specific MCU . some of the
74 routines may be reusable, will have to see */
85 extern int xa51_ptrRegReq;
86 extern int xa51_nRegs;
87 extern FILE *codeOutFile;
89 static lineNode *lineHead = NULL;
90 static lineNode *lineCurr = NULL;
97 static char *MOVB="mov.b";
98 static char *MOVW="mov.w";
99 //static char *MOVCB="movc.b";
100 //static char *MOVCW="movc.w";
102 void bailOut (char *mesg) {
103 fprintf (stderr, "%s: bailing out\n", mesg);
107 /*-----------------------------------------------------------------*/
108 /* emitcode - writes the code into a file : for now it is simple */
109 /*-----------------------------------------------------------------*/
110 static void emitcode (char *inst, char *fmt,...) {
112 char lb[INITIAL_INLINEASM];
120 sprintf (lb, "%s\t", inst);
122 sprintf (lb, "%s", inst);
123 vsprintf (lb + (strlen (lb)), fmt, ap);
126 vsprintf (lb, fmt, ap);
128 while (isspace ((int)*lbp))
132 lineCurr = (lineCurr ?
133 connectLine (lineCurr, newLineNode (lb)) :
134 (lineHead = newLineNode (lb)));
135 lineCurr->isInline = _G.inLine;
136 lineCurr->isDebug = _G.debugLine;
140 char *getStackOffset(int stack) {
141 static char gsoBuf[1024];
142 // dit slaat natuurlijk nergens op, maar ja voor nou
143 sprintf (gsoBuf, "r7+(%+d+0%+d%+d)", stack,
144 FUNC_ISISR(currFunc->type) ?
145 port->stack.isr_overhead : port->stack.call_overhead,
150 /*-----------------------------------------------------------------*/
151 /* newAsmop - creates a new asmOp */
152 /*-----------------------------------------------------------------*/
154 newAsmop (short type)
158 aop = Safe_calloc (1, sizeof (asmop));
163 char *aopTypeName(asmop *aop) {
166 case AOP_LIT: return "lit";
167 case AOP_REG: return "reg";
168 case AOP_DIR: return "dir";
169 case AOP_FAR: return "far";
170 case AOP_CODE: return "code";
171 case AOP_GPTR: return "gptr";
172 case AOP_STK: return "stack";
173 case AOP_IMMD: return "imm";
174 case AOP_BIT: return "bit";
179 /*-----------------------------------------------------------------*/
180 /* aopForSym - for a true symbol */
181 /*-----------------------------------------------------------------*/
182 static asmop *aopForSym(symbol *sym, bool result, bool cantUsePointer) {
186 sym->aop = aop = newAsmop(0);
187 size=aop->size=getSize(sym->type);
189 // if the sym has registers
190 if (sym->nRegs && sym->regs[0]) {
192 sprintf (aop->name[0], sym->regs[0]->name);
194 sprintf (aop->name[1], sym->regs[1]->name);
201 if (cantUsePointer) {
206 emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
207 sprintf (aop->name[0], "r0l");
210 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
211 sprintf (aop->name[0], "r0");
214 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
215 sprintf (aop->name[0], "r0");
216 emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
217 sprintf (aop->name[1], "r1l");
220 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
221 sprintf (aop->name[0], "r0");
222 emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
223 sprintf (aop->name[1], "r1");
226 bailOut("aopForSym: onStack CantUsePointer unknown size");
229 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
231 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
236 // if it has a spillLoc
237 if (sym->usl.spillLoc) {
238 return aopForSym (sym->usl.spillLoc, result, cantUsePointer);
242 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
244 sprintf (aop->name[0], sym->rname);
248 // if in direct space
249 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
251 sprintf (aop->name[0], sym->rname);
253 sprintf (aop->name[1], "%s+2", sym->rname);
259 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
261 bailOut("aopForSym: result can not be in code space");
264 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
265 sprintf (aop->name[0], "[r0]");
267 sprintf (aop->name[1], "[r0+2]");
273 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
275 emitcode ("mov", "r0,#%s ; aopForSym:far", sym->rname);
276 sprintf (aop->name[0], "[r0]");
278 sprintf (aop->name[1], "[r0+2]");
283 bailOut("aopForSym");
287 /*-----------------------------------------------------------------*/
288 /* aopForVal - for a value */
289 /*-----------------------------------------------------------------*/
290 static asmop *aopForVal(operand *op) {
293 if (IS_OP_LITERAL(op)) {
294 op->aop = aop = newAsmop (AOP_LIT);
295 switch ((aop->size=getSize(operandType(op))))
298 sprintf (aop->name[0], "#0x%02x",
299 SPEC_CVAL(operandType(op)).v_int & 0xff);
300 sprintf (aop->name[1], "#0");
303 sprintf (aop->name[0], "#0x%04x",
304 SPEC_CVAL(operandType(op)).v_int & 0xffff);
305 sprintf (aop->name[1], "#0");
308 // must be a generic pointer, can only be zero
309 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
310 sprintf (aop->name[0], "#0x%04x",
311 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
312 sprintf (aop->name[1], "#0");
315 sprintf (aop->name[0], "#0x%04lx",
316 SPEC_CVAL(operandType(op)).v_ulong >> 16);
317 sprintf (aop->name[1], "#0x%04x",
318 SPEC_CVAL(operandType(op)).v_ulong && 0xffff);
321 bailOut("aopForVal");
328 op->aop = aop = newAsmop (AOP_IMMD);
329 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
333 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
335 case 3: // generic pointer
336 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
337 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
342 bailOut ("aopForVal: unknown type");
346 static void aopOp(operand *op, bool result, bool cantUsePointer) {
349 op->aop=aopForSym (OP_SYMBOL(op), result, cantUsePointer);
354 bailOut("aopOp: result can not be a value");
356 op->aop=aopForVal (op);
360 bailOut("aopOp: unexpected operand");
363 bool aopIsPtr(operand *op) {
364 if (AOP_TYPE(op)==AOP_STK ||
365 AOP_TYPE(op)==AOP_CODE ||
366 AOP_TYPE(op)==AOP_FAR) {
373 char *opRegName(operand *op, int offset, char *opName) {
376 if (OP_SYMBOL(op)->onStack) {
377 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
380 if (IS_TRUE_SYMOP(op))
381 return OP_SYMBOL(op)->rname;
382 else if (OP_SYMBOL(op)->regs[offset])
383 return OP_SYMBOL(op)->regs[offset]->name;
385 bailOut("opRegName: unknown regs");
389 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
392 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
393 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
394 bailOut("opRegName: invalid bit value");
398 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
401 if (SPEC_LONG(OP_VALUE(op)->type)) {
402 sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
404 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
408 sprintf (opName, "#%f", SPEC_CVAL(OP_VALUE(op)->type).v_float);
411 bailOut("opRegName: unexpected noun");
415 bailOut("opRegName: unexpected operand type");
419 char * printOp (operand *op) {
420 static char line[132];
421 sym_link *optype=operandType(op);
422 bool isPtr = IS_PTR(optype);
425 symbol *sym=OP_SYMBOL(op);
426 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
427 sym=SYM_SPIL_LOC(sym);
431 if (DCL_TYPE(optype)==FPOINTER)
432 strcat (line, "far * ");
433 else if (DCL_TYPE(optype)==CPOINTER)
434 strcat (line, "code * ");
435 else if (DCL_TYPE(optype)==GPOINTER)
436 strcat (line, "gen * ");
437 else if (DCL_TYPE(optype)==POINTER)
438 strcat (line, "near * ");
440 strcat (line, "unknown * ");
442 strcat (line, nounName(sym->etype));
444 strcat (line, sym->name);
447 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
450 strcat (line, sym->regs[0]->name);
453 strcat (line, sym->regs[1]->name);
458 sprintf (line+strlen(line), "stack%+d", sym->stack);
461 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
462 strcat (line, "code");
465 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
466 strcat (line, "far");
469 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
470 strcat (line, "bit");
473 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
474 strcat (line, "dir");
477 strcat (line, "unknown");
479 } else if (IS_VALOP(op)) {
480 opRegName(op, 0, line);
481 } else if (IS_TYPOP(op)) {
484 if (DCL_TYPE(optype)==FPOINTER)
485 strcat (line, "far * ");
486 else if (DCL_TYPE(optype)==CPOINTER)
487 strcat (line, "code * ");
488 else if (DCL_TYPE(optype)==GPOINTER)
489 strcat (line, "gen * ");
490 else if (DCL_TYPE(optype)==POINTER)
491 strcat (line, "near * ");
493 strcat (line, "unknown * ");
495 // forget about static, volatile, ... for now
496 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
497 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
498 strcat (line, nounName(operandType(op)));
501 bailOut("printOp: unexpected operand type");
506 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
509 sprintf (line, "%s(%d)", op, ic->lineno);
511 strcat (line, " result=");
512 strcat (line, printOp (IC_RESULT(ic)));
515 strcat (line, " left=");
516 strcat (line, printOp (IC_LEFT(ic)));
519 strcat (line, " right=");
520 strcat (line, printOp (IC_RIGHT(ic)));
522 emitcode (";", line);
525 /*-----------------------------------------------------------------*/
526 /* toBoolean - return carry for operand!=0 */
527 /*-----------------------------------------------------------------*/
528 static char *toBoolean (operand * op) {
529 switch (AOP_SIZE(op))
533 emitcode ("cmp", "%s,#0", AOP_NAME(op));
534 emitcode ("mov", "c,z");
538 bailOut("toBoolean: unknown size");
542 /*-----------------------------------------------------------------*/
543 /* regsInCommon - two operands have some registers in common */
544 /*-----------------------------------------------------------------*/
545 static bool regsInCommon (operand * op1, operand * op2) {
549 /* if they have registers in common */
550 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
553 sym1 = OP_SYMBOL (op1);
554 sym2 = OP_SYMBOL (op2);
556 if (sym1->nRegs == 0 || sym2->nRegs == 0)
559 for (i = 0; i < sym1->nRegs; i++)
565 for (j = 0; j < sym2->nRegs; j++)
570 if (sym2->regs[j] == sym1->regs[i])
578 /*-----------------------------------------------------------------*/
579 /* resultRemat - result is rematerializable */
580 /*-----------------------------------------------------------------*/
581 static int resultRemat (iCode * ic) {
582 if (SKIP_IC (ic) || ic->op == IFX)
585 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
587 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
588 if (sym->remat && !POINTER_SET (ic))
595 /*-----------------------------------------------------------------*/
596 /* genNot - generate code for ! operation */
597 /*-----------------------------------------------------------------*/
598 static void genNot (iCode * ic) {
599 printIc("genNot:", ic, 1,1,0);
602 /*-----------------------------------------------------------------*/
603 /* genCpl - generate code for complement */
604 /*-----------------------------------------------------------------*/
605 static void genCpl (iCode * ic) {
606 printIc("genCpl", ic, 1,1,0);
609 /*-----------------------------------------------------------------*/
610 /* genUminus - unary minus code generation */
611 /*-----------------------------------------------------------------*/
612 static void genUminus (iCode * ic) {
613 printIc("genUminus", ic, 1,1,0);
616 /*-----------------------------------------------------------------*/
617 /* genIpush - genrate code for pushing this gets a little complex */
618 /*-----------------------------------------------------------------*/
619 static void genIpush (iCode * ic) {
620 printIc ("genIpush", ic, 0,1,0);
623 /*-----------------------------------------------------------------*/
624 /* genIpop - recover the registers: can happen only for spilling */
625 /*-----------------------------------------------------------------*/
626 static void genIpop (iCode * ic) {
627 printIc ("genIpop", ic, 0,1,0);
630 /*-----------------------------------------------------------------*/
631 /* genCall - generates a call statement */
632 /*-----------------------------------------------------------------*/
633 static void genCall (iCode * ic) {
634 emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
635 printOp (IC_RESULT(ic)));
638 /*-----------------------------------------------------------------*/
639 /* genPcall - generates a call by pointer statement */
640 /*-----------------------------------------------------------------*/
642 genPcall (iCode * ic)
644 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
647 /*-----------------------------------------------------------------*/
648 /* genFunction - generated code for function entry */
649 /*-----------------------------------------------------------------*/
650 static void genFunction (iCode * ic) {
651 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
652 sym_link *type=sym->type;
654 emitcode (";", "-----------------------------------------");
655 emitcode (";", " function %s", sym->name);
656 emitcode (";", "-----------------------------------------");
658 emitcode ("", "%s:", sym->rname);
660 if (IFFUNC_ISNAKED(type))
662 emitcode(";", "naked function: no prologue.");
666 /* if critical function then turn interrupts off */
667 if (IFFUNC_ISCRITICAL (type))
668 emitcode ("clr", "ea");
672 /*-----------------------------------------------------------------*/
673 /* genEndFunction - generates epilogue for functions */
674 /*-----------------------------------------------------------------*/
676 genEndFunction (iCode * ic)
678 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
680 if (IFFUNC_ISNAKED(sym->type))
682 emitcode(";", "naked function: no epilogue.");
686 printIc ("genEndFunction", ic, 0,0,0);
689 /*-----------------------------------------------------------------*/
690 /* genRet - generate code for return statement */
691 /*-----------------------------------------------------------------*/
692 static void genRet (iCode * ic) {
694 printIc ("genRet", ic, 0,1,0);
696 aopOp(IC_LEFT(ic),FALSE, FALSE);
698 switch (AOP_SIZE(IC_LEFT(ic)))
701 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
702 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
705 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
708 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
711 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
717 /*-----------------------------------------------------------------*/
718 /* genLabel - generates a label */
719 /*-----------------------------------------------------------------*/
720 static void genLabel (iCode * ic) {
721 /* special case never generate */
722 if (IC_LABEL (ic) == entryLabel)
725 emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
726 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
729 /*-----------------------------------------------------------------*/
730 /* genGoto - generates a jmp */
731 /*-----------------------------------------------------------------*/
732 static void genGoto (iCode * ic) {
733 emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
734 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
737 /*-----------------------------------------------------------------*/
738 /* genPlus - generates code for addition */
739 /*-----------------------------------------------------------------*/
740 static void genPlus (iCode * ic) {
741 printIc ("genPlus", ic, 1,1,1);
744 /*-----------------------------------------------------------------*/
745 /* genMinus - generates code for subtraction */
746 /*-----------------------------------------------------------------*/
747 static void genMinus (iCode * ic) {
748 printIc ("genMinus", ic, 1,1,1);
752 /*-----------------------------------------------------------------*/
753 /* genMult - generates code for multiplication */
754 /*-----------------------------------------------------------------*/
755 static void genMult (iCode * ic) {
756 printIc ("genMult", ic, 1,1,1);
759 /*-----------------------------------------------------------------*/
760 /* genDiv - generates code for division */
761 /*-----------------------------------------------------------------*/
762 static void genDiv (iCode * ic) {
763 printIc ("genDiv", ic, 1,1,1);
766 /*-----------------------------------------------------------------*/
767 /* genMod - generates code for division */
768 /*-----------------------------------------------------------------*/
769 static void genMod (iCode * ic) {
770 printIc ("genMod", ic, 1,1,1);
773 /*-----------------------------------------------------------------*/
774 /* genCmpGt :- greater than comparison */
775 /*-----------------------------------------------------------------*/
776 static void genCmpGt (iCode * ic) {
777 printIc ("genCmpGt", ic, 1,1,1);
779 /*-----------------------------------------------------------------*/
780 /* genCmpGt :- greater than comparison */
781 /*-----------------------------------------------------------------*/
782 static void genCmpLe (iCode * ic) {
783 printIc ("genCmpGt", ic, 1,1,1);
785 /*-----------------------------------------------------------------*/
786 /* genCmpGt :- greater than comparison */
787 /*-----------------------------------------------------------------*/
788 static void genCmpGe (iCode * ic) {
789 printIc ("genCmpGt", ic, 1,1,1);
791 /*-----------------------------------------------------------------*/
792 /* genCmpGt :- greater than comparison */
793 /*-----------------------------------------------------------------*/
794 static void genCmpNe (iCode * ic) {
795 printIc ("genCmpGt", ic, 1,1,1);
797 /*-----------------------------------------------------------------*/
798 /* genCmpLt - less than comparisons */
799 /*-----------------------------------------------------------------*/
800 static void genCmpLt (iCode * ic) {
801 printIc ("genCmpLt", ic, 1,1,1);
803 /*-----------------------------------------------------------------*/
804 /* genCmpEq - generates code for equal to */
805 /*-----------------------------------------------------------------*/
806 static void genCmpEq (iCode * ic) {
807 printIc ("genCmpEq", ic, 1,1,1);
810 /*-----------------------------------------------------------------*/
811 /* ifxForOp - returns the icode containing the ifx for operand */
812 /*-----------------------------------------------------------------*/
813 static iCode *ifxForOp (operand * op, iCode * ic) {
814 /* if true symbol then needs to be assigned */
815 if (IS_TRUE_SYMOP (op))
818 /* if this has register type condition and
819 the next instruction is ifx with the same operand
820 and live to of the operand is upto the ifx only then */
822 ic->next->op == IFX &&
823 IC_COND (ic->next)->key == op->key &&
824 OP_SYMBOL (op)->liveTo <= ic->next->seq)
830 /*-----------------------------------------------------------------*/
831 /* hasInc - operand is incremented before any other use */
832 /*-----------------------------------------------------------------*/
833 static iCode *hasInc (operand *op, iCode *ic, int osize) {
834 sym_link *type = operandType(op);
835 sym_link *retype = getSpec (type);
836 iCode *lic = ic->next;
839 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
840 if (!IS_SYMOP(op)) return NULL;
842 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
843 if (IS_AGGREGATE(type->next)) return NULL;
844 if (osize != (isize = getSize(type->next))) return NULL;
847 /* if operand of the form op = op + <sizeof *op> */
848 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
849 isOperandEqual(IC_RESULT(lic),op) &&
850 isOperandLiteral(IC_RIGHT(lic)) &&
851 operandLitValue(IC_RIGHT(lic)) == isize) {
854 /* if the operand used or deffed */
855 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
859 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
865 /*-----------------------------------------------------------------*/
866 /* genAndOp - for && operation */
867 /*-----------------------------------------------------------------*/
868 static void genAndOp (iCode * ic) {
869 printIc ("genAndOp(&&)", ic, 1,1,1);
872 /*-----------------------------------------------------------------*/
873 /* genOrOp - for || operation */
874 /*-----------------------------------------------------------------*/
875 static void genOrOp (iCode * ic) {
876 printIc ("genOrOp(||)", ic, 1,1,1);
879 /*-----------------------------------------------------------------*/
880 /* genAnd - code for and */
881 /*-----------------------------------------------------------------*/
882 static void genAnd (iCode * ic, iCode * ifx) {
883 printIc ("genAnd", ic, 1,1,1);
886 /*-----------------------------------------------------------------*/
887 /* genOr - code for or */
888 /*-----------------------------------------------------------------*/
889 static void genOr (iCode * ic, iCode * ifx) {
890 printIc ("genOr", ic, 1,1,1);
893 /*-----------------------------------------------------------------*/
894 /* genXor - code for xclusive or */
895 /*-----------------------------------------------------------------*/
896 static void genXor (iCode * ic, iCode * ifx) {
897 printIc ("genXor", ic, 1,1,1);
900 /*-----------------------------------------------------------------*/
901 /* genInline - write the inline code out */
902 /*-----------------------------------------------------------------*/
903 static void genInline (iCode * ic) {
904 printIc ("genInline", ic, 0,0,0);
907 /*-----------------------------------------------------------------*/
908 /* genRRC - rotate right with carry */
909 /*-----------------------------------------------------------------*/
910 static void genRRC (iCode * ic) {
911 printIc ("genRRC", ic, 1,1,0);
914 /*-----------------------------------------------------------------*/
915 /* genRLC - generate code for rotate left with carry */
916 /*-----------------------------------------------------------------*/
917 static void genRLC (iCode * ic) {
918 printIc ("genRLC", ic, 1,1,0);
921 /*-----------------------------------------------------------------*/
922 /* genGetHbit - generates code get highest order bit */
923 /*-----------------------------------------------------------------*/
924 static void genGetHbit (iCode * ic) {
925 printIc ("genGetHbit", ic, 1,1,0);
928 /*-----------------------------------------------------------------*/
929 /* genLeftShift - generates code for left shifting */
930 /*-----------------------------------------------------------------*/
931 static void genLeftShift (iCode * ic) {
932 printIc ("genLeftShift", ic, 1,1,1);
935 /*-----------------------------------------------------------------*/
936 /* genRightShift - generate code for right shifting */
937 /*-----------------------------------------------------------------*/
938 static void genRightShift (iCode * ic) {
939 printIc ("genRightShift", ic, 1,1,1);
942 /*-----------------------------------------------------------------*/
943 /* genPointerGet - generate code for pointer get */
944 /*-----------------------------------------------------------------*/
945 static void genPointerGet (iCode * ic, iCode *pi) {
946 printIc ("genPointerGet", ic, 1,1,0);
948 char *instr, *scratchReg;
949 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
951 if (!IS_PTR(operandType(left))) {
952 bailOut ("genPointerGet: pointer required");
958 if (IS_GENPTR(operandType(left))) {
959 emitcode (";", "INLINE\t_gptrget ; %s %s = [%s %s]",
960 AOP_NAME(result)[0], AOP_NAME(result)[1],
961 AOP_NAME(left)[0], AOP_NAME(left)[1]);
965 switch (AOP_TYPE(left))
968 if (AOP_SIZE(result)==1) {
973 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
974 if (AOP_SIZE(result) > 2) {
975 if (AOP_SIZE(result)==3) {
980 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
984 if (AOP_SIZE(result)==1) {
989 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
990 if (AOP_SIZE(result) > 2) {
991 if (AOP_SIZE(result)==3) {
996 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1000 if (AOP_SIZE(result)==1) {
1005 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1006 if (AOP_SIZE(result) > 2) {
1007 if (AOP_SIZE(result)==3) {
1012 emitcode (instr, "%s,%s+2", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1016 if (AOP_SIZE(result)==1) {
1023 // if result=onstack
1024 if (AOP_TYPE(result)==AOP_STK) {
1025 emitcode (instr, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1026 emitcode (instr, "%s,%s", AOP_NAME(result)[0], scratchReg);
1028 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1030 if (AOP_SIZE(result) > 2) {
1031 // result is generic pointer
1032 sym_link *optype=operandType(left);
1033 sym_link *opetype=getSpec(optype);
1034 if (IS_PTR(optype) && !IS_GENPTR(optype)) {
1035 emitcode (MOVB, "%s,#0x%02x", AOP_NAME(result)[1],
1036 PTR_TYPE(SPEC_OCLS(opetype)));
1038 emitcode (MOVB, "%s,[%s]", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1044 if (AOP_TYPE(result)==AOP_STK) {
1045 if (AOP_SIZE(result)==1) {
1046 emitcode ("mov", "r0l,%s", AOP_NAME(left)[0]);
1047 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
1049 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1050 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
1053 if (AOP_SIZE(result)==1) {
1054 emitcode ("mov.b", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1056 emitcode ("mov.w", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1059 if (AOP_SIZE(result) > 2) {
1060 if (AOP_TYPE(result)==AOP_STK) {
1061 if (AOP_SIZE(result)==3) {
1062 emitcode ("mov", "r0l,%s", AOP_NAME(left)[1]);
1063 emitcode ("mov", "%s,r0l", AOP_NAME(result)[1]);
1065 emitcode ("mov", "r0,%s", AOP_NAME(left)[1]);
1066 emitcode ("mov", "%s,r0", AOP_NAME(result)[1]);
1069 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1074 bailOut ("genPointerGet: unknown pointer");
1078 /*-----------------------------------------------------------------*/
1079 /* genPointerSet - stores the value into a pointer location */
1080 /*-----------------------------------------------------------------*/
1081 static void genPointerSet (iCode * ic, iCode *pi) {
1082 printIc ("genPointerSet", ic, 1,0,1);
1085 /*-----------------------------------------------------------------*/
1086 /* genIfx - generate code for Ifx statement */
1087 /*-----------------------------------------------------------------*/
1088 static void genIfx (iCode * ic, iCode * popIc) {
1091 symbol *jlbl, *tlbl;
1092 operand *cond=IC_COND(ic);
1094 emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s",
1096 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1097 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1099 aopOp(cond,FALSE,FALSE);
1109 switch (AOP_TYPE(cond) )
1112 emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$",
1113 AOP_NAME(cond)[0], jlbl->key+100);
1119 tlbl=newiTempLabel(NULL);
1120 if (AOP_SIZE(cond)==1) {
1125 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1126 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1127 if (AOP_SIZE(cond) > 2) {
1128 if (AOP_SIZE(cond)==3) {
1133 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1134 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1136 emitcode ("jmp", "%05d$", jlbl->key+100);
1137 emitcode ("", "%05d$:", tlbl->key+100);
1143 /*-----------------------------------------------------------------*/
1144 /* genAddrOf - generates code for address of */
1145 /*-----------------------------------------------------------------*/
1146 static void genAddrOf (iCode * ic) {
1147 operand *left=IC_LEFT(ic);
1149 printIc ("genAddrOf", ic, 1,1,0);
1151 aopOp (IC_RESULT(ic),TRUE, FALSE);
1153 if (isOperandOnStack(left)) {
1154 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1155 getStackOffset(OP_SYMBOL(left)->stack));
1156 if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1157 // this must be a generic pointer
1158 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1163 if (isOperandInDirSpace(left) ||
1164 isOperandInFarSpace(left) ||
1165 isOperandInCodeSpace(left)) {
1166 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1167 OP_SYMBOL(left)->rname);
1168 if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1169 // this must be a generic pointer
1170 int space=0; // dir space
1171 if (isOperandInFarSpace(left)) {
1173 } else if (isOperandInCodeSpace(left)) {
1176 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1181 bailOut("genAddrOf");
1184 /*-----------------------------------------------------------------*/
1185 /* genAssign - generate code for assignment */
1186 /*-----------------------------------------------------------------*/
1187 static void genAssign (iCode * ic) {
1188 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1192 printIc ("genAssign", ic, 1,0,1);
1194 if (!IS_SYMOP(result)) {
1195 bailOut("genAssign: result is not a symbol");
1198 aopOp(result, TRUE, FALSE);
1199 aopOp(right, FALSE, aopIsPtr(result));
1200 size=AOP_SIZE(result);
1202 /* if result is a bit */
1203 if (AOP_TYPE(result) == AOP_BIT) {
1204 /* if right is literal, we know what the value is */
1205 if (AOP_TYPE(right) == AOP_LIT) {
1206 if (operandLitValue(right)) {
1207 emitcode ("setb", AOP_NAME(result)[0]);
1209 emitcode ("clr", AOP_NAME(result)[0]);
1213 /* if right is also a bit */
1214 if (AOP_TYPE(right) == AOP_BIT) {
1215 emitcode ("mov", "c,%s", AOP_NAME(right));
1216 emitcode ("mov", "%s,c", AOP_NAME(result));
1220 emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
1230 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1232 if (AOP_SIZE(result) > 2) {
1239 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1244 /*-----------------------------------------------------------------*/
1245 /* genJumpTab - genrates code for jump table */
1246 /*-----------------------------------------------------------------*/
1247 static void genJumpTab (iCode * ic) {
1248 printIc ("genJumpTab", ic, 0,0,0);
1251 /*-----------------------------------------------------------------*/
1252 /* genCast - gen code for casting */
1253 /*-----------------------------------------------------------------*/
1254 static void genCast (iCode * ic) {
1255 printIc ("genCast", ic, 1,1,1);
1258 /*-----------------------------------------------------------------*/
1259 /* genDjnz - generate decrement & jump if not zero instrucion */
1260 /*-----------------------------------------------------------------*/
1261 static bool genDjnz (iCode * ic, iCode * ifx) {
1267 /* if the if condition has a false label
1268 then we cannot save */
1272 /* if the minus is not of the form
1274 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1275 !IS_OP_LITERAL (IC_RIGHT (ic)))
1278 if (operandLitValue (IC_RIGHT (ic)) != 1)
1281 /* if the size of this greater than two then no
1283 if (getSize (operandType (IC_RESULT (ic))) > 2)
1286 printIc ("genDjnz", ic, 1,1,1);
1288 /* otherwise we can save BIG */
1289 lbl = newiTempLabel (NULL);
1290 lbl1 = newiTempLabel (NULL);
1292 aopOp (IC_RESULT (ic), TRUE, FALSE);
1294 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1295 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1296 emitcode ("br", "%05d$", lbl1->key + 100);
1297 emitcode ("", "%05d$:", lbl->key + 100);
1298 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1299 emitcode ("", "%05d$:", lbl1->key + 100);
1303 bailOut("genDjnz: aop type");
1307 /*-----------------------------------------------------------------*/
1308 /* genReceive - generate code for a receive iCode */
1309 /*-----------------------------------------------------------------*/
1310 static void genReceive (iCode * ic) {
1311 printIc ("genReceive", ic, 1,0,0);
1314 /*-----------------------------------------------------------------*/
1315 /* gen51Code - generate code for 8051 based controllers */
1316 /*-----------------------------------------------------------------*/
1317 void genXA51Code (iCode * lic) {
1321 lineHead = lineCurr = NULL;
1323 /* print the allocation information */
1325 printAllocInfo (currFunc, codeOutFile);
1327 /* if debug information required */
1328 if (options.debug && currFunc)
1330 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1332 if (IS_STATIC (currFunc->etype))
1333 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1335 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1339 for (ic = lic; ic; ic = ic->next) {
1340 if (cln != ic->lineno) {
1341 if (options.debug) {
1343 emitcode ("", "C$%s$%d$%d$%d ==.",
1344 FileBaseName (ic->filename), ic->lineno,
1345 ic->level, ic->block);
1348 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1349 printCLine(ic->filename, ic->lineno));
1352 /* if the result is marked as
1353 spilt and rematerializable or code for
1354 this has already been generated then
1356 if (resultRemat (ic) || ic->generated)
1359 /* depending on the operation */
1379 /* IPOP happens only when trying to restore a
1380 spilt live range, if there is an ifx statement
1381 following this pop then the if statement might
1382 be using some of the registers being popped which
1383 would destory the contents of the register so
1384 we need to check for this condition and handle it */
1386 ic->next->op == IFX &&
1387 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1388 genIfx (ic->next, ic);
1406 genEndFunction (ic);
1426 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1475 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1479 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1483 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1510 case GET_VALUE_AT_ADDRESS:
1511 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
1515 if (POINTER_SET (ic))
1516 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1542 addSet (&_G.sendSet, ic);
1551 /* now we are ready to call the
1552 peep hole optimizer */
1553 if (!options.nopeep)
1554 peepHole (&lineHead);
1556 /* now do the actual printing */
1557 printLine (lineHead, codeOutFile);