1 /*-------------------------------------------------------------------------
2 gen.c - Z80 specific code generator.
4 Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
6 Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
7 Improved WORD push 22784 144 19AE
8 With label1 on 22694 144 197E
9 With label2 on 22743 144 198A
10 With label3 on 22776 144 1999
11 With label4 on 22776 144 1999
12 With all 'label' on 22661 144 196F
13 With loopInvariant on 20919 156 19AB
14 With loopInduction on Breaks 198B
15 With all working on 20796 158 196C
16 Slightly better genCmp(signed) 20597 159 195B
17 Better reg packing, first peephole 20038 163 1873
18 With assign packing 19281 165 1849
20 Michael Hope <michaelh@earthling.net> 2000
21 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
22 and - Jean-Louis VERN.jlvern@writeme.com (1999)
24 This program is free software; you can redistribute it and/or modify it
25 under the terms of the GNU General Public License as published by the
26 Free Software Foundation; either version 2, or (at your option) any
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
34 You should have received a copy of the GNU General Public License
35 along with this program; if not, write to the Free Software
36 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 In other words, you are welcome to use, share and improve this program.
39 You are forbidden to forbid anyone else to use, share and improve
40 what you give them. Help stamp out software-hoarding!
42 -------------------------------------------------------------------------*/
49 #ifdef HAVE_SYS_ISA_DEFS_H
50 #include <sys/isa_defs.h>
54 #include "SDCCpeeph.h"
58 /* this is the down and dirty file with all kinds of kludgy & hacky
59 stuff. This is what it is all about CODE GENERATION for a specific MCU.
60 Some of the routines may be reusable, will have to see */
62 static char *zero = "#0x00";
63 static char *one = "#0x01";
65 static char *_z80_return[] = {"l", "h", "e", "d" };
66 static char *_gbz80_return[] = { "e", "d", "l", "h" };
67 static char **_fReturn;
70 static char *accUse[] = {"a" };
76 extern int ptrRegReq ;
78 extern FILE *codeOutFile;
80 #define RESULTONSTACK(x) \
81 (IC_RESULT(x) && IC_RESULT(x)->aop && \
82 IC_RESULT(x)->aop->type == AOP_STK )
84 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
85 #define CLRC emitcode("xor","a,a");
87 #define LABEL_STR "%05d$"
89 lineNode *lineHead = NULL;
90 lineNode *lineCurr = NULL;
92 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
93 0xE0, 0xC0, 0x80, 0x00};
94 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
95 0x07, 0x03, 0x01, 0x00};
97 static int _lastStack = 0;
98 static int _pushed = 0;
114 /*-----------------------------------------------------------------*/
115 /* emitcode - writes the code into a file : for now it is simple */
116 /*-----------------------------------------------------------------*/
117 void emitcode (const char *inst, const char *fmt, ...)
120 char lb[MAX_INLINEASM];
126 sprintf(lb,"%s\t",inst);
127 vsprintf(lb+(strlen(lb)),fmt,ap);
131 while (isspace(*lbp)) lbp++;
134 lineCurr = (lineCurr ?
135 connectLine(lineCurr,newLineNode(lb)) :
136 (lineHead = newLineNode(lb)));
137 lineCurr->isInline = inLine;
138 lineCurr->isDebug = debugLine;
142 const char *getPairName(asmop *aop)
144 if (aop->type == AOP_REG) {
145 switch (aop->aopu.aop_reg[0]->rIdx) {
157 else if (aop->type == AOP_STR) {
158 switch (*aop->aopu.aop_str[0]) {
174 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
175 bool isPair(asmop *aop)
177 if (aop->size == 2) {
178 if (aop->type == AOP_REG) {
179 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
182 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
185 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
189 if (aop->type == AOP_STR) {
190 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
193 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
196 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
204 /** Push a register pair onto the stack */
205 void genPairPush(asmop *aop)
207 emitcode("push", "%s", getPairName(aop));
210 /*-----------------------------------------------------------------*/
211 /* newAsmop - creates a new asmOp */
212 /*-----------------------------------------------------------------*/
213 static asmop *newAsmop (short type)
217 ALLOC(aop,sizeof(asmop));
222 /*-----------------------------------------------------------------*/
223 /* aopForSym - for a true symbol */
224 /*-----------------------------------------------------------------*/
225 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
228 memmap *space= SPEC_OCLS(sym->etype);
230 /* if already has one */
234 /* Assign depending on the storage class */
235 if (sym->onStack || sym->iaccess) {
236 sym->aop = aop = newAsmop(AOP_STK);
237 aop->size = getSize(sym->type);
239 aop->aopu.aop_stk = sym->stack;
243 /* special case for a function */
244 if (IS_FUNC(sym->type)) {
245 sym->aop = aop = newAsmop(AOP_IMMD);
246 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
247 strcpy(aop->aopu.aop_immd,sym->rname);
253 /* if it is in direct space */
254 if (IN_DIRSPACE(space)) {
255 sym->aop = aop = newAsmop (AOP_DIR);
256 aop->aopu.aop_dir = sym->rname ;
257 aop->size = getSize(sym->type);
258 emitcode("", "; AOP_DIR for %s", sym->rname);
263 /* only remaining is far space */
264 /* in which case DPTR gets the address */
265 sym->aop = aop = newAsmop(AOP_IY);
267 emitcode ("ld","iy,#%s ; a", sym->rname);
268 aop->size = getSize(sym->type);
269 aop->aopu.aop_dir = sym->rname;
271 /* if it is in code space */
272 if (IN_CODESPACE(space))
278 /*-----------------------------------------------------------------*/
279 /* aopForRemat - rematerialzes an object */
280 /*-----------------------------------------------------------------*/
281 static asmop *aopForRemat (symbol *sym)
284 iCode *ic = sym->rematiCode;
285 asmop *aop = newAsmop(AOP_IMMD);
288 /* if plus or minus print the right hand side */
289 if (ic->op == '+' || ic->op == '-') {
290 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
293 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
296 /* we reached the end */
297 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
301 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
302 strcpy(aop->aopu.aop_immd,buffer);
306 /*-----------------------------------------------------------------*/
307 /* regsInCommon - two operands have some registers in common */
308 /*-----------------------------------------------------------------*/
309 bool regsInCommon (operand *op1, operand *op2)
314 /* if they have registers in common */
315 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
318 sym1 = OP_SYMBOL(op1);
319 sym2 = OP_SYMBOL(op2);
321 if (sym1->nRegs == 0 || sym2->nRegs == 0)
324 for (i = 0 ; i < sym1->nRegs ; i++) {
329 for (j = 0 ; j < sym2->nRegs ;j++ ) {
333 if (sym2->regs[j] == sym1->regs[i])
341 /*-----------------------------------------------------------------*/
342 /* operandsEqu - equivalent */
343 /*-----------------------------------------------------------------*/
344 bool operandsEqu ( operand *op1, operand *op2)
348 /* if they not symbols */
349 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
352 sym1 = OP_SYMBOL(op1);
353 sym2 = OP_SYMBOL(op2);
355 /* if both are itemps & one is spilt
356 and the other is not then false */
357 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
358 sym1->isspilt != sym2->isspilt )
361 /* if they are the same */
365 if (strcmp(sym1->rname,sym2->rname) == 0)
369 /* if left is a tmp & right is not */
373 (sym1->usl.spillLoc == sym2))
380 (sym2->usl.spillLoc == sym1))
386 /*-----------------------------------------------------------------*/
387 /* sameRegs - two asmops have the same registers */
388 /*-----------------------------------------------------------------*/
389 bool sameRegs (asmop *aop1, asmop *aop2 )
396 if (aop1->type != AOP_REG ||
397 aop2->type != AOP_REG )
400 if (aop1->size != aop2->size)
403 for (i = 0 ; i < aop1->size ; i++ )
404 if (aop1->aopu.aop_reg[i] !=
405 aop2->aopu.aop_reg[i] )
411 /*-----------------------------------------------------------------*/
412 /* aopOp - allocates an asmop for an operand : */
413 /*-----------------------------------------------------------------*/
414 static void aopOp (operand *op, iCode *ic, bool result)
423 /* if this a literal */
424 if (IS_OP_LITERAL(op)) {
425 op->aop = aop = newAsmop(AOP_LIT);
426 aop->aopu.aop_lit = op->operand.valOperand;
427 aop->size = getSize(operandType(op));
431 /* if already has a asmop then continue */
435 /* if the underlying symbol has a aop */
436 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
437 op->aop = OP_SYMBOL(op)->aop;
441 /* if this is a true symbol */
442 if (IS_TRUE_SYMOP(op)) {
443 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
447 /* this is a temporary : this has
453 e) can be a return use only */
457 /* if the type is a conditional */
458 if (sym->regType == REG_CND) {
459 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
464 /* if it is spilt then two situations
466 b) has a spill location */
467 if (sym->isspilt || sym->nRegs == 0) {
468 /* rematerialize it NOW */
470 sym->aop = op->aop = aop =
472 aop->size = getSize(sym->type);
478 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
479 aop->size = getSize(sym->type);
480 for ( i = 0 ; i < 2 ; i++ )
481 aop->aopu.aop_str[i] = accUse[i];
487 aop = op->aop = sym->aop = newAsmop(AOP_STR);
488 aop->size = getSize(sym->type);
489 for ( i = 0 ; i < 4 ; i++ )
490 aop->aopu.aop_str[i] = "xx"; /*_fReturn[i];*/
494 /* else spill location */
495 sym->aop = op->aop = aop =
496 aopForSym(ic,sym->usl.spillLoc,result);
497 aop->size = getSize(sym->type);
501 /* must be in a register */
502 sym->aop = op->aop = aop = newAsmop(AOP_REG);
503 aop->size = sym->nRegs;
504 for ( i = 0 ; i < sym->nRegs ;i++)
505 aop->aopu.aop_reg[i] = sym->regs[i];
508 /*-----------------------------------------------------------------*/
509 /* freeAsmop - free up the asmop given to an operand */
510 /*----------------------------------------------------------------*/
511 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
534 /* all other cases just dealloc */
538 OP_SYMBOL(op)->aop = NULL;
539 /* if the symbol has a spill */
541 SPIL_LOC(op)->aop = NULL;
546 char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
555 /* depending on type */
558 sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
559 ALLOC_ATOMIC(rs,strlen(s)+1);
564 value * val = aop->aopu.aop_lit;
565 /* if it is a float then it gets tricky */
566 /* otherwise it is fairly simple */
567 if (!IS_FLOAT(val->type)) {
568 unsigned long v = floatFromVal(val);
570 sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
571 ALLOC_ATOMIC(rs,strlen(buffer)+1);
572 return strcpy (rs,buffer);
581 char *aopGetWord(asmop *aop, int offset)
583 return aopGetWordLong(aop, offset, TRUE);
586 /*-----------------------------------------------------------------*/
587 /* aopGet - for fetching value of the aop */
588 /*-----------------------------------------------------------------*/
589 static char *aopGet (asmop *aop, int offset, bool bit16)
594 /* offset is greater than size then zero */
595 if (offset > (aop->size - 1) &&
596 aop->type != AOP_LIT)
599 /* depending on type */
603 sprintf (s,"#%s",aop->aopu.aop_immd);
613 ALLOC_ATOMIC(rs,strlen(s)+1);
619 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
621 ALLOC_ATOMIC(rs,strlen(s)+1);
626 return aop->aopu.aop_reg[offset]->name;
629 sprintf(s,"%d(iy)", offset);
630 ALLOC_ATOMIC(rs,strlen(s)+1);
636 /* We cant really optimise this as we cant afford to
639 emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
643 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
645 ALLOC_ATOMIC(rs,strlen(s)+1);
659 return aopLiteral (aop->aopu.aop_lit,offset);
663 return aop->aopu.aop_str[offset];
666 fprintf(stderr, "Type %u\n", aop->type);
668 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
669 "aopget got unsupported aop->type");
673 bool isRegString(char *s)
675 if (!strcmp(s, "b") ||
686 bool isConstant(char *s)
691 bool canAssignToPtr(char *s)
700 /*-----------------------------------------------------------------*/
701 /* aopPut - puts a string for a aop */
702 /*-----------------------------------------------------------------*/
703 static void aopPut (asmop *aop, char *s, int offset)
705 if (aop->size && offset > ( aop->size - 1)) {
706 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
707 "aopPut got offset > aop->size");
711 /* will assign value to value */
712 /* depending on where it is ofcourse */
717 emitcode("ld", "a,%s", s);
718 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
722 /* Dont bother if it's a ld x,x */
723 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
724 emitcode("ld","%s,%s",
725 aop->aopu.aop_reg[offset]->name,s);
731 if (!canAssignToPtr(s)) {
732 emitcode("ld", "a,%s", s);
733 emitcode("ld", "%d(iy),a", offset);
736 emitcode("ld", "%d(iy),%s", offset, s);
741 if (!strcmp("(hl)", s)) {
742 emitcode("ld", "a,(hl)");
745 emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
746 if (!canAssignToPtr(s)) {
747 emitcode("ld", "a,%s", s);
748 emitcode("ld", "(hl),a");
751 emitcode("ld", "(hl),%s", s);
754 if (!canAssignToPtr(s)) {
755 emitcode("ld", "a,%s", s);
756 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
759 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
764 /* if bit variable */
765 if (!aop->aopu.aop_dir) {
766 emitcode("ld", "a,#0");
769 /* In bit space but not in C - cant happen */
776 if (strcmp(aop->aopu.aop_str[offset],s)) {
777 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
783 if (!offset && (strcmp(s,"acc") == 0))
787 emitcode("", "; Error aopPut AOP_ACC");
790 if (strcmp(aop->aopu.aop_str[offset],s))
791 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
796 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
797 "aopPut got unsupported aop->type");
802 #define AOP(op) op->aop
803 #define AOP_TYPE(op) AOP(op)->type
804 #define AOP_SIZE(op) AOP(op)->size
805 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
807 /*-----------------------------------------------------------------*/
808 /* getDataSize - get the operand data size */
809 /*-----------------------------------------------------------------*/
810 int getDataSize(operand *op)
821 /*-----------------------------------------------------------------*/
822 /* movLeft2Result - move byte from left to result */
823 /*-----------------------------------------------------------------*/
824 static void movLeft2Result (operand *left, int offl,
825 operand *result, int offr, int sign)
828 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
829 l = aopGet(AOP(left),offl,FALSE);
832 aopPut(AOP(result),l,offr);
841 /** Put Acc into a register set
843 void outAcc(operand *result)
846 size = getDataSize(result);
848 aopPut(AOP(result),"a",0);
851 /* unsigned or positive */
853 aopPut(AOP(result),zero,offset++);
858 /** Take the value in carry and put it into a register
860 void outBitC(operand *result)
862 /* if the result is bit */
863 if (AOP_TYPE(result) == AOP_CRY) {
864 emitcode("", "; Note: outBitC form 1");
865 aopPut(AOP(result),"blah",0);
868 emitcode("ld", "a,#0");
874 /*-----------------------------------------------------------------*/
875 /* toBoolean - emit code for orl a,operator(sizeop) */
876 /*-----------------------------------------------------------------*/
877 void toBoolean(operand *oper)
879 int size = AOP_SIZE(oper);
882 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
885 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
888 if (AOP(oper)->type != AOP_ACC) {
890 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
895 /*-----------------------------------------------------------------*/
896 /* genNot - generate code for ! operation */
897 /*-----------------------------------------------------------------*/
898 static void genNot (iCode *ic)
900 link *optype = operandType(IC_LEFT(ic));
902 /* assign asmOps to operand & result */
903 aopOp (IC_LEFT(ic),ic,FALSE);
904 aopOp (IC_RESULT(ic),ic,TRUE);
906 /* if in bit space then a special case */
907 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
911 /* if type float then do float */
912 if (IS_FLOAT(optype)) {
916 toBoolean(IC_LEFT(ic));
921 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
922 emitcode("sub", "a,#0x01");
923 outBitC(IC_RESULT(ic));
925 /* release the aops */
926 freeAsmop(IC_LEFT(ic),NULL,ic);
927 freeAsmop(IC_RESULT(ic),NULL,ic);
930 /*-----------------------------------------------------------------*/
931 /* genCpl - generate code for complement */
932 /*-----------------------------------------------------------------*/
933 static void genCpl (iCode *ic)
939 /* assign asmOps to operand & result */
940 aopOp (IC_LEFT(ic),ic,FALSE);
941 aopOp (IC_RESULT(ic),ic,TRUE);
943 /* if both are in bit space then
945 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
946 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
950 size = AOP_SIZE(IC_RESULT(ic));
952 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
955 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
958 /* release the aops */
959 freeAsmop(IC_LEFT(ic),NULL,ic);
960 freeAsmop(IC_RESULT(ic),NULL,ic);
963 /*-----------------------------------------------------------------*/
964 /* genUminus - unary minus code generation */
965 /*-----------------------------------------------------------------*/
966 static void genUminus (iCode *ic)
969 link *optype, *rtype;
972 aopOp(IC_LEFT(ic),ic,FALSE);
973 aopOp(IC_RESULT(ic),ic,TRUE);
975 /* if both in bit space then special
977 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
978 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
983 optype = operandType(IC_LEFT(ic));
984 rtype = operandType(IC_RESULT(ic));
986 /* if float then do float stuff */
987 if (IS_FLOAT(optype)) {
992 /* otherwise subtract from zero */
993 size = AOP_SIZE(IC_LEFT(ic));
997 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
998 emitcode("ld", "a,#0");
999 emitcode("sbc","a,%s",l);
1000 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1003 /* if any remaining bytes in the result */
1004 /* we just need to propagate the sign */
1005 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1006 emitcode("rlc","a");
1007 emitcode("sbc","a,a");
1009 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1013 /* release the aops */
1014 freeAsmop(IC_LEFT(ic),NULL,ic);
1015 freeAsmop(IC_RESULT(ic),NULL,ic);
1018 static bool requiresHL(asmop *aop)
1020 switch (aop->type) {
1028 /*-----------------------------------------------------------------*/
1029 /* assignResultValue - */
1030 /*-----------------------------------------------------------------*/
1031 void assignResultValue(operand * oper)
1034 int size = AOP_SIZE(oper);
1039 aopPut(AOP(oper),_fReturn[offset],offset);
1044 static void fetchHL(asmop *aop)
1046 if (IS_GB && requiresHL(aop)) {
1047 emitcode("ld", "a,%s", aopGet(aop, 0, FALSE));
1048 emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
1049 emitcode("ld", "l,a");
1052 emitcode("ld", "l,%s", aopGet(aop, 0, FALSE));
1053 emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
1057 /*-----------------------------------------------------------------*/
1058 /* genIpush - genrate code for pushing this gets a little complex */
1059 /*-----------------------------------------------------------------*/
1060 static void genIpush (iCode *ic)
1062 int size, offset = 0 ;
1066 /* if this is not a parm push : ie. it is spill push
1067 and spill push is always done on the local stack */
1068 if (!ic->parmPush) {
1069 /* and the item is spilt then do nothing */
1070 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1073 aopOp(IC_LEFT(ic),ic,FALSE);
1074 size = AOP_SIZE(IC_LEFT(ic));
1075 /* push it on the stack */
1076 if (isPair(AOP(IC_LEFT(ic)))) {
1077 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1083 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1084 /* Simple for now - load into A and PUSH AF */
1085 emitcode("ld", "a,%s", l);
1086 emitcode("push", "af");
1087 emitcode("inc", "sp");
1094 /* Hmmm... what about saving the currently used registers
1097 /* then do the push */
1098 aopOp(IC_LEFT(ic),ic,FALSE);
1100 size = AOP_SIZE(IC_LEFT(ic));
1102 if (isPair(AOP(IC_LEFT(ic)))) {
1104 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1108 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1110 emitcode("ld", "hl,%s", s);
1111 emitcode("push", "hl");
1115 /* Optimise here - load into HL then push HL */
1116 fetchHL(AOP(IC_LEFT(ic)));
1117 emitcode("push", "hl");
1124 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1125 emitcode("ld", "a,%s", l);
1126 emitcode("push", "af");
1127 emitcode("inc", "sp");
1132 freeAsmop(IC_LEFT(ic),NULL,ic);
1135 /*-----------------------------------------------------------------*/
1136 /* genIpop - recover the registers: can happen only for spilling */
1137 /*-----------------------------------------------------------------*/
1138 static void genIpop (iCode *ic)
1143 /* if the temp was not pushed then */
1144 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1147 aopOp(IC_LEFT(ic),ic,FALSE);
1148 size = AOP_SIZE(IC_LEFT(ic));
1150 if (isPair(AOP(IC_LEFT(ic)))) {
1151 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1155 emitcode("dec", "sp");
1156 emitcode("pop", "hl");
1157 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1161 freeAsmop(IC_LEFT(ic),NULL,ic);
1164 /** Emit the code for a call statement
1166 static void emitCall (iCode *ic, bool ispcall)
1168 /* if caller saves & we have not saved then */
1169 if (!ic->regsSaved) {
1173 /* if send set is not empty then assign */
1177 for (sic = setFirstItem(sendSet) ; sic ;
1178 sic = setNextItem(sendSet)) {
1179 int size, offset = 0;
1180 aopOp(IC_LEFT(sic),sic,FALSE);
1181 size = AOP_SIZE(IC_LEFT(sic));
1183 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1185 if (strcmp(l, _fReturn[offset]))
1186 emitcode("ld","%s,%s",
1191 freeAsmop (IC_LEFT(sic),NULL,sic);
1197 symbol *rlbl = newiTempLabel(NULL);
1199 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1200 emitcode("push", "hl");
1202 aopOp(IC_LEFT(ic),ic,FALSE);
1203 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1204 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1205 freeAsmop(IC_LEFT(ic),NULL,ic);
1207 emitcode("jp", "(hl)");
1208 emitcode("","%05d$:",(rlbl->key+100));
1212 emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1213 OP_SYMBOL(IC_LEFT(ic))->rname :
1214 OP_SYMBOL(IC_LEFT(ic))->name));
1217 /* if we need assign a result value */
1218 if ((IS_ITEMP(IC_RESULT(ic)) &&
1219 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1220 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1221 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1224 aopOp(IC_RESULT(ic),ic,FALSE);
1227 assignResultValue(IC_RESULT(ic));
1229 freeAsmop(IC_RESULT(ic),NULL, ic);
1232 /* adjust the stack for parameters if required */
1233 if (IC_LEFT(ic)->parmBytes) {
1234 int i = IC_LEFT(ic)->parmBytes;
1237 emitcode("ld", "hl,#%d", i);
1238 emitcode("add", "hl,sp");
1239 emitcode("ld", "sp,hl");
1243 emitcode("pop", "hl");
1247 emitcode("inc", "sp");
1253 /*-----------------------------------------------------------------*/
1254 /* genCall - generates a call statement */
1255 /*-----------------------------------------------------------------*/
1256 static void genCall (iCode *ic)
1258 emitCall(ic, FALSE);
1261 /*-----------------------------------------------------------------*/
1262 /* genPcall - generates a call by pointer statement */
1263 /*-----------------------------------------------------------------*/
1264 static void genPcall (iCode *ic)
1269 /*-----------------------------------------------------------------*/
1270 /* resultRemat - result is rematerializable */
1271 /*-----------------------------------------------------------------*/
1272 static int resultRemat (iCode *ic)
1274 if (SKIP_IC(ic) || ic->op == IFX)
1277 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1278 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1279 if (sym->remat && !POINTER_SET(ic))
1286 /*-----------------------------------------------------------------*/
1287 /* genFunction - generated code for function entry */
1288 /*-----------------------------------------------------------------*/
1289 static void genFunction (iCode *ic)
1295 /* create the function header */
1296 emitcode(";","-----------------------------------------");
1297 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1298 emitcode(";","-----------------------------------------");
1300 emitcode("","%s:",sym->rname);
1301 fetype = getSpec(operandType(IC_LEFT(ic)));
1303 /* if critical function then turn interrupts off */
1304 if (SPEC_CRTCL(fetype))
1307 /* if this is an interrupt service routine then
1308 save acc, b, dpl, dph */
1309 if (IS_ISR(sym->etype)) {
1310 emitcode("push", "af");
1311 emitcode("push", "bc");
1312 emitcode("push", "de");
1313 emitcode("push", "hl");
1315 /* PENDING: callee-save etc */
1317 /* adjust the stack for the function */
1318 emitcode("push", "bc");
1320 emitcode("push", "de");
1321 emitcode("push", "ix");
1322 emitcode("ld", "ix,#0");
1323 emitcode("add", "ix,sp");
1326 _lastStack = sym->stack;
1329 emitcode("ld", "hl,#-%d", sym->stack);
1330 emitcode("add", "hl,sp");
1331 emitcode("ld", "sp,hl");
1333 _spoffset = sym->stack;
1336 /*-----------------------------------------------------------------*/
1337 /* genEndFunction - generates epilogue for functions */
1338 /*-----------------------------------------------------------------*/
1339 static void genEndFunction (iCode *ic)
1341 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1343 if (IS_ISR(sym->etype)) {
1347 if (SPEC_CRTCL(sym->etype))
1350 /* PENDING: calleeSave */
1352 /* if debug then send end of function */
1353 if (options.debug && currFunc) {
1355 emitcode("","C$%s$%d$%d$%d ==.",
1356 ic->filename,currFunc->lastLine,
1357 ic->level,ic->block);
1358 if (IS_STATIC(currFunc->etype))
1359 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1361 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1365 emitcode("ld", "sp,ix");
1366 emitcode("pop", "ix");
1367 emitcode("pop", "de");
1369 emitcode("pop", "bc");
1370 emitcode("ret", "");
1375 /*-----------------------------------------------------------------*/
1376 /* genRet - generate code for return statement */
1377 /*-----------------------------------------------------------------*/
1378 static void genRet (iCode *ic)
1381 /* Errk. This is a hack until I can figure out how
1382 to cause dehl to spill on a call */
1383 int size,offset = 0;
1385 /* if we have no return value then
1386 just generate the "ret" */
1390 /* we have something to return then
1391 move the return value into place */
1392 aopOp(IC_LEFT(ic),ic,FALSE);
1393 size = AOP_SIZE(IC_LEFT(ic));
1395 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1396 emitcode("ld", "hl,%s", l);
1400 l = aopGet(AOP(IC_LEFT(ic)),offset,
1402 if (strcmp(_fReturn[offset],l))
1403 emitcode("ld","%s,%s", _fReturn[offset++],l);
1406 freeAsmop (IC_LEFT(ic),NULL,ic);
1409 /* generate a jump to the return label
1410 if the next is not the return statement */
1411 if (!(ic->next && ic->next->op == LABEL &&
1412 IC_LABEL(ic->next) == returnLabel))
1414 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1417 /*-----------------------------------------------------------------*/
1418 /* genLabel - generates a label */
1419 /*-----------------------------------------------------------------*/
1420 static void genLabel (iCode *ic)
1422 /* special case never generate */
1423 if (IC_LABEL(ic) == entryLabel)
1426 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1429 /*-----------------------------------------------------------------*/
1430 /* genGoto - generates a ljmp */
1431 /*-----------------------------------------------------------------*/
1432 static void genGoto (iCode *ic)
1434 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1437 /*-----------------------------------------------------------------*/
1438 /* genPlusIncr :- does addition with increment if possible */
1439 /*-----------------------------------------------------------------*/
1440 static bool genPlusIncr (iCode *ic)
1442 unsigned int icount ;
1443 unsigned int size = getDataSize(IC_RESULT(ic));
1445 /* will try to generate an increment */
1446 /* if the right side is not a literal
1448 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1451 emitcode("", "; genPlusIncr");
1453 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1455 /* If result is a pair */
1456 if (isPair(AOP(IC_RESULT(ic)))) {
1457 char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1459 /* Both a lit on the right and a true symbol on the left */
1460 emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
1465 /* if the literal value of the right hand side
1466 is greater than 4 then it is not worth it */
1471 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1472 isPair(AOP(IC_RESULT(ic)))) {
1474 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1478 /* if increment 16 bits in register */
1479 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1482 symbol *tlbl = newiTempLabel(NULL);
1483 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1484 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1486 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1490 emitcode("", LABEL_STR ":",tlbl->key+100);
1494 /* If result is a pair */
1495 if (isPair(AOP(IC_RESULT(ic)))) {
1496 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1497 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1499 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1503 /* if the sizes are greater than 1 then we cannot */
1504 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1505 AOP_SIZE(IC_LEFT(ic)) > 1 )
1508 /* we can if the aops of the left & result match or
1509 if they are in registers and the registers are the
1511 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1513 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1521 /*-----------------------------------------------------------------*/
1522 /* outBitAcc - output a bit in acc */
1523 /*-----------------------------------------------------------------*/
1524 void outBitAcc(operand *result)
1526 symbol *tlbl = newiTempLabel(NULL);
1527 /* if the result is a bit */
1528 if (AOP_TYPE(result) == AOP_CRY){
1532 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1533 emitcode("ld","a,%s",one);
1534 emitcode("", LABEL_STR ":",tlbl->key+100);
1539 /*-----------------------------------------------------------------*/
1540 /* genPlus - generates code for addition */
1541 /*-----------------------------------------------------------------*/
1542 static void genPlus (iCode *ic)
1544 int size, offset = 0;
1546 /* special cases :- */
1548 aopOp (IC_LEFT(ic),ic,FALSE);
1549 aopOp (IC_RIGHT(ic),ic,FALSE);
1550 aopOp (IC_RESULT(ic),ic,TRUE);
1552 /* Swap the left and right operands if:
1554 if literal, literal on the right or
1555 if left requires ACC or right is already
1558 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1559 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1560 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1561 operand *t = IC_RIGHT(ic);
1562 IC_RIGHT(ic) = IC_LEFT(ic);
1566 /* if both left & right are in bit
1568 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1569 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1574 /* if left in bit space & right literal */
1575 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1576 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1577 /* Can happen I guess */
1581 /* if I can do an increment instead
1582 of add then GOOD for ME */
1583 if (genPlusIncr (ic) == TRUE)
1586 size = getDataSize(IC_RESULT(ic));
1588 /* Special case when left and right are constant */
1589 if (isPair(AOP(IC_RESULT(ic)))) {
1592 left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1593 right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1594 if (left && right) {
1598 sprintf(buffer, "#(%s + %s)", left, right);
1599 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1605 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1606 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1608 emitcode("add","a,%s",
1609 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1611 emitcode("adc","a,%s",
1612 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1614 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1616 emitcode("add","a,%s",
1617 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1619 emitcode("adc","a,%s",
1620 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1622 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1625 /* Some kind of pointer arith. */
1626 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1627 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1628 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1631 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1632 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1633 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1638 freeAsmop(IC_LEFT(ic),NULL,ic);
1639 freeAsmop(IC_RIGHT(ic),NULL,ic);
1640 freeAsmop(IC_RESULT(ic),NULL,ic);
1644 /*-----------------------------------------------------------------*/
1645 /* genMinusDec :- does subtraction with deccrement if possible */
1646 /*-----------------------------------------------------------------*/
1647 static bool genMinusDec (iCode *ic)
1649 unsigned int icount ;
1650 unsigned int size = getDataSize(IC_RESULT(ic));
1652 /* will try to generate an increment */
1653 /* if the right side is not a literal we cannot */
1654 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1657 /* if the literal value of the right hand side
1658 is greater than 4 then it is not worth it */
1659 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1662 size = getDataSize(IC_RESULT(ic));
1665 /* if increment 16 bits in register */
1666 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1669 symbol *tlbl = newiTempLabel(NULL);
1670 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1671 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1673 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1677 emitcode("", LABEL_STR ":",tlbl->key+100);
1682 /* if decrement 16 bits in register */
1683 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1684 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1686 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1690 /* If result is a pair */
1691 if (isPair(AOP(IC_RESULT(ic)))) {
1692 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1693 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1695 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1699 /* if the sizes are greater than 1 then we cannot */
1700 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1701 AOP_SIZE(IC_LEFT(ic)) > 1 )
1704 /* we can if the aops of the left & result match or if they are in
1705 registers and the registers are the same */
1706 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1708 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1715 /*-----------------------------------------------------------------*/
1716 /* genMinus - generates code for subtraction */
1717 /*-----------------------------------------------------------------*/
1718 static void genMinus (iCode *ic)
1720 int size, offset = 0;
1721 unsigned long lit = 0L;
1723 aopOp (IC_LEFT(ic),ic,FALSE);
1724 aopOp (IC_RIGHT(ic),ic,FALSE);
1725 aopOp (IC_RESULT(ic),ic,TRUE);
1727 /* special cases :- */
1728 /* if both left & right are in bit space */
1729 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1730 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1735 /* if I can do an decrement instead of subtract then GOOD for ME */
1736 if (genMinusDec (ic) == TRUE)
1739 size = getDataSize(IC_RESULT(ic));
1741 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1744 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1749 /* if literal, add a,#-lit, else normal subb */
1751 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1752 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1754 emitcode("sub","a,%s",
1755 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1757 emitcode("sbc","a,%s",
1758 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1761 /* first add without previous c */
1763 emitcode("add","a,#0x%02x",
1764 (unsigned int)(lit & 0x0FFL));
1766 emitcode("adc","a,#0x%02x",
1767 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1769 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1772 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1773 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1774 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1778 freeAsmop(IC_LEFT(ic),NULL,ic);
1779 freeAsmop(IC_RIGHT(ic),NULL,ic);
1780 freeAsmop(IC_RESULT(ic),NULL,ic);
1783 /*-----------------------------------------------------------------*/
1784 /* genMult - generates code for multiplication */
1785 /*-----------------------------------------------------------------*/
1786 static void genMult (iCode *ic)
1788 /* Shouldn't occur - all done through function calls */
1792 /*-----------------------------------------------------------------*/
1793 /* genDiv - generates code for division */
1794 /*-----------------------------------------------------------------*/
1795 static void genDiv (iCode *ic)
1797 /* Shouldn't occur - all done through function calls */
1801 /*-----------------------------------------------------------------*/
1802 /* genMod - generates code for division */
1803 /*-----------------------------------------------------------------*/
1804 static void genMod (iCode *ic)
1806 /* Shouldn't occur - all done through function calls */
1810 /*-----------------------------------------------------------------*/
1811 /* genIfxJump :- will create a jump depending on the ifx */
1812 /*-----------------------------------------------------------------*/
1813 static void genIfxJump (iCode *ic, char *jval)
1818 /* if true label then we jump if condition
1820 if ( IC_TRUE(ic) ) {
1822 if (!strcmp(jval, "a")) {
1825 else if (!strcmp(jval, "c")) {
1829 /* The buffer contains the bit on A that we should test */
1834 /* false label is present */
1835 jlbl = IC_FALSE(ic) ;
1836 if (!strcmp(jval, "a")) {
1839 else if (!strcmp(jval, "c")) {
1843 /* The buffer contains the bit on A that we should test */
1847 /* Z80 can do a conditional long jump */
1848 if (!strcmp(jval, "a")) {
1849 emitcode("or", "a,a");
1851 else if (!strcmp(jval, "c")) {
1854 emitcode("bit", "%s,a", jval);
1856 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1858 /* mark the icode as generated */
1862 /** Generic compare for > or <
1864 static void genCmp (operand *left,operand *right,
1865 operand *result, iCode *ifx, int sign)
1867 int size, offset = 0 ;
1868 unsigned long lit = 0L;
1870 /* if left & right are bit variables */
1871 if (AOP_TYPE(left) == AOP_CRY &&
1872 AOP_TYPE(right) == AOP_CRY ) {
1873 /* Cant happen on the Z80 */
1876 /* subtract right from left if at the
1877 end the carry flag is set then we know that
1878 left is greater than right */
1879 size = max(AOP_SIZE(left),AOP_SIZE(right));
1881 /* if unsigned char cmp with lit, just compare */
1883 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1884 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1886 emitcode("xor", "a,#0x80");
1887 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
1890 emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
1893 if(AOP_TYPE(right) == AOP_LIT) {
1894 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1895 /* optimize if(x < 0) or if(x >= 0) */
1898 /* No sign so it's always false */
1902 /* Just load in the top most bit */
1903 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1904 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1905 genIfxJump (ifx,"7");
1909 emitcode("rlc","a");
1915 /* First setup h and l contaning the top most bytes XORed */
1916 bool fDidXor = FALSE;
1917 if (AOP_TYPE(left) == AOP_LIT){
1918 unsigned long lit = (unsigned long)
1919 floatFromVal(AOP(left)->aopu.aop_lit);
1920 emitcode("ld", "%s,#0x%02x", _fTmp[0],
1921 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1924 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
1925 emitcode("xor", "a,#0x80");
1926 emitcode("ld", "%s,a", _fTmp[0]);
1929 if (AOP_TYPE(right) == AOP_LIT) {
1930 unsigned long lit = (unsigned long)
1931 floatFromVal(AOP(right)->aopu.aop_lit);
1932 emitcode("ld", "%s,#0x%02x", _fTmp[1],
1933 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1936 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
1937 emitcode("xor", "a,#0x80");
1938 emitcode("ld", "%s,a", _fTmp[1]);
1948 /* Do a long subtract */
1950 MOVA(aopGet(AOP(left),offset,FALSE));
1951 if (sign && size == 0) {
1952 emitcode("ld", "a,%s", _fTmp[0]);
1953 emitcode("sbc", "a,%s", _fTmp[1]);
1956 /* Subtract through, propagating the carry */
1957 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1964 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1967 /* if the result is used in the next
1968 ifx conditional branch then generate
1969 code a little differently */
1971 genIfxJump (ifx,"c");
1974 /* leave the result in acc */
1978 /*-----------------------------------------------------------------*/
1979 /* genCmpGt :- greater than comparison */
1980 /*-----------------------------------------------------------------*/
1981 static void genCmpGt (iCode *ic, iCode *ifx)
1983 operand *left, *right, *result;
1984 link *letype , *retype;
1988 right= IC_RIGHT(ic);
1989 result = IC_RESULT(ic);
1991 letype = getSpec(operandType(left));
1992 retype =getSpec(operandType(right));
1993 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1994 /* assign the amsops */
1995 aopOp (left,ic,FALSE);
1996 aopOp (right,ic,FALSE);
1997 aopOp (result,ic,TRUE);
1999 genCmp(right, left, result, ifx, sign);
2001 freeAsmop(left,NULL,ic);
2002 freeAsmop(right,NULL,ic);
2003 freeAsmop(result,NULL,ic);
2006 /*-----------------------------------------------------------------*/
2007 /* genCmpLt - less than comparisons */
2008 /*-----------------------------------------------------------------*/
2009 static void genCmpLt (iCode *ic, iCode *ifx)
2011 operand *left, *right, *result;
2012 link *letype , *retype;
2016 right= IC_RIGHT(ic);
2017 result = IC_RESULT(ic);
2019 letype = getSpec(operandType(left));
2020 retype =getSpec(operandType(right));
2021 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2023 /* assign the amsops */
2024 aopOp (left,ic,FALSE);
2025 aopOp (right,ic,FALSE);
2026 aopOp (result,ic,TRUE);
2028 genCmp(left, right, result, ifx, sign);
2030 freeAsmop(left,NULL,ic);
2031 freeAsmop(right,NULL,ic);
2032 freeAsmop(result,NULL,ic);
2035 /*-----------------------------------------------------------------*/
2036 /* gencjneshort - compare and jump if not equal */
2037 /*-----------------------------------------------------------------*/
2038 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2040 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2042 unsigned long lit = 0L;
2044 /* Swap the left and right if it makes the computation easier */
2045 if (AOP_TYPE(left) == AOP_LIT) {
2051 if(AOP_TYPE(right) == AOP_LIT)
2052 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2054 /* if the right side is a literal then anything goes */
2055 if (AOP_TYPE(right) == AOP_LIT &&
2056 AOP_TYPE(left) != AOP_DIR ) {
2058 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2059 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2060 emitcode("or", "a,a");
2062 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2063 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2067 /* if the right side is in a register or in direct space or
2068 if the left is a pointer register & right is not */
2069 else if (AOP_TYPE(right) == AOP_REG ||
2070 AOP_TYPE(right) == AOP_DIR ||
2071 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2073 MOVA(aopGet(AOP(left),offset,FALSE));
2074 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2075 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2077 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
2079 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2080 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2085 /* right is a pointer reg need both a & b */
2086 /* PENDING: is this required? */
2088 char *l = aopGet(AOP(left),offset,FALSE);
2089 MOVA(aopGet(AOP(right),offset,FALSE));
2090 emitcode("cp", "%s ; 5", l);
2091 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2097 /*-----------------------------------------------------------------*/
2098 /* gencjne - compare and jump if not equal */
2099 /*-----------------------------------------------------------------*/
2100 static void gencjne(operand *left, operand *right, symbol *lbl)
2102 symbol *tlbl = newiTempLabel(NULL);
2104 gencjneshort(left, right, lbl);
2107 emitcode("ld","a,%s",one);
2108 emitcode("jp", LABEL_STR ,tlbl->key+100);
2109 emitcode("", LABEL_STR ":",lbl->key+100);
2110 emitcode("xor","a,a");
2111 emitcode("", LABEL_STR ":",tlbl->key+100);
2114 /*-----------------------------------------------------------------*/
2115 /* genCmpEq - generates code for equal to */
2116 /*-----------------------------------------------------------------*/
2117 static void genCmpEq (iCode *ic, iCode *ifx)
2119 operand *left, *right, *result;
2121 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2122 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2123 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2125 /* Swap operands if it makes the operation easier. ie if:
2126 1. Left is a literal.
2128 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2129 operand *t = IC_RIGHT(ic);
2130 IC_RIGHT(ic) = IC_LEFT(ic);
2134 if (ifx && !AOP_SIZE(result)){
2136 /* if they are both bit variables */
2137 if (AOP_TYPE(left) == AOP_CRY &&
2138 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2141 tlbl = newiTempLabel(NULL);
2142 gencjneshort(left, right, tlbl);
2143 if ( IC_TRUE(ifx) ) {
2144 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2145 emitcode("", LABEL_STR ":",tlbl->key+100);
2147 /* PENDING: do this better */
2148 symbol *lbl = newiTempLabel(NULL);
2149 emitcode("jp", LABEL_STR ,lbl->key+100);
2150 emitcode("", LABEL_STR ":",tlbl->key+100);
2151 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2152 emitcode("", LABEL_STR ":",lbl->key+100);
2155 /* mark the icode as generated */
2160 /* if they are both bit variables */
2161 if (AOP_TYPE(left) == AOP_CRY &&
2162 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2165 gencjne(left,right,newiTempLabel(NULL));
2166 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2170 genIfxJump(ifx,"a");
2173 /* if the result is used in an arithmetic operation
2174 then put the result in place */
2175 if (AOP_TYPE(result) != AOP_CRY) {
2178 /* leave the result in acc */
2182 freeAsmop(left,NULL,ic);
2183 freeAsmop(right,NULL,ic);
2184 freeAsmop(result,NULL,ic);
2187 /*-----------------------------------------------------------------*/
2188 /* ifxForOp - returns the icode containing the ifx for operand */
2189 /*-----------------------------------------------------------------*/
2190 static iCode *ifxForOp ( operand *op, iCode *ic )
2192 /* if true symbol then needs to be assigned */
2193 if (IS_TRUE_SYMOP(op))
2196 /* if this has register type condition and
2197 the next instruction is ifx with the same operand
2198 and live to of the operand is upto the ifx only then */
2200 ic->next->op == IFX &&
2201 IC_COND(ic->next)->key == op->key &&
2202 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2208 /*-----------------------------------------------------------------*/
2209 /* genAndOp - for && operation */
2210 /*-----------------------------------------------------------------*/
2211 static void genAndOp (iCode *ic)
2213 operand *left,*right, *result;
2216 /* note here that && operations that are in an if statement are
2217 taken away by backPatchLabels only those used in arthmetic
2218 operations remain */
2219 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2220 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2221 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2223 /* if both are bit variables */
2224 if (AOP_TYPE(left) == AOP_CRY &&
2225 AOP_TYPE(right) == AOP_CRY ) {
2228 tlbl = newiTempLabel(NULL);
2230 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2232 emitcode("", LABEL_STR ":",tlbl->key+100);
2236 freeAsmop(left,NULL,ic);
2237 freeAsmop(right,NULL,ic);
2238 freeAsmop(result,NULL,ic);
2241 /*-----------------------------------------------------------------*/
2242 /* genOrOp - for || operation */
2243 /*-----------------------------------------------------------------*/
2244 static void genOrOp (iCode *ic)
2246 operand *left,*right, *result;
2249 /* note here that || operations that are in an
2250 if statement are taken away by backPatchLabels
2251 only those used in arthmetic operations remain */
2252 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2253 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2254 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2256 /* if both are bit variables */
2257 if (AOP_TYPE(left) == AOP_CRY &&
2258 AOP_TYPE(right) == AOP_CRY ) {
2261 tlbl = newiTempLabel(NULL);
2263 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2265 emitcode("", LABEL_STR,tlbl->key+100);
2269 freeAsmop(left,NULL,ic);
2270 freeAsmop(right,NULL,ic);
2271 freeAsmop(result,NULL,ic);
2274 /*-----------------------------------------------------------------*/
2275 /* isLiteralBit - test if lit == 2^n */
2276 /*-----------------------------------------------------------------*/
2277 int isLiteralBit(unsigned long lit)
2279 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2280 0x100L,0x200L,0x400L,0x800L,
2281 0x1000L,0x2000L,0x4000L,0x8000L,
2282 0x10000L,0x20000L,0x40000L,0x80000L,
2283 0x100000L,0x200000L,0x400000L,0x800000L,
2284 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2285 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2288 for(idx = 0; idx < 32; idx++)
2294 /*-----------------------------------------------------------------*/
2295 /* genAnd - code for and */
2296 /*-----------------------------------------------------------------*/
2297 static void genAnd (iCode *ic, iCode *ifx)
2299 operand *left, *right, *result;
2301 unsigned long lit = 0L;
2304 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2305 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2306 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2309 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2311 AOP_TYPE(left), AOP_TYPE(right));
2312 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2314 AOP_SIZE(left), AOP_SIZE(right));
2317 /* if left is a literal & right is not then exchange them */
2318 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2319 AOP_NEEDSACC(left)) {
2320 operand *tmp = right ;
2325 /* if result = right then exchange them */
2326 if(sameRegs(AOP(result),AOP(right))){
2327 operand *tmp = right ;
2332 /* if right is bit then exchange them */
2333 if (AOP_TYPE(right) == AOP_CRY &&
2334 AOP_TYPE(left) != AOP_CRY){
2335 operand *tmp = right ;
2339 if(AOP_TYPE(right) == AOP_LIT)
2340 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2342 size = AOP_SIZE(result);
2344 if (AOP_TYPE(left) == AOP_CRY){
2349 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2350 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2351 if((AOP_TYPE(right) == AOP_LIT) &&
2352 (AOP_TYPE(result) == AOP_CRY) &&
2353 (AOP_TYPE(left) != AOP_CRY)) {
2354 int posbit = isLiteralBit(lit);
2358 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2362 emitcode("mov","c,acc.%d",posbit&0x07);
2367 sprintf(buffer, "%d", posbit&0x07);
2368 genIfxJump(ifx, buffer);
2376 symbol *tlbl = newiTempLabel(NULL);
2377 int sizel = AOP_SIZE(left);
2380 emitcode("setb","c");
2383 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2384 MOVA( aopGet(AOP(left),offset,FALSE));
2386 if((posbit = isLiteralBit(bytelit)) != 0) {
2388 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2391 if(bytelit != 0x0FFL)
2392 emitcode("and","a,%s",
2393 aopGet(AOP(right),offset,FALSE));
2394 emitcode("jr","nz, %05d$",tlbl->key+100);
2399 // bit = left & literal
2401 emitcode("clr","c");
2402 emitcode("","%05d$:",tlbl->key+100);
2404 // if(left & literal)
2408 jmpTrueOrFalse(ifx, tlbl);
2419 /* if left is same as result */
2420 if(sameRegs(AOP(result),AOP(left))){
2421 for(;size--; offset++) {
2422 if(AOP_TYPE(right) == AOP_LIT){
2423 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2427 aopPut(AOP(result),zero,offset);
2429 MOVA(aopGet(AOP(left),offset,FALSE));
2430 emitcode("and","a,%s",
2431 aopGet(AOP(right),offset,FALSE));
2432 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2437 if (AOP_TYPE(left) == AOP_ACC) {
2441 MOVA(aopGet(AOP(right),offset,FALSE));
2442 emitcode("and","%s,a",
2443 aopGet(AOP(left),offset,FALSE));
2448 // left & result in different registers
2449 if(AOP_TYPE(result) == AOP_CRY){
2452 for(;(size--);offset++) {
2454 // result = left & right
2455 if(AOP_TYPE(right) == AOP_LIT){
2456 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2458 aopGet(AOP(left),offset,FALSE),
2461 } else if(bytelit == 0){
2462 aopPut(AOP(result),zero,offset);
2466 // faster than result <- left, anl result,right
2467 // and better if result is SFR
2468 if (AOP_TYPE(left) == AOP_ACC)
2469 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2471 MOVA(aopGet(AOP(right),offset,FALSE));
2472 emitcode("and","a,%s",
2473 aopGet(AOP(left),offset,FALSE));
2475 aopPut(AOP(result),"a",offset);
2482 freeAsmop(left,NULL,ic);
2483 freeAsmop(right,NULL,ic);
2484 freeAsmop(result,NULL,ic);
2487 /*-----------------------------------------------------------------*/
2488 /* genOr - code for or */
2489 /*-----------------------------------------------------------------*/
2490 static void genOr (iCode *ic, iCode *ifx)
2492 operand *left, *right, *result;
2494 unsigned long lit = 0L;
2496 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2497 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2498 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2501 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2503 AOP_TYPE(left), AOP_TYPE(right));
2504 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2506 AOP_SIZE(left), AOP_SIZE(right));
2509 /* if left is a literal & right is not then exchange them */
2510 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2511 AOP_NEEDSACC(left)) {
2512 operand *tmp = right ;
2517 /* if result = right then exchange them */
2518 if(sameRegs(AOP(result),AOP(right))){
2519 operand *tmp = right ;
2524 /* if right is bit then exchange them */
2525 if (AOP_TYPE(right) == AOP_CRY &&
2526 AOP_TYPE(left) != AOP_CRY){
2527 operand *tmp = right ;
2531 if(AOP_TYPE(right) == AOP_LIT)
2532 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2534 size = AOP_SIZE(result);
2536 if (AOP_TYPE(left) == AOP_CRY){
2541 if((AOP_TYPE(right) == AOP_LIT) &&
2542 (AOP_TYPE(result) == AOP_CRY) &&
2543 (AOP_TYPE(left) != AOP_CRY)){
2548 /* if left is same as result */
2549 if(sameRegs(AOP(result),AOP(left))){
2550 for(;size--; offset++) {
2551 if(AOP_TYPE(right) == AOP_LIT){
2552 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2555 emitcode("or","%s,%s; 5",
2556 aopGet(AOP(left),offset,FALSE),
2557 aopGet(AOP(right),offset,FALSE));
2559 if (AOP_TYPE(left) == AOP_ACC)
2560 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2562 MOVA(aopGet(AOP(right),offset,FALSE));
2563 emitcode("or","a,%s ; 7",
2564 aopGet(AOP(left),offset,FALSE));
2565 aopPut(AOP(result),"a ; 8",0);
2570 // left & result in different registers
2571 if(AOP_TYPE(result) == AOP_CRY){
2573 } else for(;(size--);offset++){
2575 // result = left & right
2576 if(AOP_TYPE(right) == AOP_LIT){
2577 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2579 aopGet(AOP(left),offset,FALSE),
2584 // faster than result <- left, anl result,right
2585 // and better if result is SFR
2586 if (AOP_TYPE(left) == AOP_ACC)
2587 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2589 MOVA(aopGet(AOP(right),offset,FALSE));
2590 emitcode("or","a,%s",
2591 aopGet(AOP(left),offset,FALSE));
2593 aopPut(AOP(result),"a",offset);
2594 /* PENDING: something weird is going on here. Add exception. */
2595 if (AOP_TYPE(result) == AOP_ACC)
2601 freeAsmop(left,NULL,ic);
2602 freeAsmop(right,NULL,ic);
2603 freeAsmop(result,NULL,ic);
2606 /*-----------------------------------------------------------------*/
2607 /* genXor - code for xclusive or */
2608 /*-----------------------------------------------------------------*/
2609 static void genXor (iCode *ic, iCode *ifx)
2611 operand *left, *right, *result;
2613 unsigned long lit = 0L;
2615 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2616 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2617 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2619 /* if left is a literal & right is not then exchange them */
2620 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2621 AOP_NEEDSACC(left)) {
2622 operand *tmp = right ;
2627 /* if result = right then exchange them */
2628 if(sameRegs(AOP(result),AOP(right))){
2629 operand *tmp = right ;
2634 /* if right is bit then exchange them */
2635 if (AOP_TYPE(right) == AOP_CRY &&
2636 AOP_TYPE(left) != AOP_CRY){
2637 operand *tmp = right ;
2641 if(AOP_TYPE(right) == AOP_LIT)
2642 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2644 size = AOP_SIZE(result);
2646 if (AOP_TYPE(left) == AOP_CRY){
2651 if((AOP_TYPE(right) == AOP_LIT) &&
2652 (AOP_TYPE(result) == AOP_CRY) &&
2653 (AOP_TYPE(left) != AOP_CRY)){
2658 /* if left is same as result */
2659 if(sameRegs(AOP(result),AOP(left))){
2660 for(;size--; offset++) {
2661 if(AOP_TYPE(right) == AOP_LIT){
2662 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2665 MOVA(aopGet(AOP(right),offset,FALSE));
2666 emitcode("xor","a,%s",
2667 aopGet(AOP(left),offset,FALSE));
2668 aopPut(AOP(result),"a",0);
2671 if (AOP_TYPE(left) == AOP_ACC)
2672 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2674 MOVA(aopGet(AOP(right),offset,FALSE));
2675 emitcode("xor","a,%s",
2676 aopGet(AOP(left),offset,FALSE));
2677 aopPut(AOP(result),"a",0);
2682 // left & result in different registers
2683 if(AOP_TYPE(result) == AOP_CRY){
2685 } else for(;(size--);offset++){
2687 // result = left & right
2688 if(AOP_TYPE(right) == AOP_LIT){
2689 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2691 aopGet(AOP(left),offset,FALSE),
2696 // faster than result <- left, anl result,right
2697 // and better if result is SFR
2698 if (AOP_TYPE(left) == AOP_ACC)
2699 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2701 MOVA(aopGet(AOP(right),offset,FALSE));
2702 emitcode("xor","a,%s",
2703 aopGet(AOP(left),offset,FALSE));
2704 aopPut(AOP(result),"a",0);
2706 aopPut(AOP(result),"a",offset);
2711 freeAsmop(left,NULL,ic);
2712 freeAsmop(right,NULL,ic);
2713 freeAsmop(result,NULL,ic);
2716 /*-----------------------------------------------------------------*/
2717 /* genInline - write the inline code out */
2718 /*-----------------------------------------------------------------*/
2719 static void genInline (iCode *ic)
2721 char buffer[MAX_INLINEASM];
2725 inLine += (!options.asmpeep);
2726 strcpy(buffer,IC_INLINE(ic));
2728 /* emit each line as a code */
2747 /* emitcode("",buffer); */
2748 inLine -= (!options.asmpeep);
2751 /*-----------------------------------------------------------------*/
2752 /* genRRC - rotate right with carry */
2753 /*-----------------------------------------------------------------*/
2754 static void genRRC (iCode *ic)
2759 /*-----------------------------------------------------------------*/
2760 /* genRLC - generate code for rotate left with carry */
2761 /*-----------------------------------------------------------------*/
2762 static void genRLC (iCode *ic)
2767 /*-----------------------------------------------------------------*/
2768 /* shiftR2Left2Result - shift right two bytes from left to result */
2769 /*-----------------------------------------------------------------*/
2770 static void shiftR2Left2Result (operand *left, int offl,
2771 operand *result, int offr,
2772 int shCount, int sign)
2774 if(sameRegs(AOP(result), AOP(left)) &&
2775 ((offl + MSB16) == offr)){
2778 movLeft2Result(left, offl, result, offr, 0);
2779 movLeft2Result(left, offl+1, result, offr+1, 0);
2786 /* if (AOP(result)->type == AOP_REG) {*/
2789 symbol *tlbl , *tlbl1;
2792 /* Left is already in result - so now do the shift */
2794 emitcode("ld","a,#%u+1", shCount);
2795 tlbl = newiTempLabel(NULL);
2796 tlbl1 = newiTempLabel(NULL);
2797 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2798 emitcode("", LABEL_STR ":",tlbl->key+100);
2801 emitcode("or", "a,a");
2804 l = aopGet(AOP(result), --offset, FALSE);
2805 emitcode("rr","%s", l);
2808 emitcode("", LABEL_STR ":",tlbl1->key+100);
2809 emitcode("dec", "a");
2810 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2815 /*-----------------------------------------------------------------*/
2816 /* shiftL2Left2Result - shift left two bytes from left to result */
2817 /*-----------------------------------------------------------------*/
2818 static void shiftL2Left2Result (operand *left, int offl,
2819 operand *result, int offr, int shCount)
2821 if(sameRegs(AOP(result), AOP(left)) &&
2822 ((offl + MSB16) == offr)){
2825 /* Copy left into result */
2826 movLeft2Result(left, offl, result, offr, 0);
2827 movLeft2Result(left, offl+1, result, offr+1, 0);
2829 /* PENDING: for now just see if it'll work. */
2830 /*if (AOP(result)->type == AOP_REG) { */
2834 symbol *tlbl , *tlbl1;
2837 /* Left is already in result - so now do the shift */
2839 emitcode("ld","a,#%u+1", shCount);
2840 tlbl = newiTempLabel(NULL);
2841 tlbl1 = newiTempLabel(NULL);
2842 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2843 emitcode("", LABEL_STR ":",tlbl->key+100);
2846 emitcode("or", "a,a");
2848 l = aopGet(AOP(result),offset++,FALSE);
2849 emitcode("rl","%s", l);
2852 emitcode("", LABEL_STR ":",tlbl1->key+100);
2853 emitcode("dec", "a");
2854 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2859 /*-----------------------------------------------------------------*/
2860 /* AccRol - rotate left accumulator by known count */
2861 /*-----------------------------------------------------------------*/
2862 static void AccRol (int shCount)
2864 shCount &= 0x0007; // shCount : 0..7
2901 /*-----------------------------------------------------------------*/
2902 /* AccLsh - left shift accumulator by known count */
2903 /*-----------------------------------------------------------------*/
2904 static void AccLsh (int shCount)
2908 emitcode("add","a,a");
2911 emitcode("add","a,a");
2912 emitcode("add","a,a");
2914 /* rotate left accumulator */
2916 /* and kill the lower order bits */
2917 emitcode("and","a,#0x%02x", SLMask[shCount]);
2922 /*-----------------------------------------------------------------*/
2923 /* shiftL1Left2Result - shift left one byte from left to result */
2924 /*-----------------------------------------------------------------*/
2925 static void shiftL1Left2Result (operand *left, int offl,
2926 operand *result, int offr, int shCount)
2929 l = aopGet(AOP(left),offl,FALSE);
2931 /* shift left accumulator */
2933 aopPut(AOP(result),"a",offr);
2937 /*-----------------------------------------------------------------*/
2938 /* genlshTwo - left shift two bytes by known amount != 0 */
2939 /*-----------------------------------------------------------------*/
2940 static void genlshTwo (operand *result,operand *left, int shCount)
2942 int size = AOP_SIZE(result);
2946 /* if shCount >= 8 */
2952 movLeft2Result(left, LSB, result, MSB16, 0);
2953 aopPut(AOP(result),zero, 0);
2954 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2957 movLeft2Result(left, LSB, result, MSB16, 0);
2958 aopPut(AOP(result),zero, 0);
2961 aopPut(AOP(result),zero,LSB);
2963 /* 1 <= shCount <= 7 */
2969 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2974 /*-----------------------------------------------------------------*/
2975 /* genlshOne - left shift a one byte quantity by known count */
2976 /*-----------------------------------------------------------------*/
2977 static void genlshOne (operand *result, operand *left, int shCount)
2979 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2982 /*-----------------------------------------------------------------*/
2983 /* genLeftShiftLiteral - left shifting by known count */
2984 /*-----------------------------------------------------------------*/
2985 static void genLeftShiftLiteral (operand *left,
2990 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2993 freeAsmop(right,NULL,ic);
2995 aopOp(left,ic,FALSE);
2996 aopOp(result,ic,FALSE);
2998 size = getSize(operandType(result));
3001 emitcode("; shift left ","result %d, left %d",size,
3005 /* I suppose that the left size >= result size */
3010 else if(shCount >= (size * 8))
3012 aopPut(AOP(result),zero,size);
3016 genlshOne (result,left,shCount);
3019 genlshTwo (result,left,shCount);
3028 freeAsmop(left,NULL,ic);
3029 freeAsmop(result,NULL,ic);
3032 /*-----------------------------------------------------------------*/
3033 /* genLeftShift - generates code for left shifting */
3034 /*-----------------------------------------------------------------*/
3035 static void genLeftShift (iCode *ic)
3039 symbol *tlbl , *tlbl1;
3040 operand *left,*right, *result;
3042 right = IC_RIGHT(ic);
3044 result = IC_RESULT(ic);
3046 aopOp(right,ic,FALSE);
3048 /* if the shift count is known then do it
3049 as efficiently as possible */
3050 if (AOP_TYPE(right) == AOP_LIT) {
3051 genLeftShiftLiteral (left,right,result,ic);
3055 /* shift count is unknown then we have to form a loop get the loop
3056 count in B : Note: we take only the lower order byte since
3057 shifting more that 32 bits make no sense anyway, ( the largest
3058 size of an object can be only 32 bits ) */
3059 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3060 emitcode("inc","a");
3061 freeAsmop (right,NULL,ic);
3062 aopOp(left,ic,FALSE);
3063 aopOp(result,ic,FALSE);
3065 /* now move the left to the result if they are not the
3068 if (!sameRegs(AOP(left),AOP(result))) {
3070 size = AOP_SIZE(result);
3073 l = aopGet(AOP(left),offset,FALSE);
3074 aopPut(AOP(result),l,offset);
3079 size = AOP_SIZE(result);
3082 l = aopGet(AOP(left),offset,FALSE);
3083 aopPut(AOP(result),l,offset);
3089 tlbl = newiTempLabel(NULL);
3090 size = AOP_SIZE(result);
3092 tlbl1 = newiTempLabel(NULL);
3094 emitcode("jp", LABEL_STR ,tlbl1->key+100);
3095 emitcode("", LABEL_STR ":",tlbl->key+100);
3096 l = aopGet(AOP(result),offset,FALSE);
3097 emitcode("or", "a,a");
3099 l = aopGet(AOP(result),offset++,FALSE);
3100 emitcode("rl","%s", l);
3102 emitcode("", LABEL_STR ":",tlbl1->key+100);
3103 emitcode("dec", "a");
3104 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
3106 freeAsmop(left,NULL,ic);
3107 freeAsmop(result,NULL,ic);
3110 /* genlshTwo - left shift two bytes by known amount != 0 */
3111 /*-----------------------------------------------------------------*/
3112 static void genrshOne (operand *result,operand *left, int shCount)
3115 int size = AOP_SIZE(result);
3121 l = aopGet(AOP(left),0,FALSE);
3122 if (AOP(result)->type == AOP_REG) {
3123 aopPut(AOP(result), l, 0);
3124 l = aopGet(AOP(result), 0, FALSE);
3126 emitcode("srl", "%s", l);
3131 emitcode("srl", "a");
3133 aopPut(AOP(result),"a",0);
3137 /*-----------------------------------------------------------------*/
3138 /* AccRsh - right shift accumulator by known count */
3139 /*-----------------------------------------------------------------*/
3140 static void AccRsh (int shCount)
3147 /* rotate right accumulator */
3148 AccRol(8 - shCount);
3149 /* and kill the higher order bits */
3150 emitcode("and","a,#0x%02x", SRMask[shCount]);
3155 /*-----------------------------------------------------------------*/
3156 /* shiftR1Left2Result - shift right one byte from left to result */
3157 /*-----------------------------------------------------------------*/
3158 static void shiftR1Left2Result (operand *left, int offl,
3159 operand *result, int offr,
3160 int shCount, int sign)
3162 MOVA(aopGet(AOP(left),offl,FALSE));
3169 aopPut(AOP(result),"a",offr);
3172 /*-----------------------------------------------------------------*/
3173 /* genrshTwo - right shift two bytes by known amount != 0 */
3174 /*-----------------------------------------------------------------*/
3175 static void genrshTwo (operand *result,operand *left,
3176 int shCount, int sign)
3178 /* if shCount >= 8 */
3183 shiftR1Left2Result(left, MSB16, result, LSB,
3187 movLeft2Result(left, MSB16, result, LSB, sign);
3188 aopPut(AOP(result),zero,1);
3191 /* 1 <= shCount <= 7 */
3193 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3197 /*-----------------------------------------------------------------*/
3198 /* genRightShiftLiteral - left shifting by known count */
3199 /*-----------------------------------------------------------------*/
3200 static void genRightShiftLiteral (operand *left,
3205 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3208 freeAsmop(right,NULL,ic);
3210 aopOp(left,ic,FALSE);
3211 aopOp(result,ic,FALSE);
3213 size = getSize(operandType(result));
3215 emitcode("; shift right ","result %d, left %d",size,
3218 /* I suppose that the left size >= result size */
3223 else if(shCount >= (size * 8))
3225 aopPut(AOP(result),zero,size);
3229 genrshOne(result, left, shCount);
3232 /* PENDING: sign support */
3233 genrshTwo(result, left, shCount, FALSE);
3242 freeAsmop(left,NULL,ic);
3243 freeAsmop(result,NULL,ic);
3246 /*-----------------------------------------------------------------*/
3247 /* genRightShift - generate code for right shifting */
3248 /*-----------------------------------------------------------------*/
3249 static void genRightShift (iCode *ic)
3251 operand *left,*right, *result;
3253 right = IC_RIGHT(ic);
3255 result = IC_RESULT(ic);
3257 aopOp(right,ic,FALSE);
3259 /* if the shift count is known then do it
3260 as efficiently as possible */
3261 if (AOP_TYPE(right) == AOP_LIT) {
3262 genRightShiftLiteral (left,right,result,ic);
3270 /*-----------------------------------------------------------------*/
3271 /* genGenPointerGet - gget value from generic pointer space */
3272 /*-----------------------------------------------------------------*/
3273 static void genGenPointerGet (operand *left,
3274 operand *result, iCode *ic)
3277 link *retype = getSpec(operandType(result));
3279 aopOp(left,ic,FALSE);
3280 aopOp(result,ic,FALSE);
3282 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3284 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3285 aopPut(AOP(result),"a", 0);
3286 freeAsmop(left,NULL,ic);
3290 /* For now we always load into IY */
3291 /* if this is remateriazable */
3292 if (AOP_TYPE(left) == AOP_IMMD)
3293 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3294 else { /* we need to get it byte by byte */
3297 /* so iy now contains the address */
3298 freeAsmop(left,NULL,ic);
3300 /* if bit then unpack */
3301 if (IS_BITVAR(retype)) {
3305 size = AOP_SIZE(result);
3309 /* PENDING: make this better */
3310 if (AOP(result)->type == AOP_REG) {
3311 aopPut(AOP(result),"(hl)",offset++);
3314 emitcode("ld", "a,(hl)", offset);
3315 aopPut(AOP(result),"a",offset++);
3318 emitcode("inc", "hl");
3324 freeAsmop(result,NULL,ic);
3327 /*-----------------------------------------------------------------*/
3328 /* genPointerGet - generate code for pointer get */
3329 /*-----------------------------------------------------------------*/
3330 static void genPointerGet (iCode *ic)
3332 operand *left, *result ;
3336 result = IC_RESULT(ic) ;
3338 /* depending on the type of pointer we need to
3339 move it to the correct pointer register */
3340 type = operandType(left);
3341 etype = getSpec(type);
3343 genGenPointerGet (left,result,ic);
3346 bool isRegOrLit(asmop *aop)
3348 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3353 /*-----------------------------------------------------------------*/
3354 /* genGenPointerSet - stores the value into a pointer location */
3355 /*-----------------------------------------------------------------*/
3356 static void genGenPointerSet (operand *right,
3357 operand *result, iCode *ic)
3360 link *retype = getSpec(operandType(right));
3362 aopOp(result,ic,FALSE);
3363 aopOp(right,ic,FALSE);
3365 /* Handle the exceptions first */
3366 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3368 char *l = aopGet(AOP(right), 0, FALSE);
3370 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3371 freeAsmop(result,NULL,ic);
3375 /* if the operand is already in dptr
3376 then we do nothing else we move the value to dptr */
3377 if (AOP_TYPE(result) != AOP_STR) {
3378 /* if this is remateriazable */
3379 if (AOP_TYPE(result) == AOP_IMMD) {
3380 emitcode("", "; Error 2");
3381 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3383 else { /* we need to get it byte by byte */
3384 /* PENDING: do this better */
3385 fetchHL(AOP(result));
3388 /* so hl know contains the address */
3389 freeAsmop(result,NULL,ic);
3391 /* if bit then unpack */
3392 if (IS_BITVAR(retype)) {
3396 size = AOP_SIZE(right);
3400 char *l = aopGet(AOP(right),offset,FALSE);
3402 if (isRegOrLit(AOP(right))) {
3403 emitcode("ld", "(hl),%s", l);
3407 emitcode("ld", "(hl),a", offset);
3410 emitcode("inc", "hl");
3416 freeAsmop(right,NULL,ic);
3419 /*-----------------------------------------------------------------*/
3420 /* genPointerSet - stores the value into a pointer location */
3421 /*-----------------------------------------------------------------*/
3422 static void genPointerSet (iCode *ic)
3424 operand *right, *result ;
3427 right = IC_RIGHT(ic);
3428 result = IC_RESULT(ic) ;
3430 /* depending on the type of pointer we need to
3431 move it to the correct pointer register */
3432 type = operandType(result);
3433 etype = getSpec(type);
3435 genGenPointerSet (right,result,ic);
3438 /*-----------------------------------------------------------------*/
3439 /* genIfx - generate code for Ifx statement */
3440 /*-----------------------------------------------------------------*/
3441 static void genIfx (iCode *ic, iCode *popIc)
3443 operand *cond = IC_COND(ic);
3446 aopOp(cond,ic,FALSE);
3448 /* get the value into acc */
3449 if (AOP_TYPE(cond) != AOP_CRY)
3453 /* the result is now in the accumulator */
3454 freeAsmop(cond,NULL,ic);
3456 /* if there was something to be popped then do it */
3460 /* if the condition is a bit variable */
3461 if (isbit && IS_ITEMP(cond) &&
3463 genIfxJump(ic,SPIL_LOC(cond)->rname);
3465 if (isbit && !IS_ITEMP(cond))
3466 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3473 /*-----------------------------------------------------------------*/
3474 /* genAddrOf - generates code for address of */
3475 /*-----------------------------------------------------------------*/
3476 static void genAddrOf (iCode *ic)
3478 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3480 aopOp(IC_RESULT(ic),ic,FALSE);
3482 /* if the operand is on the stack then we
3483 need to get the stack offset of this
3486 /* if it has an offset then we need to compute it */
3488 emitcode("lda", "hl,%d(sp)", sym->stack);
3489 emitcode("ld", "d,h");
3490 emitcode("ld", "e,l");
3491 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3492 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3496 emitcode("push", "de");
3497 emitcode("push", "ix");
3498 emitcode("pop", "hl");
3499 emitcode("ld", "de,#%d", sym->stack);
3500 emitcode("add", "hl,de");
3501 emitcode("pop", "de");
3505 emitcode("ld", "hl,#%s", sym->rname);
3507 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3508 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3510 freeAsmop(IC_RESULT(ic),NULL,ic);
3513 /*-----------------------------------------------------------------*/
3514 /* genAssign - generate code for assignment */
3515 /*-----------------------------------------------------------------*/
3516 static void genAssign (iCode *ic)
3518 operand *result, *right;
3520 unsigned long lit = 0L;
3522 result = IC_RESULT(ic);
3523 right = IC_RIGHT(ic) ;
3526 /* Dont bother assigning if they are the same */
3527 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3528 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3533 aopOp(right,ic,FALSE);
3534 aopOp(result,ic,TRUE);
3536 /* if they are the same registers */
3537 if (sameRegs(AOP(right),AOP(result))) {
3538 emitcode("", "; (registers are the same)");
3542 /* if the result is a bit */
3543 if (AOP_TYPE(result) == AOP_CRY) {
3548 size = AOP_SIZE(result);
3551 if(AOP_TYPE(right) == AOP_LIT)
3552 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3554 (AOP_TYPE(result) != AOP_REG) &&
3555 (AOP_TYPE(right) == AOP_LIT) &&
3556 !IS_FLOAT(operandType(right)) &&
3558 bool fXored = FALSE;
3560 /* Work from the top down.
3561 Done this way so that we can use the cached copy of 0
3562 in A for a fast clear */
3564 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3565 if (!fXored && size>1) {
3566 emitcode("xor", "a,a");
3570 aopPut(AOP(result),"a",offset);
3573 aopPut(AOP(result), "#0", offset);
3578 aopGet(AOP(right),offset,FALSE),
3585 aopGet(AOP(right),offset,FALSE),
3592 freeAsmop(right,NULL,ic);
3593 freeAsmop(result,NULL,ic);
3596 /*-----------------------------------------------------------------*/
3597 /* genJumpTab - genrates code for jump table */
3598 /*-----------------------------------------------------------------*/
3599 static void genJumpTab (iCode *ic)
3604 aopOp(IC_JTCOND(ic),ic,FALSE);
3605 /* get the condition into accumulator */
3606 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3609 emitcode("push", "de");
3610 emitcode("ld", "e,%s", l);
3611 emitcode("ld", "d,#0");
3612 jtab = newiTempLabel(NULL);
3613 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3614 emitcode("add", "hl,de");
3615 emitcode("add", "hl,de");
3616 freeAsmop(IC_JTCOND(ic),NULL,ic);
3618 emitcode("pop", "de");
3619 emitcode("jp", "(hl)");
3620 emitcode("","%05d$:",jtab->key+100);
3621 /* now generate the jump labels */
3622 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3623 jtab = setNextItem(IC_JTLABELS(ic)))
3624 emitcode("jp", LABEL_STR, jtab->key+100);
3627 /*-----------------------------------------------------------------*/
3628 /* genCast - gen code for casting */
3629 /*-----------------------------------------------------------------*/
3630 static void genCast (iCode *ic)
3632 operand *result = IC_RESULT(ic);
3633 link *ctype = operandType(IC_LEFT(ic));
3634 operand *right = IC_RIGHT(ic);
3637 /* if they are equivalent then do nothing */
3638 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3641 aopOp(right,ic,FALSE) ;
3642 aopOp(result,ic,FALSE);
3644 /* if the result is a bit */
3645 if (AOP_TYPE(result) == AOP_CRY) {
3649 /* if they are the same size : or less */
3650 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3652 /* if they are in the same place */
3653 if (sameRegs(AOP(right),AOP(result)))
3656 /* if they in different places then copy */
3657 size = AOP_SIZE(result);
3661 aopGet(AOP(right),offset,FALSE),
3668 /* PENDING: should be OK. */
3670 /* if the result is of type pointer */
3671 if (IS_PTR(ctype)) {
3676 /* so we now know that the size of destination is greater
3677 than the size of the source */
3678 /* we move to result for the size of source */
3679 size = AOP_SIZE(right);
3683 aopGet(AOP(right),offset,FALSE),
3688 /* now depending on the sign of the destination */
3689 size = AOP_SIZE(result) - AOP_SIZE(right);
3690 /* Unsigned or not an integral type - right fill with zeros */
3691 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3693 aopPut(AOP(result),zero,offset++);
3695 /* we need to extend the sign :{ */
3696 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3699 emitcode("", "; genCast: sign extend untested.");
3700 emitcode("rla", "");
3701 emitcode("sbc", "a,a");
3703 aopPut(AOP(result),"a",offset++);
3707 freeAsmop(right, NULL, ic);
3708 freeAsmop(result, NULL, ic);
3711 /*-----------------------------------------------------------------*/
3712 /* genReceive - generate code for a receive iCode */
3713 /*-----------------------------------------------------------------*/
3714 static void genReceive (iCode *ic)
3716 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3717 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3718 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3722 aopOp(IC_RESULT(ic),ic,FALSE);
3724 assignResultValue(IC_RESULT(ic));
3727 freeAsmop(IC_RESULT(ic),NULL,ic);
3730 /*-----------------------------------------------------------------*/
3731 /* genZ80Code - generate code for Z80 based controllers */
3732 /*-----------------------------------------------------------------*/
3733 void genZ80Code (iCode *lic)
3740 _fReturn = _gbz80_return;
3741 _fTmp = _gbz80_return;
3744 _fReturn = _z80_return;
3745 _fTmp = _z80_return;
3748 lineHead = lineCurr = NULL;
3750 /* if debug information required */
3751 if (options.debug && currFunc) {
3752 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3754 if (IS_STATIC(currFunc->etype))
3755 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3757 emitcode("","G$%s$0$0 ==.",currFunc->name);
3760 /* stack pointer name */
3764 for (ic = lic ; ic ; ic = ic->next ) {
3766 if ( cln != ic->lineno ) {
3767 if ( options.debug ) {
3769 emitcode("","C$%s$%d$%d$%d ==.",
3770 ic->filename,ic->lineno,
3771 ic->level,ic->block);
3774 emitcode(";","%s %d",ic->filename,ic->lineno);
3777 /* if the result is marked as
3778 spilt and rematerializable or code for
3779 this has already been generated then
3781 if (resultRemat(ic) || ic->generated )
3784 /* depending on the operation */
3787 emitcode("", "; genNot");
3792 emitcode("", "; genCpl");
3797 emitcode("", "; genUminus");
3802 emitcode("", "; genIpush");
3807 /* IPOP happens only when trying to restore a
3808 spilt live range, if there is an ifx statement
3809 following this pop then the if statement might
3810 be using some of the registers being popped which
3811 would destory the contents of the register so
3812 we need to check for this condition and handle it */
3814 ic->next->op == IFX &&
3815 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3816 emitcode("", "; genIfx");
3817 genIfx (ic->next,ic);
3820 emitcode("", "; genIpop");
3826 emitcode("", "; genCall");
3831 emitcode("", "; genPcall");
3836 emitcode("", "; genFunction");
3841 emitcode("", "; genEndFunction");
3842 genEndFunction (ic);
3846 emitcode("", "; genRet");
3851 emitcode("", "; genLabel");
3856 emitcode("", "; genGoto");
3861 emitcode("", "; genPlus");
3866 emitcode("", "; genMinus");
3871 emitcode("", "; genMult");
3876 emitcode("", "; genDiv");
3881 emitcode("", "; genMod");
3886 emitcode("", "; genCmpGt");
3887 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3891 emitcode("", "; genCmpLt");
3892 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3899 /* note these two are xlated by algebraic equivalence
3900 during parsing SDCC.y */
3901 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3902 "got '>=' or '<=' shouldn't have come here");
3906 emitcode("", "; genCmpEq");
3907 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3911 emitcode("", "; genAndOp");
3916 emitcode("", "; genOrOp");
3921 emitcode("", "; genXor");
3922 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3926 emitcode("", "; genOr");
3927 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3931 emitcode("", "; genAnd");
3932 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3936 emitcode("", "; genInline");
3941 emitcode("", "; genRRC");
3946 emitcode("", "; genRLC");
3951 emitcode("", "; genHBIT");
3955 emitcode("", "; genLeftShift");
3960 emitcode("", "; genRightShift");
3964 case GET_VALUE_AT_ADDRESS:
3965 emitcode("", "; genPointerGet");
3971 if (POINTER_SET(ic)) {
3972 emitcode("", "; genAssign (pointer)");
3976 emitcode("", "; genAssign");
3982 emitcode("", "; genIfx");
3987 emitcode("", "; genAddrOf");
3992 emitcode("", "; genJumpTab");
3997 emitcode("", "; genCast");
4002 emitcode("", "; genReceive");
4007 emitcode("", "; addSet");
4008 addSet(&sendSet,ic);
4013 /* piCode(ic,stdout); */
4019 /* now we are ready to call the
4020 peep hole optimizer */
4021 if (!options.nopeep)
4022 peepHole (&lineHead);
4024 /* now do the actual printing */
4025 printLine (lineHead,codeOutFile);