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"
45 /* this is the down and dirty file with all kinds of
46 kludgy & hacky stuff. This is what it is all about
47 CODE GENERATION for a specific MCU . some of the
48 routines may be reusable, will have to see */
61 extern int xa51_ptrRegReq;
62 extern int xa51_nRegs;
63 extern struct dbuf_s *codeOutBuf;
65 static lineNode *lineHead = NULL;
66 static lineNode *lineCurr = NULL;
73 static char *MOV="mov";
74 static char *MOVB="mov.b";
75 static char *MOVW="mov.w";
76 static char *MOVC="movc";
77 static char *MOVCB="movc.b";
78 static char *MOVCW="movc.w";
80 static char *R1L="r1l";
83 void bailOut (char *mesg) {
84 fprintf (stderr, "%s: bailing out\n", mesg);
88 /*-----------------------------------------------------------------*/
89 /* emitcode - writes the code into a file : for now it is simple */
90 /*-----------------------------------------------------------------*/
91 static void emitcode (char *inst, char *fmt,...) {
93 char lb[INITIAL_INLINEASM];
101 sprintf (lb, "%s\t", inst);
103 sprintf (lb, "%s", inst);
104 vsprintf (lb + (strlen (lb)), fmt, ap);
107 vsprintf (lb, fmt, ap);
109 while (isspace (*lbp))
113 lineCurr = (lineCurr ?
114 connectLine (lineCurr, newLineNode (lb)) :
115 (lineHead = newLineNode (lb)));
116 lineCurr->isInline = _G.inLine;
117 lineCurr->isDebug = _G.debugLine;
121 /*-----------------------------------------------------------------*/
122 /* xa51_emitDebuggerSymbol - associate the current code location */
123 /* with a debugger symbol */
124 /*-----------------------------------------------------------------*/
126 xa51_emitDebuggerSymbol (char * debugSym)
129 emitcode ("", "%s ==.", debugSym);
134 char *getStackOffset(int stack) {
135 static char gsoBuf[1024];
136 sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
137 currFunc->stack, _G.nRegsSaved);
141 /*-----------------------------------------------------------------*/
142 /* newAsmop - creates a new asmOp */
143 /*-----------------------------------------------------------------*/
145 newAsmop (short type)
149 aop = Safe_calloc (1, sizeof (asmop));
154 char *aopTypeName(asmop *aop) {
157 case AOP_LIT: return "lit";
158 case AOP_REG: return "reg";
159 case AOP_DIR: return "dir";
160 case AOP_FAR: return "far";
161 case AOP_CODE: return "code";
162 case AOP_GPTR: return "gptr";
163 case AOP_STK: return "stack";
164 case AOP_IMMD: return "imm";
165 case AOP_BIT: return "bit";
170 /*-----------------------------------------------------------------*/
171 /* aopForSym - for a true symbol */
172 /*-----------------------------------------------------------------*/
173 static asmop *aopForSym(symbol *sym,
174 bool canUsePointer, bool canUseOffset) {
178 sym->aop = aop = newAsmop(0);
179 size=aop->size=getSize(sym->type);
181 // if the sym has registers
182 if (sym->nRegs && sym->regs[0]) {
184 sprintf (aop->name[0], sym->regs[0]->name);
186 sprintf (aop->name[1], sym->regs[1]->name);
193 if (!canUsePointer || !canUseOffset) {
198 emitcode ("mov.b", "r0l,[%s] ;aopForSym:stack:1", getStackOffset(sym->stack));
199 sprintf (aop->name[0], "r0l");
202 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:2", getStackOffset(sym->stack));
203 sprintf (aop->name[0], "r0");
206 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:3.w", getStackOffset(sym->stack));
207 sprintf (aop->name[0], "r0");
208 emitcode ("mov.b", "r1l,[%s] ;aopForSym:stack:3.b", getStackOffset(sym->stack+2));
209 sprintf (aop->name[1], "r1l");
212 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack));
213 sprintf (aop->name[0], "r0");
214 emitcode ("mov.w", "r1,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack+2));
215 sprintf (aop->name[1], "r1");
220 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
222 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
227 // if it has a spillLoc
228 if (sym->usl.spillLoc) {
229 return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
233 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
235 sprintf (aop->name[0], sym->rname);
239 // if in direct space
240 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
242 sprintf (aop->name[0], sym->rname);
244 sprintf (aop->name[1], "%s+2", sym->rname);
250 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
251 if (!canUsePointer) {
256 emitcode (MOV, "r0,#%s", sym->rname);
257 emitcode (MOVC, "r0l,[r0+]");
258 sprintf (aop->name[0], "r0l");
261 emitcode (MOV, "r0,#%s", sym->rname);
262 emitcode (MOVC, "r0,[r0+]");
263 sprintf (aop->name[0], "r0");
266 emitcode (MOV, "r0,#%s", sym->rname);
267 emitcode (MOVC, "r0,[r0+]");
268 sprintf (aop->name[1], "r0");
269 emitcode (MOV, "r1l,[r0+]");
270 sprintf (aop->name[0], "r1l");
273 emitcode (MOV, "r0,#%s", sym->rname);
274 emitcode (MOVC, "r1,[r0+]");
275 emitcode (MOVC, "r0,[r0+]");
276 emitcode ("xch", "r0,r1");
277 sprintf (aop->name[0], "r0");
278 sprintf (aop->name[1], "r1");
284 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
285 sprintf (aop->name[0], "[r0]");
287 sprintf (aop->name[1], "[r0+2]");
294 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
295 if (!canUsePointer) {
300 emitcode (MOV, "r0,#%s", sym->rname);
301 emitcode (MOV, "r0l,[r0]");
302 sprintf (aop->name[0], "r0l");
305 emitcode (MOV, "r0,#%s", sym->rname);
306 emitcode (MOV, "r0,[r0]");
307 sprintf (aop->name[0], "r0");
310 emitcode (MOV, "r0,#%s", sym->rname);
311 emitcode (MOV, "r1l,[r0+2]");
312 sprintf (aop->name[1], "r1l");
313 emitcode (MOV, "r0,[r0]");
314 sprintf (aop->name[0], "r0");
317 emitcode (MOV, "r0,#%s", sym->rname);
318 emitcode (MOV, "r1,[r0+2]");
319 sprintf (aop->name[1], "r1");
320 emitcode (MOV, "r0,[r0]");
321 sprintf (aop->name[0], "r0");
326 emitcode ("mov.w", "r0,#%s ; aopForSym:far", sym->rname);
327 sprintf (aop->name[0], "[r0]");
329 sprintf (aop->name[1], "[r0+2]");
335 bailOut("aopForSym");
339 /*-----------------------------------------------------------------*/
340 /* aopForVal - for a value */
341 /*-----------------------------------------------------------------*/
342 static asmop *aopForVal(operand *op) {
345 if (IS_OP_LITERAL(op)) {
346 op->aop = aop = newAsmop (AOP_LIT);
347 switch ((aop->size=getSize(operandType(op))))
350 sprintf (aop->name[0], "#0x%02x",
351 SPEC_CVAL(operandType(op)).v_int & 0xff);
352 sprintf (aop->name[1], "#0");
355 sprintf (aop->name[0], "#0x%04x",
356 SPEC_CVAL(operandType(op)).v_int & 0xffff);
357 sprintf (aop->name[1], "#0");
360 // must be a generic pointer, can only be zero
361 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
362 sprintf (aop->name[0], "#0x%04x",
363 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
364 sprintf (aop->name[1], "#0");
367 sprintf (aop->name[0], "#0x%04x",
368 SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
369 sprintf (aop->name[1], "#0x%04x",
370 SPEC_CVAL(operandType(op)).v_ulong >> 16);
373 bailOut("aopForVal");
380 op->aop = aop = newAsmop (AOP_IMMD);
381 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
385 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
387 case 3: // generic pointer
388 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
389 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
394 bailOut ("aopForVal: unknown type");
398 static int aopOp(operand *op,
399 bool canUsePointer, bool canUseOffset) {
402 op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
406 op->aop=aopForVal (op);
410 bailOut("aopOp: unexpected operand");
414 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
415 if (strcmp(aop1->name[offset], aop2->name[offset])) {
421 bool aopIsDir(operand *op) {
422 return AOP_TYPE(op)==AOP_DIR;
425 bool aopIsBit(operand *op) {
426 return AOP_TYPE(op)==AOP_BIT;
429 bool aopIsPtr(operand *op) {
430 if (AOP_TYPE(op)==AOP_STK ||
431 AOP_TYPE(op)==AOP_CODE ||
432 AOP_TYPE(op)==AOP_FAR) {
439 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
442 if (OP_SYMBOL(op)->onStack) {
443 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
446 if (IS_TRUE_SYMOP(op))
447 return OP_SYMBOL(op)->rname;
448 else if (OP_SYMBOL(op)->regs[offset])
449 return OP_SYMBOL(op)->regs[offset]->name;
451 bailOut("opRegName: unknown regs");
455 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
458 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
459 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
460 bailOut("opRegName: invalid bit value");
464 sprintf (opName, "#%s0x%02x", decorate?"(char)":"",
465 SPEC_CVAL(OP_VALUE(op)->type).v_int);
468 if (SPEC_LONG(OP_VALUE(op)->type)) {
469 sprintf (opName, "#%s0x%02x", decorate?"(long)":"",
470 SPEC_CVAL(OP_VALUE(op)->type).v_long);
472 sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
473 SPEC_CVAL(OP_VALUE(op)->type).v_int);
477 sprintf (opName, "#%s%f", decorate?"(float)":"",
478 SPEC_CVAL(OP_VALUE(op)->type).v_float);
481 bailOut("opRegName: unexpected noun");
485 bailOut("opRegName: unexpected operand type");
489 char * printOp (operand *op) {
490 static char line[132];
491 sym_link *optype=operandType(op);
492 bool isPtr = IS_PTR(optype);
495 symbol *sym=OP_SYMBOL(op);
496 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
497 sym=SYM_SPIL_LOC(sym);
501 if (DCL_TYPE(optype)==FPOINTER)
502 strcat (line, "far * ");
503 else if (DCL_TYPE(optype)==CPOINTER)
504 strcat (line, "code * ");
505 else if (DCL_TYPE(optype)==GPOINTER)
506 strcat (line, "gen * ");
507 else if (DCL_TYPE(optype)==POINTER)
508 strcat (line, "near * ");
510 strcat (line, "unknown * ");
512 strcat (line, nounName(sym->etype));
514 strcat (line, sym->name);
517 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
520 strcat (line, sym->regs[0]->name);
523 strcat (line, sym->regs[1]->name);
528 sprintf (line+strlen(line), "stack%+d", sym->stack);
531 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
532 strcat (line, "code");
535 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
536 strcat (line, "far");
539 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
540 strcat (line, "bit");
543 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
544 strcat (line, "dir");
547 strcat (line, "unknown");
549 } else if (IS_VALOP(op)) {
550 opRegName(op, 0, line, 1);
551 } else if (IS_TYPOP(op)) {
554 if (DCL_TYPE(optype)==FPOINTER)
555 strcat (line, "far * ");
556 else if (DCL_TYPE(optype)==CPOINTER)
557 strcat (line, "code * ");
558 else if (DCL_TYPE(optype)==GPOINTER)
559 strcat (line, "gen * ");
560 else if (DCL_TYPE(optype)==POINTER)
561 strcat (line, "near * ");
563 strcat (line, "unknown * ");
565 // forget about static, volatile, ... for now
566 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
567 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
568 strcat (line, nounName(operandType(op)));
571 bailOut("printOp: unexpected operand type");
576 void printIc (bool printToStderr,
577 char *op, iCode * ic, bool result, bool left, bool right) {
580 sprintf (line, "%s(%d)", op, ic->lineno);
582 strcat (line, " result=");
583 strcat (line, printOp (IC_RESULT(ic)));
586 strcat (line, " left=");
587 strcat (line, printOp (IC_LEFT(ic)));
590 strcat (line, " right=");
591 strcat (line, printOp (IC_RIGHT(ic)));
593 emitcode (";", line);
595 fprintf (stderr, "%s\n", line);
599 /*-----------------------------------------------------------------*/
600 /* toBoolean - return carry for operand!=0 */
601 /*-----------------------------------------------------------------*/
602 static char *toBoolean (operand * op) {
603 symbol *tlbl=newiTempLabel(NULL);
605 switch (AOP_SIZE(op))
609 emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
610 "This needs a second thought");
612 emitcode ("", "%05d$:", tlbl->key+100);
616 bailOut("toBoolean: unknown size");
620 /*-----------------------------------------------------------------*/
621 /* regsInCommon - two operands have some registers in common */
622 /*-----------------------------------------------------------------*/
623 static bool regsInCommon (operand * op1, operand * op2) {
627 /* if they have registers in common */
628 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
631 sym1 = OP_SYMBOL (op1);
632 sym2 = OP_SYMBOL (op2);
634 if (sym1->nRegs == 0 || sym2->nRegs == 0)
637 for (i = 0; i < sym1->nRegs; i++)
643 for (j = 0; j < sym2->nRegs; j++)
648 if (sym2->regs[j] == sym1->regs[i])
656 /*-----------------------------------------------------------------*/
657 /* resultRemat - result is rematerializable */
658 /*-----------------------------------------------------------------*/
659 static int resultRemat (iCode * ic) {
660 if (SKIP_IC (ic) || ic->op == IFX)
663 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
665 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
666 if (sym->remat && !POINTER_SET (ic))
673 /*-----------------------------------------------------------------*/
674 /* genNot - generate code for ! operation */
675 /*-----------------------------------------------------------------*/
676 static void genNot (iCode * ic) {
677 printIc (0, "genNot:", ic, 1,1,0);
680 /*-----------------------------------------------------------------*/
681 /* genCpl - generate code for complement */
682 /*-----------------------------------------------------------------*/
683 static void genCpl (iCode * ic) {
684 printIc (0, "genCpl", ic, 1,1,0);
687 /*-----------------------------------------------------------------*/
688 /* genUminus - unary minus code generation */
689 /*-----------------------------------------------------------------*/
690 static void genUminus (iCode * ic) {
691 printIc (0, "genUminus", ic, 1,1,0);
694 /*-----------------------------------------------------------------*/
695 /* genIpush - generate code for pushing */
696 /*-----------------------------------------------------------------*/
697 static void genIpush (iCode * ic) {
698 operand *left=IC_LEFT(ic);
700 printIc (0, "genIpush", ic, 0,1,0);
701 aopOp(left,FALSE,FALSE);
704 if (AOP_TYPE(left)==AOP_LIT) {
705 switch (AOP_SIZE(left))
708 emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
709 emitcode ("push", "r1l");
713 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
714 emitcode ("push", "r1");
718 emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
719 emitcode ("push", "r1l");
720 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
721 emitcode ("push", "r1");
725 emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
726 emitcode ("push", "r1");
727 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
728 emitcode ("push", "r1");
733 if (AOP_SIZE(left)>2) {
734 emitcode ("push", "%s", AOP_NAME(left)[1]);
737 emitcode ("push", "%s", AOP_NAME(left)[0]);
742 /*-----------------------------------------------------------------*/
743 /* genIpop - recover the registers: can happen only for spilling */
744 /*-----------------------------------------------------------------*/
745 static void genIpop (iCode * ic) {
746 printIc (0, "genIpop", ic, 0,1,0);
749 /*-----------------------------------------------------------------*/
750 /* genCall - generates a call statement */
751 /*-----------------------------------------------------------------*/
752 static void genCall (iCode * ic) {
753 operand *result=IC_RESULT(ic);
755 emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
756 OP_SYMBOL(IC_LEFT(ic))->name,
757 printOp (IC_RESULT(ic)));
758 emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
760 /* readjust the stack if we have pushed some parms */
761 if (_G.parmsPushed) {
762 emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
766 /* if we need to assign a result value */
767 if (IS_ITEMP (IC_RESULT(ic)) &&
768 OP_SYMBOL (IC_RESULT (ic))->nRegs) {
769 aopOp(result,FALSE,FALSE);
770 switch (AOP_SIZE(result))
773 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
776 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
780 emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
781 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
784 emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
785 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
792 /*-----------------------------------------------------------------*/
793 /* genPcall - generates a call by pointer statement */
794 /*-----------------------------------------------------------------*/
796 genPcall (iCode * ic)
798 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
801 /*-----------------------------------------------------------------*/
802 /* genFunction - generated code for function entry */
803 /*-----------------------------------------------------------------*/
804 static void genFunction (iCode * ic) {
805 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
806 sym_link *type=sym->type;
808 emitcode (";", "genFunction %s", sym->rname);
810 /* print the allocation information */
811 printAllocInfo (currFunc, codeOutBuf);
813 emitcode ("", "%s:", sym->rname);
815 if (IFFUNC_ISNAKED(type))
817 emitcode(";", "naked function: no prologue.");
821 /* adjust the stack for locals used in this function */
823 emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
827 /*-----------------------------------------------------------------*/
828 /* genEndFunction - generates epilogue for functions */
829 /*-----------------------------------------------------------------*/
831 genEndFunction (iCode * ic)
833 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
835 printIc (0, "genEndFunction", ic, 0,0,0);
837 if (IFFUNC_ISNAKED(sym->type)) {
838 emitcode(";", "naked function: no epilogue.");
839 if (options.debug && currFunc)
840 debugFile->writeEndFunction (currFunc, ic, 0);
844 /* readjust the stock for locals used in this function */
846 emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
849 if (options.debug && currFunc) {
850 debugFile->writeEndFunction (currFunc, ic, 1);
853 if (IFFUNC_ISISR(sym->type)) {
854 emitcode ("reti", "");
856 emitcode ("ret", "");
860 /*-----------------------------------------------------------------*/
861 /* genRet - generate code for return statement */
862 /*-----------------------------------------------------------------*/
863 static void genRet (iCode * ic) {
866 printIc (0, "genRet", ic, 0, 0, 0);
868 printIc (0, "genRet", ic, 0, 1, 0);
869 aopOp(IC_LEFT(ic), TRUE, TRUE);
870 switch (AOP_SIZE(IC_LEFT(ic)))
873 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
874 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
877 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
880 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
883 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
890 emitcode ("jmp", "%05d$", returnLabel->key+100);
893 /*-----------------------------------------------------------------*/
894 /* genLabel - generates a label */
895 /*-----------------------------------------------------------------*/
896 static void genLabel (iCode * ic) {
897 /* special case never generate */
898 if (IC_LABEL (ic) == entryLabel)
901 emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
902 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
905 /*-----------------------------------------------------------------*/
906 /* genGoto - generates a jmp */
907 /*-----------------------------------------------------------------*/
908 static void genGoto (iCode * ic) {
909 emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
910 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
913 /*-----------------------------------------------------------------*/
914 /* genPlus - generates code for addition */
915 /*-----------------------------------------------------------------*/
916 static void genPlus (iCode * ic) {
917 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
921 printIc (0, "genPlus", ic, 1,1,1);
923 size=aopOp(result, TRUE, TRUE);
925 /* if left is a literal, then exchange them */
926 if (IS_LITERAL(operandType(left))) {
927 operand *tmp = right;
932 if (aopIsBit(result)) {
933 if (IS_LITERAL(operandType(right))) {
934 if (operandLitValue(right)) {
935 emitcode ("setb", AOP_NAME(result)[0]);
938 aopOp(left, TRUE, TRUE);
939 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
942 bailOut("genPlus: unfinished genPlus bit");
945 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
946 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
948 // special case for "* = * + char", needs a closer look
949 // heck, this shouldn't have come here but bug-223113 does
950 if (size==3 && AOP_SIZE(right)==1) {
951 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
952 emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
953 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
954 emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
955 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
959 // special case for "xdata * = xdata * + char", needs a closer look
960 // heck, this shouldn't have come here but bug-441448 does
961 if (size==2 && AOP_SIZE(right)==1) {
962 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
963 emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
964 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
965 emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
974 if (!aopEqual(result->aop, left->aop, 0)) {
975 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
977 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
979 if (!aopEqual(result->aop, left->aop, 1)) {
980 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
985 emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
991 /*-----------------------------------------------------------------*/
992 /* genMinus - generates code for subtraction */
993 /*-----------------------------------------------------------------*/
994 static void genMinus (iCode * ic) {
995 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
999 printIc (0, "genMinus", ic, 1,1,1);
1001 size=aopOp(result, TRUE, TRUE);
1003 /* if left is a literal, then exchange them */
1004 if (IS_LITERAL(operandType(left))) {
1005 operand *tmp = right;
1010 if (aopIsBit(result)) {
1011 if (IS_LITERAL(operandType(right))) {
1012 if (operandLitValue(right)) {
1013 emitcode ("clr", AOP_NAME(result)[0]);
1016 aopOp(left, TRUE, TRUE);
1017 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1020 bailOut("genPlus: unfinished genPlus bit");
1023 if (isOperandEqual(result,left)) {
1024 left->aop=result->aop;
1026 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1028 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1035 if (!aopEqual(result->aop, left->aop, 0)) {
1036 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1038 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1040 if (!aopEqual(result->aop, left->aop, 1)) {
1041 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1046 emitcode ("subb.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1052 /*-----------------------------------------------------------------*/
1053 /* genMult - generates code for multiplication */
1054 /*-----------------------------------------------------------------*/
1055 static void genMult (iCode * ic) {
1056 printIc (0, "genMult", ic, 1,1,1);
1059 /*-----------------------------------------------------------------*/
1060 /* genDiv - generates code for division */
1061 /*-----------------------------------------------------------------*/
1062 static void genDiv (iCode * ic) {
1063 printIc (0, "genDiv", ic, 1,1,1);
1066 /*-----------------------------------------------------------------*/
1067 /* genMod - generates code for division */
1068 /*-----------------------------------------------------------------*/
1069 static void genMod (iCode * ic) {
1070 printIc (0, "genMod", ic, 1,1,1);
1073 /*-----------------------------------------------------------------*/
1074 /* ifxForOp - returns the icode containing the ifx for operand */
1075 /*-----------------------------------------------------------------*/
1076 static iCode *ifxForOp (operand * op, iCode * ic) {
1077 /* if true symbol then needs to be assigned */
1078 if (IS_TRUE_SYMOP (op))
1081 /* if this has register type condition and
1082 the next instruction is ifx with the same operand
1083 and live to of the operand is upto the ifx only then */
1085 ic->next->op == IFX &&
1086 IC_COND (ic->next)->key == op->key &&
1087 OP_SYMBOL (op)->liveTo <= ic->next->seq)
1093 /*-----------------------------------------------------------------*/
1094 /* genCmp - compares whatever */
1095 /*-----------------------------------------------------------------*/
1096 static void genCmp (iCode * ic, char *trueInstr, char *falseInstr) {
1097 iCode *ifx=ifxForOp(IC_RESULT(ic),ic);
1098 operand *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1105 size=aopOp(left, TRUE, TRUE);
1106 aopOp(right, !aopIsPtr(left), TRUE);
1116 jlbl=IC_TRUE(ifx)->key+100;
1119 jlbl=IC_FALSE(ifx)->key+100;
1123 aopOp(IC_RESULT(ic), !aopIsPtr(left), TRUE);
1124 jlbl=newiTempLabel(NULL)->key+100;
1125 emitcode("mov", "%s,#-1", AOP_NAME(IC_RESULT(ic))[0]);
1126 emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1127 emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1128 emitcode("cpl", "%s", AOP_NAME(IC_RESULT(ic))[0]);
1129 emitcode("", "%05d$:", jlbl);
1131 emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1132 emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1137 bailOut("genCmp: size > 2");
1142 /*-----------------------------------------------------------------*/
1143 /* genCmpEq :- generates code for equal to */
1144 /*-----------------------------------------------------------------*/
1145 static void genCmpEq (iCode * ic) {
1146 printIc (0, "genCmpEq", ic, 0,1,1);
1147 genCmp(ic, "beq", "bne"); // no sign
1150 /*-----------------------------------------------------------------*/
1151 /* genCmpGt :- greater than comparison */
1152 /*-----------------------------------------------------------------*/
1153 static void genCmpGt (iCode * ic) {
1154 printIc (0, "genCmpGt", ic, 0,1,1);
1155 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1156 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1157 genCmp(ic, "bg", "bl"); // unsigned
1159 genCmp(ic, "bgt", "ble"); // signed
1163 /*-----------------------------------------------------------------*/
1164 /* genCmpLt - less than comparisons */
1165 /*-----------------------------------------------------------------*/
1166 static void genCmpLt (iCode * ic) {
1167 printIc (0, "genCmpLt", ic, 0,1,1);
1168 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1169 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1170 genCmp(ic, "bcs", "bcc"); // unsigned
1172 genCmp(ic, "blt", "bge"); // signed
1176 /*-----------------------------------------------------------------*/
1177 /* hasInc - operand is incremented before any other use */
1178 /*-----------------------------------------------------------------*/
1179 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1180 sym_link *type = operandType(op);
1181 sym_link *retype = getSpec (type);
1182 iCode *lic = ic->next;
1185 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1186 if (!IS_SYMOP(op)) return NULL;
1188 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1189 if (IS_AGGREGATE(type->next)) return NULL;
1190 if (osize != (isize = getSize(type->next))) return NULL;
1193 /* if operand of the form op = op + <sizeof *op> */
1194 if (lic->op == '+') {
1195 if (isOperandEqual(IC_LEFT(lic),op) &&
1196 //isOperandEqual(IC_RESULT(lic),op) &&
1197 isOperandLiteral(IC_RIGHT(lic)) &&
1198 operandLitValue(IC_RIGHT(lic)) == isize) {
1199 emitcode (";", "Found hasInc");
1203 /* if the operand used or deffed */
1204 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
1207 /* if GOTO or IFX */
1208 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1214 /*-----------------------------------------------------------------*/
1215 /* genAndOp - for && operation */
1216 /*-----------------------------------------------------------------*/
1217 static void genAndOp (iCode * ic) {
1218 printIc (0, "genAndOp(&&)", ic, 1,1,1);
1221 /*-----------------------------------------------------------------*/
1222 /* genOrOp - for || operation */
1223 /*-----------------------------------------------------------------*/
1224 static void genOrOp (iCode * ic) {
1225 printIc (0, "genOrOp(||)", ic, 1,1,1);
1228 /*-----------------------------------------------------------------*/
1229 /* genAnd - code for and */
1230 /*-----------------------------------------------------------------*/
1231 static void genAnd (iCode * ic, iCode * ifx) {
1232 printIc (0, "genAnd", ic, 1,1,1);
1235 /*-----------------------------------------------------------------*/
1236 /* genOr - code for or */
1237 /*-----------------------------------------------------------------*/
1238 static void genOr (iCode * ic, iCode * ifx) {
1239 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1243 printIc (0, "genOr", ic, 1,1,1);
1245 size=aopOp(result, TRUE, TRUE);
1247 /* if left is a literal, then exchange them */
1248 if (IS_LITERAL(operandType(left))) {
1249 operand *tmp = right;
1254 if (aopIsBit(result)) {
1255 if (IS_LITERAL(operandType(right))) {
1256 if (operandLitValue(right)) {
1257 emitcode ("setb", AOP_NAME(result)[0]);
1260 aopOp(left, TRUE, TRUE);
1261 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1266 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1267 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1274 if (!aopEqual(result->aop, left->aop, 0)) {
1275 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1277 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1279 if (!aopEqual(result->aop, left->aop, 1)) {
1280 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1282 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1287 /*-----------------------------------------------------------------*/
1288 /* genXor - code for xclusive or */
1289 /*-----------------------------------------------------------------*/
1290 static void genXor (iCode * ic, iCode * ifx) {
1291 printIc (0, "genXor", ic, 1,1,1);
1294 /*-----------------------------------------------------------------*/
1295 /* genInline - write the inline code out */
1296 /*-----------------------------------------------------------------*/
1297 static void genInline (iCode * ic) {
1299 printIc (0, "genInline", ic, 0,0,0);
1301 emitcode ("", IC_INLINE(ic));
1304 /*-----------------------------------------------------------------*/
1305 /* genRRC - rotate right with carry */
1306 /*-----------------------------------------------------------------*/
1307 static void genRRC (iCode * ic) {
1308 printIc (0, "genRRC", ic, 1,1,0);
1311 /*-----------------------------------------------------------------*/
1312 /* genRLC - generate code for rotate left with carry */
1313 /*-----------------------------------------------------------------*/
1314 static void genRLC (iCode * ic) {
1315 printIc (0, "genRLC", ic, 1,1,0);
1318 /*-----------------------------------------------------------------*/
1319 /* genGetHbit - generates code get highest order bit */
1320 /*-----------------------------------------------------------------*/
1321 static void genGetHbit (iCode * ic) {
1322 printIc (0, "genGetHbit", ic, 1,1,0);
1325 /*-----------------------------------------------------------------*/
1326 /* genLeftShift - generates code for left shifting */
1327 /*-----------------------------------------------------------------*/
1328 static void genLeftShift (iCode * ic) {
1329 printIc (0, "genLeftShift", ic, 1,1,1);
1332 /*-----------------------------------------------------------------*/
1333 /* genRightShift - generate code for right shifting */
1334 /*-----------------------------------------------------------------*/
1335 static void genRightShift (iCode * ic) {
1336 printIc (0, "genRightShift", ic, 1,1,1);
1339 /*-----------------------------------------------------------------*/
1340 /* genPointerGet - generate code for pointer get */
1341 /*-----------------------------------------------------------------*/
1342 static void genPointerGet (iCode * ic, iCode *pi) {
1343 char *instr, *scratchReg;
1344 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1345 bool codePointer=IS_CODEPTR(operandType(left));
1349 printIc (0, "genPointerGet pi", ic, 1,1,0);
1351 printIc (0, "genPointerGet", ic, 1,1,0);
1354 if (!IS_PTR(operandType(left))) {
1355 bailOut ("genPointerGet: pointer required");
1358 aopOp(left,FALSE,FALSE);
1359 size=aopOp(result,TRUE,aopIsDir(left));
1361 if (IS_GENPTR(operandType(left))) {
1362 symbol *tlbl1=newiTempLabel(NULL);
1363 symbol *tlbl2=newiTempLabel(NULL);
1364 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1365 emitcode ("beq", "%05d$", tlbl1->key+100);
1368 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1371 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1375 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1377 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1380 emitcode ("br", "%05d$", tlbl2->key+100);
1381 emitcode ("", "%05d$:", tlbl1->key+100);
1384 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1387 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1388 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1392 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1394 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1397 emitcode ("", "%05d$:", tlbl2->key+100);
1401 switch (AOP_TYPE(left))
1404 emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1405 sprintf (AOP_NAME(left)[0], "r1");
1423 if (AOP_TYPE(result)==AOP_STK) {
1424 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1425 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1428 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
1433 emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1434 emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1436 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
1450 if (AOP_TYPE(result)==AOP_STK) {
1451 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1452 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1455 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1459 emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1461 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1469 bailOut ("genPointerGet");
1472 /*-----------------------------------------------------------------*/
1473 /* genPointerSet - stores the value into a pointer location */
1474 /*-----------------------------------------------------------------*/
1475 static void genPointerSet (iCode * ic, iCode *pi) {
1477 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1480 printIc (0, "genPointerSet", ic, 1,0,1);
1482 if (!IS_PTR(operandType(result))) {
1483 bailOut ("genPointerSet: pointer required");
1486 aopOp(result,FALSE,FALSE);
1487 size=aopOp(right,FALSE, FALSE);
1489 if (IS_GENPTR(operandType(result))) {
1490 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1491 AOP_NAME(result)[0], AOP_NAME(result)[1],
1492 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1496 switch (AOP_TYPE(right))
1506 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1509 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1516 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1517 AOP_NAME(right)[1]);
1519 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1520 AOP_NAME(right)[1]);
1525 bailOut ("genPointerSet");
1528 /*-----------------------------------------------------------------*/
1529 /* genIfx - generate code for Ifx statement */
1530 /*-----------------------------------------------------------------*/
1531 static void genIfx (iCode * ic, iCode * popIc) {
1535 symbol *jlbl, *tlbl=newiTempLabel(NULL);
1536 operand *cond=IC_COND(ic);
1538 emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s",
1539 ic->lineno, printOp(cond),
1540 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1541 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1543 size=aopOp(cond,TRUE,TRUE);
1553 switch (AOP_TYPE(cond) )
1556 emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$",
1557 AOP_NAME(cond)[0], tlbl->key+100);
1558 emitcode ("jmp", "%05d$", jlbl->key+100);
1559 emitcode ("", "%05d$:", tlbl->key+100);
1570 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1571 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1574 // generic pointer, forget the generic part
1576 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1577 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1580 emitcode ("jmp", "%05d$", jlbl->key+100);
1581 emitcode ("", "%05d$:", tlbl->key+100);
1587 /*-----------------------------------------------------------------*/
1588 /* genAddrOf - generates code for address of */
1589 /*-----------------------------------------------------------------*/
1590 static void genAddrOf (iCode * ic) {
1592 operand *left=IC_LEFT(ic);
1594 printIc (0, "genAddrOf", ic, 1,1,0);
1596 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1598 if (isOperandOnStack(left)) {
1599 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1600 getStackOffset(OP_SYMBOL(left)->stack));
1602 // this must be a generic pointer
1603 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1608 if (isOperandInDirSpace(left) ||
1609 isOperandInFarSpace(left) ||
1610 isOperandInCodeSpace(left)) {
1611 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1612 OP_SYMBOL(left)->rname);
1614 // this must be a generic pointer
1615 int space=0; // dir space
1616 if (isOperandInFarSpace(left)) {
1618 } else if (isOperandInCodeSpace(left)) {
1621 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1626 bailOut("genAddrOf");
1629 /*-----------------------------------------------------------------*/
1630 /* genAssign - generate code for assignment */
1631 /*-----------------------------------------------------------------*/
1632 static void genAssign (iCode * ic) {
1633 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1637 printIc (0, "genAssign", ic, 1,0,1);
1639 if (!IS_SYMOP(result)) {
1640 bailOut("genAssign: result is not a symbol");
1643 aopOp(result, TRUE, TRUE);
1644 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1645 size=AOP_SIZE(result);
1647 /* if result is a bit */
1648 if (AOP_TYPE(result) == AOP_BIT) {
1649 /* if right is literal, we know what the value is */
1650 if (AOP_TYPE(right) == AOP_LIT) {
1651 if (operandLitValue(right)) {
1652 emitcode ("setb", AOP_NAME(result)[0]);
1654 emitcode ("clr", AOP_NAME(result)[0]);
1658 /* if right is also a bit */
1659 if (AOP_TYPE(right) == AOP_BIT) {
1660 emitcode ("mov", "c,%s", AOP_NAME(right));
1661 emitcode ("mov", "%s,c", AOP_NAME(result));
1665 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1669 // TODO: if (-8 >= right==lit <= 7) instr=MOVS
1676 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1683 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1688 /*-----------------------------------------------------------------*/
1689 /* genJumpTab - genrates code for jump table */
1690 /*-----------------------------------------------------------------*/
1691 static void genJumpTab (iCode * ic) {
1692 printIc (0, "genJumpTab", ic, 0,0,0);
1695 /*-----------------------------------------------------------------*/
1696 /* genCast - gen code for casting */
1697 /*-----------------------------------------------------------------*/
1698 static void genCast (iCode * ic) {
1700 operand *result=IC_RESULT(ic);
1701 operand *right=IC_RIGHT(ic);
1702 sym_link *ctype=operandType(IC_LEFT(ic));
1703 sym_link *rtype=operandType(IC_RIGHT(ic));
1704 sym_link *etype=getSpec(rtype);
1705 short ptrType, signedness;
1707 printIc (0, "genCast", ic, 1,1,1);
1709 aopOp(result, TRUE, TRUE);
1710 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1711 size=AOP_SIZE(result);
1713 /* if result is a bit */
1714 if (AOP_TYPE(result) == AOP_BIT) {
1715 /* if right is literal, we know what the value is */
1716 if (AOP_TYPE(right) == AOP_LIT) {
1717 if (operandLitValue(right)) {
1718 emitcode ("setb", AOP_NAME(result)[0]);
1720 emitcode ("clr", AOP_NAME(result)[0]);
1724 /* if right is also a bit */
1725 if (AOP_TYPE(right) == AOP_BIT) {
1726 emitcode ("mov", "c,%s", AOP_NAME(right));
1727 emitcode ("mov", "%s,c", AOP_NAME(result));
1731 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1735 /* if right is a bit */
1736 if (AOP_TYPE(right)==AOP_BIT) {
1737 emitcode ("mov", "c,%s", AOP_NAME(right));
1738 emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1739 emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1741 emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1746 /* if the result is of type pointer */
1747 if (IS_PTR (ctype)) {
1749 if (AOP_SIZE(right)>1) {
1750 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1752 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1753 emitcode ("sext", "r1h");
1754 emitcode ("mov", "%s,r1", AOP_NAME(result)[0]);
1757 /* if pointer to generic pointer */
1758 if (IS_GENPTR (ctype)) {
1760 if (IS_GENPTR (rtype)) {
1761 bailOut("genCast: gptr -> gptr");
1764 if (IS_PTR (rtype)) {
1765 ptrType = DCL_TYPE (rtype);
1767 /* we have to go by the storage class */
1768 if (!SPEC_OCLS(etype)) {
1769 ptrType=0; // hush the compiler
1770 bailOut("genCast: unknown storage class");
1772 ptrType = PTR_TYPE (SPEC_OCLS (etype));
1776 /* the generic part depends on the type */
1780 emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1783 emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1786 emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1789 bailOut("genCast: got unknown storage class");
1795 /* do we have to sign extend? */
1796 signedness = SPEC_USIGN(rtype);
1798 /* now depending on the size */
1799 switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1803 emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1808 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1811 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1813 emitcode("sext", "%s", AOP_NAME(result)[1]);
1815 emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1820 emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1822 emitcode("sext", "r1h");
1824 emitcode("mov", "r1h,#0");
1826 emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1829 // fall through: case 0x41
1831 emitcode("sext", "r1");
1833 emitcode("mov", "r1,#0");
1835 emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1839 emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1840 emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1843 fprintf(stderr, "genCast: unknown size: %d:%d\n",
1844 AOP_SIZE(result), AOP_SIZE(right));
1845 bailOut("genCast: unknown size");
1849 /*-----------------------------------------------------------------*/
1850 /* genDjnz - generate decrement & jump if not zero instrucion */
1851 /*-----------------------------------------------------------------*/
1852 static bool genDjnz (iCode * ic, iCode * ifx) {
1858 /* if the if condition has a false label
1859 then we cannot save */
1863 /* if the minus is not of the form
1865 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1866 !IS_OP_LITERAL (IC_RIGHT (ic)))
1869 if (operandLitValue (IC_RIGHT (ic)) != 1)
1872 /* if the size of this greater than two then no
1874 if (getSize (operandType (IC_RESULT (ic))) > 2)
1877 printIc (0, "genDjnz", ic, 1,1,1);
1879 /* otherwise we can save BIG */
1880 lbl = newiTempLabel (NULL);
1881 lbl1 = newiTempLabel (NULL);
1883 aopOp (IC_RESULT (ic), FALSE, TRUE);
1885 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1886 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1887 emitcode ("br", "%05d$", lbl1->key + 100);
1888 emitcode ("", "%05d$:", lbl->key + 100);
1889 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1890 emitcode ("", "%05d$:", lbl1->key + 100);
1894 bailOut("genDjnz: aop type");
1898 /*-----------------------------------------------------------------*/
1899 /* genReceive - generate code for a receive iCode */
1900 /*-----------------------------------------------------------------*/
1901 static void genReceive (iCode * ic) {
1902 printIc (0, "genReceive", ic, 1,0,0);
1905 /*-----------------------------------------------------------------*/
1906 /* genDummyRead - generate code for dummy read of volatiles */
1907 /*-----------------------------------------------------------------*/
1909 genDummyRead (iCode * ic)
1911 emitcode ("; genDummyRead","");
1916 /*-----------------------------------------------------------------*/
1917 /* gen51Code - generate code for 8051 based controllers */
1918 /*-----------------------------------------------------------------*/
1919 void genXA51Code (iCode * lic) {
1923 lineHead = lineCurr = NULL;
1925 /* if debug information required */
1926 if (options.debug && currFunc)
1928 debugFile->writeFunction (currFunc, lic);
1931 for (ic = lic; ic; ic = ic->next) {
1932 if (ic->lineno && cln != ic->lineno) {
1933 if (options.debug) {
1934 debugFile->writeCLine (ic);
1936 if (!options.noCcodeInAsm) {
1937 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1938 printCLine(ic->filename, ic->lineno));
1942 if (options.iCodeInAsm) {
1943 const char *iLine = printILine(ic);
1944 emitcode("", ";ic:%d: %s", ic->key, iLine);
1948 /* if the result is marked as
1949 spilt and rematerializable or code for
1950 this has already been generated then
1952 if (resultRemat (ic) || ic->generated)
1955 /* depending on the operation */
1975 /* IPOP happens only when trying to restore a
1976 spilt live range, if there is an ifx statement
1977 following this pop then the if statement might
1978 be using some of the registers being popped which
1979 would destory the contents of the register so
1980 we need to check for this condition and handle it */
1982 ic->next->op == IFX &&
1983 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1984 genIfx (ic->next, ic);
2002 genEndFunction (ic);
2022 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
2050 /* note these two are xlated by algebraic equivalence
2051 during parsing SDCC.y */
2052 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2053 "got '>=' or '<=' shouldn't have come here");
2069 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
2073 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
2077 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
2104 case GET_VALUE_AT_ADDRESS:
2105 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
2109 if (POINTER_SET (ic))
2110 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2136 addSet (&_G.sendSet, ic);
2139 case DUMMY_READ_VOLATILE:
2149 /* now we are ready to call the
2150 peep hole optimizer */
2151 if (!options.nopeep)
2152 peepHole (&lineHead);
2154 /* now do the actual printing */
2155 printLine (lineHead, codeOutBuf);