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"
39 #include "SDCCpeeph.h"
43 #if defined(__BORLANDC__) || defined(_MSC_VER)
44 #define STRCASECMP stricmp
46 #define STRCASECMP strcasecmp
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
67 extern int xa51_ptrRegReq;
68 extern int xa51_nRegs;
69 extern FILE *codeOutFile;
71 static lineNode *lineHead = NULL;
72 static lineNode *lineCurr = NULL;
79 static char *MOV="mov";
80 static char *MOVB="mov.b";
81 static char *MOVW="mov.w";
82 static char *MOVC="movc";
83 static char *MOVCB="movc.b";
84 static char *MOVCW="movc.w";
86 static char *R1L="r1l";
89 void bailOut (char *mesg) {
90 fprintf (stderr, "%s: bailing out\n", mesg);
94 /*-----------------------------------------------------------------*/
95 /* emitcode - writes the code into a file : for now it is simple */
96 /*-----------------------------------------------------------------*/
97 static void emitcode (char *inst, char *fmt,...) {
99 char lb[INITIAL_INLINEASM];
107 sprintf (lb, "%s\t", inst);
109 sprintf (lb, "%s", inst);
110 vsprintf (lb + (strlen (lb)), fmt, ap);
113 vsprintf (lb, fmt, ap);
115 while (isspace ((int)*lbp))
119 lineCurr = (lineCurr ?
120 connectLine (lineCurr, newLineNode (lb)) :
121 (lineHead = newLineNode (lb)));
122 lineCurr->isInline = _G.inLine;
123 lineCurr->isDebug = _G.debugLine;
127 char *getStackOffset(int stack) {
128 static char gsoBuf[1024];
129 sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
130 currFunc->stack, _G.nRegsSaved);
134 /*-----------------------------------------------------------------*/
135 /* newAsmop - creates a new asmOp */
136 /*-----------------------------------------------------------------*/
138 newAsmop (short type)
142 aop = Safe_calloc (1, sizeof (asmop));
147 char *aopTypeName(asmop *aop) {
150 case AOP_LIT: return "lit";
151 case AOP_REG: return "reg";
152 case AOP_DIR: return "dir";
153 case AOP_FAR: return "far";
154 case AOP_CODE: return "code";
155 case AOP_GPTR: return "gptr";
156 case AOP_STK: return "stack";
157 case AOP_IMMD: return "imm";
158 case AOP_BIT: return "bit";
163 /*-----------------------------------------------------------------*/
164 /* aopForSym - for a true symbol */
165 /*-----------------------------------------------------------------*/
166 static asmop *aopForSym(symbol *sym,
167 bool canUsePointer, bool canUseOffset) {
171 sym->aop = aop = newAsmop(0);
172 size=aop->size=getSize(sym->type);
174 // if the sym has registers
175 if (sym->nRegs && sym->regs[0]) {
177 sprintf (aop->name[0], sym->regs[0]->name);
179 sprintf (aop->name[1], sym->regs[1]->name);
186 if (!canUsePointer || !canUseOffset) {
191 emitcode ("mov.b", "r0l,[%s] ;aopForSym:stack:1", getStackOffset(sym->stack));
192 sprintf (aop->name[0], "r0l");
195 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:2", getStackOffset(sym->stack));
196 sprintf (aop->name[0], "r0");
199 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:3.w", getStackOffset(sym->stack));
200 sprintf (aop->name[0], "r0");
201 emitcode ("mov.b", "r1l,[%s] ;aopForSym:stack:3.b", getStackOffset(sym->stack+2));
202 sprintf (aop->name[1], "r1l");
205 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack));
206 sprintf (aop->name[0], "r0");
207 emitcode ("mov.w", "r1,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack+2));
208 sprintf (aop->name[1], "r1");
213 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
215 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
220 // if it has a spillLoc
221 if (sym->usl.spillLoc) {
222 return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
226 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
228 sprintf (aop->name[0], sym->rname);
232 // if in direct space
233 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
235 sprintf (aop->name[0], sym->rname);
237 sprintf (aop->name[1], "%s+2", sym->rname);
243 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
244 if (!canUsePointer) {
249 emitcode (MOV, "r0,#%s", sym->rname);
250 emitcode (MOVC, "r0l,[r0+]");
251 sprintf (aop->name[0], "r0l");
254 emitcode (MOV, "r0,#%s", sym->rname);
255 emitcode (MOVC, "r0,[r0+]");
256 sprintf (aop->name[0], "r0");
259 emitcode (MOV, "r0,#%s", sym->rname);
260 emitcode (MOVC, "r0,[r0+]");
261 sprintf (aop->name[1], "r0");
262 emitcode (MOV, "r1l,[r0+]");
263 sprintf (aop->name[0], "r1l");
266 emitcode (MOV, "r0,#%s", sym->rname);
267 emitcode (MOVC, "r1,[r0+]");
268 emitcode (MOVC, "r0,[r0+]");
269 emitcode ("xch", "r0,r1");
270 sprintf (aop->name[0], "r0");
271 sprintf (aop->name[1], "r1");
277 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
278 sprintf (aop->name[0], "[r0]");
280 sprintf (aop->name[1], "[r0+2]");
287 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
288 if (!canUsePointer) {
293 emitcode (MOV, "r0,#%s", sym->rname);
294 emitcode (MOV, "r0l,[r0]");
295 sprintf (aop->name[0], "r0l");
298 emitcode (MOV, "r0,#%s", sym->rname);
299 emitcode (MOV, "r0,[r0]");
300 sprintf (aop->name[0], "r0");
303 emitcode (MOV, "r0,#%s", sym->rname);
304 emitcode (MOV, "r1l,[r0+2]");
305 sprintf (aop->name[1], "r1l");
306 emitcode (MOV, "r0,[r0]");
307 sprintf (aop->name[0], "r0");
310 emitcode (MOV, "r0,#%s", sym->rname);
311 emitcode (MOV, "r1,[r0+2]");
312 sprintf (aop->name[1], "r1");
313 emitcode (MOV, "r0,[r0]");
314 sprintf (aop->name[0], "r0");
319 emitcode ("mov.w", "r0,#%s ; aopForSym:far", sym->rname);
320 sprintf (aop->name[0], "[r0]");
322 sprintf (aop->name[1], "[r0+2]");
328 bailOut("aopForSym");
332 /*-----------------------------------------------------------------*/
333 /* aopForVal - for a value */
334 /*-----------------------------------------------------------------*/
335 static asmop *aopForVal(operand *op) {
338 if (IS_OP_LITERAL(op)) {
339 op->aop = aop = newAsmop (AOP_LIT);
340 switch ((aop->size=getSize(operandType(op))))
343 sprintf (aop->name[0], "#0x%02x",
344 SPEC_CVAL(operandType(op)).v_int & 0xff);
345 sprintf (aop->name[1], "#0");
348 sprintf (aop->name[0], "#0x%04x",
349 SPEC_CVAL(operandType(op)).v_int & 0xffff);
350 sprintf (aop->name[1], "#0");
353 // must be a generic pointer, can only be zero
354 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
355 sprintf (aop->name[0], "#0x%04x",
356 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
357 sprintf (aop->name[1], "#0");
360 sprintf (aop->name[0], "#0x%04x",
361 SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
362 sprintf (aop->name[1], "#0x%04x",
363 SPEC_CVAL(operandType(op)).v_ulong >> 16);
366 bailOut("aopForVal");
373 op->aop = aop = newAsmop (AOP_IMMD);
374 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
378 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
380 case 3: // generic pointer
381 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
382 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
387 bailOut ("aopForVal: unknown type");
391 static int aopOp(operand *op,
392 bool canUsePointer, bool canUseOffset) {
395 op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
399 op->aop=aopForVal (op);
403 bailOut("aopOp: unexpected operand");
407 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
408 if (strcmp(aop1->name[offset], aop2->name[offset])) {
414 bool aopIsDir(operand *op) {
415 return AOP_TYPE(op)==AOP_DIR;
418 bool aopIsBit(operand *op) {
419 return AOP_TYPE(op)==AOP_BIT;
422 bool aopIsPtr(operand *op) {
423 if (AOP_TYPE(op)==AOP_STK ||
424 AOP_TYPE(op)==AOP_CODE ||
425 AOP_TYPE(op)==AOP_FAR) {
432 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
435 if (OP_SYMBOL(op)->onStack) {
436 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
439 if (IS_TRUE_SYMOP(op))
440 return OP_SYMBOL(op)->rname;
441 else if (OP_SYMBOL(op)->regs[offset])
442 return OP_SYMBOL(op)->regs[offset]->name;
444 bailOut("opRegName: unknown regs");
448 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
451 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
452 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
453 bailOut("opRegName: invalid bit value");
457 sprintf (opName, "#%s0x%02x", decorate?"(char)":"",
458 SPEC_CVAL(OP_VALUE(op)->type).v_int);
461 if (SPEC_LONG(OP_VALUE(op)->type)) {
462 sprintf (opName, "#%s0x%02x", decorate?"(long)":"",
463 SPEC_CVAL(OP_VALUE(op)->type).v_long);
465 sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
466 SPEC_CVAL(OP_VALUE(op)->type).v_int);
470 sprintf (opName, "#%s%f", decorate?"(float)":"",
471 SPEC_CVAL(OP_VALUE(op)->type).v_float);
474 bailOut("opRegName: unexpected noun");
478 bailOut("opRegName: unexpected operand type");
482 char * printOp (operand *op) {
483 static char line[132];
484 sym_link *optype=operandType(op);
485 bool isPtr = IS_PTR(optype);
488 symbol *sym=OP_SYMBOL(op);
489 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
490 sym=SYM_SPIL_LOC(sym);
494 if (DCL_TYPE(optype)==FPOINTER)
495 strcat (line, "far * ");
496 else if (DCL_TYPE(optype)==CPOINTER)
497 strcat (line, "code * ");
498 else if (DCL_TYPE(optype)==GPOINTER)
499 strcat (line, "gen * ");
500 else if (DCL_TYPE(optype)==POINTER)
501 strcat (line, "near * ");
503 strcat (line, "unknown * ");
505 strcat (line, nounName(sym->etype));
507 strcat (line, sym->name);
510 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
513 strcat (line, sym->regs[0]->name);
516 strcat (line, sym->regs[1]->name);
521 sprintf (line+strlen(line), "stack%+d", sym->stack);
524 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
525 strcat (line, "code");
528 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
529 strcat (line, "far");
532 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
533 strcat (line, "bit");
536 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
537 strcat (line, "dir");
540 strcat (line, "unknown");
542 } else if (IS_VALOP(op)) {
543 opRegName(op, 0, line, 1);
544 } else if (IS_TYPOP(op)) {
547 if (DCL_TYPE(optype)==FPOINTER)
548 strcat (line, "far * ");
549 else if (DCL_TYPE(optype)==CPOINTER)
550 strcat (line, "code * ");
551 else if (DCL_TYPE(optype)==GPOINTER)
552 strcat (line, "gen * ");
553 else if (DCL_TYPE(optype)==POINTER)
554 strcat (line, "near * ");
556 strcat (line, "unknown * ");
558 // forget about static, volatile, ... for now
559 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
560 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
561 strcat (line, nounName(operandType(op)));
564 bailOut("printOp: unexpected operand type");
569 void printIc (bool printToStderr,
570 char *op, iCode * ic, bool result, bool left, bool right) {
573 sprintf (line, "%s(%d)", op, ic->lineno);
575 strcat (line, " result=");
576 strcat (line, printOp (IC_RESULT(ic)));
579 strcat (line, " left=");
580 strcat (line, printOp (IC_LEFT(ic)));
583 strcat (line, " right=");
584 strcat (line, printOp (IC_RIGHT(ic)));
586 emitcode (";", line);
588 fprintf (stderr, "%s\n", line);
592 /*-----------------------------------------------------------------*/
593 /* toBoolean - return carry for operand!=0 */
594 /*-----------------------------------------------------------------*/
595 static char *toBoolean (operand * op) {
596 symbol *tlbl=newiTempLabel(NULL);
598 switch (AOP_SIZE(op))
602 emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
603 "This needs a second thought");
605 emitcode ("", "%05d$:", tlbl->key+100);
609 bailOut("toBoolean: unknown size");
613 /*-----------------------------------------------------------------*/
614 /* regsInCommon - two operands have some registers in common */
615 /*-----------------------------------------------------------------*/
616 static bool regsInCommon (operand * op1, operand * op2) {
620 /* if they have registers in common */
621 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
624 sym1 = OP_SYMBOL (op1);
625 sym2 = OP_SYMBOL (op2);
627 if (sym1->nRegs == 0 || sym2->nRegs == 0)
630 for (i = 0; i < sym1->nRegs; i++)
636 for (j = 0; j < sym2->nRegs; j++)
641 if (sym2->regs[j] == sym1->regs[i])
649 /*-----------------------------------------------------------------*/
650 /* resultRemat - result is rematerializable */
651 /*-----------------------------------------------------------------*/
652 static int resultRemat (iCode * ic) {
653 if (SKIP_IC (ic) || ic->op == IFX)
656 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
658 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
659 if (sym->remat && !POINTER_SET (ic))
666 /*-----------------------------------------------------------------*/
667 /* genNot - generate code for ! operation */
668 /*-----------------------------------------------------------------*/
669 static void genNot (iCode * ic) {
670 printIc (0, "genNot:", ic, 1,1,0);
673 /*-----------------------------------------------------------------*/
674 /* genCpl - generate code for complement */
675 /*-----------------------------------------------------------------*/
676 static void genCpl (iCode * ic) {
677 printIc (0, "genCpl", ic, 1,1,0);
680 /*-----------------------------------------------------------------*/
681 /* genUminus - unary minus code generation */
682 /*-----------------------------------------------------------------*/
683 static void genUminus (iCode * ic) {
684 printIc (0, "genUminus", ic, 1,1,0);
687 /*-----------------------------------------------------------------*/
688 /* genIpush - generate code for pushing */
689 /*-----------------------------------------------------------------*/
690 static void genIpush (iCode * ic) {
691 operand *left=IC_LEFT(ic);
693 printIc (0, "genIpush", ic, 0,1,0);
694 aopOp(left,FALSE,FALSE);
697 if (AOP_TYPE(left)==AOP_LIT) {
698 switch (AOP_SIZE(left))
701 emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
702 emitcode ("push", "r1l");
706 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
707 emitcode ("push", "r1");
711 emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
712 emitcode ("push", "r1l");
713 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
714 emitcode ("push", "r1");
718 emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
719 emitcode ("push", "r1");
720 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
721 emitcode ("push", "r1");
726 if (AOP_SIZE(left)>2) {
727 emitcode ("push", "%s", AOP_NAME(left)[1]);
730 emitcode ("push", "%s", AOP_NAME(left)[0]);
735 /*-----------------------------------------------------------------*/
736 /* genIpop - recover the registers: can happen only for spilling */
737 /*-----------------------------------------------------------------*/
738 static void genIpop (iCode * ic) {
739 printIc (0, "genIpop", ic, 0,1,0);
742 /*-----------------------------------------------------------------*/
743 /* genCall - generates a call statement */
744 /*-----------------------------------------------------------------*/
745 static void genCall (iCode * ic) {
746 operand *result=IC_RESULT(ic);
748 emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
749 OP_SYMBOL(IC_LEFT(ic))->name,
750 printOp (IC_RESULT(ic)));
751 emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
753 /* readjust the stack if we have pushed some parms */
754 if (_G.parmsPushed) {
755 emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
759 /* if we need to assign a result value */
760 if (IS_ITEMP (IC_RESULT(ic)) &&
761 OP_SYMBOL (IC_RESULT (ic))->nRegs) {
762 aopOp(result,FALSE,FALSE);
763 switch (AOP_SIZE(result))
766 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
769 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
773 emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
774 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
777 emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
778 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
785 /*-----------------------------------------------------------------*/
786 /* genPcall - generates a call by pointer statement */
787 /*-----------------------------------------------------------------*/
789 genPcall (iCode * ic)
791 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
794 /*-----------------------------------------------------------------*/
795 /* genFunction - generated code for function entry */
796 /*-----------------------------------------------------------------*/
797 static void genFunction (iCode * ic) {
798 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
799 sym_link *type=sym->type;
801 emitcode (";", "genFunction %s", sym->rname);
803 /* print the allocation information */
804 printAllocInfo (currFunc, codeOutFile);
806 emitcode ("", "%s:", sym->rname);
808 if (IFFUNC_ISNAKED(type))
810 emitcode(";", "naked function: no prologue.");
814 /* adjust the stack for locals used in this function */
816 emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
820 /*-----------------------------------------------------------------*/
821 /* genEndFunction - generates epilogue for functions */
822 /*-----------------------------------------------------------------*/
824 genEndFunction (iCode * ic)
826 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
828 printIc (0, "genEndFunction", ic, 0,0,0);
830 if (IFFUNC_ISNAKED(sym->type)) {
831 emitcode(";", "naked function: no epilogue.");
835 /* readjust the stock for locals used in this function */
837 emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
840 if (IFFUNC_ISISR(sym->type)) {
841 emitcode ("reti", "");
843 emitcode ("ret", "");
847 /*-----------------------------------------------------------------*/
848 /* genRet - generate code for return statement */
849 /*-----------------------------------------------------------------*/
850 static void genRet (iCode * ic) {
853 printIc (0, "genRet", ic, 0, 0, 0);
855 printIc (0, "genRet", ic, 0, 1, 0);
856 aopOp(IC_LEFT(ic), TRUE, TRUE);
857 switch (AOP_SIZE(IC_LEFT(ic)))
860 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
861 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
864 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
867 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
870 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
877 emitcode ("jmp", "%05d$", returnLabel->key+100);
880 /*-----------------------------------------------------------------*/
881 /* genLabel - generates a label */
882 /*-----------------------------------------------------------------*/
883 static void genLabel (iCode * ic) {
884 /* special case never generate */
885 if (IC_LABEL (ic) == entryLabel)
888 emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
889 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
892 /*-----------------------------------------------------------------*/
893 /* genGoto - generates a jmp */
894 /*-----------------------------------------------------------------*/
895 static void genGoto (iCode * ic) {
896 emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
897 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
900 /*-----------------------------------------------------------------*/
901 /* genPlus - generates code for addition */
902 /*-----------------------------------------------------------------*/
903 static void genPlus (iCode * ic) {
904 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
908 printIc (0, "genPlus", ic, 1,1,1);
910 size=aopOp(result, TRUE, TRUE);
912 /* if left is a literal, then exchange them */
913 if (IS_LITERAL(operandType(left))) {
914 operand *tmp = right;
919 if (aopIsBit(result)) {
920 if (IS_LITERAL(operandType(right))) {
921 if (operandLitValue(right)) {
922 emitcode ("setb", AOP_NAME(result)[0]);
925 aopOp(left, TRUE, TRUE);
926 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
929 bailOut("genPlus: unfinished genPlus bit");
932 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
933 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
935 // special case for "* = * + char", needs a closer look
936 // heck, this shouldn't have come here but bug-223113 does
937 if (size==3 && AOP_SIZE(right)==1) {
938 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
939 emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
940 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
941 emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
942 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
946 // special case for "xdata * = xdata * + char", needs a closer look
947 // heck, this shouldn't have come here but bug-441448 does
948 if (size==2 && AOP_SIZE(right)==1) {
949 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
950 emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
951 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
952 emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
961 if (!aopEqual(result->aop, left->aop, 0)) {
962 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
964 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
966 if (!aopEqual(result->aop, left->aop, 1)) {
967 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
972 emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
978 /*-----------------------------------------------------------------*/
979 /* genMinus - generates code for subtraction */
980 /*-----------------------------------------------------------------*/
981 static void genMinus (iCode * ic) {
982 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
986 printIc (0, "genMinus", ic, 1,1,1);
988 size=aopOp(result, TRUE, TRUE);
990 /* if left is a literal, then exchange them */
991 if (IS_LITERAL(operandType(left))) {
992 operand *tmp = right;
997 if (aopIsBit(result)) {
998 if (IS_LITERAL(operandType(right))) {
999 if (operandLitValue(right)) {
1000 emitcode ("clr", AOP_NAME(result)[0]);
1003 aopOp(left, TRUE, TRUE);
1004 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1007 bailOut("genPlus: unfinished genPlus bit");
1010 if (isOperandEqual(result,left)) {
1011 left->aop=result->aop;
1013 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1015 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1022 if (!aopEqual(result->aop, left->aop, 0)) {
1023 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1025 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1027 if (!aopEqual(result->aop, left->aop, 1)) {
1028 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1033 emitcode ("subb.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1039 /*-----------------------------------------------------------------*/
1040 /* genMult - generates code for multiplication */
1041 /*-----------------------------------------------------------------*/
1042 static void genMult (iCode * ic) {
1043 printIc (0, "genMult", ic, 1,1,1);
1046 /*-----------------------------------------------------------------*/
1047 /* genDiv - generates code for division */
1048 /*-----------------------------------------------------------------*/
1049 static void genDiv (iCode * ic) {
1050 printIc (0, "genDiv", ic, 1,1,1);
1053 /*-----------------------------------------------------------------*/
1054 /* genMod - generates code for division */
1055 /*-----------------------------------------------------------------*/
1056 static void genMod (iCode * ic) {
1057 printIc (0, "genMod", ic, 1,1,1);
1060 /*-----------------------------------------------------------------*/
1061 /* ifxForOp - returns the icode containing the ifx for operand */
1062 /*-----------------------------------------------------------------*/
1063 static iCode *ifxForOp (operand * op, iCode * ic) {
1064 /* if true symbol then needs to be assigned */
1065 if (IS_TRUE_SYMOP (op))
1068 /* if this has register type condition and
1069 the next instruction is ifx with the same operand
1070 and live to of the operand is upto the ifx only then */
1072 ic->next->op == IFX &&
1073 IC_COND (ic->next)->key == op->key &&
1074 OP_SYMBOL (op)->liveTo <= ic->next->seq)
1080 /*-----------------------------------------------------------------*/
1081 /* genCmp - compares whatever */
1082 /*-----------------------------------------------------------------*/
1083 static void genCmp (iCode * ic, char *trueInstr, char *falseInstr) {
1084 iCode *ifx=ifxForOp(IC_RESULT(ic),ic);
1085 operand *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1092 size=aopOp(left, TRUE, TRUE);
1093 aopOp(right, !aopIsPtr(left), TRUE);
1103 jlbl=IC_TRUE(ifx)->key+100;
1106 jlbl=IC_FALSE(ifx)->key+100;
1110 aopOp(IC_RESULT(ic), !aopIsPtr(left), TRUE);
1111 jlbl=newiTempLabel(NULL)->key+100;
1112 emitcode("mov", "%s,#-1", AOP_NAME(IC_RESULT(ic))[0]);
1113 emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1114 emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1115 emitcode("cpl", "%s", AOP_NAME(IC_RESULT(ic))[0]);
1116 emitcode("", "%05d$:", jlbl);
1118 emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1119 emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1124 bailOut("genCmp: size > 2");
1129 /*-----------------------------------------------------------------*/
1130 /* genCmpEq :- generates code for equal to */
1131 /*-----------------------------------------------------------------*/
1132 static void genCmpEq (iCode * ic) {
1133 printIc (0, "genCmpEq", ic, 0,1,1);
1134 genCmp(ic, "beq", "bne"); // no sign
1137 /*-----------------------------------------------------------------*/
1138 /* genCmpGt :- greater than comparison */
1139 /*-----------------------------------------------------------------*/
1140 static void genCmpGt (iCode * ic) {
1141 printIc (0, "genCmpGt", ic, 0,1,1);
1142 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1143 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1144 genCmp(ic, "bg", "bl"); // unsigned
1146 genCmp(ic, "bgt", "ble"); // signed
1150 /*-----------------------------------------------------------------*/
1151 /* genCmpLt - less than comparisons */
1152 /*-----------------------------------------------------------------*/
1153 static void genCmpLt (iCode * ic) {
1154 printIc (0, "genCmpLt", ic, 0,1,1);
1155 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1156 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1157 genCmp(ic, "bcs", "bcc"); // unsigned
1159 genCmp(ic, "blt", "bge"); // signed
1163 /*-----------------------------------------------------------------*/
1164 /* hasInc - operand is incremented before any other use */
1165 /*-----------------------------------------------------------------*/
1166 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1167 sym_link *type = operandType(op);
1168 sym_link *retype = getSpec (type);
1169 iCode *lic = ic->next;
1172 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1173 if (!IS_SYMOP(op)) return NULL;
1175 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1176 if (IS_AGGREGATE(type->next)) return NULL;
1177 if (osize != (isize = getSize(type->next))) return NULL;
1180 /* if operand of the form op = op + <sizeof *op> */
1181 if (lic->op == '+') {
1182 if (isOperandEqual(IC_LEFT(lic),op) &&
1183 //isOperandEqual(IC_RESULT(lic),op) &&
1184 isOperandLiteral(IC_RIGHT(lic)) &&
1185 operandLitValue(IC_RIGHT(lic)) == isize) {
1186 emitcode (";", "Found hasInc");
1190 /* if the operand used or deffed */
1191 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1194 /* if GOTO or IFX */
1195 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1201 /*-----------------------------------------------------------------*/
1202 /* genAndOp - for && operation */
1203 /*-----------------------------------------------------------------*/
1204 static void genAndOp (iCode * ic) {
1205 printIc (0, "genAndOp(&&)", ic, 1,1,1);
1208 /*-----------------------------------------------------------------*/
1209 /* genOrOp - for || operation */
1210 /*-----------------------------------------------------------------*/
1211 static void genOrOp (iCode * ic) {
1212 printIc (0, "genOrOp(||)", ic, 1,1,1);
1215 /*-----------------------------------------------------------------*/
1216 /* genAnd - code for and */
1217 /*-----------------------------------------------------------------*/
1218 static void genAnd (iCode * ic, iCode * ifx) {
1219 printIc (0, "genAnd", ic, 1,1,1);
1222 /*-----------------------------------------------------------------*/
1223 /* genOr - code for or */
1224 /*-----------------------------------------------------------------*/
1225 static void genOr (iCode * ic, iCode * ifx) {
1226 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1230 printIc (0, "genOr", ic, 1,1,1);
1232 size=aopOp(result, TRUE, TRUE);
1234 /* if left is a literal, then exchange them */
1235 if (IS_LITERAL(operandType(left))) {
1236 operand *tmp = right;
1241 if (aopIsBit(result)) {
1242 if (IS_LITERAL(operandType(right))) {
1243 if (operandLitValue(right)) {
1244 emitcode ("setb", AOP_NAME(result)[0]);
1247 aopOp(left, TRUE, TRUE);
1248 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1253 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1254 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1261 if (!aopEqual(result->aop, left->aop, 0)) {
1262 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1264 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1266 if (!aopEqual(result->aop, left->aop, 1)) {
1267 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1269 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1274 /*-----------------------------------------------------------------*/
1275 /* genXor - code for xclusive or */
1276 /*-----------------------------------------------------------------*/
1277 static void genXor (iCode * ic, iCode * ifx) {
1278 printIc (0, "genXor", ic, 1,1,1);
1281 /*-----------------------------------------------------------------*/
1282 /* genInline - write the inline code out */
1283 /*-----------------------------------------------------------------*/
1284 static void genInline (iCode * ic) {
1286 printIc (0, "genInline", ic, 0,0,0);
1288 emitcode ("", IC_INLINE(ic));
1291 /*-----------------------------------------------------------------*/
1292 /* genRRC - rotate right with carry */
1293 /*-----------------------------------------------------------------*/
1294 static void genRRC (iCode * ic) {
1295 printIc (0, "genRRC", ic, 1,1,0);
1298 /*-----------------------------------------------------------------*/
1299 /* genRLC - generate code for rotate left with carry */
1300 /*-----------------------------------------------------------------*/
1301 static void genRLC (iCode * ic) {
1302 printIc (0, "genRLC", ic, 1,1,0);
1305 /*-----------------------------------------------------------------*/
1306 /* genGetHbit - generates code get highest order bit */
1307 /*-----------------------------------------------------------------*/
1308 static void genGetHbit (iCode * ic) {
1309 printIc (0, "genGetHbit", ic, 1,1,0);
1312 /*-----------------------------------------------------------------*/
1313 /* genLeftShift - generates code for left shifting */
1314 /*-----------------------------------------------------------------*/
1315 static void genLeftShift (iCode * ic) {
1316 printIc (0, "genLeftShift", ic, 1,1,1);
1319 /*-----------------------------------------------------------------*/
1320 /* genRightShift - generate code for right shifting */
1321 /*-----------------------------------------------------------------*/
1322 static void genRightShift (iCode * ic) {
1323 printIc (0, "genRightShift", ic, 1,1,1);
1326 /*-----------------------------------------------------------------*/
1327 /* genPointerGet - generate code for pointer get */
1328 /*-----------------------------------------------------------------*/
1329 static void genPointerGet (iCode * ic, iCode *pi) {
1330 char *instr, *scratchReg;
1331 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1332 bool codePointer=IS_CODEPTR(operandType(left));
1336 printIc (0, "genPointerGet pi", ic, 1,1,0);
1338 printIc (0, "genPointerGet", ic, 1,1,0);
1341 if (!IS_PTR(operandType(left))) {
1342 bailOut ("genPointerGet: pointer required");
1345 aopOp(left,FALSE,FALSE);
1346 size=aopOp(result,TRUE,aopIsDir(left));
1348 if (IS_GENPTR(operandType(left))) {
1349 symbol *tlbl1=newiTempLabel(NULL);
1350 symbol *tlbl2=newiTempLabel(NULL);
1351 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1352 emitcode ("beq", "%05d$", tlbl1->key+100);
1355 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1358 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1362 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1364 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1367 emitcode ("br", "%05d$", tlbl2->key+100);
1368 emitcode ("", "%05d$:", tlbl1->key+100);
1371 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1374 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1375 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1379 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1381 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1384 emitcode ("", "%05d$:", tlbl2->key+100);
1388 switch (AOP_TYPE(left))
1391 emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1392 sprintf (AOP_NAME(left)[0], "r1");
1410 if (AOP_TYPE(result)==AOP_STK) {
1411 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1412 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1415 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
1420 emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1421 emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1423 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
1437 if (AOP_TYPE(result)==AOP_STK) {
1438 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1439 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1442 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1446 emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1448 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1456 bailOut ("genPointerGet");
1459 /*-----------------------------------------------------------------*/
1460 /* genPointerSet - stores the value into a pointer location */
1461 /*-----------------------------------------------------------------*/
1462 static void genPointerSet (iCode * ic, iCode *pi) {
1464 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1467 printIc (0, "genPointerSet", ic, 1,0,1);
1469 if (!IS_PTR(operandType(result))) {
1470 bailOut ("genPointerSet: pointer required");
1473 aopOp(result,FALSE,FALSE);
1474 size=aopOp(right,FALSE, FALSE);
1476 if (IS_GENPTR(operandType(result))) {
1477 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1478 AOP_NAME(result)[0], AOP_NAME(result)[1],
1479 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1483 switch (AOP_TYPE(right))
1493 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1496 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1503 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1504 AOP_NAME(right)[1]);
1506 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1507 AOP_NAME(right)[1]);
1512 bailOut ("genPointerSet");
1515 /*-----------------------------------------------------------------*/
1516 /* genIfx - generate code for Ifx statement */
1517 /*-----------------------------------------------------------------*/
1518 static void genIfx (iCode * ic, iCode * popIc) {
1522 symbol *jlbl, *tlbl=newiTempLabel(NULL);
1523 operand *cond=IC_COND(ic);
1525 emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s",
1526 ic->lineno, printOp(cond),
1527 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1528 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1530 size=aopOp(cond,TRUE,TRUE);
1540 switch (AOP_TYPE(cond) )
1543 emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$",
1544 AOP_NAME(cond)[0], tlbl->key+100);
1545 emitcode ("jmp", "%05d$", jlbl->key+100);
1546 emitcode ("", "%05d$:", tlbl->key+100);
1557 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1558 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1561 // generic pointer, forget the generic part
1563 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1564 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1567 emitcode ("jmp", "%05d$", jlbl->key+100);
1568 emitcode ("", "%05d$:", tlbl->key+100);
1574 /*-----------------------------------------------------------------*/
1575 /* genAddrOf - generates code for address of */
1576 /*-----------------------------------------------------------------*/
1577 static void genAddrOf (iCode * ic) {
1579 operand *left=IC_LEFT(ic);
1581 printIc (0, "genAddrOf", ic, 1,1,0);
1583 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1585 if (isOperandOnStack(left)) {
1586 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1587 getStackOffset(OP_SYMBOL(left)->stack));
1589 // this must be a generic pointer
1590 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1595 if (isOperandInDirSpace(left) ||
1596 isOperandInFarSpace(left) ||
1597 isOperandInCodeSpace(left)) {
1598 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1599 OP_SYMBOL(left)->rname);
1601 // this must be a generic pointer
1602 int space=0; // dir space
1603 if (isOperandInFarSpace(left)) {
1605 } else if (isOperandInCodeSpace(left)) {
1608 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1613 bailOut("genAddrOf");
1616 /*-----------------------------------------------------------------*/
1617 /* genAssign - generate code for assignment */
1618 /*-----------------------------------------------------------------*/
1619 static void genAssign (iCode * ic) {
1620 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1624 printIc (0, "genAssign", ic, 1,0,1);
1626 if (!IS_SYMOP(result)) {
1627 bailOut("genAssign: result is not a symbol");
1630 aopOp(result, TRUE, TRUE);
1631 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1632 size=AOP_SIZE(result);
1634 /* if result is a bit */
1635 if (AOP_TYPE(result) == AOP_BIT) {
1636 /* if right is literal, we know what the value is */
1637 if (AOP_TYPE(right) == AOP_LIT) {
1638 if (operandLitValue(right)) {
1639 emitcode ("setb", AOP_NAME(result)[0]);
1641 emitcode ("clr", AOP_NAME(result)[0]);
1645 /* if right is also a bit */
1646 if (AOP_TYPE(right) == AOP_BIT) {
1647 emitcode ("mov", "c,%s", AOP_NAME(right));
1648 emitcode ("mov", "%s,c", AOP_NAME(result));
1652 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1656 // TODO: if (-8 >= right==lit <= 7) instr=MOVS
1663 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1670 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1675 /*-----------------------------------------------------------------*/
1676 /* genJumpTab - genrates code for jump table */
1677 /*-----------------------------------------------------------------*/
1678 static void genJumpTab (iCode * ic) {
1679 printIc (0, "genJumpTab", ic, 0,0,0);
1682 /*-----------------------------------------------------------------*/
1683 /* genCast - gen code for casting */
1684 /*-----------------------------------------------------------------*/
1685 static void genCast (iCode * ic) {
1687 operand *result=IC_RESULT(ic);
1688 operand *right=IC_RIGHT(ic);
1689 sym_link *ctype=operandType(IC_LEFT(ic));
1690 sym_link *rtype=operandType(IC_RIGHT(ic));
1691 sym_link *etype=getSpec(rtype);
1692 short ptrType, signedness;
1694 printIc (0, "genCast", ic, 1,1,1);
1696 aopOp(result, TRUE, TRUE);
1697 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1698 size=AOP_SIZE(result);
1700 /* if result is a bit */
1701 if (AOP_TYPE(result) == AOP_BIT) {
1702 /* if right is literal, we know what the value is */
1703 if (AOP_TYPE(right) == AOP_LIT) {
1704 if (operandLitValue(right)) {
1705 emitcode ("setb", AOP_NAME(result)[0]);
1707 emitcode ("clr", AOP_NAME(result)[0]);
1711 /* if right is also a bit */
1712 if (AOP_TYPE(right) == AOP_BIT) {
1713 emitcode ("mov", "c,%s", AOP_NAME(right));
1714 emitcode ("mov", "%s,c", AOP_NAME(result));
1718 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1722 /* if right is a bit */
1723 if (AOP_TYPE(right)==AOP_BIT) {
1724 emitcode ("mov", "c,%s", AOP_NAME(right));
1725 emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1726 emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1728 emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1733 /* if the result is of type pointer */
1734 if (IS_PTR (ctype)) {
1736 if (AOP_SIZE(right)>1) {
1737 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1739 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1740 emitcode ("sext", "r1h");
1741 emitcode ("mov", "%s,r1", AOP_NAME(result)[0]);
1744 /* if pointer to generic pointer */
1745 if (IS_GENPTR (ctype)) {
1747 if (IS_GENPTR (rtype)) {
1748 bailOut("genCast: gptr -> gptr");
1751 if (IS_PTR (rtype)) {
1752 ptrType = DCL_TYPE (rtype);
1754 /* we have to go by the storage class */
1755 if (!SPEC_OCLS(etype)) {
1756 ptrType=0; // hush the compiler
1757 bailOut("genCast: unknown storage class");
1759 ptrType = PTR_TYPE (SPEC_OCLS (etype));
1763 /* the generic part depends on the type */
1767 emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1770 emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1773 emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1776 bailOut("genCast: got unknown storage class");
1782 /* do we have to sign extend? */
1783 signedness = SPEC_USIGN(rtype);
1785 /* now depending on the size */
1786 switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1790 emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1795 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1798 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1800 emitcode("sext", "%s", AOP_NAME(result)[1]);
1802 emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1807 emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1809 emitcode("sext", "r1h");
1811 emitcode("mov", "r1h,#0");
1813 emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1816 // fall through: case 0x41
1818 emitcode("sext", "r1");
1820 emitcode("mov", "r1,#0");
1822 emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1826 emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1827 emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1830 fprintf(stderr, "genCast: unknown size: %d:%d\n",
1831 AOP_SIZE(result), AOP_SIZE(right));
1832 bailOut("genCast: unknown size");
1836 /*-----------------------------------------------------------------*/
1837 /* genDjnz - generate decrement & jump if not zero instrucion */
1838 /*-----------------------------------------------------------------*/
1839 static bool genDjnz (iCode * ic, iCode * ifx) {
1845 /* if the if condition has a false label
1846 then we cannot save */
1850 /* if the minus is not of the form
1852 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1853 !IS_OP_LITERAL (IC_RIGHT (ic)))
1856 if (operandLitValue (IC_RIGHT (ic)) != 1)
1859 /* if the size of this greater than two then no
1861 if (getSize (operandType (IC_RESULT (ic))) > 2)
1864 printIc (0, "genDjnz", ic, 1,1,1);
1866 /* otherwise we can save BIG */
1867 lbl = newiTempLabel (NULL);
1868 lbl1 = newiTempLabel (NULL);
1870 aopOp (IC_RESULT (ic), FALSE, TRUE);
1872 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1873 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1874 emitcode ("br", "%05d$", lbl1->key + 100);
1875 emitcode ("", "%05d$:", lbl->key + 100);
1876 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1877 emitcode ("", "%05d$:", lbl1->key + 100);
1881 bailOut("genDjnz: aop type");
1885 /*-----------------------------------------------------------------*/
1886 /* genReceive - generate code for a receive iCode */
1887 /*-----------------------------------------------------------------*/
1888 static void genReceive (iCode * ic) {
1889 printIc (0, "genReceive", ic, 1,0,0);
1892 /*-----------------------------------------------------------------*/
1893 /* gen51Code - generate code for 8051 based controllers */
1894 /*-----------------------------------------------------------------*/
1895 void genXA51Code (iCode * lic) {
1899 lineHead = lineCurr = NULL;
1901 /* if debug information required */
1902 if (options.debug && currFunc)
1904 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1906 if (IS_STATIC (currFunc->etype))
1907 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1909 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1913 for (ic = lic; ic; ic = ic->next) {
1914 if (ic->lineno && cln != ic->lineno) {
1915 if (options.debug) {
1917 emitcode ("", "C$%s$%d$%d$%d ==.",
1918 FileBaseName (ic->filename), ic->lineno,
1919 ic->level, ic->block);
1922 if (!options.noCcodeInAsm) {
1923 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1924 printCLine(ic->filename, ic->lineno));
1928 if (options.iCodeInAsm) {
1929 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
1932 /* if the result is marked as
1933 spilt and rematerializable or code for
1934 this has already been generated then
1936 if (resultRemat (ic) || ic->generated)
1939 /* depending on the operation */
1959 /* IPOP happens only when trying to restore a
1960 spilt live range, if there is an ifx statement
1961 following this pop then the if statement might
1962 be using some of the registers being popped which
1963 would destory the contents of the register so
1964 we need to check for this condition and handle it */
1966 ic->next->op == IFX &&
1967 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1968 genIfx (ic->next, ic);
1986 genEndFunction (ic);
2006 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
2034 /* note these two are xlated by algebraic equivalence
2035 during parsing SDCC.y */
2036 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2037 "got '>=' or '<=' shouldn't have come here");
2053 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
2057 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
2061 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
2088 case GET_VALUE_AT_ADDRESS:
2089 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
2093 if (POINTER_SET (ic))
2094 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2120 addSet (&_G.sendSet, ic);
2129 /* now we are ready to call the
2130 peep hole optimizer */
2131 if (!options.nopeep)
2132 peepHole (&lineHead);
2134 /* now do the actual printing */
2135 printLine (lineHead, codeOutFile);