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 */
3403 emitcode("ld", "e,%s ; 1", aopGet(AOP(left), 0, FALSE));
3404 emitcode("ld", "d,%s ; 2", aopGet(AOP(left), 1, FALSE));
3409 /* so iy now contains the address */
3410 freeAsmop(left,NULL,ic);
3412 /* if bit then unpack */
3413 if (IS_BITVAR(retype)) {
3417 size = AOP_SIZE(result);
3421 /* PENDING: make this better */
3422 if (!IS_GB && AOP(result)->type == AOP_REG) {
3423 aopPut(AOP(result),"(hl)",offset++);
3426 emitcode("ld", "a,(%s)", ptr, offset);
3427 aopPut(AOP(result),"a",offset++);
3430 emitcode("inc", "%s", ptr);
3436 freeAsmop(result,NULL,ic);
3439 /*-----------------------------------------------------------------*/
3440 /* genPointerGet - generate code for pointer get */
3441 /*-----------------------------------------------------------------*/
3442 static void genPointerGet (iCode *ic)
3444 operand *left, *result ;
3448 result = IC_RESULT(ic) ;
3450 /* depending on the type of pointer we need to
3451 move it to the correct pointer register */
3452 type = operandType(left);
3453 etype = getSpec(type);
3455 genGenPointerGet (left,result,ic);
3458 bool isRegOrLit(asmop *aop)
3460 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3465 /*-----------------------------------------------------------------*/
3466 /* genGenPointerSet - stores the value into a pointer location */
3467 /*-----------------------------------------------------------------*/
3468 static void genGenPointerSet (operand *right,
3469 operand *result, iCode *ic)
3472 link *retype = getSpec(operandType(right));
3473 const char *ptr = "hl";
3475 aopOp(result,ic,FALSE);
3476 aopOp(right,ic,FALSE);
3481 /* Handle the exceptions first */
3482 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3484 char *l = aopGet(AOP(right), 0, FALSE);
3486 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3487 freeAsmop(result,NULL,ic);
3491 /* if the operand is already in dptr
3492 then we do nothing else we move the value to dptr */
3493 if (AOP_TYPE(result) != AOP_STR) {
3494 /* if this is remateriazable */
3495 if (AOP_TYPE(result) == AOP_IMMD) {
3496 emitcode("", "; Error 2");
3497 emitcode("ld", "%s,%s", ptr, aopGet(AOP(result), 0, TRUE));
3499 else { /* we need to get it byte by byte */
3501 emitcode("ld", "e,%s", aopGet(AOP(result), 0, TRUE));
3502 emitcode("ld", "d,%s", aopGet(AOP(result), 1, TRUE));
3505 /* PENDING: do this better */
3506 fetchHL(AOP(result));
3510 /* so hl know contains the address */
3511 freeAsmop(result,NULL,ic);
3513 /* if bit then unpack */
3514 if (IS_BITVAR(retype)) {
3518 size = AOP_SIZE(right);
3522 char *l = aopGet(AOP(right),offset,FALSE);
3523 if (isRegOrLit(AOP(right)) && !IS_GB) {
3524 emitcode("ld", "(%s),%s", ptr, l);
3528 emitcode("ld", "(%s),a", ptr, offset);
3531 emitcode("inc", ptr);
3537 freeAsmop(right,NULL,ic);
3540 /*-----------------------------------------------------------------*/
3541 /* genPointerSet - stores the value into a pointer location */
3542 /*-----------------------------------------------------------------*/
3543 static void genPointerSet (iCode *ic)
3545 operand *right, *result ;
3548 right = IC_RIGHT(ic);
3549 result = IC_RESULT(ic) ;
3551 /* depending on the type of pointer we need to
3552 move it to the correct pointer register */
3553 type = operandType(result);
3554 etype = getSpec(type);
3556 genGenPointerSet (right,result,ic);
3559 /*-----------------------------------------------------------------*/
3560 /* genIfx - generate code for Ifx statement */
3561 /*-----------------------------------------------------------------*/
3562 static void genIfx (iCode *ic, iCode *popIc)
3564 operand *cond = IC_COND(ic);
3567 aopOp(cond,ic,FALSE);
3569 /* get the value into acc */
3570 if (AOP_TYPE(cond) != AOP_CRY)
3574 /* the result is now in the accumulator */
3575 freeAsmop(cond,NULL,ic);
3577 /* if there was something to be popped then do it */
3581 /* if the condition is a bit variable */
3582 if (isbit && IS_ITEMP(cond) &&
3584 genIfxJump(ic,SPIL_LOC(cond)->rname);
3586 if (isbit && !IS_ITEMP(cond))
3587 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3594 /*-----------------------------------------------------------------*/
3595 /* genAddrOf - generates code for address of */
3596 /*-----------------------------------------------------------------*/
3597 static void genAddrOf (iCode *ic)
3599 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3601 aopOp(IC_RESULT(ic),ic,FALSE);
3603 /* if the operand is on the stack then we
3604 need to get the stack offset of this
3608 emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _pushed, _spoffset);
3609 emitcode("ld", "d,h");
3610 emitcode("ld", "e,l");
3613 emitcode("ld", "de,#%s", sym->rname);
3615 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3616 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3620 /* if it has an offset then we need to compute it */
3621 emitcode("push", "de");
3622 emitcode("push", "ix");
3623 emitcode("pop", "hl");
3624 emitcode("ld", "de,#%d", sym->stack);
3625 emitcode("add", "hl,de");
3626 emitcode("pop", "de");
3629 emitcode("ld", "hl,#%s", sym->rname);
3631 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3632 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3634 freeAsmop(IC_RESULT(ic),NULL,ic);
3637 /*-----------------------------------------------------------------*/
3638 /* genAssign - generate code for assignment */
3639 /*-----------------------------------------------------------------*/
3640 static void genAssign (iCode *ic)
3642 operand *result, *right;
3644 unsigned long lit = 0L;
3646 result = IC_RESULT(ic);
3647 right = IC_RIGHT(ic) ;
3650 /* Dont bother assigning if they are the same */
3651 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3652 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3657 aopOp(right,ic,FALSE);
3658 aopOp(result,ic,TRUE);
3660 /* if they are the same registers */
3661 if (sameRegs(AOP(right),AOP(result))) {
3662 emitcode("", "; (registers are the same)");
3666 /* if the result is a bit */
3667 if (AOP_TYPE(result) == AOP_CRY) {
3672 size = AOP_SIZE(result);
3675 if(AOP_TYPE(right) == AOP_LIT)
3676 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3677 if (isPair(AOP(result)) && AOP_TYPE(right) == AOP_LIT) {
3678 emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
3680 else if((size > 1) &&
3681 (AOP_TYPE(result) != AOP_REG) &&
3682 (AOP_TYPE(right) == AOP_LIT) &&
3683 !IS_FLOAT(operandType(right)) &&
3685 bool fXored = FALSE;
3687 /* Work from the top down.
3688 Done this way so that we can use the cached copy of 0
3689 in A for a fast clear */
3691 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3692 if (!fXored && size>1) {
3693 emitcode("xor", "a,a");
3697 aopPut(AOP(result),"a",offset);
3700 aopPut(AOP(result), "#0", offset);
3705 aopGet(AOP(right),offset,FALSE),
3710 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
3711 /* Special case. Load into a and d, then load out. */
3712 MOVA(aopGet(AOP(right), 0, FALSE));
3713 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
3714 aopPut(AOP(result), "a", 0);
3715 aopPut(AOP(result), "e", 1);
3719 aopGet(AOP(right),offset,FALSE),
3726 freeAsmop(right,NULL,ic);
3727 freeAsmop(result,NULL,ic);
3730 /*-----------------------------------------------------------------*/
3731 /* genJumpTab - genrates code for jump table */
3732 /*-----------------------------------------------------------------*/
3733 static void genJumpTab (iCode *ic)
3738 aopOp(IC_JTCOND(ic),ic,FALSE);
3739 /* get the condition into accumulator */
3740 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3743 emitcode("push", "de");
3744 emitcode("ld", "e,%s", l);
3745 emitcode("ld", "d,#0");
3746 jtab = newiTempLabel(NULL);
3747 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3748 emitcode("add", "hl,de");
3749 emitcode("add", "hl,de");
3750 emitcode("add", "hl,de");
3751 freeAsmop(IC_JTCOND(ic),NULL,ic);
3753 emitcode("pop", "de");
3754 emitcode("jp", "(hl)");
3755 emitcode("","%05d$:",jtab->key+100);
3756 /* now generate the jump labels */
3757 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3758 jtab = setNextItem(IC_JTLABELS(ic)))
3759 emitcode("jp", LABEL_STR, jtab->key+100);
3762 /*-----------------------------------------------------------------*/
3763 /* genCast - gen code for casting */
3764 /*-----------------------------------------------------------------*/
3765 static void genCast (iCode *ic)
3767 operand *result = IC_RESULT(ic);
3768 link *ctype = operandType(IC_LEFT(ic));
3769 operand *right = IC_RIGHT(ic);
3772 /* if they are equivalent then do nothing */
3773 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3776 aopOp(right,ic,FALSE) ;
3777 aopOp(result,ic,FALSE);
3779 /* if the result is a bit */
3780 if (AOP_TYPE(result) == AOP_CRY) {
3784 /* if they are the same size : or less */
3785 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3787 /* if they are in the same place */
3788 if (sameRegs(AOP(right),AOP(result)))
3791 /* if they in different places then copy */
3792 size = AOP_SIZE(result);
3796 aopGet(AOP(right),offset,FALSE),
3803 /* PENDING: should be OK. */
3805 /* if the result is of type pointer */
3806 if (IS_PTR(ctype)) {
3811 /* so we now know that the size of destination is greater
3812 than the size of the source */
3813 /* we move to result for the size of source */
3814 size = AOP_SIZE(right);
3818 aopGet(AOP(right),offset,FALSE),
3823 /* now depending on the sign of the destination */
3824 size = AOP_SIZE(result) - AOP_SIZE(right);
3825 /* Unsigned or not an integral type - right fill with zeros */
3826 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3828 aopPut(AOP(result),zero,offset++);
3830 /* we need to extend the sign :{ */
3831 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3834 emitcode("", "; genCast: sign extend untested.");
3835 emitcode("rla", "");
3836 emitcode("sbc", "a,a");
3838 aopPut(AOP(result),"a",offset++);
3842 freeAsmop(right, NULL, ic);
3843 freeAsmop(result, NULL, ic);
3846 /*-----------------------------------------------------------------*/
3847 /* genReceive - generate code for a receive iCode */
3848 /*-----------------------------------------------------------------*/
3849 static void genReceive (iCode *ic)
3851 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3852 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3853 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3857 aopOp(IC_RESULT(ic),ic,FALSE);
3859 assignResultValue(IC_RESULT(ic));
3862 freeAsmop(IC_RESULT(ic),NULL,ic);
3865 /*-----------------------------------------------------------------*/
3866 /* genZ80Code - generate code for Z80 based controllers */
3867 /*-----------------------------------------------------------------*/
3868 void genZ80Code (iCode *lic)
3875 _fReturn = _gbz80_return;
3876 _fTmp = _gbz80_return;
3880 _fReturn = _z80_return;
3881 _fTmp = _z80_return;
3885 lineHead = lineCurr = NULL;
3887 /* if debug information required */
3888 if (options.debug && currFunc) {
3889 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3891 if (IS_STATIC(currFunc->etype))
3892 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3894 emitcode("","G$%s$0$0 ==.",currFunc->name);
3897 /* stack pointer name */
3901 for (ic = lic ; ic ; ic = ic->next ) {
3903 if ( cln != ic->lineno ) {
3904 if ( options.debug ) {
3906 emitcode("","C$%s$%d$%d$%d ==.",
3907 ic->filename,ic->lineno,
3908 ic->level,ic->block);
3911 emitcode(";","%s %d",ic->filename,ic->lineno);
3914 /* if the result is marked as
3915 spilt and rematerializable or code for
3916 this has already been generated then
3918 if (resultRemat(ic) || ic->generated )
3921 /* depending on the operation */
3924 emitcode("", "; genNot");
3929 emitcode("", "; genCpl");
3934 emitcode("", "; genUminus");
3939 emitcode("", "; genIpush");
3944 /* IPOP happens only when trying to restore a
3945 spilt live range, if there is an ifx statement
3946 following this pop then the if statement might
3947 be using some of the registers being popped which
3948 would destory the contents of the register so
3949 we need to check for this condition and handle it */
3951 ic->next->op == IFX &&
3952 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3953 emitcode("", "; genIfx");
3954 genIfx (ic->next,ic);
3957 emitcode("", "; genIpop");
3963 emitcode("", "; genCall");
3968 emitcode("", "; genPcall");
3973 emitcode("", "; genFunction");
3978 emitcode("", "; genEndFunction");
3979 genEndFunction (ic);
3983 emitcode("", "; genRet");
3988 emitcode("", "; genLabel");
3993 emitcode("", "; genGoto");
3998 emitcode("", "; genPlus");
4003 emitcode("", "; genMinus");
4008 emitcode("", "; genMult");
4013 emitcode("", "; genDiv");
4018 emitcode("", "; genMod");
4023 emitcode("", "; genCmpGt");
4024 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4028 emitcode("", "; genCmpLt");
4029 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4036 /* note these two are xlated by algebraic equivalence
4037 during parsing SDCC.y */
4038 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4039 "got '>=' or '<=' shouldn't have come here");
4043 emitcode("", "; genCmpEq");
4044 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4048 emitcode("", "; genAndOp");
4053 emitcode("", "; genOrOp");
4058 emitcode("", "; genXor");
4059 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4063 emitcode("", "; genOr");
4064 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4068 emitcode("", "; genAnd");
4069 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4073 emitcode("", "; genInline");
4078 emitcode("", "; genRRC");
4083 emitcode("", "; genRLC");
4088 emitcode("", "; genHBIT");
4092 emitcode("", "; genLeftShift");
4097 emitcode("", "; genRightShift");
4101 case GET_VALUE_AT_ADDRESS:
4102 emitcode("", "; genPointerGet");
4108 if (POINTER_SET(ic)) {
4109 emitcode("", "; genAssign (pointer)");
4113 emitcode("", "; genAssign");
4119 emitcode("", "; genIfx");
4124 emitcode("", "; genAddrOf");
4129 emitcode("", "; genJumpTab");
4134 emitcode("", "; genCast");
4139 emitcode("", "; genReceive");
4144 emitcode("", "; addSet");
4145 addSet(&sendSet,ic);
4150 /* piCode(ic,stdout); */
4156 /* now we are ready to call the
4157 peep hole optimizer */
4158 if (!options.nopeep)
4159 peepHole (&lineHead);
4161 /* now do the actual printing */
4162 printLine (lineHead,codeOutFile);