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)
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 In other words, you are welcome to use, share and improve this program.
22 You are forbidden to forbid anyone else to use, share and improve
23 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
33 #ifdef HAVE_SYS_ISA_DEFS_H
34 #include <sys/isa_defs.h>
40 #include "SDCChasht.h"
43 #include "SDCCicode.h"
44 #include "SDCClabel.h"
45 #include "SDCCBBlock.h"
48 #include "SDCCcflow.h"
49 #include "SDCCdflow.h"
50 #include "SDCClrange.h"
53 #include "SDCCpeeph.h"
54 #include "SDCCglue.h" /* drdani Jan 30 2000 */
56 /* this is the down and dirty file with all kinds of kludgy & hacky
57 stuff. This is what it is all about CODE GENERATION for a specific MCU.
58 Some of the routines may be reusable, will have to see */
60 static char *zero = "#0x00";
61 static char *one = "#0x01";
63 static char *fReturn[] = {"l", "h", "e", "d" };
64 static char *accUse[] = {"a" };
70 extern int ptrRegReq ;
72 extern FILE *codeOutFile;
74 #define RESULTONSTACK(x) \
75 (IC_RESULT(x) && IC_RESULT(x)->aop && \
76 IC_RESULT(x)->aop->type == AOP_STK )
78 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
79 #define CLRC emitcode("xor","a,a");
81 #define LABEL_STR "%05d$"
83 lineNode *lineHead = NULL;
84 lineNode *lineCurr = NULL;
86 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
87 0xE0, 0xC0, 0x80, 0x00};
88 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
89 0x07, 0x03, 0x01, 0x00};
91 static int _lastStack = 0;
106 /*-----------------------------------------------------------------*/
107 /* emitcode - writes the code into a file : for now it is simple */
108 /*-----------------------------------------------------------------*/
109 void emitcode (const char *inst, const char *fmt, ...)
112 char lb[MAX_INLINEASM];
118 sprintf(lb,"%s\t",inst);
119 vsprintf(lb+(strlen(lb)),fmt,ap);
123 while (isspace(*lbp)) lbp++;
126 lineCurr = (lineCurr ?
127 connectLine(lineCurr,newLineNode(lb)) :
128 (lineHead = newLineNode(lb)));
129 lineCurr->isInline = inLine;
130 lineCurr->isDebug = debugLine;
134 const char *getPairName(asmop *aop)
136 if (aop->type == AOP_REG) {
137 switch (aop->aopu.aop_reg[0]->rIdx) {
149 else if (aop->type == AOP_STR) {
150 switch (*aop->aopu.aop_str[0]) {
166 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
167 bool isPair(asmop *aop)
169 if (aop->size == 2) {
170 if (aop->type == AOP_REG) {
171 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
174 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
177 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
181 if (aop->type == AOP_STR) {
182 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
185 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
188 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
196 /** Push a register pair onto the stack */
197 void genPairPush(asmop *aop)
199 emitcode("push", "%s", getPairName(aop));
202 /*-----------------------------------------------------------------*/
203 /* newAsmop - creates a new asmOp */
204 /*-----------------------------------------------------------------*/
205 static asmop *newAsmop (short type)
209 ALLOC(aop,sizeof(asmop));
214 /*-----------------------------------------------------------------*/
215 /* aopForSym - for a true symbol */
216 /*-----------------------------------------------------------------*/
217 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
220 memmap *space= SPEC_OCLS(sym->etype);
222 /* if already has one */
226 /* Assign depending on the storage class */
227 if (sym->onStack || sym->iaccess) {
228 sym->aop = aop = newAsmop(AOP_STK);
229 aop->size = getSize(sym->type);
231 aop->aopu.aop_stk = sym->stack;
235 /* special case for a function */
236 if (IS_FUNC(sym->type)) {
237 sym->aop = aop = newAsmop(AOP_IMMD);
238 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
239 strcpy(aop->aopu.aop_immd,sym->rname);
244 /* only remaining is far space */
245 /* in which case DPTR gets the address */
246 sym->aop = aop = newAsmop(AOP_IY);
247 emitcode ("ld","iy,#%s", sym->rname);
248 aop->size = getSize(sym->type);
249 aop->aopu.aop_dir = sym->rname;
251 /* if it is in code space */
252 if (IN_CODESPACE(space))
258 /*-----------------------------------------------------------------*/
259 /* aopForRemat - rematerialzes an object */
260 /*-----------------------------------------------------------------*/
261 static asmop *aopForRemat (symbol *sym)
264 iCode *ic = sym->rematiCode;
265 asmop *aop = newAsmop(AOP_IMMD);
268 /* if plus or minus print the right hand side */
269 if (ic->op == '+' || ic->op == '-') {
270 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
273 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
276 /* we reached the end */
277 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
281 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
282 strcpy(aop->aopu.aop_immd,buffer);
286 /*-----------------------------------------------------------------*/
287 /* regsInCommon - two operands have some registers in common */
288 /*-----------------------------------------------------------------*/
289 bool regsInCommon (operand *op1, operand *op2)
294 /* if they have registers in common */
295 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
298 sym1 = OP_SYMBOL(op1);
299 sym2 = OP_SYMBOL(op2);
301 if (sym1->nRegs == 0 || sym2->nRegs == 0)
304 for (i = 0 ; i < sym1->nRegs ; i++) {
309 for (j = 0 ; j < sym2->nRegs ;j++ ) {
313 if (sym2->regs[j] == sym1->regs[i])
321 /*-----------------------------------------------------------------*/
322 /* operandsEqu - equivalent */
323 /*-----------------------------------------------------------------*/
324 bool operandsEqu ( operand *op1, operand *op2)
328 /* if they not symbols */
329 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
332 sym1 = OP_SYMBOL(op1);
333 sym2 = OP_SYMBOL(op2);
335 /* if both are itemps & one is spilt
336 and the other is not then false */
337 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
338 sym1->isspilt != sym2->isspilt )
341 /* if they are the same */
345 if (strcmp(sym1->rname,sym2->rname) == 0)
349 /* if left is a tmp & right is not */
353 (sym1->usl.spillLoc == sym2))
360 (sym2->usl.spillLoc == sym1))
366 /*-----------------------------------------------------------------*/
367 /* sameRegs - two asmops have the same registers */
368 /*-----------------------------------------------------------------*/
369 bool sameRegs (asmop *aop1, asmop *aop2 )
376 if (aop1->type != AOP_REG ||
377 aop2->type != AOP_REG )
380 if (aop1->size != aop2->size)
383 for (i = 0 ; i < aop1->size ; i++ )
384 if (aop1->aopu.aop_reg[i] !=
385 aop2->aopu.aop_reg[i] )
391 /*-----------------------------------------------------------------*/
392 /* aopOp - allocates an asmop for an operand : */
393 /*-----------------------------------------------------------------*/
394 static void aopOp (operand *op, iCode *ic, bool result)
403 /* if this a literal */
404 if (IS_OP_LITERAL(op)) {
405 op->aop = aop = newAsmop(AOP_LIT);
406 aop->aopu.aop_lit = op->operand.valOperand;
407 aop->size = getSize(operandType(op));
411 /* if already has a asmop then continue */
415 /* if the underlying symbol has a aop */
416 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
417 op->aop = OP_SYMBOL(op)->aop;
421 /* if this is a true symbol */
422 if (IS_TRUE_SYMOP(op)) {
423 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
427 /* this is a temporary : this has
433 e) can be a return use only */
437 /* if the type is a conditional */
438 if (sym->regType == REG_CND) {
439 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
444 /* if it is spilt then two situations
446 b) has a spill location */
447 if (sym->isspilt || sym->nRegs == 0) {
448 /* rematerialize it NOW */
450 sym->aop = op->aop = aop =
452 aop->size = getSize(sym->type);
458 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
459 aop->size = getSize(sym->type);
460 for ( i = 0 ; i < 2 ; i++ )
461 aop->aopu.aop_str[i] = accUse[i];
467 aop = op->aop = sym->aop = newAsmop(AOP_STR);
468 aop->size = getSize(sym->type);
469 for ( i = 0 ; i < 4 ; i++ )
470 aop->aopu.aop_str[i] = fReturn[i];
474 /* else spill location */
475 sym->aop = op->aop = aop =
476 aopForSym(ic,sym->usl.spillLoc,result);
477 aop->size = getSize(sym->type);
481 /* must be in a register */
482 sym->aop = op->aop = aop = newAsmop(AOP_REG);
483 aop->size = sym->nRegs;
484 for ( i = 0 ; i < sym->nRegs ;i++)
485 aop->aopu.aop_reg[i] = sym->regs[i];
488 /*-----------------------------------------------------------------*/
489 /* freeAsmop - free up the asmop given to an operand */
490 /*----------------------------------------------------------------*/
491 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
514 /* all other cases just dealloc */
518 OP_SYMBOL(op)->aop = NULL;
519 /* if the symbol has a spill */
521 SPIL_LOC(op)->aop = NULL;
526 char *aopGetWord(asmop *aop, int offset)
531 assert(aop->size == 2);
534 /* depending on type */
537 sprintf (s,"#%s",aop->aopu.aop_immd);
538 ALLOC_ATOMIC(rs,strlen(s)+1);
543 value * val = aop->aopu.aop_lit;
544 /* if it is a float then it gets tricky */
545 /* otherwise it is fairly simple */
546 if (!IS_FLOAT(val->type)) {
547 unsigned long v = floatFromVal(val);
549 sprintf(buffer,"#0x%04lx", v);
550 ALLOC_ATOMIC(rs,strlen(buffer)+1);
551 return strcpy (rs,buffer);
560 /*-----------------------------------------------------------------*/
561 /* aopGet - for fetching value of the aop */
562 /*-----------------------------------------------------------------*/
563 static char *aopGet (asmop *aop, int offset, bool bit16)
568 /* offset is greater than size then zero */
569 if (offset > (aop->size - 1) &&
570 aop->type != AOP_LIT)
573 /* depending on type */
577 sprintf (s,"#%s",aop->aopu.aop_immd);
587 ALLOC_ATOMIC(rs,strlen(s)+1);
593 emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
595 ALLOC_ATOMIC(rs,strlen(s)+1);
600 return aop->aopu.aop_reg[offset]->name;
603 sprintf(s,"%d(iy)", offset);
604 ALLOC_ATOMIC(rs,strlen(s)+1);
609 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
610 ALLOC_ATOMIC(rs,strlen(s)+1);
624 return aopLiteral (aop->aopu.aop_lit,offset);
628 return aop->aopu.aop_str[offset];
631 fprintf(stderr, "Type %u\n", aop->type);
633 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
634 "aopget got unsupported aop->type");
638 bool isRegString(char *s)
640 if (!strcmp(s, "b") ||
651 bool isConstant(char *s)
656 bool canAssignToPtr(char *s)
665 /*-----------------------------------------------------------------*/
666 /* aopPut - puts a string for a aop */
667 /*-----------------------------------------------------------------*/
668 static void aopPut (asmop *aop, char *s, int offset)
672 if (aop->size && offset > ( aop->size - 1)) {
673 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
674 "aopPut got offset > aop->size");
678 /* will assign value to value */
679 /* depending on where it is ofcourse */
684 emitcode("ld", "a,%s", s);
685 emitcode("ld", "(%s+%d),a", d, offset);
689 /* Dont bother if it's a ld x,x */
690 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
691 emitcode("ld","%s,%s",
692 aop->aopu.aop_reg[offset]->name,s);
697 if (!canAssignToPtr(s)) {
698 emitcode("ld", "a,%s", s);
699 emitcode("ld", "%d(iy),a", offset);
702 emitcode("ld", "%d(iy),%s", offset, s);
706 if (!canAssignToPtr(s)) {
707 emitcode("ld", "a,%s", s);
708 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
711 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
715 /* if bit variable */
716 if (!aop->aopu.aop_dir) {
717 emitcode("ld", "a,#0");
720 /* In bit space but not in C - cant happen */
727 if (strcmp(aop->aopu.aop_str[offset],s)) {
728 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
734 if (!offset && (strcmp(s,"acc") == 0))
738 emitcode("", "; Error aopPut AOP_ACC");
741 if (strcmp(aop->aopu.aop_str[offset],s))
742 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
747 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
748 "aopPut got unsupported aop->type");
753 #define AOP(op) op->aop
754 #define AOP_TYPE(op) AOP(op)->type
755 #define AOP_SIZE(op) AOP(op)->size
756 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
758 /*-----------------------------------------------------------------*/
759 /* getDataSize - get the operand data size */
760 /*-----------------------------------------------------------------*/
761 int getDataSize(operand *op)
772 /*-----------------------------------------------------------------*/
773 /* movLeft2Result - move byte from left to result */
774 /*-----------------------------------------------------------------*/
775 static void movLeft2Result (operand *left, int offl,
776 operand *result, int offr, int sign)
779 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
780 l = aopGet(AOP(left),offl,FALSE);
783 aopPut(AOP(result),l,offr);
792 /** Put Acc into a register set
794 void outAcc(operand *result)
797 size = getDataSize(result);
799 aopPut(AOP(result),"a",0);
802 /* unsigned or positive */
804 aopPut(AOP(result),zero,offset++);
809 /** Take the value in carry and put it into a register
811 void outBitC(operand *result)
813 /* if the result is bit */
814 if (AOP_TYPE(result) == AOP_CRY) {
815 emitcode("", "; Note: outBitC form 1");
816 aopPut(AOP(result),"blah",0);
819 emitcode("ld", "a,#0");
825 /*-----------------------------------------------------------------*/
826 /* toBoolean - emit code for orl a,operator(sizeop) */
827 /*-----------------------------------------------------------------*/
828 void toBoolean(operand *oper)
830 int size = AOP_SIZE(oper);
833 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
836 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
840 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
844 /*-----------------------------------------------------------------*/
845 /* genNot - generate code for ! operation */
846 /*-----------------------------------------------------------------*/
847 static void genNot (iCode *ic)
849 link *optype = operandType(IC_LEFT(ic));
851 /* assign asmOps to operand & result */
852 aopOp (IC_LEFT(ic),ic,FALSE);
853 aopOp (IC_RESULT(ic),ic,TRUE);
855 /* if in bit space then a special case */
856 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
860 /* if type float then do float */
861 if (IS_FLOAT(optype)) {
865 toBoolean(IC_LEFT(ic));
870 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
871 emitcode("sub", "a,#0x01");
872 outBitC(IC_RESULT(ic));
874 /* release the aops */
875 freeAsmop(IC_LEFT(ic),NULL,ic);
876 freeAsmop(IC_RESULT(ic),NULL,ic);
879 /*-----------------------------------------------------------------*/
880 /* genCpl - generate code for complement */
881 /*-----------------------------------------------------------------*/
882 static void genCpl (iCode *ic)
888 /* assign asmOps to operand & result */
889 aopOp (IC_LEFT(ic),ic,FALSE);
890 aopOp (IC_RESULT(ic),ic,TRUE);
892 /* if both are in bit space then
894 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
895 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
899 size = AOP_SIZE(IC_RESULT(ic));
901 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
904 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
907 /* release the aops */
908 freeAsmop(IC_LEFT(ic),NULL,ic);
909 freeAsmop(IC_RESULT(ic),NULL,ic);
912 /*-----------------------------------------------------------------*/
913 /* genUminus - unary minus code generation */
914 /*-----------------------------------------------------------------*/
915 static void genUminus (iCode *ic)
918 link *optype, *rtype;
921 aopOp(IC_LEFT(ic),ic,FALSE);
922 aopOp(IC_RESULT(ic),ic,TRUE);
924 /* if both in bit space then special
926 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
927 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
932 optype = operandType(IC_LEFT(ic));
933 rtype = operandType(IC_RESULT(ic));
935 /* if float then do float stuff */
936 if (IS_FLOAT(optype)) {
941 /* otherwise subtract from zero */
942 size = AOP_SIZE(IC_LEFT(ic));
946 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
947 emitcode("ld", "a,#0");
948 emitcode("sbc","a,%s",l);
949 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
952 /* if any remaining bytes in the result */
953 /* we just need to propagate the sign */
954 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
956 emitcode("sbc","a,a");
958 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
962 /* release the aops */
963 freeAsmop(IC_LEFT(ic),NULL,ic);
964 freeAsmop(IC_RESULT(ic),NULL,ic);
968 /*-----------------------------------------------------------------*/
969 /* assignResultValue - */
970 /*-----------------------------------------------------------------*/
971 void assignResultValue(operand * oper)
974 int size = AOP_SIZE(oper);
976 aopPut(AOP(oper),fReturn[offset],offset);
981 /*-----------------------------------------------------------------*/
982 /* genIpush - genrate code for pushing this gets a little complex */
983 /*-----------------------------------------------------------------*/
984 static void genIpush (iCode *ic)
986 int size, offset = 0 ;
990 /* if this is not a parm push : ie. it is spill push
991 and spill push is always done on the local stack */
993 /* and the item is spilt then do nothing */
994 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
997 aopOp(IC_LEFT(ic),ic,FALSE);
998 size = AOP_SIZE(IC_LEFT(ic));
999 /* push it on the stack */
1000 if (isPair(AOP(IC_LEFT(ic)))) {
1001 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1006 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1007 /* Simple for now - load into A and PUSH AF */
1008 emitcode("ld", "a,%s", l);
1009 emitcode("push", "af");
1010 emitcode("inc", "sp");
1016 /* Hmmm... what about saving the currently used registers
1019 /* then do the push */
1020 aopOp(IC_LEFT(ic),ic,FALSE);
1022 size = AOP_SIZE(IC_LEFT(ic));
1024 if (isPair(AOP(IC_LEFT(ic)))) {
1025 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1029 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1031 emitcode("ld", "hl,%s", s);
1032 emitcode("push", "hl");
1038 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1039 emitcode("ld", "a,%s", l);
1040 emitcode("push", "af");
1041 emitcode("inc", "sp");
1045 freeAsmop(IC_LEFT(ic),NULL,ic);
1048 /*-----------------------------------------------------------------*/
1049 /* genIpop - recover the registers: can happen only for spilling */
1050 /*-----------------------------------------------------------------*/
1051 static void genIpop (iCode *ic)
1056 /* if the temp was not pushed then */
1057 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1060 aopOp(IC_LEFT(ic),ic,FALSE);
1061 size = AOP_SIZE(IC_LEFT(ic));
1063 if (isPair(AOP(IC_LEFT(ic)))) {
1064 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1068 emitcode("dec", "sp");
1069 emitcode("pop", "hl");
1070 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1074 freeAsmop(IC_LEFT(ic),NULL,ic);
1077 /** Emit the code for a call statement
1079 static void emitCall (iCode *ic, bool ispcall)
1081 /* if caller saves & we have not saved then */
1082 if (!ic->regsSaved) {
1086 /* if send set is not empty then assign */
1090 for (sic = setFirstItem(sendSet) ; sic ;
1091 sic = setNextItem(sendSet)) {
1092 int size, offset = 0;
1093 aopOp(IC_LEFT(sic),sic,FALSE);
1094 size = AOP_SIZE(IC_LEFT(sic));
1096 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1098 if (strcmp(l,fReturn[offset]))
1099 emitcode("ld","%s,%s",
1104 freeAsmop (IC_LEFT(sic),NULL,sic);
1110 symbol *rlbl = newiTempLabel(NULL);
1112 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1113 emitcode("push", "hl");
1115 aopOp(IC_LEFT(ic),ic,FALSE);
1116 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1117 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1118 freeAsmop(IC_LEFT(ic),NULL,ic);
1120 emitcode("jp", "(hl)");
1121 emitcode("","%05d$:",(rlbl->key+100));
1125 emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1126 OP_SYMBOL(IC_LEFT(ic))->rname :
1127 OP_SYMBOL(IC_LEFT(ic))->name));
1130 /* if we need assign a result value */
1131 if ((IS_ITEMP(IC_RESULT(ic)) &&
1132 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1133 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1134 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1137 aopOp(IC_RESULT(ic),ic,FALSE);
1140 assignResultValue(IC_RESULT(ic));
1142 freeAsmop(IC_RESULT(ic),NULL, ic);
1145 /* PENDING: mega hack */
1147 char *s = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1148 OP_SYMBOL(IC_LEFT(ic))->rname :
1149 OP_SYMBOL(IC_LEFT(ic))->name;
1150 if (!strcmp(s, "__mulsint") ||
1151 !strcmp(s, "__divsint"))
1152 IC_LEFT(ic)->parmBytes = 4;
1154 /* adjust the stack for parameters if required */
1155 if (IC_LEFT(ic)->parmBytes) {
1156 int i = IC_LEFT(ic)->parmBytes;
1158 emitcode("ld", "hl,#%d", i);
1159 emitcode("add", "hl,sp");
1160 emitcode("ld", "sp,hl");
1164 emitcode("pop", "hl");
1168 emitcode("inc", "sp");
1174 /*-----------------------------------------------------------------*/
1175 /* genCall - generates a call statement */
1176 /*-----------------------------------------------------------------*/
1177 static void genCall (iCode *ic)
1179 emitCall(ic, FALSE);
1182 /*-----------------------------------------------------------------*/
1183 /* genPcall - generates a call by pointer statement */
1184 /*-----------------------------------------------------------------*/
1185 static void genPcall (iCode *ic)
1190 /*-----------------------------------------------------------------*/
1191 /* resultRemat - result is rematerializable */
1192 /*-----------------------------------------------------------------*/
1193 static int resultRemat (iCode *ic)
1195 if (SKIP_IC(ic) || ic->op == IFX)
1198 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1199 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1200 if (sym->remat && !POINTER_SET(ic))
1207 /*-----------------------------------------------------------------*/
1208 /* genFunction - generated code for function entry */
1209 /*-----------------------------------------------------------------*/
1210 static void genFunction (iCode *ic)
1216 /* create the function header */
1217 emitcode(";","-----------------------------------------");
1218 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1219 emitcode(";","-----------------------------------------");
1221 emitcode("","%s:",sym->rname);
1222 fetype = getSpec(operandType(IC_LEFT(ic)));
1224 /* if critical function then turn interrupts off */
1225 if (SPEC_CRTCL(fetype))
1228 /* if this is an interrupt service routine then
1229 save acc, b, dpl, dph */
1230 if (IS_ISR(sym->etype)) {
1231 emitcode("push", "af");
1232 emitcode("push", "bc");
1233 emitcode("push", "de");
1234 emitcode("push", "hl");
1236 /* PENDING: callee-save etc */
1238 /* adjust the stack for the function */
1239 emitcode("push", "de");
1240 emitcode("push", "bc");
1241 emitcode("push", "ix");
1242 emitcode("ld", "ix,#0");
1243 emitcode("add", "ix,sp");
1245 _lastStack = sym->stack;
1248 emitcode("ld", "hl,#-%d", sym->stack);
1249 emitcode("add", "hl,sp");
1250 emitcode("ld", "sp,hl");
1254 /*-----------------------------------------------------------------*/
1255 /* genEndFunction - generates epilogue for functions */
1256 /*-----------------------------------------------------------------*/
1257 static void genEndFunction (iCode *ic)
1259 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1261 if (IS_ISR(sym->etype)) {
1265 if (SPEC_CRTCL(sym->etype))
1268 /* PENDING: calleeSave */
1270 /* if debug then send end of function */
1271 if (options.debug && currFunc) {
1273 emitcode("","C$%s$%d$%d$%d ==.",
1274 ic->filename,currFunc->lastLine,
1275 ic->level,ic->block);
1276 if (IS_STATIC(currFunc->etype))
1277 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1279 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1282 emitcode("ld", "sp,ix");
1283 emitcode("pop", "ix");
1284 emitcode("pop", "bc");
1285 emitcode("pop", "de");
1286 emitcode("ret", "");
1291 /*-----------------------------------------------------------------*/
1292 /* genRet - generate code for return statement */
1293 /*-----------------------------------------------------------------*/
1294 static void genRet (iCode *ic)
1297 /* Errk. This is a hack until I can figure out how
1298 to cause dehl to spill on a call */
1299 int size,offset = 0;
1301 /* if we have no return value then
1302 just generate the "ret" */
1306 /* we have something to return then
1307 move the return value into place */
1308 aopOp(IC_LEFT(ic),ic,FALSE);
1309 size = AOP_SIZE(IC_LEFT(ic));
1311 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1312 emitcode("ld", "hl,%s", l);
1316 l = aopGet(AOP(IC_LEFT(ic)),offset,
1318 if (strcmp(fReturn[offset],l))
1319 emitcode("ld","%s,%s",fReturn[offset++],l);
1322 freeAsmop (IC_LEFT(ic),NULL,ic);
1325 /* generate a jump to the return label
1326 if the next is not the return statement */
1327 if (!(ic->next && ic->next->op == LABEL &&
1328 IC_LABEL(ic->next) == returnLabel))
1330 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1333 /*-----------------------------------------------------------------*/
1334 /* genLabel - generates a label */
1335 /*-----------------------------------------------------------------*/
1336 static void genLabel (iCode *ic)
1338 /* special case never generate */
1339 if (IC_LABEL(ic) == entryLabel)
1342 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1345 /*-----------------------------------------------------------------*/
1346 /* genGoto - generates a ljmp */
1347 /*-----------------------------------------------------------------*/
1348 static void genGoto (iCode *ic)
1350 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1353 /*-----------------------------------------------------------------*/
1354 /* genPlusIncr :- does addition with increment if possible */
1355 /*-----------------------------------------------------------------*/
1356 static bool genPlusIncr (iCode *ic)
1358 unsigned int icount ;
1359 unsigned int size = getDataSize(IC_RESULT(ic));
1361 /* will try to generate an increment */
1362 /* if the right side is not a literal
1364 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1367 /* if the literal value of the right hand side
1368 is greater than 4 then it is not worth it */
1369 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
1373 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1374 isPair(AOP(IC_RESULT(ic)))) {
1376 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1380 /* if increment 16 bits in register */
1381 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1384 symbol *tlbl = newiTempLabel(NULL);
1385 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1386 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1388 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1392 emitcode("", LABEL_STR ":",tlbl->key+100);
1396 /* If result is a pair */
1397 if (isPair(AOP(IC_RESULT(ic)))) {
1398 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1399 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1401 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1405 /* if the sizes are greater than 1 then we cannot */
1406 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1407 AOP_SIZE(IC_LEFT(ic)) > 1 )
1410 /* we can if the aops of the left & result match or
1411 if they are in registers and the registers are the
1413 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1415 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1423 /*-----------------------------------------------------------------*/
1424 /* outBitAcc - output a bit in acc */
1425 /*-----------------------------------------------------------------*/
1426 void outBitAcc(operand *result)
1428 symbol *tlbl = newiTempLabel(NULL);
1429 /* if the result is a bit */
1430 if (AOP_TYPE(result) == AOP_CRY){
1434 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1435 emitcode("ld","a,%s",one);
1436 emitcode("", LABEL_STR ":",tlbl->key+100);
1441 /*-----------------------------------------------------------------*/
1442 /* genPlus - generates code for addition */
1443 /*-----------------------------------------------------------------*/
1444 static void genPlus (iCode *ic)
1446 int size, offset = 0;
1448 /* special cases :- */
1450 aopOp (IC_LEFT(ic),ic,FALSE);
1451 aopOp (IC_RIGHT(ic),ic,FALSE);
1452 aopOp (IC_RESULT(ic),ic,TRUE);
1454 /* Swap the left and right operands if:
1456 if literal, literal on the right or
1457 if left requires ACC or right is already
1460 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1461 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1462 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1463 operand *t = IC_RIGHT(ic);
1464 IC_RIGHT(ic) = IC_LEFT(ic);
1468 /* if both left & right are in bit
1470 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1471 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1476 /* if left in bit space & right literal */
1477 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1478 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1479 /* Can happen I guess */
1483 /* if I can do an increment instead
1484 of add then GOOD for ME */
1485 if (genPlusIncr (ic) == TRUE)
1488 size = getDataSize(IC_RESULT(ic));
1491 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1492 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1494 emitcode("add","a,%s",
1495 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1497 emitcode("adc","a,%s",
1498 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1500 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1502 emitcode("add","a,%s",
1503 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1505 emitcode("adc","a,%s",
1506 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1508 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1511 /* Some kind of pointer arith. */
1512 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1513 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1514 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1517 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1518 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1519 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1524 freeAsmop(IC_LEFT(ic),NULL,ic);
1525 freeAsmop(IC_RIGHT(ic),NULL,ic);
1526 freeAsmop(IC_RESULT(ic),NULL,ic);
1530 /*-----------------------------------------------------------------*/
1531 /* genMinusDec :- does subtraction with deccrement if possible */
1532 /*-----------------------------------------------------------------*/
1533 static bool genMinusDec (iCode *ic)
1535 unsigned int icount ;
1536 unsigned int size = getDataSize(IC_RESULT(ic));
1538 /* will try to generate an increment */
1539 /* if the right side is not a literal we cannot */
1540 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1543 /* if the literal value of the right hand side
1544 is greater than 4 then it is not worth it */
1545 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1548 size = getDataSize(IC_RESULT(ic));
1549 /* if decrement 16 bits in register */
1550 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1551 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1553 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1557 /* If result is a pair */
1558 if (isPair(AOP(IC_RESULT(ic)))) {
1559 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1560 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1562 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1566 /* if the sizes are greater than 1 then we cannot */
1567 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1568 AOP_SIZE(IC_LEFT(ic)) > 1 )
1571 /* we can if the aops of the left & result match or if they are in
1572 registers and the registers are the same */
1573 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1575 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1582 /*-----------------------------------------------------------------*/
1583 /* genMinus - generates code for subtraction */
1584 /*-----------------------------------------------------------------*/
1585 static void genMinus (iCode *ic)
1587 int size, offset = 0;
1588 unsigned long lit = 0L;
1590 aopOp (IC_LEFT(ic),ic,FALSE);
1591 aopOp (IC_RIGHT(ic),ic,FALSE);
1592 aopOp (IC_RESULT(ic),ic,TRUE);
1594 /* special cases :- */
1595 /* if both left & right are in bit space */
1596 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1597 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1602 /* if I can do an decrement instead of subtract then GOOD for ME */
1603 if (genMinusDec (ic) == TRUE)
1606 size = getDataSize(IC_RESULT(ic));
1608 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1612 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1617 /* if literal, add a,#-lit, else normal subb */
1619 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1620 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1621 emitcode("sbc","a,%s",
1622 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1624 /* first add without previous c */
1626 emitcode("add","a,#0x%02x",
1627 (unsigned int)(lit & 0x0FFL));
1629 emitcode("adc","a,#0x%02x",
1630 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1632 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1635 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1636 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1637 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1641 freeAsmop(IC_LEFT(ic),NULL,ic);
1642 freeAsmop(IC_RIGHT(ic),NULL,ic);
1643 freeAsmop(IC_RESULT(ic),NULL,ic);
1646 /*-----------------------------------------------------------------*/
1647 /* genMult - generates code for multiplication */
1648 /*-----------------------------------------------------------------*/
1649 static void genMult (iCode *ic)
1651 /* Shouldn't occur - all done through function calls */
1655 /*-----------------------------------------------------------------*/
1656 /* genDiv - generates code for division */
1657 /*-----------------------------------------------------------------*/
1658 static void genDiv (iCode *ic)
1660 /* Shouldn't occur - all done through function calls */
1664 /*-----------------------------------------------------------------*/
1665 /* genMod - generates code for division */
1666 /*-----------------------------------------------------------------*/
1667 static void genMod (iCode *ic)
1669 /* Shouldn't occur - all done through function calls */
1673 /*-----------------------------------------------------------------*/
1674 /* genIfxJump :- will create a jump depending on the ifx */
1675 /*-----------------------------------------------------------------*/
1676 static void genIfxJump (iCode *ic, char *jval)
1681 /* if true label then we jump if condition
1683 if ( IC_TRUE(ic) ) {
1685 if (!strcmp(jval, "a")) {
1688 else if (!strcmp(jval, "c")) {
1692 /* The buffer contains the bit on A that we should test */
1697 /* false label is present */
1698 jlbl = IC_FALSE(ic) ;
1699 if (!strcmp(jval, "a")) {
1702 else if (!strcmp(jval, "c")) {
1706 /* The buffer contains the bit on A that we should test */
1710 /* Z80 can do a conditional long jump */
1711 if (!strcmp(jval, "a")) {
1712 emitcode("or", "a,a");
1714 else if (!strcmp(jval, "c")) {
1717 emitcode("bit", "%s,a", jval);
1719 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1721 /* mark the icode as generated */
1725 /** Generic compare for > or <
1727 static void genCmp (operand *left,operand *right,
1728 operand *result, iCode *ifx, int sign)
1730 int size, offset = 0 ;
1731 unsigned long lit = 0L;
1733 /* if left & right are bit variables */
1734 if (AOP_TYPE(left) == AOP_CRY &&
1735 AOP_TYPE(right) == AOP_CRY ) {
1736 /* Cant happen on the Z80 */
1739 /* subtract right from left if at the
1740 end the carry flag is set then we know that
1741 left is greater than right */
1742 size = max(AOP_SIZE(left),AOP_SIZE(right));
1744 /* if unsigned char cmp with lit, just compare */
1745 if((size == 1) && !sign &&
1746 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1747 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1748 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1751 if(AOP_TYPE(right) == AOP_LIT) {
1752 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1753 /* optimize if(x < 0) or if(x >= 0) */
1756 /* No sign so it's always false */
1760 /* Just load in the top most bit */
1761 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1762 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1763 genIfxJump (ifx,"7");
1767 emitcode("rlc","a");
1774 /* Do a long subtract */
1775 MOVA(aopGet(AOP(left),offset,FALSE));
1776 if (sign && size == 0) {
1778 emitcode("push", "af");
1779 emitcode("xor", "a,#0x80");
1780 emitcode("ld", "l,a");
1781 emitcode("pop", "af");
1782 emitcode("ld", "a,l");
1783 if (AOP_TYPE(right) == AOP_LIT){
1784 unsigned long lit = (unsigned long)
1785 floatFromVal(AOP(right)->aopu.aop_lit);
1786 emitcode("sbc","a,#0x%02x",
1787 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1789 emitcode("push", "af");
1790 emitcode("ld", "a,%s",aopGet(AOP(right),offset++,FALSE));
1791 emitcode("xor", "a,#0x80");
1792 emitcode("ld", "l,a");
1793 emitcode("pop", "af");
1794 emitcode("sbc", "a,l");
1798 /* Subtract through, propagating the carry */
1799 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1806 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1809 /* if the result is used in the next
1810 ifx conditional branch then generate
1811 code a little differently */
1813 genIfxJump (ifx,"c");
1816 /* leave the result in acc */
1820 /*-----------------------------------------------------------------*/
1821 /* genCmpGt :- greater than comparison */
1822 /*-----------------------------------------------------------------*/
1823 static void genCmpGt (iCode *ic, iCode *ifx)
1825 operand *left, *right, *result;
1826 link *letype , *retype;
1830 right= IC_RIGHT(ic);
1831 result = IC_RESULT(ic);
1833 letype = getSpec(operandType(left));
1834 retype =getSpec(operandType(right));
1835 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1836 /* assign the amsops */
1837 aopOp (left,ic,FALSE);
1838 aopOp (right,ic,FALSE);
1839 aopOp (result,ic,TRUE);
1841 genCmp(right, left, result, ifx, sign);
1843 freeAsmop(left,NULL,ic);
1844 freeAsmop(right,NULL,ic);
1845 freeAsmop(result,NULL,ic);
1848 /*-----------------------------------------------------------------*/
1849 /* genCmpLt - less than comparisons */
1850 /*-----------------------------------------------------------------*/
1851 static void genCmpLt (iCode *ic, iCode *ifx)
1853 operand *left, *right, *result;
1854 link *letype , *retype;
1858 right= IC_RIGHT(ic);
1859 result = IC_RESULT(ic);
1861 letype = getSpec(operandType(left));
1862 retype =getSpec(operandType(right));
1863 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1865 /* assign the amsops */
1866 aopOp (left,ic,FALSE);
1867 aopOp (right,ic,FALSE);
1868 aopOp (result,ic,TRUE);
1870 genCmp(left, right, result, ifx, sign);
1872 freeAsmop(left,NULL,ic);
1873 freeAsmop(right,NULL,ic);
1874 freeAsmop(result,NULL,ic);
1877 /*-----------------------------------------------------------------*/
1878 /* gencjneshort - compare and jump if not equal */
1879 /*-----------------------------------------------------------------*/
1880 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1882 int size = max(AOP_SIZE(left),AOP_SIZE(right));
1884 unsigned long lit = 0L;
1886 /* Swap the left and right if it makes the computation easier */
1887 if (AOP_TYPE(left) == AOP_LIT) {
1893 if(AOP_TYPE(right) == AOP_LIT)
1894 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1896 /* if the right side is a literal then anything goes */
1897 if (AOP_TYPE(right) == AOP_LIT &&
1898 AOP_TYPE(left) != AOP_DIR ) {
1900 emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1901 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1902 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1906 /* if the right side is in a register or in direct space or
1907 if the left is a pointer register & right is not */
1908 else if (AOP_TYPE(right) == AOP_REG ||
1909 AOP_TYPE(right) == AOP_DIR ||
1910 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1912 MOVA(aopGet(AOP(left),offset,FALSE));
1913 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1914 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1916 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1918 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1919 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1924 /* right is a pointer reg need both a & b */
1925 /* PENDING: is this required? */
1927 char *l = aopGet(AOP(left),offset,FALSE);
1928 MOVA(aopGet(AOP(right),offset,FALSE));
1929 emitcode("cp", "%s", l);
1930 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
1936 /*-----------------------------------------------------------------*/
1937 /* gencjne - compare and jump if not equal */
1938 /*-----------------------------------------------------------------*/
1939 static void gencjne(operand *left, operand *right, symbol *lbl)
1941 symbol *tlbl = newiTempLabel(NULL);
1943 gencjneshort(left, right, lbl);
1946 emitcode("ld","a,%s",one);
1947 emitcode("jp", LABEL_STR ,tlbl->key+100);
1948 emitcode("", LABEL_STR ":",lbl->key+100);
1949 emitcode("xor","a,a");
1950 emitcode("", LABEL_STR ":",tlbl->key+100);
1953 /*-----------------------------------------------------------------*/
1954 /* genCmpEq - generates code for equal to */
1955 /*-----------------------------------------------------------------*/
1956 static void genCmpEq (iCode *ic, iCode *ifx)
1958 operand *left, *right, *result;
1960 aopOp((left=IC_LEFT(ic)),ic,FALSE);
1961 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1962 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1964 /* Swap operands if it makes the operation easier. ie if:
1965 1. Left is a literal.
1967 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1968 operand *t = IC_RIGHT(ic);
1969 IC_RIGHT(ic) = IC_LEFT(ic);
1973 if (ifx && !AOP_SIZE(result)){
1975 /* if they are both bit variables */
1976 if (AOP_TYPE(left) == AOP_CRY &&
1977 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1980 tlbl = newiTempLabel(NULL);
1981 gencjneshort(left, right, tlbl);
1982 if ( IC_TRUE(ifx) ) {
1983 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
1984 emitcode("", LABEL_STR ":",tlbl->key+100);
1986 /* PENDING: do this better */
1987 symbol *lbl = newiTempLabel(NULL);
1988 emitcode("jp", LABEL_STR ,lbl->key+100);
1989 emitcode("", LABEL_STR ":",tlbl->key+100);
1990 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
1991 emitcode("", LABEL_STR ":",lbl->key+100);
1994 /* mark the icode as generated */
1999 /* if they are both bit variables */
2000 if (AOP_TYPE(left) == AOP_CRY &&
2001 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2004 gencjne(left,right,newiTempLabel(NULL));
2005 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2009 genIfxJump(ifx,"a");
2012 /* if the result is used in an arithmetic operation
2013 then put the result in place */
2014 if (AOP_TYPE(result) != AOP_CRY) {
2017 /* leave the result in acc */
2021 freeAsmop(left,NULL,ic);
2022 freeAsmop(right,NULL,ic);
2023 freeAsmop(result,NULL,ic);
2026 /*-----------------------------------------------------------------*/
2027 /* ifxForOp - returns the icode containing the ifx for operand */
2028 /*-----------------------------------------------------------------*/
2029 static iCode *ifxForOp ( operand *op, iCode *ic )
2031 /* if true symbol then needs to be assigned */
2032 if (IS_TRUE_SYMOP(op))
2035 /* if this has register type condition and
2036 the next instruction is ifx with the same operand
2037 and live to of the operand is upto the ifx only then */
2039 ic->next->op == IFX &&
2040 IC_COND(ic->next)->key == op->key &&
2041 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2047 /*-----------------------------------------------------------------*/
2048 /* genAndOp - for && operation */
2049 /*-----------------------------------------------------------------*/
2050 static void genAndOp (iCode *ic)
2052 operand *left,*right, *result;
2055 /* note here that && operations that are in an if statement are
2056 taken away by backPatchLabels only those used in arthmetic
2057 operations remain */
2058 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2059 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2060 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2062 /* if both are bit variables */
2063 if (AOP_TYPE(left) == AOP_CRY &&
2064 AOP_TYPE(right) == AOP_CRY ) {
2067 tlbl = newiTempLabel(NULL);
2069 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2071 emitcode("", LABEL_STR ":",tlbl->key+100);
2075 freeAsmop(left,NULL,ic);
2076 freeAsmop(right,NULL,ic);
2077 freeAsmop(result,NULL,ic);
2080 /*-----------------------------------------------------------------*/
2081 /* genOrOp - for || operation */
2082 /*-----------------------------------------------------------------*/
2083 static void genOrOp (iCode *ic)
2085 operand *left,*right, *result;
2088 /* note here that || operations that are in an
2089 if statement are taken away by backPatchLabels
2090 only those used in arthmetic operations remain */
2091 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2092 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2093 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2095 /* if both are bit variables */
2096 if (AOP_TYPE(left) == AOP_CRY &&
2097 AOP_TYPE(right) == AOP_CRY ) {
2100 tlbl = newiTempLabel(NULL);
2102 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2104 emitcode("", LABEL_STR,tlbl->key+100);
2108 freeAsmop(left,NULL,ic);
2109 freeAsmop(right,NULL,ic);
2110 freeAsmop(result,NULL,ic);
2113 /*-----------------------------------------------------------------*/
2114 /* isLiteralBit - test if lit == 2^n */
2115 /*-----------------------------------------------------------------*/
2116 int isLiteralBit(unsigned long lit)
2118 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2119 0x100L,0x200L,0x400L,0x800L,
2120 0x1000L,0x2000L,0x4000L,0x8000L,
2121 0x10000L,0x20000L,0x40000L,0x80000L,
2122 0x100000L,0x200000L,0x400000L,0x800000L,
2123 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2124 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2127 for(idx = 0; idx < 32; idx++)
2133 /*-----------------------------------------------------------------*/
2134 /* genAnd - code for and */
2135 /*-----------------------------------------------------------------*/
2136 static void genAnd (iCode *ic, iCode *ifx)
2138 operand *left, *right, *result;
2140 unsigned long lit = 0L;
2143 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2144 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2145 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2148 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2150 AOP_TYPE(left), AOP_TYPE(right));
2151 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2153 AOP_SIZE(left), AOP_SIZE(right));
2156 /* if left is a literal & right is not then exchange them */
2157 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2158 AOP_NEEDSACC(left)) {
2159 operand *tmp = right ;
2164 /* if result = right then exchange them */
2165 if(sameRegs(AOP(result),AOP(right))){
2166 operand *tmp = right ;
2171 /* if right is bit then exchange them */
2172 if (AOP_TYPE(right) == AOP_CRY &&
2173 AOP_TYPE(left) != AOP_CRY){
2174 operand *tmp = right ;
2178 if(AOP_TYPE(right) == AOP_LIT)
2179 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2181 size = AOP_SIZE(result);
2183 if (AOP_TYPE(left) == AOP_CRY){
2188 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2189 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2190 if((AOP_TYPE(right) == AOP_LIT) &&
2191 (AOP_TYPE(result) == AOP_CRY) &&
2192 (AOP_TYPE(left) != AOP_CRY)) {
2193 int posbit = isLiteralBit(lit);
2197 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2201 emitcode("mov","c,acc.%d",posbit&0x07);
2206 sprintf(buffer, "%d", posbit&0x07);
2207 genIfxJump(ifx, buffer);
2215 symbol *tlbl = newiTempLabel(NULL);
2216 int sizel = AOP_SIZE(left);
2219 emitcode("setb","c");
2222 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2223 MOVA( aopGet(AOP(left),offset,FALSE));
2225 if((posbit = isLiteralBit(bytelit)) != 0) {
2227 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2230 if(bytelit != 0x0FFL)
2231 emitcode("and","a,%s",
2232 aopGet(AOP(right),offset,FALSE));
2233 emitcode("jr","nz, %05d$",tlbl->key+100);
2238 // bit = left & literal
2240 emitcode("clr","c");
2241 emitcode("","%05d$:",tlbl->key+100);
2243 // if(left & literal)
2247 jmpTrueOrFalse(ifx, tlbl);
2258 /* if left is same as result */
2259 if(sameRegs(AOP(result),AOP(left))){
2260 for(;size--; offset++) {
2261 if(AOP_TYPE(right) == AOP_LIT){
2262 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2266 aopPut(AOP(result),zero,offset);
2268 MOVA(aopGet(AOP(left),offset,FALSE));
2269 emitcode("and","a,%s",
2270 aopGet(AOP(right),offset,FALSE));
2271 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2276 if (AOP_TYPE(left) == AOP_ACC) {
2280 MOVA(aopGet(AOP(right),offset,FALSE));
2281 emitcode("and","%s,a",
2282 aopGet(AOP(left),offset,FALSE));
2287 // left & result in different registers
2288 if(AOP_TYPE(result) == AOP_CRY){
2291 for(;(size--);offset++) {
2293 // result = left & right
2294 if(AOP_TYPE(right) == AOP_LIT){
2295 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2297 aopGet(AOP(left),offset,FALSE),
2300 } else if(bytelit == 0){
2301 aopPut(AOP(result),zero,offset);
2305 // faster than result <- left, anl result,right
2306 // and better if result is SFR
2307 if (AOP_TYPE(left) == AOP_ACC)
2308 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2310 MOVA(aopGet(AOP(right),offset,FALSE));
2311 emitcode("and","a,%s",
2312 aopGet(AOP(left),offset,FALSE));
2314 aopPut(AOP(result),"a",offset);
2321 freeAsmop(left,NULL,ic);
2322 freeAsmop(right,NULL,ic);
2323 freeAsmop(result,NULL,ic);
2326 /*-----------------------------------------------------------------*/
2327 /* genOr - code for or */
2328 /*-----------------------------------------------------------------*/
2329 static void genOr (iCode *ic, iCode *ifx)
2331 operand *left, *right, *result;
2333 unsigned long lit = 0L;
2335 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2336 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2337 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2340 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2342 AOP_TYPE(left), AOP_TYPE(right));
2343 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2345 AOP_SIZE(left), AOP_SIZE(right));
2348 /* if left is a literal & right is not then exchange them */
2349 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2350 AOP_NEEDSACC(left)) {
2351 operand *tmp = right ;
2356 /* if result = right then exchange them */
2357 if(sameRegs(AOP(result),AOP(right))){
2358 operand *tmp = right ;
2363 /* if right is bit then exchange them */
2364 if (AOP_TYPE(right) == AOP_CRY &&
2365 AOP_TYPE(left) != AOP_CRY){
2366 operand *tmp = right ;
2370 if(AOP_TYPE(right) == AOP_LIT)
2371 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2373 size = AOP_SIZE(result);
2375 if (AOP_TYPE(left) == AOP_CRY){
2380 if((AOP_TYPE(right) == AOP_LIT) &&
2381 (AOP_TYPE(result) == AOP_CRY) &&
2382 (AOP_TYPE(left) != AOP_CRY)){
2387 /* if left is same as result */
2388 if(sameRegs(AOP(result),AOP(left))){
2389 for(;size--; offset++) {
2390 if(AOP_TYPE(right) == AOP_LIT){
2391 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2394 emitcode("or","%s,%s; 5",
2395 aopGet(AOP(left),offset,FALSE),
2396 aopGet(AOP(right),offset,FALSE));
2398 if (AOP_TYPE(left) == AOP_ACC)
2399 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2401 MOVA(aopGet(AOP(right),offset,FALSE));
2402 emitcode("or","a,%s ; 7",
2403 aopGet(AOP(left),offset,FALSE));
2404 aopPut(AOP(result),"a ; 8",0);
2409 // left & result in different registers
2410 if(AOP_TYPE(result) == AOP_CRY){
2412 } else for(;(size--);offset++){
2414 // result = left & right
2415 if(AOP_TYPE(right) == AOP_LIT){
2416 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2418 aopGet(AOP(left),offset,FALSE),
2423 // faster than result <- left, anl result,right
2424 // and better if result is SFR
2425 if (AOP_TYPE(left) == AOP_ACC)
2426 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2428 MOVA(aopGet(AOP(right),offset,FALSE));
2429 emitcode("or","a,%s",
2430 aopGet(AOP(left),offset,FALSE));
2432 aopPut(AOP(result),"a",offset);
2433 /* PENDING: something weird is going on here. Add exception. */
2434 if (AOP_TYPE(result) == AOP_ACC)
2440 freeAsmop(left,NULL,ic);
2441 freeAsmop(right,NULL,ic);
2442 freeAsmop(result,NULL,ic);
2445 /*-----------------------------------------------------------------*/
2446 /* genXor - code for xclusive or */
2447 /*-----------------------------------------------------------------*/
2448 static void genXor (iCode *ic, iCode *ifx)
2450 operand *left, *right, *result;
2452 unsigned long lit = 0L;
2454 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2455 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2456 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2458 /* if left is a literal & right is not then exchange them */
2459 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2460 AOP_NEEDSACC(left)) {
2461 operand *tmp = right ;
2466 /* if result = right then exchange them */
2467 if(sameRegs(AOP(result),AOP(right))){
2468 operand *tmp = right ;
2473 /* if right is bit then exchange them */
2474 if (AOP_TYPE(right) == AOP_CRY &&
2475 AOP_TYPE(left) != AOP_CRY){
2476 operand *tmp = right ;
2480 if(AOP_TYPE(right) == AOP_LIT)
2481 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2483 size = AOP_SIZE(result);
2485 if (AOP_TYPE(left) == AOP_CRY){
2490 if((AOP_TYPE(right) == AOP_LIT) &&
2491 (AOP_TYPE(result) == AOP_CRY) &&
2492 (AOP_TYPE(left) != AOP_CRY)){
2497 /* if left is same as result */
2498 if(sameRegs(AOP(result),AOP(left))){
2499 for(;size--; offset++) {
2500 if(AOP_TYPE(right) == AOP_LIT){
2501 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2504 MOVA(aopGet(AOP(right),offset,FALSE));
2505 emitcode("xor","a,%s",
2506 aopGet(AOP(left),offset,FALSE));
2507 aopPut(AOP(result),"a",0);
2510 if (AOP_TYPE(left) == AOP_ACC)
2511 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2513 MOVA(aopGet(AOP(right),offset,FALSE));
2514 emitcode("xor","a,%s",
2515 aopGet(AOP(left),offset,FALSE));
2516 aopPut(AOP(result),"a",0);
2521 // left & result in different registers
2522 if(AOP_TYPE(result) == AOP_CRY){
2524 } else for(;(size--);offset++){
2526 // result = left & right
2527 if(AOP_TYPE(right) == AOP_LIT){
2528 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2530 aopGet(AOP(left),offset,FALSE),
2535 // faster than result <- left, anl result,right
2536 // and better if result is SFR
2537 if (AOP_TYPE(left) == AOP_ACC)
2538 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2540 MOVA(aopGet(AOP(right),offset,FALSE));
2541 emitcode("xor","a,%s",
2542 aopGet(AOP(left),offset,FALSE));
2543 aopPut(AOP(result),"a",0);
2545 aopPut(AOP(result),"a",offset);
2550 freeAsmop(left,NULL,ic);
2551 freeAsmop(right,NULL,ic);
2552 freeAsmop(result,NULL,ic);
2555 /*-----------------------------------------------------------------*/
2556 /* genInline - write the inline code out */
2557 /*-----------------------------------------------------------------*/
2558 static void genInline (iCode *ic)
2560 char buffer[MAX_INLINEASM];
2564 inLine += (!options.asmpeep);
2565 strcpy(buffer,IC_INLINE(ic));
2567 /* emit each line as a code */
2586 /* emitcode("",buffer); */
2587 inLine -= (!options.asmpeep);
2590 /*-----------------------------------------------------------------*/
2591 /* genRRC - rotate right with carry */
2592 /*-----------------------------------------------------------------*/
2593 static void genRRC (iCode *ic)
2598 /*-----------------------------------------------------------------*/
2599 /* genRLC - generate code for rotate left with carry */
2600 /*-----------------------------------------------------------------*/
2601 static void genRLC (iCode *ic)
2606 /*-----------------------------------------------------------------*/
2607 /* shiftR2Left2Result - shift right two bytes from left to result */
2608 /*-----------------------------------------------------------------*/
2609 static void shiftR2Left2Result (operand *left, int offl,
2610 operand *result, int offr,
2611 int shCount, int sign)
2613 if(sameRegs(AOP(result), AOP(left)) &&
2614 ((offl + MSB16) == offr)){
2617 movLeft2Result(left, offl, result, offr, 0);
2618 movLeft2Result(left, offl+1, result, offr+1, 0);
2625 /* if (AOP(result)->type == AOP_REG) {*/
2628 symbol *tlbl , *tlbl1;
2631 /* Left is already in result - so now do the shift */
2633 emitcode("ld","a,#%u+1", shCount);
2634 tlbl = newiTempLabel(NULL);
2635 tlbl1 = newiTempLabel(NULL);
2636 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2637 emitcode("", LABEL_STR ":",tlbl->key+100);
2640 emitcode("or", "a,a");
2643 l = aopGet(AOP(result), --offset, FALSE);
2644 emitcode("rr","%s", l);
2647 emitcode("", LABEL_STR ":",tlbl1->key+100);
2648 emitcode("dec", "a");
2649 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2654 /*-----------------------------------------------------------------*/
2655 /* shiftL2Left2Result - shift left two bytes from left to result */
2656 /*-----------------------------------------------------------------*/
2657 static void shiftL2Left2Result (operand *left, int offl,
2658 operand *result, int offr, int shCount)
2660 if(sameRegs(AOP(result), AOP(left)) &&
2661 ((offl + MSB16) == offr)){
2664 /* Copy left into result */
2665 movLeft2Result(left, offl, result, offr, 0);
2666 movLeft2Result(left, offl+1, result, offr+1, 0);
2668 /* PENDING: for now just see if it'll work. */
2669 /*if (AOP(result)->type == AOP_REG) { */
2673 symbol *tlbl , *tlbl1;
2676 /* Left is already in result - so now do the shift */
2678 emitcode("ld","a,#%u+1", shCount);
2679 tlbl = newiTempLabel(NULL);
2680 tlbl1 = newiTempLabel(NULL);
2681 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2682 emitcode("", LABEL_STR ":",tlbl->key+100);
2685 emitcode("or", "a,a");
2687 l = aopGet(AOP(result),offset++,FALSE);
2688 emitcode("rl","%s", l);
2691 emitcode("", LABEL_STR ":",tlbl1->key+100);
2692 emitcode("dec", "a");
2693 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2698 /*-----------------------------------------------------------------*/
2699 /* AccRol - rotate left accumulator by known count */
2700 /*-----------------------------------------------------------------*/
2701 static void AccRol (int shCount)
2703 shCount &= 0x0007; // shCount : 0..7
2740 /*-----------------------------------------------------------------*/
2741 /* AccLsh - left shift accumulator by known count */
2742 /*-----------------------------------------------------------------*/
2743 static void AccLsh (int shCount)
2747 emitcode("add","a,a");
2750 emitcode("add","a,a");
2751 emitcode("add","a,a");
2753 /* rotate left accumulator */
2755 /* and kill the lower order bits */
2756 emitcode("and","a,#0x%02x", SLMask[shCount]);
2761 /*-----------------------------------------------------------------*/
2762 /* shiftL1Left2Result - shift left one byte from left to result */
2763 /*-----------------------------------------------------------------*/
2764 static void shiftL1Left2Result (operand *left, int offl,
2765 operand *result, int offr, int shCount)
2768 l = aopGet(AOP(left),offl,FALSE);
2770 /* shift left accumulator */
2772 aopPut(AOP(result),"a",offr);
2776 /*-----------------------------------------------------------------*/
2777 /* genlshTwo - left shift two bytes by known amount != 0 */
2778 /*-----------------------------------------------------------------*/
2779 static void genlshTwo (operand *result,operand *left, int shCount)
2781 int size = AOP_SIZE(result);
2785 /* if shCount >= 8 */
2791 movLeft2Result(left, LSB, result, MSB16, 0);
2792 aopPut(AOP(result),zero, 0);
2793 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2796 movLeft2Result(left, LSB, result, MSB16, 0);
2797 aopPut(AOP(result),zero, 0);
2800 aopPut(AOP(result),zero,LSB);
2802 /* 1 <= shCount <= 7 */
2808 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2813 /*-----------------------------------------------------------------*/
2814 /* genlshOne - left shift a one byte quantity by known count */
2815 /*-----------------------------------------------------------------*/
2816 static void genlshOne (operand *result, operand *left, int shCount)
2818 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2821 /*-----------------------------------------------------------------*/
2822 /* genLeftShiftLiteral - left shifting by known count */
2823 /*-----------------------------------------------------------------*/
2824 static void genLeftShiftLiteral (operand *left,
2829 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2832 freeAsmop(right,NULL,ic);
2834 aopOp(left,ic,FALSE);
2835 aopOp(result,ic,FALSE);
2837 size = getSize(operandType(result));
2840 emitcode("; shift left ","result %d, left %d",size,
2844 /* I suppose that the left size >= result size */
2849 else if(shCount >= (size * 8))
2851 aopPut(AOP(result),zero,size);
2855 genlshOne (result,left,shCount);
2858 genlshTwo (result,left,shCount);
2867 freeAsmop(left,NULL,ic);
2868 freeAsmop(result,NULL,ic);
2871 /*-----------------------------------------------------------------*/
2872 /* genLeftShift - generates code for left shifting */
2873 /*-----------------------------------------------------------------*/
2874 static void genLeftShift (iCode *ic)
2878 symbol *tlbl , *tlbl1;
2879 operand *left,*right, *result;
2881 right = IC_RIGHT(ic);
2883 result = IC_RESULT(ic);
2885 aopOp(right,ic,FALSE);
2887 /* if the shift count is known then do it
2888 as efficiently as possible */
2889 if (AOP_TYPE(right) == AOP_LIT) {
2890 genLeftShiftLiteral (left,right,result,ic);
2894 /* shift count is unknown then we have to form a loop get the loop
2895 count in B : Note: we take only the lower order byte since
2896 shifting more that 32 bits make no sense anyway, ( the largest
2897 size of an object can be only 32 bits ) */
2898 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2899 emitcode("inc","a");
2900 freeAsmop (right,NULL,ic);
2901 aopOp(left,ic,FALSE);
2902 aopOp(result,ic,FALSE);
2904 /* now move the left to the result if they are not the
2907 if (!sameRegs(AOP(left),AOP(result))) {
2909 size = AOP_SIZE(result);
2912 l = aopGet(AOP(left),offset,FALSE);
2913 aopPut(AOP(result),l,offset);
2918 size = AOP_SIZE(result);
2921 l = aopGet(AOP(left),offset,FALSE);
2922 aopPut(AOP(result),l,offset);
2928 tlbl = newiTempLabel(NULL);
2929 size = AOP_SIZE(result);
2931 tlbl1 = newiTempLabel(NULL);
2933 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2934 emitcode("", LABEL_STR ":",tlbl->key+100);
2935 l = aopGet(AOP(result),offset,FALSE);
2936 emitcode("or", "a,a");
2938 l = aopGet(AOP(result),offset++,FALSE);
2939 emitcode("rl","%s", l);
2941 emitcode("", LABEL_STR ":",tlbl1->key+100);
2942 emitcode("dec", "a");
2943 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2945 freeAsmop(left,NULL,ic);
2946 freeAsmop(result,NULL,ic);
2949 /* genlshTwo - left shift two bytes by known amount != 0 */
2950 /*-----------------------------------------------------------------*/
2951 static void genrshOne (operand *result,operand *left, int shCount)
2954 int size = AOP_SIZE(result);
2960 l = aopGet(AOP(left),0,FALSE);
2961 if (AOP(result)->type == AOP_REG) {
2962 aopPut(AOP(result), l, 0);
2963 l = aopGet(AOP(result), 0, FALSE);
2965 emitcode("srl", "%s", l);
2970 emitcode("srl", "a");
2972 aopPut(AOP(result),"a",0);
2976 /*-----------------------------------------------------------------*/
2977 /* AccRsh - right shift accumulator by known count */
2978 /*-----------------------------------------------------------------*/
2979 static void AccRsh (int shCount)
2986 /* rotate right accumulator */
2987 AccRol(8 - shCount);
2988 /* and kill the higher order bits */
2989 emitcode("and","a,#0x%02x", SRMask[shCount]);
2994 /*-----------------------------------------------------------------*/
2995 /* shiftR1Left2Result - shift right one byte from left to result */
2996 /*-----------------------------------------------------------------*/
2997 static void shiftR1Left2Result (operand *left, int offl,
2998 operand *result, int offr,
2999 int shCount, int sign)
3001 MOVA(aopGet(AOP(left),offl,FALSE));
3008 aopPut(AOP(result),"a",offr);
3011 /*-----------------------------------------------------------------*/
3012 /* genrshTwo - right shift two bytes by known amount != 0 */
3013 /*-----------------------------------------------------------------*/
3014 static void genrshTwo (operand *result,operand *left,
3015 int shCount, int sign)
3017 /* if shCount >= 8 */
3022 shiftR1Left2Result(left, MSB16, result, LSB,
3026 movLeft2Result(left, MSB16, result, LSB, sign);
3027 aopPut(AOP(result),zero,1);
3030 /* 1 <= shCount <= 7 */
3032 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3036 /*-----------------------------------------------------------------*/
3037 /* genRightShiftLiteral - left shifting by known count */
3038 /*-----------------------------------------------------------------*/
3039 static void genRightShiftLiteral (operand *left,
3044 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3047 freeAsmop(right,NULL,ic);
3049 aopOp(left,ic,FALSE);
3050 aopOp(result,ic,FALSE);
3052 size = getSize(operandType(result));
3054 emitcode("; shift right ","result %d, left %d",size,
3057 /* I suppose that the left size >= result size */
3062 else if(shCount >= (size * 8))
3064 aopPut(AOP(result),zero,size);
3068 genrshOne(result, left, shCount);
3071 /* PENDING: sign support */
3072 genrshTwo(result, left, shCount, FALSE);
3081 freeAsmop(left,NULL,ic);
3082 freeAsmop(result,NULL,ic);
3085 /*-----------------------------------------------------------------*/
3086 /* genRightShift - generate code for right shifting */
3087 /*-----------------------------------------------------------------*/
3088 static void genRightShift (iCode *ic)
3090 operand *left,*right, *result;
3092 right = IC_RIGHT(ic);
3094 result = IC_RESULT(ic);
3096 aopOp(right,ic,FALSE);
3098 /* if the shift count is known then do it
3099 as efficiently as possible */
3100 if (AOP_TYPE(right) == AOP_LIT) {
3101 genRightShiftLiteral (left,right,result,ic);
3109 /*-----------------------------------------------------------------*/
3110 /* genGenPointerGet - gget value from generic pointer space */
3111 /*-----------------------------------------------------------------*/
3112 static void genGenPointerGet (operand *left,
3113 operand *result, iCode *ic)
3116 link *retype = getSpec(operandType(result));
3118 aopOp(left,ic,FALSE);
3119 aopOp(result,ic,FALSE);
3121 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3123 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3124 aopPut(AOP(result),"a", 0);
3125 freeAsmop(left,NULL,ic);
3129 /* For now we always load into IY */
3130 /* if this is remateriazable */
3131 if (AOP_TYPE(left) == AOP_IMMD)
3132 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3133 else { /* we need to get it byte by byte */
3134 emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3135 emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3137 /* so iy now contains the address */
3138 freeAsmop(left,NULL,ic);
3140 /* if bit then unpack */
3141 if (IS_BITVAR(retype)) {
3145 size = AOP_SIZE(result);
3149 /* PENDING: make this better */
3150 if (AOP(result)->type == AOP_REG) {
3151 aopPut(AOP(result),"(hl)",offset++);
3154 emitcode("ld", "a,(hl)", offset);
3155 aopPut(AOP(result),"a",offset++);
3158 emitcode("inc", "hl");
3164 freeAsmop(result,NULL,ic);
3167 /*-----------------------------------------------------------------*/
3168 /* genPointerGet - generate code for pointer get */
3169 /*-----------------------------------------------------------------*/
3170 static void genPointerGet (iCode *ic)
3172 operand *left, *result ;
3176 result = IC_RESULT(ic) ;
3178 /* depending on the type of pointer we need to
3179 move it to the correct pointer register */
3180 type = operandType(left);
3181 etype = getSpec(type);
3183 genGenPointerGet (left,result,ic);
3186 bool isRegOrLit(asmop *aop)
3188 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3193 /*-----------------------------------------------------------------*/
3194 /* genGenPointerSet - stores the value into a pointer location */
3195 /*-----------------------------------------------------------------*/
3196 static void genGenPointerSet (operand *right,
3197 operand *result, iCode *ic)
3200 link *retype = getSpec(operandType(right));
3202 aopOp(result,ic,FALSE);
3203 aopOp(right,ic,FALSE);
3205 /* Handle the exceptions first */
3206 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3208 char *l = aopGet(AOP(right), 0, FALSE);
3210 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3211 freeAsmop(result,NULL,ic);
3215 /* if the operand is already in dptr
3216 then we do nothing else we move the value to dptr */
3217 if (AOP_TYPE(result) != AOP_STR) {
3218 /* if this is remateriazable */
3219 if (AOP_TYPE(result) == AOP_IMMD) {
3220 emitcode("", "; Error 2");
3221 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3223 else { /* we need to get it byte by byte */
3224 /* PENDING: do this better */
3225 emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3226 emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3229 /* so hl know contains the address */
3230 freeAsmop(result,NULL,ic);
3232 /* if bit then unpack */
3233 if (IS_BITVAR(retype)) {
3237 size = AOP_SIZE(right);
3241 char *l = aopGet(AOP(right),offset,FALSE);
3243 if (isRegOrLit(AOP(right))) {
3244 emitcode("ld", "(hl),%s", l);
3248 emitcode("ld", "(hl),a", offset);
3251 emitcode("inc", "hl");
3257 freeAsmop(right,NULL,ic);
3260 /*-----------------------------------------------------------------*/
3261 /* genPointerSet - stores the value into a pointer location */
3262 /*-----------------------------------------------------------------*/
3263 static void genPointerSet (iCode *ic)
3265 operand *right, *result ;
3268 right = IC_RIGHT(ic);
3269 result = IC_RESULT(ic) ;
3271 /* depending on the type of pointer we need to
3272 move it to the correct pointer register */
3273 type = operandType(result);
3274 etype = getSpec(type);
3276 genGenPointerSet (right,result,ic);
3279 /*-----------------------------------------------------------------*/
3280 /* genIfx - generate code for Ifx statement */
3281 /*-----------------------------------------------------------------*/
3282 static void genIfx (iCode *ic, iCode *popIc)
3284 operand *cond = IC_COND(ic);
3287 aopOp(cond,ic,FALSE);
3289 /* get the value into acc */
3290 if (AOP_TYPE(cond) != AOP_CRY)
3294 /* the result is now in the accumulator */
3295 freeAsmop(cond,NULL,ic);
3297 /* if there was something to be popped then do it */
3301 /* if the condition is a bit variable */
3302 if (isbit && IS_ITEMP(cond) &&
3304 genIfxJump(ic,SPIL_LOC(cond)->rname);
3306 if (isbit && !IS_ITEMP(cond))
3307 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3314 /*-----------------------------------------------------------------*/
3315 /* genAddrOf - generates code for address of */
3316 /*-----------------------------------------------------------------*/
3317 static void genAddrOf (iCode *ic)
3319 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3321 aopOp(IC_RESULT(ic),ic,FALSE);
3323 /* if the operand is on the stack then we
3324 need to get the stack offset of this
3327 /* if it has an offset then we need to compute it */
3328 emitcode("push", "de");
3329 emitcode("push", "ix");
3330 emitcode("pop", "hl");
3331 emitcode("ld", "de,#%d", sym->stack);
3332 emitcode("add", "hl,de");
3333 emitcode("pop", "de");
3336 emitcode("ld", "hl,#%s", sym->rname);
3338 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3339 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3341 freeAsmop(IC_RESULT(ic),NULL,ic);
3344 /*-----------------------------------------------------------------*/
3345 /* genAssign - generate code for assignment */
3346 /*-----------------------------------------------------------------*/
3347 static void genAssign (iCode *ic)
3349 operand *result, *right;
3351 unsigned long lit = 0L;
3353 result = IC_RESULT(ic);
3354 right = IC_RIGHT(ic) ;
3357 /* Dont bother assigning if they are the same */
3358 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3359 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3364 aopOp(right,ic,FALSE);
3365 aopOp(result,ic,TRUE);
3367 /* if they are the same registers */
3368 if (sameRegs(AOP(right),AOP(result))) {
3369 emitcode("", "; (registers are the same)");
3373 /* if the result is a bit */
3374 if (AOP_TYPE(result) == AOP_CRY) {
3379 size = AOP_SIZE(result);
3382 if(AOP_TYPE(right) == AOP_LIT)
3383 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3385 (AOP_TYPE(result) != AOP_REG) &&
3386 (AOP_TYPE(right) == AOP_LIT) &&
3387 !IS_FLOAT(operandType(right)) &&
3389 emitcode("xor","a,a");
3390 /* Work from the top down.
3391 Done this way so that we can use the cached copy of 0
3392 in A for a fast clear */
3394 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
3395 aopPut(AOP(result),"a",size);
3398 aopGet(AOP(right),size,FALSE),
3404 aopGet(AOP(right),offset,FALSE),
3411 freeAsmop(right,NULL,ic);
3412 freeAsmop(result,NULL,ic);
3415 /*-----------------------------------------------------------------*/
3416 /* genJumpTab - genrates code for jump table */
3417 /*-----------------------------------------------------------------*/
3418 static void genJumpTab (iCode *ic)
3423 aopOp(IC_JTCOND(ic),ic,FALSE);
3424 /* get the condition into accumulator */
3425 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3427 emitcode("push", "de");
3428 emitcode("ld", "e,%s", l);
3429 emitcode("ld", "d,#0");
3430 jtab = newiTempLabel(NULL);
3431 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3432 emitcode("add", "hl,de");
3433 emitcode("add", "hl,de");
3434 freeAsmop(IC_JTCOND(ic),NULL,ic);
3435 emitcode("pop", "de");
3436 emitcode("jp", "(hl)");
3437 emitcode("","%05d$:",jtab->key+100);
3438 /* now generate the jump labels */
3439 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3440 jtab = setNextItem(IC_JTLABELS(ic)))
3441 emitcode("jp", LABEL_STR, jtab->key+100);
3444 /*-----------------------------------------------------------------*/
3445 /* genCast - gen code for casting */
3446 /*-----------------------------------------------------------------*/
3447 static void genCast (iCode *ic)
3449 operand *result = IC_RESULT(ic);
3450 link *ctype = operandType(IC_LEFT(ic));
3451 operand *right = IC_RIGHT(ic);
3454 /* if they are equivalent then do nothing */
3455 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3458 aopOp(right,ic,FALSE) ;
3459 aopOp(result,ic,FALSE);
3461 /* if the result is a bit */
3462 if (AOP_TYPE(result) == AOP_CRY) {
3466 /* if they are the same size : or less */
3467 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3469 /* if they are in the same place */
3470 if (sameRegs(AOP(right),AOP(result)))
3473 /* if they in different places then copy */
3474 size = AOP_SIZE(result);
3478 aopGet(AOP(right),offset,FALSE),
3485 /* if the result is of type pointer */
3486 if (IS_PTR(ctype)) {
3490 /* so we now know that the size of destination is greater
3491 than the size of the source */
3492 /* we move to result for the size of source */
3493 size = AOP_SIZE(right);
3497 aopGet(AOP(right),offset,FALSE),
3502 /* now depending on the sign of the destination */
3503 size = AOP_SIZE(result) - AOP_SIZE(right);
3504 /* Unsigned or not an integral type - right fill with zeros */
3505 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3507 aopPut(AOP(result),zero,offset++);
3509 /* we need to extend the sign :{ */
3510 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3513 emitcode("", "; genCast: sign extend untested.");
3514 emitcode("rla", "");
3515 emitcode("sbc", "a,a");
3517 aopPut(AOP(result),"a",offset++);
3521 freeAsmop(right, NULL, ic);
3522 freeAsmop(result, NULL, ic);
3525 /*-----------------------------------------------------------------*/
3526 /* genReceive - generate code for a receive iCode */
3527 /*-----------------------------------------------------------------*/
3528 static void genReceive (iCode *ic)
3530 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3531 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3532 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3536 aopOp(IC_RESULT(ic),ic,FALSE);
3538 assignResultValue(IC_RESULT(ic));
3541 freeAsmop(IC_RESULT(ic),NULL,ic);
3544 /*-----------------------------------------------------------------*/
3545 /* genZ80Code - generate code for Z80 based controllers */
3546 /*-----------------------------------------------------------------*/
3547 void genZ80Code (iCode *lic)
3552 lineHead = lineCurr = NULL;
3554 /* if debug information required */
3555 if (options.debug && currFunc) {
3556 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3558 if (IS_STATIC(currFunc->etype))
3559 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3561 emitcode("","G$%s$0$0 ==.",currFunc->name);
3564 /* stack pointer name */
3568 for (ic = lic ; ic ; ic = ic->next ) {
3570 if ( cln != ic->lineno ) {
3571 if ( options.debug ) {
3573 emitcode("","C$%s$%d$%d$%d ==.",
3574 ic->filename,ic->lineno,
3575 ic->level,ic->block);
3578 emitcode(";","%s %d",ic->filename,ic->lineno);
3581 /* if the result is marked as
3582 spilt and rematerializable or code for
3583 this has already been generated then
3585 if (resultRemat(ic) || ic->generated )
3588 /* depending on the operation */
3591 emitcode("", "; genNot");
3596 emitcode("", "; genCpl");
3601 emitcode("", "; genUminus");
3606 emitcode("", "; genIpush");
3611 /* IPOP happens only when trying to restore a
3612 spilt live range, if there is an ifx statement
3613 following this pop then the if statement might
3614 be using some of the registers being popped which
3615 would destory the contents of the register so
3616 we need to check for this condition and handle it */
3618 ic->next->op == IFX &&
3619 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3620 emitcode("", "; genIfx");
3621 genIfx (ic->next,ic);
3624 emitcode("", "; genIpop");
3630 emitcode("", "; genCall");
3635 emitcode("", "; genPcall");
3640 emitcode("", "; genFunction");
3645 emitcode("", "; genEndFunction");
3646 genEndFunction (ic);
3650 emitcode("", "; genRet");
3655 emitcode("", "; genLabel");
3660 emitcode("", "; genGoto");
3665 emitcode("", "; genPlus");
3670 emitcode("", "; genMinus");
3675 emitcode("", "; genMult");
3680 emitcode("", "; genDiv");
3685 emitcode("", "; genMod");
3690 emitcode("", "; genCmpGt");
3691 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3695 emitcode("", "; genCmpLt");
3696 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3703 /* note these two are xlated by algebraic equivalence
3704 during parsing SDCC.y */
3705 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3706 "got '>=' or '<=' shouldn't have come here");
3710 emitcode("", "; genCmpEq");
3711 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3715 emitcode("", "; genAndOp");
3720 emitcode("", "; genOrOp");
3725 emitcode("", "; genXor");
3726 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3730 emitcode("", "; genOr");
3731 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3735 emitcode("", "; genAnd");
3736 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3740 emitcode("", "; genInline");
3745 emitcode("", "; genRRC");
3750 emitcode("", "; genRLC");
3755 emitcode("", "; genHBIT");
3759 emitcode("", "; genLeftShift");
3764 emitcode("", "; genRightShift");
3768 case GET_VALUE_AT_ADDRESS:
3769 emitcode("", "; genPointerGet");
3775 if (POINTER_SET(ic)) {
3776 emitcode("", "; genAssign (pointer)");
3780 emitcode("", "; genAssign");
3786 emitcode("", "; genIfx");
3791 emitcode("", "; genAddrOf");
3796 emitcode("", "; genJumpTab");
3801 emitcode("", "; genCast");
3806 emitcode("", "; genReceive");
3811 emitcode("", "; addSet");
3812 addSet(&sendSet,ic);
3817 /* piCode(ic,stdout); */
3823 /* now we are ready to call the
3824 peep hole optimizer */
3825 /* if (!options.nopeep)
3826 peepHole (&lineHead); */
3828 /* now do the actual printing */
3829 printLine (lineHead,codeOutFile);