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 if (offset > (aop->size - 1) &&
636 aop->type != AOP_LIT)
639 /* depending on type */
643 sprintf (s,"#%s",aop->aopu.aop_immd);
653 ALLOC_ATOMIC(rs,strlen(s)+1);
659 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
661 ALLOC_ATOMIC(rs,strlen(s)+1);
666 return aop->aopu.aop_reg[offset]->name;
670 setupHL(aop, offset);
672 ALLOC_ATOMIC(rs, strlen(s)+1);
677 sprintf(s,"%d(iy)", offset);
678 ALLOC_ATOMIC(rs,strlen(s)+1);
684 setupHL(aop, offset);
688 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
690 ALLOC_ATOMIC(rs,strlen(s)+1);
704 return aopLiteral (aop->aopu.aop_lit,offset);
708 return aop->aopu.aop_str[offset];
711 fprintf(stderr, "Type %u\n", aop->type);
713 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
714 "aopget got unsupported aop->type");
718 bool isRegString(char *s)
720 if (!strcmp(s, "b") ||
731 bool isConstant(char *s)
736 bool canAssignToPtr(char *s)
745 /*-----------------------------------------------------------------*/
746 /* aopPut - puts a string for a aop */
747 /*-----------------------------------------------------------------*/
748 static void aopPut (asmop *aop, char *s, int offset)
750 if (aop->size && offset > ( aop->size - 1)) {
751 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
752 "aopPut got offset > aop->size");
756 /* will assign value to value */
757 /* depending on where it is ofcourse */
762 emitcode("ld", "a,%s", s);
763 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
767 /* Dont bother if it's a ld x,x */
768 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
769 emitcode("ld","%s,%s",
770 aop->aopu.aop_reg[offset]->name,s);
776 if (!canAssignToPtr(s)) {
777 emitcode("ld", "a,%s", s);
778 emitcode("ld", "%d(iy),a", offset);
781 emitcode("ld", "%d(iy),%s", offset, s);
786 if (!strcmp(s, "(hl)")) {
787 emitcode("ld", "a,(hl)");
790 setupHL(aop, offset);
791 emitcode("ld", "(hl),%s", s);
796 if (!strcmp("(hl)", s)) {
797 emitcode("ld", "a,(hl)");
800 setupHL(aop, offset);
801 if (!canAssignToPtr(s)) {
802 emitcode("ld", "a,%s", s);
803 emitcode("ld", "(hl),a");
806 emitcode("ld", "(hl),%s", s);
809 if (!canAssignToPtr(s)) {
810 emitcode("ld", "a,%s", s);
811 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
814 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
819 /* if bit variable */
820 if (!aop->aopu.aop_dir) {
821 emitcode("ld", "a,#0");
824 /* In bit space but not in C - cant happen */
831 if (strcmp(aop->aopu.aop_str[offset],s)) {
832 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
838 if (!offset && (strcmp(s,"acc") == 0))
842 emitcode("", "; Error aopPut AOP_ACC");
845 if (strcmp(aop->aopu.aop_str[offset],s))
846 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
851 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
852 "aopPut got unsupported aop->type");
857 #define AOP(op) op->aop
858 #define AOP_TYPE(op) AOP(op)->type
859 #define AOP_SIZE(op) AOP(op)->size
860 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
862 /*-----------------------------------------------------------------*/
863 /* getDataSize - get the operand data size */
864 /*-----------------------------------------------------------------*/
865 int getDataSize(operand *op)
876 /*-----------------------------------------------------------------*/
877 /* movLeft2Result - move byte from left to result */
878 /*-----------------------------------------------------------------*/
879 static void movLeft2Result (operand *left, int offl,
880 operand *result, int offr, int sign)
883 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
884 l = aopGet(AOP(left),offl,FALSE);
887 aopPut(AOP(result),l,offr);
896 /** Put Acc into a register set
898 void outAcc(operand *result)
901 size = getDataSize(result);
903 aopPut(AOP(result),"a",0);
906 /* unsigned or positive */
908 aopPut(AOP(result),zero,offset++);
913 /** Take the value in carry and put it into a register
915 void outBitC(operand *result)
917 /* if the result is bit */
918 if (AOP_TYPE(result) == AOP_CRY) {
919 emitcode("", "; Note: outBitC form 1");
920 aopPut(AOP(result),"blah",0);
923 emitcode("ld", "a,#0");
929 /*-----------------------------------------------------------------*/
930 /* toBoolean - emit code for orl a,operator(sizeop) */
931 /*-----------------------------------------------------------------*/
932 void toBoolean(operand *oper)
934 int size = AOP_SIZE(oper);
937 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
940 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
943 if (AOP(oper)->type != AOP_ACC) {
945 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
950 /*-----------------------------------------------------------------*/
951 /* genNot - generate code for ! operation */
952 /*-----------------------------------------------------------------*/
953 static void genNot (iCode *ic)
955 link *optype = operandType(IC_LEFT(ic));
957 /* assign asmOps to operand & result */
958 aopOp (IC_LEFT(ic),ic,FALSE);
959 aopOp (IC_RESULT(ic),ic,TRUE);
961 /* if in bit space then a special case */
962 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
966 /* if type float then do float */
967 if (IS_FLOAT(optype)) {
971 toBoolean(IC_LEFT(ic));
976 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
977 emitcode("sub", "a,#0x01");
978 outBitC(IC_RESULT(ic));
980 /* release the aops */
981 freeAsmop(IC_LEFT(ic),NULL,ic);
982 freeAsmop(IC_RESULT(ic),NULL,ic);
985 /*-----------------------------------------------------------------*/
986 /* genCpl - generate code for complement */
987 /*-----------------------------------------------------------------*/
988 static void genCpl (iCode *ic)
994 /* assign asmOps to operand & result */
995 aopOp (IC_LEFT(ic),ic,FALSE);
996 aopOp (IC_RESULT(ic),ic,TRUE);
998 /* if both are in bit space then
1000 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1001 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1005 size = AOP_SIZE(IC_RESULT(ic));
1007 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1010 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1013 /* release the aops */
1014 freeAsmop(IC_LEFT(ic),NULL,ic);
1015 freeAsmop(IC_RESULT(ic),NULL,ic);
1018 /*-----------------------------------------------------------------*/
1019 /* genUminus - unary minus code generation */
1020 /*-----------------------------------------------------------------*/
1021 static void genUminus (iCode *ic)
1024 link *optype, *rtype;
1027 aopOp(IC_LEFT(ic),ic,FALSE);
1028 aopOp(IC_RESULT(ic),ic,TRUE);
1030 /* if both in bit space then special
1032 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1033 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1038 optype = operandType(IC_LEFT(ic));
1039 rtype = operandType(IC_RESULT(ic));
1041 /* if float then do float stuff */
1042 if (IS_FLOAT(optype)) {
1047 /* otherwise subtract from zero */
1048 size = AOP_SIZE(IC_LEFT(ic));
1052 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1053 emitcode("ld", "a,#0");
1054 emitcode("sbc","a,%s",l);
1055 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1058 /* if any remaining bytes in the result */
1059 /* we just need to propagate the sign */
1060 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1061 emitcode("rlc","a");
1062 emitcode("sbc","a,a");
1064 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1068 /* release the aops */
1069 freeAsmop(IC_LEFT(ic),NULL,ic);
1070 freeAsmop(IC_RESULT(ic),NULL,ic);
1073 static bool requiresHL(asmop *aop)
1075 switch (aop->type) {
1084 /*-----------------------------------------------------------------*/
1085 /* assignResultValue - */
1086 /*-----------------------------------------------------------------*/
1087 void assignResultValue(operand * oper)
1090 int size = AOP_SIZE(oper);
1095 aopPut(AOP(oper),_fReturn[offset],offset);
1100 static void fetchHL(asmop *aop)
1102 if (IS_GB && requiresHL(aop)) {
1103 aopGet(aop, 0, FALSE);
1104 emitcode("ld", "a,(hl+)");
1105 emitcode("ld", "h,(hl)");
1106 emitcode("ld", "l,a");
1109 emitcode("ld", "l,%s", aopGet(aop, 0, FALSE));
1110 emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
1114 /*-----------------------------------------------------------------*/
1115 /* genIpush - genrate code for pushing this gets a little complex */
1116 /*-----------------------------------------------------------------*/
1117 static void genIpush (iCode *ic)
1119 int size, offset = 0 ;
1123 /* if this is not a parm push : ie. it is spill push
1124 and spill push is always done on the local stack */
1125 if (!ic->parmPush) {
1126 /* and the item is spilt then do nothing */
1127 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1130 aopOp(IC_LEFT(ic),ic,FALSE);
1131 size = AOP_SIZE(IC_LEFT(ic));
1132 /* push it on the stack */
1133 if (isPair(AOP(IC_LEFT(ic)))) {
1134 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1140 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1141 /* Simple for now - load into A and PUSH AF */
1142 emitcode("ld", "a,%s", l);
1143 emitcode("push", "af");
1144 emitcode("inc", "sp");
1151 /* Hmmm... what about saving the currently used registers
1154 /* then do the push */
1155 aopOp(IC_LEFT(ic),ic,FALSE);
1157 size = AOP_SIZE(IC_LEFT(ic));
1159 if (isPair(AOP(IC_LEFT(ic)))) {
1161 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1165 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1167 emitcode("ld", "hl,%s", s);
1168 emitcode("push", "hl");
1172 /* Optimise here - load into HL then push HL */
1173 fetchHL(AOP(IC_LEFT(ic)));
1174 emitcode("push", "hl");
1181 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1182 emitcode("ld", "a,%s", l);
1183 emitcode("push", "af");
1184 emitcode("inc", "sp");
1189 freeAsmop(IC_LEFT(ic),NULL,ic);
1192 /*-----------------------------------------------------------------*/
1193 /* genIpop - recover the registers: can happen only for spilling */
1194 /*-----------------------------------------------------------------*/
1195 static void genIpop (iCode *ic)
1200 /* if the temp was not pushed then */
1201 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1204 aopOp(IC_LEFT(ic),ic,FALSE);
1205 size = AOP_SIZE(IC_LEFT(ic));
1207 if (isPair(AOP(IC_LEFT(ic)))) {
1208 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1212 emitcode("dec", "sp");
1213 emitcode("pop", "hl");
1214 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1218 freeAsmop(IC_LEFT(ic),NULL,ic);
1221 /** Emit the code for a call statement
1223 static void emitCall (iCode *ic, bool ispcall)
1225 /* if caller saves & we have not saved then */
1226 if (!ic->regsSaved) {
1230 /* if send set is not empty then assign */
1233 for (sic = setFirstItem(sendSet) ; sic ;
1234 sic = setNextItem(sendSet)) {
1235 int size, offset = 0;
1236 aopOp(IC_LEFT(sic),sic,FALSE);
1237 size = AOP_SIZE(IC_LEFT(sic));
1239 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1241 if (strcmp(l, _fReturn[offset]))
1242 emitcode("ld","%s,%s",
1247 freeAsmop (IC_LEFT(sic),NULL,sic);
1253 symbol *rlbl = newiTempLabel(NULL);
1255 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1256 emitcode("push", "hl");
1259 aopOp(IC_LEFT(ic),ic,FALSE);
1260 fetchHL(AOP(IC_LEFT(ic)));
1261 freeAsmop(IC_LEFT(ic),NULL,ic);
1263 emitcode("jp", "(hl)");
1264 emitcode("","%05d$:",(rlbl->key+100));
1269 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1270 OP_SYMBOL(IC_LEFT(ic))->rname :
1271 OP_SYMBOL(IC_LEFT(ic))->name;
1272 emitcode("call", "%s", name);
1275 /* if we need assign a result value */
1276 if ((IS_ITEMP(IC_RESULT(ic)) &&
1277 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1278 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1279 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1282 aopOp(IC_RESULT(ic),ic,FALSE);
1285 assignResultValue(IC_RESULT(ic));
1287 freeAsmop(IC_RESULT(ic),NULL, ic);
1290 /* adjust the stack for parameters if required */
1291 if (IC_LEFT(ic)->parmBytes) {
1292 int i = IC_LEFT(ic)->parmBytes;
1295 emitcode("lda", "sp,%d(sp)", i);
1299 emitcode("ld", "hl,#%d", i);
1300 emitcode("add", "hl,sp");
1301 emitcode("ld", "sp,hl");
1305 emitcode("pop", "hl");
1309 emitcode("inc", "sp");
1316 /*-----------------------------------------------------------------*/
1317 /* genCall - generates a call statement */
1318 /*-----------------------------------------------------------------*/
1319 static void genCall (iCode *ic)
1321 emitCall(ic, FALSE);
1324 /*-----------------------------------------------------------------*/
1325 /* genPcall - generates a call by pointer statement */
1326 /*-----------------------------------------------------------------*/
1327 static void genPcall (iCode *ic)
1332 /*-----------------------------------------------------------------*/
1333 /* resultRemat - result is rematerializable */
1334 /*-----------------------------------------------------------------*/
1335 static int resultRemat (iCode *ic)
1337 if (SKIP_IC(ic) || ic->op == IFX)
1340 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1341 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1342 if (sym->remat && !POINTER_SET(ic))
1349 /*-----------------------------------------------------------------*/
1350 /* genFunction - generated code for function entry */
1351 /*-----------------------------------------------------------------*/
1352 static void genFunction (iCode *ic)
1358 /* create the function header */
1359 emitcode(";","-----------------------------------------");
1360 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1361 emitcode(";","-----------------------------------------");
1363 emitcode("","%s:",sym->rname);
1364 fetype = getSpec(operandType(IC_LEFT(ic)));
1366 /* if critical function then turn interrupts off */
1367 if (SPEC_CRTCL(fetype))
1370 /* if this is an interrupt service routine then
1371 save acc, b, dpl, dph */
1372 if (IS_ISR(sym->etype)) {
1373 emitcode("push", "af");
1374 emitcode("push", "bc");
1375 emitcode("push", "de");
1376 emitcode("push", "hl");
1378 /* PENDING: callee-save etc */
1380 /* adjust the stack for the function */
1381 emitcode("push", "bc");
1383 emitcode("push", "de");
1384 emitcode("push", "ix");
1385 emitcode("ld", "ix,#0");
1386 emitcode("add", "ix,sp");
1389 _lastStack = sym->stack;
1393 emitcode("lda", "sp,-%d(sp)", sym->stack);
1396 emitcode("ld", "hl,#-%d", sym->stack);
1397 emitcode("add", "hl,sp");
1398 emitcode("ld", "sp,hl");
1401 _spoffset = sym->stack;
1404 /*-----------------------------------------------------------------*/
1405 /* genEndFunction - generates epilogue for functions */
1406 /*-----------------------------------------------------------------*/
1407 static void genEndFunction (iCode *ic)
1409 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1411 if (IS_ISR(sym->etype)) {
1415 if (SPEC_CRTCL(sym->etype))
1418 /* PENDING: calleeSave */
1420 /* if debug then send end of function */
1421 if (options.debug && currFunc) {
1423 emitcode("","C$%s$%d$%d$%d ==.",
1424 ic->filename,currFunc->lastLine,
1425 ic->level,ic->block);
1426 if (IS_STATIC(currFunc->etype))
1427 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1429 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1433 emitcode("ld", "sp,ix");
1434 emitcode("pop", "ix");
1435 emitcode("pop", "de");
1439 emitcode("ld", "hl,#%d", _spoffset);
1440 emitcode("add", "hl,sp");
1441 emitcode("ld", "sp,hl");
1444 emitcode("pop", "bc");
1445 emitcode("ret", "");
1451 /*-----------------------------------------------------------------*/
1452 /* genRet - generate code for return statement */
1453 /*-----------------------------------------------------------------*/
1454 static void genRet (iCode *ic)
1457 /* Errk. This is a hack until I can figure out how
1458 to cause dehl to spill on a call */
1459 int size,offset = 0;
1461 /* if we have no return value then
1462 just generate the "ret" */
1466 /* we have something to return then
1467 move the return value into place */
1468 aopOp(IC_LEFT(ic),ic,FALSE);
1469 size = AOP_SIZE(IC_LEFT(ic));
1471 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1473 emitcode("ld", "de,%s", l);
1476 emitcode("ld", "hl,%s", l);
1481 l = aopGet(AOP(IC_LEFT(ic)),offset,
1483 if (strcmp(_fReturn[offset],l))
1484 emitcode("ld","%s,%s", _fReturn[offset++],l);
1487 freeAsmop (IC_LEFT(ic),NULL,ic);
1490 /* generate a jump to the return label
1491 if the next is not the return statement */
1492 if (!(ic->next && ic->next->op == LABEL &&
1493 IC_LABEL(ic->next) == returnLabel))
1495 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1498 /*-----------------------------------------------------------------*/
1499 /* genLabel - generates a label */
1500 /*-----------------------------------------------------------------*/
1501 static void genLabel (iCode *ic)
1503 /* special case never generate */
1504 if (IC_LABEL(ic) == entryLabel)
1507 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1510 /*-----------------------------------------------------------------*/
1511 /* genGoto - generates a ljmp */
1512 /*-----------------------------------------------------------------*/
1513 static void genGoto (iCode *ic)
1515 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1518 /*-----------------------------------------------------------------*/
1519 /* genPlusIncr :- does addition with increment if possible */
1520 /*-----------------------------------------------------------------*/
1521 static bool genPlusIncr (iCode *ic)
1523 unsigned int icount ;
1524 unsigned int size = getDataSize(IC_RESULT(ic));
1526 /* will try to generate an increment */
1527 /* if the right side is not a literal
1529 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1532 emitcode("", "; genPlusIncr");
1534 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1536 /* If result is a pair */
1537 if (isPair(AOP(IC_RESULT(ic)))) {
1538 char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1540 /* Both a lit on the right and a true symbol on the left */
1541 emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
1546 /* if the literal value of the right hand side
1547 is greater than 4 then it is not worth it */
1552 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1553 isPair(AOP(IC_RESULT(ic)))) {
1555 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1559 /* if increment 16 bits in register */
1560 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1563 symbol *tlbl = newiTempLabel(NULL);
1564 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1565 emitcode(_shortJP, "nz," LABEL_STR ,tlbl->key+100);
1567 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1571 emitcode("", LABEL_STR ":",tlbl->key+100);
1575 /* If result is a pair */
1576 if (isPair(AOP(IC_RESULT(ic)))) {
1577 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1578 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1580 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1584 /* if the sizes are greater than 1 then we cannot */
1585 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1586 AOP_SIZE(IC_LEFT(ic)) > 1 )
1589 /* we can if the aops of the left & result match or
1590 if they are in registers and the registers are the
1592 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1594 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1602 /*-----------------------------------------------------------------*/
1603 /* outBitAcc - output a bit in acc */
1604 /*-----------------------------------------------------------------*/
1605 void outBitAcc(operand *result)
1607 symbol *tlbl = newiTempLabel(NULL);
1608 /* if the result is a bit */
1609 if (AOP_TYPE(result) == AOP_CRY){
1613 emitcode(_shortJP,"z," LABEL_STR ,tlbl->key+100);
1614 emitcode("ld","a,%s",one);
1615 emitcode("", LABEL_STR ":",tlbl->key+100);
1620 /*-----------------------------------------------------------------*/
1621 /* genPlus - generates code for addition */
1622 /*-----------------------------------------------------------------*/
1623 static void genPlus (iCode *ic)
1625 int size, offset = 0;
1627 /* special cases :- */
1629 aopOp (IC_LEFT(ic),ic,FALSE);
1630 aopOp (IC_RIGHT(ic),ic,FALSE);
1631 aopOp (IC_RESULT(ic),ic,TRUE);
1633 /* Swap the left and right operands if:
1635 if literal, literal on the right or
1636 if left requires ACC or right is already
1639 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1640 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1641 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1642 operand *t = IC_RIGHT(ic);
1643 IC_RIGHT(ic) = IC_LEFT(ic);
1647 /* if both left & right are in bit
1649 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1650 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1655 /* if left in bit space & right literal */
1656 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1657 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1658 /* Can happen I guess */
1662 /* if I can do an increment instead
1663 of add then GOOD for ME */
1664 if (genPlusIncr (ic) == TRUE)
1667 size = getDataSize(IC_RESULT(ic));
1669 /* Special case when left and right are constant */
1670 if (isPair(AOP(IC_RESULT(ic)))) {
1673 left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1674 right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1675 if (left && right) {
1679 sprintf(buffer, "#(%s + %s)", left, right);
1680 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1686 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1687 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1689 emitcode("add","a,%s",
1690 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1692 emitcode("adc","a,%s",
1693 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1695 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1697 emitcode("add","a,%s",
1698 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1700 emitcode("adc","a,%s",
1701 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1703 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1706 /* Some kind of pointer arith. */
1707 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1708 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1709 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1712 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1713 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1714 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1719 freeAsmop(IC_LEFT(ic),NULL,ic);
1720 freeAsmop(IC_RIGHT(ic),NULL,ic);
1721 freeAsmop(IC_RESULT(ic),NULL,ic);
1725 /*-----------------------------------------------------------------*/
1726 /* genMinusDec :- does subtraction with deccrement if possible */
1727 /*-----------------------------------------------------------------*/
1728 static bool genMinusDec (iCode *ic)
1730 unsigned int icount ;
1731 unsigned int size = getDataSize(IC_RESULT(ic));
1733 /* will try to generate an increment */
1734 /* if the right side is not a literal we cannot */
1735 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1738 /* if the literal value of the right hand side
1739 is greater than 4 then it is not worth it */
1740 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1743 size = getDataSize(IC_RESULT(ic));
1746 /* if increment 16 bits in register */
1747 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1750 symbol *tlbl = newiTempLabel(NULL);
1751 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1752 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1754 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1758 emitcode("", LABEL_STR ":",tlbl->key+100);
1763 /* if decrement 16 bits in register */
1764 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1765 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1767 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1771 /* If result is a pair */
1772 if (isPair(AOP(IC_RESULT(ic)))) {
1773 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1774 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1776 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1780 /* if the sizes are greater than 1 then we cannot */
1781 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1782 AOP_SIZE(IC_LEFT(ic)) > 1 )
1785 /* we can if the aops of the left & result match or if they are in
1786 registers and the registers are the same */
1787 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1789 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1796 /*-----------------------------------------------------------------*/
1797 /* genMinus - generates code for subtraction */
1798 /*-----------------------------------------------------------------*/
1799 static void genMinus (iCode *ic)
1801 int size, offset = 0;
1802 unsigned long lit = 0L;
1804 aopOp (IC_LEFT(ic),ic,FALSE);
1805 aopOp (IC_RIGHT(ic),ic,FALSE);
1806 aopOp (IC_RESULT(ic),ic,TRUE);
1808 /* special cases :- */
1809 /* if both left & right are in bit space */
1810 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1811 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1816 /* if I can do an decrement instead of subtract then GOOD for ME */
1817 if (genMinusDec (ic) == TRUE)
1820 size = getDataSize(IC_RESULT(ic));
1822 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1825 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1830 /* if literal, add a,#-lit, else normal subb */
1832 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1833 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1835 emitcode("sub","a,%s",
1836 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1838 emitcode("sbc","a,%s",
1839 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1842 /* first add without previous c */
1844 emitcode("add","a,#0x%02x",
1845 (unsigned int)(lit & 0x0FFL));
1847 emitcode("adc","a,#0x%02x",
1848 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1850 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1853 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1854 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1855 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1859 freeAsmop(IC_LEFT(ic),NULL,ic);
1860 freeAsmop(IC_RIGHT(ic),NULL,ic);
1861 freeAsmop(IC_RESULT(ic),NULL,ic);
1864 /*-----------------------------------------------------------------*/
1865 /* genMult - generates code for multiplication */
1866 /*-----------------------------------------------------------------*/
1867 static void genMult (iCode *ic)
1869 /* Shouldn't occur - all done through function calls */
1873 /*-----------------------------------------------------------------*/
1874 /* genDiv - generates code for division */
1875 /*-----------------------------------------------------------------*/
1876 static void genDiv (iCode *ic)
1878 /* Shouldn't occur - all done through function calls */
1882 /*-----------------------------------------------------------------*/
1883 /* genMod - generates code for division */
1884 /*-----------------------------------------------------------------*/
1885 static void genMod (iCode *ic)
1887 /* Shouldn't occur - all done through function calls */
1891 /*-----------------------------------------------------------------*/
1892 /* genIfxJump :- will create a jump depending on the ifx */
1893 /*-----------------------------------------------------------------*/
1894 static void genIfxJump (iCode *ic, char *jval)
1899 /* if true label then we jump if condition
1901 if ( IC_TRUE(ic) ) {
1903 if (!strcmp(jval, "a")) {
1906 else if (!strcmp(jval, "c")) {
1910 /* The buffer contains the bit on A that we should test */
1915 /* false label is present */
1916 jlbl = IC_FALSE(ic) ;
1917 if (!strcmp(jval, "a")) {
1920 else if (!strcmp(jval, "c")) {
1924 /* The buffer contains the bit on A that we should test */
1928 /* Z80 can do a conditional long jump */
1929 if (!strcmp(jval, "a")) {
1930 emitcode("or", "a,a");
1932 else if (!strcmp(jval, "c")) {
1935 emitcode("bit", "%s,a", jval);
1937 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1939 /* mark the icode as generated */
1943 /** Generic compare for > or <
1945 static void genCmp (operand *left,operand *right,
1946 operand *result, iCode *ifx, int sign)
1948 int size, offset = 0 ;
1949 unsigned long lit = 0L;
1951 /* if left & right are bit variables */
1952 if (AOP_TYPE(left) == AOP_CRY &&
1953 AOP_TYPE(right) == AOP_CRY ) {
1954 /* Cant happen on the Z80 */
1957 /* subtract right from left if at the
1958 end the carry flag is set then we know that
1959 left is greater than right */
1960 size = max(AOP_SIZE(left),AOP_SIZE(right));
1962 /* if unsigned char cmp with lit, just compare */
1964 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1965 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1967 emitcode("xor", "a,#0x80");
1968 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
1971 emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
1974 if(AOP_TYPE(right) == AOP_LIT) {
1975 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1976 /* optimize if(x < 0) or if(x >= 0) */
1979 /* No sign so it's always false */
1983 /* Just load in the top most bit */
1984 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1985 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1986 genIfxJump (ifx,"7");
1990 emitcode("rlc","a");
1996 /* First setup h and l contaning the top most bytes XORed */
1997 bool fDidXor = FALSE;
1998 if (AOP_TYPE(left) == AOP_LIT){
1999 unsigned long lit = (unsigned long)
2000 floatFromVal(AOP(left)->aopu.aop_lit);
2001 emitcode("ld", "%s,#0x%02x", _fTmp[0],
2002 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2005 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2006 emitcode("xor", "a,#0x80");
2007 emitcode("ld", "%s,a", _fTmp[0]);
2010 if (AOP_TYPE(right) == AOP_LIT) {
2011 unsigned long lit = (unsigned long)
2012 floatFromVal(AOP(right)->aopu.aop_lit);
2013 emitcode("ld", "%s,#0x%02x", _fTmp[1],
2014 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2017 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2018 emitcode("xor", "a,#0x80");
2019 emitcode("ld", "%s,a", _fTmp[1]);
2029 /* Do a long subtract */
2031 MOVA(aopGet(AOP(left),offset,FALSE));
2032 if (sign && size == 0) {
2033 emitcode("ld", "a,%s", _fTmp[0]);
2034 emitcode("sbc", "a,%s", _fTmp[1]);
2037 /* Subtract through, propagating the carry */
2038 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
2045 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2048 /* if the result is used in the next
2049 ifx conditional branch then generate
2050 code a little differently */
2052 genIfxJump (ifx,"c");
2055 /* leave the result in acc */
2059 /*-----------------------------------------------------------------*/
2060 /* genCmpGt :- greater than comparison */
2061 /*-----------------------------------------------------------------*/
2062 static void genCmpGt (iCode *ic, iCode *ifx)
2064 operand *left, *right, *result;
2065 link *letype , *retype;
2069 right= IC_RIGHT(ic);
2070 result = IC_RESULT(ic);
2072 letype = getSpec(operandType(left));
2073 retype =getSpec(operandType(right));
2074 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2075 /* assign the amsops */
2076 aopOp (left,ic,FALSE);
2077 aopOp (right,ic,FALSE);
2078 aopOp (result,ic,TRUE);
2080 genCmp(right, left, result, ifx, sign);
2082 freeAsmop(left,NULL,ic);
2083 freeAsmop(right,NULL,ic);
2084 freeAsmop(result,NULL,ic);
2087 /*-----------------------------------------------------------------*/
2088 /* genCmpLt - less than comparisons */
2089 /*-----------------------------------------------------------------*/
2090 static void genCmpLt (iCode *ic, iCode *ifx)
2092 operand *left, *right, *result;
2093 link *letype , *retype;
2097 right= IC_RIGHT(ic);
2098 result = IC_RESULT(ic);
2100 letype = getSpec(operandType(left));
2101 retype =getSpec(operandType(right));
2102 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2104 /* assign the amsops */
2105 aopOp (left,ic,FALSE);
2106 aopOp (right,ic,FALSE);
2107 aopOp (result,ic,TRUE);
2109 genCmp(left, right, result, ifx, sign);
2111 freeAsmop(left,NULL,ic);
2112 freeAsmop(right,NULL,ic);
2113 freeAsmop(result,NULL,ic);
2116 /*-----------------------------------------------------------------*/
2117 /* gencjneshort - compare and jump if not equal */
2118 /*-----------------------------------------------------------------*/
2119 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2121 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2123 unsigned long lit = 0L;
2125 /* Swap the left and right if it makes the computation easier */
2126 if (AOP_TYPE(left) == AOP_LIT) {
2132 if(AOP_TYPE(right) == AOP_LIT)
2133 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2135 /* if the right side is a literal then anything goes */
2136 if (AOP_TYPE(right) == AOP_LIT &&
2137 AOP_TYPE(left) != AOP_DIR ) {
2139 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2140 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2141 emitcode("or", "a,a");
2143 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2144 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2148 /* if the right side is in a register or in direct space or
2149 if the left is a pointer register & right is not */
2150 else if (AOP_TYPE(right) == AOP_REG ||
2151 AOP_TYPE(right) == AOP_DIR ||
2152 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2154 MOVA(aopGet(AOP(left),offset,FALSE));
2155 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2156 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2158 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
2160 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2161 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2166 /* right is a pointer reg need both a & b */
2167 /* PENDING: is this required? */
2169 char *l = aopGet(AOP(left),offset,FALSE);
2170 MOVA(aopGet(AOP(right),offset,FALSE));
2171 emitcode("cp", "%s ; 5", l);
2172 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2178 /*-----------------------------------------------------------------*/
2179 /* gencjne - compare and jump if not equal */
2180 /*-----------------------------------------------------------------*/
2181 static void gencjne(operand *left, operand *right, symbol *lbl)
2183 symbol *tlbl = newiTempLabel(NULL);
2185 gencjneshort(left, right, lbl);
2188 emitcode("ld","a,%s",one);
2189 emitcode(_shortJP, LABEL_STR ,tlbl->key+100);
2190 emitcode("", LABEL_STR ":",lbl->key+100);
2191 emitcode("xor","a,a");
2192 emitcode("", LABEL_STR ":",tlbl->key+100);
2195 /*-----------------------------------------------------------------*/
2196 /* genCmpEq - generates code for equal to */
2197 /*-----------------------------------------------------------------*/
2198 static void genCmpEq (iCode *ic, iCode *ifx)
2200 operand *left, *right, *result;
2202 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2203 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2204 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2206 /* Swap operands if it makes the operation easier. ie if:
2207 1. Left is a literal.
2209 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2210 operand *t = IC_RIGHT(ic);
2211 IC_RIGHT(ic) = IC_LEFT(ic);
2215 if (ifx && !AOP_SIZE(result)){
2217 /* if they are both bit variables */
2218 if (AOP_TYPE(left) == AOP_CRY &&
2219 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2222 tlbl = newiTempLabel(NULL);
2223 gencjneshort(left, right, tlbl);
2224 if ( IC_TRUE(ifx) ) {
2225 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2226 emitcode("", LABEL_STR ":",tlbl->key+100);
2228 /* PENDING: do this better */
2229 symbol *lbl = newiTempLabel(NULL);
2230 emitcode(_shortJP, LABEL_STR ,lbl->key+100);
2231 emitcode("", LABEL_STR ":",tlbl->key+100);
2232 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2233 emitcode("", LABEL_STR ":",lbl->key+100);
2236 /* mark the icode as generated */
2241 /* if they are both bit variables */
2242 if (AOP_TYPE(left) == AOP_CRY &&
2243 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2246 gencjne(left,right,newiTempLabel(NULL));
2247 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2251 genIfxJump(ifx,"a");
2254 /* if the result is used in an arithmetic operation
2255 then put the result in place */
2256 if (AOP_TYPE(result) != AOP_CRY) {
2259 /* leave the result in acc */
2263 freeAsmop(left,NULL,ic);
2264 freeAsmop(right,NULL,ic);
2265 freeAsmop(result,NULL,ic);
2268 /*-----------------------------------------------------------------*/
2269 /* ifxForOp - returns the icode containing the ifx for operand */
2270 /*-----------------------------------------------------------------*/
2271 static iCode *ifxForOp ( operand *op, iCode *ic )
2273 /* if true symbol then needs to be assigned */
2274 if (IS_TRUE_SYMOP(op))
2277 /* if this has register type condition and
2278 the next instruction is ifx with the same operand
2279 and live to of the operand is upto the ifx only then */
2281 ic->next->op == IFX &&
2282 IC_COND(ic->next)->key == op->key &&
2283 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2289 /*-----------------------------------------------------------------*/
2290 /* genAndOp - for && operation */
2291 /*-----------------------------------------------------------------*/
2292 static void genAndOp (iCode *ic)
2294 operand *left,*right, *result;
2297 /* note here that && operations that are in an if statement are
2298 taken away by backPatchLabels only those used in arthmetic
2299 operations remain */
2300 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2301 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2302 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2304 /* if both are bit variables */
2305 if (AOP_TYPE(left) == AOP_CRY &&
2306 AOP_TYPE(right) == AOP_CRY ) {
2309 tlbl = newiTempLabel(NULL);
2311 emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100);
2313 emitcode("", LABEL_STR ":",tlbl->key+100);
2317 freeAsmop(left,NULL,ic);
2318 freeAsmop(right,NULL,ic);
2319 freeAsmop(result,NULL,ic);
2322 /*-----------------------------------------------------------------*/
2323 /* genOrOp - for || operation */
2324 /*-----------------------------------------------------------------*/
2325 static void genOrOp (iCode *ic)
2327 operand *left,*right, *result;
2330 /* note here that || operations that are in an
2331 if statement are taken away by backPatchLabels
2332 only those used in arthmetic operations remain */
2333 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2334 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2335 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2337 /* if both are bit variables */
2338 if (AOP_TYPE(left) == AOP_CRY &&
2339 AOP_TYPE(right) == AOP_CRY ) {
2342 tlbl = newiTempLabel(NULL);
2344 emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100);
2346 emitcode("", LABEL_STR ":",tlbl->key+100);
2350 freeAsmop(left,NULL,ic);
2351 freeAsmop(right,NULL,ic);
2352 freeAsmop(result,NULL,ic);
2355 /*-----------------------------------------------------------------*/
2356 /* isLiteralBit - test if lit == 2^n */
2357 /*-----------------------------------------------------------------*/
2358 int isLiteralBit(unsigned long lit)
2360 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2361 0x100L,0x200L,0x400L,0x800L,
2362 0x1000L,0x2000L,0x4000L,0x8000L,
2363 0x10000L,0x20000L,0x40000L,0x80000L,
2364 0x100000L,0x200000L,0x400000L,0x800000L,
2365 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2366 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2369 for(idx = 0; idx < 32; idx++)
2375 /*-----------------------------------------------------------------*/
2376 /* jmpTrueOrFalse - */
2377 /*-----------------------------------------------------------------*/
2378 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2380 // ugly but optimized by peephole
2382 symbol *nlbl = newiTempLabel(NULL);
2383 emitcode("jp", LABEL_STR, nlbl->key+100);
2384 emitcode("", LABEL_STR ":",tlbl->key+100);
2385 emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100);
2386 emitcode("", LABEL_STR ":",nlbl->key+100);
2389 emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100);
2390 emitcode("", LABEL_STR ":",tlbl->key+100);
2395 /*-----------------------------------------------------------------*/
2396 /* genAnd - code for and */
2397 /*-----------------------------------------------------------------*/
2398 static void genAnd (iCode *ic, iCode *ifx)
2400 operand *left, *right, *result;
2402 unsigned long lit = 0L;
2405 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2406 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2407 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2410 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2412 AOP_TYPE(left), AOP_TYPE(right));
2413 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2415 AOP_SIZE(left), AOP_SIZE(right));
2418 /* if left is a literal & right is not then exchange them */
2419 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2420 AOP_NEEDSACC(left)) {
2421 operand *tmp = right ;
2426 /* if result = right then exchange them */
2427 if(sameRegs(AOP(result),AOP(right))){
2428 operand *tmp = right ;
2433 /* if right is bit then exchange them */
2434 if (AOP_TYPE(right) == AOP_CRY &&
2435 AOP_TYPE(left) != AOP_CRY){
2436 operand *tmp = right ;
2440 if(AOP_TYPE(right) == AOP_LIT)
2441 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2443 size = AOP_SIZE(result);
2445 if (AOP_TYPE(left) == AOP_CRY){
2450 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2451 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2452 if((AOP_TYPE(right) == AOP_LIT) &&
2453 (AOP_TYPE(result) == AOP_CRY) &&
2454 (AOP_TYPE(left) != AOP_CRY)) {
2455 int posbit = isLiteralBit(lit);
2459 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2463 emitcode("mov","c,acc.%d",posbit&0x07);
2468 sprintf(buffer, "%d", posbit&0x07);
2469 genIfxJump(ifx, buffer);
2477 symbol *tlbl = newiTempLabel(NULL);
2478 int sizel = AOP_SIZE(left);
2481 emitcode("setb","c");
2484 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2485 MOVA( aopGet(AOP(left),offset,FALSE));
2487 if((posbit = isLiteralBit(bytelit)) != 0) {
2489 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2492 if(bytelit != 0x0FFL)
2493 emitcode("and","a,%s",
2494 aopGet(AOP(right),offset,FALSE));
2495 emitcode("jr","nz, %05d$",tlbl->key+100);
2500 // bit = left & literal
2502 emitcode("clr","c");
2503 emitcode("","%05d$:",tlbl->key+100);
2505 // if(left & literal)
2508 jmpTrueOrFalse(ifx, tlbl);
2516 /* if left is same as result */
2517 if(sameRegs(AOP(result),AOP(left))){
2518 for(;size--; offset++) {
2519 if(AOP_TYPE(right) == AOP_LIT){
2520 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2524 aopPut(AOP(result),zero,offset);
2526 MOVA(aopGet(AOP(left),offset,FALSE));
2527 emitcode("and","a,%s",
2528 aopGet(AOP(right),offset,FALSE));
2529 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2534 if (AOP_TYPE(left) == AOP_ACC) {
2538 MOVA(aopGet(AOP(right),offset,FALSE));
2539 emitcode("and","%s,a",
2540 aopGet(AOP(left),offset,FALSE));
2545 // left & result in different registers
2546 if(AOP_TYPE(result) == AOP_CRY){
2549 for(;(size--);offset++) {
2551 // result = left & right
2552 if(AOP_TYPE(right) == AOP_LIT){
2553 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2555 aopGet(AOP(left),offset,FALSE),
2558 } else if(bytelit == 0){
2559 aopPut(AOP(result),zero,offset);
2563 // faster than result <- left, anl result,right
2564 // and better if result is SFR
2565 if (AOP_TYPE(left) == AOP_ACC)
2566 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2568 MOVA(aopGet(AOP(right),offset,FALSE));
2569 emitcode("and","a,%s",
2570 aopGet(AOP(left),offset,FALSE));
2572 aopPut(AOP(result),"a",offset);
2579 freeAsmop(left,NULL,ic);
2580 freeAsmop(right,NULL,ic);
2581 freeAsmop(result,NULL,ic);
2584 /*-----------------------------------------------------------------*/
2585 /* genOr - code for or */
2586 /*-----------------------------------------------------------------*/
2587 static void genOr (iCode *ic, iCode *ifx)
2589 operand *left, *right, *result;
2591 unsigned long lit = 0L;
2593 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2594 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2595 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2598 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2600 AOP_TYPE(left), AOP_TYPE(right));
2601 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2603 AOP_SIZE(left), AOP_SIZE(right));
2606 /* if left is a literal & right is not then exchange them */
2607 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2608 AOP_NEEDSACC(left)) {
2609 operand *tmp = right ;
2614 /* if result = right then exchange them */
2615 if(sameRegs(AOP(result),AOP(right))){
2616 operand *tmp = right ;
2621 /* if right is bit then exchange them */
2622 if (AOP_TYPE(right) == AOP_CRY &&
2623 AOP_TYPE(left) != AOP_CRY){
2624 operand *tmp = right ;
2628 if(AOP_TYPE(right) == AOP_LIT)
2629 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2631 size = AOP_SIZE(result);
2633 if (AOP_TYPE(left) == AOP_CRY){
2638 if((AOP_TYPE(right) == AOP_LIT) &&
2639 (AOP_TYPE(result) == AOP_CRY) &&
2640 (AOP_TYPE(left) != AOP_CRY)){
2645 /* if left is same as result */
2646 if(sameRegs(AOP(result),AOP(left))){
2647 for(;size--; offset++) {
2648 if(AOP_TYPE(right) == AOP_LIT){
2649 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2652 emitcode("or","%s,%s; 5",
2653 aopGet(AOP(left),offset,FALSE),
2654 aopGet(AOP(right),offset,FALSE));
2656 if (AOP_TYPE(left) == AOP_ACC)
2657 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2659 MOVA(aopGet(AOP(right),offset,FALSE));
2660 emitcode("or","a,%s ; 7",
2661 aopGet(AOP(left),offset,FALSE));
2662 aopPut(AOP(result),"a ; 8", offset);
2667 // left & result in different registers
2668 if(AOP_TYPE(result) == AOP_CRY){
2670 } else for(;(size--);offset++){
2672 // result = left & right
2673 if(AOP_TYPE(right) == AOP_LIT){
2674 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2676 aopGet(AOP(left),offset,FALSE),
2681 // faster than result <- left, anl result,right
2682 // and better if result is SFR
2683 if (AOP_TYPE(left) == AOP_ACC)
2684 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2686 MOVA(aopGet(AOP(right),offset,FALSE));
2687 emitcode("or","a,%s",
2688 aopGet(AOP(left),offset,FALSE));
2690 aopPut(AOP(result),"a",offset);
2691 /* PENDING: something weird is going on here. Add exception. */
2692 if (AOP_TYPE(result) == AOP_ACC)
2698 freeAsmop(left,NULL,ic);
2699 freeAsmop(right,NULL,ic);
2700 freeAsmop(result,NULL,ic);
2703 /*-----------------------------------------------------------------*/
2704 /* genXor - code for xclusive or */
2705 /*-----------------------------------------------------------------*/
2706 static void genXor (iCode *ic, iCode *ifx)
2708 operand *left, *right, *result;
2710 unsigned long lit = 0L;
2712 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2713 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2714 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2716 /* if left is a literal & right is not then exchange them */
2717 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2718 AOP_NEEDSACC(left)) {
2719 operand *tmp = right ;
2724 /* if result = right then exchange them */
2725 if(sameRegs(AOP(result),AOP(right))){
2726 operand *tmp = right ;
2731 /* if right is bit then exchange them */
2732 if (AOP_TYPE(right) == AOP_CRY &&
2733 AOP_TYPE(left) != AOP_CRY){
2734 operand *tmp = right ;
2738 if(AOP_TYPE(right) == AOP_LIT)
2739 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2741 size = AOP_SIZE(result);
2743 if (AOP_TYPE(left) == AOP_CRY){
2748 if((AOP_TYPE(right) == AOP_LIT) &&
2749 (AOP_TYPE(result) == AOP_CRY) &&
2750 (AOP_TYPE(left) != AOP_CRY)){
2755 /* if left is same as result */
2756 if(sameRegs(AOP(result),AOP(left))){
2757 for(;size--; offset++) {
2758 if(AOP_TYPE(right) == AOP_LIT){
2759 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2762 MOVA(aopGet(AOP(right),offset,FALSE));
2763 emitcode("xor","a,%s",
2764 aopGet(AOP(left),offset,FALSE));
2765 aopPut(AOP(result),"a",0);
2768 if (AOP_TYPE(left) == AOP_ACC)
2769 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2771 MOVA(aopGet(AOP(right),offset,FALSE));
2772 emitcode("xor","a,%s",
2773 aopGet(AOP(left),offset,FALSE));
2774 aopPut(AOP(result),"a",0);
2779 // left & result in different registers
2780 if(AOP_TYPE(result) == AOP_CRY){
2782 } else for(;(size--);offset++){
2784 // result = left & right
2785 if(AOP_TYPE(right) == AOP_LIT){
2786 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2788 aopGet(AOP(left),offset,FALSE),
2793 // faster than result <- left, anl result,right
2794 // and better if result is SFR
2795 if (AOP_TYPE(left) == AOP_ACC)
2796 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2798 MOVA(aopGet(AOP(right),offset,FALSE));
2799 emitcode("xor","a,%s",
2800 aopGet(AOP(left),offset,FALSE));
2801 aopPut(AOP(result),"a",0);
2803 aopPut(AOP(result),"a",offset);
2808 freeAsmop(left,NULL,ic);
2809 freeAsmop(right,NULL,ic);
2810 freeAsmop(result,NULL,ic);
2813 /*-----------------------------------------------------------------*/
2814 /* genInline - write the inline code out */
2815 /*-----------------------------------------------------------------*/
2816 static void genInline (iCode *ic)
2818 char buffer[MAX_INLINEASM];
2822 inLine += (!options.asmpeep);
2823 strcpy(buffer,IC_INLINE(ic));
2825 /* emit each line as a code */
2844 /* emitcode("",buffer); */
2845 inLine -= (!options.asmpeep);
2848 /*-----------------------------------------------------------------*/
2849 /* genRRC - rotate right with carry */
2850 /*-----------------------------------------------------------------*/
2851 static void genRRC (iCode *ic)
2856 /*-----------------------------------------------------------------*/
2857 /* genRLC - generate code for rotate left with carry */
2858 /*-----------------------------------------------------------------*/
2859 static void genRLC (iCode *ic)
2864 /*-----------------------------------------------------------------*/
2865 /* shiftR2Left2Result - shift right two bytes from left to result */
2866 /*-----------------------------------------------------------------*/
2867 static void shiftR2Left2Result (operand *left, int offl,
2868 operand *result, int offr,
2869 int shCount, int sign)
2871 if(sameRegs(AOP(result), AOP(left)) &&
2872 ((offl + MSB16) == offr)){
2875 movLeft2Result(left, offl, result, offr, 0);
2876 movLeft2Result(left, offl+1, result, offr+1, 0);
2883 /* if (AOP(result)->type == AOP_REG) {*/
2886 symbol *tlbl , *tlbl1;
2889 /* Left is already in result - so now do the shift */
2891 emitcode("ld","a,#%u+1", shCount);
2892 tlbl = newiTempLabel(NULL);
2893 tlbl1 = newiTempLabel(NULL);
2894 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
2895 emitcode("", LABEL_STR ":",tlbl->key+100);
2898 emitcode("or", "a,a");
2901 l = aopGet(AOP(result), --offset, FALSE);
2902 emitcode("rr","%s", l);
2905 emitcode("", LABEL_STR ":",tlbl1->key+100);
2906 emitcode("dec", "a");
2907 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
2912 /*-----------------------------------------------------------------*/
2913 /* shiftL2Left2Result - shift left two bytes from left to result */
2914 /*-----------------------------------------------------------------*/
2915 static void shiftL2Left2Result (operand *left, int offl,
2916 operand *result, int offr, int shCount)
2918 if(sameRegs(AOP(result), AOP(left)) &&
2919 ((offl + MSB16) == offr)){
2922 /* Copy left into result */
2923 movLeft2Result(left, offl, result, offr, 0);
2924 movLeft2Result(left, offl+1, result, offr+1, 0);
2926 /* PENDING: for now just see if it'll work. */
2927 /*if (AOP(result)->type == AOP_REG) { */
2931 symbol *tlbl , *tlbl1;
2934 /* Left is already in result - so now do the shift */
2936 emitcode("ld","a,#%u+1", shCount);
2937 tlbl = newiTempLabel(NULL);
2938 tlbl1 = newiTempLabel(NULL);
2939 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
2940 emitcode("", LABEL_STR ":",tlbl->key+100);
2943 emitcode("or", "a,a");
2945 l = aopGet(AOP(result),offset++,FALSE);
2946 emitcode("rl","%s", l);
2949 emitcode("", LABEL_STR ":",tlbl1->key+100);
2950 emitcode("dec", "a");
2951 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
2956 /*-----------------------------------------------------------------*/
2957 /* AccRol - rotate left accumulator by known count */
2958 /*-----------------------------------------------------------------*/
2959 static void AccRol (int shCount)
2961 shCount &= 0x0007; // shCount : 0..7
2998 /*-----------------------------------------------------------------*/
2999 /* AccLsh - left shift accumulator by known count */
3000 /*-----------------------------------------------------------------*/
3001 static void AccLsh (int shCount)
3005 emitcode("add","a,a");
3008 emitcode("add","a,a");
3009 emitcode("add","a,a");
3011 /* rotate left accumulator */
3013 /* and kill the lower order bits */
3014 emitcode("and","a,#0x%02x", SLMask[shCount]);
3019 /*-----------------------------------------------------------------*/
3020 /* shiftL1Left2Result - shift left one byte from left to result */
3021 /*-----------------------------------------------------------------*/
3022 static void shiftL1Left2Result (operand *left, int offl,
3023 operand *result, int offr, int shCount)
3026 l = aopGet(AOP(left),offl,FALSE);
3028 /* shift left accumulator */
3030 aopPut(AOP(result),"a",offr);
3034 /*-----------------------------------------------------------------*/
3035 /* genlshTwo - left shift two bytes by known amount != 0 */
3036 /*-----------------------------------------------------------------*/
3037 static void genlshTwo (operand *result,operand *left, int shCount)
3039 int size = AOP_SIZE(result);
3043 /* if shCount >= 8 */
3049 movLeft2Result(left, LSB, result, MSB16, 0);
3050 aopPut(AOP(result),zero, 0);
3051 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
3054 movLeft2Result(left, LSB, result, MSB16, 0);
3055 aopPut(AOP(result),zero, 0);
3058 aopPut(AOP(result),zero,LSB);
3060 /* 1 <= shCount <= 7 */
3066 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3071 /*-----------------------------------------------------------------*/
3072 /* genlshOne - left shift a one byte quantity by known count */
3073 /*-----------------------------------------------------------------*/
3074 static void genlshOne (operand *result, operand *left, int shCount)
3076 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3079 /*-----------------------------------------------------------------*/
3080 /* genLeftShiftLiteral - left shifting by known count */
3081 /*-----------------------------------------------------------------*/
3082 static void genLeftShiftLiteral (operand *left,
3087 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3090 freeAsmop(right,NULL,ic);
3092 aopOp(left,ic,FALSE);
3093 aopOp(result,ic,FALSE);
3095 size = getSize(operandType(result));
3098 emitcode("; shift left ","result %d, left %d",size,
3102 /* I suppose that the left size >= result size */
3107 else if(shCount >= (size * 8))
3109 aopPut(AOP(result),zero,size);
3113 genlshOne (result,left,shCount);
3116 genlshTwo (result,left,shCount);
3125 freeAsmop(left,NULL,ic);
3126 freeAsmop(result,NULL,ic);
3129 /*-----------------------------------------------------------------*/
3130 /* genLeftShift - generates code for left shifting */
3131 /*-----------------------------------------------------------------*/
3132 static void genLeftShift (iCode *ic)
3136 symbol *tlbl , *tlbl1;
3137 operand *left,*right, *result;
3139 right = IC_RIGHT(ic);
3141 result = IC_RESULT(ic);
3143 aopOp(right,ic,FALSE);
3145 /* if the shift count is known then do it
3146 as efficiently as possible */
3147 if (AOP_TYPE(right) == AOP_LIT) {
3148 genLeftShiftLiteral (left,right,result,ic);
3152 /* shift count is unknown then we have to form a loop get the loop
3153 count in B : Note: we take only the lower order byte since
3154 shifting more that 32 bits make no sense anyway, ( the largest
3155 size of an object can be only 32 bits ) */
3156 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3157 emitcode("inc","a");
3158 freeAsmop (right,NULL,ic);
3159 aopOp(left,ic,FALSE);
3160 aopOp(result,ic,FALSE);
3162 /* now move the left to the result if they are not the
3165 if (!sameRegs(AOP(left),AOP(result))) {
3167 size = AOP_SIZE(result);
3170 l = aopGet(AOP(left),offset,FALSE);
3171 aopPut(AOP(result),l,offset);
3176 size = AOP_SIZE(result);
3179 l = aopGet(AOP(left),offset,FALSE);
3180 aopPut(AOP(result),l,offset);
3186 tlbl = newiTempLabel(NULL);
3187 size = AOP_SIZE(result);
3189 tlbl1 = newiTempLabel(NULL);
3191 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3192 emitcode("", LABEL_STR ":",tlbl->key+100);
3193 l = aopGet(AOP(result),offset,FALSE);
3194 emitcode("or", "a,a");
3196 l = aopGet(AOP(result),offset++,FALSE);
3197 emitcode("rl","%s", l);
3199 emitcode("", LABEL_STR ":",tlbl1->key+100);
3200 emitcode("dec", "a");
3201 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3203 freeAsmop(left,NULL,ic);
3204 freeAsmop(result,NULL,ic);
3207 /* genlshTwo - left shift two bytes by known amount != 0 */
3208 /*-----------------------------------------------------------------*/
3209 static void genrshOne (operand *result,operand *left, int shCount)
3212 int size = AOP_SIZE(result);
3218 l = aopGet(AOP(left),0,FALSE);
3219 if (AOP(result)->type == AOP_REG) {
3220 aopPut(AOP(result), l, 0);
3221 l = aopGet(AOP(result), 0, FALSE);
3223 emitcode("srl", "%s", l);
3228 emitcode("srl", "a");
3230 aopPut(AOP(result),"a",0);
3234 /*-----------------------------------------------------------------*/
3235 /* AccRsh - right shift accumulator by known count */
3236 /*-----------------------------------------------------------------*/
3237 static void AccRsh (int shCount)
3244 /* rotate right accumulator */
3245 AccRol(8 - shCount);
3246 /* and kill the higher order bits */
3247 emitcode("and","a,#0x%02x", SRMask[shCount]);
3252 /*-----------------------------------------------------------------*/
3253 /* shiftR1Left2Result - shift right one byte from left to result */
3254 /*-----------------------------------------------------------------*/
3255 static void shiftR1Left2Result (operand *left, int offl,
3256 operand *result, int offr,
3257 int shCount, int sign)
3259 MOVA(aopGet(AOP(left),offl,FALSE));
3266 aopPut(AOP(result),"a",offr);
3269 /*-----------------------------------------------------------------*/
3270 /* genrshTwo - right shift two bytes by known amount != 0 */
3271 /*-----------------------------------------------------------------*/
3272 static void genrshTwo (operand *result,operand *left,
3273 int shCount, int sign)
3275 /* if shCount >= 8 */
3280 shiftR1Left2Result(left, MSB16, result, LSB,
3284 movLeft2Result(left, MSB16, result, LSB, sign);
3285 aopPut(AOP(result),zero,1);
3288 /* 1 <= shCount <= 7 */
3290 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3294 /*-----------------------------------------------------------------*/
3295 /* genRightShiftLiteral - left shifting by known count */
3296 /*-----------------------------------------------------------------*/
3297 static void genRightShiftLiteral (operand *left,
3302 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3305 freeAsmop(right,NULL,ic);
3307 aopOp(left,ic,FALSE);
3308 aopOp(result,ic,FALSE);
3310 size = getSize(operandType(result));
3312 emitcode("; shift right ","result %d, left %d",size,
3315 /* I suppose that the left size >= result size */
3320 else if(shCount >= (size * 8))
3322 aopPut(AOP(result),zero,size);
3326 genrshOne(result, left, shCount);
3329 /* PENDING: sign support */
3330 genrshTwo(result, left, shCount, FALSE);
3339 freeAsmop(left,NULL,ic);
3340 freeAsmop(result,NULL,ic);
3343 /*-----------------------------------------------------------------*/
3344 /* genRightShift - generate code for right shifting */
3345 /*-----------------------------------------------------------------*/
3346 static void genRightShift (iCode *ic)
3348 operand *left,*right, *result;
3350 right = IC_RIGHT(ic);
3352 result = IC_RESULT(ic);
3354 aopOp(right,ic,FALSE);
3356 /* if the shift count is known then do it
3357 as efficiently as possible */
3358 if (AOP_TYPE(right) == AOP_LIT) {
3359 genRightShiftLiteral (left,right,result,ic);
3367 /*-----------------------------------------------------------------*/
3368 /* genGenPointerGet - gget value from generic pointer space */
3369 /*-----------------------------------------------------------------*/
3370 static void genGenPointerGet (operand *left,
3371 operand *result, iCode *ic)
3374 link *retype = getSpec(operandType(result));
3375 const char *ptr = "hl";
3380 aopOp(left,ic,FALSE);
3381 aopOp(result,ic,FALSE);
3383 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3385 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3386 aopPut(AOP(result),"a", 0);
3387 freeAsmop(left,NULL,ic);
3391 /* For now we always load into IY */
3392 /* if this is remateriazable */
3393 if (AOP_TYPE(left) == AOP_IMMD)
3394 emitcode("ld","%s,%s", ptr, aopGet(AOP(left),0,TRUE));
3395 else { /* we need to get it byte by byte */
3397 emitcode("ld", "e,%s", aopGet(AOP(left), 0, FALSE));
3398 emitcode("ld", "d,%s", aopGet(AOP(left), 1, FALSE));
3403 /* so iy now contains the address */
3404 freeAsmop(left,NULL,ic);
3406 /* if bit then unpack */
3407 if (IS_BITVAR(retype)) {
3411 size = AOP_SIZE(result);
3415 /* PENDING: make this better */
3416 if (!IS_GB && AOP(result)->type == AOP_REG) {
3417 aopPut(AOP(result),"(hl)",offset++);
3420 emitcode("ld", "a,(%s)", ptr, offset);
3421 aopPut(AOP(result),"a",offset++);
3424 emitcode("inc", "%s", ptr);
3430 freeAsmop(result,NULL,ic);
3433 /*-----------------------------------------------------------------*/
3434 /* genPointerGet - generate code for pointer get */
3435 /*-----------------------------------------------------------------*/
3436 static void genPointerGet (iCode *ic)
3438 operand *left, *result ;
3442 result = IC_RESULT(ic) ;
3444 /* depending on the type of pointer we need to
3445 move it to the correct pointer register */
3446 type = operandType(left);
3447 etype = getSpec(type);
3449 genGenPointerGet (left,result,ic);
3452 bool isRegOrLit(asmop *aop)
3454 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3459 /*-----------------------------------------------------------------*/
3460 /* genGenPointerSet - stores the value into a pointer location */
3461 /*-----------------------------------------------------------------*/
3462 static void genGenPointerSet (operand *right,
3463 operand *result, iCode *ic)
3466 link *retype = getSpec(operandType(right));
3467 const char *ptr = "hl";
3469 aopOp(result,ic,FALSE);
3470 aopOp(right,ic,FALSE);
3475 /* Handle the exceptions first */
3476 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3478 char *l = aopGet(AOP(right), 0, FALSE);
3480 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3481 freeAsmop(result,NULL,ic);
3485 /* if the operand is already in dptr
3486 then we do nothing else we move the value to dptr */
3487 if (AOP_TYPE(result) != AOP_STR) {
3488 /* if this is remateriazable */
3489 if (AOP_TYPE(result) == AOP_IMMD) {
3490 emitcode("", "; Error 2");
3491 emitcode("ld", "%s,%s", ptr, aopGet(AOP(result), 0, TRUE));
3493 else { /* we need to get it byte by byte */
3495 emitcode("ld", "e,%s", aopGet(AOP(result), 0, TRUE));
3496 emitcode("ld", "d,%s", aopGet(AOP(result), 1, TRUE));
3499 /* PENDING: do this better */
3500 fetchHL(AOP(result));
3504 /* so hl know contains the address */
3505 freeAsmop(result,NULL,ic);
3507 /* if bit then unpack */
3508 if (IS_BITVAR(retype)) {
3512 size = AOP_SIZE(right);
3516 char *l = aopGet(AOP(right),offset,FALSE);
3517 if (isRegOrLit(AOP(right)) && !IS_GB) {
3518 emitcode("ld", "(%s),%s", ptr, l);
3522 emitcode("ld", "(%s),a", ptr, offset);
3525 emitcode("inc", ptr);
3531 freeAsmop(right,NULL,ic);
3534 /*-----------------------------------------------------------------*/
3535 /* genPointerSet - stores the value into a pointer location */
3536 /*-----------------------------------------------------------------*/
3537 static void genPointerSet (iCode *ic)
3539 operand *right, *result ;
3542 right = IC_RIGHT(ic);
3543 result = IC_RESULT(ic) ;
3545 /* depending on the type of pointer we need to
3546 move it to the correct pointer register */
3547 type = operandType(result);
3548 etype = getSpec(type);
3550 genGenPointerSet (right,result,ic);
3553 /*-----------------------------------------------------------------*/
3554 /* genIfx - generate code for Ifx statement */
3555 /*-----------------------------------------------------------------*/
3556 static void genIfx (iCode *ic, iCode *popIc)
3558 operand *cond = IC_COND(ic);
3561 aopOp(cond,ic,FALSE);
3563 /* get the value into acc */
3564 if (AOP_TYPE(cond) != AOP_CRY)
3568 /* the result is now in the accumulator */
3569 freeAsmop(cond,NULL,ic);
3571 /* if there was something to be popped then do it */
3575 /* if the condition is a bit variable */
3576 if (isbit && IS_ITEMP(cond) &&
3578 genIfxJump(ic,SPIL_LOC(cond)->rname);
3580 if (isbit && !IS_ITEMP(cond))
3581 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3588 /*-----------------------------------------------------------------*/
3589 /* genAddrOf - generates code for address of */
3590 /*-----------------------------------------------------------------*/
3591 static void genAddrOf (iCode *ic)
3593 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3595 aopOp(IC_RESULT(ic),ic,FALSE);
3597 /* if the operand is on the stack then we
3598 need to get the stack offset of this
3601 /* if it has an offset then we need to compute it */
3603 emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _pushed, _spoffset);
3604 emitcode("ld", "d,h");
3605 emitcode("ld", "e,l");
3606 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3607 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3611 emitcode("push", "de");
3612 emitcode("push", "ix");
3613 emitcode("pop", "hl");
3614 emitcode("ld", "de,#%d", sym->stack);
3615 emitcode("add", "hl,de");
3616 emitcode("pop", "de");
3620 emitcode("ld", "hl,#%s", sym->rname);
3622 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3623 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3625 freeAsmop(IC_RESULT(ic),NULL,ic);
3628 /*-----------------------------------------------------------------*/
3629 /* genAssign - generate code for assignment */
3630 /*-----------------------------------------------------------------*/
3631 static void genAssign (iCode *ic)
3633 operand *result, *right;
3635 unsigned long lit = 0L;
3637 result = IC_RESULT(ic);
3638 right = IC_RIGHT(ic) ;
3641 /* Dont bother assigning if they are the same */
3642 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3643 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3648 aopOp(right,ic,FALSE);
3649 aopOp(result,ic,TRUE);
3651 /* if they are the same registers */
3652 if (sameRegs(AOP(right),AOP(result))) {
3653 emitcode("", "; (registers are the same)");
3657 /* if the result is a bit */
3658 if (AOP_TYPE(result) == AOP_CRY) {
3663 size = AOP_SIZE(result);
3666 if(AOP_TYPE(right) == AOP_LIT)
3667 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3669 (AOP_TYPE(result) != AOP_REG) &&
3670 (AOP_TYPE(right) == AOP_LIT) &&
3671 !IS_FLOAT(operandType(right)) &&
3673 bool fXored = FALSE;
3675 /* Work from the top down.
3676 Done this way so that we can use the cached copy of 0
3677 in A for a fast clear */
3679 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3680 if (!fXored && size>1) {
3681 emitcode("xor", "a,a");
3685 aopPut(AOP(result),"a",offset);
3688 aopPut(AOP(result), "#0", offset);
3693 aopGet(AOP(right),offset,FALSE),
3698 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
3699 /* Special case. Load into a and d, then load out. */
3700 MOVA(aopGet(AOP(right), 0, FALSE));
3701 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
3702 aopPut(AOP(result), "a", 0);
3703 aopPut(AOP(result), "e", 1);
3707 aopGet(AOP(right),offset,FALSE),
3714 freeAsmop(right,NULL,ic);
3715 freeAsmop(result,NULL,ic);
3718 /*-----------------------------------------------------------------*/
3719 /* genJumpTab - genrates code for jump table */
3720 /*-----------------------------------------------------------------*/
3721 static void genJumpTab (iCode *ic)
3726 aopOp(IC_JTCOND(ic),ic,FALSE);
3727 /* get the condition into accumulator */
3728 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3731 emitcode("push", "de");
3732 emitcode("ld", "e,%s", l);
3733 emitcode("ld", "d,#0");
3734 jtab = newiTempLabel(NULL);
3735 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3736 emitcode("add", "hl,de");
3737 emitcode("add", "hl,de");
3738 emitcode("add", "hl,de");
3739 freeAsmop(IC_JTCOND(ic),NULL,ic);
3741 emitcode("pop", "de");
3742 emitcode("jp", "(hl)");
3743 emitcode("","%05d$:",jtab->key+100);
3744 /* now generate the jump labels */
3745 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3746 jtab = setNextItem(IC_JTLABELS(ic)))
3747 emitcode("jp", LABEL_STR, jtab->key+100);
3750 /*-----------------------------------------------------------------*/
3751 /* genCast - gen code for casting */
3752 /*-----------------------------------------------------------------*/
3753 static void genCast (iCode *ic)
3755 operand *result = IC_RESULT(ic);
3756 link *ctype = operandType(IC_LEFT(ic));
3757 operand *right = IC_RIGHT(ic);
3760 /* if they are equivalent then do nothing */
3761 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3764 aopOp(right,ic,FALSE) ;
3765 aopOp(result,ic,FALSE);
3767 /* if the result is a bit */
3768 if (AOP_TYPE(result) == AOP_CRY) {
3772 /* if they are the same size : or less */
3773 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3775 /* if they are in the same place */
3776 if (sameRegs(AOP(right),AOP(result)))
3779 /* if they in different places then copy */
3780 size = AOP_SIZE(result);
3784 aopGet(AOP(right),offset,FALSE),
3791 /* PENDING: should be OK. */
3793 /* if the result is of type pointer */
3794 if (IS_PTR(ctype)) {
3799 /* so we now know that the size of destination is greater
3800 than the size of the source */
3801 /* we move to result for the size of source */
3802 size = AOP_SIZE(right);
3806 aopGet(AOP(right),offset,FALSE),
3811 /* now depending on the sign of the destination */
3812 size = AOP_SIZE(result) - AOP_SIZE(right);
3813 /* Unsigned or not an integral type - right fill with zeros */
3814 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3816 aopPut(AOP(result),zero,offset++);
3818 /* we need to extend the sign :{ */
3819 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3822 emitcode("", "; genCast: sign extend untested.");
3823 emitcode("rla", "");
3824 emitcode("sbc", "a,a");
3826 aopPut(AOP(result),"a",offset++);
3830 freeAsmop(right, NULL, ic);
3831 freeAsmop(result, NULL, ic);
3834 /*-----------------------------------------------------------------*/
3835 /* genReceive - generate code for a receive iCode */
3836 /*-----------------------------------------------------------------*/
3837 static void genReceive (iCode *ic)
3839 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3840 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3841 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3845 aopOp(IC_RESULT(ic),ic,FALSE);
3847 assignResultValue(IC_RESULT(ic));
3850 freeAsmop(IC_RESULT(ic),NULL,ic);
3853 /*-----------------------------------------------------------------*/
3854 /* genZ80Code - generate code for Z80 based controllers */
3855 /*-----------------------------------------------------------------*/
3856 void genZ80Code (iCode *lic)
3863 _fReturn = _gbz80_return;
3864 _fTmp = _gbz80_return;
3868 _fReturn = _z80_return;
3869 _fTmp = _z80_return;
3873 lineHead = lineCurr = NULL;
3875 /* if debug information required */
3876 if (options.debug && currFunc) {
3877 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3879 if (IS_STATIC(currFunc->etype))
3880 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3882 emitcode("","G$%s$0$0 ==.",currFunc->name);
3885 /* stack pointer name */
3889 for (ic = lic ; ic ; ic = ic->next ) {
3891 if ( cln != ic->lineno ) {
3892 if ( options.debug ) {
3894 emitcode("","C$%s$%d$%d$%d ==.",
3895 ic->filename,ic->lineno,
3896 ic->level,ic->block);
3899 emitcode(";","%s %d",ic->filename,ic->lineno);
3902 /* if the result is marked as
3903 spilt and rematerializable or code for
3904 this has already been generated then
3906 if (resultRemat(ic) || ic->generated )
3909 /* depending on the operation */
3912 emitcode("", "; genNot");
3917 emitcode("", "; genCpl");
3922 emitcode("", "; genUminus");
3927 emitcode("", "; genIpush");
3932 /* IPOP happens only when trying to restore a
3933 spilt live range, if there is an ifx statement
3934 following this pop then the if statement might
3935 be using some of the registers being popped which
3936 would destory the contents of the register so
3937 we need to check for this condition and handle it */
3939 ic->next->op == IFX &&
3940 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3941 emitcode("", "; genIfx");
3942 genIfx (ic->next,ic);
3945 emitcode("", "; genIpop");
3951 emitcode("", "; genCall");
3956 emitcode("", "; genPcall");
3961 emitcode("", "; genFunction");
3966 emitcode("", "; genEndFunction");
3967 genEndFunction (ic);
3971 emitcode("", "; genRet");
3976 emitcode("", "; genLabel");
3981 emitcode("", "; genGoto");
3986 emitcode("", "; genPlus");
3991 emitcode("", "; genMinus");
3996 emitcode("", "; genMult");
4001 emitcode("", "; genDiv");
4006 emitcode("", "; genMod");
4011 emitcode("", "; genCmpGt");
4012 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4016 emitcode("", "; genCmpLt");
4017 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4024 /* note these two are xlated by algebraic equivalence
4025 during parsing SDCC.y */
4026 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4027 "got '>=' or '<=' shouldn't have come here");
4031 emitcode("", "; genCmpEq");
4032 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4036 emitcode("", "; genAndOp");
4041 emitcode("", "; genOrOp");
4046 emitcode("", "; genXor");
4047 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4051 emitcode("", "; genOr");
4052 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4056 emitcode("", "; genAnd");
4057 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4061 emitcode("", "; genInline");
4066 emitcode("", "; genRRC");
4071 emitcode("", "; genRLC");
4076 emitcode("", "; genHBIT");
4080 emitcode("", "; genLeftShift");
4085 emitcode("", "; genRightShift");
4089 case GET_VALUE_AT_ADDRESS:
4090 emitcode("", "; genPointerGet");
4096 if (POINTER_SET(ic)) {
4097 emitcode("", "; genAssign (pointer)");
4101 emitcode("", "; genAssign");
4107 emitcode("", "; genIfx");
4112 emitcode("", "; genAddrOf");
4117 emitcode("", "; genJumpTab");
4122 emitcode("", "; genCast");
4127 emitcode("", "; genReceive");
4132 emitcode("", "; addSet");
4133 addSet(&sendSet,ic);
4138 /* piCode(ic,stdout); */
4144 /* now we are ready to call the
4145 peep hole optimizer */
4146 if (!options.nopeep)
4147 peepHole (&lineHead);
4149 /* now do the actual printing */
4150 printLine (lineHead,codeOutFile);