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)
1168 /* if caller saves & we have not saved then */
1169 if (!ic->regsSaved) {
1173 /* if send set is not empty then assign */
1176 for (sic = setFirstItem(sendSet) ; sic ;
1177 sic = setNextItem(sendSet)) {
1178 int size, offset = 0;
1179 aopOp(IC_LEFT(sic),sic,FALSE);
1180 size = AOP_SIZE(IC_LEFT(sic));
1182 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1184 if (strcmp(l, _fReturn[offset]))
1185 emitcode("ld","%s,%s",
1190 freeAsmop (IC_LEFT(sic),NULL,sic);
1196 symbol *rlbl = newiTempLabel(NULL);
1198 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1199 emitcode("push", "hl");
1202 aopOp(IC_LEFT(ic),ic,FALSE);
1203 fetchHL(AOP(IC_LEFT(ic)));
1204 freeAsmop(IC_LEFT(ic),NULL,ic);
1206 emitcode("jp", "(hl)");
1207 emitcode("","%05d$:",(rlbl->key+100));
1212 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1213 OP_SYMBOL(IC_LEFT(ic))->rname :
1214 OP_SYMBOL(IC_LEFT(ic))->name;
1215 emitcode("call", "%s", name);
1218 /* if we need assign a result value */
1219 if ((IS_ITEMP(IC_RESULT(ic)) &&
1220 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1221 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1222 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1225 aopOp(IC_RESULT(ic),ic,FALSE);
1228 assignResultValue(IC_RESULT(ic));
1230 freeAsmop(IC_RESULT(ic),NULL, ic);
1233 /* adjust the stack for parameters if required */
1234 if (IC_LEFT(ic)->parmBytes) {
1235 int i = IC_LEFT(ic)->parmBytes;
1238 emitcode("ld", "hl,#%d", i);
1239 emitcode("add", "hl,sp");
1240 emitcode("ld", "sp,hl");
1244 emitcode("pop", "hl");
1248 emitcode("inc", "sp");
1254 /*-----------------------------------------------------------------*/
1255 /* genCall - generates a call statement */
1256 /*-----------------------------------------------------------------*/
1257 static void genCall (iCode *ic)
1259 emitCall(ic, FALSE);
1262 /*-----------------------------------------------------------------*/
1263 /* genPcall - generates a call by pointer statement */
1264 /*-----------------------------------------------------------------*/
1265 static void genPcall (iCode *ic)
1270 /*-----------------------------------------------------------------*/
1271 /* resultRemat - result is rematerializable */
1272 /*-----------------------------------------------------------------*/
1273 static int resultRemat (iCode *ic)
1275 if (SKIP_IC(ic) || ic->op == IFX)
1278 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1279 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1280 if (sym->remat && !POINTER_SET(ic))
1287 /*-----------------------------------------------------------------*/
1288 /* genFunction - generated code for function entry */
1289 /*-----------------------------------------------------------------*/
1290 static void genFunction (iCode *ic)
1296 /* create the function header */
1297 emitcode(";","-----------------------------------------");
1298 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1299 emitcode(";","-----------------------------------------");
1301 emitcode("","%s:",sym->rname);
1302 fetype = getSpec(operandType(IC_LEFT(ic)));
1304 /* if critical function then turn interrupts off */
1305 if (SPEC_CRTCL(fetype))
1308 /* if this is an interrupt service routine then
1309 save acc, b, dpl, dph */
1310 if (IS_ISR(sym->etype)) {
1311 emitcode("push", "af");
1312 emitcode("push", "bc");
1313 emitcode("push", "de");
1314 emitcode("push", "hl");
1316 /* PENDING: callee-save etc */
1318 /* adjust the stack for the function */
1319 emitcode("push", "bc");
1321 emitcode("push", "de");
1322 emitcode("push", "ix");
1323 emitcode("ld", "ix,#0");
1324 emitcode("add", "ix,sp");
1327 _lastStack = sym->stack;
1330 emitcode("ld", "hl,#-%d", sym->stack);
1331 emitcode("add", "hl,sp");
1332 emitcode("ld", "sp,hl");
1334 _spoffset = sym->stack;
1337 /*-----------------------------------------------------------------*/
1338 /* genEndFunction - generates epilogue for functions */
1339 /*-----------------------------------------------------------------*/
1340 static void genEndFunction (iCode *ic)
1342 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1344 if (IS_ISR(sym->etype)) {
1348 if (SPEC_CRTCL(sym->etype))
1351 /* PENDING: calleeSave */
1353 /* if debug then send end of function */
1354 if (options.debug && currFunc) {
1356 emitcode("","C$%s$%d$%d$%d ==.",
1357 ic->filename,currFunc->lastLine,
1358 ic->level,ic->block);
1359 if (IS_STATIC(currFunc->etype))
1360 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1362 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1366 emitcode("ld", "sp,ix");
1367 emitcode("pop", "ix");
1368 emitcode("pop", "de");
1372 emitcode("ld", "hl,#%d", _spoffset);
1373 emitcode("add", "hl,sp");
1374 emitcode("ld", "sp,hl");
1377 emitcode("pop", "bc");
1378 emitcode("ret", "");
1384 /*-----------------------------------------------------------------*/
1385 /* genRet - generate code for return statement */
1386 /*-----------------------------------------------------------------*/
1387 static void genRet (iCode *ic)
1390 /* Errk. This is a hack until I can figure out how
1391 to cause dehl to spill on a call */
1392 int size,offset = 0;
1394 /* if we have no return value then
1395 just generate the "ret" */
1399 /* we have something to return then
1400 move the return value into place */
1401 aopOp(IC_LEFT(ic),ic,FALSE);
1402 size = AOP_SIZE(IC_LEFT(ic));
1404 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1405 emitcode("ld", "hl,%s", l);
1409 l = aopGet(AOP(IC_LEFT(ic)),offset,
1411 if (strcmp(_fReturn[offset],l))
1412 emitcode("ld","%s,%s", _fReturn[offset++],l);
1415 freeAsmop (IC_LEFT(ic),NULL,ic);
1418 /* generate a jump to the return label
1419 if the next is not the return statement */
1420 if (!(ic->next && ic->next->op == LABEL &&
1421 IC_LABEL(ic->next) == returnLabel))
1423 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1426 /*-----------------------------------------------------------------*/
1427 /* genLabel - generates a label */
1428 /*-----------------------------------------------------------------*/
1429 static void genLabel (iCode *ic)
1431 /* special case never generate */
1432 if (IC_LABEL(ic) == entryLabel)
1435 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1438 /*-----------------------------------------------------------------*/
1439 /* genGoto - generates a ljmp */
1440 /*-----------------------------------------------------------------*/
1441 static void genGoto (iCode *ic)
1443 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1446 /*-----------------------------------------------------------------*/
1447 /* genPlusIncr :- does addition with increment if possible */
1448 /*-----------------------------------------------------------------*/
1449 static bool genPlusIncr (iCode *ic)
1451 unsigned int icount ;
1452 unsigned int size = getDataSize(IC_RESULT(ic));
1454 /* will try to generate an increment */
1455 /* if the right side is not a literal
1457 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1460 emitcode("", "; genPlusIncr");
1462 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1464 /* If result is a pair */
1465 if (isPair(AOP(IC_RESULT(ic)))) {
1466 char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1468 /* Both a lit on the right and a true symbol on the left */
1469 emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
1474 /* if the literal value of the right hand side
1475 is greater than 4 then it is not worth it */
1480 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1481 isPair(AOP(IC_RESULT(ic)))) {
1483 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1487 /* if increment 16 bits in register */
1488 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1491 symbol *tlbl = newiTempLabel(NULL);
1492 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1493 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1495 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1499 emitcode("", LABEL_STR ":",tlbl->key+100);
1503 /* If result is a pair */
1504 if (isPair(AOP(IC_RESULT(ic)))) {
1505 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1506 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1508 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1512 /* if the sizes are greater than 1 then we cannot */
1513 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1514 AOP_SIZE(IC_LEFT(ic)) > 1 )
1517 /* we can if the aops of the left & result match or
1518 if they are in registers and the registers are the
1520 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1522 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1530 /*-----------------------------------------------------------------*/
1531 /* outBitAcc - output a bit in acc */
1532 /*-----------------------------------------------------------------*/
1533 void outBitAcc(operand *result)
1535 symbol *tlbl = newiTempLabel(NULL);
1536 /* if the result is a bit */
1537 if (AOP_TYPE(result) == AOP_CRY){
1541 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1542 emitcode("ld","a,%s",one);
1543 emitcode("", LABEL_STR ":",tlbl->key+100);
1548 /*-----------------------------------------------------------------*/
1549 /* genPlus - generates code for addition */
1550 /*-----------------------------------------------------------------*/
1551 static void genPlus (iCode *ic)
1553 int size, offset = 0;
1555 /* special cases :- */
1557 aopOp (IC_LEFT(ic),ic,FALSE);
1558 aopOp (IC_RIGHT(ic),ic,FALSE);
1559 aopOp (IC_RESULT(ic),ic,TRUE);
1561 /* Swap the left and right operands if:
1563 if literal, literal on the right or
1564 if left requires ACC or right is already
1567 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1568 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1569 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1570 operand *t = IC_RIGHT(ic);
1571 IC_RIGHT(ic) = IC_LEFT(ic);
1575 /* if both left & right are in bit
1577 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1578 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1583 /* if left in bit space & right literal */
1584 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1585 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1586 /* Can happen I guess */
1590 /* if I can do an increment instead
1591 of add then GOOD for ME */
1592 if (genPlusIncr (ic) == TRUE)
1595 size = getDataSize(IC_RESULT(ic));
1597 /* Special case when left and right are constant */
1598 if (isPair(AOP(IC_RESULT(ic)))) {
1601 left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1602 right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1603 if (left && right) {
1607 sprintf(buffer, "#(%s + %s)", left, right);
1608 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1614 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1615 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1617 emitcode("add","a,%s",
1618 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1620 emitcode("adc","a,%s",
1621 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1623 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1625 emitcode("add","a,%s",
1626 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1628 emitcode("adc","a,%s",
1629 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1631 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1634 /* Some kind of pointer arith. */
1635 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1636 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1637 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1640 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1641 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1642 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1647 freeAsmop(IC_LEFT(ic),NULL,ic);
1648 freeAsmop(IC_RIGHT(ic),NULL,ic);
1649 freeAsmop(IC_RESULT(ic),NULL,ic);
1653 /*-----------------------------------------------------------------*/
1654 /* genMinusDec :- does subtraction with deccrement if possible */
1655 /*-----------------------------------------------------------------*/
1656 static bool genMinusDec (iCode *ic)
1658 unsigned int icount ;
1659 unsigned int size = getDataSize(IC_RESULT(ic));
1661 /* will try to generate an increment */
1662 /* if the right side is not a literal we cannot */
1663 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1666 /* if the literal value of the right hand side
1667 is greater than 4 then it is not worth it */
1668 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1671 size = getDataSize(IC_RESULT(ic));
1674 /* if increment 16 bits in register */
1675 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1678 symbol *tlbl = newiTempLabel(NULL);
1679 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1680 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1682 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1686 emitcode("", LABEL_STR ":",tlbl->key+100);
1691 /* if decrement 16 bits in register */
1692 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1693 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1695 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1699 /* If result is a pair */
1700 if (isPair(AOP(IC_RESULT(ic)))) {
1701 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1702 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1704 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1708 /* if the sizes are greater than 1 then we cannot */
1709 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1710 AOP_SIZE(IC_LEFT(ic)) > 1 )
1713 /* we can if the aops of the left & result match or if they are in
1714 registers and the registers are the same */
1715 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1717 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1724 /*-----------------------------------------------------------------*/
1725 /* genMinus - generates code for subtraction */
1726 /*-----------------------------------------------------------------*/
1727 static void genMinus (iCode *ic)
1729 int size, offset = 0;
1730 unsigned long lit = 0L;
1732 aopOp (IC_LEFT(ic),ic,FALSE);
1733 aopOp (IC_RIGHT(ic),ic,FALSE);
1734 aopOp (IC_RESULT(ic),ic,TRUE);
1736 /* special cases :- */
1737 /* if both left & right are in bit space */
1738 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1739 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1744 /* if I can do an decrement instead of subtract then GOOD for ME */
1745 if (genMinusDec (ic) == TRUE)
1748 size = getDataSize(IC_RESULT(ic));
1750 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1753 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1758 /* if literal, add a,#-lit, else normal subb */
1760 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1761 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1763 emitcode("sub","a,%s",
1764 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1766 emitcode("sbc","a,%s",
1767 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1770 /* first add without previous c */
1772 emitcode("add","a,#0x%02x",
1773 (unsigned int)(lit & 0x0FFL));
1775 emitcode("adc","a,#0x%02x",
1776 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1778 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1781 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1782 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1783 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1787 freeAsmop(IC_LEFT(ic),NULL,ic);
1788 freeAsmop(IC_RIGHT(ic),NULL,ic);
1789 freeAsmop(IC_RESULT(ic),NULL,ic);
1792 /*-----------------------------------------------------------------*/
1793 /* genMult - generates code for multiplication */
1794 /*-----------------------------------------------------------------*/
1795 static void genMult (iCode *ic)
1797 /* Shouldn't occur - all done through function calls */
1801 /*-----------------------------------------------------------------*/
1802 /* genDiv - generates code for division */
1803 /*-----------------------------------------------------------------*/
1804 static void genDiv (iCode *ic)
1806 /* Shouldn't occur - all done through function calls */
1810 /*-----------------------------------------------------------------*/
1811 /* genMod - generates code for division */
1812 /*-----------------------------------------------------------------*/
1813 static void genMod (iCode *ic)
1815 /* Shouldn't occur - all done through function calls */
1819 /*-----------------------------------------------------------------*/
1820 /* genIfxJump :- will create a jump depending on the ifx */
1821 /*-----------------------------------------------------------------*/
1822 static void genIfxJump (iCode *ic, char *jval)
1827 /* if true label then we jump if condition
1829 if ( IC_TRUE(ic) ) {
1831 if (!strcmp(jval, "a")) {
1834 else if (!strcmp(jval, "c")) {
1838 /* The buffer contains the bit on A that we should test */
1843 /* false label is present */
1844 jlbl = IC_FALSE(ic) ;
1845 if (!strcmp(jval, "a")) {
1848 else if (!strcmp(jval, "c")) {
1852 /* The buffer contains the bit on A that we should test */
1856 /* Z80 can do a conditional long jump */
1857 if (!strcmp(jval, "a")) {
1858 emitcode("or", "a,a");
1860 else if (!strcmp(jval, "c")) {
1863 emitcode("bit", "%s,a", jval);
1865 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1867 /* mark the icode as generated */
1871 /** Generic compare for > or <
1873 static void genCmp (operand *left,operand *right,
1874 operand *result, iCode *ifx, int sign)
1876 int size, offset = 0 ;
1877 unsigned long lit = 0L;
1879 /* if left & right are bit variables */
1880 if (AOP_TYPE(left) == AOP_CRY &&
1881 AOP_TYPE(right) == AOP_CRY ) {
1882 /* Cant happen on the Z80 */
1885 /* subtract right from left if at the
1886 end the carry flag is set then we know that
1887 left is greater than right */
1888 size = max(AOP_SIZE(left),AOP_SIZE(right));
1890 /* if unsigned char cmp with lit, just compare */
1892 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1893 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1895 emitcode("xor", "a,#0x80");
1896 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
1899 emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
1902 if(AOP_TYPE(right) == AOP_LIT) {
1903 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1904 /* optimize if(x < 0) or if(x >= 0) */
1907 /* No sign so it's always false */
1911 /* Just load in the top most bit */
1912 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1913 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1914 genIfxJump (ifx,"7");
1918 emitcode("rlc","a");
1924 /* First setup h and l contaning the top most bytes XORed */
1925 bool fDidXor = FALSE;
1926 if (AOP_TYPE(left) == AOP_LIT){
1927 unsigned long lit = (unsigned long)
1928 floatFromVal(AOP(left)->aopu.aop_lit);
1929 emitcode("ld", "%s,#0x%02x", _fTmp[0],
1930 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1933 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
1934 emitcode("xor", "a,#0x80");
1935 emitcode("ld", "%s,a", _fTmp[0]);
1938 if (AOP_TYPE(right) == AOP_LIT) {
1939 unsigned long lit = (unsigned long)
1940 floatFromVal(AOP(right)->aopu.aop_lit);
1941 emitcode("ld", "%s,#0x%02x", _fTmp[1],
1942 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1945 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
1946 emitcode("xor", "a,#0x80");
1947 emitcode("ld", "%s,a", _fTmp[1]);
1957 /* Do a long subtract */
1959 MOVA(aopGet(AOP(left),offset,FALSE));
1960 if (sign && size == 0) {
1961 emitcode("ld", "a,%s", _fTmp[0]);
1962 emitcode("sbc", "a,%s", _fTmp[1]);
1965 /* Subtract through, propagating the carry */
1966 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1973 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1976 /* if the result is used in the next
1977 ifx conditional branch then generate
1978 code a little differently */
1980 genIfxJump (ifx,"c");
1983 /* leave the result in acc */
1987 /*-----------------------------------------------------------------*/
1988 /* genCmpGt :- greater than comparison */
1989 /*-----------------------------------------------------------------*/
1990 static void genCmpGt (iCode *ic, iCode *ifx)
1992 operand *left, *right, *result;
1993 link *letype , *retype;
1997 right= IC_RIGHT(ic);
1998 result = IC_RESULT(ic);
2000 letype = getSpec(operandType(left));
2001 retype =getSpec(operandType(right));
2002 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2003 /* assign the amsops */
2004 aopOp (left,ic,FALSE);
2005 aopOp (right,ic,FALSE);
2006 aopOp (result,ic,TRUE);
2008 genCmp(right, left, result, ifx, sign);
2010 freeAsmop(left,NULL,ic);
2011 freeAsmop(right,NULL,ic);
2012 freeAsmop(result,NULL,ic);
2015 /*-----------------------------------------------------------------*/
2016 /* genCmpLt - less than comparisons */
2017 /*-----------------------------------------------------------------*/
2018 static void genCmpLt (iCode *ic, iCode *ifx)
2020 operand *left, *right, *result;
2021 link *letype , *retype;
2025 right= IC_RIGHT(ic);
2026 result = IC_RESULT(ic);
2028 letype = getSpec(operandType(left));
2029 retype =getSpec(operandType(right));
2030 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2032 /* assign the amsops */
2033 aopOp (left,ic,FALSE);
2034 aopOp (right,ic,FALSE);
2035 aopOp (result,ic,TRUE);
2037 genCmp(left, right, result, ifx, sign);
2039 freeAsmop(left,NULL,ic);
2040 freeAsmop(right,NULL,ic);
2041 freeAsmop(result,NULL,ic);
2044 /*-----------------------------------------------------------------*/
2045 /* gencjneshort - compare and jump if not equal */
2046 /*-----------------------------------------------------------------*/
2047 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2049 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2051 unsigned long lit = 0L;
2053 /* Swap the left and right if it makes the computation easier */
2054 if (AOP_TYPE(left) == AOP_LIT) {
2060 if(AOP_TYPE(right) == AOP_LIT)
2061 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2063 /* if the right side is a literal then anything goes */
2064 if (AOP_TYPE(right) == AOP_LIT &&
2065 AOP_TYPE(left) != AOP_DIR ) {
2067 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2068 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2069 emitcode("or", "a,a");
2071 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2072 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2076 /* if the right side is in a register or in direct space or
2077 if the left is a pointer register & right is not */
2078 else if (AOP_TYPE(right) == AOP_REG ||
2079 AOP_TYPE(right) == AOP_DIR ||
2080 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2082 MOVA(aopGet(AOP(left),offset,FALSE));
2083 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2084 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2086 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
2088 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2089 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2094 /* right is a pointer reg need both a & b */
2095 /* PENDING: is this required? */
2097 char *l = aopGet(AOP(left),offset,FALSE);
2098 MOVA(aopGet(AOP(right),offset,FALSE));
2099 emitcode("cp", "%s ; 5", l);
2100 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2106 /*-----------------------------------------------------------------*/
2107 /* gencjne - compare and jump if not equal */
2108 /*-----------------------------------------------------------------*/
2109 static void gencjne(operand *left, operand *right, symbol *lbl)
2111 symbol *tlbl = newiTempLabel(NULL);
2113 gencjneshort(left, right, lbl);
2116 emitcode("ld","a,%s",one);
2117 emitcode("jp", LABEL_STR ,tlbl->key+100);
2118 emitcode("", LABEL_STR ":",lbl->key+100);
2119 emitcode("xor","a,a");
2120 emitcode("", LABEL_STR ":",tlbl->key+100);
2123 /*-----------------------------------------------------------------*/
2124 /* genCmpEq - generates code for equal to */
2125 /*-----------------------------------------------------------------*/
2126 static void genCmpEq (iCode *ic, iCode *ifx)
2128 operand *left, *right, *result;
2130 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2131 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2132 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2134 /* Swap operands if it makes the operation easier. ie if:
2135 1. Left is a literal.
2137 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2138 operand *t = IC_RIGHT(ic);
2139 IC_RIGHT(ic) = IC_LEFT(ic);
2143 if (ifx && !AOP_SIZE(result)){
2145 /* if they are both bit variables */
2146 if (AOP_TYPE(left) == AOP_CRY &&
2147 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2150 tlbl = newiTempLabel(NULL);
2151 gencjneshort(left, right, tlbl);
2152 if ( IC_TRUE(ifx) ) {
2153 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2154 emitcode("", LABEL_STR ":",tlbl->key+100);
2156 /* PENDING: do this better */
2157 symbol *lbl = newiTempLabel(NULL);
2158 emitcode("jp", LABEL_STR ,lbl->key+100);
2159 emitcode("", LABEL_STR ":",tlbl->key+100);
2160 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2161 emitcode("", LABEL_STR ":",lbl->key+100);
2164 /* mark the icode as generated */
2169 /* if they are both bit variables */
2170 if (AOP_TYPE(left) == AOP_CRY &&
2171 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2174 gencjne(left,right,newiTempLabel(NULL));
2175 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2179 genIfxJump(ifx,"a");
2182 /* if the result is used in an arithmetic operation
2183 then put the result in place */
2184 if (AOP_TYPE(result) != AOP_CRY) {
2187 /* leave the result in acc */
2191 freeAsmop(left,NULL,ic);
2192 freeAsmop(right,NULL,ic);
2193 freeAsmop(result,NULL,ic);
2196 /*-----------------------------------------------------------------*/
2197 /* ifxForOp - returns the icode containing the ifx for operand */
2198 /*-----------------------------------------------------------------*/
2199 static iCode *ifxForOp ( operand *op, iCode *ic )
2201 /* if true symbol then needs to be assigned */
2202 if (IS_TRUE_SYMOP(op))
2205 /* if this has register type condition and
2206 the next instruction is ifx with the same operand
2207 and live to of the operand is upto the ifx only then */
2209 ic->next->op == IFX &&
2210 IC_COND(ic->next)->key == op->key &&
2211 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2217 /*-----------------------------------------------------------------*/
2218 /* genAndOp - for && operation */
2219 /*-----------------------------------------------------------------*/
2220 static void genAndOp (iCode *ic)
2222 operand *left,*right, *result;
2225 /* note here that && operations that are in an if statement are
2226 taken away by backPatchLabels only those used in arthmetic
2227 operations remain */
2228 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2229 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2230 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2232 /* if both are bit variables */
2233 if (AOP_TYPE(left) == AOP_CRY &&
2234 AOP_TYPE(right) == AOP_CRY ) {
2237 tlbl = newiTempLabel(NULL);
2239 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2241 emitcode("", LABEL_STR ":",tlbl->key+100);
2245 freeAsmop(left,NULL,ic);
2246 freeAsmop(right,NULL,ic);
2247 freeAsmop(result,NULL,ic);
2250 /*-----------------------------------------------------------------*/
2251 /* genOrOp - for || operation */
2252 /*-----------------------------------------------------------------*/
2253 static void genOrOp (iCode *ic)
2255 operand *left,*right, *result;
2258 /* note here that || operations that are in an
2259 if statement are taken away by backPatchLabels
2260 only those used in arthmetic operations remain */
2261 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2262 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2263 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2265 /* if both are bit variables */
2266 if (AOP_TYPE(left) == AOP_CRY &&
2267 AOP_TYPE(right) == AOP_CRY ) {
2270 tlbl = newiTempLabel(NULL);
2272 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2274 emitcode("", LABEL_STR,tlbl->key+100);
2278 freeAsmop(left,NULL,ic);
2279 freeAsmop(right,NULL,ic);
2280 freeAsmop(result,NULL,ic);
2283 /*-----------------------------------------------------------------*/
2284 /* isLiteralBit - test if lit == 2^n */
2285 /*-----------------------------------------------------------------*/
2286 int isLiteralBit(unsigned long lit)
2288 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2289 0x100L,0x200L,0x400L,0x800L,
2290 0x1000L,0x2000L,0x4000L,0x8000L,
2291 0x10000L,0x20000L,0x40000L,0x80000L,
2292 0x100000L,0x200000L,0x400000L,0x800000L,
2293 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2294 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2297 for(idx = 0; idx < 32; idx++)
2303 /*-----------------------------------------------------------------*/
2304 /* genAnd - code for and */
2305 /*-----------------------------------------------------------------*/
2306 static void genAnd (iCode *ic, iCode *ifx)
2308 operand *left, *right, *result;
2310 unsigned long lit = 0L;
2313 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2314 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2315 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2318 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2320 AOP_TYPE(left), AOP_TYPE(right));
2321 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2323 AOP_SIZE(left), AOP_SIZE(right));
2326 /* if left is a literal & right is not then exchange them */
2327 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2328 AOP_NEEDSACC(left)) {
2329 operand *tmp = right ;
2334 /* if result = right then exchange them */
2335 if(sameRegs(AOP(result),AOP(right))){
2336 operand *tmp = right ;
2341 /* if right is bit then exchange them */
2342 if (AOP_TYPE(right) == AOP_CRY &&
2343 AOP_TYPE(left) != AOP_CRY){
2344 operand *tmp = right ;
2348 if(AOP_TYPE(right) == AOP_LIT)
2349 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2351 size = AOP_SIZE(result);
2353 if (AOP_TYPE(left) == AOP_CRY){
2358 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2359 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2360 if((AOP_TYPE(right) == AOP_LIT) &&
2361 (AOP_TYPE(result) == AOP_CRY) &&
2362 (AOP_TYPE(left) != AOP_CRY)) {
2363 int posbit = isLiteralBit(lit);
2367 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2371 emitcode("mov","c,acc.%d",posbit&0x07);
2376 sprintf(buffer, "%d", posbit&0x07);
2377 genIfxJump(ifx, buffer);
2385 symbol *tlbl = newiTempLabel(NULL);
2386 int sizel = AOP_SIZE(left);
2389 emitcode("setb","c");
2392 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2393 MOVA( aopGet(AOP(left),offset,FALSE));
2395 if((posbit = isLiteralBit(bytelit)) != 0) {
2397 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2400 if(bytelit != 0x0FFL)
2401 emitcode("and","a,%s",
2402 aopGet(AOP(right),offset,FALSE));
2403 emitcode("jr","nz, %05d$",tlbl->key+100);
2408 // bit = left & literal
2410 emitcode("clr","c");
2411 emitcode("","%05d$:",tlbl->key+100);
2413 // if(left & literal)
2417 jmpTrueOrFalse(ifx, tlbl);
2428 /* if left is same as result */
2429 if(sameRegs(AOP(result),AOP(left))){
2430 for(;size--; offset++) {
2431 if(AOP_TYPE(right) == AOP_LIT){
2432 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2436 aopPut(AOP(result),zero,offset);
2438 MOVA(aopGet(AOP(left),offset,FALSE));
2439 emitcode("and","a,%s",
2440 aopGet(AOP(right),offset,FALSE));
2441 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2446 if (AOP_TYPE(left) == AOP_ACC) {
2450 MOVA(aopGet(AOP(right),offset,FALSE));
2451 emitcode("and","%s,a",
2452 aopGet(AOP(left),offset,FALSE));
2457 // left & result in different registers
2458 if(AOP_TYPE(result) == AOP_CRY){
2461 for(;(size--);offset++) {
2463 // result = left & right
2464 if(AOP_TYPE(right) == AOP_LIT){
2465 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2467 aopGet(AOP(left),offset,FALSE),
2470 } else if(bytelit == 0){
2471 aopPut(AOP(result),zero,offset);
2475 // faster than result <- left, anl result,right
2476 // and better if result is SFR
2477 if (AOP_TYPE(left) == AOP_ACC)
2478 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2480 MOVA(aopGet(AOP(right),offset,FALSE));
2481 emitcode("and","a,%s",
2482 aopGet(AOP(left),offset,FALSE));
2484 aopPut(AOP(result),"a",offset);
2491 freeAsmop(left,NULL,ic);
2492 freeAsmop(right,NULL,ic);
2493 freeAsmop(result,NULL,ic);
2496 /*-----------------------------------------------------------------*/
2497 /* genOr - code for or */
2498 /*-----------------------------------------------------------------*/
2499 static void genOr (iCode *ic, iCode *ifx)
2501 operand *left, *right, *result;
2503 unsigned long lit = 0L;
2505 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2506 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2507 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2510 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2512 AOP_TYPE(left), AOP_TYPE(right));
2513 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2515 AOP_SIZE(left), AOP_SIZE(right));
2518 /* if left is a literal & right is not then exchange them */
2519 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2520 AOP_NEEDSACC(left)) {
2521 operand *tmp = right ;
2526 /* if result = right then exchange them */
2527 if(sameRegs(AOP(result),AOP(right))){
2528 operand *tmp = right ;
2533 /* if right is bit then exchange them */
2534 if (AOP_TYPE(right) == AOP_CRY &&
2535 AOP_TYPE(left) != AOP_CRY){
2536 operand *tmp = right ;
2540 if(AOP_TYPE(right) == AOP_LIT)
2541 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2543 size = AOP_SIZE(result);
2545 if (AOP_TYPE(left) == AOP_CRY){
2550 if((AOP_TYPE(right) == AOP_LIT) &&
2551 (AOP_TYPE(result) == AOP_CRY) &&
2552 (AOP_TYPE(left) != AOP_CRY)){
2557 /* if left is same as result */
2558 if(sameRegs(AOP(result),AOP(left))){
2559 for(;size--; offset++) {
2560 if(AOP_TYPE(right) == AOP_LIT){
2561 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2564 emitcode("or","%s,%s; 5",
2565 aopGet(AOP(left),offset,FALSE),
2566 aopGet(AOP(right),offset,FALSE));
2568 if (AOP_TYPE(left) == AOP_ACC)
2569 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2571 MOVA(aopGet(AOP(right),offset,FALSE));
2572 emitcode("or","a,%s ; 7",
2573 aopGet(AOP(left),offset,FALSE));
2574 aopPut(AOP(result),"a ; 8",0);
2579 // left & result in different registers
2580 if(AOP_TYPE(result) == AOP_CRY){
2582 } else for(;(size--);offset++){
2584 // result = left & right
2585 if(AOP_TYPE(right) == AOP_LIT){
2586 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2588 aopGet(AOP(left),offset,FALSE),
2593 // faster than result <- left, anl result,right
2594 // and better if result is SFR
2595 if (AOP_TYPE(left) == AOP_ACC)
2596 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2598 MOVA(aopGet(AOP(right),offset,FALSE));
2599 emitcode("or","a,%s",
2600 aopGet(AOP(left),offset,FALSE));
2602 aopPut(AOP(result),"a",offset);
2603 /* PENDING: something weird is going on here. Add exception. */
2604 if (AOP_TYPE(result) == AOP_ACC)
2610 freeAsmop(left,NULL,ic);
2611 freeAsmop(right,NULL,ic);
2612 freeAsmop(result,NULL,ic);
2615 /*-----------------------------------------------------------------*/
2616 /* genXor - code for xclusive or */
2617 /*-----------------------------------------------------------------*/
2618 static void genXor (iCode *ic, iCode *ifx)
2620 operand *left, *right, *result;
2622 unsigned long lit = 0L;
2624 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2625 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2626 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2628 /* if left is a literal & right is not then exchange them */
2629 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2630 AOP_NEEDSACC(left)) {
2631 operand *tmp = right ;
2636 /* if result = right then exchange them */
2637 if(sameRegs(AOP(result),AOP(right))){
2638 operand *tmp = right ;
2643 /* if right is bit then exchange them */
2644 if (AOP_TYPE(right) == AOP_CRY &&
2645 AOP_TYPE(left) != AOP_CRY){
2646 operand *tmp = right ;
2650 if(AOP_TYPE(right) == AOP_LIT)
2651 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2653 size = AOP_SIZE(result);
2655 if (AOP_TYPE(left) == AOP_CRY){
2660 if((AOP_TYPE(right) == AOP_LIT) &&
2661 (AOP_TYPE(result) == AOP_CRY) &&
2662 (AOP_TYPE(left) != AOP_CRY)){
2667 /* if left is same as result */
2668 if(sameRegs(AOP(result),AOP(left))){
2669 for(;size--; offset++) {
2670 if(AOP_TYPE(right) == AOP_LIT){
2671 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2674 MOVA(aopGet(AOP(right),offset,FALSE));
2675 emitcode("xor","a,%s",
2676 aopGet(AOP(left),offset,FALSE));
2677 aopPut(AOP(result),"a",0);
2680 if (AOP_TYPE(left) == AOP_ACC)
2681 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2683 MOVA(aopGet(AOP(right),offset,FALSE));
2684 emitcode("xor","a,%s",
2685 aopGet(AOP(left),offset,FALSE));
2686 aopPut(AOP(result),"a",0);
2691 // left & result in different registers
2692 if(AOP_TYPE(result) == AOP_CRY){
2694 } else for(;(size--);offset++){
2696 // result = left & right
2697 if(AOP_TYPE(right) == AOP_LIT){
2698 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2700 aopGet(AOP(left),offset,FALSE),
2705 // faster than result <- left, anl result,right
2706 // and better if result is SFR
2707 if (AOP_TYPE(left) == AOP_ACC)
2708 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2710 MOVA(aopGet(AOP(right),offset,FALSE));
2711 emitcode("xor","a,%s",
2712 aopGet(AOP(left),offset,FALSE));
2713 aopPut(AOP(result),"a",0);
2715 aopPut(AOP(result),"a",offset);
2720 freeAsmop(left,NULL,ic);
2721 freeAsmop(right,NULL,ic);
2722 freeAsmop(result,NULL,ic);
2725 /*-----------------------------------------------------------------*/
2726 /* genInline - write the inline code out */
2727 /*-----------------------------------------------------------------*/
2728 static void genInline (iCode *ic)
2730 char buffer[MAX_INLINEASM];
2734 inLine += (!options.asmpeep);
2735 strcpy(buffer,IC_INLINE(ic));
2737 /* emit each line as a code */
2756 /* emitcode("",buffer); */
2757 inLine -= (!options.asmpeep);
2760 /*-----------------------------------------------------------------*/
2761 /* genRRC - rotate right with carry */
2762 /*-----------------------------------------------------------------*/
2763 static void genRRC (iCode *ic)
2768 /*-----------------------------------------------------------------*/
2769 /* genRLC - generate code for rotate left with carry */
2770 /*-----------------------------------------------------------------*/
2771 static void genRLC (iCode *ic)
2776 /*-----------------------------------------------------------------*/
2777 /* shiftR2Left2Result - shift right two bytes from left to result */
2778 /*-----------------------------------------------------------------*/
2779 static void shiftR2Left2Result (operand *left, int offl,
2780 operand *result, int offr,
2781 int shCount, int sign)
2783 if(sameRegs(AOP(result), AOP(left)) &&
2784 ((offl + MSB16) == offr)){
2787 movLeft2Result(left, offl, result, offr, 0);
2788 movLeft2Result(left, offl+1, result, offr+1, 0);
2795 /* if (AOP(result)->type == AOP_REG) {*/
2798 symbol *tlbl , *tlbl1;
2801 /* Left is already in result - so now do the shift */
2803 emitcode("ld","a,#%u+1", shCount);
2804 tlbl = newiTempLabel(NULL);
2805 tlbl1 = newiTempLabel(NULL);
2806 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2807 emitcode("", LABEL_STR ":",tlbl->key+100);
2810 emitcode("or", "a,a");
2813 l = aopGet(AOP(result), --offset, FALSE);
2814 emitcode("rr","%s", l);
2817 emitcode("", LABEL_STR ":",tlbl1->key+100);
2818 emitcode("dec", "a");
2819 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2824 /*-----------------------------------------------------------------*/
2825 /* shiftL2Left2Result - shift left two bytes from left to result */
2826 /*-----------------------------------------------------------------*/
2827 static void shiftL2Left2Result (operand *left, int offl,
2828 operand *result, int offr, int shCount)
2830 if(sameRegs(AOP(result), AOP(left)) &&
2831 ((offl + MSB16) == offr)){
2834 /* Copy left into result */
2835 movLeft2Result(left, offl, result, offr, 0);
2836 movLeft2Result(left, offl+1, result, offr+1, 0);
2838 /* PENDING: for now just see if it'll work. */
2839 /*if (AOP(result)->type == AOP_REG) { */
2843 symbol *tlbl , *tlbl1;
2846 /* Left is already in result - so now do the shift */
2848 emitcode("ld","a,#%u+1", shCount);
2849 tlbl = newiTempLabel(NULL);
2850 tlbl1 = newiTempLabel(NULL);
2851 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2852 emitcode("", LABEL_STR ":",tlbl->key+100);
2855 emitcode("or", "a,a");
2857 l = aopGet(AOP(result),offset++,FALSE);
2858 emitcode("rl","%s", l);
2861 emitcode("", LABEL_STR ":",tlbl1->key+100);
2862 emitcode("dec", "a");
2863 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2868 /*-----------------------------------------------------------------*/
2869 /* AccRol - rotate left accumulator by known count */
2870 /*-----------------------------------------------------------------*/
2871 static void AccRol (int shCount)
2873 shCount &= 0x0007; // shCount : 0..7
2910 /*-----------------------------------------------------------------*/
2911 /* AccLsh - left shift accumulator by known count */
2912 /*-----------------------------------------------------------------*/
2913 static void AccLsh (int shCount)
2917 emitcode("add","a,a");
2920 emitcode("add","a,a");
2921 emitcode("add","a,a");
2923 /* rotate left accumulator */
2925 /* and kill the lower order bits */
2926 emitcode("and","a,#0x%02x", SLMask[shCount]);
2931 /*-----------------------------------------------------------------*/
2932 /* shiftL1Left2Result - shift left one byte from left to result */
2933 /*-----------------------------------------------------------------*/
2934 static void shiftL1Left2Result (operand *left, int offl,
2935 operand *result, int offr, int shCount)
2938 l = aopGet(AOP(left),offl,FALSE);
2940 /* shift left accumulator */
2942 aopPut(AOP(result),"a",offr);
2946 /*-----------------------------------------------------------------*/
2947 /* genlshTwo - left shift two bytes by known amount != 0 */
2948 /*-----------------------------------------------------------------*/
2949 static void genlshTwo (operand *result,operand *left, int shCount)
2951 int size = AOP_SIZE(result);
2955 /* if shCount >= 8 */
2961 movLeft2Result(left, LSB, result, MSB16, 0);
2962 aopPut(AOP(result),zero, 0);
2963 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2966 movLeft2Result(left, LSB, result, MSB16, 0);
2967 aopPut(AOP(result),zero, 0);
2970 aopPut(AOP(result),zero,LSB);
2972 /* 1 <= shCount <= 7 */
2978 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2983 /*-----------------------------------------------------------------*/
2984 /* genlshOne - left shift a one byte quantity by known count */
2985 /*-----------------------------------------------------------------*/
2986 static void genlshOne (operand *result, operand *left, int shCount)
2988 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2991 /*-----------------------------------------------------------------*/
2992 /* genLeftShiftLiteral - left shifting by known count */
2993 /*-----------------------------------------------------------------*/
2994 static void genLeftShiftLiteral (operand *left,
2999 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3002 freeAsmop(right,NULL,ic);
3004 aopOp(left,ic,FALSE);
3005 aopOp(result,ic,FALSE);
3007 size = getSize(operandType(result));
3010 emitcode("; shift left ","result %d, left %d",size,
3014 /* I suppose that the left size >= result size */
3019 else if(shCount >= (size * 8))
3021 aopPut(AOP(result),zero,size);
3025 genlshOne (result,left,shCount);
3028 genlshTwo (result,left,shCount);
3037 freeAsmop(left,NULL,ic);
3038 freeAsmop(result,NULL,ic);
3041 /*-----------------------------------------------------------------*/
3042 /* genLeftShift - generates code for left shifting */
3043 /*-----------------------------------------------------------------*/
3044 static void genLeftShift (iCode *ic)
3048 symbol *tlbl , *tlbl1;
3049 operand *left,*right, *result;
3051 right = IC_RIGHT(ic);
3053 result = IC_RESULT(ic);
3055 aopOp(right,ic,FALSE);
3057 /* if the shift count is known then do it
3058 as efficiently as possible */
3059 if (AOP_TYPE(right) == AOP_LIT) {
3060 genLeftShiftLiteral (left,right,result,ic);
3064 /* shift count is unknown then we have to form a loop get the loop
3065 count in B : Note: we take only the lower order byte since
3066 shifting more that 32 bits make no sense anyway, ( the largest
3067 size of an object can be only 32 bits ) */
3068 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3069 emitcode("inc","a");
3070 freeAsmop (right,NULL,ic);
3071 aopOp(left,ic,FALSE);
3072 aopOp(result,ic,FALSE);
3074 /* now move the left to the result if they are not the
3077 if (!sameRegs(AOP(left),AOP(result))) {
3079 size = AOP_SIZE(result);
3082 l = aopGet(AOP(left),offset,FALSE);
3083 aopPut(AOP(result),l,offset);
3088 size = AOP_SIZE(result);
3091 l = aopGet(AOP(left),offset,FALSE);
3092 aopPut(AOP(result),l,offset);
3098 tlbl = newiTempLabel(NULL);
3099 size = AOP_SIZE(result);
3101 tlbl1 = newiTempLabel(NULL);
3103 emitcode("jp", LABEL_STR ,tlbl1->key+100);
3104 emitcode("", LABEL_STR ":",tlbl->key+100);
3105 l = aopGet(AOP(result),offset,FALSE);
3106 emitcode("or", "a,a");
3108 l = aopGet(AOP(result),offset++,FALSE);
3109 emitcode("rl","%s", l);
3111 emitcode("", LABEL_STR ":",tlbl1->key+100);
3112 emitcode("dec", "a");
3113 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
3115 freeAsmop(left,NULL,ic);
3116 freeAsmop(result,NULL,ic);
3119 /* genlshTwo - left shift two bytes by known amount != 0 */
3120 /*-----------------------------------------------------------------*/
3121 static void genrshOne (operand *result,operand *left, int shCount)
3124 int size = AOP_SIZE(result);
3130 l = aopGet(AOP(left),0,FALSE);
3131 if (AOP(result)->type == AOP_REG) {
3132 aopPut(AOP(result), l, 0);
3133 l = aopGet(AOP(result), 0, FALSE);
3135 emitcode("srl", "%s", l);
3140 emitcode("srl", "a");
3142 aopPut(AOP(result),"a",0);
3146 /*-----------------------------------------------------------------*/
3147 /* AccRsh - right shift accumulator by known count */
3148 /*-----------------------------------------------------------------*/
3149 static void AccRsh (int shCount)
3156 /* rotate right accumulator */
3157 AccRol(8 - shCount);
3158 /* and kill the higher order bits */
3159 emitcode("and","a,#0x%02x", SRMask[shCount]);
3164 /*-----------------------------------------------------------------*/
3165 /* shiftR1Left2Result - shift right one byte from left to result */
3166 /*-----------------------------------------------------------------*/
3167 static void shiftR1Left2Result (operand *left, int offl,
3168 operand *result, int offr,
3169 int shCount, int sign)
3171 MOVA(aopGet(AOP(left),offl,FALSE));
3178 aopPut(AOP(result),"a",offr);
3181 /*-----------------------------------------------------------------*/
3182 /* genrshTwo - right shift two bytes by known amount != 0 */
3183 /*-----------------------------------------------------------------*/
3184 static void genrshTwo (operand *result,operand *left,
3185 int shCount, int sign)
3187 /* if shCount >= 8 */
3192 shiftR1Left2Result(left, MSB16, result, LSB,
3196 movLeft2Result(left, MSB16, result, LSB, sign);
3197 aopPut(AOP(result),zero,1);
3200 /* 1 <= shCount <= 7 */
3202 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3206 /*-----------------------------------------------------------------*/
3207 /* genRightShiftLiteral - left shifting by known count */
3208 /*-----------------------------------------------------------------*/
3209 static void genRightShiftLiteral (operand *left,
3214 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3217 freeAsmop(right,NULL,ic);
3219 aopOp(left,ic,FALSE);
3220 aopOp(result,ic,FALSE);
3222 size = getSize(operandType(result));
3224 emitcode("; shift right ","result %d, left %d",size,
3227 /* I suppose that the left size >= result size */
3232 else if(shCount >= (size * 8))
3234 aopPut(AOP(result),zero,size);
3238 genrshOne(result, left, shCount);
3241 /* PENDING: sign support */
3242 genrshTwo(result, left, shCount, FALSE);
3251 freeAsmop(left,NULL,ic);
3252 freeAsmop(result,NULL,ic);
3255 /*-----------------------------------------------------------------*/
3256 /* genRightShift - generate code for right shifting */
3257 /*-----------------------------------------------------------------*/
3258 static void genRightShift (iCode *ic)
3260 operand *left,*right, *result;
3262 right = IC_RIGHT(ic);
3264 result = IC_RESULT(ic);
3266 aopOp(right,ic,FALSE);
3268 /* if the shift count is known then do it
3269 as efficiently as possible */
3270 if (AOP_TYPE(right) == AOP_LIT) {
3271 genRightShiftLiteral (left,right,result,ic);
3279 /*-----------------------------------------------------------------*/
3280 /* genGenPointerGet - gget value from generic pointer space */
3281 /*-----------------------------------------------------------------*/
3282 static void genGenPointerGet (operand *left,
3283 operand *result, iCode *ic)
3286 link *retype = getSpec(operandType(result));
3287 const char *ptr = "hl";
3292 aopOp(left,ic,FALSE);
3293 aopOp(result,ic,FALSE);
3295 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3297 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3298 aopPut(AOP(result),"a", 0);
3299 freeAsmop(left,NULL,ic);
3303 /* For now we always load into IY */
3304 /* if this is remateriazable */
3305 if (AOP_TYPE(left) == AOP_IMMD)
3306 emitcode("ld","%s,%s", ptr, aopGet(AOP(left),0,TRUE));
3307 else { /* we need to get it byte by byte */
3309 emitcode("ld", "e,%s", aopGet(AOP(left), 0, FALSE));
3310 emitcode("ld", "d,%s", aopGet(AOP(left), 1, FALSE));
3315 /* so iy now contains the address */
3316 freeAsmop(left,NULL,ic);
3318 /* if bit then unpack */
3319 if (IS_BITVAR(retype)) {
3323 size = AOP_SIZE(result);
3327 /* PENDING: make this better */
3328 if (!IS_GB && AOP(result)->type == AOP_REG) {
3329 aopPut(AOP(result),"(hl)",offset++);
3332 emitcode("ld", "a,(%s)", ptr, offset);
3333 aopPut(AOP(result),"a",offset++);
3336 emitcode("inc", "%s", ptr);
3342 freeAsmop(result,NULL,ic);
3345 /*-----------------------------------------------------------------*/
3346 /* genPointerGet - generate code for pointer get */
3347 /*-----------------------------------------------------------------*/
3348 static void genPointerGet (iCode *ic)
3350 operand *left, *result ;
3354 result = IC_RESULT(ic) ;
3356 /* depending on the type of pointer we need to
3357 move it to the correct pointer register */
3358 type = operandType(left);
3359 etype = getSpec(type);
3361 genGenPointerGet (left,result,ic);
3364 bool isRegOrLit(asmop *aop)
3366 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3371 /*-----------------------------------------------------------------*/
3372 /* genGenPointerSet - stores the value into a pointer location */
3373 /*-----------------------------------------------------------------*/
3374 static void genGenPointerSet (operand *right,
3375 operand *result, iCode *ic)
3378 link *retype = getSpec(operandType(right));
3380 aopOp(result,ic,FALSE);
3381 aopOp(right,ic,FALSE);
3383 /* Handle the exceptions first */
3384 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3386 char *l = aopGet(AOP(right), 0, FALSE);
3388 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3389 freeAsmop(result,NULL,ic);
3393 /* if the operand is already in dptr
3394 then we do nothing else we move the value to dptr */
3395 if (AOP_TYPE(result) != AOP_STR) {
3396 /* if this is remateriazable */
3397 if (AOP_TYPE(result) == AOP_IMMD) {
3398 emitcode("", "; Error 2");
3399 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3401 else { /* we need to get it byte by byte */
3402 /* PENDING: do this better */
3403 fetchHL(AOP(result));
3406 /* so hl know contains the address */
3407 freeAsmop(result,NULL,ic);
3409 /* if bit then unpack */
3410 if (IS_BITVAR(retype)) {
3414 size = AOP_SIZE(right);
3418 char *l = aopGet(AOP(right),offset,FALSE);
3420 if (isRegOrLit(AOP(right))) {
3421 emitcode("ld", "(hl),%s", l);
3425 emitcode("ld", "(hl),a", offset);
3428 emitcode("inc", "hl");
3434 freeAsmop(right,NULL,ic);
3437 /*-----------------------------------------------------------------*/
3438 /* genPointerSet - stores the value into a pointer location */
3439 /*-----------------------------------------------------------------*/
3440 static void genPointerSet (iCode *ic)
3442 operand *right, *result ;
3445 right = IC_RIGHT(ic);
3446 result = IC_RESULT(ic) ;
3448 /* depending on the type of pointer we need to
3449 move it to the correct pointer register */
3450 type = operandType(result);
3451 etype = getSpec(type);
3453 genGenPointerSet (right,result,ic);
3456 /*-----------------------------------------------------------------*/
3457 /* genIfx - generate code for Ifx statement */
3458 /*-----------------------------------------------------------------*/
3459 static void genIfx (iCode *ic, iCode *popIc)
3461 operand *cond = IC_COND(ic);
3464 aopOp(cond,ic,FALSE);
3466 /* get the value into acc */
3467 if (AOP_TYPE(cond) != AOP_CRY)
3471 /* the result is now in the accumulator */
3472 freeAsmop(cond,NULL,ic);
3474 /* if there was something to be popped then do it */
3478 /* if the condition is a bit variable */
3479 if (isbit && IS_ITEMP(cond) &&
3481 genIfxJump(ic,SPIL_LOC(cond)->rname);
3483 if (isbit && !IS_ITEMP(cond))
3484 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3491 /*-----------------------------------------------------------------*/
3492 /* genAddrOf - generates code for address of */
3493 /*-----------------------------------------------------------------*/
3494 static void genAddrOf (iCode *ic)
3496 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3498 aopOp(IC_RESULT(ic),ic,FALSE);
3500 /* if the operand is on the stack then we
3501 need to get the stack offset of this
3504 /* if it has an offset then we need to compute it */
3506 emitcode("lda", "hl,%d+%d(sp)", sym->stack, _spoffset);
3507 emitcode("ld", "d,h");
3508 emitcode("ld", "e,l");
3509 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3510 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3514 emitcode("push", "de");
3515 emitcode("push", "ix");
3516 emitcode("pop", "hl");
3517 emitcode("ld", "de,#%d", sym->stack);
3518 emitcode("add", "hl,de");
3519 emitcode("pop", "de");
3523 emitcode("ld", "hl,#%s", sym->rname);
3525 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3526 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3528 freeAsmop(IC_RESULT(ic),NULL,ic);
3531 /*-----------------------------------------------------------------*/
3532 /* genAssign - generate code for assignment */
3533 /*-----------------------------------------------------------------*/
3534 static void genAssign (iCode *ic)
3536 operand *result, *right;
3538 unsigned long lit = 0L;
3540 result = IC_RESULT(ic);
3541 right = IC_RIGHT(ic) ;
3544 /* Dont bother assigning if they are the same */
3545 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3546 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3551 aopOp(right,ic,FALSE);
3552 aopOp(result,ic,TRUE);
3554 /* if they are the same registers */
3555 if (sameRegs(AOP(right),AOP(result))) {
3556 emitcode("", "; (registers are the same)");
3560 /* if the result is a bit */
3561 if (AOP_TYPE(result) == AOP_CRY) {
3566 size = AOP_SIZE(result);
3569 if(AOP_TYPE(right) == AOP_LIT)
3570 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3572 (AOP_TYPE(result) != AOP_REG) &&
3573 (AOP_TYPE(right) == AOP_LIT) &&
3574 !IS_FLOAT(operandType(right)) &&
3576 bool fXored = FALSE;
3578 /* Work from the top down.
3579 Done this way so that we can use the cached copy of 0
3580 in A for a fast clear */
3582 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3583 if (!fXored && size>1) {
3584 emitcode("xor", "a,a");
3588 aopPut(AOP(result),"a",offset);
3591 aopPut(AOP(result), "#0", offset);
3596 aopGet(AOP(right),offset,FALSE),
3603 aopGet(AOP(right),offset,FALSE),
3610 freeAsmop(right,NULL,ic);
3611 freeAsmop(result,NULL,ic);
3614 /*-----------------------------------------------------------------*/
3615 /* genJumpTab - genrates code for jump table */
3616 /*-----------------------------------------------------------------*/
3617 static void genJumpTab (iCode *ic)
3622 aopOp(IC_JTCOND(ic),ic,FALSE);
3623 /* get the condition into accumulator */
3624 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3627 emitcode("push", "de");
3628 emitcode("ld", "e,%s", l);
3629 emitcode("ld", "d,#0");
3630 jtab = newiTempLabel(NULL);
3631 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3632 emitcode("add", "hl,de");
3633 emitcode("add", "hl,de");
3634 freeAsmop(IC_JTCOND(ic),NULL,ic);
3636 emitcode("pop", "de");
3637 emitcode("jp", "(hl)");
3638 emitcode("","%05d$:",jtab->key+100);
3639 /* now generate the jump labels */
3640 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3641 jtab = setNextItem(IC_JTLABELS(ic)))
3642 emitcode("jp", LABEL_STR, jtab->key+100);
3645 /*-----------------------------------------------------------------*/
3646 /* genCast - gen code for casting */
3647 /*-----------------------------------------------------------------*/
3648 static void genCast (iCode *ic)
3650 operand *result = IC_RESULT(ic);
3651 link *ctype = operandType(IC_LEFT(ic));
3652 operand *right = IC_RIGHT(ic);
3655 /* if they are equivalent then do nothing */
3656 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3659 aopOp(right,ic,FALSE) ;
3660 aopOp(result,ic,FALSE);
3662 /* if the result is a bit */
3663 if (AOP_TYPE(result) == AOP_CRY) {
3667 /* if they are the same size : or less */
3668 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3670 /* if they are in the same place */
3671 if (sameRegs(AOP(right),AOP(result)))
3674 /* if they in different places then copy */
3675 size = AOP_SIZE(result);
3679 aopGet(AOP(right),offset,FALSE),
3686 /* PENDING: should be OK. */
3688 /* if the result is of type pointer */
3689 if (IS_PTR(ctype)) {
3694 /* so we now know that the size of destination is greater
3695 than the size of the source */
3696 /* we move to result for the size of source */
3697 size = AOP_SIZE(right);
3701 aopGet(AOP(right),offset,FALSE),
3706 /* now depending on the sign of the destination */
3707 size = AOP_SIZE(result) - AOP_SIZE(right);
3708 /* Unsigned or not an integral type - right fill with zeros */
3709 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3711 aopPut(AOP(result),zero,offset++);
3713 /* we need to extend the sign :{ */
3714 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3717 emitcode("", "; genCast: sign extend untested.");
3718 emitcode("rla", "");
3719 emitcode("sbc", "a,a");
3721 aopPut(AOP(result),"a",offset++);
3725 freeAsmop(right, NULL, ic);
3726 freeAsmop(result, NULL, ic);
3729 /*-----------------------------------------------------------------*/
3730 /* genReceive - generate code for a receive iCode */
3731 /*-----------------------------------------------------------------*/
3732 static void genReceive (iCode *ic)
3734 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3735 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3736 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3740 aopOp(IC_RESULT(ic),ic,FALSE);
3742 assignResultValue(IC_RESULT(ic));
3745 freeAsmop(IC_RESULT(ic),NULL,ic);
3748 /*-----------------------------------------------------------------*/
3749 /* genZ80Code - generate code for Z80 based controllers */
3750 /*-----------------------------------------------------------------*/
3751 void genZ80Code (iCode *lic)
3758 _fReturn = _gbz80_return;
3759 _fTmp = _gbz80_return;
3762 _fReturn = _z80_return;
3763 _fTmp = _z80_return;
3766 lineHead = lineCurr = NULL;
3768 /* if debug information required */
3769 if (options.debug && currFunc) {
3770 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3772 if (IS_STATIC(currFunc->etype))
3773 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3775 emitcode("","G$%s$0$0 ==.",currFunc->name);
3778 /* stack pointer name */
3782 for (ic = lic ; ic ; ic = ic->next ) {
3784 if ( cln != ic->lineno ) {
3785 if ( options.debug ) {
3787 emitcode("","C$%s$%d$%d$%d ==.",
3788 ic->filename,ic->lineno,
3789 ic->level,ic->block);
3792 emitcode(";","%s %d",ic->filename,ic->lineno);
3795 /* if the result is marked as
3796 spilt and rematerializable or code for
3797 this has already been generated then
3799 if (resultRemat(ic) || ic->generated )
3802 /* depending on the operation */
3805 emitcode("", "; genNot");
3810 emitcode("", "; genCpl");
3815 emitcode("", "; genUminus");
3820 emitcode("", "; genIpush");
3825 /* IPOP happens only when trying to restore a
3826 spilt live range, if there is an ifx statement
3827 following this pop then the if statement might
3828 be using some of the registers being popped which
3829 would destory the contents of the register so
3830 we need to check for this condition and handle it */
3832 ic->next->op == IFX &&
3833 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3834 emitcode("", "; genIfx");
3835 genIfx (ic->next,ic);
3838 emitcode("", "; genIpop");
3844 emitcode("", "; genCall");
3849 emitcode("", "; genPcall");
3854 emitcode("", "; genFunction");
3859 emitcode("", "; genEndFunction");
3860 genEndFunction (ic);
3864 emitcode("", "; genRet");
3869 emitcode("", "; genLabel");
3874 emitcode("", "; genGoto");
3879 emitcode("", "; genPlus");
3884 emitcode("", "; genMinus");
3889 emitcode("", "; genMult");
3894 emitcode("", "; genDiv");
3899 emitcode("", "; genMod");
3904 emitcode("", "; genCmpGt");
3905 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3909 emitcode("", "; genCmpLt");
3910 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3917 /* note these two are xlated by algebraic equivalence
3918 during parsing SDCC.y */
3919 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3920 "got '>=' or '<=' shouldn't have come here");
3924 emitcode("", "; genCmpEq");
3925 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3929 emitcode("", "; genAndOp");
3934 emitcode("", "; genOrOp");
3939 emitcode("", "; genXor");
3940 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3944 emitcode("", "; genOr");
3945 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3949 emitcode("", "; genAnd");
3950 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3954 emitcode("", "; genInline");
3959 emitcode("", "; genRRC");
3964 emitcode("", "; genRLC");
3969 emitcode("", "; genHBIT");
3973 emitcode("", "; genLeftShift");
3978 emitcode("", "; genRightShift");
3982 case GET_VALUE_AT_ADDRESS:
3983 emitcode("", "; genPointerGet");
3989 if (POINTER_SET(ic)) {
3990 emitcode("", "; genAssign (pointer)");
3994 emitcode("", "; genAssign");
4000 emitcode("", "; genIfx");
4005 emitcode("", "; genAddrOf");
4010 emitcode("", "; genJumpTab");
4015 emitcode("", "; genCast");
4020 emitcode("", "; genReceive");
4025 emitcode("", "; addSet");
4026 addSet(&sendSet,ic);
4031 /* piCode(ic,stdout); */
4037 /* now we are ready to call the
4038 peep hole optimizer */
4039 if (!options.nopeep)
4040 peepHole (&lineHead);
4042 /* now do the actual printing */
4043 printLine (lineHead,codeOutFile);