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);
254 /* if it is in direct space */
255 if (IN_DIRSPACE(space)) {
256 sym->aop = aop = newAsmop (AOP_DIR);
257 aop->aopu.aop_dir = sym->rname ;
258 aop->size = getSize(sym->type);
259 emitcode("", "; AOP_DIR for %s", sym->rname);
265 /* only remaining is far space */
266 /* in which case DPTR gets the address */
268 sym->aop = aop = newAsmop(AOP_HL);
270 sym->aop = aop = newAsmop(AOP_IY);
271 emitcode ("ld","iy,#%s ; a", sym->rname);
273 aop->size = getSize(sym->type);
274 aop->aopu.aop_dir = sym->rname;
276 /* if it is in code space */
277 if (IN_CODESPACE(space))
283 /*-----------------------------------------------------------------*/
284 /* aopForRemat - rematerialzes an object */
285 /*-----------------------------------------------------------------*/
286 static asmop *aopForRemat (symbol *sym)
289 iCode *ic = sym->rematiCode;
290 asmop *aop = newAsmop(AOP_IMMD);
293 /* if plus or minus print the right hand side */
294 if (ic->op == '+' || ic->op == '-') {
295 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
298 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
301 /* we reached the end */
302 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
306 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
307 strcpy(aop->aopu.aop_immd,buffer);
311 /*-----------------------------------------------------------------*/
312 /* regsInCommon - two operands have some registers in common */
313 /*-----------------------------------------------------------------*/
314 bool regsInCommon (operand *op1, operand *op2)
319 /* if they have registers in common */
320 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
323 sym1 = OP_SYMBOL(op1);
324 sym2 = OP_SYMBOL(op2);
326 if (sym1->nRegs == 0 || sym2->nRegs == 0)
329 for (i = 0 ; i < sym1->nRegs ; i++) {
334 for (j = 0 ; j < sym2->nRegs ;j++ ) {
338 if (sym2->regs[j] == sym1->regs[i])
346 /*-----------------------------------------------------------------*/
347 /* operandsEqu - equivalent */
348 /*-----------------------------------------------------------------*/
349 bool operandsEqu ( operand *op1, operand *op2)
353 /* if they not symbols */
354 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
357 sym1 = OP_SYMBOL(op1);
358 sym2 = OP_SYMBOL(op2);
360 /* if both are itemps & one is spilt
361 and the other is not then false */
362 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
363 sym1->isspilt != sym2->isspilt )
366 /* if they are the same */
370 if (strcmp(sym1->rname,sym2->rname) == 0)
374 /* if left is a tmp & right is not */
378 (sym1->usl.spillLoc == sym2))
385 (sym2->usl.spillLoc == sym1))
391 /*-----------------------------------------------------------------*/
392 /* sameRegs - two asmops have the same registers */
393 /*-----------------------------------------------------------------*/
394 bool sameRegs (asmop *aop1, asmop *aop2 )
401 if (aop1->type != AOP_REG ||
402 aop2->type != AOP_REG )
405 if (aop1->size != aop2->size)
408 for (i = 0 ; i < aop1->size ; i++ )
409 if (aop1->aopu.aop_reg[i] !=
410 aop2->aopu.aop_reg[i] )
416 /*-----------------------------------------------------------------*/
417 /* aopOp - allocates an asmop for an operand : */
418 /*-----------------------------------------------------------------*/
419 static void aopOp (operand *op, iCode *ic, bool result)
428 /* if this a literal */
429 if (IS_OP_LITERAL(op)) {
430 op->aop = aop = newAsmop(AOP_LIT);
431 aop->aopu.aop_lit = op->operand.valOperand;
432 aop->size = getSize(operandType(op));
436 /* if already has a asmop then continue */
440 /* if the underlying symbol has a aop */
441 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
442 op->aop = OP_SYMBOL(op)->aop;
446 /* if this is a true symbol */
447 if (IS_TRUE_SYMOP(op)) {
448 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
452 /* this is a temporary : this has
458 e) can be a return use only */
462 /* if the type is a conditional */
463 if (sym->regType == REG_CND) {
464 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
469 /* if it is spilt then two situations
471 b) has a spill location */
472 if (sym->isspilt || sym->nRegs == 0) {
473 /* rematerialize it NOW */
475 sym->aop = op->aop = aop =
477 aop->size = getSize(sym->type);
483 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
484 aop->size = getSize(sym->type);
485 for ( i = 0 ; i < 2 ; i++ )
486 aop->aopu.aop_str[i] = accUse[i];
492 aop = op->aop = sym->aop = newAsmop(AOP_STR);
493 aop->size = getSize(sym->type);
494 for ( i = 0 ; i < 4 ; i++ )
495 aop->aopu.aop_str[i] = _fReturn[i];
499 /* else spill location */
500 sym->aop = op->aop = aop =
501 aopForSym(ic,sym->usl.spillLoc,result);
502 aop->size = getSize(sym->type);
506 /* must be in a register */
507 sym->aop = op->aop = aop = newAsmop(AOP_REG);
508 aop->size = sym->nRegs;
509 for ( i = 0 ; i < sym->nRegs ;i++)
510 aop->aopu.aop_reg[i] = sym->regs[i];
513 /*-----------------------------------------------------------------*/
514 /* freeAsmop - free up the asmop given to an operand */
515 /*----------------------------------------------------------------*/
516 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
539 /* all other cases just dealloc */
543 OP_SYMBOL(op)->aop = NULL;
544 /* if the symbol has a spill */
546 SPIL_LOC(op)->aop = NULL;
551 char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
560 /* depending on type */
563 sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
564 ALLOC_ATOMIC(rs,strlen(s)+1);
569 value * val = aop->aopu.aop_lit;
570 /* if it is a float then it gets tricky */
571 /* otherwise it is fairly simple */
572 if (!IS_FLOAT(val->type)) {
573 unsigned long v = floatFromVal(val);
575 sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
576 ALLOC_ATOMIC(rs,strlen(buffer)+1);
577 return strcpy (rs,buffer);
586 char *aopGetWord(asmop *aop, int offset)
588 return aopGetWordLong(aop, offset, TRUE);
591 /*-----------------------------------------------------------------*/
592 /* aopGet - for fetching value of the aop */
593 /*-----------------------------------------------------------------*/
594 static char *aopGet (asmop *aop, int offset, bool bit16)
599 /* offset is greater than size then zero */
600 if (offset > (aop->size - 1) &&
601 aop->type != AOP_LIT)
604 /* depending on type */
608 sprintf (s,"#%s",aop->aopu.aop_immd);
618 ALLOC_ATOMIC(rs,strlen(s)+1);
624 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
626 ALLOC_ATOMIC(rs,strlen(s)+1);
631 return aop->aopu.aop_reg[offset]->name;
634 emitcode("ld", "hl,#%s+%d", aop->aopu.aop_dir, offset);
636 ALLOC_ATOMIC(rs, strlen(s)+1);
641 sprintf(s,"%d(iy)", offset);
642 ALLOC_ATOMIC(rs,strlen(s)+1);
648 /* We cant really optimise this as we cant afford to
651 emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
655 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
657 ALLOC_ATOMIC(rs,strlen(s)+1);
671 return aopLiteral (aop->aopu.aop_lit,offset);
675 return aop->aopu.aop_str[offset];
678 fprintf(stderr, "Type %u\n", aop->type);
680 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
681 "aopget got unsupported aop->type");
685 bool isRegString(char *s)
687 if (!strcmp(s, "b") ||
698 bool isConstant(char *s)
703 bool canAssignToPtr(char *s)
712 /*-----------------------------------------------------------------*/
713 /* aopPut - puts a string for a aop */
714 /*-----------------------------------------------------------------*/
715 static void aopPut (asmop *aop, char *s, int offset)
717 if (aop->size && offset > ( aop->size - 1)) {
718 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
719 "aopPut got offset > aop->size");
723 /* will assign value to value */
724 /* depending on where it is ofcourse */
729 emitcode("ld", "a,%s", s);
730 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
734 /* Dont bother if it's a ld x,x */
735 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
736 emitcode("ld","%s,%s",
737 aop->aopu.aop_reg[offset]->name,s);
743 if (!canAssignToPtr(s)) {
744 emitcode("ld", "a,%s", s);
745 emitcode("ld", "%d(iy),a", offset);
748 emitcode("ld", "%d(iy),%s", offset, s);
753 if (!strcmp(s, "(hl)")) {
754 emitcode("ld", "a,(hl)");
757 emitcode("ld", "hl,#%s+%d", aop->aopu.aop_dir, offset);
758 emitcode("ld", "(hl),%s", s);
763 if (!strcmp("(hl)", s)) {
764 emitcode("ld", "a,(hl)");
767 emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
768 if (!canAssignToPtr(s)) {
769 emitcode("ld", "a,%s", s);
770 emitcode("ld", "(hl),a");
773 emitcode("ld", "(hl),%s", s);
776 if (!canAssignToPtr(s)) {
777 emitcode("ld", "a,%s", s);
778 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
781 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
786 /* if bit variable */
787 if (!aop->aopu.aop_dir) {
788 emitcode("ld", "a,#0");
791 /* In bit space but not in C - cant happen */
798 if (strcmp(aop->aopu.aop_str[offset],s)) {
799 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
805 if (!offset && (strcmp(s,"acc") == 0))
809 emitcode("", "; Error aopPut AOP_ACC");
812 if (strcmp(aop->aopu.aop_str[offset],s))
813 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
818 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
819 "aopPut got unsupported aop->type");
824 #define AOP(op) op->aop
825 #define AOP_TYPE(op) AOP(op)->type
826 #define AOP_SIZE(op) AOP(op)->size
827 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
829 /*-----------------------------------------------------------------*/
830 /* getDataSize - get the operand data size */
831 /*-----------------------------------------------------------------*/
832 int getDataSize(operand *op)
843 /*-----------------------------------------------------------------*/
844 /* movLeft2Result - move byte from left to result */
845 /*-----------------------------------------------------------------*/
846 static void movLeft2Result (operand *left, int offl,
847 operand *result, int offr, int sign)
850 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
851 l = aopGet(AOP(left),offl,FALSE);
854 aopPut(AOP(result),l,offr);
863 /** Put Acc into a register set
865 void outAcc(operand *result)
868 size = getDataSize(result);
870 aopPut(AOP(result),"a",0);
873 /* unsigned or positive */
875 aopPut(AOP(result),zero,offset++);
880 /** Take the value in carry and put it into a register
882 void outBitC(operand *result)
884 /* if the result is bit */
885 if (AOP_TYPE(result) == AOP_CRY) {
886 emitcode("", "; Note: outBitC form 1");
887 aopPut(AOP(result),"blah",0);
890 emitcode("ld", "a,#0");
896 /*-----------------------------------------------------------------*/
897 /* toBoolean - emit code for orl a,operator(sizeop) */
898 /*-----------------------------------------------------------------*/
899 void toBoolean(operand *oper)
901 int size = AOP_SIZE(oper);
904 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
907 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
910 if (AOP(oper)->type != AOP_ACC) {
912 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
917 /*-----------------------------------------------------------------*/
918 /* genNot - generate code for ! operation */
919 /*-----------------------------------------------------------------*/
920 static void genNot (iCode *ic)
922 link *optype = operandType(IC_LEFT(ic));
924 /* assign asmOps to operand & result */
925 aopOp (IC_LEFT(ic),ic,FALSE);
926 aopOp (IC_RESULT(ic),ic,TRUE);
928 /* if in bit space then a special case */
929 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
933 /* if type float then do float */
934 if (IS_FLOAT(optype)) {
938 toBoolean(IC_LEFT(ic));
943 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
944 emitcode("sub", "a,#0x01");
945 outBitC(IC_RESULT(ic));
947 /* release the aops */
948 freeAsmop(IC_LEFT(ic),NULL,ic);
949 freeAsmop(IC_RESULT(ic),NULL,ic);
952 /*-----------------------------------------------------------------*/
953 /* genCpl - generate code for complement */
954 /*-----------------------------------------------------------------*/
955 static void genCpl (iCode *ic)
961 /* assign asmOps to operand & result */
962 aopOp (IC_LEFT(ic),ic,FALSE);
963 aopOp (IC_RESULT(ic),ic,TRUE);
965 /* if both are in bit space then
967 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
968 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
972 size = AOP_SIZE(IC_RESULT(ic));
974 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
977 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
980 /* release the aops */
981 freeAsmop(IC_LEFT(ic),NULL,ic);
982 freeAsmop(IC_RESULT(ic),NULL,ic);
985 /*-----------------------------------------------------------------*/
986 /* genUminus - unary minus code generation */
987 /*-----------------------------------------------------------------*/
988 static void genUminus (iCode *ic)
991 link *optype, *rtype;
994 aopOp(IC_LEFT(ic),ic,FALSE);
995 aopOp(IC_RESULT(ic),ic,TRUE);
997 /* if both in bit space then special
999 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1000 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1005 optype = operandType(IC_LEFT(ic));
1006 rtype = operandType(IC_RESULT(ic));
1008 /* if float then do float stuff */
1009 if (IS_FLOAT(optype)) {
1014 /* otherwise subtract from zero */
1015 size = AOP_SIZE(IC_LEFT(ic));
1019 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1020 emitcode("ld", "a,#0");
1021 emitcode("sbc","a,%s",l);
1022 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1025 /* if any remaining bytes in the result */
1026 /* we just need to propagate the sign */
1027 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1028 emitcode("rlc","a");
1029 emitcode("sbc","a,a");
1031 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1035 /* release the aops */
1036 freeAsmop(IC_LEFT(ic),NULL,ic);
1037 freeAsmop(IC_RESULT(ic),NULL,ic);
1040 static bool requiresHL(asmop *aop)
1042 switch (aop->type) {
1052 /*-----------------------------------------------------------------*/
1053 /* assignResultValue - */
1054 /*-----------------------------------------------------------------*/
1055 void assignResultValue(operand * oper)
1058 int size = AOP_SIZE(oper);
1063 aopPut(AOP(oper),_fReturn[offset],offset);
1068 static void fetchHL(asmop *aop)
1070 if (IS_GB && requiresHL(aop)) {
1071 aopGet(aop, 0, FALSE);
1072 emitcode("ld", "a,(hl+)");
1073 emitcode("ld", "h,(hl)");
1074 emitcode("ld", "l,a");
1077 emitcode("ld", "l,%s", aopGet(aop, 0, FALSE));
1078 emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
1082 /*-----------------------------------------------------------------*/
1083 /* genIpush - genrate code for pushing this gets a little complex */
1084 /*-----------------------------------------------------------------*/
1085 static void genIpush (iCode *ic)
1087 int size, offset = 0 ;
1091 /* if this is not a parm push : ie. it is spill push
1092 and spill push is always done on the local stack */
1093 if (!ic->parmPush) {
1094 /* and the item is spilt then do nothing */
1095 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1098 aopOp(IC_LEFT(ic),ic,FALSE);
1099 size = AOP_SIZE(IC_LEFT(ic));
1100 /* push it on the stack */
1101 if (isPair(AOP(IC_LEFT(ic)))) {
1102 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1108 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1109 /* Simple for now - load into A and PUSH AF */
1110 emitcode("ld", "a,%s", l);
1111 emitcode("push", "af");
1112 emitcode("inc", "sp");
1119 /* Hmmm... what about saving the currently used registers
1122 /* then do the push */
1123 aopOp(IC_LEFT(ic),ic,FALSE);
1125 size = AOP_SIZE(IC_LEFT(ic));
1127 if (isPair(AOP(IC_LEFT(ic)))) {
1129 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1133 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1135 emitcode("ld", "hl,%s", s);
1136 emitcode("push", "hl");
1140 /* Optimise here - load into HL then push HL */
1141 fetchHL(AOP(IC_LEFT(ic)));
1142 emitcode("push", "hl");
1149 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1150 emitcode("ld", "a,%s", l);
1151 emitcode("push", "af");
1152 emitcode("inc", "sp");
1157 freeAsmop(IC_LEFT(ic),NULL,ic);
1160 /*-----------------------------------------------------------------*/
1161 /* genIpop - recover the registers: can happen only for spilling */
1162 /*-----------------------------------------------------------------*/
1163 static void genIpop (iCode *ic)
1168 /* if the temp was not pushed then */
1169 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1172 aopOp(IC_LEFT(ic),ic,FALSE);
1173 size = AOP_SIZE(IC_LEFT(ic));
1175 if (isPair(AOP(IC_LEFT(ic)))) {
1176 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1180 emitcode("dec", "sp");
1181 emitcode("pop", "hl");
1182 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1186 freeAsmop(IC_LEFT(ic),NULL,ic);
1189 /** Emit the code for a call statement
1191 static void emitCall (iCode *ic, bool ispcall)
1193 /* if caller saves & we have not saved then */
1194 if (!ic->regsSaved) {
1198 /* if send set is not empty then assign */
1201 for (sic = setFirstItem(sendSet) ; sic ;
1202 sic = setNextItem(sendSet)) {
1203 int size, offset = 0;
1204 aopOp(IC_LEFT(sic),sic,FALSE);
1205 size = AOP_SIZE(IC_LEFT(sic));
1207 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1209 if (strcmp(l, _fReturn[offset]))
1210 emitcode("ld","%s,%s",
1215 freeAsmop (IC_LEFT(sic),NULL,sic);
1221 symbol *rlbl = newiTempLabel(NULL);
1223 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1224 emitcode("push", "hl");
1227 aopOp(IC_LEFT(ic),ic,FALSE);
1228 fetchHL(AOP(IC_LEFT(ic)));
1229 freeAsmop(IC_LEFT(ic),NULL,ic);
1231 emitcode("jp", "(hl)");
1232 emitcode("","%05d$:",(rlbl->key+100));
1237 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1238 OP_SYMBOL(IC_LEFT(ic))->rname :
1239 OP_SYMBOL(IC_LEFT(ic))->name;
1240 emitcode("call", "%s", name);
1243 /* if we need assign a result value */
1244 if ((IS_ITEMP(IC_RESULT(ic)) &&
1245 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1246 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1247 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1250 aopOp(IC_RESULT(ic),ic,FALSE);
1253 assignResultValue(IC_RESULT(ic));
1255 freeAsmop(IC_RESULT(ic),NULL, ic);
1258 /* adjust the stack for parameters if required */
1259 if (IC_LEFT(ic)->parmBytes) {
1260 int i = IC_LEFT(ic)->parmBytes;
1263 emitcode("ld", "hl,#%d", i);
1264 emitcode("add", "hl,sp");
1265 emitcode("ld", "sp,hl");
1269 emitcode("pop", "hl");
1273 emitcode("inc", "sp");
1279 /*-----------------------------------------------------------------*/
1280 /* genCall - generates a call statement */
1281 /*-----------------------------------------------------------------*/
1282 static void genCall (iCode *ic)
1284 emitCall(ic, FALSE);
1287 /*-----------------------------------------------------------------*/
1288 /* genPcall - generates a call by pointer statement */
1289 /*-----------------------------------------------------------------*/
1290 static void genPcall (iCode *ic)
1295 /*-----------------------------------------------------------------*/
1296 /* resultRemat - result is rematerializable */
1297 /*-----------------------------------------------------------------*/
1298 static int resultRemat (iCode *ic)
1300 if (SKIP_IC(ic) || ic->op == IFX)
1303 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1304 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1305 if (sym->remat && !POINTER_SET(ic))
1312 /*-----------------------------------------------------------------*/
1313 /* genFunction - generated code for function entry */
1314 /*-----------------------------------------------------------------*/
1315 static void genFunction (iCode *ic)
1321 /* create the function header */
1322 emitcode(";","-----------------------------------------");
1323 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1324 emitcode(";","-----------------------------------------");
1326 emitcode("","%s:",sym->rname);
1327 fetype = getSpec(operandType(IC_LEFT(ic)));
1329 /* if critical function then turn interrupts off */
1330 if (SPEC_CRTCL(fetype))
1333 /* if this is an interrupt service routine then
1334 save acc, b, dpl, dph */
1335 if (IS_ISR(sym->etype)) {
1336 emitcode("push", "af");
1337 emitcode("push", "bc");
1338 emitcode("push", "de");
1339 emitcode("push", "hl");
1341 /* PENDING: callee-save etc */
1343 /* adjust the stack for the function */
1344 emitcode("push", "bc");
1346 emitcode("push", "de");
1347 emitcode("push", "ix");
1348 emitcode("ld", "ix,#0");
1349 emitcode("add", "ix,sp");
1352 _lastStack = sym->stack;
1355 emitcode("ld", "hl,#-%d", sym->stack);
1356 emitcode("add", "hl,sp");
1357 emitcode("ld", "sp,hl");
1359 _spoffset = sym->stack;
1362 /*-----------------------------------------------------------------*/
1363 /* genEndFunction - generates epilogue for functions */
1364 /*-----------------------------------------------------------------*/
1365 static void genEndFunction (iCode *ic)
1367 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1369 if (IS_ISR(sym->etype)) {
1373 if (SPEC_CRTCL(sym->etype))
1376 /* PENDING: calleeSave */
1378 /* if debug then send end of function */
1379 if (options.debug && currFunc) {
1381 emitcode("","C$%s$%d$%d$%d ==.",
1382 ic->filename,currFunc->lastLine,
1383 ic->level,ic->block);
1384 if (IS_STATIC(currFunc->etype))
1385 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1387 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1391 emitcode("ld", "sp,ix");
1392 emitcode("pop", "ix");
1393 emitcode("pop", "de");
1397 emitcode("ld", "hl,#%d", _spoffset);
1398 emitcode("add", "hl,sp");
1399 emitcode("ld", "sp,hl");
1402 emitcode("pop", "bc");
1403 emitcode("ret", "");
1409 /*-----------------------------------------------------------------*/
1410 /* genRet - generate code for return statement */
1411 /*-----------------------------------------------------------------*/
1412 static void genRet (iCode *ic)
1415 /* Errk. This is a hack until I can figure out how
1416 to cause dehl to spill on a call */
1417 int size,offset = 0;
1419 /* if we have no return value then
1420 just generate the "ret" */
1424 /* we have something to return then
1425 move the return value into place */
1426 aopOp(IC_LEFT(ic),ic,FALSE);
1427 size = AOP_SIZE(IC_LEFT(ic));
1429 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1431 emitcode("ld", "de,%s", l);
1434 emitcode("ld", "hl,%s", l);
1439 l = aopGet(AOP(IC_LEFT(ic)),offset,
1441 if (strcmp(_fReturn[offset],l))
1442 emitcode("ld","%s,%s", _fReturn[offset++],l);
1445 freeAsmop (IC_LEFT(ic),NULL,ic);
1448 /* generate a jump to the return label
1449 if the next is not the return statement */
1450 if (!(ic->next && ic->next->op == LABEL &&
1451 IC_LABEL(ic->next) == returnLabel))
1453 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1456 /*-----------------------------------------------------------------*/
1457 /* genLabel - generates a label */
1458 /*-----------------------------------------------------------------*/
1459 static void genLabel (iCode *ic)
1461 /* special case never generate */
1462 if (IC_LABEL(ic) == entryLabel)
1465 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1468 /*-----------------------------------------------------------------*/
1469 /* genGoto - generates a ljmp */
1470 /*-----------------------------------------------------------------*/
1471 static void genGoto (iCode *ic)
1473 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1476 /*-----------------------------------------------------------------*/
1477 /* genPlusIncr :- does addition with increment if possible */
1478 /*-----------------------------------------------------------------*/
1479 static bool genPlusIncr (iCode *ic)
1481 unsigned int icount ;
1482 unsigned int size = getDataSize(IC_RESULT(ic));
1484 /* will try to generate an increment */
1485 /* if the right side is not a literal
1487 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1490 emitcode("", "; genPlusIncr");
1492 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1494 /* If result is a pair */
1495 if (isPair(AOP(IC_RESULT(ic)))) {
1496 char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1498 /* Both a lit on the right and a true symbol on the left */
1499 emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
1504 /* if the literal value of the right hand side
1505 is greater than 4 then it is not worth it */
1510 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1511 isPair(AOP(IC_RESULT(ic)))) {
1513 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1517 /* if increment 16 bits in register */
1518 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1521 symbol *tlbl = newiTempLabel(NULL);
1522 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1523 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1525 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1529 emitcode("", LABEL_STR ":",tlbl->key+100);
1533 /* If result is a pair */
1534 if (isPair(AOP(IC_RESULT(ic)))) {
1535 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1536 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1538 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1542 /* if the sizes are greater than 1 then we cannot */
1543 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1544 AOP_SIZE(IC_LEFT(ic)) > 1 )
1547 /* we can if the aops of the left & result match or
1548 if they are in registers and the registers are the
1550 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1552 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1560 /*-----------------------------------------------------------------*/
1561 /* outBitAcc - output a bit in acc */
1562 /*-----------------------------------------------------------------*/
1563 void outBitAcc(operand *result)
1565 symbol *tlbl = newiTempLabel(NULL);
1566 /* if the result is a bit */
1567 if (AOP_TYPE(result) == AOP_CRY){
1571 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1572 emitcode("ld","a,%s",one);
1573 emitcode("", LABEL_STR ":",tlbl->key+100);
1578 /*-----------------------------------------------------------------*/
1579 /* genPlus - generates code for addition */
1580 /*-----------------------------------------------------------------*/
1581 static void genPlus (iCode *ic)
1583 int size, offset = 0;
1585 /* special cases :- */
1587 aopOp (IC_LEFT(ic),ic,FALSE);
1588 aopOp (IC_RIGHT(ic),ic,FALSE);
1589 aopOp (IC_RESULT(ic),ic,TRUE);
1591 /* Swap the left and right operands if:
1593 if literal, literal on the right or
1594 if left requires ACC or right is already
1597 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1598 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1599 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1600 operand *t = IC_RIGHT(ic);
1601 IC_RIGHT(ic) = IC_LEFT(ic);
1605 /* if both left & right are in bit
1607 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1608 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1613 /* if left in bit space & right literal */
1614 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1615 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1616 /* Can happen I guess */
1620 /* if I can do an increment instead
1621 of add then GOOD for ME */
1622 if (genPlusIncr (ic) == TRUE)
1625 size = getDataSize(IC_RESULT(ic));
1627 /* Special case when left and right are constant */
1628 if (isPair(AOP(IC_RESULT(ic)))) {
1631 left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1632 right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1633 if (left && right) {
1637 sprintf(buffer, "#(%s + %s)", left, right);
1638 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1644 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1645 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1647 emitcode("add","a,%s",
1648 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1650 emitcode("adc","a,%s",
1651 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1653 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1655 emitcode("add","a,%s",
1656 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1658 emitcode("adc","a,%s",
1659 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1661 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1664 /* Some kind of pointer arith. */
1665 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1666 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1667 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1670 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1671 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1672 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1677 freeAsmop(IC_LEFT(ic),NULL,ic);
1678 freeAsmop(IC_RIGHT(ic),NULL,ic);
1679 freeAsmop(IC_RESULT(ic),NULL,ic);
1683 /*-----------------------------------------------------------------*/
1684 /* genMinusDec :- does subtraction with deccrement if possible */
1685 /*-----------------------------------------------------------------*/
1686 static bool genMinusDec (iCode *ic)
1688 unsigned int icount ;
1689 unsigned int size = getDataSize(IC_RESULT(ic));
1691 /* will try to generate an increment */
1692 /* if the right side is not a literal we cannot */
1693 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1696 /* if the literal value of the right hand side
1697 is greater than 4 then it is not worth it */
1698 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1701 size = getDataSize(IC_RESULT(ic));
1704 /* if increment 16 bits in register */
1705 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1708 symbol *tlbl = newiTempLabel(NULL);
1709 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1710 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1712 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1716 emitcode("", LABEL_STR ":",tlbl->key+100);
1721 /* if decrement 16 bits in register */
1722 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1723 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1725 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1729 /* If result is a pair */
1730 if (isPair(AOP(IC_RESULT(ic)))) {
1731 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1732 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1734 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1738 /* if the sizes are greater than 1 then we cannot */
1739 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1740 AOP_SIZE(IC_LEFT(ic)) > 1 )
1743 /* we can if the aops of the left & result match or if they are in
1744 registers and the registers are the same */
1745 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1747 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1754 /*-----------------------------------------------------------------*/
1755 /* genMinus - generates code for subtraction */
1756 /*-----------------------------------------------------------------*/
1757 static void genMinus (iCode *ic)
1759 int size, offset = 0;
1760 unsigned long lit = 0L;
1762 aopOp (IC_LEFT(ic),ic,FALSE);
1763 aopOp (IC_RIGHT(ic),ic,FALSE);
1764 aopOp (IC_RESULT(ic),ic,TRUE);
1766 /* special cases :- */
1767 /* if both left & right are in bit space */
1768 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1769 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1774 /* if I can do an decrement instead of subtract then GOOD for ME */
1775 if (genMinusDec (ic) == TRUE)
1778 size = getDataSize(IC_RESULT(ic));
1780 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1783 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1788 /* if literal, add a,#-lit, else normal subb */
1790 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1791 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1793 emitcode("sub","a,%s",
1794 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1796 emitcode("sbc","a,%s",
1797 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1800 /* first add without previous c */
1802 emitcode("add","a,#0x%02x",
1803 (unsigned int)(lit & 0x0FFL));
1805 emitcode("adc","a,#0x%02x",
1806 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1808 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1811 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1812 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1813 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1817 freeAsmop(IC_LEFT(ic),NULL,ic);
1818 freeAsmop(IC_RIGHT(ic),NULL,ic);
1819 freeAsmop(IC_RESULT(ic),NULL,ic);
1822 /*-----------------------------------------------------------------*/
1823 /* genMult - generates code for multiplication */
1824 /*-----------------------------------------------------------------*/
1825 static void genMult (iCode *ic)
1827 /* Shouldn't occur - all done through function calls */
1831 /*-----------------------------------------------------------------*/
1832 /* genDiv - generates code for division */
1833 /*-----------------------------------------------------------------*/
1834 static void genDiv (iCode *ic)
1836 /* Shouldn't occur - all done through function calls */
1840 /*-----------------------------------------------------------------*/
1841 /* genMod - generates code for division */
1842 /*-----------------------------------------------------------------*/
1843 static void genMod (iCode *ic)
1845 /* Shouldn't occur - all done through function calls */
1849 /*-----------------------------------------------------------------*/
1850 /* genIfxJump :- will create a jump depending on the ifx */
1851 /*-----------------------------------------------------------------*/
1852 static void genIfxJump (iCode *ic, char *jval)
1857 /* if true label then we jump if condition
1859 if ( IC_TRUE(ic) ) {
1861 if (!strcmp(jval, "a")) {
1864 else if (!strcmp(jval, "c")) {
1868 /* The buffer contains the bit on A that we should test */
1873 /* false label is present */
1874 jlbl = IC_FALSE(ic) ;
1875 if (!strcmp(jval, "a")) {
1878 else if (!strcmp(jval, "c")) {
1882 /* The buffer contains the bit on A that we should test */
1886 /* Z80 can do a conditional long jump */
1887 if (!strcmp(jval, "a")) {
1888 emitcode("or", "a,a");
1890 else if (!strcmp(jval, "c")) {
1893 emitcode("bit", "%s,a", jval);
1895 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1897 /* mark the icode as generated */
1901 /** Generic compare for > or <
1903 static void genCmp (operand *left,operand *right,
1904 operand *result, iCode *ifx, int sign)
1906 int size, offset = 0 ;
1907 unsigned long lit = 0L;
1909 /* if left & right are bit variables */
1910 if (AOP_TYPE(left) == AOP_CRY &&
1911 AOP_TYPE(right) == AOP_CRY ) {
1912 /* Cant happen on the Z80 */
1915 /* subtract right from left if at the
1916 end the carry flag is set then we know that
1917 left is greater than right */
1918 size = max(AOP_SIZE(left),AOP_SIZE(right));
1920 /* if unsigned char cmp with lit, just compare */
1922 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1923 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1925 emitcode("xor", "a,#0x80");
1926 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
1929 emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
1932 if(AOP_TYPE(right) == AOP_LIT) {
1933 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1934 /* optimize if(x < 0) or if(x >= 0) */
1937 /* No sign so it's always false */
1941 /* Just load in the top most bit */
1942 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1943 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1944 genIfxJump (ifx,"7");
1948 emitcode("rlc","a");
1954 /* First setup h and l contaning the top most bytes XORed */
1955 bool fDidXor = FALSE;
1956 if (AOP_TYPE(left) == AOP_LIT){
1957 unsigned long lit = (unsigned long)
1958 floatFromVal(AOP(left)->aopu.aop_lit);
1959 emitcode("ld", "%s,#0x%02x", _fTmp[0],
1960 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1963 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
1964 emitcode("xor", "a,#0x80");
1965 emitcode("ld", "%s,a", _fTmp[0]);
1968 if (AOP_TYPE(right) == AOP_LIT) {
1969 unsigned long lit = (unsigned long)
1970 floatFromVal(AOP(right)->aopu.aop_lit);
1971 emitcode("ld", "%s,#0x%02x", _fTmp[1],
1972 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1975 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
1976 emitcode("xor", "a,#0x80");
1977 emitcode("ld", "%s,a", _fTmp[1]);
1987 /* Do a long subtract */
1989 MOVA(aopGet(AOP(left),offset,FALSE));
1990 if (sign && size == 0) {
1991 emitcode("ld", "a,%s", _fTmp[0]);
1992 emitcode("sbc", "a,%s", _fTmp[1]);
1995 /* Subtract through, propagating the carry */
1996 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
2003 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2006 /* if the result is used in the next
2007 ifx conditional branch then generate
2008 code a little differently */
2010 genIfxJump (ifx,"c");
2013 /* leave the result in acc */
2017 /*-----------------------------------------------------------------*/
2018 /* genCmpGt :- greater than comparison */
2019 /*-----------------------------------------------------------------*/
2020 static void genCmpGt (iCode *ic, iCode *ifx)
2022 operand *left, *right, *result;
2023 link *letype , *retype;
2027 right= IC_RIGHT(ic);
2028 result = IC_RESULT(ic);
2030 letype = getSpec(operandType(left));
2031 retype =getSpec(operandType(right));
2032 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2033 /* assign the amsops */
2034 aopOp (left,ic,FALSE);
2035 aopOp (right,ic,FALSE);
2036 aopOp (result,ic,TRUE);
2038 genCmp(right, left, result, ifx, sign);
2040 freeAsmop(left,NULL,ic);
2041 freeAsmop(right,NULL,ic);
2042 freeAsmop(result,NULL,ic);
2045 /*-----------------------------------------------------------------*/
2046 /* genCmpLt - less than comparisons */
2047 /*-----------------------------------------------------------------*/
2048 static void genCmpLt (iCode *ic, iCode *ifx)
2050 operand *left, *right, *result;
2051 link *letype , *retype;
2055 right= IC_RIGHT(ic);
2056 result = IC_RESULT(ic);
2058 letype = getSpec(operandType(left));
2059 retype =getSpec(operandType(right));
2060 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2062 /* assign the amsops */
2063 aopOp (left,ic,FALSE);
2064 aopOp (right,ic,FALSE);
2065 aopOp (result,ic,TRUE);
2067 genCmp(left, right, result, ifx, sign);
2069 freeAsmop(left,NULL,ic);
2070 freeAsmop(right,NULL,ic);
2071 freeAsmop(result,NULL,ic);
2074 /*-----------------------------------------------------------------*/
2075 /* gencjneshort - compare and jump if not equal */
2076 /*-----------------------------------------------------------------*/
2077 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2079 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2081 unsigned long lit = 0L;
2083 /* Swap the left and right if it makes the computation easier */
2084 if (AOP_TYPE(left) == AOP_LIT) {
2090 if(AOP_TYPE(right) == AOP_LIT)
2091 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2093 /* if the right side is a literal then anything goes */
2094 if (AOP_TYPE(right) == AOP_LIT &&
2095 AOP_TYPE(left) != AOP_DIR ) {
2097 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2098 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2099 emitcode("or", "a,a");
2101 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2102 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2106 /* if the right side is in a register or in direct space or
2107 if the left is a pointer register & right is not */
2108 else if (AOP_TYPE(right) == AOP_REG ||
2109 AOP_TYPE(right) == AOP_DIR ||
2110 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2112 MOVA(aopGet(AOP(left),offset,FALSE));
2113 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2114 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2116 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
2118 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2119 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2124 /* right is a pointer reg need both a & b */
2125 /* PENDING: is this required? */
2127 char *l = aopGet(AOP(left),offset,FALSE);
2128 MOVA(aopGet(AOP(right),offset,FALSE));
2129 emitcode("cp", "%s ; 5", l);
2130 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2136 /*-----------------------------------------------------------------*/
2137 /* gencjne - compare and jump if not equal */
2138 /*-----------------------------------------------------------------*/
2139 static void gencjne(operand *left, operand *right, symbol *lbl)
2141 symbol *tlbl = newiTempLabel(NULL);
2143 gencjneshort(left, right, lbl);
2146 emitcode("ld","a,%s",one);
2147 emitcode("jp", LABEL_STR ,tlbl->key+100);
2148 emitcode("", LABEL_STR ":",lbl->key+100);
2149 emitcode("xor","a,a");
2150 emitcode("", LABEL_STR ":",tlbl->key+100);
2153 /*-----------------------------------------------------------------*/
2154 /* genCmpEq - generates code for equal to */
2155 /*-----------------------------------------------------------------*/
2156 static void genCmpEq (iCode *ic, iCode *ifx)
2158 operand *left, *right, *result;
2160 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2161 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2162 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2164 /* Swap operands if it makes the operation easier. ie if:
2165 1. Left is a literal.
2167 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2168 operand *t = IC_RIGHT(ic);
2169 IC_RIGHT(ic) = IC_LEFT(ic);
2173 if (ifx && !AOP_SIZE(result)){
2175 /* if they are both bit variables */
2176 if (AOP_TYPE(left) == AOP_CRY &&
2177 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2180 tlbl = newiTempLabel(NULL);
2181 gencjneshort(left, right, tlbl);
2182 if ( IC_TRUE(ifx) ) {
2183 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2184 emitcode("", LABEL_STR ":",tlbl->key+100);
2186 /* PENDING: do this better */
2187 symbol *lbl = newiTempLabel(NULL);
2188 emitcode("jp", LABEL_STR ,lbl->key+100);
2189 emitcode("", LABEL_STR ":",tlbl->key+100);
2190 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2191 emitcode("", LABEL_STR ":",lbl->key+100);
2194 /* mark the icode as generated */
2199 /* if they are both bit variables */
2200 if (AOP_TYPE(left) == AOP_CRY &&
2201 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2204 gencjne(left,right,newiTempLabel(NULL));
2205 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2209 genIfxJump(ifx,"a");
2212 /* if the result is used in an arithmetic operation
2213 then put the result in place */
2214 if (AOP_TYPE(result) != AOP_CRY) {
2217 /* leave the result in acc */
2221 freeAsmop(left,NULL,ic);
2222 freeAsmop(right,NULL,ic);
2223 freeAsmop(result,NULL,ic);
2226 /*-----------------------------------------------------------------*/
2227 /* ifxForOp - returns the icode containing the ifx for operand */
2228 /*-----------------------------------------------------------------*/
2229 static iCode *ifxForOp ( operand *op, iCode *ic )
2231 /* if true symbol then needs to be assigned */
2232 if (IS_TRUE_SYMOP(op))
2235 /* if this has register type condition and
2236 the next instruction is ifx with the same operand
2237 and live to of the operand is upto the ifx only then */
2239 ic->next->op == IFX &&
2240 IC_COND(ic->next)->key == op->key &&
2241 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2247 /*-----------------------------------------------------------------*/
2248 /* genAndOp - for && operation */
2249 /*-----------------------------------------------------------------*/
2250 static void genAndOp (iCode *ic)
2252 operand *left,*right, *result;
2255 /* note here that && operations that are in an if statement are
2256 taken away by backPatchLabels only those used in arthmetic
2257 operations remain */
2258 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2259 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2260 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2262 /* if both are bit variables */
2263 if (AOP_TYPE(left) == AOP_CRY &&
2264 AOP_TYPE(right) == AOP_CRY ) {
2267 tlbl = newiTempLabel(NULL);
2269 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2271 emitcode("", LABEL_STR ":",tlbl->key+100);
2275 freeAsmop(left,NULL,ic);
2276 freeAsmop(right,NULL,ic);
2277 freeAsmop(result,NULL,ic);
2280 /*-----------------------------------------------------------------*/
2281 /* genOrOp - for || operation */
2282 /*-----------------------------------------------------------------*/
2283 static void genOrOp (iCode *ic)
2285 operand *left,*right, *result;
2288 /* note here that || operations that are in an
2289 if statement are taken away by backPatchLabels
2290 only those used in arthmetic operations remain */
2291 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2292 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2293 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2295 /* if both are bit variables */
2296 if (AOP_TYPE(left) == AOP_CRY &&
2297 AOP_TYPE(right) == AOP_CRY ) {
2300 tlbl = newiTempLabel(NULL);
2302 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2304 emitcode("", LABEL_STR,tlbl->key+100);
2308 freeAsmop(left,NULL,ic);
2309 freeAsmop(right,NULL,ic);
2310 freeAsmop(result,NULL,ic);
2313 /*-----------------------------------------------------------------*/
2314 /* isLiteralBit - test if lit == 2^n */
2315 /*-----------------------------------------------------------------*/
2316 int isLiteralBit(unsigned long lit)
2318 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2319 0x100L,0x200L,0x400L,0x800L,
2320 0x1000L,0x2000L,0x4000L,0x8000L,
2321 0x10000L,0x20000L,0x40000L,0x80000L,
2322 0x100000L,0x200000L,0x400000L,0x800000L,
2323 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2324 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2327 for(idx = 0; idx < 32; idx++)
2333 /*-----------------------------------------------------------------*/
2334 /* genAnd - code for and */
2335 /*-----------------------------------------------------------------*/
2336 static void genAnd (iCode *ic, iCode *ifx)
2338 operand *left, *right, *result;
2340 unsigned long lit = 0L;
2343 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2344 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2345 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2348 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2350 AOP_TYPE(left), AOP_TYPE(right));
2351 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2353 AOP_SIZE(left), AOP_SIZE(right));
2356 /* if left is a literal & right is not then exchange them */
2357 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2358 AOP_NEEDSACC(left)) {
2359 operand *tmp = right ;
2364 /* if result = right then exchange them */
2365 if(sameRegs(AOP(result),AOP(right))){
2366 operand *tmp = right ;
2371 /* if right is bit then exchange them */
2372 if (AOP_TYPE(right) == AOP_CRY &&
2373 AOP_TYPE(left) != AOP_CRY){
2374 operand *tmp = right ;
2378 if(AOP_TYPE(right) == AOP_LIT)
2379 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2381 size = AOP_SIZE(result);
2383 if (AOP_TYPE(left) == AOP_CRY){
2388 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2389 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2390 if((AOP_TYPE(right) == AOP_LIT) &&
2391 (AOP_TYPE(result) == AOP_CRY) &&
2392 (AOP_TYPE(left) != AOP_CRY)) {
2393 int posbit = isLiteralBit(lit);
2397 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2401 emitcode("mov","c,acc.%d",posbit&0x07);
2406 sprintf(buffer, "%d", posbit&0x07);
2407 genIfxJump(ifx, buffer);
2415 symbol *tlbl = newiTempLabel(NULL);
2416 int sizel = AOP_SIZE(left);
2419 emitcode("setb","c");
2422 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2423 MOVA( aopGet(AOP(left),offset,FALSE));
2425 if((posbit = isLiteralBit(bytelit)) != 0) {
2427 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2430 if(bytelit != 0x0FFL)
2431 emitcode("and","a,%s",
2432 aopGet(AOP(right),offset,FALSE));
2433 emitcode("jr","nz, %05d$",tlbl->key+100);
2438 // bit = left & literal
2440 emitcode("clr","c");
2441 emitcode("","%05d$:",tlbl->key+100);
2443 // if(left & literal)
2447 jmpTrueOrFalse(ifx, tlbl);
2458 /* if left is same as result */
2459 if(sameRegs(AOP(result),AOP(left))){
2460 for(;size--; offset++) {
2461 if(AOP_TYPE(right) == AOP_LIT){
2462 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2466 aopPut(AOP(result),zero,offset);
2468 MOVA(aopGet(AOP(left),offset,FALSE));
2469 emitcode("and","a,%s",
2470 aopGet(AOP(right),offset,FALSE));
2471 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2476 if (AOP_TYPE(left) == AOP_ACC) {
2480 MOVA(aopGet(AOP(right),offset,FALSE));
2481 emitcode("and","%s,a",
2482 aopGet(AOP(left),offset,FALSE));
2487 // left & result in different registers
2488 if(AOP_TYPE(result) == AOP_CRY){
2491 for(;(size--);offset++) {
2493 // result = left & right
2494 if(AOP_TYPE(right) == AOP_LIT){
2495 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2497 aopGet(AOP(left),offset,FALSE),
2500 } else if(bytelit == 0){
2501 aopPut(AOP(result),zero,offset);
2505 // faster than result <- left, anl result,right
2506 // and better if result is SFR
2507 if (AOP_TYPE(left) == AOP_ACC)
2508 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2510 MOVA(aopGet(AOP(right),offset,FALSE));
2511 emitcode("and","a,%s",
2512 aopGet(AOP(left),offset,FALSE));
2514 aopPut(AOP(result),"a",offset);
2521 freeAsmop(left,NULL,ic);
2522 freeAsmop(right,NULL,ic);
2523 freeAsmop(result,NULL,ic);
2526 /*-----------------------------------------------------------------*/
2527 /* genOr - code for or */
2528 /*-----------------------------------------------------------------*/
2529 static void genOr (iCode *ic, iCode *ifx)
2531 operand *left, *right, *result;
2533 unsigned long lit = 0L;
2535 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2536 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2537 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2540 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2542 AOP_TYPE(left), AOP_TYPE(right));
2543 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2545 AOP_SIZE(left), AOP_SIZE(right));
2548 /* if left is a literal & right is not then exchange them */
2549 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2550 AOP_NEEDSACC(left)) {
2551 operand *tmp = right ;
2556 /* if result = right then exchange them */
2557 if(sameRegs(AOP(result),AOP(right))){
2558 operand *tmp = right ;
2563 /* if right is bit then exchange them */
2564 if (AOP_TYPE(right) == AOP_CRY &&
2565 AOP_TYPE(left) != AOP_CRY){
2566 operand *tmp = right ;
2570 if(AOP_TYPE(right) == AOP_LIT)
2571 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2573 size = AOP_SIZE(result);
2575 if (AOP_TYPE(left) == AOP_CRY){
2580 if((AOP_TYPE(right) == AOP_LIT) &&
2581 (AOP_TYPE(result) == AOP_CRY) &&
2582 (AOP_TYPE(left) != AOP_CRY)){
2587 /* if left is same as result */
2588 if(sameRegs(AOP(result),AOP(left))){
2589 for(;size--; offset++) {
2590 if(AOP_TYPE(right) == AOP_LIT){
2591 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2594 emitcode("or","%s,%s; 5",
2595 aopGet(AOP(left),offset,FALSE),
2596 aopGet(AOP(right),offset,FALSE));
2598 if (AOP_TYPE(left) == AOP_ACC)
2599 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2601 MOVA(aopGet(AOP(right),offset,FALSE));
2602 emitcode("or","a,%s ; 7",
2603 aopGet(AOP(left),offset,FALSE));
2604 aopPut(AOP(result),"a ; 8", offset);
2609 // left & result in different registers
2610 if(AOP_TYPE(result) == AOP_CRY){
2612 } else for(;(size--);offset++){
2614 // result = left & right
2615 if(AOP_TYPE(right) == AOP_LIT){
2616 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2618 aopGet(AOP(left),offset,FALSE),
2623 // faster than result <- left, anl result,right
2624 // and better if result is SFR
2625 if (AOP_TYPE(left) == AOP_ACC)
2626 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2628 MOVA(aopGet(AOP(right),offset,FALSE));
2629 emitcode("or","a,%s",
2630 aopGet(AOP(left),offset,FALSE));
2632 aopPut(AOP(result),"a",offset);
2633 /* PENDING: something weird is going on here. Add exception. */
2634 if (AOP_TYPE(result) == AOP_ACC)
2640 freeAsmop(left,NULL,ic);
2641 freeAsmop(right,NULL,ic);
2642 freeAsmop(result,NULL,ic);
2645 /*-----------------------------------------------------------------*/
2646 /* genXor - code for xclusive or */
2647 /*-----------------------------------------------------------------*/
2648 static void genXor (iCode *ic, iCode *ifx)
2650 operand *left, *right, *result;
2652 unsigned long lit = 0L;
2654 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2655 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2656 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2658 /* if left is a literal & right is not then exchange them */
2659 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2660 AOP_NEEDSACC(left)) {
2661 operand *tmp = right ;
2666 /* if result = right then exchange them */
2667 if(sameRegs(AOP(result),AOP(right))){
2668 operand *tmp = right ;
2673 /* if right is bit then exchange them */
2674 if (AOP_TYPE(right) == AOP_CRY &&
2675 AOP_TYPE(left) != AOP_CRY){
2676 operand *tmp = right ;
2680 if(AOP_TYPE(right) == AOP_LIT)
2681 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2683 size = AOP_SIZE(result);
2685 if (AOP_TYPE(left) == AOP_CRY){
2690 if((AOP_TYPE(right) == AOP_LIT) &&
2691 (AOP_TYPE(result) == AOP_CRY) &&
2692 (AOP_TYPE(left) != AOP_CRY)){
2697 /* if left is same as result */
2698 if(sameRegs(AOP(result),AOP(left))){
2699 for(;size--; offset++) {
2700 if(AOP_TYPE(right) == AOP_LIT){
2701 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2704 MOVA(aopGet(AOP(right),offset,FALSE));
2705 emitcode("xor","a,%s",
2706 aopGet(AOP(left),offset,FALSE));
2707 aopPut(AOP(result),"a",0);
2710 if (AOP_TYPE(left) == AOP_ACC)
2711 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2713 MOVA(aopGet(AOP(right),offset,FALSE));
2714 emitcode("xor","a,%s",
2715 aopGet(AOP(left),offset,FALSE));
2716 aopPut(AOP(result),"a",0);
2721 // left & result in different registers
2722 if(AOP_TYPE(result) == AOP_CRY){
2724 } else for(;(size--);offset++){
2726 // result = left & right
2727 if(AOP_TYPE(right) == AOP_LIT){
2728 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2730 aopGet(AOP(left),offset,FALSE),
2735 // faster than result <- left, anl result,right
2736 // and better if result is SFR
2737 if (AOP_TYPE(left) == AOP_ACC)
2738 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2740 MOVA(aopGet(AOP(right),offset,FALSE));
2741 emitcode("xor","a,%s",
2742 aopGet(AOP(left),offset,FALSE));
2743 aopPut(AOP(result),"a",0);
2745 aopPut(AOP(result),"a",offset);
2750 freeAsmop(left,NULL,ic);
2751 freeAsmop(right,NULL,ic);
2752 freeAsmop(result,NULL,ic);
2755 /*-----------------------------------------------------------------*/
2756 /* genInline - write the inline code out */
2757 /*-----------------------------------------------------------------*/
2758 static void genInline (iCode *ic)
2760 char buffer[MAX_INLINEASM];
2764 inLine += (!options.asmpeep);
2765 strcpy(buffer,IC_INLINE(ic));
2767 /* emit each line as a code */
2786 /* emitcode("",buffer); */
2787 inLine -= (!options.asmpeep);
2790 /*-----------------------------------------------------------------*/
2791 /* genRRC - rotate right with carry */
2792 /*-----------------------------------------------------------------*/
2793 static void genRRC (iCode *ic)
2798 /*-----------------------------------------------------------------*/
2799 /* genRLC - generate code for rotate left with carry */
2800 /*-----------------------------------------------------------------*/
2801 static void genRLC (iCode *ic)
2806 /*-----------------------------------------------------------------*/
2807 /* shiftR2Left2Result - shift right two bytes from left to result */
2808 /*-----------------------------------------------------------------*/
2809 static void shiftR2Left2Result (operand *left, int offl,
2810 operand *result, int offr,
2811 int shCount, int sign)
2813 if(sameRegs(AOP(result), AOP(left)) &&
2814 ((offl + MSB16) == offr)){
2817 movLeft2Result(left, offl, result, offr, 0);
2818 movLeft2Result(left, offl+1, result, offr+1, 0);
2825 /* if (AOP(result)->type == AOP_REG) {*/
2828 symbol *tlbl , *tlbl1;
2831 /* Left is already in result - so now do the shift */
2833 emitcode("ld","a,#%u+1", shCount);
2834 tlbl = newiTempLabel(NULL);
2835 tlbl1 = newiTempLabel(NULL);
2836 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2837 emitcode("", LABEL_STR ":",tlbl->key+100);
2840 emitcode("or", "a,a");
2843 l = aopGet(AOP(result), --offset, FALSE);
2844 emitcode("rr","%s", l);
2847 emitcode("", LABEL_STR ":",tlbl1->key+100);
2848 emitcode("dec", "a");
2849 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2854 /*-----------------------------------------------------------------*/
2855 /* shiftL2Left2Result - shift left two bytes from left to result */
2856 /*-----------------------------------------------------------------*/
2857 static void shiftL2Left2Result (operand *left, int offl,
2858 operand *result, int offr, int shCount)
2860 if(sameRegs(AOP(result), AOP(left)) &&
2861 ((offl + MSB16) == offr)){
2864 /* Copy left into result */
2865 movLeft2Result(left, offl, result, offr, 0);
2866 movLeft2Result(left, offl+1, result, offr+1, 0);
2868 /* PENDING: for now just see if it'll work. */
2869 /*if (AOP(result)->type == AOP_REG) { */
2873 symbol *tlbl , *tlbl1;
2876 /* Left is already in result - so now do the shift */
2878 emitcode("ld","a,#%u+1", shCount);
2879 tlbl = newiTempLabel(NULL);
2880 tlbl1 = newiTempLabel(NULL);
2881 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2882 emitcode("", LABEL_STR ":",tlbl->key+100);
2885 emitcode("or", "a,a");
2887 l = aopGet(AOP(result),offset++,FALSE);
2888 emitcode("rl","%s", l);
2891 emitcode("", LABEL_STR ":",tlbl1->key+100);
2892 emitcode("dec", "a");
2893 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2898 /*-----------------------------------------------------------------*/
2899 /* AccRol - rotate left accumulator by known count */
2900 /*-----------------------------------------------------------------*/
2901 static void AccRol (int shCount)
2903 shCount &= 0x0007; // shCount : 0..7
2940 /*-----------------------------------------------------------------*/
2941 /* AccLsh - left shift accumulator by known count */
2942 /*-----------------------------------------------------------------*/
2943 static void AccLsh (int shCount)
2947 emitcode("add","a,a");
2950 emitcode("add","a,a");
2951 emitcode("add","a,a");
2953 /* rotate left accumulator */
2955 /* and kill the lower order bits */
2956 emitcode("and","a,#0x%02x", SLMask[shCount]);
2961 /*-----------------------------------------------------------------*/
2962 /* shiftL1Left2Result - shift left one byte from left to result */
2963 /*-----------------------------------------------------------------*/
2964 static void shiftL1Left2Result (operand *left, int offl,
2965 operand *result, int offr, int shCount)
2968 l = aopGet(AOP(left),offl,FALSE);
2970 /* shift left accumulator */
2972 aopPut(AOP(result),"a",offr);
2976 /*-----------------------------------------------------------------*/
2977 /* genlshTwo - left shift two bytes by known amount != 0 */
2978 /*-----------------------------------------------------------------*/
2979 static void genlshTwo (operand *result,operand *left, int shCount)
2981 int size = AOP_SIZE(result);
2985 /* if shCount >= 8 */
2991 movLeft2Result(left, LSB, result, MSB16, 0);
2992 aopPut(AOP(result),zero, 0);
2993 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2996 movLeft2Result(left, LSB, result, MSB16, 0);
2997 aopPut(AOP(result),zero, 0);
3000 aopPut(AOP(result),zero,LSB);
3002 /* 1 <= shCount <= 7 */
3008 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3013 /*-----------------------------------------------------------------*/
3014 /* genlshOne - left shift a one byte quantity by known count */
3015 /*-----------------------------------------------------------------*/
3016 static void genlshOne (operand *result, operand *left, int shCount)
3018 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3021 /*-----------------------------------------------------------------*/
3022 /* genLeftShiftLiteral - left shifting by known count */
3023 /*-----------------------------------------------------------------*/
3024 static void genLeftShiftLiteral (operand *left,
3029 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3032 freeAsmop(right,NULL,ic);
3034 aopOp(left,ic,FALSE);
3035 aopOp(result,ic,FALSE);
3037 size = getSize(operandType(result));
3040 emitcode("; shift left ","result %d, left %d",size,
3044 /* I suppose that the left size >= result size */
3049 else if(shCount >= (size * 8))
3051 aopPut(AOP(result),zero,size);
3055 genlshOne (result,left,shCount);
3058 genlshTwo (result,left,shCount);
3067 freeAsmop(left,NULL,ic);
3068 freeAsmop(result,NULL,ic);
3071 /*-----------------------------------------------------------------*/
3072 /* genLeftShift - generates code for left shifting */
3073 /*-----------------------------------------------------------------*/
3074 static void genLeftShift (iCode *ic)
3078 symbol *tlbl , *tlbl1;
3079 operand *left,*right, *result;
3081 right = IC_RIGHT(ic);
3083 result = IC_RESULT(ic);
3085 aopOp(right,ic,FALSE);
3087 /* if the shift count is known then do it
3088 as efficiently as possible */
3089 if (AOP_TYPE(right) == AOP_LIT) {
3090 genLeftShiftLiteral (left,right,result,ic);
3094 /* shift count is unknown then we have to form a loop get the loop
3095 count in B : Note: we take only the lower order byte since
3096 shifting more that 32 bits make no sense anyway, ( the largest
3097 size of an object can be only 32 bits ) */
3098 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3099 emitcode("inc","a");
3100 freeAsmop (right,NULL,ic);
3101 aopOp(left,ic,FALSE);
3102 aopOp(result,ic,FALSE);
3104 /* now move the left to the result if they are not the
3107 if (!sameRegs(AOP(left),AOP(result))) {
3109 size = AOP_SIZE(result);
3112 l = aopGet(AOP(left),offset,FALSE);
3113 aopPut(AOP(result),l,offset);
3118 size = AOP_SIZE(result);
3121 l = aopGet(AOP(left),offset,FALSE);
3122 aopPut(AOP(result),l,offset);
3128 tlbl = newiTempLabel(NULL);
3129 size = AOP_SIZE(result);
3131 tlbl1 = newiTempLabel(NULL);
3133 emitcode("jp", LABEL_STR ,tlbl1->key+100);
3134 emitcode("", LABEL_STR ":",tlbl->key+100);
3135 l = aopGet(AOP(result),offset,FALSE);
3136 emitcode("or", "a,a");
3138 l = aopGet(AOP(result),offset++,FALSE);
3139 emitcode("rl","%s", l);
3141 emitcode("", LABEL_STR ":",tlbl1->key+100);
3142 emitcode("dec", "a");
3143 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
3145 freeAsmop(left,NULL,ic);
3146 freeAsmop(result,NULL,ic);
3149 /* genlshTwo - left shift two bytes by known amount != 0 */
3150 /*-----------------------------------------------------------------*/
3151 static void genrshOne (operand *result,operand *left, int shCount)
3154 int size = AOP_SIZE(result);
3160 l = aopGet(AOP(left),0,FALSE);
3161 if (AOP(result)->type == AOP_REG) {
3162 aopPut(AOP(result), l, 0);
3163 l = aopGet(AOP(result), 0, FALSE);
3165 emitcode("srl", "%s", l);
3170 emitcode("srl", "a");
3172 aopPut(AOP(result),"a",0);
3176 /*-----------------------------------------------------------------*/
3177 /* AccRsh - right shift accumulator by known count */
3178 /*-----------------------------------------------------------------*/
3179 static void AccRsh (int shCount)
3186 /* rotate right accumulator */
3187 AccRol(8 - shCount);
3188 /* and kill the higher order bits */
3189 emitcode("and","a,#0x%02x", SRMask[shCount]);
3194 /*-----------------------------------------------------------------*/
3195 /* shiftR1Left2Result - shift right one byte from left to result */
3196 /*-----------------------------------------------------------------*/
3197 static void shiftR1Left2Result (operand *left, int offl,
3198 operand *result, int offr,
3199 int shCount, int sign)
3201 MOVA(aopGet(AOP(left),offl,FALSE));
3208 aopPut(AOP(result),"a",offr);
3211 /*-----------------------------------------------------------------*/
3212 /* genrshTwo - right shift two bytes by known amount != 0 */
3213 /*-----------------------------------------------------------------*/
3214 static void genrshTwo (operand *result,operand *left,
3215 int shCount, int sign)
3217 /* if shCount >= 8 */
3222 shiftR1Left2Result(left, MSB16, result, LSB,
3226 movLeft2Result(left, MSB16, result, LSB, sign);
3227 aopPut(AOP(result),zero,1);
3230 /* 1 <= shCount <= 7 */
3232 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3236 /*-----------------------------------------------------------------*/
3237 /* genRightShiftLiteral - left shifting by known count */
3238 /*-----------------------------------------------------------------*/
3239 static void genRightShiftLiteral (operand *left,
3244 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3247 freeAsmop(right,NULL,ic);
3249 aopOp(left,ic,FALSE);
3250 aopOp(result,ic,FALSE);
3252 size = getSize(operandType(result));
3254 emitcode("; shift right ","result %d, left %d",size,
3257 /* I suppose that the left size >= result size */
3262 else if(shCount >= (size * 8))
3264 aopPut(AOP(result),zero,size);
3268 genrshOne(result, left, shCount);
3271 /* PENDING: sign support */
3272 genrshTwo(result, left, shCount, FALSE);
3281 freeAsmop(left,NULL,ic);
3282 freeAsmop(result,NULL,ic);
3285 /*-----------------------------------------------------------------*/
3286 /* genRightShift - generate code for right shifting */
3287 /*-----------------------------------------------------------------*/
3288 static void genRightShift (iCode *ic)
3290 operand *left,*right, *result;
3292 right = IC_RIGHT(ic);
3294 result = IC_RESULT(ic);
3296 aopOp(right,ic,FALSE);
3298 /* if the shift count is known then do it
3299 as efficiently as possible */
3300 if (AOP_TYPE(right) == AOP_LIT) {
3301 genRightShiftLiteral (left,right,result,ic);
3309 /*-----------------------------------------------------------------*/
3310 /* genGenPointerGet - gget value from generic pointer space */
3311 /*-----------------------------------------------------------------*/
3312 static void genGenPointerGet (operand *left,
3313 operand *result, iCode *ic)
3316 link *retype = getSpec(operandType(result));
3317 const char *ptr = "hl";
3322 aopOp(left,ic,FALSE);
3323 aopOp(result,ic,FALSE);
3325 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3327 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3328 aopPut(AOP(result),"a", 0);
3329 freeAsmop(left,NULL,ic);
3333 /* For now we always load into IY */
3334 /* if this is remateriazable */
3335 if (AOP_TYPE(left) == AOP_IMMD)
3336 emitcode("ld","%s,%s", ptr, aopGet(AOP(left),0,TRUE));
3337 else { /* we need to get it byte by byte */
3339 emitcode("ld", "e,%s", aopGet(AOP(left), 0, FALSE));
3340 emitcode("ld", "d,%s", aopGet(AOP(left), 1, FALSE));
3345 /* so iy now contains the address */
3346 freeAsmop(left,NULL,ic);
3348 /* if bit then unpack */
3349 if (IS_BITVAR(retype)) {
3353 size = AOP_SIZE(result);
3357 /* PENDING: make this better */
3358 if (!IS_GB && AOP(result)->type == AOP_REG) {
3359 aopPut(AOP(result),"(hl)",offset++);
3362 emitcode("ld", "a,(%s)", ptr, offset);
3363 aopPut(AOP(result),"a",offset++);
3366 emitcode("inc", "%s", ptr);
3372 freeAsmop(result,NULL,ic);
3375 /*-----------------------------------------------------------------*/
3376 /* genPointerGet - generate code for pointer get */
3377 /*-----------------------------------------------------------------*/
3378 static void genPointerGet (iCode *ic)
3380 operand *left, *result ;
3384 result = IC_RESULT(ic) ;
3386 /* depending on the type of pointer we need to
3387 move it to the correct pointer register */
3388 type = operandType(left);
3389 etype = getSpec(type);
3391 genGenPointerGet (left,result,ic);
3394 bool isRegOrLit(asmop *aop)
3396 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3401 /*-----------------------------------------------------------------*/
3402 /* genGenPointerSet - stores the value into a pointer location */
3403 /*-----------------------------------------------------------------*/
3404 static void genGenPointerSet (operand *right,
3405 operand *result, iCode *ic)
3408 link *retype = getSpec(operandType(right));
3409 const char *ptr = "hl";
3411 aopOp(result,ic,FALSE);
3412 aopOp(right,ic,FALSE);
3417 /* Handle the exceptions first */
3418 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3420 char *l = aopGet(AOP(right), 0, FALSE);
3422 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3423 freeAsmop(result,NULL,ic);
3427 /* if the operand is already in dptr
3428 then we do nothing else we move the value to dptr */
3429 if (AOP_TYPE(result) != AOP_STR) {
3430 /* if this is remateriazable */
3431 if (AOP_TYPE(result) == AOP_IMMD) {
3432 emitcode("", "; Error 2");
3433 emitcode("ld", "%s,%s", ptr, aopGet(AOP(result), 0, TRUE));
3435 else { /* we need to get it byte by byte */
3437 emitcode("ld", "e,%s", aopGet(AOP(result), 0, TRUE));
3438 emitcode("ld", "d,%s", aopGet(AOP(result), 1, TRUE));
3441 /* PENDING: do this better */
3442 fetchHL(AOP(result));
3446 /* so hl know contains the address */
3447 freeAsmop(result,NULL,ic);
3449 /* if bit then unpack */
3450 if (IS_BITVAR(retype)) {
3454 size = AOP_SIZE(right);
3458 char *l = aopGet(AOP(right),offset,FALSE);
3459 if (isRegOrLit(AOP(right)) && !IS_GB) {
3460 emitcode("ld", "(%s),%s", l);
3464 emitcode("ld", "(%s),a", ptr, offset);
3467 emitcode("inc", ptr);
3473 freeAsmop(right,NULL,ic);
3476 /*-----------------------------------------------------------------*/
3477 /* genPointerSet - stores the value into a pointer location */
3478 /*-----------------------------------------------------------------*/
3479 static void genPointerSet (iCode *ic)
3481 operand *right, *result ;
3484 right = IC_RIGHT(ic);
3485 result = IC_RESULT(ic) ;
3487 /* depending on the type of pointer we need to
3488 move it to the correct pointer register */
3489 type = operandType(result);
3490 etype = getSpec(type);
3492 genGenPointerSet (right,result,ic);
3495 /*-----------------------------------------------------------------*/
3496 /* genIfx - generate code for Ifx statement */
3497 /*-----------------------------------------------------------------*/
3498 static void genIfx (iCode *ic, iCode *popIc)
3500 operand *cond = IC_COND(ic);
3503 aopOp(cond,ic,FALSE);
3505 /* get the value into acc */
3506 if (AOP_TYPE(cond) != AOP_CRY)
3510 /* the result is now in the accumulator */
3511 freeAsmop(cond,NULL,ic);
3513 /* if there was something to be popped then do it */
3517 /* if the condition is a bit variable */
3518 if (isbit && IS_ITEMP(cond) &&
3520 genIfxJump(ic,SPIL_LOC(cond)->rname);
3522 if (isbit && !IS_ITEMP(cond))
3523 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3530 /*-----------------------------------------------------------------*/
3531 /* genAddrOf - generates code for address of */
3532 /*-----------------------------------------------------------------*/
3533 static void genAddrOf (iCode *ic)
3535 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3537 aopOp(IC_RESULT(ic),ic,FALSE);
3539 /* if the operand is on the stack then we
3540 need to get the stack offset of this
3543 /* if it has an offset then we need to compute it */
3545 emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _pushed, _spoffset);
3546 emitcode("ld", "d,h");
3547 emitcode("ld", "e,l");
3548 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3549 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3553 emitcode("push", "de");
3554 emitcode("push", "ix");
3555 emitcode("pop", "hl");
3556 emitcode("ld", "de,#%d", sym->stack);
3557 emitcode("add", "hl,de");
3558 emitcode("pop", "de");
3562 emitcode("ld", "hl,#%s", sym->rname);
3564 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3565 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3567 freeAsmop(IC_RESULT(ic),NULL,ic);
3570 /*-----------------------------------------------------------------*/
3571 /* genAssign - generate code for assignment */
3572 /*-----------------------------------------------------------------*/
3573 static void genAssign (iCode *ic)
3575 operand *result, *right;
3577 unsigned long lit = 0L;
3579 result = IC_RESULT(ic);
3580 right = IC_RIGHT(ic) ;
3583 /* Dont bother assigning if they are the same */
3584 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3585 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3590 aopOp(right,ic,FALSE);
3591 aopOp(result,ic,TRUE);
3593 /* if they are the same registers */
3594 if (sameRegs(AOP(right),AOP(result))) {
3595 emitcode("", "; (registers are the same)");
3599 /* if the result is a bit */
3600 if (AOP_TYPE(result) == AOP_CRY) {
3605 size = AOP_SIZE(result);
3608 if(AOP_TYPE(right) == AOP_LIT)
3609 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3611 (AOP_TYPE(result) != AOP_REG) &&
3612 (AOP_TYPE(right) == AOP_LIT) &&
3613 !IS_FLOAT(operandType(right)) &&
3615 bool fXored = FALSE;
3617 /* Work from the top down.
3618 Done this way so that we can use the cached copy of 0
3619 in A for a fast clear */
3621 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3622 if (!fXored && size>1) {
3623 emitcode("xor", "a,a");
3627 aopPut(AOP(result),"a",offset);
3630 aopPut(AOP(result), "#0", offset);
3635 aopGet(AOP(right),offset,FALSE),
3642 aopGet(AOP(right),offset,FALSE),
3649 freeAsmop(right,NULL,ic);
3650 freeAsmop(result,NULL,ic);
3653 /*-----------------------------------------------------------------*/
3654 /* genJumpTab - genrates code for jump table */
3655 /*-----------------------------------------------------------------*/
3656 static void genJumpTab (iCode *ic)
3661 aopOp(IC_JTCOND(ic),ic,FALSE);
3662 /* get the condition into accumulator */
3663 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3666 emitcode("push", "de");
3667 emitcode("ld", "e,%s", l);
3668 emitcode("ld", "d,#0");
3669 jtab = newiTempLabel(NULL);
3670 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3671 emitcode("add", "hl,de");
3672 emitcode("add", "hl,de");
3673 freeAsmop(IC_JTCOND(ic),NULL,ic);
3675 emitcode("pop", "de");
3676 emitcode("jp", "(hl)");
3677 emitcode("","%05d$:",jtab->key+100);
3678 /* now generate the jump labels */
3679 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3680 jtab = setNextItem(IC_JTLABELS(ic)))
3681 emitcode("jp", LABEL_STR, jtab->key+100);
3684 /*-----------------------------------------------------------------*/
3685 /* genCast - gen code for casting */
3686 /*-----------------------------------------------------------------*/
3687 static void genCast (iCode *ic)
3689 operand *result = IC_RESULT(ic);
3690 link *ctype = operandType(IC_LEFT(ic));
3691 operand *right = IC_RIGHT(ic);
3694 /* if they are equivalent then do nothing */
3695 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3698 aopOp(right,ic,FALSE) ;
3699 aopOp(result,ic,FALSE);
3701 /* if the result is a bit */
3702 if (AOP_TYPE(result) == AOP_CRY) {
3706 /* if they are the same size : or less */
3707 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3709 /* if they are in the same place */
3710 if (sameRegs(AOP(right),AOP(result)))
3713 /* if they in different places then copy */
3714 size = AOP_SIZE(result);
3718 aopGet(AOP(right),offset,FALSE),
3725 /* PENDING: should be OK. */
3727 /* if the result is of type pointer */
3728 if (IS_PTR(ctype)) {
3733 /* so we now know that the size of destination is greater
3734 than the size of the source */
3735 /* we move to result for the size of source */
3736 size = AOP_SIZE(right);
3740 aopGet(AOP(right),offset,FALSE),
3745 /* now depending on the sign of the destination */
3746 size = AOP_SIZE(result) - AOP_SIZE(right);
3747 /* Unsigned or not an integral type - right fill with zeros */
3748 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3750 aopPut(AOP(result),zero,offset++);
3752 /* we need to extend the sign :{ */
3753 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3756 emitcode("", "; genCast: sign extend untested.");
3757 emitcode("rla", "");
3758 emitcode("sbc", "a,a");
3760 aopPut(AOP(result),"a",offset++);
3764 freeAsmop(right, NULL, ic);
3765 freeAsmop(result, NULL, ic);
3768 /*-----------------------------------------------------------------*/
3769 /* genReceive - generate code for a receive iCode */
3770 /*-----------------------------------------------------------------*/
3771 static void genReceive (iCode *ic)
3773 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3774 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3775 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3779 aopOp(IC_RESULT(ic),ic,FALSE);
3781 assignResultValue(IC_RESULT(ic));
3784 freeAsmop(IC_RESULT(ic),NULL,ic);
3787 /*-----------------------------------------------------------------*/
3788 /* genZ80Code - generate code for Z80 based controllers */
3789 /*-----------------------------------------------------------------*/
3790 void genZ80Code (iCode *lic)
3797 _fReturn = _gbz80_return;
3798 _fTmp = _gbz80_return;
3801 _fReturn = _z80_return;
3802 _fTmp = _z80_return;
3805 lineHead = lineCurr = NULL;
3807 /* if debug information required */
3808 if (options.debug && currFunc) {
3809 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3811 if (IS_STATIC(currFunc->etype))
3812 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3814 emitcode("","G$%s$0$0 ==.",currFunc->name);
3817 /* stack pointer name */
3821 for (ic = lic ; ic ; ic = ic->next ) {
3823 if ( cln != ic->lineno ) {
3824 if ( options.debug ) {
3826 emitcode("","C$%s$%d$%d$%d ==.",
3827 ic->filename,ic->lineno,
3828 ic->level,ic->block);
3831 emitcode(";","%s %d",ic->filename,ic->lineno);
3834 /* if the result is marked as
3835 spilt and rematerializable or code for
3836 this has already been generated then
3838 if (resultRemat(ic) || ic->generated )
3841 /* depending on the operation */
3844 emitcode("", "; genNot");
3849 emitcode("", "; genCpl");
3854 emitcode("", "; genUminus");
3859 emitcode("", "; genIpush");
3864 /* IPOP happens only when trying to restore a
3865 spilt live range, if there is an ifx statement
3866 following this pop then the if statement might
3867 be using some of the registers being popped which
3868 would destory the contents of the register so
3869 we need to check for this condition and handle it */
3871 ic->next->op == IFX &&
3872 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3873 emitcode("", "; genIfx");
3874 genIfx (ic->next,ic);
3877 emitcode("", "; genIpop");
3883 emitcode("", "; genCall");
3888 emitcode("", "; genPcall");
3893 emitcode("", "; genFunction");
3898 emitcode("", "; genEndFunction");
3899 genEndFunction (ic);
3903 emitcode("", "; genRet");
3908 emitcode("", "; genLabel");
3913 emitcode("", "; genGoto");
3918 emitcode("", "; genPlus");
3923 emitcode("", "; genMinus");
3928 emitcode("", "; genMult");
3933 emitcode("", "; genDiv");
3938 emitcode("", "; genMod");
3943 emitcode("", "; genCmpGt");
3944 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3948 emitcode("", "; genCmpLt");
3949 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3956 /* note these two are xlated by algebraic equivalence
3957 during parsing SDCC.y */
3958 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3959 "got '>=' or '<=' shouldn't have come here");
3963 emitcode("", "; genCmpEq");
3964 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3968 emitcode("", "; genAndOp");
3973 emitcode("", "; genOrOp");
3978 emitcode("", "; genXor");
3979 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3983 emitcode("", "; genOr");
3984 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3988 emitcode("", "; genAnd");
3989 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3993 emitcode("", "; genInline");
3998 emitcode("", "; genRRC");
4003 emitcode("", "; genRLC");
4008 emitcode("", "; genHBIT");
4012 emitcode("", "; genLeftShift");
4017 emitcode("", "; genRightShift");
4021 case GET_VALUE_AT_ADDRESS:
4022 emitcode("", "; genPointerGet");
4028 if (POINTER_SET(ic)) {
4029 emitcode("", "; genAssign (pointer)");
4033 emitcode("", "; genAssign");
4039 emitcode("", "; genIfx");
4044 emitcode("", "; genAddrOf");
4049 emitcode("", "; genJumpTab");
4054 emitcode("", "; genCast");
4059 emitcode("", "; genReceive");
4064 emitcode("", "; addSet");
4065 addSet(&sendSet,ic);
4070 /* piCode(ic,stdout); */
4076 /* now we are ready to call the
4077 peep hole optimizer */
4078 if (!options.nopeep)
4079 peepHole (&lineHead);
4081 /* now do the actual printing */
4082 printLine (lineHead,codeOutFile);