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 const char *_shortJP = "jp";
82 #define RESULTONSTACK(x) \
83 (IC_RESULT(x) && IC_RESULT(x)->aop && \
84 IC_RESULT(x)->aop->type == AOP_STK )
86 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
87 #define CLRC emitcode("xor","a,a");
89 #define LABEL_STR "%05d$"
91 lineNode *lineHead = NULL;
92 lineNode *lineCurr = NULL;
94 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
95 0xE0, 0xC0, 0x80, 0x00};
96 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
97 0x07, 0x03, 0x01, 0x00};
99 static int _lastStack = 0;
100 static int _pushed = 0;
101 static int _spoffset;
102 static int _lastHLOff = 0;
103 static asmop *_lastHL;
118 /*-----------------------------------------------------------------*/
119 /* emitcode - writes the code into a file : for now it is simple */
120 /*-----------------------------------------------------------------*/
121 void emitcode (const char *inst, const char *fmt, ...)
124 char lb[MAX_INLINEASM];
130 sprintf(lb,"%s\t",inst);
131 vsprintf(lb+(strlen(lb)),fmt,ap);
135 while (isspace(*lbp)) lbp++;
138 lineCurr = (lineCurr ?
139 connectLine(lineCurr,newLineNode(lb)) :
140 (lineHead = newLineNode(lb)));
141 lineCurr->isInline = inLine;
142 lineCurr->isDebug = debugLine;
146 const char *getPairName(asmop *aop)
148 if (aop->type == AOP_REG) {
149 switch (aop->aopu.aop_reg[0]->rIdx) {
161 else if (aop->type == AOP_STR) {
162 switch (*aop->aopu.aop_str[0]) {
178 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
179 bool isPair(asmop *aop)
181 if (aop->size == 2) {
182 if (aop->type == AOP_REG) {
183 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
186 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
189 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
193 if (aop->type == AOP_STR) {
194 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
197 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
200 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
208 /** Push a register pair onto the stack */
209 void genPairPush(asmop *aop)
211 emitcode("push", "%s", getPairName(aop));
214 /*-----------------------------------------------------------------*/
215 /* newAsmop - creates a new asmOp */
216 /*-----------------------------------------------------------------*/
217 static asmop *newAsmop (short type)
221 ALLOC(aop,sizeof(asmop));
226 /*-----------------------------------------------------------------*/
227 /* aopForSym - for a true symbol */
228 /*-----------------------------------------------------------------*/
229 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
232 memmap *space= SPEC_OCLS(sym->etype);
234 /* if already has one */
238 /* Assign depending on the storage class */
239 if (sym->onStack || sym->iaccess) {
240 sym->aop = aop = newAsmop(AOP_STK);
241 aop->size = getSize(sym->type);
243 aop->aopu.aop_stk = sym->stack;
247 /* special case for a function */
248 if (IS_FUNC(sym->type)) {
249 sym->aop = aop = newAsmop(AOP_IMMD);
250 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
251 strcpy(aop->aopu.aop_immd,sym->rname);
258 /* if it is in direct space */
259 if (IN_DIRSPACE(space)) {
260 sym->aop = aop = newAsmop (AOP_DIR);
261 aop->aopu.aop_dir = sym->rname ;
262 aop->size = getSize(sym->type);
263 emitcode("", "; AOP_DIR for %s", sym->rname);
269 /* only remaining is far space */
270 /* in which case DPTR gets the address */
272 sym->aop = aop = newAsmop(AOP_HL);
276 sym->aop = aop = newAsmop(AOP_IY);
277 emitcode ("ld","iy,#%s ; a", sym->rname);
279 aop->size = getSize(sym->type);
280 aop->aopu.aop_dir = sym->rname;
282 /* if it is in code space */
283 if (IN_CODESPACE(space))
289 /*-----------------------------------------------------------------*/
290 /* aopForRemat - rematerialzes an object */
291 /*-----------------------------------------------------------------*/
292 static asmop *aopForRemat (symbol *sym)
295 iCode *ic = sym->rematiCode;
296 asmop *aop = newAsmop(AOP_IMMD);
299 /* if plus or minus print the right hand side */
300 if (ic->op == '+' || ic->op == '-') {
301 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
304 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
307 /* we reached the end */
308 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
312 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
313 strcpy(aop->aopu.aop_immd,buffer);
317 /*-----------------------------------------------------------------*/
318 /* regsInCommon - two operands have some registers in common */
319 /*-----------------------------------------------------------------*/
320 bool regsInCommon (operand *op1, operand *op2)
325 /* if they have registers in common */
326 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
329 sym1 = OP_SYMBOL(op1);
330 sym2 = OP_SYMBOL(op2);
332 if (sym1->nRegs == 0 || sym2->nRegs == 0)
335 for (i = 0 ; i < sym1->nRegs ; i++) {
340 for (j = 0 ; j < sym2->nRegs ;j++ ) {
344 if (sym2->regs[j] == sym1->regs[i])
352 /*-----------------------------------------------------------------*/
353 /* operandsEqu - equivalent */
354 /*-----------------------------------------------------------------*/
355 bool operandsEqu ( operand *op1, operand *op2)
359 /* if they not symbols */
360 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
363 sym1 = OP_SYMBOL(op1);
364 sym2 = OP_SYMBOL(op2);
366 /* if both are itemps & one is spilt
367 and the other is not then false */
368 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
369 sym1->isspilt != sym2->isspilt )
372 /* if they are the same */
376 if (strcmp(sym1->rname,sym2->rname) == 0)
380 /* if left is a tmp & right is not */
384 (sym1->usl.spillLoc == sym2))
391 (sym2->usl.spillLoc == sym1))
397 /*-----------------------------------------------------------------*/
398 /* sameRegs - two asmops have the same registers */
399 /*-----------------------------------------------------------------*/
400 bool sameRegs (asmop *aop1, asmop *aop2 )
407 if (aop1->type != AOP_REG ||
408 aop2->type != AOP_REG )
411 if (aop1->size != aop2->size)
414 for (i = 0 ; i < aop1->size ; i++ )
415 if (aop1->aopu.aop_reg[i] !=
416 aop2->aopu.aop_reg[i] )
422 /*-----------------------------------------------------------------*/
423 /* aopOp - allocates an asmop for an operand : */
424 /*-----------------------------------------------------------------*/
425 static void aopOp (operand *op, iCode *ic, bool result)
434 /* if this a literal */
435 if (IS_OP_LITERAL(op)) {
436 op->aop = aop = newAsmop(AOP_LIT);
437 aop->aopu.aop_lit = op->operand.valOperand;
438 aop->size = getSize(operandType(op));
442 /* if already has a asmop then continue */
446 /* if the underlying symbol has a aop */
447 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
448 op->aop = OP_SYMBOL(op)->aop;
452 /* if this is a true symbol */
453 if (IS_TRUE_SYMOP(op)) {
454 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
458 /* this is a temporary : this has
464 e) can be a return use only */
468 /* if the type is a conditional */
469 if (sym->regType == REG_CND) {
470 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
475 /* if it is spilt then two situations
477 b) has a spill location */
478 if (sym->isspilt || sym->nRegs == 0) {
479 /* rematerialize it NOW */
481 sym->aop = op->aop = aop =
483 aop->size = getSize(sym->type);
489 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
490 aop->size = getSize(sym->type);
491 for ( i = 0 ; i < 2 ; i++ )
492 aop->aopu.aop_str[i] = accUse[i];
498 aop = op->aop = sym->aop = newAsmop(AOP_STR);
499 aop->size = getSize(sym->type);
500 for ( i = 0 ; i < 4 ; i++ )
501 aop->aopu.aop_str[i] = _fReturn[i];
505 /* else spill location */
506 sym->aop = op->aop = aop =
507 aopForSym(ic,sym->usl.spillLoc,result);
508 aop->size = getSize(sym->type);
512 /* must be in a register */
513 sym->aop = op->aop = aop = newAsmop(AOP_REG);
514 aop->size = sym->nRegs;
515 for ( i = 0 ; i < sym->nRegs ;i++)
516 aop->aopu.aop_reg[i] = sym->regs[i];
519 /*-----------------------------------------------------------------*/
520 /* freeAsmop - free up the asmop given to an operand */
521 /*----------------------------------------------------------------*/
522 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
545 /* all other cases just dealloc */
549 OP_SYMBOL(op)->aop = NULL;
550 /* if the symbol has a spill */
552 SPIL_LOC(op)->aop = NULL;
557 char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
566 /* depending on type */
569 sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
570 ALLOC_ATOMIC(rs,strlen(s)+1);
575 value * val = aop->aopu.aop_lit;
576 /* if it is a float then it gets tricky */
577 /* otherwise it is fairly simple */
578 if (!IS_FLOAT(val->type)) {
579 unsigned long v = floatFromVal(val);
581 sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
582 ALLOC_ATOMIC(rs,strlen(buffer)+1);
583 return strcpy (rs,buffer);
592 char *aopGetWord(asmop *aop, int offset)
594 return aopGetWordLong(aop, offset, TRUE);
597 static void setupHL(asmop *aop, int offset)
599 if (_lastHL != aop) {
602 emitcode("ld", "hl,#%s+%d", aop->aopu.aop_dir, offset);
605 /* In some cases we can still inc or dec hl */
606 emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
615 while (offset < _lastHLOff) {
616 emitcode("dec", "hl");
619 while (offset > _lastHLOff) {
620 emitcode("inc", "hl");
626 /*-----------------------------------------------------------------*/
627 /* aopGet - for fetching value of the aop */
628 /*-----------------------------------------------------------------*/
629 static char *aopGet (asmop *aop, int offset, bool bit16)
634 /* offset is greater than size then zero */
635 /* PENDING: this seems a bit screwed in some pointer cases. */
636 if (offset > (aop->size - 1) &&
637 aop->type != AOP_LIT)
640 /* depending on type */
644 sprintf (s,"#%s",aop->aopu.aop_immd);
654 ALLOC_ATOMIC(rs,strlen(s)+1);
660 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
662 ALLOC_ATOMIC(rs,strlen(s)+1);
667 return aop->aopu.aop_reg[offset]->name;
671 setupHL(aop, offset);
673 ALLOC_ATOMIC(rs, strlen(s)+1);
678 sprintf(s,"%d(iy)", offset);
679 ALLOC_ATOMIC(rs,strlen(s)+1);
685 setupHL(aop, offset);
689 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
691 ALLOC_ATOMIC(rs,strlen(s)+1);
705 return aopLiteral (aop->aopu.aop_lit,offset);
709 return aop->aopu.aop_str[offset];
712 fprintf(stderr, "Type %u\n", aop->type);
714 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
715 "aopget got unsupported aop->type");
719 bool isRegString(char *s)
721 if (!strcmp(s, "b") ||
732 bool isConstant(char *s)
737 bool canAssignToPtr(char *s)
746 /*-----------------------------------------------------------------*/
747 /* aopPut - puts a string for a aop */
748 /*-----------------------------------------------------------------*/
749 static void aopPut (asmop *aop, char *s, int offset)
751 if (aop->size && offset > ( aop->size - 1)) {
752 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
753 "aopPut got offset > aop->size");
757 /* will assign value to value */
758 /* depending on where it is ofcourse */
763 emitcode("ld", "a,%s", s);
764 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
768 /* Dont bother if it's a ld x,x */
769 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
770 emitcode("ld","%s,%s",
771 aop->aopu.aop_reg[offset]->name,s);
777 if (!canAssignToPtr(s)) {
778 emitcode("ld", "a,%s", s);
779 emitcode("ld", "%d(iy),a", offset);
782 emitcode("ld", "%d(iy),%s", offset, s);
787 if (!strcmp(s, "(hl)")) {
788 emitcode("ld", "a,(hl)");
791 setupHL(aop, offset);
792 emitcode("ld", "(hl),%s", s);
797 if (!strcmp("(hl)", s)) {
798 emitcode("ld", "a,(hl)");
801 setupHL(aop, offset);
802 if (!canAssignToPtr(s)) {
803 emitcode("ld", "a,%s", s);
804 emitcode("ld", "(hl),a");
807 emitcode("ld", "(hl),%s", s);
810 if (!canAssignToPtr(s)) {
811 emitcode("ld", "a,%s", s);
812 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
815 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
820 /* if bit variable */
821 if (!aop->aopu.aop_dir) {
822 emitcode("ld", "a,#0");
825 /* In bit space but not in C - cant happen */
832 if (strcmp(aop->aopu.aop_str[offset],s)) {
833 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
839 if (!offset && (strcmp(s,"acc") == 0))
843 emitcode("", "; Error aopPut AOP_ACC");
846 if (strcmp(aop->aopu.aop_str[offset],s))
847 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
852 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
853 "aopPut got unsupported aop->type");
858 #define AOP(op) op->aop
859 #define AOP_TYPE(op) AOP(op)->type
860 #define AOP_SIZE(op) AOP(op)->size
861 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
863 /*-----------------------------------------------------------------*/
864 /* getDataSize - get the operand data size */
865 /*-----------------------------------------------------------------*/
866 int getDataSize(operand *op)
877 /*-----------------------------------------------------------------*/
878 /* movLeft2Result - move byte from left to result */
879 /*-----------------------------------------------------------------*/
880 static void movLeft2Result (operand *left, int offl,
881 operand *result, int offr, int sign)
884 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
885 l = aopGet(AOP(left),offl,FALSE);
888 aopPut(AOP(result),l,offr);
897 /** Put Acc into a register set
899 void outAcc(operand *result)
902 size = getDataSize(result);
904 aopPut(AOP(result),"a",0);
907 /* unsigned or positive */
909 aopPut(AOP(result),zero,offset++);
914 /** Take the value in carry and put it into a register
916 void outBitC(operand *result)
918 /* if the result is bit */
919 if (AOP_TYPE(result) == AOP_CRY) {
920 emitcode("", "; Note: outBitC form 1");
921 aopPut(AOP(result),"blah",0);
924 emitcode("ld", "a,#0");
930 /*-----------------------------------------------------------------*/
931 /* toBoolean - emit code for orl a,operator(sizeop) */
932 /*-----------------------------------------------------------------*/
933 void toBoolean(operand *oper)
935 int size = AOP_SIZE(oper);
938 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
941 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
944 if (AOP(oper)->type != AOP_ACC) {
946 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
951 /*-----------------------------------------------------------------*/
952 /* genNot - generate code for ! operation */
953 /*-----------------------------------------------------------------*/
954 static void genNot (iCode *ic)
956 link *optype = operandType(IC_LEFT(ic));
958 /* assign asmOps to operand & result */
959 aopOp (IC_LEFT(ic),ic,FALSE);
960 aopOp (IC_RESULT(ic),ic,TRUE);
962 /* if in bit space then a special case */
963 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
967 /* if type float then do float */
968 if (IS_FLOAT(optype)) {
972 toBoolean(IC_LEFT(ic));
977 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
978 emitcode("sub", "a,#0x01");
979 outBitC(IC_RESULT(ic));
981 /* release the aops */
982 freeAsmop(IC_LEFT(ic),NULL,ic);
983 freeAsmop(IC_RESULT(ic),NULL,ic);
986 /*-----------------------------------------------------------------*/
987 /* genCpl - generate code for complement */
988 /*-----------------------------------------------------------------*/
989 static void genCpl (iCode *ic)
995 /* assign asmOps to operand & result */
996 aopOp (IC_LEFT(ic),ic,FALSE);
997 aopOp (IC_RESULT(ic),ic,TRUE);
999 /* if both are in bit space then
1001 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1002 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1006 size = AOP_SIZE(IC_RESULT(ic));
1008 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1011 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1014 /* release the aops */
1015 freeAsmop(IC_LEFT(ic),NULL,ic);
1016 freeAsmop(IC_RESULT(ic),NULL,ic);
1019 /*-----------------------------------------------------------------*/
1020 /* genUminus - unary minus code generation */
1021 /*-----------------------------------------------------------------*/
1022 static void genUminus (iCode *ic)
1025 link *optype, *rtype;
1028 aopOp(IC_LEFT(ic),ic,FALSE);
1029 aopOp(IC_RESULT(ic),ic,TRUE);
1031 /* if both in bit space then special
1033 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1034 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1039 optype = operandType(IC_LEFT(ic));
1040 rtype = operandType(IC_RESULT(ic));
1042 /* if float then do float stuff */
1043 if (IS_FLOAT(optype)) {
1048 /* otherwise subtract from zero */
1049 size = AOP_SIZE(IC_LEFT(ic));
1053 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1054 emitcode("ld", "a,#0");
1055 emitcode("sbc","a,%s",l);
1056 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1059 /* if any remaining bytes in the result */
1060 /* we just need to propagate the sign */
1061 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1062 emitcode("rlc","a");
1063 emitcode("sbc","a,a");
1065 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1069 /* release the aops */
1070 freeAsmop(IC_LEFT(ic),NULL,ic);
1071 freeAsmop(IC_RESULT(ic),NULL,ic);
1074 static bool requiresHL(asmop *aop)
1076 switch (aop->type) {
1085 /*-----------------------------------------------------------------*/
1086 /* assignResultValue - */
1087 /*-----------------------------------------------------------------*/
1088 void assignResultValue(operand * oper)
1091 int size = AOP_SIZE(oper);
1096 aopPut(AOP(oper),_fReturn[offset],offset);
1101 static void fetchHL(asmop *aop)
1103 if (IS_GB && requiresHL(aop)) {
1104 aopGet(aop, 0, FALSE);
1105 emitcode("ld", "a,(hl+)");
1106 emitcode("ld", "h,(hl)");
1107 emitcode("ld", "l,a");
1110 emitcode("ld", "l,%s", aopGet(aop, 0, FALSE));
1111 emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
1115 /*-----------------------------------------------------------------*/
1116 /* genIpush - genrate code for pushing this gets a little complex */
1117 /*-----------------------------------------------------------------*/
1118 static void genIpush (iCode *ic)
1120 int size, offset = 0 ;
1124 /* if this is not a parm push : ie. it is spill push
1125 and spill push is always done on the local stack */
1126 if (!ic->parmPush) {
1127 /* and the item is spilt then do nothing */
1128 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1131 aopOp(IC_LEFT(ic),ic,FALSE);
1132 size = AOP_SIZE(IC_LEFT(ic));
1133 /* push it on the stack */
1134 if (isPair(AOP(IC_LEFT(ic)))) {
1135 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1141 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1142 /* Simple for now - load into A and PUSH AF */
1143 emitcode("ld", "a,%s", l);
1144 emitcode("push", "af");
1145 emitcode("inc", "sp");
1152 /* Hmmm... what about saving the currently used registers
1155 /* then do the push */
1156 aopOp(IC_LEFT(ic),ic,FALSE);
1158 size = AOP_SIZE(IC_LEFT(ic));
1160 if (isPair(AOP(IC_LEFT(ic)))) {
1162 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1166 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1168 emitcode("ld", "hl,%s", s);
1169 emitcode("push", "hl");
1173 /* Optimise here - load into HL then push HL */
1174 fetchHL(AOP(IC_LEFT(ic)));
1175 emitcode("push", "hl");
1182 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1183 emitcode("ld", "a,%s", l);
1184 emitcode("push", "af");
1185 emitcode("inc", "sp");
1190 freeAsmop(IC_LEFT(ic),NULL,ic);
1193 /*-----------------------------------------------------------------*/
1194 /* genIpop - recover the registers: can happen only for spilling */
1195 /*-----------------------------------------------------------------*/
1196 static void genIpop (iCode *ic)
1201 /* if the temp was not pushed then */
1202 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1205 aopOp(IC_LEFT(ic),ic,FALSE);
1206 size = AOP_SIZE(IC_LEFT(ic));
1208 if (isPair(AOP(IC_LEFT(ic)))) {
1209 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1213 emitcode("dec", "sp");
1214 emitcode("pop", "hl");
1215 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1219 freeAsmop(IC_LEFT(ic),NULL,ic);
1222 /** Emit the code for a call statement
1224 static void emitCall (iCode *ic, bool ispcall)
1226 /* if caller saves & we have not saved then */
1227 if (!ic->regsSaved) {
1231 /* if send set is not empty then assign */
1234 for (sic = setFirstItem(sendSet) ; sic ;
1235 sic = setNextItem(sendSet)) {
1236 int size, offset = 0;
1237 aopOp(IC_LEFT(sic),sic,FALSE);
1238 size = AOP_SIZE(IC_LEFT(sic));
1240 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1242 if (strcmp(l, _fReturn[offset]))
1243 emitcode("ld","%s,%s",
1248 freeAsmop (IC_LEFT(sic),NULL,sic);
1254 symbol *rlbl = newiTempLabel(NULL);
1256 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1257 emitcode("push", "hl");
1260 aopOp(IC_LEFT(ic),ic,FALSE);
1261 fetchHL(AOP(IC_LEFT(ic)));
1262 freeAsmop(IC_LEFT(ic),NULL,ic);
1264 emitcode("jp", "(hl)");
1265 emitcode("","%05d$:",(rlbl->key+100));
1270 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1271 OP_SYMBOL(IC_LEFT(ic))->rname :
1272 OP_SYMBOL(IC_LEFT(ic))->name;
1273 emitcode("call", "%s", name);
1276 /* if we need assign a result value */
1277 if ((IS_ITEMP(IC_RESULT(ic)) &&
1278 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1279 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1280 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1283 aopOp(IC_RESULT(ic),ic,FALSE);
1286 assignResultValue(IC_RESULT(ic));
1288 freeAsmop(IC_RESULT(ic),NULL, ic);
1291 /* adjust the stack for parameters if required */
1292 if (IC_LEFT(ic)->parmBytes) {
1293 int i = IC_LEFT(ic)->parmBytes;
1296 emitcode("lda", "sp,%d(sp)", i);
1300 emitcode("ld", "hl,#%d", i);
1301 emitcode("add", "hl,sp");
1302 emitcode("ld", "sp,hl");
1306 emitcode("pop", "hl");
1310 emitcode("inc", "sp");
1317 /*-----------------------------------------------------------------*/
1318 /* genCall - generates a call statement */
1319 /*-----------------------------------------------------------------*/
1320 static void genCall (iCode *ic)
1322 emitCall(ic, FALSE);
1325 /*-----------------------------------------------------------------*/
1326 /* genPcall - generates a call by pointer statement */
1327 /*-----------------------------------------------------------------*/
1328 static void genPcall (iCode *ic)
1333 /*-----------------------------------------------------------------*/
1334 /* resultRemat - result is rematerializable */
1335 /*-----------------------------------------------------------------*/
1336 static int resultRemat (iCode *ic)
1338 if (SKIP_IC(ic) || ic->op == IFX)
1341 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1342 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1343 if (sym->remat && !POINTER_SET(ic))
1350 /*-----------------------------------------------------------------*/
1351 /* genFunction - generated code for function entry */
1352 /*-----------------------------------------------------------------*/
1353 static void genFunction (iCode *ic)
1359 /* create the function header */
1360 emitcode(";","-----------------------------------------");
1361 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1362 emitcode(";","-----------------------------------------");
1364 emitcode("","%s:",sym->rname);
1365 emitcode("", "__%s_start:", sym->rname);
1366 fetype = getSpec(operandType(IC_LEFT(ic)));
1368 /* if critical function then turn interrupts off */
1369 if (SPEC_CRTCL(fetype))
1372 /* if this is an interrupt service routine then
1373 save acc, b, dpl, dph */
1374 if (IS_ISR(sym->etype)) {
1375 emitcode("push", "af");
1376 emitcode("push", "bc");
1377 emitcode("push", "de");
1378 emitcode("push", "hl");
1380 /* PENDING: callee-save etc */
1382 /* adjust the stack for the function */
1383 emitcode("push", "bc");
1385 emitcode("push", "de");
1386 emitcode("push", "ix");
1387 emitcode("ld", "ix,#0");
1388 emitcode("add", "ix,sp");
1391 _lastStack = sym->stack;
1395 emitcode("lda", "sp,-%d(sp)", sym->stack);
1398 emitcode("ld", "hl,#-%d", sym->stack);
1399 emitcode("add", "hl,sp");
1400 emitcode("ld", "sp,hl");
1403 _spoffset = sym->stack;
1406 /*-----------------------------------------------------------------*/
1407 /* genEndFunction - generates epilogue for functions */
1408 /*-----------------------------------------------------------------*/
1409 static void genEndFunction (iCode *ic)
1411 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1413 if (IS_ISR(sym->etype)) {
1417 if (SPEC_CRTCL(sym->etype))
1420 /* PENDING: calleeSave */
1422 /* if debug then send end of function */
1423 if (options.debug && currFunc) {
1425 emitcode("","C$%s$%d$%d$%d ==.",
1426 ic->filename,currFunc->lastLine,
1427 ic->level,ic->block);
1428 if (IS_STATIC(currFunc->etype))
1429 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1431 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1435 emitcode("ld", "sp,ix");
1436 emitcode("pop", "ix");
1437 emitcode("pop", "de");
1441 emitcode("ld", "hl,#%d", _spoffset);
1442 emitcode("add", "hl,sp");
1443 emitcode("ld", "sp,hl");
1446 emitcode("pop", "bc");
1447 emitcode("ret", "");
1448 emitcode("", "__%s_end:", sym->rname);
1454 /*-----------------------------------------------------------------*/
1455 /* genRet - generate code for return statement */
1456 /*-----------------------------------------------------------------*/
1457 static void genRet (iCode *ic)
1460 /* Errk. This is a hack until I can figure out how
1461 to cause dehl to spill on a call */
1462 int size,offset = 0;
1464 /* if we have no return value then
1465 just generate the "ret" */
1469 /* we have something to return then
1470 move the return value into place */
1471 aopOp(IC_LEFT(ic),ic,FALSE);
1472 size = AOP_SIZE(IC_LEFT(ic));
1474 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1476 emitcode("ld", "de,%s", l);
1479 emitcode("ld", "hl,%s", l);
1484 l = aopGet(AOP(IC_LEFT(ic)),offset,
1486 if (strcmp(_fReturn[offset],l))
1487 emitcode("ld","%s,%s", _fReturn[offset++],l);
1490 freeAsmop (IC_LEFT(ic),NULL,ic);
1493 /* generate a jump to the return label
1494 if the next is not the return statement */
1495 if (!(ic->next && ic->next->op == LABEL &&
1496 IC_LABEL(ic->next) == returnLabel))
1498 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1501 /*-----------------------------------------------------------------*/
1502 /* genLabel - generates a label */
1503 /*-----------------------------------------------------------------*/
1504 static void genLabel (iCode *ic)
1506 /* special case never generate */
1507 if (IC_LABEL(ic) == entryLabel)
1510 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1513 /*-----------------------------------------------------------------*/
1514 /* genGoto - generates a ljmp */
1515 /*-----------------------------------------------------------------*/
1516 static void genGoto (iCode *ic)
1518 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1521 /*-----------------------------------------------------------------*/
1522 /* genPlusIncr :- does addition with increment if possible */
1523 /*-----------------------------------------------------------------*/
1524 static bool genPlusIncr (iCode *ic)
1526 unsigned int icount ;
1527 unsigned int size = getDataSize(IC_RESULT(ic));
1529 /* will try to generate an increment */
1530 /* if the right side is not a literal
1532 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1535 emitcode("", "; genPlusIncr");
1537 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1539 /* If result is a pair */
1540 if (isPair(AOP(IC_RESULT(ic)))) {
1541 char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1543 /* Both a lit on the right and a true symbol on the left */
1544 emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
1549 /* if the literal value of the right hand side
1550 is greater than 4 then it is not worth it */
1555 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1556 isPair(AOP(IC_RESULT(ic)))) {
1558 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1562 /* if increment 16 bits in register */
1563 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1566 symbol *tlbl = newiTempLabel(NULL);
1567 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1568 emitcode(_shortJP, "nz," LABEL_STR ,tlbl->key+100);
1570 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1574 emitcode("", LABEL_STR ":",tlbl->key+100);
1578 /* If result is a pair */
1579 if (isPair(AOP(IC_RESULT(ic)))) {
1580 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1581 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1583 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1587 /* if the sizes are greater than 1 then we cannot */
1588 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1589 AOP_SIZE(IC_LEFT(ic)) > 1 )
1592 /* we can if the aops of the left & result match or
1593 if they are in registers and the registers are the
1595 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1597 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1605 /*-----------------------------------------------------------------*/
1606 /* outBitAcc - output a bit in acc */
1607 /*-----------------------------------------------------------------*/
1608 void outBitAcc(operand *result)
1610 symbol *tlbl = newiTempLabel(NULL);
1611 /* if the result is a bit */
1612 if (AOP_TYPE(result) == AOP_CRY){
1616 emitcode(_shortJP,"z," LABEL_STR ,tlbl->key+100);
1617 emitcode("ld","a,%s",one);
1618 emitcode("", LABEL_STR ":",tlbl->key+100);
1623 /*-----------------------------------------------------------------*/
1624 /* genPlus - generates code for addition */
1625 /*-----------------------------------------------------------------*/
1626 static void genPlus (iCode *ic)
1628 int size, offset = 0;
1630 /* special cases :- */
1632 aopOp (IC_LEFT(ic),ic,FALSE);
1633 aopOp (IC_RIGHT(ic),ic,FALSE);
1634 aopOp (IC_RESULT(ic),ic,TRUE);
1636 /* Swap the left and right operands if:
1638 if literal, literal on the right or
1639 if left requires ACC or right is already
1642 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1643 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1644 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1645 operand *t = IC_RIGHT(ic);
1646 IC_RIGHT(ic) = IC_LEFT(ic);
1650 /* if both left & right are in bit
1652 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1653 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1658 /* if left in bit space & right literal */
1659 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1660 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1661 /* Can happen I guess */
1665 /* if I can do an increment instead
1666 of add then GOOD for ME */
1667 if (genPlusIncr (ic) == TRUE)
1670 size = getDataSize(IC_RESULT(ic));
1672 /* Special case when left and right are constant */
1673 if (isPair(AOP(IC_RESULT(ic)))) {
1676 left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1677 right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1678 if (left && right) {
1682 sprintf(buffer, "#(%s + %s)", left, right);
1683 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1689 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1690 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1692 emitcode("add","a,%s",
1693 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1695 emitcode("adc","a,%s",
1696 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1698 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1700 emitcode("add","a,%s",
1701 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1703 emitcode("adc","a,%s",
1704 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1706 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1709 /* Some kind of pointer arith. */
1710 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1711 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1712 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1715 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1716 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1717 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1722 freeAsmop(IC_LEFT(ic),NULL,ic);
1723 freeAsmop(IC_RIGHT(ic),NULL,ic);
1724 freeAsmop(IC_RESULT(ic),NULL,ic);
1728 /*-----------------------------------------------------------------*/
1729 /* genMinusDec :- does subtraction with deccrement if possible */
1730 /*-----------------------------------------------------------------*/
1731 static bool genMinusDec (iCode *ic)
1733 unsigned int icount ;
1734 unsigned int size = getDataSize(IC_RESULT(ic));
1736 /* will try to generate an increment */
1737 /* if the right side is not a literal we cannot */
1738 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1741 /* if the literal value of the right hand side
1742 is greater than 4 then it is not worth it */
1743 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1746 size = getDataSize(IC_RESULT(ic));
1749 /* if increment 16 bits in register */
1750 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1753 symbol *tlbl = newiTempLabel(NULL);
1754 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1755 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1757 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1761 emitcode("", LABEL_STR ":",tlbl->key+100);
1766 /* if decrement 16 bits in register */
1767 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1768 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1770 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1774 /* If result is a pair */
1775 if (isPair(AOP(IC_RESULT(ic)))) {
1776 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1777 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1779 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1783 /* if the sizes are greater than 1 then we cannot */
1784 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1785 AOP_SIZE(IC_LEFT(ic)) > 1 )
1788 /* we can if the aops of the left & result match or if they are in
1789 registers and the registers are the same */
1790 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1792 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1799 /*-----------------------------------------------------------------*/
1800 /* genMinus - generates code for subtraction */
1801 /*-----------------------------------------------------------------*/
1802 static void genMinus (iCode *ic)
1804 int size, offset = 0;
1805 unsigned long lit = 0L;
1807 aopOp (IC_LEFT(ic),ic,FALSE);
1808 aopOp (IC_RIGHT(ic),ic,FALSE);
1809 aopOp (IC_RESULT(ic),ic,TRUE);
1811 /* special cases :- */
1812 /* if both left & right are in bit space */
1813 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1814 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1819 /* if I can do an decrement instead of subtract then GOOD for ME */
1820 if (genMinusDec (ic) == TRUE)
1823 size = getDataSize(IC_RESULT(ic));
1825 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1828 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1833 /* if literal, add a,#-lit, else normal subb */
1835 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1836 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1838 emitcode("sub","a,%s",
1839 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1841 emitcode("sbc","a,%s",
1842 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1845 /* first add without previous c */
1847 emitcode("add","a,#0x%02x",
1848 (unsigned int)(lit & 0x0FFL));
1850 emitcode("adc","a,#0x%02x",
1851 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1853 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1856 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1857 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1858 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1862 freeAsmop(IC_LEFT(ic),NULL,ic);
1863 freeAsmop(IC_RIGHT(ic),NULL,ic);
1864 freeAsmop(IC_RESULT(ic),NULL,ic);
1867 /*-----------------------------------------------------------------*/
1868 /* genMult - generates code for multiplication */
1869 /*-----------------------------------------------------------------*/
1870 static void genMult (iCode *ic)
1872 /* Shouldn't occur - all done through function calls */
1876 /*-----------------------------------------------------------------*/
1877 /* genDiv - generates code for division */
1878 /*-----------------------------------------------------------------*/
1879 static void genDiv (iCode *ic)
1881 /* Shouldn't occur - all done through function calls */
1885 /*-----------------------------------------------------------------*/
1886 /* genMod - generates code for division */
1887 /*-----------------------------------------------------------------*/
1888 static void genMod (iCode *ic)
1890 /* Shouldn't occur - all done through function calls */
1894 /*-----------------------------------------------------------------*/
1895 /* genIfxJump :- will create a jump depending on the ifx */
1896 /*-----------------------------------------------------------------*/
1897 static void genIfxJump (iCode *ic, char *jval)
1902 /* if true label then we jump if condition
1904 if ( IC_TRUE(ic) ) {
1906 if (!strcmp(jval, "a")) {
1909 else if (!strcmp(jval, "c")) {
1913 /* The buffer contains the bit on A that we should test */
1918 /* false label is present */
1919 jlbl = IC_FALSE(ic) ;
1920 if (!strcmp(jval, "a")) {
1923 else if (!strcmp(jval, "c")) {
1927 /* The buffer contains the bit on A that we should test */
1931 /* Z80 can do a conditional long jump */
1932 if (!strcmp(jval, "a")) {
1933 emitcode("or", "a,a");
1935 else if (!strcmp(jval, "c")) {
1938 emitcode("bit", "%s,a", jval);
1940 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1942 /* mark the icode as generated */
1946 /** Generic compare for > or <
1948 static void genCmp (operand *left,operand *right,
1949 operand *result, iCode *ifx, int sign)
1951 int size, offset = 0 ;
1952 unsigned long lit = 0L;
1954 /* if left & right are bit variables */
1955 if (AOP_TYPE(left) == AOP_CRY &&
1956 AOP_TYPE(right) == AOP_CRY ) {
1957 /* Cant happen on the Z80 */
1960 /* subtract right from left if at the
1961 end the carry flag is set then we know that
1962 left is greater than right */
1963 size = max(AOP_SIZE(left),AOP_SIZE(right));
1965 /* if unsigned char cmp with lit, just compare */
1967 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1968 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1970 emitcode("xor", "a,#0x80");
1971 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
1974 emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
1977 if(AOP_TYPE(right) == AOP_LIT) {
1978 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1979 /* optimize if(x < 0) or if(x >= 0) */
1982 /* No sign so it's always false */
1986 /* Just load in the top most bit */
1987 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1988 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1989 genIfxJump (ifx,"7");
1993 emitcode("rlc","a");
1999 /* First setup h and l contaning the top most bytes XORed */
2000 bool fDidXor = FALSE;
2001 if (AOP_TYPE(left) == AOP_LIT){
2002 unsigned long lit = (unsigned long)
2003 floatFromVal(AOP(left)->aopu.aop_lit);
2004 emitcode("ld", "%s,#0x%02x", _fTmp[0],
2005 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2008 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2009 emitcode("xor", "a,#0x80");
2010 emitcode("ld", "%s,a", _fTmp[0]);
2013 if (AOP_TYPE(right) == AOP_LIT) {
2014 unsigned long lit = (unsigned long)
2015 floatFromVal(AOP(right)->aopu.aop_lit);
2016 emitcode("ld", "%s,#0x%02x", _fTmp[1],
2017 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2020 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2021 emitcode("xor", "a,#0x80");
2022 emitcode("ld", "%s,a", _fTmp[1]);
2032 /* Do a long subtract */
2033 if (!sign || size ) {
2034 MOVA(aopGet(AOP(left),offset,FALSE));
2036 if (sign && size == 0) {
2037 emitcode("ld", "a,%s", _fTmp[0]);
2038 emitcode("sbc", "a,%s", _fTmp[1]);
2041 /* Subtract through, propagating the carry */
2042 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2049 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2052 /* if the result is used in the next
2053 ifx conditional branch then generate
2054 code a little differently */
2056 genIfxJump (ifx,"c");
2059 /* leave the result in acc */
2063 /*-----------------------------------------------------------------*/
2064 /* genCmpGt :- greater than comparison */
2065 /*-----------------------------------------------------------------*/
2066 static void genCmpGt (iCode *ic, iCode *ifx)
2068 operand *left, *right, *result;
2069 link *letype , *retype;
2073 right= IC_RIGHT(ic);
2074 result = IC_RESULT(ic);
2076 letype = getSpec(operandType(left));
2077 retype =getSpec(operandType(right));
2078 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2079 /* assign the amsops */
2080 aopOp (left,ic,FALSE);
2081 aopOp (right,ic,FALSE);
2082 aopOp (result,ic,TRUE);
2084 genCmp(right, left, result, ifx, sign);
2086 freeAsmop(left,NULL,ic);
2087 freeAsmop(right,NULL,ic);
2088 freeAsmop(result,NULL,ic);
2091 /*-----------------------------------------------------------------*/
2092 /* genCmpLt - less than comparisons */
2093 /*-----------------------------------------------------------------*/
2094 static void genCmpLt (iCode *ic, iCode *ifx)
2096 operand *left, *right, *result;
2097 link *letype , *retype;
2101 right= IC_RIGHT(ic);
2102 result = IC_RESULT(ic);
2104 letype = getSpec(operandType(left));
2105 retype =getSpec(operandType(right));
2106 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2108 /* assign the amsops */
2109 aopOp (left,ic,FALSE);
2110 aopOp (right,ic,FALSE);
2111 aopOp (result,ic,TRUE);
2113 genCmp(left, right, result, ifx, sign);
2115 freeAsmop(left,NULL,ic);
2116 freeAsmop(right,NULL,ic);
2117 freeAsmop(result,NULL,ic);
2120 /*-----------------------------------------------------------------*/
2121 /* gencjneshort - compare and jump if not equal */
2122 /*-----------------------------------------------------------------*/
2123 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2125 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2127 unsigned long lit = 0L;
2129 /* Swap the left and right if it makes the computation easier */
2130 if (AOP_TYPE(left) == AOP_LIT) {
2136 if(AOP_TYPE(right) == AOP_LIT)
2137 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2139 /* if the right side is a literal then anything goes */
2140 if (AOP_TYPE(right) == AOP_LIT &&
2141 AOP_TYPE(left) != AOP_DIR ) {
2143 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2144 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2145 emitcode("or", "a,a");
2147 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2148 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2152 /* if the right side is in a register or in direct space or
2153 if the left is a pointer register & right is not */
2154 else if (AOP_TYPE(right) == AOP_REG ||
2155 AOP_TYPE(right) == AOP_DIR ||
2156 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2158 MOVA(aopGet(AOP(left),offset,FALSE));
2159 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2160 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2162 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
2164 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2165 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2170 /* right is a pointer reg need both a & b */
2171 /* PENDING: is this required? */
2173 char *l = aopGet(AOP(left),offset,FALSE);
2174 MOVA(aopGet(AOP(right),offset,FALSE));
2175 emitcode("cp", "%s ; 5", l);
2176 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2182 /*-----------------------------------------------------------------*/
2183 /* gencjne - compare and jump if not equal */
2184 /*-----------------------------------------------------------------*/
2185 static void gencjne(operand *left, operand *right, symbol *lbl)
2187 symbol *tlbl = newiTempLabel(NULL);
2189 gencjneshort(left, right, lbl);
2192 emitcode("ld","a,%s",one);
2193 emitcode(_shortJP, LABEL_STR ,tlbl->key+100);
2194 emitcode("", LABEL_STR ":",lbl->key+100);
2195 emitcode("xor","a,a");
2196 emitcode("", LABEL_STR ":",tlbl->key+100);
2199 /*-----------------------------------------------------------------*/
2200 /* genCmpEq - generates code for equal to */
2201 /*-----------------------------------------------------------------*/
2202 static void genCmpEq (iCode *ic, iCode *ifx)
2204 operand *left, *right, *result;
2206 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2207 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2208 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2210 /* Swap operands if it makes the operation easier. ie if:
2211 1. Left is a literal.
2213 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2214 operand *t = IC_RIGHT(ic);
2215 IC_RIGHT(ic) = IC_LEFT(ic);
2219 if (ifx && !AOP_SIZE(result)){
2221 /* if they are both bit variables */
2222 if (AOP_TYPE(left) == AOP_CRY &&
2223 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2226 tlbl = newiTempLabel(NULL);
2227 gencjneshort(left, right, tlbl);
2228 if ( IC_TRUE(ifx) ) {
2229 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2230 emitcode("", LABEL_STR ":",tlbl->key+100);
2232 /* PENDING: do this better */
2233 symbol *lbl = newiTempLabel(NULL);
2234 emitcode(_shortJP, LABEL_STR ,lbl->key+100);
2235 emitcode("", LABEL_STR ":",tlbl->key+100);
2236 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2237 emitcode("", LABEL_STR ":",lbl->key+100);
2240 /* mark the icode as generated */
2245 /* if they are both bit variables */
2246 if (AOP_TYPE(left) == AOP_CRY &&
2247 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2250 gencjne(left,right,newiTempLabel(NULL));
2251 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2255 genIfxJump(ifx,"a");
2258 /* if the result is used in an arithmetic operation
2259 then put the result in place */
2260 if (AOP_TYPE(result) != AOP_CRY) {
2263 /* leave the result in acc */
2267 freeAsmop(left,NULL,ic);
2268 freeAsmop(right,NULL,ic);
2269 freeAsmop(result,NULL,ic);
2272 /*-----------------------------------------------------------------*/
2273 /* ifxForOp - returns the icode containing the ifx for operand */
2274 /*-----------------------------------------------------------------*/
2275 static iCode *ifxForOp ( operand *op, iCode *ic )
2277 /* if true symbol then needs to be assigned */
2278 if (IS_TRUE_SYMOP(op))
2281 /* if this has register type condition and
2282 the next instruction is ifx with the same operand
2283 and live to of the operand is upto the ifx only then */
2285 ic->next->op == IFX &&
2286 IC_COND(ic->next)->key == op->key &&
2287 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2293 /*-----------------------------------------------------------------*/
2294 /* genAndOp - for && operation */
2295 /*-----------------------------------------------------------------*/
2296 static void genAndOp (iCode *ic)
2298 operand *left,*right, *result;
2301 /* note here that && operations that are in an if statement are
2302 taken away by backPatchLabels only those used in arthmetic
2303 operations remain */
2304 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2305 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2306 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2308 /* if both are bit variables */
2309 if (AOP_TYPE(left) == AOP_CRY &&
2310 AOP_TYPE(right) == AOP_CRY ) {
2313 tlbl = newiTempLabel(NULL);
2315 emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100);
2317 emitcode("", LABEL_STR ":",tlbl->key+100);
2321 freeAsmop(left,NULL,ic);
2322 freeAsmop(right,NULL,ic);
2323 freeAsmop(result,NULL,ic);
2326 /*-----------------------------------------------------------------*/
2327 /* genOrOp - for || operation */
2328 /*-----------------------------------------------------------------*/
2329 static void genOrOp (iCode *ic)
2331 operand *left,*right, *result;
2334 /* note here that || operations that are in an
2335 if statement are taken away by backPatchLabels
2336 only those used in arthmetic operations remain */
2337 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2338 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2339 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2341 /* if both are bit variables */
2342 if (AOP_TYPE(left) == AOP_CRY &&
2343 AOP_TYPE(right) == AOP_CRY ) {
2346 tlbl = newiTempLabel(NULL);
2348 emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100);
2350 emitcode("", LABEL_STR ":",tlbl->key+100);
2354 freeAsmop(left,NULL,ic);
2355 freeAsmop(right,NULL,ic);
2356 freeAsmop(result,NULL,ic);
2359 /*-----------------------------------------------------------------*/
2360 /* isLiteralBit - test if lit == 2^n */
2361 /*-----------------------------------------------------------------*/
2362 int isLiteralBit(unsigned long lit)
2364 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2365 0x100L,0x200L,0x400L,0x800L,
2366 0x1000L,0x2000L,0x4000L,0x8000L,
2367 0x10000L,0x20000L,0x40000L,0x80000L,
2368 0x100000L,0x200000L,0x400000L,0x800000L,
2369 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2370 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2373 for(idx = 0; idx < 32; idx++)
2379 /*-----------------------------------------------------------------*/
2380 /* jmpTrueOrFalse - */
2381 /*-----------------------------------------------------------------*/
2382 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2384 // ugly but optimized by peephole
2386 symbol *nlbl = newiTempLabel(NULL);
2387 emitcode("jp", LABEL_STR, nlbl->key+100);
2388 emitcode("", LABEL_STR ":",tlbl->key+100);
2389 emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100);
2390 emitcode("", LABEL_STR ":",nlbl->key+100);
2393 emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100);
2394 emitcode("", LABEL_STR ":",tlbl->key+100);
2399 /*-----------------------------------------------------------------*/
2400 /* genAnd - code for and */
2401 /*-----------------------------------------------------------------*/
2402 static void genAnd (iCode *ic, iCode *ifx)
2404 operand *left, *right, *result;
2406 unsigned long lit = 0L;
2409 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2410 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2411 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2414 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2416 AOP_TYPE(left), AOP_TYPE(right));
2417 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2419 AOP_SIZE(left), AOP_SIZE(right));
2422 /* if left is a literal & right is not then exchange them */
2423 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2424 AOP_NEEDSACC(left)) {
2425 operand *tmp = right ;
2430 /* if result = right then exchange them */
2431 if(sameRegs(AOP(result),AOP(right))){
2432 operand *tmp = right ;
2437 /* if right is bit then exchange them */
2438 if (AOP_TYPE(right) == AOP_CRY &&
2439 AOP_TYPE(left) != AOP_CRY){
2440 operand *tmp = right ;
2444 if(AOP_TYPE(right) == AOP_LIT)
2445 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2447 size = AOP_SIZE(result);
2449 if (AOP_TYPE(left) == AOP_CRY){
2454 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2455 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2456 if((AOP_TYPE(right) == AOP_LIT) &&
2457 (AOP_TYPE(result) == AOP_CRY) &&
2458 (AOP_TYPE(left) != AOP_CRY)) {
2459 int posbit = isLiteralBit(lit);
2463 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2467 emitcode("mov","c,acc.%d",posbit&0x07);
2472 sprintf(buffer, "%d", posbit&0x07);
2473 genIfxJump(ifx, buffer);
2481 symbol *tlbl = newiTempLabel(NULL);
2482 int sizel = AOP_SIZE(left);
2485 emitcode("setb","c");
2488 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2489 MOVA( aopGet(AOP(left),offset,FALSE));
2491 if((posbit = isLiteralBit(bytelit)) != 0) {
2493 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2496 if(bytelit != 0x0FFL)
2497 emitcode("and","a,%s",
2498 aopGet(AOP(right),offset,FALSE));
2499 emitcode("jr","nz, %05d$",tlbl->key+100);
2504 // bit = left & literal
2506 emitcode("clr","c");
2507 emitcode("","%05d$:",tlbl->key+100);
2509 // if(left & literal)
2512 jmpTrueOrFalse(ifx, tlbl);
2520 /* if left is same as result */
2521 if(sameRegs(AOP(result),AOP(left))){
2522 for(;size--; offset++) {
2523 if(AOP_TYPE(right) == AOP_LIT){
2524 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2528 aopPut(AOP(result),zero,offset);
2530 MOVA(aopGet(AOP(left),offset,FALSE));
2531 emitcode("and","a,%s",
2532 aopGet(AOP(right),offset,FALSE));
2533 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2538 if (AOP_TYPE(left) == AOP_ACC) {
2542 MOVA(aopGet(AOP(right),offset,FALSE));
2543 emitcode("and","%s,a",
2544 aopGet(AOP(left),offset,FALSE));
2549 // left & result in different registers
2550 if(AOP_TYPE(result) == AOP_CRY){
2553 for(;(size--);offset++) {
2555 // result = left & right
2556 if(AOP_TYPE(right) == AOP_LIT){
2557 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2559 aopGet(AOP(left),offset,FALSE),
2562 } else if(bytelit == 0){
2563 aopPut(AOP(result),zero,offset);
2567 // faster than result <- left, anl result,right
2568 // and better if result is SFR
2569 if (AOP_TYPE(left) == AOP_ACC)
2570 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2572 MOVA(aopGet(AOP(right),offset,FALSE));
2573 emitcode("and","a,%s",
2574 aopGet(AOP(left),offset,FALSE));
2576 aopPut(AOP(result),"a",offset);
2583 freeAsmop(left,NULL,ic);
2584 freeAsmop(right,NULL,ic);
2585 freeAsmop(result,NULL,ic);
2588 /*-----------------------------------------------------------------*/
2589 /* genOr - code for or */
2590 /*-----------------------------------------------------------------*/
2591 static void genOr (iCode *ic, iCode *ifx)
2593 operand *left, *right, *result;
2595 unsigned long lit = 0L;
2597 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2598 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2599 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2602 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2604 AOP_TYPE(left), AOP_TYPE(right));
2605 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2607 AOP_SIZE(left), AOP_SIZE(right));
2610 /* if left is a literal & right is not then exchange them */
2611 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2612 AOP_NEEDSACC(left)) {
2613 operand *tmp = right ;
2618 /* if result = right then exchange them */
2619 if(sameRegs(AOP(result),AOP(right))){
2620 operand *tmp = right ;
2625 /* if right is bit then exchange them */
2626 if (AOP_TYPE(right) == AOP_CRY &&
2627 AOP_TYPE(left) != AOP_CRY){
2628 operand *tmp = right ;
2632 if(AOP_TYPE(right) == AOP_LIT)
2633 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2635 size = AOP_SIZE(result);
2637 if (AOP_TYPE(left) == AOP_CRY){
2642 if((AOP_TYPE(right) == AOP_LIT) &&
2643 (AOP_TYPE(result) == AOP_CRY) &&
2644 (AOP_TYPE(left) != AOP_CRY)){
2649 /* if left is same as result */
2650 if(sameRegs(AOP(result),AOP(left))){
2651 for(;size--; offset++) {
2652 if(AOP_TYPE(right) == AOP_LIT){
2653 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2656 MOVA(aopGet(AOP(right),offset,FALSE));
2657 emitcode("or","a,%s; 5",
2658 aopGet(AOP(left),offset,FALSE));
2659 aopPut(AOP(result),"a ; 8", offset);
2662 if (AOP_TYPE(left) == AOP_ACC)
2663 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2665 MOVA(aopGet(AOP(right),offset,FALSE));
2666 emitcode("or","a,%s ; 7",
2667 aopGet(AOP(left),offset,FALSE));
2668 aopPut(AOP(result),"a ; 8", offset);
2673 // left & result in different registers
2674 if(AOP_TYPE(result) == AOP_CRY){
2676 } else for(;(size--);offset++){
2678 // result = left & right
2679 if(AOP_TYPE(right) == AOP_LIT){
2680 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2682 aopGet(AOP(left),offset,FALSE),
2687 // faster than result <- left, anl result,right
2688 // and better if result is SFR
2689 if (AOP_TYPE(left) == AOP_ACC)
2690 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2692 MOVA(aopGet(AOP(right),offset,FALSE));
2693 emitcode("or","a,%s",
2694 aopGet(AOP(left),offset,FALSE));
2696 aopPut(AOP(result),"a",offset);
2697 /* PENDING: something weird is going on here. Add exception. */
2698 if (AOP_TYPE(result) == AOP_ACC)
2704 freeAsmop(left,NULL,ic);
2705 freeAsmop(right,NULL,ic);
2706 freeAsmop(result,NULL,ic);
2709 /*-----------------------------------------------------------------*/
2710 /* genXor - code for xclusive or */
2711 /*-----------------------------------------------------------------*/
2712 static void genXor (iCode *ic, iCode *ifx)
2714 operand *left, *right, *result;
2716 unsigned long lit = 0L;
2718 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2719 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2720 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2722 /* if left is a literal & right is not then exchange them */
2723 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2724 AOP_NEEDSACC(left)) {
2725 operand *tmp = right ;
2730 /* if result = right then exchange them */
2731 if(sameRegs(AOP(result),AOP(right))){
2732 operand *tmp = right ;
2737 /* if right is bit then exchange them */
2738 if (AOP_TYPE(right) == AOP_CRY &&
2739 AOP_TYPE(left) != AOP_CRY){
2740 operand *tmp = right ;
2744 if(AOP_TYPE(right) == AOP_LIT)
2745 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2747 size = AOP_SIZE(result);
2749 if (AOP_TYPE(left) == AOP_CRY){
2754 if((AOP_TYPE(right) == AOP_LIT) &&
2755 (AOP_TYPE(result) == AOP_CRY) &&
2756 (AOP_TYPE(left) != AOP_CRY)){
2761 /* if left is same as result */
2762 if(sameRegs(AOP(result),AOP(left))){
2763 for(;size--; offset++) {
2764 if(AOP_TYPE(right) == AOP_LIT){
2765 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2768 MOVA(aopGet(AOP(right),offset,FALSE));
2769 emitcode("xor","a,%s",
2770 aopGet(AOP(left),offset,FALSE));
2771 aopPut(AOP(result),"a",0);
2774 if (AOP_TYPE(left) == AOP_ACC)
2775 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2777 MOVA(aopGet(AOP(right),offset,FALSE));
2778 emitcode("xor","a,%s",
2779 aopGet(AOP(left),offset,FALSE));
2780 aopPut(AOP(result),"a",0);
2785 // left & result in different registers
2786 if(AOP_TYPE(result) == AOP_CRY){
2788 } else for(;(size--);offset++){
2790 // result = left & right
2791 if(AOP_TYPE(right) == AOP_LIT){
2792 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2794 aopGet(AOP(left),offset,FALSE),
2799 // faster than result <- left, anl result,right
2800 // and better if result is SFR
2801 if (AOP_TYPE(left) == AOP_ACC)
2802 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2804 MOVA(aopGet(AOP(right),offset,FALSE));
2805 emitcode("xor","a,%s",
2806 aopGet(AOP(left),offset,FALSE));
2807 aopPut(AOP(result),"a",0);
2809 aopPut(AOP(result),"a",offset);
2814 freeAsmop(left,NULL,ic);
2815 freeAsmop(right,NULL,ic);
2816 freeAsmop(result,NULL,ic);
2819 /*-----------------------------------------------------------------*/
2820 /* genInline - write the inline code out */
2821 /*-----------------------------------------------------------------*/
2822 static void genInline (iCode *ic)
2824 char buffer[MAX_INLINEASM];
2828 inLine += (!options.asmpeep);
2829 strcpy(buffer,IC_INLINE(ic));
2831 /* emit each line as a code */
2850 /* emitcode("",buffer); */
2851 inLine -= (!options.asmpeep);
2854 /*-----------------------------------------------------------------*/
2855 /* genRRC - rotate right with carry */
2856 /*-----------------------------------------------------------------*/
2857 static void genRRC (iCode *ic)
2862 /*-----------------------------------------------------------------*/
2863 /* genRLC - generate code for rotate left with carry */
2864 /*-----------------------------------------------------------------*/
2865 static void genRLC (iCode *ic)
2870 /*-----------------------------------------------------------------*/
2871 /* shiftR2Left2Result - shift right two bytes from left to result */
2872 /*-----------------------------------------------------------------*/
2873 static void shiftR2Left2Result (operand *left, int offl,
2874 operand *result, int offr,
2875 int shCount, int sign)
2877 if(sameRegs(AOP(result), AOP(left)) &&
2878 ((offl + MSB16) == offr)){
2881 movLeft2Result(left, offl, result, offr, 0);
2882 movLeft2Result(left, offl+1, result, offr+1, 0);
2889 /* if (AOP(result)->type == AOP_REG) {*/
2892 symbol *tlbl , *tlbl1;
2895 /* Left is already in result - so now do the shift */
2897 emitcode("ld","a,#%u+1", shCount);
2898 tlbl = newiTempLabel(NULL);
2899 tlbl1 = newiTempLabel(NULL);
2900 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
2901 emitcode("", LABEL_STR ":",tlbl->key+100);
2904 emitcode("or", "a,a");
2907 l = aopGet(AOP(result), --offset, FALSE);
2908 emitcode("rr","%s", l);
2911 emitcode("", LABEL_STR ":",tlbl1->key+100);
2912 emitcode("dec", "a");
2913 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
2918 /*-----------------------------------------------------------------*/
2919 /* shiftL2Left2Result - shift left two bytes from left to result */
2920 /*-----------------------------------------------------------------*/
2921 static void shiftL2Left2Result (operand *left, int offl,
2922 operand *result, int offr, int shCount)
2924 if(sameRegs(AOP(result), AOP(left)) &&
2925 ((offl + MSB16) == offr)){
2928 /* Copy left into result */
2929 movLeft2Result(left, offl, result, offr, 0);
2930 movLeft2Result(left, offl+1, result, offr+1, 0);
2932 /* PENDING: for now just see if it'll work. */
2933 /*if (AOP(result)->type == AOP_REG) { */
2937 symbol *tlbl , *tlbl1;
2940 /* Left is already in result - so now do the shift */
2942 emitcode("ld","a,#%u+1", shCount);
2943 tlbl = newiTempLabel(NULL);
2944 tlbl1 = newiTempLabel(NULL);
2945 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
2946 emitcode("", LABEL_STR ":",tlbl->key+100);
2949 emitcode("or", "a,a");
2951 l = aopGet(AOP(result),offset++,FALSE);
2952 emitcode("rl","%s", l);
2955 emitcode("", LABEL_STR ":",tlbl1->key+100);
2956 emitcode("dec", "a");
2957 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
2962 /*-----------------------------------------------------------------*/
2963 /* AccRol - rotate left accumulator by known count */
2964 /*-----------------------------------------------------------------*/
2965 static void AccRol (int shCount)
2967 shCount &= 0x0007; // shCount : 0..7
3004 /*-----------------------------------------------------------------*/
3005 /* AccLsh - left shift accumulator by known count */
3006 /*-----------------------------------------------------------------*/
3007 static void AccLsh (int shCount)
3011 emitcode("add","a,a");
3014 emitcode("add","a,a");
3015 emitcode("add","a,a");
3017 /* rotate left accumulator */
3019 /* and kill the lower order bits */
3020 emitcode("and","a,#0x%02x", SLMask[shCount]);
3025 /*-----------------------------------------------------------------*/
3026 /* shiftL1Left2Result - shift left one byte from left to result */
3027 /*-----------------------------------------------------------------*/
3028 static void shiftL1Left2Result (operand *left, int offl,
3029 operand *result, int offr, int shCount)
3032 l = aopGet(AOP(left),offl,FALSE);
3034 /* shift left accumulator */
3036 aopPut(AOP(result),"a",offr);
3040 /*-----------------------------------------------------------------*/
3041 /* genlshTwo - left shift two bytes by known amount != 0 */
3042 /*-----------------------------------------------------------------*/
3043 static void genlshTwo (operand *result,operand *left, int shCount)
3045 int size = AOP_SIZE(result);
3049 /* if shCount >= 8 */
3055 movLeft2Result(left, LSB, result, MSB16, 0);
3056 aopPut(AOP(result),zero, 0);
3057 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
3060 movLeft2Result(left, LSB, result, MSB16, 0);
3061 aopPut(AOP(result),zero, 0);
3064 aopPut(AOP(result),zero,LSB);
3066 /* 1 <= shCount <= 7 */
3072 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3077 /*-----------------------------------------------------------------*/
3078 /* genlshOne - left shift a one byte quantity by known count */
3079 /*-----------------------------------------------------------------*/
3080 static void genlshOne (operand *result, operand *left, int shCount)
3082 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3085 /*-----------------------------------------------------------------*/
3086 /* genLeftShiftLiteral - left shifting by known count */
3087 /*-----------------------------------------------------------------*/
3088 static void genLeftShiftLiteral (operand *left,
3093 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3096 freeAsmop(right,NULL,ic);
3098 aopOp(left,ic,FALSE);
3099 aopOp(result,ic,FALSE);
3101 size = getSize(operandType(result));
3104 emitcode("; shift left ","result %d, left %d",size,
3108 /* I suppose that the left size >= result size */
3113 else if(shCount >= (size * 8))
3115 aopPut(AOP(result),zero,size);
3119 genlshOne (result,left,shCount);
3122 genlshTwo (result,left,shCount);
3131 freeAsmop(left,NULL,ic);
3132 freeAsmop(result,NULL,ic);
3135 /*-----------------------------------------------------------------*/
3136 /* genLeftShift - generates code for left shifting */
3137 /*-----------------------------------------------------------------*/
3138 static void genLeftShift (iCode *ic)
3142 symbol *tlbl , *tlbl1;
3143 operand *left,*right, *result;
3145 right = IC_RIGHT(ic);
3147 result = IC_RESULT(ic);
3149 aopOp(right,ic,FALSE);
3151 /* if the shift count is known then do it
3152 as efficiently as possible */
3153 if (AOP_TYPE(right) == AOP_LIT) {
3154 genLeftShiftLiteral (left,right,result,ic);
3158 /* shift count is unknown then we have to form a loop get the loop
3159 count in B : Note: we take only the lower order byte since
3160 shifting more that 32 bits make no sense anyway, ( the largest
3161 size of an object can be only 32 bits ) */
3162 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3163 emitcode("inc","a");
3164 freeAsmop (right,NULL,ic);
3165 aopOp(left,ic,FALSE);
3166 aopOp(result,ic,FALSE);
3168 /* now move the left to the result if they are not the
3171 if (!sameRegs(AOP(left),AOP(result))) {
3173 size = AOP_SIZE(result);
3176 l = aopGet(AOP(left),offset,FALSE);
3177 aopPut(AOP(result),l,offset);
3182 size = AOP_SIZE(result);
3185 l = aopGet(AOP(left),offset,FALSE);
3186 aopPut(AOP(result),l,offset);
3192 tlbl = newiTempLabel(NULL);
3193 size = AOP_SIZE(result);
3195 tlbl1 = newiTempLabel(NULL);
3197 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3198 emitcode("", LABEL_STR ":",tlbl->key+100);
3199 l = aopGet(AOP(result),offset,FALSE);
3200 emitcode("or", "a,a");
3202 l = aopGet(AOP(result),offset++,FALSE);
3203 emitcode("rl","%s", l);
3205 emitcode("", LABEL_STR ":",tlbl1->key+100);
3206 emitcode("dec", "a");
3207 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3209 freeAsmop(left,NULL,ic);
3210 freeAsmop(result,NULL,ic);
3213 /* genlshTwo - left shift two bytes by known amount != 0 */
3214 /*-----------------------------------------------------------------*/
3215 static void genrshOne (operand *result,operand *left, int shCount)
3218 int size = AOP_SIZE(result);
3224 l = aopGet(AOP(left),0,FALSE);
3225 if (AOP(result)->type == AOP_REG) {
3226 aopPut(AOP(result), l, 0);
3227 l = aopGet(AOP(result), 0, FALSE);
3229 emitcode("srl", "%s", l);
3234 emitcode("srl", "a");
3236 aopPut(AOP(result),"a",0);
3240 /*-----------------------------------------------------------------*/
3241 /* AccRsh - right shift accumulator by known count */
3242 /*-----------------------------------------------------------------*/
3243 static void AccRsh (int shCount)
3250 /* rotate right accumulator */
3251 AccRol(8 - shCount);
3252 /* and kill the higher order bits */
3253 emitcode("and","a,#0x%02x", SRMask[shCount]);
3258 /*-----------------------------------------------------------------*/
3259 /* shiftR1Left2Result - shift right one byte from left to result */
3260 /*-----------------------------------------------------------------*/
3261 static void shiftR1Left2Result (operand *left, int offl,
3262 operand *result, int offr,
3263 int shCount, int sign)
3265 MOVA(aopGet(AOP(left),offl,FALSE));
3272 aopPut(AOP(result),"a",offr);
3275 /*-----------------------------------------------------------------*/
3276 /* genrshTwo - right shift two bytes by known amount != 0 */
3277 /*-----------------------------------------------------------------*/
3278 static void genrshTwo (operand *result,operand *left,
3279 int shCount, int sign)
3281 /* if shCount >= 8 */
3286 shiftR1Left2Result(left, MSB16, result, LSB,
3290 movLeft2Result(left, MSB16, result, LSB, sign);
3291 aopPut(AOP(result),zero,1);
3294 /* 1 <= shCount <= 7 */
3296 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3300 /*-----------------------------------------------------------------*/
3301 /* genRightShiftLiteral - left shifting by known count */
3302 /*-----------------------------------------------------------------*/
3303 static void genRightShiftLiteral (operand *left,
3308 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3311 freeAsmop(right,NULL,ic);
3313 aopOp(left,ic,FALSE);
3314 aopOp(result,ic,FALSE);
3316 size = getSize(operandType(result));
3318 emitcode("; shift right ","result %d, left %d",size,
3321 /* I suppose that the left size >= result size */
3326 else if(shCount >= (size * 8))
3328 aopPut(AOP(result),zero,size);
3332 genrshOne(result, left, shCount);
3335 /* PENDING: sign support */
3336 genrshTwo(result, left, shCount, FALSE);
3345 freeAsmop(left,NULL,ic);
3346 freeAsmop(result,NULL,ic);
3349 /*-----------------------------------------------------------------*/
3350 /* genRightShift - generate code for right shifting */
3351 /*-----------------------------------------------------------------*/
3352 static void genRightShift (iCode *ic)
3354 operand *left,*right, *result;
3356 right = IC_RIGHT(ic);
3358 result = IC_RESULT(ic);
3360 aopOp(right,ic,FALSE);
3362 /* if the shift count is known then do it
3363 as efficiently as possible */
3364 if (AOP_TYPE(right) == AOP_LIT) {
3365 genRightShiftLiteral (left,right,result,ic);
3373 /*-----------------------------------------------------------------*/
3374 /* genGenPointerGet - gget value from generic pointer space */
3375 /*-----------------------------------------------------------------*/
3376 static void genGenPointerGet (operand *left,
3377 operand *result, iCode *ic)
3380 link *retype = getSpec(operandType(result));
3381 const char *ptr = "hl";
3386 aopOp(left,ic,FALSE);
3387 aopOp(result,ic,FALSE);
3389 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3391 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3392 aopPut(AOP(result),"a", 0);
3393 freeAsmop(left,NULL,ic);
3397 /* For now we always load into IY */
3398 /* if this is remateriazable */
3399 if (AOP_TYPE(left) == AOP_IMMD)
3400 emitcode("ld","%s,%s", ptr, aopGet(AOP(left),0,TRUE));
3401 else { /* we need to get it byte by byte */
3405 if (AOP_SIZE(left) == 1) {
3409 emitcode("ld", "e,%s ; 1", aopGet(AOP(left), 0, FALSE));
3410 emitcode("ld", "d,%s ; 2", aopGet(AOP(left), 1, FALSE));
3417 /* so iy now contains the address */
3418 freeAsmop(left,NULL,ic);
3420 /* if bit then unpack */
3421 if (IS_BITVAR(retype)) {
3425 size = AOP_SIZE(result);
3429 /* PENDING: make this better */
3430 if (!IS_GB && AOP(result)->type == AOP_REG) {
3431 aopPut(AOP(result),"(hl)",offset++);
3434 emitcode("ld", "a,(%s)", ptr, offset);
3435 aopPut(AOP(result),"a",offset++);
3438 emitcode("inc", "%s", ptr);
3444 freeAsmop(result,NULL,ic);
3447 /*-----------------------------------------------------------------*/
3448 /* genPointerGet - generate code for pointer get */
3449 /*-----------------------------------------------------------------*/
3450 static void genPointerGet (iCode *ic)
3452 operand *left, *result ;
3456 result = IC_RESULT(ic) ;
3458 /* depending on the type of pointer we need to
3459 move it to the correct pointer register */
3460 type = operandType(left);
3461 etype = getSpec(type);
3463 genGenPointerGet (left,result,ic);
3466 bool isRegOrLit(asmop *aop)
3468 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3473 /*-----------------------------------------------------------------*/
3474 /* genGenPointerSet - stores the value into a pointer location */
3475 /*-----------------------------------------------------------------*/
3476 static void genGenPointerSet (operand *right,
3477 operand *result, iCode *ic)
3480 link *retype = getSpec(operandType(right));
3481 const char *ptr = "hl";
3483 aopOp(result,ic,FALSE);
3484 aopOp(right,ic,FALSE);
3489 /* Handle the exceptions first */
3490 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3492 char *l = aopGet(AOP(right), 0, FALSE);
3494 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3495 freeAsmop(result,NULL,ic);
3499 /* if the operand is already in dptr
3500 then we do nothing else we move the value to dptr */
3501 if (AOP_TYPE(result) != AOP_STR) {
3502 /* if this is remateriazable */
3503 if (AOP_TYPE(result) == AOP_IMMD) {
3504 emitcode("", "; Error 2");
3505 emitcode("ld", "%s,%s", ptr, aopGet(AOP(result), 0, TRUE));
3507 else { /* we need to get it byte by byte */
3509 emitcode("ld", "e,%s", aopGet(AOP(result), 0, TRUE));
3510 emitcode("ld", "d,%s", aopGet(AOP(result), 1, TRUE));
3513 /* PENDING: do this better */
3514 fetchHL(AOP(result));
3518 /* so hl know contains the address */
3519 freeAsmop(result,NULL,ic);
3521 /* if bit then unpack */
3522 if (IS_BITVAR(retype)) {
3526 size = AOP_SIZE(right);
3530 char *l = aopGet(AOP(right),offset,FALSE);
3531 if (isRegOrLit(AOP(right)) && !IS_GB) {
3532 emitcode("ld", "(%s),%s", ptr, l);
3536 emitcode("ld", "(%s),a", ptr, offset);
3539 emitcode("inc", ptr);
3545 freeAsmop(right,NULL,ic);
3548 /*-----------------------------------------------------------------*/
3549 /* genPointerSet - stores the value into a pointer location */
3550 /*-----------------------------------------------------------------*/
3551 static void genPointerSet (iCode *ic)
3553 operand *right, *result ;
3556 right = IC_RIGHT(ic);
3557 result = IC_RESULT(ic) ;
3559 /* depending on the type of pointer we need to
3560 move it to the correct pointer register */
3561 type = operandType(result);
3562 etype = getSpec(type);
3564 genGenPointerSet (right,result,ic);
3567 /*-----------------------------------------------------------------*/
3568 /* genIfx - generate code for Ifx statement */
3569 /*-----------------------------------------------------------------*/
3570 static void genIfx (iCode *ic, iCode *popIc)
3572 operand *cond = IC_COND(ic);
3575 aopOp(cond,ic,FALSE);
3577 /* get the value into acc */
3578 if (AOP_TYPE(cond) != AOP_CRY)
3582 /* the result is now in the accumulator */
3583 freeAsmop(cond,NULL,ic);
3585 /* if there was something to be popped then do it */
3589 /* if the condition is a bit variable */
3590 if (isbit && IS_ITEMP(cond) &&
3592 genIfxJump(ic,SPIL_LOC(cond)->rname);
3594 if (isbit && !IS_ITEMP(cond))
3595 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3602 /*-----------------------------------------------------------------*/
3603 /* genAddrOf - generates code for address of */
3604 /*-----------------------------------------------------------------*/
3605 static void genAddrOf (iCode *ic)
3607 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3609 aopOp(IC_RESULT(ic),ic,FALSE);
3611 /* if the operand is on the stack then we
3612 need to get the stack offset of this
3615 /* if it has an offset then we need to compute it */
3617 emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _pushed, _spoffset);
3618 emitcode("ld", "d,h");
3619 emitcode("ld", "e,l");
3620 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3621 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3625 emitcode("push", "de");
3626 emitcode("push", "ix");
3627 emitcode("pop", "hl");
3628 emitcode("ld", "de,#%d", sym->stack);
3629 emitcode("add", "hl,de");
3630 emitcode("pop", "de");
3634 emitcode("ld", "hl,#%s", sym->rname);
3636 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3637 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3639 freeAsmop(IC_RESULT(ic),NULL,ic);
3642 /*-----------------------------------------------------------------*/
3643 /* genAssign - generate code for assignment */
3644 /*-----------------------------------------------------------------*/
3645 static void genAssign (iCode *ic)
3647 operand *result, *right;
3649 unsigned long lit = 0L;
3651 result = IC_RESULT(ic);
3652 right = IC_RIGHT(ic) ;
3655 /* Dont bother assigning if they are the same */
3656 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3657 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3662 aopOp(right,ic,FALSE);
3663 aopOp(result,ic,TRUE);
3665 /* if they are the same registers */
3666 if (sameRegs(AOP(right),AOP(result))) {
3667 emitcode("", "; (registers are the same)");
3671 /* if the result is a bit */
3672 if (AOP_TYPE(result) == AOP_CRY) {
3677 size = AOP_SIZE(result);
3680 if(AOP_TYPE(right) == AOP_LIT)
3681 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3683 (AOP_TYPE(result) != AOP_REG) &&
3684 (AOP_TYPE(right) == AOP_LIT) &&
3685 !IS_FLOAT(operandType(right)) &&
3687 bool fXored = FALSE;
3689 /* Work from the top down.
3690 Done this way so that we can use the cached copy of 0
3691 in A for a fast clear */
3693 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3694 if (!fXored && size>1) {
3695 emitcode("xor", "a,a");
3699 aopPut(AOP(result),"a",offset);
3702 aopPut(AOP(result), "#0", offset);
3707 aopGet(AOP(right),offset,FALSE),
3712 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
3713 /* Special case. Load into a and d, then load out. */
3714 MOVA(aopGet(AOP(right), 0, FALSE));
3715 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
3716 aopPut(AOP(result), "a", 0);
3717 aopPut(AOP(result), "e", 1);
3721 aopGet(AOP(right),offset,FALSE),
3728 freeAsmop(right,NULL,ic);
3729 freeAsmop(result,NULL,ic);
3732 /*-----------------------------------------------------------------*/
3733 /* genJumpTab - genrates code for jump table */
3734 /*-----------------------------------------------------------------*/
3735 static void genJumpTab (iCode *ic)
3740 aopOp(IC_JTCOND(ic),ic,FALSE);
3741 /* get the condition into accumulator */
3742 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3745 emitcode("push", "de");
3746 emitcode("ld", "e,%s", l);
3747 emitcode("ld", "d,#0");
3748 jtab = newiTempLabel(NULL);
3749 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3750 emitcode("add", "hl,de");
3751 emitcode("add", "hl,de");
3752 emitcode("add", "hl,de");
3753 freeAsmop(IC_JTCOND(ic),NULL,ic);
3755 emitcode("pop", "de");
3756 emitcode("jp", "(hl)");
3757 emitcode("","%05d$:",jtab->key+100);
3758 /* now generate the jump labels */
3759 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3760 jtab = setNextItem(IC_JTLABELS(ic)))
3761 emitcode("jp", LABEL_STR, jtab->key+100);
3764 /*-----------------------------------------------------------------*/
3765 /* genCast - gen code for casting */
3766 /*-----------------------------------------------------------------*/
3767 static void genCast (iCode *ic)
3769 operand *result = IC_RESULT(ic);
3770 link *ctype = operandType(IC_LEFT(ic));
3771 operand *right = IC_RIGHT(ic);
3774 /* if they are equivalent then do nothing */
3775 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3778 aopOp(right,ic,FALSE) ;
3779 aopOp(result,ic,FALSE);
3781 /* if the result is a bit */
3782 if (AOP_TYPE(result) == AOP_CRY) {
3786 /* if they are the same size : or less */
3787 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3789 /* if they are in the same place */
3790 if (sameRegs(AOP(right),AOP(result)))
3793 /* if they in different places then copy */
3794 size = AOP_SIZE(result);
3798 aopGet(AOP(right),offset,FALSE),
3805 /* PENDING: should be OK. */
3807 /* if the result is of type pointer */
3808 if (IS_PTR(ctype)) {
3813 /* so we now know that the size of destination is greater
3814 than the size of the source */
3815 /* we move to result for the size of source */
3816 size = AOP_SIZE(right);
3820 aopGet(AOP(right),offset,FALSE),
3825 /* now depending on the sign of the destination */
3826 size = AOP_SIZE(result) - AOP_SIZE(right);
3827 /* Unsigned or not an integral type - right fill with zeros */
3828 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3830 aopPut(AOP(result),zero,offset++);
3832 /* we need to extend the sign :{ */
3833 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3836 emitcode("", "; genCast: sign extend untested.");
3837 emitcode("rla", "");
3838 emitcode("sbc", "a,a");
3840 aopPut(AOP(result),"a",offset++);
3844 freeAsmop(right, NULL, ic);
3845 freeAsmop(result, NULL, ic);
3848 /*-----------------------------------------------------------------*/
3849 /* genReceive - generate code for a receive iCode */
3850 /*-----------------------------------------------------------------*/
3851 static void genReceive (iCode *ic)
3853 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3854 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3855 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3859 aopOp(IC_RESULT(ic),ic,FALSE);
3861 assignResultValue(IC_RESULT(ic));
3864 freeAsmop(IC_RESULT(ic),NULL,ic);
3867 /*-----------------------------------------------------------------*/
3868 /* genZ80Code - generate code for Z80 based controllers */
3869 /*-----------------------------------------------------------------*/
3870 void genZ80Code (iCode *lic)
3877 _fReturn = _gbz80_return;
3878 _fTmp = _gbz80_return;
3882 _fReturn = _z80_return;
3883 _fTmp = _z80_return;
3887 lineHead = lineCurr = NULL;
3889 /* if debug information required */
3890 if (options.debug && currFunc) {
3891 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3893 if (IS_STATIC(currFunc->etype))
3894 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3896 emitcode("","G$%s$0$0 ==.",currFunc->name);
3899 /* stack pointer name */
3903 for (ic = lic ; ic ; ic = ic->next ) {
3905 if ( cln != ic->lineno ) {
3906 if ( options.debug ) {
3908 emitcode("","C$%s$%d$%d$%d ==.",
3909 ic->filename,ic->lineno,
3910 ic->level,ic->block);
3913 emitcode(";","%s %d",ic->filename,ic->lineno);
3916 /* if the result is marked as
3917 spilt and rematerializable or code for
3918 this has already been generated then
3920 if (resultRemat(ic) || ic->generated )
3923 /* depending on the operation */
3926 emitcode("", "; genNot");
3931 emitcode("", "; genCpl");
3936 emitcode("", "; genUminus");
3941 emitcode("", "; genIpush");
3946 /* IPOP happens only when trying to restore a
3947 spilt live range, if there is an ifx statement
3948 following this pop then the if statement might
3949 be using some of the registers being popped which
3950 would destory the contents of the register so
3951 we need to check for this condition and handle it */
3953 ic->next->op == IFX &&
3954 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3955 emitcode("", "; genIfx");
3956 genIfx (ic->next,ic);
3959 emitcode("", "; genIpop");
3965 emitcode("", "; genCall");
3970 emitcode("", "; genPcall");
3975 emitcode("", "; genFunction");
3980 emitcode("", "; genEndFunction");
3981 genEndFunction (ic);
3985 emitcode("", "; genRet");
3990 emitcode("", "; genLabel");
3995 emitcode("", "; genGoto");
4000 emitcode("", "; genPlus");
4005 emitcode("", "; genMinus");
4010 emitcode("", "; genMult");
4015 emitcode("", "; genDiv");
4020 emitcode("", "; genMod");
4025 emitcode("", "; genCmpGt");
4026 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4030 emitcode("", "; genCmpLt");
4031 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4038 /* note these two are xlated by algebraic equivalence
4039 during parsing SDCC.y */
4040 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4041 "got '>=' or '<=' shouldn't have come here");
4045 emitcode("", "; genCmpEq");
4046 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4050 emitcode("", "; genAndOp");
4055 emitcode("", "; genOrOp");
4060 emitcode("", "; genXor");
4061 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4065 emitcode("", "; genOr");
4066 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4070 emitcode("", "; genAnd");
4071 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4075 emitcode("", "; genInline");
4080 emitcode("", "; genRRC");
4085 emitcode("", "; genRLC");
4090 emitcode("", "; genHBIT");
4094 emitcode("", "; genLeftShift");
4099 emitcode("", "; genRightShift");
4103 case GET_VALUE_AT_ADDRESS:
4104 emitcode("", "; genPointerGet");
4110 if (POINTER_SET(ic)) {
4111 emitcode("", "; genAssign (pointer)");
4115 emitcode("", "; genAssign");
4121 emitcode("", "; genIfx");
4126 emitcode("", "; genAddrOf");
4131 emitcode("", "; genJumpTab");
4136 emitcode("", "; genCast");
4141 emitcode("", "; genReceive");
4146 emitcode("", "; addSet");
4147 addSet(&sendSet,ic);
4152 /* piCode(ic,stdout); */
4158 /* now we are ready to call the
4159 peep hole optimizer */
4160 if (!options.nopeep)
4161 peepHole (&lineHead);
4163 /* now do the actual printing */
4164 printLine (lineHead,codeOutFile);