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!
26 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
41 #ifdef HAVE_MACHINE_ENDIAN_H
42 #include <machine/endian.h>
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #include "SDCCpeeph.h"
60 #if defined(__BORLANDC__) || defined(_MSC_VER)
61 #define STRCASECMP stricmp
63 #define STRCASECMP strcasecmp
68 /* this is the down and dirty file with all kinds of
69 kludgy & hacky stuff. This is what it is all about
70 CODE GENERATION for a specific MCU . some of the
71 routines may be reusable, will have to see */
83 extern int xa51_ptrRegReq;
84 extern int xa51_nRegs;
85 extern FILE *codeOutFile;
87 static lineNode *lineHead = NULL;
88 static lineNode *lineCurr = NULL;
95 static char *MOV="mov";
96 static char *MOVB="mov.b";
97 static char *MOVW="mov.w";
98 static char *MOVC="movc";
99 static char *MOVCB="movc.b";
100 static char *MOVCW="movc.w";
102 static char *R1L="r1l";
103 static char *R1="r1";
105 void bailOut (char *mesg) {
106 fprintf (stderr, "%s: bailing out\n", mesg);
110 /*-----------------------------------------------------------------*/
111 /* emitcode - writes the code into a file : for now it is simple */
112 /*-----------------------------------------------------------------*/
113 static void emitcode (char *inst, char *fmt,...) {
115 char lb[INITIAL_INLINEASM];
123 sprintf (lb, "%s\t", inst);
125 sprintf (lb, "%s", inst);
126 vsprintf (lb + (strlen (lb)), fmt, ap);
129 vsprintf (lb, fmt, ap);
131 while (isspace ((int)*lbp))
135 lineCurr = (lineCurr ?
136 connectLine (lineCurr, newLineNode (lb)) :
137 (lineHead = newLineNode (lb)));
138 lineCurr->isInline = _G.inLine;
139 lineCurr->isDebug = _G.debugLine;
143 char *getStackOffset(int stack) {
144 static char gsoBuf[1024];
145 sprintf (gsoBuf, "r7+(%d%+d%+d%+d)", stack,
146 FUNC_ISISR(currFunc->type) ?
147 port->stack.isr_overhead : port->stack.call_overhead,
148 currFunc->stack, _G.nRegsSaved);
152 /*-----------------------------------------------------------------*/
153 /* newAsmop - creates a new asmOp */
154 /*-----------------------------------------------------------------*/
156 newAsmop (short type)
160 aop = Safe_calloc (1, sizeof (asmop));
165 char *aopTypeName(asmop *aop) {
168 case AOP_LIT: return "lit";
169 case AOP_REG: return "reg";
170 case AOP_DIR: return "dir";
171 case AOP_FAR: return "far";
172 case AOP_CODE: return "code";
173 case AOP_GPTR: return "gptr";
174 case AOP_STK: return "stack";
175 case AOP_IMMD: return "imm";
176 case AOP_BIT: return "bit";
181 /*-----------------------------------------------------------------*/
182 /* aopForSym - for a true symbol */
183 /*-----------------------------------------------------------------*/
184 static asmop *aopForSym(symbol *sym,
185 bool canUsePointer, bool canUseOffset) {
189 sym->aop = aop = newAsmop(0);
190 size=aop->size=getSize(sym->type);
192 // if the sym has registers
193 if (sym->nRegs && sym->regs[0]) {
195 sprintf (aop->name[0], sym->regs[0]->name);
197 sprintf (aop->name[1], sym->regs[1]->name);
204 if (!canUsePointer || !canUseOffset) {
209 emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
210 sprintf (aop->name[0], "r0l");
213 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
214 sprintf (aop->name[0], "r0");
217 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
218 sprintf (aop->name[0], "r0");
219 emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
220 sprintf (aop->name[1], "r1l");
223 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
224 sprintf (aop->name[0], "r0");
225 emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
226 sprintf (aop->name[1], "r1");
231 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
233 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
238 // if it has a spillLoc
239 if (sym->usl.spillLoc) {
240 return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
244 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
246 sprintf (aop->name[0], sym->rname);
250 // if in direct space
251 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
253 sprintf (aop->name[0], sym->rname);
255 sprintf (aop->name[1], "%s+2", sym->rname);
261 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
262 if (!canUsePointer) {
267 emitcode (MOV, "r0,#%s", sym->rname);
268 emitcode (MOVC, "r0l,[r0]");
269 sprintf (aop->name[0], "r0l");
272 emitcode (MOV, "r0,#%s", sym->rname);
273 emitcode (MOVC, "r0,[r0]");
274 sprintf (aop->name[0], "r0");
277 emitcode (MOV, "r0,#%s", sym->rname);
278 emitcode (MOVC, "r1l,[r0+2]");
279 sprintf (aop->name[1], "r1l");
280 emitcode (MOV, "r0,[r0]");
281 sprintf (aop->name[0], "r0");
284 emitcode (MOV, "r0,#%s", sym->rname);
285 emitcode (MOVC, "r1,[r0+2]");
286 sprintf (aop->name[1], "r1");
287 emitcode (MOVC, "r0,[r0]");
288 sprintf (aop->name[0], "r0");
294 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
295 sprintf (aop->name[0], "[r0]");
297 sprintf (aop->name[1], "[r0+2]");
304 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
305 if (!canUsePointer) {
310 emitcode (MOV, "r0,#%s", sym->rname);
311 emitcode (MOV, "r0l,[r0]");
312 sprintf (aop->name[0], "r0l");
315 emitcode (MOV, "r0,#%s", sym->rname);
316 emitcode (MOV, "r0,[r0]");
317 sprintf (aop->name[0], "r0");
320 emitcode (MOV, "r0,#%s", sym->rname);
321 emitcode (MOV, "r1l,[r0+2]");
322 sprintf (aop->name[1], "r1l");
323 emitcode (MOV, "r0,[r0]");
324 sprintf (aop->name[0], "r0");
327 emitcode (MOV, "r0,#%s", sym->rname);
328 emitcode (MOV, "r1,[r0+2]");
329 sprintf (aop->name[1], "r1");
330 emitcode (MOV, "r0,[r0]");
331 sprintf (aop->name[0], "r0");
336 emitcode ("mov", "r0,#%s ; aopForSym:far", sym->rname);
337 sprintf (aop->name[0], "[r0]");
339 sprintf (aop->name[1], "[r0+2]");
345 bailOut("aopForSym");
349 /*-----------------------------------------------------------------*/
350 /* aopForVal - for a value */
351 /*-----------------------------------------------------------------*/
352 static asmop *aopForVal(operand *op) {
355 if (IS_OP_LITERAL(op)) {
356 op->aop = aop = newAsmop (AOP_LIT);
357 switch ((aop->size=getSize(operandType(op))))
360 sprintf (aop->name[0], "#0x%02x",
361 SPEC_CVAL(operandType(op)).v_int & 0xff);
362 sprintf (aop->name[1], "#0");
365 sprintf (aop->name[0], "#0x%04x",
366 SPEC_CVAL(operandType(op)).v_int & 0xffff);
367 sprintf (aop->name[1], "#0");
370 // must be a generic pointer, can only be zero
371 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
372 sprintf (aop->name[0], "#0x%04x",
373 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
374 sprintf (aop->name[1], "#0");
377 sprintf (aop->name[0], "#0x%04lx",
378 SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
379 sprintf (aop->name[1], "#0x%04lx",
380 SPEC_CVAL(operandType(op)).v_ulong >> 16);
383 bailOut("aopForVal");
390 op->aop = aop = newAsmop (AOP_IMMD);
391 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
395 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
397 case 3: // generic pointer
398 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
399 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
404 bailOut ("aopForVal: unknown type");
408 static int aopOp(operand *op,
409 bool canUsePointer, bool canUseOffset) {
412 op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
416 op->aop=aopForVal (op);
420 bailOut("aopOp: unexpected operand");
424 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
425 if (strcmp(aop1->name[offset], aop2->name[offset])) {
431 bool aopIsDir(operand *op) {
432 return AOP_TYPE(op)==AOP_DIR;
435 bool aopIsBit(operand *op) {
436 return AOP_TYPE(op)==AOP_BIT;
439 bool aopIsPtr(operand *op) {
440 if (AOP_TYPE(op)==AOP_STK ||
441 AOP_TYPE(op)==AOP_CODE ||
442 AOP_TYPE(op)==AOP_FAR) {
449 char *opRegName(operand *op, int offset, char *opName) {
452 if (OP_SYMBOL(op)->onStack) {
453 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
456 if (IS_TRUE_SYMOP(op))
457 return OP_SYMBOL(op)->rname;
458 else if (OP_SYMBOL(op)->regs[offset])
459 return OP_SYMBOL(op)->regs[offset]->name;
461 bailOut("opRegName: unknown regs");
465 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
468 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
469 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
470 bailOut("opRegName: invalid bit value");
474 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
477 if (SPEC_LONG(OP_VALUE(op)->type)) {
478 sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
480 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
484 sprintf (opName, "#%f", SPEC_CVAL(OP_VALUE(op)->type).v_float);
487 bailOut("opRegName: unexpected noun");
491 bailOut("opRegName: unexpected operand type");
495 char * printOp (operand *op) {
496 static char line[132];
497 sym_link *optype=operandType(op);
498 bool isPtr = IS_PTR(optype);
501 symbol *sym=OP_SYMBOL(op);
502 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
503 sym=SYM_SPIL_LOC(sym);
507 if (DCL_TYPE(optype)==FPOINTER)
508 strcat (line, "far * ");
509 else if (DCL_TYPE(optype)==CPOINTER)
510 strcat (line, "code * ");
511 else if (DCL_TYPE(optype)==GPOINTER)
512 strcat (line, "gen * ");
513 else if (DCL_TYPE(optype)==POINTER)
514 strcat (line, "near * ");
516 strcat (line, "unknown * ");
518 strcat (line, nounName(sym->etype));
520 strcat (line, sym->name);
523 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
526 strcat (line, sym->regs[0]->name);
529 strcat (line, sym->regs[1]->name);
534 sprintf (line+strlen(line), "stack%+d", sym->stack);
537 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
538 strcat (line, "code");
541 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
542 strcat (line, "far");
545 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
546 strcat (line, "bit");
549 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
550 strcat (line, "dir");
553 strcat (line, "unknown");
555 } else if (IS_VALOP(op)) {
556 opRegName(op, 0, line);
557 } else if (IS_TYPOP(op)) {
560 if (DCL_TYPE(optype)==FPOINTER)
561 strcat (line, "far * ");
562 else if (DCL_TYPE(optype)==CPOINTER)
563 strcat (line, "code * ");
564 else if (DCL_TYPE(optype)==GPOINTER)
565 strcat (line, "gen * ");
566 else if (DCL_TYPE(optype)==POINTER)
567 strcat (line, "near * ");
569 strcat (line, "unknown * ");
571 // forget about static, volatile, ... for now
572 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
573 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
574 strcat (line, nounName(operandType(op)));
577 bailOut("printOp: unexpected operand type");
582 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
585 sprintf (line, "%s(%d)", op, ic->lineno);
587 strcat (line, " result=");
588 strcat (line, printOp (IC_RESULT(ic)));
591 strcat (line, " left=");
592 strcat (line, printOp (IC_LEFT(ic)));
595 strcat (line, " right=");
596 strcat (line, printOp (IC_RIGHT(ic)));
598 emitcode (";", line);
601 /*-----------------------------------------------------------------*/
602 /* toBoolean - return carry for operand!=0 */
603 /*-----------------------------------------------------------------*/
604 static char *toBoolean (operand * op) {
605 symbol *tlbl=newiTempLabel(NULL);
607 switch (AOP_SIZE(op))
611 emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
612 "This needs a second thought");
614 emitcode ("", "%05d$:", tlbl->key+100);
618 bailOut("toBoolean: unknown size");
622 /*-----------------------------------------------------------------*/
623 /* regsInCommon - two operands have some registers in common */
624 /*-----------------------------------------------------------------*/
625 static bool regsInCommon (operand * op1, operand * op2) {
629 /* if they have registers in common */
630 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
633 sym1 = OP_SYMBOL (op1);
634 sym2 = OP_SYMBOL (op2);
636 if (sym1->nRegs == 0 || sym2->nRegs == 0)
639 for (i = 0; i < sym1->nRegs; i++)
645 for (j = 0; j < sym2->nRegs; j++)
650 if (sym2->regs[j] == sym1->regs[i])
658 /*-----------------------------------------------------------------*/
659 /* resultRemat - result is rematerializable */
660 /*-----------------------------------------------------------------*/
661 static int resultRemat (iCode * ic) {
662 if (SKIP_IC (ic) || ic->op == IFX)
665 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
667 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
668 if (sym->remat && !POINTER_SET (ic))
675 /*-----------------------------------------------------------------*/
676 /* genNot - generate code for ! operation */
677 /*-----------------------------------------------------------------*/
678 static void genNot (iCode * ic) {
679 printIc("genNot:", ic, 1,1,0);
682 /*-----------------------------------------------------------------*/
683 /* genCpl - generate code for complement */
684 /*-----------------------------------------------------------------*/
685 static void genCpl (iCode * ic) {
686 printIc("genCpl", ic, 1,1,0);
689 /*-----------------------------------------------------------------*/
690 /* genUminus - unary minus code generation */
691 /*-----------------------------------------------------------------*/
692 static void genUminus (iCode * ic) {
693 printIc("genUminus", ic, 1,1,0);
696 /*-----------------------------------------------------------------*/
697 /* genIpush - genrate code for pushing this gets a little complex */
698 /*-----------------------------------------------------------------*/
699 static void genIpush (iCode * ic) {
700 printIc ("genIpush", ic, 0,1,0);
703 /*-----------------------------------------------------------------*/
704 /* genIpop - recover the registers: can happen only for spilling */
705 /*-----------------------------------------------------------------*/
706 static void genIpop (iCode * ic) {
707 printIc ("genIpop", ic, 0,1,0);
710 /*-----------------------------------------------------------------*/
711 /* genCall - generates a call statement */
712 /*-----------------------------------------------------------------*/
713 static void genCall (iCode * ic) {
714 emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
715 printOp (IC_RESULT(ic)));
718 /*-----------------------------------------------------------------*/
719 /* genPcall - generates a call by pointer statement */
720 /*-----------------------------------------------------------------*/
722 genPcall (iCode * ic)
724 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
727 /*-----------------------------------------------------------------*/
728 /* genFunction - generated code for function entry */
729 /*-----------------------------------------------------------------*/
730 static void genFunction (iCode * ic) {
731 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
732 sym_link *type=sym->type;
734 emitcode (";", "genFunction %s", sym->rname);
736 /* print the allocation information */
737 printAllocInfo (currFunc, codeOutFile);
739 emitcode ("", "%s:", sym->rname);
741 if (IFFUNC_ISNAKED(type))
743 emitcode(";", "naked function: no prologue.");
747 /* adjust the stack for locals used in this function */
749 emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
753 /*-----------------------------------------------------------------*/
754 /* genEndFunction - generates epilogue for functions */
755 /*-----------------------------------------------------------------*/
757 genEndFunction (iCode * ic)
759 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
761 printIc ("genEndFunction", ic, 0,0,0);
763 if (IFFUNC_ISNAKED(sym->type)) {
764 emitcode(";", "naked function: no epilogue.");
768 /* readjust the stock for locals used in this function */
770 emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
773 if (IFFUNC_ISISR(sym->type)) {
774 emitcode ("reti", "");
776 emitcode ("ret", "");
780 /*-----------------------------------------------------------------*/
781 /* genRet - generate code for return statement */
782 /*-----------------------------------------------------------------*/
783 static void genRet (iCode * ic) {
785 printIc ("genRet", ic, 0,1,0);
787 aopOp(IC_LEFT(ic), TRUE, TRUE);
789 switch (AOP_SIZE(IC_LEFT(ic)))
792 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
793 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
796 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
799 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
802 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
808 /*-----------------------------------------------------------------*/
809 /* genLabel - generates a label */
810 /*-----------------------------------------------------------------*/
811 static void genLabel (iCode * ic) {
812 /* special case never generate */
813 if (IC_LABEL (ic) == entryLabel)
816 emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
817 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
820 /*-----------------------------------------------------------------*/
821 /* genGoto - generates a jmp */
822 /*-----------------------------------------------------------------*/
823 static void genGoto (iCode * ic) {
824 emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
825 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
828 /*-----------------------------------------------------------------*/
829 /* genPlus - generates code for addition */
830 /*-----------------------------------------------------------------*/
831 static void genPlus (iCode * ic) {
832 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
836 printIc ("genPlus", ic, 1,1,1);
838 size=aopOp(result, TRUE, TRUE);
840 /* if left is a literal, then exchange them */
841 if (IS_LITERAL(operandType(left))) {
842 operand *tmp = right;
847 if (aopIsBit(result)) {
848 if (IS_LITERAL(operandType(right))) {
849 if (operandLitValue(right)) {
850 emitcode ("setb", AOP_NAME(result)[0]);
853 aopOp(left, TRUE, TRUE);
854 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
857 bailOut("genPlus: unfinished genPlus bit");
860 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
861 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
868 if (!aopEqual(result->aop, left->aop, 0)) {
869 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
871 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
873 if (!aopEqual(result->aop, left->aop, 1)) {
874 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
879 emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
885 /*-----------------------------------------------------------------*/
886 /* genMinus - generates code for subtraction */
887 /*-----------------------------------------------------------------*/
888 static void genMinus (iCode * ic) {
889 printIc ("genMinus", ic, 1,1,1);
893 /*-----------------------------------------------------------------*/
894 /* genMult - generates code for multiplication */
895 /*-----------------------------------------------------------------*/
896 static void genMult (iCode * ic) {
897 printIc ("genMult", ic, 1,1,1);
900 /*-----------------------------------------------------------------*/
901 /* genDiv - generates code for division */
902 /*-----------------------------------------------------------------*/
903 static void genDiv (iCode * ic) {
904 printIc ("genDiv", ic, 1,1,1);
907 /*-----------------------------------------------------------------*/
908 /* genMod - generates code for division */
909 /*-----------------------------------------------------------------*/
910 static void genMod (iCode * ic) {
911 printIc ("genMod", ic, 1,1,1);
914 /*-----------------------------------------------------------------*/
915 /* genCmpGt :- greater than comparison */
916 /*-----------------------------------------------------------------*/
917 static void genCmpGt (iCode * ic) {
918 printIc ("genCmpGt", ic, 1,1,1);
920 /*-----------------------------------------------------------------*/
921 /* genCmpGt :- greater than comparison */
922 /*-----------------------------------------------------------------*/
923 static void genCmpLe (iCode * ic) {
924 printIc ("genCmpLe", ic, 1,1,1);
926 /*-----------------------------------------------------------------*/
927 /* genCmpGt :- greater than comparison */
928 /*-----------------------------------------------------------------*/
929 static void genCmpGe (iCode * ic) {
930 printIc ("genCmpGe", ic, 1,1,1);
932 /*-----------------------------------------------------------------*/
933 /* genCmpGt :- greater than comparison */
934 /*-----------------------------------------------------------------*/
935 static void genCmpNe (iCode * ic) {
936 printIc ("genCmpNe", ic, 1,1,1);
938 /*-----------------------------------------------------------------*/
939 /* genCmpLt - less than comparisons */
940 /*-----------------------------------------------------------------*/
941 static void genCmpLt (iCode * ic) {
942 printIc ("genCmpLt", ic, 1,1,1);
944 /*-----------------------------------------------------------------*/
945 /* genCmpEq - generates code for equal to */
946 /*-----------------------------------------------------------------*/
947 static void genCmpEq (iCode * ic) {
948 printIc ("genCmpEq", ic, 1,1,1);
951 /*-----------------------------------------------------------------*/
952 /* ifxForOp - returns the icode containing the ifx for operand */
953 /*-----------------------------------------------------------------*/
954 static iCode *ifxForOp (operand * op, iCode * ic) {
955 /* if true symbol then needs to be assigned */
956 if (IS_TRUE_SYMOP (op))
959 /* if this has register type condition and
960 the next instruction is ifx with the same operand
961 and live to of the operand is upto the ifx only then */
963 ic->next->op == IFX &&
964 IC_COND (ic->next)->key == op->key &&
965 OP_SYMBOL (op)->liveTo <= ic->next->seq)
971 /*-----------------------------------------------------------------*/
972 /* hasInc - operand is incremented before any other use */
973 /*-----------------------------------------------------------------*/
974 static iCode *hasInc (operand *op, iCode *ic, int osize) {
975 sym_link *type = operandType(op);
976 sym_link *retype = getSpec (type);
977 iCode *lic = ic->next;
980 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
981 if (!IS_SYMOP(op)) return NULL;
983 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
984 if (IS_AGGREGATE(type->next)) return NULL;
985 if (osize != (isize = getSize(type->next))) return NULL;
988 /* if operand of the form op = op + <sizeof *op> */
989 if (lic->op == '+') {
990 fprintf (stderr, "isOperandEqual(IC_LEFT(lic),op):%d\n",
991 isOperandEqual(IC_LEFT(lic),op));
992 fprintf (stderr, "isOperandEqual(IC_RESULT(lic),op):%d\n",
993 isOperandEqual(IC_RESULT(lic),op));
994 fprintf (stderr, "isOperandLiteral(IC_RIGHT(lic)):%d\n",
995 isOperandLiteral(IC_RIGHT(lic)));
996 fprintf (stderr, "operandLitValue(IC_RIGHT(lic)) %f %d\n",
997 operandLitValue(IC_RIGHT(lic)), isize);
998 if (isOperandEqual(IC_LEFT(lic),op) &&
999 //isOperandEqual(IC_RESULT(lic),op) &&
1000 isOperandLiteral(IC_RIGHT(lic)) &&
1001 operandLitValue(IC_RIGHT(lic)) == isize) {
1002 emitcode (";", "Found hasInc");
1006 /* if the operand used or deffed */
1007 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1010 /* if GOTO or IFX */
1011 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1017 /*-----------------------------------------------------------------*/
1018 /* genAndOp - for && operation */
1019 /*-----------------------------------------------------------------*/
1020 static void genAndOp (iCode * ic) {
1021 printIc ("genAndOp(&&)", ic, 1,1,1);
1024 /*-----------------------------------------------------------------*/
1025 /* genOrOp - for || operation */
1026 /*-----------------------------------------------------------------*/
1027 static void genOrOp (iCode * ic) {
1028 printIc ("genOrOp(||)", ic, 1,1,1);
1031 /*-----------------------------------------------------------------*/
1032 /* genAnd - code for and */
1033 /*-----------------------------------------------------------------*/
1034 static void genAnd (iCode * ic, iCode * ifx) {
1035 printIc ("genAnd", ic, 1,1,1);
1038 /*-----------------------------------------------------------------*/
1039 /* genOr - code for or */
1040 /*-----------------------------------------------------------------*/
1041 static void genOr (iCode * ic, iCode * ifx) {
1042 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1046 printIc ("genOr", ic, 1,1,1);
1048 size=aopOp(result, TRUE, TRUE);
1050 /* if left is a literal, then exchange them */
1051 if (IS_LITERAL(operandType(left))) {
1052 operand *tmp = right;
1057 if (aopIsBit(result)) {
1058 if (IS_LITERAL(operandType(right))) {
1059 if (operandLitValue(right)) {
1060 emitcode ("setb", AOP_NAME(result)[0]);
1063 aopOp(left, TRUE, TRUE);
1064 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1069 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1070 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1077 if (!aopEqual(result->aop, left->aop, 0)) {
1078 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1080 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1082 if (!aopEqual(result->aop, left->aop, 1)) {
1083 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1085 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1090 /*-----------------------------------------------------------------*/
1091 /* genXor - code for xclusive or */
1092 /*-----------------------------------------------------------------*/
1093 static void genXor (iCode * ic, iCode * ifx) {
1094 printIc ("genXor", ic, 1,1,1);
1097 /*-----------------------------------------------------------------*/
1098 /* genInline - write the inline code out */
1099 /*-----------------------------------------------------------------*/
1100 static void genInline (iCode * ic) {
1102 printIc ("genInline", ic, 0,0,0);
1104 emitcode ("", IC_INLINE(ic));
1107 /*-----------------------------------------------------------------*/
1108 /* genRRC - rotate right with carry */
1109 /*-----------------------------------------------------------------*/
1110 static void genRRC (iCode * ic) {
1111 printIc ("genRRC", ic, 1,1,0);
1114 /*-----------------------------------------------------------------*/
1115 /* genRLC - generate code for rotate left with carry */
1116 /*-----------------------------------------------------------------*/
1117 static void genRLC (iCode * ic) {
1118 printIc ("genRLC", ic, 1,1,0);
1121 /*-----------------------------------------------------------------*/
1122 /* genGetHbit - generates code get highest order bit */
1123 /*-----------------------------------------------------------------*/
1124 static void genGetHbit (iCode * ic) {
1125 printIc ("genGetHbit", ic, 1,1,0);
1128 /*-----------------------------------------------------------------*/
1129 /* genLeftShift - generates code for left shifting */
1130 /*-----------------------------------------------------------------*/
1131 static void genLeftShift (iCode * ic) {
1132 printIc ("genLeftShift", ic, 1,1,1);
1135 /*-----------------------------------------------------------------*/
1136 /* genRightShift - generate code for right shifting */
1137 /*-----------------------------------------------------------------*/
1138 static void genRightShift (iCode * ic) {
1139 printIc ("genRightShift", ic, 1,1,1);
1142 /*-----------------------------------------------------------------*/
1143 /* genPointerGet - generate code for pointer get */
1144 /*-----------------------------------------------------------------*/
1145 static void genPointerGet (iCode * ic, iCode *pi) {
1146 char *instr, *scratchReg;
1147 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1148 bool codePointer=IS_CODEPTR(operandType(left));
1151 printIc ("genPointerGet", ic, 1,1,0);
1153 if (!IS_PTR(operandType(left))) {
1154 bailOut ("genPointerGet: pointer required");
1157 aopOp(left,FALSE,FALSE);
1158 size=aopOp(result,TRUE,aopIsDir(left));
1160 if (IS_GENPTR(operandType(left))) {
1161 symbol *tlbl1=newiTempLabel(NULL);
1162 symbol *tlbl2=newiTempLabel(NULL);
1163 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1164 emitcode ("bne", "%05d$", tlbl1->key+100);
1167 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1170 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1174 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1176 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1179 emitcode ("br", "%05d$", tlbl2->key+100);
1180 emitcode ("", "%05d$:", tlbl1->key+100);
1183 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1186 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1187 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1191 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1193 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1196 emitcode ("", "%05d$:", tlbl2->key+100);
1200 switch (AOP_TYPE(left))
1218 if (AOP_TYPE(result)==AOP_STK) {
1219 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1220 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1223 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
1228 emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1229 emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1231 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
1245 if (AOP_TYPE(result)==AOP_STK) {
1246 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1247 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1250 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1254 emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1256 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1264 bailOut ("genPointerGet");
1267 /*-----------------------------------------------------------------*/
1268 /* genPointerSet - stores the value into a pointer location */
1269 /*-----------------------------------------------------------------*/
1270 static void genPointerSet (iCode * ic, iCode *pi) {
1272 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1275 printIc ("genPointerSet", ic, 1,0,1);
1277 if (!IS_PTR(operandType(result))) {
1278 bailOut ("genPointerSet: pointer required");
1281 aopOp(result,FALSE,FALSE);
1282 size=aopOp(right,FALSE, FALSE);
1284 if (IS_GENPTR(operandType(result))) {
1285 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1286 AOP_NAME(result)[0], AOP_NAME(result)[1],
1287 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1291 switch (AOP_TYPE(right))
1301 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1304 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1311 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1312 AOP_NAME(right)[1]);
1314 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1315 AOP_NAME(right)[1]);
1320 bailOut ("genPointerSet");
1323 /*-----------------------------------------------------------------*/
1324 /* genIfx - generate code for Ifx statement */
1325 /*-----------------------------------------------------------------*/
1326 static void genIfx (iCode * ic, iCode * popIc) {
1330 symbol *jlbl, *tlbl;
1331 operand *cond=IC_COND(ic);
1333 emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s",
1335 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1336 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1338 size=aopOp(cond,TRUE,TRUE);
1348 switch (AOP_TYPE(cond) )
1351 emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$",
1352 AOP_NAME(cond)[0], jlbl->key+100);
1358 tlbl=newiTempLabel(NULL);
1364 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1365 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1368 // generic pointer, forget the generic part
1370 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1371 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1374 emitcode ("jmp", "%05d$", jlbl->key+100);
1375 emitcode ("", "%05d$:", tlbl->key+100);
1381 /*-----------------------------------------------------------------*/
1382 /* genAddrOf - generates code for address of */
1383 /*-----------------------------------------------------------------*/
1384 static void genAddrOf (iCode * ic) {
1386 operand *left=IC_LEFT(ic);
1388 printIc ("genAddrOf", ic, 1,1,0);
1390 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1392 if (isOperandOnStack(left)) {
1393 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1394 getStackOffset(OP_SYMBOL(left)->stack));
1396 // this must be a generic pointer
1397 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1402 if (isOperandInDirSpace(left) ||
1403 isOperandInFarSpace(left) ||
1404 isOperandInCodeSpace(left)) {
1405 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1406 OP_SYMBOL(left)->rname);
1408 // this must be a generic pointer
1409 int space=0; // dir space
1410 if (isOperandInFarSpace(left)) {
1412 } else if (isOperandInCodeSpace(left)) {
1415 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1420 bailOut("genAddrOf");
1423 /*-----------------------------------------------------------------*/
1424 /* genAssign - generate code for assignment */
1425 /*-----------------------------------------------------------------*/
1426 static void genAssign (iCode * ic) {
1427 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1431 printIc ("genAssign", ic, 1,0,1);
1433 if (!IS_SYMOP(result)) {
1434 bailOut("genAssign: result is not a symbol");
1437 aopOp(result, TRUE, TRUE);
1438 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1439 size=AOP_SIZE(result);
1441 /* if result is a bit */
1442 if (AOP_TYPE(result) == AOP_BIT) {
1443 /* if right is literal, we know what the value is */
1444 if (AOP_TYPE(right) == AOP_LIT) {
1445 if (operandLitValue(right)) {
1446 emitcode ("setb", AOP_NAME(result)[0]);
1448 emitcode ("clr", AOP_NAME(result)[0]);
1452 /* if right is also a bit */
1453 if (AOP_TYPE(right) == AOP_BIT) {
1454 emitcode ("mov", "c,%s", AOP_NAME(right));
1455 emitcode ("mov", "%s,c", AOP_NAME(result));
1459 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1469 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1476 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1481 /*-----------------------------------------------------------------*/
1482 /* genJumpTab - genrates code for jump table */
1483 /*-----------------------------------------------------------------*/
1484 static void genJumpTab (iCode * ic) {
1485 printIc ("genJumpTab", ic, 0,0,0);
1488 /*-----------------------------------------------------------------*/
1489 /* genCast - gen code for casting */
1490 /*-----------------------------------------------------------------*/
1491 static void genCast (iCode * ic) {
1492 printIc ("genCast", ic, 1,1,1);
1495 /*-----------------------------------------------------------------*/
1496 /* genDjnz - generate decrement & jump if not zero instrucion */
1497 /*-----------------------------------------------------------------*/
1498 static bool genDjnz (iCode * ic, iCode * ifx) {
1504 /* if the if condition has a false label
1505 then we cannot save */
1509 /* if the minus is not of the form
1511 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1512 !IS_OP_LITERAL (IC_RIGHT (ic)))
1515 if (operandLitValue (IC_RIGHT (ic)) != 1)
1518 /* if the size of this greater than two then no
1520 if (getSize (operandType (IC_RESULT (ic))) > 2)
1523 printIc ("genDjnz", ic, 1,1,1);
1525 /* otherwise we can save BIG */
1526 lbl = newiTempLabel (NULL);
1527 lbl1 = newiTempLabel (NULL);
1529 aopOp (IC_RESULT (ic), FALSE, TRUE);
1531 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1532 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1533 emitcode ("br", "%05d$", lbl1->key + 100);
1534 emitcode ("", "%05d$:", lbl->key + 100);
1535 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1536 emitcode ("", "%05d$:", lbl1->key + 100);
1540 bailOut("genDjnz: aop type");
1544 /*-----------------------------------------------------------------*/
1545 /* genReceive - generate code for a receive iCode */
1546 /*-----------------------------------------------------------------*/
1547 static void genReceive (iCode * ic) {
1548 printIc ("genReceive", ic, 1,0,0);
1551 /*-----------------------------------------------------------------*/
1552 /* gen51Code - generate code for 8051 based controllers */
1553 /*-----------------------------------------------------------------*/
1554 void genXA51Code (iCode * lic) {
1558 lineHead = lineCurr = NULL;
1560 /* if debug information required */
1561 if (options.debug && currFunc)
1563 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1565 if (IS_STATIC (currFunc->etype))
1566 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1568 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1572 for (ic = lic; ic; ic = ic->next) {
1573 if (ic->lineno && cln != ic->lineno) {
1574 if (options.debug) {
1576 emitcode ("", "C$%s$%d$%d$%d ==.",
1577 FileBaseName (ic->filename), ic->lineno,
1578 ic->level, ic->block);
1581 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1582 printCLine(ic->filename, ic->lineno));
1585 /* if the result is marked as
1586 spilt and rematerializable or code for
1587 this has already been generated then
1589 if (resultRemat (ic) || ic->generated)
1592 /* depending on the operation */
1612 /* IPOP happens only when trying to restore a
1613 spilt live range, if there is an ifx statement
1614 following this pop then the if statement might
1615 be using some of the registers being popped which
1616 would destory the contents of the register so
1617 we need to check for this condition and handle it */
1619 ic->next->op == IFX &&
1620 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1621 genIfx (ic->next, ic);
1639 genEndFunction (ic);
1659 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1708 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1712 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1716 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1743 case GET_VALUE_AT_ADDRESS:
1744 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
1748 if (POINTER_SET (ic))
1749 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1775 addSet (&_G.sendSet, ic);
1784 /* now we are ready to call the
1785 peep hole optimizer */
1786 if (!options.nopeep)
1787 peepHole (&lineHead);
1789 /* now do the actual printing */
1790 printLine (lineHead, codeOutFile);