1 /* The only ops for now are:
8 /*-------------------------------------------------------------------------
9 SDCCgen51.c - source file for code generation for 8051
11 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
12 and - Jean-Louis VERN.jlvern@writeme.com (1999)
13 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
15 This program is free software; you can redistribute it and/or modify it
16 under the terms of the GNU General Public License as published by the
17 Free Software Foundation; either version 2, or (at your option) any
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 In other words, you are welcome to use, share and improve this program.
30 You are forbidden to forbid anyone else to use, share and improve
31 what you give them. Help stamp out software-hoarding!
34 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
35 Made everything static
36 -------------------------------------------------------------------------*/
45 #include "SDCCglobl.h"
48 #ifdef HAVE_SYS_ISA_DEFS_H
49 #include <sys/isa_defs.h>
51 #ifdef HAVE_MACHINE_ENDIAN_H
52 #include <machine/endian.h>
57 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
58 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
59 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
66 #include "SDCCpeeph.h"
70 #if defined(__BORLANDC__) || defined(_MSC_VER)
71 #define STRCASECMP stricmp
73 #define STRCASECMP strcasecmp
78 /* this is the down and dirty file with all kinds of
79 kludgy & hacky stuff. This is what it is all about
80 CODE GENERATION for a specific MCU . some of the
81 routines may be reusable, will have to see */
92 extern int xa51_ptrRegReq;
93 extern int xa51_nRegs;
94 extern FILE *codeOutFile;
96 static lineNode *lineHead = NULL;
97 static lineNode *lineCurr = NULL;
104 void bailOut (char *mesg) {
105 fprintf (stderr, "%s: bailing out\n", mesg);
109 /*-----------------------------------------------------------------*/
110 /* emitcode - writes the code into a file : for now it is simple */
111 /*-----------------------------------------------------------------*/
112 static void emitcode (char *inst, char *fmt,...) {
114 char lb[INITIAL_INLINEASM];
122 sprintf (lb, "%s\t", inst);
124 sprintf (lb, "%s", inst);
125 vsprintf (lb + (strlen (lb)), fmt, ap);
128 vsprintf (lb, fmt, ap);
130 while (isspace ((int)*lbp))
134 lineCurr = (lineCurr ?
135 connectLine (lineCurr, newLineNode (lb)) :
136 (lineHead = newLineNode (lb)));
137 lineCurr->isInline = _G.inLine;
138 lineCurr->isDebug = _G.debugLine;
142 /*-----------------------------------------------------------------*/
143 /* newAsmop - creates a new asmOp */
144 /*-----------------------------------------------------------------*/
146 newAsmop (short type)
150 aop = Safe_calloc (1, sizeof (asmop));
155 char *aopTypeName(asmop *aop) {
158 case AOP_LIT: return "lit";
159 case AOP_REG: return "reg";
160 case AOP_DIR: return "dir";
161 case AOP_FAR: return "far";
162 case AOP_CODE: return "code";
163 case AOP_STK: return "stack";
164 case AOP_IMMD: return "imm";
165 case AOP_CRY: return "bit";
170 /*-----------------------------------------------------------------*/
171 /* aopForSym - for a true symbol */
172 /*-----------------------------------------------------------------*/
173 static asmop *aopForSym(symbol *sym, bool result) {
176 sym->aop = aop = newAsmop(0);
177 aop->size=getSize(sym->type);
179 // if it is in registers
180 if (sym->nRegs && sym->regs[0]) {
182 sprintf (aop->name[0], sym->regs[0]->name);
184 sprintf (aop->name[1], sym->regs[1]->name);
192 sprintf (aop->name[0], "[r7%+d+0%+d%+d]", sym->stack,
193 FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
195 sprintf (aop->name[1], "[r7%+d+2%+d%+d]", sym->stack,
196 FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
201 // if it has a spillLoc
202 if (sym->usl.spillLoc) {
203 return aopForSym (sym->usl.spillLoc, result);
207 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
209 sprintf (aop->name[0], sym->rname);
213 // if in direct space
214 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
216 sprintf (aop->name[0], sym->rname);
221 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
223 fprintf (stderr, "aopForSym: result can not be in code space\n");
227 emitcode ("mov", "r0,#%s", sym->rname);
228 sprintf (aop->name[0], "r0");
233 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
235 emitcode ("mov", "r0,#%s", sym->rname);
236 sprintf (aop->name[0], "r0");
240 fprintf (stderr, "aopForSym (%s): What's up?\n", sym->name);
244 /*-----------------------------------------------------------------*/
245 /* aopForVal - for a value */
246 /*-----------------------------------------------------------------*/
247 static asmop *aopForVal(operand *op) {
249 long v=(long long)floatFromVal(OP_VALUE(op));
251 if (IS_OP_LITERAL(op)) {
252 op->aop = aop = newAsmop (AOP_LIT);
253 switch ((aop->size=getSize(operandType(op))))
256 sprintf (aop->name[0], "#0x%02lx", v);
259 sprintf (aop->name[0], "#0x%04lx", v);
262 sprintf (aop->name[0], "#(0x%08lx >> 16)", v);
263 sprintf (aop->name[1], "#(0x%08lx & 0xffff)", v);
266 bailOut("aopForVal");
273 op->aop = aop = newAsmop (AOP_IMMD);
274 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
278 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
280 case 3: // generic pointer
281 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
282 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
286 fprintf (stderr, "aopForVal: unknown type\n");
291 static void aopOp(operand *op, bool result) {
294 op->aop=aopForSym (OP_SYMBOL(op), result);
299 fprintf (stderr, "aopOp: result can not be a value\n");
306 fprintf (stderr, "aopOp: unexpected operand\n");
310 char *opRegName(operand *op, int offset, char *opName) {
313 if (OP_SYMBOL(op)->onStack) {
314 sprintf (opName, "[r7%+d+0%+d%+d]", OP_SYMBOL(op)->stack,
315 FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
318 if (IS_TRUE_SYMOP(op))
319 return OP_SYMBOL(op)->rname;
320 else if (OP_SYMBOL(op)->regs[offset])
321 return OP_SYMBOL(op)->regs[offset]->name;
327 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
330 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
331 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
332 fprintf (stderr, "opRegName: invalid bit value (%d)\n",
333 SPEC_CVAL(OP_VALUE(op)->type).v_int);
338 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
341 if (SPEC_LONG(OP_VALUE(op)->type)) {
342 sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
344 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
348 sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
351 fprintf (stderr, "opRegName: unexpected noun\n");
356 fprintf (stderr, "opRegName: unexpected operand type\n");
358 return NULL; // to keep the compiler happy
361 char * printOp (operand *op) {
362 static char line[132];
363 sym_link *optype=operandType(op);
364 bool isPtr = IS_PTR(optype);
367 symbol *sym=OP_SYMBOL(op);
368 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
369 sym=SYM_SPIL_LOC(sym);
373 if (DCL_TYPE(optype)==FPOINTER)
374 strcat (line, "far * ");
375 else if (DCL_TYPE(optype)==CPOINTER)
376 strcat (line, "code * ");
377 else if (DCL_TYPE(optype)==GPOINTER)
378 strcat (line, "gen * ");
379 else if (DCL_TYPE(optype)==POINTER)
380 strcat (line, "near * ");
382 strcat (line, "unknown * ");
384 strcat (line, nounName(sym->etype));
386 strcat (line, sym->name);
389 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
392 strcat (line, sym->regs[0]->name);
395 strcat (line, sym->regs[1]->name);
400 sprintf (line+strlen(line), "stack%+d", sym->stack);
403 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
404 strcat (line, "far");
407 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
408 strcat (line, "bit");
411 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
412 strcat (line, "dir");
415 strcat (line, "unknown");
417 } else if (IS_VALOP(op)) {
418 opRegName(op, 0, line);
419 } else if (IS_TYPOP(op)) {
422 if (DCL_TYPE(optype)==FPOINTER)
423 strcat (line, "far * ");
424 else if (DCL_TYPE(optype)==CPOINTER)
425 strcat (line, "code * ");
426 else if (DCL_TYPE(optype)==GPOINTER)
427 strcat (line, "gen * ");
428 else if (DCL_TYPE(optype)==POINTER)
429 strcat (line, "near * ");
431 strcat (line, "unknown * ");
433 // forget about static, volatile, ... for now
434 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
435 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
436 strcat (line, nounName(operandType(op)));
439 fprintf (stderr, "printOp: unexpected operand type\n");
445 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
448 sprintf (line, "%s(%d)", op, ic->lineno);
450 strcat (line, " result=");
451 strcat (line, printOp (IC_RESULT(ic)));
454 strcat (line, " left=");
455 strcat (line, printOp (IC_LEFT(ic)));
458 strcat (line, " right=");
459 strcat (line, printOp (IC_RIGHT(ic)));
461 emitcode (";", line);
464 /*-----------------------------------------------------------------*/
465 /* toBoolean - return bit for operand!=0 */
466 /*-----------------------------------------------------------------*/
467 static char *toBoolean (operand * op) {
468 switch (AOP_SIZE(op))
472 emitcode ("cmp", "%s,#0", AOP_NAME(op));
476 fprintf (stderr, "toBoolean: unknown size %d\n", AOP_SIZE(op));
481 /*-----------------------------------------------------------------*/
482 /* regsInCommon - two operands have some registers in common */
483 /*-----------------------------------------------------------------*/
484 static bool regsInCommon (operand * op1, operand * op2) {
488 /* if they have registers in common */
489 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
492 sym1 = OP_SYMBOL (op1);
493 sym2 = OP_SYMBOL (op2);
495 if (sym1->nRegs == 0 || sym2->nRegs == 0)
498 for (i = 0; i < sym1->nRegs; i++)
504 for (j = 0; j < sym2->nRegs; j++)
509 if (sym2->regs[j] == sym1->regs[i])
517 /*-----------------------------------------------------------------*/
518 /* resultRemat - result is rematerializable */
519 /*-----------------------------------------------------------------*/
520 static int resultRemat (iCode * ic) {
521 if (SKIP_IC (ic) || ic->op == IFX)
524 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
526 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
527 if (sym->remat && !POINTER_SET (ic))
534 /*-----------------------------------------------------------------*/
535 /* genNot - generate code for ! operation */
536 /*-----------------------------------------------------------------*/
537 static void genNot (iCode * ic) {
538 printIc("genNot:", ic, 1,1,0);
541 /*-----------------------------------------------------------------*/
542 /* genCpl - generate code for complement */
543 /*-----------------------------------------------------------------*/
544 static void genCpl (iCode * ic) {
545 printIc("genCpl", ic, 1,1,0);
548 /*-----------------------------------------------------------------*/
549 /* genUminus - unary minus code generation */
550 /*-----------------------------------------------------------------*/
551 static void genUminus (iCode * ic) {
552 printIc("genUminus", ic, 1,1,0);
555 /*-----------------------------------------------------------------*/
556 /* genIpush - genrate code for pushing this gets a little complex */
557 /*-----------------------------------------------------------------*/
558 static void genIpush (iCode * ic) {
559 printIc ("genIpush", ic, 0,1,0);
562 /*-----------------------------------------------------------------*/
563 /* genIpop - recover the registers: can happen only for spilling */
564 /*-----------------------------------------------------------------*/
565 static void genIpop (iCode * ic) {
566 printIc ("genIpop", ic, 0,1,0);
569 /*-----------------------------------------------------------------*/
570 /* genCall - generates a call statement */
571 /*-----------------------------------------------------------------*/
572 static void genCall (iCode * ic) {
573 emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
574 printOp (IC_RESULT(ic)));
577 /*-----------------------------------------------------------------*/
578 /* genPcall - generates a call by pointer statement */
579 /*-----------------------------------------------------------------*/
581 genPcall (iCode * ic)
583 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
586 /*-----------------------------------------------------------------*/
587 /* genFunction - generated code for function entry */
588 /*-----------------------------------------------------------------*/
589 static void genFunction (iCode * ic) {
590 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
591 sym_link *type=sym->type;
593 emitcode (";", "-----------------------------------------");
594 emitcode (";", " function %s", sym->name);
595 emitcode (";", "-----------------------------------------");
597 emitcode ("", "%s:", sym->rname);
599 if (IFFUNC_ISNAKED(type))
601 emitcode(";", "naked function: no prologue.");
605 /* if critical function then turn interrupts off */
606 if (IFFUNC_ISCRITICAL (type))
607 emitcode ("clr", "ea");
611 /*-----------------------------------------------------------------*/
612 /* genEndFunction - generates epilogue for functions */
613 /*-----------------------------------------------------------------*/
615 genEndFunction (iCode * ic)
617 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
619 if (IFFUNC_ISNAKED(sym->type))
621 emitcode(";", "naked function: no epilogue.");
625 printIc ("genEndFunction", ic, 0,0,0);
628 /*-----------------------------------------------------------------*/
629 /* genRet - generate code for return statement */
630 /*-----------------------------------------------------------------*/
631 static void genRet (iCode * ic) {
632 printIc ("genRet", ic, 0,1,0);
635 /*-----------------------------------------------------------------*/
636 /* genLabel - generates a label */
637 /*-----------------------------------------------------------------*/
638 static void genLabel (iCode * ic) {
639 /* special case never generate */
640 if (IC_LABEL (ic) == entryLabel)
643 emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
644 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
647 /*-----------------------------------------------------------------*/
648 /* genGoto - generates a ljmp */
649 /*-----------------------------------------------------------------*/
650 static void genGoto (iCode * ic) {
651 emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
652 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
655 /*-----------------------------------------------------------------*/
656 /* genPlus - generates code for addition */
657 /*-----------------------------------------------------------------*/
658 static void genPlus (iCode * ic) {
659 printIc ("genPlus", ic, 1,1,1);
662 /*-----------------------------------------------------------------*/
663 /* genMinus - generates code for subtraction */
664 /*-----------------------------------------------------------------*/
665 static void genMinus (iCode * ic) {
666 printIc ("genMinus", ic, 1,1,1);
670 /*-----------------------------------------------------------------*/
671 /* genMult - generates code for multiplication */
672 /*-----------------------------------------------------------------*/
673 static void genMult (iCode * ic) {
674 printIc ("genMult", ic, 1,1,1);
677 /*-----------------------------------------------------------------*/
678 /* genDiv - generates code for division */
679 /*-----------------------------------------------------------------*/
680 static void genDiv (iCode * ic) {
681 printIc ("genDiv", ic, 1,1,1);
684 /*-----------------------------------------------------------------*/
685 /* genMod - generates code for division */
686 /*-----------------------------------------------------------------*/
687 static void genMod (iCode * ic) {
688 printIc ("genMod", ic, 1,1,1);
691 /*-----------------------------------------------------------------*/
692 /* genCmpGt :- greater than comparison */
693 /*-----------------------------------------------------------------*/
694 static void genCmpGt (iCode * ic, iCode * ifx) {
695 printIc ("genCmpGt", ic, 1,1,1);
697 /*-----------------------------------------------------------------*/
698 /* genCmpLt - less than comparisons */
699 /*-----------------------------------------------------------------*/
700 static void genCmpLt (iCode * ic, iCode * ifx) {
701 printIc ("genCmpLt", ic, 1,1,1);
703 /*-----------------------------------------------------------------*/
704 /* genCmpEq - generates code for equal to */
705 /*-----------------------------------------------------------------*/
706 static void genCmpEq (iCode * ic, iCode * ifx) {
707 printIc ("genCmpEq", ic, 1,1,1);
710 /*-----------------------------------------------------------------*/
711 /* ifxForOp - returns the icode containing the ifx for operand */
712 /*-----------------------------------------------------------------*/
713 static iCode *ifxForOp (operand * op, iCode * ic) {
714 /* if true symbol then needs to be assigned */
715 if (IS_TRUE_SYMOP (op))
718 /* if this has register type condition and
719 the next instruction is ifx with the same operand
720 and live to of the operand is upto the ifx only then */
722 ic->next->op == IFX &&
723 IC_COND (ic->next)->key == op->key &&
724 OP_SYMBOL (op)->liveTo <= ic->next->seq)
730 /*-----------------------------------------------------------------*/
731 /* hasInc - operand is incremented before any other use */
732 /*-----------------------------------------------------------------*/
733 static iCode *hasInc (operand *op, iCode *ic, int osize) {
734 sym_link *type = operandType(op);
735 sym_link *retype = getSpec (type);
736 iCode *lic = ic->next;
739 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
740 if (!IS_SYMOP(op)) return NULL;
742 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
743 if (IS_AGGREGATE(type->next)) return NULL;
744 if (osize != (isize = getSize(type->next))) return NULL;
747 /* if operand of the form op = op + <sizeof *op> */
748 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
749 isOperandEqual(IC_RESULT(lic),op) &&
750 isOperandLiteral(IC_RIGHT(lic)) &&
751 operandLitValue(IC_RIGHT(lic)) == isize) {
754 /* if the operand used or deffed */
755 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
759 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
765 /*-----------------------------------------------------------------*/
766 /* genAndOp - for && operation */
767 /*-----------------------------------------------------------------*/
768 static void genAndOp (iCode * ic) {
769 printIc ("genAndOp(&&)", ic, 1,1,1);
772 /*-----------------------------------------------------------------*/
773 /* genOrOp - for || operation */
774 /*-----------------------------------------------------------------*/
775 static void genOrOp (iCode * ic) {
776 printIc ("genOrOp(||)", ic, 1,1,1);
779 /*-----------------------------------------------------------------*/
780 /* genAnd - code for and */
781 /*-----------------------------------------------------------------*/
782 static void genAnd (iCode * ic, iCode * ifx) {
783 printIc ("genAnd", ic, 1,1,1);
786 /*-----------------------------------------------------------------*/
787 /* genOr - code for or */
788 /*-----------------------------------------------------------------*/
789 static void genOr (iCode * ic, iCode * ifx) {
790 printIc ("genOr", ic, 1,1,1);
793 /*-----------------------------------------------------------------*/
794 /* genXor - code for xclusive or */
795 /*-----------------------------------------------------------------*/
796 static void genXor (iCode * ic, iCode * ifx) {
797 printIc ("genXor", ic, 1,1,1);
800 /*-----------------------------------------------------------------*/
801 /* genInline - write the inline code out */
802 /*-----------------------------------------------------------------*/
803 static void genInline (iCode * ic) {
804 printIc ("genInline", ic, 0,0,0);
807 /*-----------------------------------------------------------------*/
808 /* genRRC - rotate right with carry */
809 /*-----------------------------------------------------------------*/
810 static void genRRC (iCode * ic) {
811 printIc ("genRRC", ic, 1,1,0);
814 /*-----------------------------------------------------------------*/
815 /* genRLC - generate code for rotate left with carry */
816 /*-----------------------------------------------------------------*/
817 static void genRLC (iCode * ic) {
818 printIc ("genRLC", ic, 1,1,0);
821 /*-----------------------------------------------------------------*/
822 /* genGetHbit - generates code get highest order bit */
823 /*-----------------------------------------------------------------*/
824 static void genGetHbit (iCode * ic) {
825 printIc ("genGetHbit", ic, 1,1,0);
828 /*-----------------------------------------------------------------*/
829 /* genLeftShift - generates code for left shifting */
830 /*-----------------------------------------------------------------*/
831 static void genLeftShift (iCode * ic) {
832 printIc ("genLeftShift", ic, 1,1,1);
835 /*-----------------------------------------------------------------*/
836 /* genRightShift - generate code for right shifting */
837 /*-----------------------------------------------------------------*/
838 static void genRightShift (iCode * ic) {
839 printIc ("genRightShift", ic, 1,1,1);
842 /*-----------------------------------------------------------------*/
843 /* genPointerGet - generate code for pointer get */
844 /*-----------------------------------------------------------------*/
845 static void genPointerGet (iCode * ic, iCode *pi) {
848 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
850 printIc ("genPointerGet", ic, 1,1,0);
852 if (!IS_PTR(operandType(left))) {
853 bailOut ("genPointerGet: pointer required");
859 if (IS_GENPTR(operandType(left))) {
860 emitcode ("INLINE", "_gptrget %s %s= [%s,%s]",
861 AOP_NAME(result)[0], AOP_NAME(result)[1],
862 AOP_NAME(left)[0], AOP_NAME(left)[1]);
866 switch (AOP_TYPE(left))
875 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
876 if (AOP_SIZE(result) > 2) {
877 emitcode (instr, "%s,[%s]", AOP_NAME(result)[1], AOP_NAME(left)[1]);
882 bailOut ("genPointerGet: unknown pointer");
885 /*-----------------------------------------------------------------*/
886 /* genPointerSet - stores the value into a pointer location */
887 /*-----------------------------------------------------------------*/
888 static void genPointerSet (iCode * ic, iCode *pi) {
891 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
893 printIc ("genPointerSet", ic, 1,0,1);
895 if (!IS_PTR(operandType(result))) {
896 bailOut ("genPointerSet: pointer required");
902 if (IS_GENPTR(operandType(result))) {
903 emitcode ("INLINE", "_gptrset %s,%s= [%s,%s]",
904 AOP_NAME(result)[0], AOP_NAME(result)[1],
905 AOP_NAME(right)[0], AOP_NAME(right)[1]);
909 switch (AOP_TYPE(result))
918 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
919 if (AOP_SIZE(result) > 2) {
920 emitcode (instr, "[%s],%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
925 bailOut ("genPointerSet: unknown pointer");
928 /*-----------------------------------------------------------------*/
929 /* genIfx - generate code for Ifx statement */
930 /*-----------------------------------------------------------------*/
931 static void genIfx (iCode * ic, iCode * popIc) {
934 operand *cond=IC_COND(ic);
936 emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s",
938 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
939 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
951 switch (AOP_TYPE(cond) )
954 emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$",
955 AOP_NAME(cond)[0], jlbl->key+100);
961 tlbl=newiTempLabel(NULL);
962 emitcode ("cmp", "%s,#0", AOP_NAME(cond)[0]);
963 emitcode (trueOrFalse ? "bne" : "beq", "%05d$", tlbl->key+100);
964 if (AOP_SIZE(cond) > 2) {
965 emitcode ("cmp", "%s,#0", AOP_NAME(cond)[1]);
966 emitcode (trueOrFalse ? "bne" : "beq", "%05d$", tlbl->key+100);
968 emitcode ("jmp", "%05d$", jlbl->key+100);
969 emitcode ("", "%05d$:", tlbl->key+100);
975 /*-----------------------------------------------------------------*/
976 /* genAddrOf - generates code for address of */
977 /*-----------------------------------------------------------------*/
978 static void genAddrOf (iCode * ic) {
979 operand *left=IC_LEFT(ic);
981 printIc ("genAddrOf", ic, 1,1,0);
983 aopOp (IC_RESULT(ic),TRUE);
985 if (isOperandOnStack(left)) {
986 aopOp (IC_LEFT(ic),FALSE);
987 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
988 AOP_NAME(IC_LEFT(ic))[0]);
989 if (AOP_SIZE(IC_RESULT(ic)) > 2) {
990 // this must be a generic pointer
991 emitcode ("mov", "%s,#0x01", AOP_NAME(IC_RESULT(ic))[1]);
996 if (isOperandInDirSpace(left) ||
997 isOperandInFarSpace(left) ||
998 isOperandInCodeSpace(left)) {
999 emitcode ("mov", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1001 if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1002 // this must be a generic pointer
1003 int space=0; // dir space
1004 if (isOperandInFarSpace(left)) {
1006 } else if (isOperandInCodeSpace(left)) {
1009 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1014 bailOut("genAddrOf");
1017 /*-----------------------------------------------------------------*/
1018 /* genAssign - generate code for assignment */
1019 /*-----------------------------------------------------------------*/
1020 static void genAssign (iCode * ic) {
1021 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1023 printIc ("genAssign", ic, 1,0,1);
1025 if (!IS_SYMOP(result)) {
1026 fprintf (stderr, "genAssign: result is not a symbol\n");
1030 aopOp(right, FALSE);
1031 aopOp(result, TRUE);
1033 if (result->aop->type==AOP_REG ||
1034 right->aop->type==AOP_REG ||
1035 right->aop->type==AOP_LIT ||
1036 right->aop->type==AOP_STK ||
1037 right->aop->type==AOP_IMMD) {
1038 // everything will do
1040 // they have to match
1041 if (result->aop->type != right->aop->type) {
1042 fprintf (stderr, "genAssign: types don't match (%s!=%s)\n",
1043 aopTypeName(result->aop), aopTypeName(right->aop));
1048 /* if result is a bit */
1049 if (AOP_TYPE(result) == AOP_CRY) {
1050 /* if right is literal, we know what the value is */
1051 if (AOP_TYPE(right) == AOP_LIT) {
1052 if (operandLitValue(right)) {
1053 emitcode ("setb", AOP_NAME(result)[0]);
1055 emitcode ("clr", AOP_NAME(result)[0]);
1059 /* if right is also a bit */
1060 if (AOP_TYPE(right) == AOP_CRY) {
1061 emitcode ("mov", "c,%s", AOP_NAME(right));
1062 emitcode ("mov", "%s,c", AOP_NAME(result));
1066 emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
1071 emitcode ("mov", "%s,%s",
1072 result->aop->name[0], right->aop->name[0]);
1073 if (AOP_SIZE(result) > 2) {
1074 emitcode ("mov", "%s,%s",
1075 result->aop->name[1], right->aop->name[1]);
1080 /*-----------------------------------------------------------------*/
1081 /* genJumpTab - genrates code for jump table */
1082 /*-----------------------------------------------------------------*/
1083 static void genJumpTab (iCode * ic) {
1084 printIc ("genJumpTab", ic, 0,0,0);
1087 /*-----------------------------------------------------------------*/
1088 /* genCast - gen code for casting */
1089 /*-----------------------------------------------------------------*/
1090 static void genCast (iCode * ic) {
1091 printIc ("genCast", ic, 1,1,1);
1094 /*-----------------------------------------------------------------*/
1095 /* genDjnz - generate decrement & jump if not zero instrucion */
1096 /*-----------------------------------------------------------------*/
1097 static bool genDjnz (iCode * ic, iCode * ifx) {
1098 printIc ("genDjnz", ic, 0,0,0);
1102 /*-----------------------------------------------------------------*/
1103 /* genReceive - generate code for a receive iCode */
1104 /*-----------------------------------------------------------------*/
1105 static void genReceive (iCode * ic) {
1106 printIc ("genReceive", ic, 1,0,0);
1109 /*-----------------------------------------------------------------*/
1110 /* gen51Code - generate code for 8051 based controllers */
1111 /*-----------------------------------------------------------------*/
1112 void genXA51Code (iCode * lic) {
1116 fprintf (stderr, "genXA51Code\n");
1117 lineHead = lineCurr = NULL;
1119 /* print the allocation information */
1121 printAllocInfo (currFunc, codeOutFile);
1123 /* if debug information required */
1124 if (options.debug && currFunc)
1126 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1128 if (IS_STATIC (currFunc->etype))
1129 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1131 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1135 for (ic = lic; ic; ic = ic->next) {
1136 if (cln != ic->lineno) {
1137 if (options.debug) {
1139 emitcode ("", "C$%s$%d$%d$%d ==.",
1140 FileBaseName (ic->filename), ic->lineno,
1141 ic->level, ic->block);
1144 emitcode (";", "%s %d", ic->filename, ic->lineno);
1147 /* if the result is marked as
1148 spilt and rematerializable or code for
1149 this has already been generated then
1151 if (resultRemat (ic) || ic->generated)
1154 /* depending on the operation */
1174 /* IPOP happens only when trying to restore a
1175 spilt live range, if there is an ifx statement
1176 following this pop then the if statement might
1177 be using some of the registers being popped which
1178 would destory the contents of the register so
1179 we need to check for this condition and handle it */
1181 ic->next->op == IFX &&
1182 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1183 genIfx (ic->next, ic);
1201 genEndFunction (ic);
1221 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1238 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
1242 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
1249 /* note these two are xlated by algebraic equivalence
1250 during parsing SDCC.y */
1251 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1252 "got '>=' or '<=' shouldn't have come here");
1256 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
1268 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1272 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1276 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1303 case GET_VALUE_AT_ADDRESS:
1304 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
1308 if (POINTER_SET (ic))
1309 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1335 addSet (&_G.sendSet, ic);
1344 /* now we are ready to call the
1345 peep hole optimizer */
1346 if (!options.nopeep)
1347 peepHole (&lineHead);
1349 /* now do the actual printing */
1350 printLine (lineHead, codeOutFile);