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] = _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)
1170 /* if caller saves & we have not saved then */
1171 if (!ic->regsSaved) {
1175 /* if send set is not empty then assign */
1178 for (sic = setFirstItem(sendSet) ; sic ;
1179 sic = setNextItem(sendSet)) {
1180 int size, offset = 0;
1181 aopOp(IC_LEFT(sic),sic,FALSE);
1182 size = AOP_SIZE(IC_LEFT(sic));
1184 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1186 if (strcmp(l, _fReturn[offset]))
1187 emitcode("ld","%s,%s",
1192 freeAsmop (IC_LEFT(sic),NULL,sic);
1198 symbol *rlbl = newiTempLabel(NULL);
1200 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1201 emitcode("push", "hl");
1203 aopOp(IC_LEFT(ic),ic,FALSE);
1204 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1205 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1206 freeAsmop(IC_LEFT(ic),NULL,ic);
1208 emitcode("jp", "(hl)");
1209 emitcode("","%05d$:",(rlbl->key+100));
1213 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1214 OP_SYMBOL(IC_LEFT(ic))->rname :
1215 OP_SYMBOL(IC_LEFT(ic))->name;
1216 emitcode("call", "%s", name);
1217 if (!strcmp(name, "__printf"))
1222 /* if we need assign a result value */
1223 if ((IS_ITEMP(IC_RESULT(ic)) &&
1224 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1225 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1226 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1229 aopOp(IC_RESULT(ic),ic,FALSE);
1232 assignResultValue(IC_RESULT(ic));
1234 freeAsmop(IC_RESULT(ic),NULL, ic);
1237 /* adjust the stack for parameters if required */
1238 if (IC_LEFT(ic)->parmBytes) {
1239 int i = IC_LEFT(ic)->parmBytes;
1240 emitcode("", ";parmBytes = %u\n", i);
1245 emitcode("ld", "hl,#%d", i);
1246 emitcode("add", "hl,sp");
1247 emitcode("ld", "sp,hl");
1251 emitcode("pop", "hl");
1255 emitcode("inc", "sp");
1261 /*-----------------------------------------------------------------*/
1262 /* genCall - generates a call statement */
1263 /*-----------------------------------------------------------------*/
1264 static void genCall (iCode *ic)
1266 emitCall(ic, FALSE);
1269 /*-----------------------------------------------------------------*/
1270 /* genPcall - generates a call by pointer statement */
1271 /*-----------------------------------------------------------------*/
1272 static void genPcall (iCode *ic)
1277 /*-----------------------------------------------------------------*/
1278 /* resultRemat - result is rematerializable */
1279 /*-----------------------------------------------------------------*/
1280 static int resultRemat (iCode *ic)
1282 if (SKIP_IC(ic) || ic->op == IFX)
1285 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1286 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1287 if (sym->remat && !POINTER_SET(ic))
1294 /*-----------------------------------------------------------------*/
1295 /* genFunction - generated code for function entry */
1296 /*-----------------------------------------------------------------*/
1297 static void genFunction (iCode *ic)
1303 /* create the function header */
1304 emitcode(";","-----------------------------------------");
1305 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1306 emitcode(";","-----------------------------------------");
1308 emitcode("","%s:",sym->rname);
1309 fetype = getSpec(operandType(IC_LEFT(ic)));
1311 /* if critical function then turn interrupts off */
1312 if (SPEC_CRTCL(fetype))
1315 /* if this is an interrupt service routine then
1316 save acc, b, dpl, dph */
1317 if (IS_ISR(sym->etype)) {
1318 emitcode("push", "af");
1319 emitcode("push", "bc");
1320 emitcode("push", "de");
1321 emitcode("push", "hl");
1323 /* PENDING: callee-save etc */
1325 /* adjust the stack for the function */
1326 emitcode("push", "bc");
1328 emitcode("push", "de");
1329 emitcode("push", "ix");
1330 emitcode("ld", "ix,#0");
1331 emitcode("add", "ix,sp");
1334 _lastStack = sym->stack;
1337 emitcode("ld", "hl,#-%d", sym->stack);
1338 emitcode("add", "hl,sp");
1339 emitcode("ld", "sp,hl");
1341 _spoffset = sym->stack;
1344 /*-----------------------------------------------------------------*/
1345 /* genEndFunction - generates epilogue for functions */
1346 /*-----------------------------------------------------------------*/
1347 static void genEndFunction (iCode *ic)
1349 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1351 if (IS_ISR(sym->etype)) {
1355 if (SPEC_CRTCL(sym->etype))
1358 /* PENDING: calleeSave */
1360 /* if debug then send end of function */
1361 if (options.debug && currFunc) {
1363 emitcode("","C$%s$%d$%d$%d ==.",
1364 ic->filename,currFunc->lastLine,
1365 ic->level,ic->block);
1366 if (IS_STATIC(currFunc->etype))
1367 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1369 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1373 emitcode("ld", "sp,ix");
1374 emitcode("pop", "ix");
1375 emitcode("pop", "de");
1379 emitcode("ld", "hl,#%d", _spoffset);
1380 emitcode("add", "hl,sp");
1381 emitcode("ld", "sp,hl");
1384 emitcode("pop", "bc");
1385 emitcode("ret", "");
1391 /*-----------------------------------------------------------------*/
1392 /* genRet - generate code for return statement */
1393 /*-----------------------------------------------------------------*/
1394 static void genRet (iCode *ic)
1397 /* Errk. This is a hack until I can figure out how
1398 to cause dehl to spill on a call */
1399 int size,offset = 0;
1401 /* if we have no return value then
1402 just generate the "ret" */
1406 /* we have something to return then
1407 move the return value into place */
1408 aopOp(IC_LEFT(ic),ic,FALSE);
1409 size = AOP_SIZE(IC_LEFT(ic));
1411 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1412 emitcode("ld", "hl,%s", l);
1416 l = aopGet(AOP(IC_LEFT(ic)),offset,
1418 if (strcmp(_fReturn[offset],l))
1419 emitcode("ld","%s,%s", _fReturn[offset++],l);
1422 freeAsmop (IC_LEFT(ic),NULL,ic);
1425 /* generate a jump to the return label
1426 if the next is not the return statement */
1427 if (!(ic->next && ic->next->op == LABEL &&
1428 IC_LABEL(ic->next) == returnLabel))
1430 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1433 /*-----------------------------------------------------------------*/
1434 /* genLabel - generates a label */
1435 /*-----------------------------------------------------------------*/
1436 static void genLabel (iCode *ic)
1438 /* special case never generate */
1439 if (IC_LABEL(ic) == entryLabel)
1442 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1445 /*-----------------------------------------------------------------*/
1446 /* genGoto - generates a ljmp */
1447 /*-----------------------------------------------------------------*/
1448 static void genGoto (iCode *ic)
1450 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1453 /*-----------------------------------------------------------------*/
1454 /* genPlusIncr :- does addition with increment if possible */
1455 /*-----------------------------------------------------------------*/
1456 static bool genPlusIncr (iCode *ic)
1458 unsigned int icount ;
1459 unsigned int size = getDataSize(IC_RESULT(ic));
1461 /* will try to generate an increment */
1462 /* if the right side is not a literal
1464 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1467 emitcode("", "; genPlusIncr");
1469 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1471 /* If result is a pair */
1472 if (isPair(AOP(IC_RESULT(ic)))) {
1473 char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1475 /* Both a lit on the right and a true symbol on the left */
1476 emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
1481 /* if the literal value of the right hand side
1482 is greater than 4 then it is not worth it */
1487 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1488 isPair(AOP(IC_RESULT(ic)))) {
1490 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1494 /* if increment 16 bits in register */
1495 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1498 symbol *tlbl = newiTempLabel(NULL);
1499 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1500 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1502 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1506 emitcode("", LABEL_STR ":",tlbl->key+100);
1510 /* If result is a pair */
1511 if (isPair(AOP(IC_RESULT(ic)))) {
1512 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1513 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1515 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1519 /* if the sizes are greater than 1 then we cannot */
1520 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1521 AOP_SIZE(IC_LEFT(ic)) > 1 )
1524 /* we can if the aops of the left & result match or
1525 if they are in registers and the registers are the
1527 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1529 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1537 /*-----------------------------------------------------------------*/
1538 /* outBitAcc - output a bit in acc */
1539 /*-----------------------------------------------------------------*/
1540 void outBitAcc(operand *result)
1542 symbol *tlbl = newiTempLabel(NULL);
1543 /* if the result is a bit */
1544 if (AOP_TYPE(result) == AOP_CRY){
1548 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1549 emitcode("ld","a,%s",one);
1550 emitcode("", LABEL_STR ":",tlbl->key+100);
1555 /*-----------------------------------------------------------------*/
1556 /* genPlus - generates code for addition */
1557 /*-----------------------------------------------------------------*/
1558 static void genPlus (iCode *ic)
1560 int size, offset = 0;
1562 /* special cases :- */
1564 aopOp (IC_LEFT(ic),ic,FALSE);
1565 aopOp (IC_RIGHT(ic),ic,FALSE);
1566 aopOp (IC_RESULT(ic),ic,TRUE);
1568 /* Swap the left and right operands if:
1570 if literal, literal on the right or
1571 if left requires ACC or right is already
1574 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1575 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1576 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1577 operand *t = IC_RIGHT(ic);
1578 IC_RIGHT(ic) = IC_LEFT(ic);
1582 /* if both left & right are in bit
1584 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1585 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1590 /* if left in bit space & right literal */
1591 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1592 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1593 /* Can happen I guess */
1597 /* if I can do an increment instead
1598 of add then GOOD for ME */
1599 if (genPlusIncr (ic) == TRUE)
1602 size = getDataSize(IC_RESULT(ic));
1604 /* Special case when left and right are constant */
1605 if (isPair(AOP(IC_RESULT(ic)))) {
1608 left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1609 right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1610 if (left && right) {
1614 sprintf(buffer, "#(%s + %s)", left, right);
1615 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1621 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1622 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1624 emitcode("add","a,%s",
1625 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1627 emitcode("adc","a,%s",
1628 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1630 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1632 emitcode("add","a,%s",
1633 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1635 emitcode("adc","a,%s",
1636 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1638 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1641 /* Some kind of pointer arith. */
1642 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1643 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1644 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1647 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1648 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1649 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1654 freeAsmop(IC_LEFT(ic),NULL,ic);
1655 freeAsmop(IC_RIGHT(ic),NULL,ic);
1656 freeAsmop(IC_RESULT(ic),NULL,ic);
1660 /*-----------------------------------------------------------------*/
1661 /* genMinusDec :- does subtraction with deccrement if possible */
1662 /*-----------------------------------------------------------------*/
1663 static bool genMinusDec (iCode *ic)
1665 unsigned int icount ;
1666 unsigned int size = getDataSize(IC_RESULT(ic));
1668 /* will try to generate an increment */
1669 /* if the right side is not a literal we cannot */
1670 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1673 /* if the literal value of the right hand side
1674 is greater than 4 then it is not worth it */
1675 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1678 size = getDataSize(IC_RESULT(ic));
1681 /* if increment 16 bits in register */
1682 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1685 symbol *tlbl = newiTempLabel(NULL);
1686 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1687 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1689 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1693 emitcode("", LABEL_STR ":",tlbl->key+100);
1698 /* if decrement 16 bits in register */
1699 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1700 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1702 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1706 /* If result is a pair */
1707 if (isPair(AOP(IC_RESULT(ic)))) {
1708 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1709 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1711 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1715 /* if the sizes are greater than 1 then we cannot */
1716 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1717 AOP_SIZE(IC_LEFT(ic)) > 1 )
1720 /* we can if the aops of the left & result match or if they are in
1721 registers and the registers are the same */
1722 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1724 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1731 /*-----------------------------------------------------------------*/
1732 /* genMinus - generates code for subtraction */
1733 /*-----------------------------------------------------------------*/
1734 static void genMinus (iCode *ic)
1736 int size, offset = 0;
1737 unsigned long lit = 0L;
1739 aopOp (IC_LEFT(ic),ic,FALSE);
1740 aopOp (IC_RIGHT(ic),ic,FALSE);
1741 aopOp (IC_RESULT(ic),ic,TRUE);
1743 /* special cases :- */
1744 /* if both left & right are in bit space */
1745 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1746 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1751 /* if I can do an decrement instead of subtract then GOOD for ME */
1752 if (genMinusDec (ic) == TRUE)
1755 size = getDataSize(IC_RESULT(ic));
1757 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1760 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1765 /* if literal, add a,#-lit, else normal subb */
1767 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1768 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1770 emitcode("sub","a,%s",
1771 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1773 emitcode("sbc","a,%s",
1774 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1777 /* first add without previous c */
1779 emitcode("add","a,#0x%02x",
1780 (unsigned int)(lit & 0x0FFL));
1782 emitcode("adc","a,#0x%02x",
1783 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1785 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1788 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1789 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1790 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1794 freeAsmop(IC_LEFT(ic),NULL,ic);
1795 freeAsmop(IC_RIGHT(ic),NULL,ic);
1796 freeAsmop(IC_RESULT(ic),NULL,ic);
1799 /*-----------------------------------------------------------------*/
1800 /* genMult - generates code for multiplication */
1801 /*-----------------------------------------------------------------*/
1802 static void genMult (iCode *ic)
1804 /* Shouldn't occur - all done through function calls */
1808 /*-----------------------------------------------------------------*/
1809 /* genDiv - generates code for division */
1810 /*-----------------------------------------------------------------*/
1811 static void genDiv (iCode *ic)
1813 /* Shouldn't occur - all done through function calls */
1817 /*-----------------------------------------------------------------*/
1818 /* genMod - generates code for division */
1819 /*-----------------------------------------------------------------*/
1820 static void genMod (iCode *ic)
1822 /* Shouldn't occur - all done through function calls */
1826 /*-----------------------------------------------------------------*/
1827 /* genIfxJump :- will create a jump depending on the ifx */
1828 /*-----------------------------------------------------------------*/
1829 static void genIfxJump (iCode *ic, char *jval)
1834 /* if true label then we jump if condition
1836 if ( IC_TRUE(ic) ) {
1838 if (!strcmp(jval, "a")) {
1841 else if (!strcmp(jval, "c")) {
1845 /* The buffer contains the bit on A that we should test */
1850 /* false label is present */
1851 jlbl = IC_FALSE(ic) ;
1852 if (!strcmp(jval, "a")) {
1855 else if (!strcmp(jval, "c")) {
1859 /* The buffer contains the bit on A that we should test */
1863 /* Z80 can do a conditional long jump */
1864 if (!strcmp(jval, "a")) {
1865 emitcode("or", "a,a");
1867 else if (!strcmp(jval, "c")) {
1870 emitcode("bit", "%s,a", jval);
1872 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1874 /* mark the icode as generated */
1878 /** Generic compare for > or <
1880 static void genCmp (operand *left,operand *right,
1881 operand *result, iCode *ifx, int sign)
1883 int size, offset = 0 ;
1884 unsigned long lit = 0L;
1886 /* if left & right are bit variables */
1887 if (AOP_TYPE(left) == AOP_CRY &&
1888 AOP_TYPE(right) == AOP_CRY ) {
1889 /* Cant happen on the Z80 */
1892 /* subtract right from left if at the
1893 end the carry flag is set then we know that
1894 left is greater than right */
1895 size = max(AOP_SIZE(left),AOP_SIZE(right));
1897 /* if unsigned char cmp with lit, just compare */
1899 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1900 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1902 emitcode("xor", "a,#0x80");
1903 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
1906 emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
1909 if(AOP_TYPE(right) == AOP_LIT) {
1910 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1911 /* optimize if(x < 0) or if(x >= 0) */
1914 /* No sign so it's always false */
1918 /* Just load in the top most bit */
1919 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1920 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1921 genIfxJump (ifx,"7");
1925 emitcode("rlc","a");
1931 /* First setup h and l contaning the top most bytes XORed */
1932 bool fDidXor = FALSE;
1933 if (AOP_TYPE(left) == AOP_LIT){
1934 unsigned long lit = (unsigned long)
1935 floatFromVal(AOP(left)->aopu.aop_lit);
1936 emitcode("ld", "%s,#0x%02x", _fTmp[0],
1937 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1940 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
1941 emitcode("xor", "a,#0x80");
1942 emitcode("ld", "%s,a", _fTmp[0]);
1945 if (AOP_TYPE(right) == AOP_LIT) {
1946 unsigned long lit = (unsigned long)
1947 floatFromVal(AOP(right)->aopu.aop_lit);
1948 emitcode("ld", "%s,#0x%02x", _fTmp[1],
1949 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1952 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
1953 emitcode("xor", "a,#0x80");
1954 emitcode("ld", "%s,a", _fTmp[1]);
1964 /* Do a long subtract */
1966 MOVA(aopGet(AOP(left),offset,FALSE));
1967 if (sign && size == 0) {
1968 emitcode("ld", "a,%s", _fTmp[0]);
1969 emitcode("sbc", "a,%s", _fTmp[1]);
1972 /* Subtract through, propagating the carry */
1973 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1980 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1983 /* if the result is used in the next
1984 ifx conditional branch then generate
1985 code a little differently */
1987 genIfxJump (ifx,"c");
1990 /* leave the result in acc */
1994 /*-----------------------------------------------------------------*/
1995 /* genCmpGt :- greater than comparison */
1996 /*-----------------------------------------------------------------*/
1997 static void genCmpGt (iCode *ic, iCode *ifx)
1999 operand *left, *right, *result;
2000 link *letype , *retype;
2004 right= IC_RIGHT(ic);
2005 result = IC_RESULT(ic);
2007 letype = getSpec(operandType(left));
2008 retype =getSpec(operandType(right));
2009 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2010 /* assign the amsops */
2011 aopOp (left,ic,FALSE);
2012 aopOp (right,ic,FALSE);
2013 aopOp (result,ic,TRUE);
2015 genCmp(right, left, result, ifx, sign);
2017 freeAsmop(left,NULL,ic);
2018 freeAsmop(right,NULL,ic);
2019 freeAsmop(result,NULL,ic);
2022 /*-----------------------------------------------------------------*/
2023 /* genCmpLt - less than comparisons */
2024 /*-----------------------------------------------------------------*/
2025 static void genCmpLt (iCode *ic, iCode *ifx)
2027 operand *left, *right, *result;
2028 link *letype , *retype;
2032 right= IC_RIGHT(ic);
2033 result = IC_RESULT(ic);
2035 letype = getSpec(operandType(left));
2036 retype =getSpec(operandType(right));
2037 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2039 /* assign the amsops */
2040 aopOp (left,ic,FALSE);
2041 aopOp (right,ic,FALSE);
2042 aopOp (result,ic,TRUE);
2044 genCmp(left, right, result, ifx, sign);
2046 freeAsmop(left,NULL,ic);
2047 freeAsmop(right,NULL,ic);
2048 freeAsmop(result,NULL,ic);
2051 /*-----------------------------------------------------------------*/
2052 /* gencjneshort - compare and jump if not equal */
2053 /*-----------------------------------------------------------------*/
2054 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2056 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2058 unsigned long lit = 0L;
2060 /* Swap the left and right if it makes the computation easier */
2061 if (AOP_TYPE(left) == AOP_LIT) {
2067 if(AOP_TYPE(right) == AOP_LIT)
2068 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2070 /* if the right side is a literal then anything goes */
2071 if (AOP_TYPE(right) == AOP_LIT &&
2072 AOP_TYPE(left) != AOP_DIR ) {
2074 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2075 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2076 emitcode("or", "a,a");
2078 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2079 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2083 /* if the right side is in a register or in direct space or
2084 if the left is a pointer register & right is not */
2085 else if (AOP_TYPE(right) == AOP_REG ||
2086 AOP_TYPE(right) == AOP_DIR ||
2087 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2089 MOVA(aopGet(AOP(left),offset,FALSE));
2090 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2091 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2093 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
2095 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2096 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2101 /* right is a pointer reg need both a & b */
2102 /* PENDING: is this required? */
2104 char *l = aopGet(AOP(left),offset,FALSE);
2105 MOVA(aopGet(AOP(right),offset,FALSE));
2106 emitcode("cp", "%s ; 5", l);
2107 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2113 /*-----------------------------------------------------------------*/
2114 /* gencjne - compare and jump if not equal */
2115 /*-----------------------------------------------------------------*/
2116 static void gencjne(operand *left, operand *right, symbol *lbl)
2118 symbol *tlbl = newiTempLabel(NULL);
2120 gencjneshort(left, right, lbl);
2123 emitcode("ld","a,%s",one);
2124 emitcode("jp", LABEL_STR ,tlbl->key+100);
2125 emitcode("", LABEL_STR ":",lbl->key+100);
2126 emitcode("xor","a,a");
2127 emitcode("", LABEL_STR ":",tlbl->key+100);
2130 /*-----------------------------------------------------------------*/
2131 /* genCmpEq - generates code for equal to */
2132 /*-----------------------------------------------------------------*/
2133 static void genCmpEq (iCode *ic, iCode *ifx)
2135 operand *left, *right, *result;
2137 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2138 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2139 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2141 /* Swap operands if it makes the operation easier. ie if:
2142 1. Left is a literal.
2144 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2145 operand *t = IC_RIGHT(ic);
2146 IC_RIGHT(ic) = IC_LEFT(ic);
2150 if (ifx && !AOP_SIZE(result)){
2152 /* if they are both bit variables */
2153 if (AOP_TYPE(left) == AOP_CRY &&
2154 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2157 tlbl = newiTempLabel(NULL);
2158 gencjneshort(left, right, tlbl);
2159 if ( IC_TRUE(ifx) ) {
2160 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2161 emitcode("", LABEL_STR ":",tlbl->key+100);
2163 /* PENDING: do this better */
2164 symbol *lbl = newiTempLabel(NULL);
2165 emitcode("jp", LABEL_STR ,lbl->key+100);
2166 emitcode("", LABEL_STR ":",tlbl->key+100);
2167 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2168 emitcode("", LABEL_STR ":",lbl->key+100);
2171 /* mark the icode as generated */
2176 /* if they are both bit variables */
2177 if (AOP_TYPE(left) == AOP_CRY &&
2178 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2181 gencjne(left,right,newiTempLabel(NULL));
2182 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2186 genIfxJump(ifx,"a");
2189 /* if the result is used in an arithmetic operation
2190 then put the result in place */
2191 if (AOP_TYPE(result) != AOP_CRY) {
2194 /* leave the result in acc */
2198 freeAsmop(left,NULL,ic);
2199 freeAsmop(right,NULL,ic);
2200 freeAsmop(result,NULL,ic);
2203 /*-----------------------------------------------------------------*/
2204 /* ifxForOp - returns the icode containing the ifx for operand */
2205 /*-----------------------------------------------------------------*/
2206 static iCode *ifxForOp ( operand *op, iCode *ic )
2208 /* if true symbol then needs to be assigned */
2209 if (IS_TRUE_SYMOP(op))
2212 /* if this has register type condition and
2213 the next instruction is ifx with the same operand
2214 and live to of the operand is upto the ifx only then */
2216 ic->next->op == IFX &&
2217 IC_COND(ic->next)->key == op->key &&
2218 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2224 /*-----------------------------------------------------------------*/
2225 /* genAndOp - for && operation */
2226 /*-----------------------------------------------------------------*/
2227 static void genAndOp (iCode *ic)
2229 operand *left,*right, *result;
2232 /* note here that && operations that are in an if statement are
2233 taken away by backPatchLabels only those used in arthmetic
2234 operations remain */
2235 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2236 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2237 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2239 /* if both are bit variables */
2240 if (AOP_TYPE(left) == AOP_CRY &&
2241 AOP_TYPE(right) == AOP_CRY ) {
2244 tlbl = newiTempLabel(NULL);
2246 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2248 emitcode("", LABEL_STR ":",tlbl->key+100);
2252 freeAsmop(left,NULL,ic);
2253 freeAsmop(right,NULL,ic);
2254 freeAsmop(result,NULL,ic);
2257 /*-----------------------------------------------------------------*/
2258 /* genOrOp - for || operation */
2259 /*-----------------------------------------------------------------*/
2260 static void genOrOp (iCode *ic)
2262 operand *left,*right, *result;
2265 /* note here that || operations that are in an
2266 if statement are taken away by backPatchLabels
2267 only those used in arthmetic operations remain */
2268 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2269 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2270 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2272 /* if both are bit variables */
2273 if (AOP_TYPE(left) == AOP_CRY &&
2274 AOP_TYPE(right) == AOP_CRY ) {
2277 tlbl = newiTempLabel(NULL);
2279 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2281 emitcode("", LABEL_STR,tlbl->key+100);
2285 freeAsmop(left,NULL,ic);
2286 freeAsmop(right,NULL,ic);
2287 freeAsmop(result,NULL,ic);
2290 /*-----------------------------------------------------------------*/
2291 /* isLiteralBit - test if lit == 2^n */
2292 /*-----------------------------------------------------------------*/
2293 int isLiteralBit(unsigned long lit)
2295 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2296 0x100L,0x200L,0x400L,0x800L,
2297 0x1000L,0x2000L,0x4000L,0x8000L,
2298 0x10000L,0x20000L,0x40000L,0x80000L,
2299 0x100000L,0x200000L,0x400000L,0x800000L,
2300 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2301 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2304 for(idx = 0; idx < 32; idx++)
2310 /*-----------------------------------------------------------------*/
2311 /* genAnd - code for and */
2312 /*-----------------------------------------------------------------*/
2313 static void genAnd (iCode *ic, iCode *ifx)
2315 operand *left, *right, *result;
2317 unsigned long lit = 0L;
2320 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2321 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2322 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2325 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2327 AOP_TYPE(left), AOP_TYPE(right));
2328 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2330 AOP_SIZE(left), AOP_SIZE(right));
2333 /* if left is a literal & right is not then exchange them */
2334 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2335 AOP_NEEDSACC(left)) {
2336 operand *tmp = right ;
2341 /* if result = right then exchange them */
2342 if(sameRegs(AOP(result),AOP(right))){
2343 operand *tmp = right ;
2348 /* if right is bit then exchange them */
2349 if (AOP_TYPE(right) == AOP_CRY &&
2350 AOP_TYPE(left) != AOP_CRY){
2351 operand *tmp = right ;
2355 if(AOP_TYPE(right) == AOP_LIT)
2356 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2358 size = AOP_SIZE(result);
2360 if (AOP_TYPE(left) == AOP_CRY){
2365 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2366 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2367 if((AOP_TYPE(right) == AOP_LIT) &&
2368 (AOP_TYPE(result) == AOP_CRY) &&
2369 (AOP_TYPE(left) != AOP_CRY)) {
2370 int posbit = isLiteralBit(lit);
2374 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2378 emitcode("mov","c,acc.%d",posbit&0x07);
2383 sprintf(buffer, "%d", posbit&0x07);
2384 genIfxJump(ifx, buffer);
2392 symbol *tlbl = newiTempLabel(NULL);
2393 int sizel = AOP_SIZE(left);
2396 emitcode("setb","c");
2399 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2400 MOVA( aopGet(AOP(left),offset,FALSE));
2402 if((posbit = isLiteralBit(bytelit)) != 0) {
2404 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2407 if(bytelit != 0x0FFL)
2408 emitcode("and","a,%s",
2409 aopGet(AOP(right),offset,FALSE));
2410 emitcode("jr","nz, %05d$",tlbl->key+100);
2415 // bit = left & literal
2417 emitcode("clr","c");
2418 emitcode("","%05d$:",tlbl->key+100);
2420 // if(left & literal)
2424 jmpTrueOrFalse(ifx, tlbl);
2435 /* if left is same as result */
2436 if(sameRegs(AOP(result),AOP(left))){
2437 for(;size--; offset++) {
2438 if(AOP_TYPE(right) == AOP_LIT){
2439 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2443 aopPut(AOP(result),zero,offset);
2445 MOVA(aopGet(AOP(left),offset,FALSE));
2446 emitcode("and","a,%s",
2447 aopGet(AOP(right),offset,FALSE));
2448 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2453 if (AOP_TYPE(left) == AOP_ACC) {
2457 MOVA(aopGet(AOP(right),offset,FALSE));
2458 emitcode("and","%s,a",
2459 aopGet(AOP(left),offset,FALSE));
2464 // left & result in different registers
2465 if(AOP_TYPE(result) == AOP_CRY){
2468 for(;(size--);offset++) {
2470 // result = left & right
2471 if(AOP_TYPE(right) == AOP_LIT){
2472 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2474 aopGet(AOP(left),offset,FALSE),
2477 } else if(bytelit == 0){
2478 aopPut(AOP(result),zero,offset);
2482 // faster than result <- left, anl result,right
2483 // and better if result is SFR
2484 if (AOP_TYPE(left) == AOP_ACC)
2485 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2487 MOVA(aopGet(AOP(right),offset,FALSE));
2488 emitcode("and","a,%s",
2489 aopGet(AOP(left),offset,FALSE));
2491 aopPut(AOP(result),"a",offset);
2498 freeAsmop(left,NULL,ic);
2499 freeAsmop(right,NULL,ic);
2500 freeAsmop(result,NULL,ic);
2503 /*-----------------------------------------------------------------*/
2504 /* genOr - code for or */
2505 /*-----------------------------------------------------------------*/
2506 static void genOr (iCode *ic, iCode *ifx)
2508 operand *left, *right, *result;
2510 unsigned long lit = 0L;
2512 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2513 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2514 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2517 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2519 AOP_TYPE(left), AOP_TYPE(right));
2520 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2522 AOP_SIZE(left), AOP_SIZE(right));
2525 /* if left is a literal & right is not then exchange them */
2526 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2527 AOP_NEEDSACC(left)) {
2528 operand *tmp = right ;
2533 /* if result = right then exchange them */
2534 if(sameRegs(AOP(result),AOP(right))){
2535 operand *tmp = right ;
2540 /* if right is bit then exchange them */
2541 if (AOP_TYPE(right) == AOP_CRY &&
2542 AOP_TYPE(left) != AOP_CRY){
2543 operand *tmp = right ;
2547 if(AOP_TYPE(right) == AOP_LIT)
2548 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2550 size = AOP_SIZE(result);
2552 if (AOP_TYPE(left) == AOP_CRY){
2557 if((AOP_TYPE(right) == AOP_LIT) &&
2558 (AOP_TYPE(result) == AOP_CRY) &&
2559 (AOP_TYPE(left) != AOP_CRY)){
2564 /* if left is same as result */
2565 if(sameRegs(AOP(result),AOP(left))){
2566 for(;size--; offset++) {
2567 if(AOP_TYPE(right) == AOP_LIT){
2568 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2571 emitcode("or","%s,%s; 5",
2572 aopGet(AOP(left),offset,FALSE),
2573 aopGet(AOP(right),offset,FALSE));
2575 if (AOP_TYPE(left) == AOP_ACC)
2576 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2578 MOVA(aopGet(AOP(right),offset,FALSE));
2579 emitcode("or","a,%s ; 7",
2580 aopGet(AOP(left),offset,FALSE));
2581 aopPut(AOP(result),"a ; 8",0);
2586 // left & result in different registers
2587 if(AOP_TYPE(result) == AOP_CRY){
2589 } else for(;(size--);offset++){
2591 // result = left & right
2592 if(AOP_TYPE(right) == AOP_LIT){
2593 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2595 aopGet(AOP(left),offset,FALSE),
2600 // faster than result <- left, anl result,right
2601 // and better if result is SFR
2602 if (AOP_TYPE(left) == AOP_ACC)
2603 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2605 MOVA(aopGet(AOP(right),offset,FALSE));
2606 emitcode("or","a,%s",
2607 aopGet(AOP(left),offset,FALSE));
2609 aopPut(AOP(result),"a",offset);
2610 /* PENDING: something weird is going on here. Add exception. */
2611 if (AOP_TYPE(result) == AOP_ACC)
2617 freeAsmop(left,NULL,ic);
2618 freeAsmop(right,NULL,ic);
2619 freeAsmop(result,NULL,ic);
2622 /*-----------------------------------------------------------------*/
2623 /* genXor - code for xclusive or */
2624 /*-----------------------------------------------------------------*/
2625 static void genXor (iCode *ic, iCode *ifx)
2627 operand *left, *right, *result;
2629 unsigned long lit = 0L;
2631 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2632 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2633 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2635 /* if left is a literal & right is not then exchange them */
2636 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2637 AOP_NEEDSACC(left)) {
2638 operand *tmp = right ;
2643 /* if result = right then exchange them */
2644 if(sameRegs(AOP(result),AOP(right))){
2645 operand *tmp = right ;
2650 /* if right is bit then exchange them */
2651 if (AOP_TYPE(right) == AOP_CRY &&
2652 AOP_TYPE(left) != AOP_CRY){
2653 operand *tmp = right ;
2657 if(AOP_TYPE(right) == AOP_LIT)
2658 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2660 size = AOP_SIZE(result);
2662 if (AOP_TYPE(left) == AOP_CRY){
2667 if((AOP_TYPE(right) == AOP_LIT) &&
2668 (AOP_TYPE(result) == AOP_CRY) &&
2669 (AOP_TYPE(left) != AOP_CRY)){
2674 /* if left is same as result */
2675 if(sameRegs(AOP(result),AOP(left))){
2676 for(;size--; offset++) {
2677 if(AOP_TYPE(right) == AOP_LIT){
2678 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2681 MOVA(aopGet(AOP(right),offset,FALSE));
2682 emitcode("xor","a,%s",
2683 aopGet(AOP(left),offset,FALSE));
2684 aopPut(AOP(result),"a",0);
2687 if (AOP_TYPE(left) == AOP_ACC)
2688 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2690 MOVA(aopGet(AOP(right),offset,FALSE));
2691 emitcode("xor","a,%s",
2692 aopGet(AOP(left),offset,FALSE));
2693 aopPut(AOP(result),"a",0);
2698 // left & result in different registers
2699 if(AOP_TYPE(result) == AOP_CRY){
2701 } else for(;(size--);offset++){
2703 // result = left & right
2704 if(AOP_TYPE(right) == AOP_LIT){
2705 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2707 aopGet(AOP(left),offset,FALSE),
2712 // faster than result <- left, anl result,right
2713 // and better if result is SFR
2714 if (AOP_TYPE(left) == AOP_ACC)
2715 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2717 MOVA(aopGet(AOP(right),offset,FALSE));
2718 emitcode("xor","a,%s",
2719 aopGet(AOP(left),offset,FALSE));
2720 aopPut(AOP(result),"a",0);
2722 aopPut(AOP(result),"a",offset);
2727 freeAsmop(left,NULL,ic);
2728 freeAsmop(right,NULL,ic);
2729 freeAsmop(result,NULL,ic);
2732 /*-----------------------------------------------------------------*/
2733 /* genInline - write the inline code out */
2734 /*-----------------------------------------------------------------*/
2735 static void genInline (iCode *ic)
2737 char buffer[MAX_INLINEASM];
2741 inLine += (!options.asmpeep);
2742 strcpy(buffer,IC_INLINE(ic));
2744 /* emit each line as a code */
2763 /* emitcode("",buffer); */
2764 inLine -= (!options.asmpeep);
2767 /*-----------------------------------------------------------------*/
2768 /* genRRC - rotate right with carry */
2769 /*-----------------------------------------------------------------*/
2770 static void genRRC (iCode *ic)
2775 /*-----------------------------------------------------------------*/
2776 /* genRLC - generate code for rotate left with carry */
2777 /*-----------------------------------------------------------------*/
2778 static void genRLC (iCode *ic)
2783 /*-----------------------------------------------------------------*/
2784 /* shiftR2Left2Result - shift right two bytes from left to result */
2785 /*-----------------------------------------------------------------*/
2786 static void shiftR2Left2Result (operand *left, int offl,
2787 operand *result, int offr,
2788 int shCount, int sign)
2790 if(sameRegs(AOP(result), AOP(left)) &&
2791 ((offl + MSB16) == offr)){
2794 movLeft2Result(left, offl, result, offr, 0);
2795 movLeft2Result(left, offl+1, result, offr+1, 0);
2802 /* if (AOP(result)->type == AOP_REG) {*/
2805 symbol *tlbl , *tlbl1;
2808 /* Left is already in result - so now do the shift */
2810 emitcode("ld","a,#%u+1", shCount);
2811 tlbl = newiTempLabel(NULL);
2812 tlbl1 = newiTempLabel(NULL);
2813 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2814 emitcode("", LABEL_STR ":",tlbl->key+100);
2817 emitcode("or", "a,a");
2820 l = aopGet(AOP(result), --offset, FALSE);
2821 emitcode("rr","%s", l);
2824 emitcode("", LABEL_STR ":",tlbl1->key+100);
2825 emitcode("dec", "a");
2826 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2831 /*-----------------------------------------------------------------*/
2832 /* shiftL2Left2Result - shift left two bytes from left to result */
2833 /*-----------------------------------------------------------------*/
2834 static void shiftL2Left2Result (operand *left, int offl,
2835 operand *result, int offr, int shCount)
2837 if(sameRegs(AOP(result), AOP(left)) &&
2838 ((offl + MSB16) == offr)){
2841 /* Copy left into result */
2842 movLeft2Result(left, offl, result, offr, 0);
2843 movLeft2Result(left, offl+1, result, offr+1, 0);
2845 /* PENDING: for now just see if it'll work. */
2846 /*if (AOP(result)->type == AOP_REG) { */
2850 symbol *tlbl , *tlbl1;
2853 /* Left is already in result - so now do the shift */
2855 emitcode("ld","a,#%u+1", shCount);
2856 tlbl = newiTempLabel(NULL);
2857 tlbl1 = newiTempLabel(NULL);
2858 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2859 emitcode("", LABEL_STR ":",tlbl->key+100);
2862 emitcode("or", "a,a");
2864 l = aopGet(AOP(result),offset++,FALSE);
2865 emitcode("rl","%s", l);
2868 emitcode("", LABEL_STR ":",tlbl1->key+100);
2869 emitcode("dec", "a");
2870 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2875 /*-----------------------------------------------------------------*/
2876 /* AccRol - rotate left accumulator by known count */
2877 /*-----------------------------------------------------------------*/
2878 static void AccRol (int shCount)
2880 shCount &= 0x0007; // shCount : 0..7
2917 /*-----------------------------------------------------------------*/
2918 /* AccLsh - left shift accumulator by known count */
2919 /*-----------------------------------------------------------------*/
2920 static void AccLsh (int shCount)
2924 emitcode("add","a,a");
2927 emitcode("add","a,a");
2928 emitcode("add","a,a");
2930 /* rotate left accumulator */
2932 /* and kill the lower order bits */
2933 emitcode("and","a,#0x%02x", SLMask[shCount]);
2938 /*-----------------------------------------------------------------*/
2939 /* shiftL1Left2Result - shift left one byte from left to result */
2940 /*-----------------------------------------------------------------*/
2941 static void shiftL1Left2Result (operand *left, int offl,
2942 operand *result, int offr, int shCount)
2945 l = aopGet(AOP(left),offl,FALSE);
2947 /* shift left accumulator */
2949 aopPut(AOP(result),"a",offr);
2953 /*-----------------------------------------------------------------*/
2954 /* genlshTwo - left shift two bytes by known amount != 0 */
2955 /*-----------------------------------------------------------------*/
2956 static void genlshTwo (operand *result,operand *left, int shCount)
2958 int size = AOP_SIZE(result);
2962 /* if shCount >= 8 */
2968 movLeft2Result(left, LSB, result, MSB16, 0);
2969 aopPut(AOP(result),zero, 0);
2970 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2973 movLeft2Result(left, LSB, result, MSB16, 0);
2974 aopPut(AOP(result),zero, 0);
2977 aopPut(AOP(result),zero,LSB);
2979 /* 1 <= shCount <= 7 */
2985 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2990 /*-----------------------------------------------------------------*/
2991 /* genlshOne - left shift a one byte quantity by known count */
2992 /*-----------------------------------------------------------------*/
2993 static void genlshOne (operand *result, operand *left, int shCount)
2995 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2998 /*-----------------------------------------------------------------*/
2999 /* genLeftShiftLiteral - left shifting by known count */
3000 /*-----------------------------------------------------------------*/
3001 static void genLeftShiftLiteral (operand *left,
3006 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3009 freeAsmop(right,NULL,ic);
3011 aopOp(left,ic,FALSE);
3012 aopOp(result,ic,FALSE);
3014 size = getSize(operandType(result));
3017 emitcode("; shift left ","result %d, left %d",size,
3021 /* I suppose that the left size >= result size */
3026 else if(shCount >= (size * 8))
3028 aopPut(AOP(result),zero,size);
3032 genlshOne (result,left,shCount);
3035 genlshTwo (result,left,shCount);
3044 freeAsmop(left,NULL,ic);
3045 freeAsmop(result,NULL,ic);
3048 /*-----------------------------------------------------------------*/
3049 /* genLeftShift - generates code for left shifting */
3050 /*-----------------------------------------------------------------*/
3051 static void genLeftShift (iCode *ic)
3055 symbol *tlbl , *tlbl1;
3056 operand *left,*right, *result;
3058 right = IC_RIGHT(ic);
3060 result = IC_RESULT(ic);
3062 aopOp(right,ic,FALSE);
3064 /* if the shift count is known then do it
3065 as efficiently as possible */
3066 if (AOP_TYPE(right) == AOP_LIT) {
3067 genLeftShiftLiteral (left,right,result,ic);
3071 /* shift count is unknown then we have to form a loop get the loop
3072 count in B : Note: we take only the lower order byte since
3073 shifting more that 32 bits make no sense anyway, ( the largest
3074 size of an object can be only 32 bits ) */
3075 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3076 emitcode("inc","a");
3077 freeAsmop (right,NULL,ic);
3078 aopOp(left,ic,FALSE);
3079 aopOp(result,ic,FALSE);
3081 /* now move the left to the result if they are not the
3084 if (!sameRegs(AOP(left),AOP(result))) {
3086 size = AOP_SIZE(result);
3089 l = aopGet(AOP(left),offset,FALSE);
3090 aopPut(AOP(result),l,offset);
3095 size = AOP_SIZE(result);
3098 l = aopGet(AOP(left),offset,FALSE);
3099 aopPut(AOP(result),l,offset);
3105 tlbl = newiTempLabel(NULL);
3106 size = AOP_SIZE(result);
3108 tlbl1 = newiTempLabel(NULL);
3110 emitcode("jp", LABEL_STR ,tlbl1->key+100);
3111 emitcode("", LABEL_STR ":",tlbl->key+100);
3112 l = aopGet(AOP(result),offset,FALSE);
3113 emitcode("or", "a,a");
3115 l = aopGet(AOP(result),offset++,FALSE);
3116 emitcode("rl","%s", l);
3118 emitcode("", LABEL_STR ":",tlbl1->key+100);
3119 emitcode("dec", "a");
3120 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
3122 freeAsmop(left,NULL,ic);
3123 freeAsmop(result,NULL,ic);
3126 /* genlshTwo - left shift two bytes by known amount != 0 */
3127 /*-----------------------------------------------------------------*/
3128 static void genrshOne (operand *result,operand *left, int shCount)
3131 int size = AOP_SIZE(result);
3137 l = aopGet(AOP(left),0,FALSE);
3138 if (AOP(result)->type == AOP_REG) {
3139 aopPut(AOP(result), l, 0);
3140 l = aopGet(AOP(result), 0, FALSE);
3142 emitcode("srl", "%s", l);
3147 emitcode("srl", "a");
3149 aopPut(AOP(result),"a",0);
3153 /*-----------------------------------------------------------------*/
3154 /* AccRsh - right shift accumulator by known count */
3155 /*-----------------------------------------------------------------*/
3156 static void AccRsh (int shCount)
3163 /* rotate right accumulator */
3164 AccRol(8 - shCount);
3165 /* and kill the higher order bits */
3166 emitcode("and","a,#0x%02x", SRMask[shCount]);
3171 /*-----------------------------------------------------------------*/
3172 /* shiftR1Left2Result - shift right one byte from left to result */
3173 /*-----------------------------------------------------------------*/
3174 static void shiftR1Left2Result (operand *left, int offl,
3175 operand *result, int offr,
3176 int shCount, int sign)
3178 MOVA(aopGet(AOP(left),offl,FALSE));
3185 aopPut(AOP(result),"a",offr);
3188 /*-----------------------------------------------------------------*/
3189 /* genrshTwo - right shift two bytes by known amount != 0 */
3190 /*-----------------------------------------------------------------*/
3191 static void genrshTwo (operand *result,operand *left,
3192 int shCount, int sign)
3194 /* if shCount >= 8 */
3199 shiftR1Left2Result(left, MSB16, result, LSB,
3203 movLeft2Result(left, MSB16, result, LSB, sign);
3204 aopPut(AOP(result),zero,1);
3207 /* 1 <= shCount <= 7 */
3209 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3213 /*-----------------------------------------------------------------*/
3214 /* genRightShiftLiteral - left shifting by known count */
3215 /*-----------------------------------------------------------------*/
3216 static void genRightShiftLiteral (operand *left,
3221 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3224 freeAsmop(right,NULL,ic);
3226 aopOp(left,ic,FALSE);
3227 aopOp(result,ic,FALSE);
3229 size = getSize(operandType(result));
3231 emitcode("; shift right ","result %d, left %d",size,
3234 /* I suppose that the left size >= result size */
3239 else if(shCount >= (size * 8))
3241 aopPut(AOP(result),zero,size);
3245 genrshOne(result, left, shCount);
3248 /* PENDING: sign support */
3249 genrshTwo(result, left, shCount, FALSE);
3258 freeAsmop(left,NULL,ic);
3259 freeAsmop(result,NULL,ic);
3262 /*-----------------------------------------------------------------*/
3263 /* genRightShift - generate code for right shifting */
3264 /*-----------------------------------------------------------------*/
3265 static void genRightShift (iCode *ic)
3267 operand *left,*right, *result;
3269 right = IC_RIGHT(ic);
3271 result = IC_RESULT(ic);
3273 aopOp(right,ic,FALSE);
3275 /* if the shift count is known then do it
3276 as efficiently as possible */
3277 if (AOP_TYPE(right) == AOP_LIT) {
3278 genRightShiftLiteral (left,right,result,ic);
3286 /*-----------------------------------------------------------------*/
3287 /* genGenPointerGet - gget value from generic pointer space */
3288 /*-----------------------------------------------------------------*/
3289 static void genGenPointerGet (operand *left,
3290 operand *result, iCode *ic)
3293 link *retype = getSpec(operandType(result));
3295 aopOp(left,ic,FALSE);
3296 aopOp(result,ic,FALSE);
3298 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3300 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3301 aopPut(AOP(result),"a", 0);
3302 freeAsmop(left,NULL,ic);
3306 /* For now we always load into IY */
3307 /* if this is remateriazable */
3308 if (AOP_TYPE(left) == AOP_IMMD)
3309 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3310 else { /* we need to get it byte by byte */
3313 /* so iy now contains the address */
3314 freeAsmop(left,NULL,ic);
3316 /* if bit then unpack */
3317 if (IS_BITVAR(retype)) {
3321 size = AOP_SIZE(result);
3325 /* PENDING: make this better */
3326 if (AOP(result)->type == AOP_REG) {
3327 aopPut(AOP(result),"(hl)",offset++);
3330 emitcode("ld", "a,(hl)", offset);
3331 aopPut(AOP(result),"a",offset++);
3334 emitcode("inc", "hl");
3340 freeAsmop(result,NULL,ic);
3343 /*-----------------------------------------------------------------*/
3344 /* genPointerGet - generate code for pointer get */
3345 /*-----------------------------------------------------------------*/
3346 static void genPointerGet (iCode *ic)
3348 operand *left, *result ;
3352 result = IC_RESULT(ic) ;
3354 /* depending on the type of pointer we need to
3355 move it to the correct pointer register */
3356 type = operandType(left);
3357 etype = getSpec(type);
3359 genGenPointerGet (left,result,ic);
3362 bool isRegOrLit(asmop *aop)
3364 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3369 /*-----------------------------------------------------------------*/
3370 /* genGenPointerSet - stores the value into a pointer location */
3371 /*-----------------------------------------------------------------*/
3372 static void genGenPointerSet (operand *right,
3373 operand *result, iCode *ic)
3376 link *retype = getSpec(operandType(right));
3378 aopOp(result,ic,FALSE);
3379 aopOp(right,ic,FALSE);
3381 /* Handle the exceptions first */
3382 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3384 char *l = aopGet(AOP(right), 0, FALSE);
3386 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3387 freeAsmop(result,NULL,ic);
3391 /* if the operand is already in dptr
3392 then we do nothing else we move the value to dptr */
3393 if (AOP_TYPE(result) != AOP_STR) {
3394 /* if this is remateriazable */
3395 if (AOP_TYPE(result) == AOP_IMMD) {
3396 emitcode("", "; Error 2");
3397 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3399 else { /* we need to get it byte by byte */
3400 /* PENDING: do this better */
3401 fetchHL(AOP(result));
3404 /* so hl know contains the address */
3405 freeAsmop(result,NULL,ic);
3407 /* if bit then unpack */
3408 if (IS_BITVAR(retype)) {
3412 size = AOP_SIZE(right);
3416 char *l = aopGet(AOP(right),offset,FALSE);
3418 if (isRegOrLit(AOP(right))) {
3419 emitcode("ld", "(hl),%s", l);
3423 emitcode("ld", "(hl),a", offset);
3426 emitcode("inc", "hl");
3432 freeAsmop(right,NULL,ic);
3435 /*-----------------------------------------------------------------*/
3436 /* genPointerSet - stores the value into a pointer location */
3437 /*-----------------------------------------------------------------*/
3438 static void genPointerSet (iCode *ic)
3440 operand *right, *result ;
3443 right = IC_RIGHT(ic);
3444 result = IC_RESULT(ic) ;
3446 /* depending on the type of pointer we need to
3447 move it to the correct pointer register */
3448 type = operandType(result);
3449 etype = getSpec(type);
3451 genGenPointerSet (right,result,ic);
3454 /*-----------------------------------------------------------------*/
3455 /* genIfx - generate code for Ifx statement */
3456 /*-----------------------------------------------------------------*/
3457 static void genIfx (iCode *ic, iCode *popIc)
3459 operand *cond = IC_COND(ic);
3462 aopOp(cond,ic,FALSE);
3464 /* get the value into acc */
3465 if (AOP_TYPE(cond) != AOP_CRY)
3469 /* the result is now in the accumulator */
3470 freeAsmop(cond,NULL,ic);
3472 /* if there was something to be popped then do it */
3476 /* if the condition is a bit variable */
3477 if (isbit && IS_ITEMP(cond) &&
3479 genIfxJump(ic,SPIL_LOC(cond)->rname);
3481 if (isbit && !IS_ITEMP(cond))
3482 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3489 /*-----------------------------------------------------------------*/
3490 /* genAddrOf - generates code for address of */
3491 /*-----------------------------------------------------------------*/
3492 static void genAddrOf (iCode *ic)
3494 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3496 aopOp(IC_RESULT(ic),ic,FALSE);
3498 /* if the operand is on the stack then we
3499 need to get the stack offset of this
3502 /* if it has an offset then we need to compute it */
3504 emitcode("lda", "hl,%d+%d(sp)", sym->stack, _spoffset);
3505 emitcode("ld", "d,h");
3506 emitcode("ld", "e,l");
3507 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3508 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3512 emitcode("push", "de");
3513 emitcode("push", "ix");
3514 emitcode("pop", "hl");
3515 emitcode("ld", "de,#%d", sym->stack);
3516 emitcode("add", "hl,de");
3517 emitcode("pop", "de");
3521 emitcode("ld", "hl,#%s", sym->rname);
3523 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3524 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3526 freeAsmop(IC_RESULT(ic),NULL,ic);
3529 /*-----------------------------------------------------------------*/
3530 /* genAssign - generate code for assignment */
3531 /*-----------------------------------------------------------------*/
3532 static void genAssign (iCode *ic)
3534 operand *result, *right;
3536 unsigned long lit = 0L;
3538 result = IC_RESULT(ic);
3539 right = IC_RIGHT(ic) ;
3542 /* Dont bother assigning if they are the same */
3543 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3544 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3549 aopOp(right,ic,FALSE);
3550 aopOp(result,ic,TRUE);
3552 /* if they are the same registers */
3553 if (sameRegs(AOP(right),AOP(result))) {
3554 emitcode("", "; (registers are the same)");
3558 /* if the result is a bit */
3559 if (AOP_TYPE(result) == AOP_CRY) {
3564 size = AOP_SIZE(result);
3567 if(AOP_TYPE(right) == AOP_LIT)
3568 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3570 (AOP_TYPE(result) != AOP_REG) &&
3571 (AOP_TYPE(right) == AOP_LIT) &&
3572 !IS_FLOAT(operandType(right)) &&
3574 bool fXored = FALSE;
3576 /* Work from the top down.
3577 Done this way so that we can use the cached copy of 0
3578 in A for a fast clear */
3580 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3581 if (!fXored && size>1) {
3582 emitcode("xor", "a,a");
3586 aopPut(AOP(result),"a",offset);
3589 aopPut(AOP(result), "#0", offset);
3594 aopGet(AOP(right),offset,FALSE),
3601 aopGet(AOP(right),offset,FALSE),
3608 freeAsmop(right,NULL,ic);
3609 freeAsmop(result,NULL,ic);
3612 /*-----------------------------------------------------------------*/
3613 /* genJumpTab - genrates code for jump table */
3614 /*-----------------------------------------------------------------*/
3615 static void genJumpTab (iCode *ic)
3620 aopOp(IC_JTCOND(ic),ic,FALSE);
3621 /* get the condition into accumulator */
3622 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3625 emitcode("push", "de");
3626 emitcode("ld", "e,%s", l);
3627 emitcode("ld", "d,#0");
3628 jtab = newiTempLabel(NULL);
3629 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3630 emitcode("add", "hl,de");
3631 emitcode("add", "hl,de");
3632 freeAsmop(IC_JTCOND(ic),NULL,ic);
3634 emitcode("pop", "de");
3635 emitcode("jp", "(hl)");
3636 emitcode("","%05d$:",jtab->key+100);
3637 /* now generate the jump labels */
3638 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3639 jtab = setNextItem(IC_JTLABELS(ic)))
3640 emitcode("jp", LABEL_STR, jtab->key+100);
3643 /*-----------------------------------------------------------------*/
3644 /* genCast - gen code for casting */
3645 /*-----------------------------------------------------------------*/
3646 static void genCast (iCode *ic)
3648 operand *result = IC_RESULT(ic);
3649 link *ctype = operandType(IC_LEFT(ic));
3650 operand *right = IC_RIGHT(ic);
3653 /* if they are equivalent then do nothing */
3654 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3657 aopOp(right,ic,FALSE) ;
3658 aopOp(result,ic,FALSE);
3660 /* if the result is a bit */
3661 if (AOP_TYPE(result) == AOP_CRY) {
3665 /* if they are the same size : or less */
3666 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3668 /* if they are in the same place */
3669 if (sameRegs(AOP(right),AOP(result)))
3672 /* if they in different places then copy */
3673 size = AOP_SIZE(result);
3677 aopGet(AOP(right),offset,FALSE),
3684 /* PENDING: should be OK. */
3686 /* if the result is of type pointer */
3687 if (IS_PTR(ctype)) {
3692 /* so we now know that the size of destination is greater
3693 than the size of the source */
3694 /* we move to result for the size of source */
3695 size = AOP_SIZE(right);
3699 aopGet(AOP(right),offset,FALSE),
3704 /* now depending on the sign of the destination */
3705 size = AOP_SIZE(result) - AOP_SIZE(right);
3706 /* Unsigned or not an integral type - right fill with zeros */
3707 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3709 aopPut(AOP(result),zero,offset++);
3711 /* we need to extend the sign :{ */
3712 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3715 emitcode("", "; genCast: sign extend untested.");
3716 emitcode("rla", "");
3717 emitcode("sbc", "a,a");
3719 aopPut(AOP(result),"a",offset++);
3723 freeAsmop(right, NULL, ic);
3724 freeAsmop(result, NULL, ic);
3727 /*-----------------------------------------------------------------*/
3728 /* genReceive - generate code for a receive iCode */
3729 /*-----------------------------------------------------------------*/
3730 static void genReceive (iCode *ic)
3732 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3733 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3734 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3738 aopOp(IC_RESULT(ic),ic,FALSE);
3740 assignResultValue(IC_RESULT(ic));
3743 freeAsmop(IC_RESULT(ic),NULL,ic);
3746 /*-----------------------------------------------------------------*/
3747 /* genZ80Code - generate code for Z80 based controllers */
3748 /*-----------------------------------------------------------------*/
3749 void genZ80Code (iCode *lic)
3756 _fReturn = _gbz80_return;
3757 _fTmp = _gbz80_return;
3760 _fReturn = _z80_return;
3761 _fTmp = _z80_return;
3764 lineHead = lineCurr = NULL;
3766 /* if debug information required */
3767 if (options.debug && currFunc) {
3768 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3770 if (IS_STATIC(currFunc->etype))
3771 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3773 emitcode("","G$%s$0$0 ==.",currFunc->name);
3776 /* stack pointer name */
3780 for (ic = lic ; ic ; ic = ic->next ) {
3782 if ( cln != ic->lineno ) {
3783 if ( options.debug ) {
3785 emitcode("","C$%s$%d$%d$%d ==.",
3786 ic->filename,ic->lineno,
3787 ic->level,ic->block);
3790 emitcode(";","%s %d",ic->filename,ic->lineno);
3793 /* if the result is marked as
3794 spilt and rematerializable or code for
3795 this has already been generated then
3797 if (resultRemat(ic) || ic->generated )
3800 /* depending on the operation */
3803 emitcode("", "; genNot");
3808 emitcode("", "; genCpl");
3813 emitcode("", "; genUminus");
3818 emitcode("", "; genIpush");
3823 /* IPOP happens only when trying to restore a
3824 spilt live range, if there is an ifx statement
3825 following this pop then the if statement might
3826 be using some of the registers being popped which
3827 would destory the contents of the register so
3828 we need to check for this condition and handle it */
3830 ic->next->op == IFX &&
3831 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3832 emitcode("", "; genIfx");
3833 genIfx (ic->next,ic);
3836 emitcode("", "; genIpop");
3842 emitcode("", "; genCall");
3847 emitcode("", "; genPcall");
3852 emitcode("", "; genFunction");
3857 emitcode("", "; genEndFunction");
3858 genEndFunction (ic);
3862 emitcode("", "; genRet");
3867 emitcode("", "; genLabel");
3872 emitcode("", "; genGoto");
3877 emitcode("", "; genPlus");
3882 emitcode("", "; genMinus");
3887 emitcode("", "; genMult");
3892 emitcode("", "; genDiv");
3897 emitcode("", "; genMod");
3902 emitcode("", "; genCmpGt");
3903 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3907 emitcode("", "; genCmpLt");
3908 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3915 /* note these two are xlated by algebraic equivalence
3916 during parsing SDCC.y */
3917 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3918 "got '>=' or '<=' shouldn't have come here");
3922 emitcode("", "; genCmpEq");
3923 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3927 emitcode("", "; genAndOp");
3932 emitcode("", "; genOrOp");
3937 emitcode("", "; genXor");
3938 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3942 emitcode("", "; genOr");
3943 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3947 emitcode("", "; genAnd");
3948 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3952 emitcode("", "; genInline");
3957 emitcode("", "; genRRC");
3962 emitcode("", "; genRLC");
3967 emitcode("", "; genHBIT");
3971 emitcode("", "; genLeftShift");
3976 emitcode("", "; genRightShift");
3980 case GET_VALUE_AT_ADDRESS:
3981 emitcode("", "; genPointerGet");
3987 if (POINTER_SET(ic)) {
3988 emitcode("", "; genAssign (pointer)");
3992 emitcode("", "; genAssign");
3998 emitcode("", "; genIfx");
4003 emitcode("", "; genAddrOf");
4008 emitcode("", "; genJumpTab");
4013 emitcode("", "; genCast");
4018 emitcode("", "; genReceive");
4023 emitcode("", "; addSet");
4024 addSet(&sendSet,ic);
4029 /* piCode(ic,stdout); */
4035 /* now we are ready to call the
4036 peep hole optimizer */
4037 if (!options.nopeep)
4038 peepHole (&lineHead);
4040 /* now do the actual printing */
4041 printLine (lineHead,codeOutFile);