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 /* genAnd - code for and */
2377 /*-----------------------------------------------------------------*/
2378 static void genAnd (iCode *ic, iCode *ifx)
2380 operand *left, *right, *result;
2382 unsigned long lit = 0L;
2385 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2386 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2387 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2390 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2392 AOP_TYPE(left), AOP_TYPE(right));
2393 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2395 AOP_SIZE(left), AOP_SIZE(right));
2398 /* if left is a literal & right is not then exchange them */
2399 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2400 AOP_NEEDSACC(left)) {
2401 operand *tmp = right ;
2406 /* if result = right then exchange them */
2407 if(sameRegs(AOP(result),AOP(right))){
2408 operand *tmp = right ;
2413 /* if right is bit then exchange them */
2414 if (AOP_TYPE(right) == AOP_CRY &&
2415 AOP_TYPE(left) != AOP_CRY){
2416 operand *tmp = right ;
2420 if(AOP_TYPE(right) == AOP_LIT)
2421 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2423 size = AOP_SIZE(result);
2425 if (AOP_TYPE(left) == AOP_CRY){
2430 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2431 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2432 if((AOP_TYPE(right) == AOP_LIT) &&
2433 (AOP_TYPE(result) == AOP_CRY) &&
2434 (AOP_TYPE(left) != AOP_CRY)) {
2435 int posbit = isLiteralBit(lit);
2439 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2443 emitcode("mov","c,acc.%d",posbit&0x07);
2448 sprintf(buffer, "%d", posbit&0x07);
2449 genIfxJump(ifx, buffer);
2457 symbol *tlbl = newiTempLabel(NULL);
2458 int sizel = AOP_SIZE(left);
2461 emitcode("setb","c");
2464 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2465 MOVA( aopGet(AOP(left),offset,FALSE));
2467 if((posbit = isLiteralBit(bytelit)) != 0) {
2469 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2472 if(bytelit != 0x0FFL)
2473 emitcode("and","a,%s",
2474 aopGet(AOP(right),offset,FALSE));
2475 emitcode("jr","nz, %05d$",tlbl->key+100);
2480 // bit = left & literal
2482 emitcode("clr","c");
2483 emitcode("","%05d$:",tlbl->key+100);
2485 // if(left & literal)
2489 jmpTrueOrFalse(ifx, tlbl);
2500 /* if left is same as result */
2501 if(sameRegs(AOP(result),AOP(left))){
2502 for(;size--; offset++) {
2503 if(AOP_TYPE(right) == AOP_LIT){
2504 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2508 aopPut(AOP(result),zero,offset);
2510 MOVA(aopGet(AOP(left),offset,FALSE));
2511 emitcode("and","a,%s",
2512 aopGet(AOP(right),offset,FALSE));
2513 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2518 if (AOP_TYPE(left) == AOP_ACC) {
2522 MOVA(aopGet(AOP(right),offset,FALSE));
2523 emitcode("and","%s,a",
2524 aopGet(AOP(left),offset,FALSE));
2529 // left & result in different registers
2530 if(AOP_TYPE(result) == AOP_CRY){
2533 for(;(size--);offset++) {
2535 // result = left & right
2536 if(AOP_TYPE(right) == AOP_LIT){
2537 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2539 aopGet(AOP(left),offset,FALSE),
2542 } else if(bytelit == 0){
2543 aopPut(AOP(result),zero,offset);
2547 // faster than result <- left, anl result,right
2548 // and better if result is SFR
2549 if (AOP_TYPE(left) == AOP_ACC)
2550 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2552 MOVA(aopGet(AOP(right),offset,FALSE));
2553 emitcode("and","a,%s",
2554 aopGet(AOP(left),offset,FALSE));
2556 aopPut(AOP(result),"a",offset);
2563 freeAsmop(left,NULL,ic);
2564 freeAsmop(right,NULL,ic);
2565 freeAsmop(result,NULL,ic);
2568 /*-----------------------------------------------------------------*/
2569 /* genOr - code for or */
2570 /*-----------------------------------------------------------------*/
2571 static void genOr (iCode *ic, iCode *ifx)
2573 operand *left, *right, *result;
2575 unsigned long lit = 0L;
2577 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2578 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2579 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2582 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2584 AOP_TYPE(left), AOP_TYPE(right));
2585 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2587 AOP_SIZE(left), AOP_SIZE(right));
2590 /* if left is a literal & right is not then exchange them */
2591 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2592 AOP_NEEDSACC(left)) {
2593 operand *tmp = right ;
2598 /* if result = right then exchange them */
2599 if(sameRegs(AOP(result),AOP(right))){
2600 operand *tmp = right ;
2605 /* if right is bit then exchange them */
2606 if (AOP_TYPE(right) == AOP_CRY &&
2607 AOP_TYPE(left) != AOP_CRY){
2608 operand *tmp = right ;
2612 if(AOP_TYPE(right) == AOP_LIT)
2613 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2615 size = AOP_SIZE(result);
2617 if (AOP_TYPE(left) == AOP_CRY){
2622 if((AOP_TYPE(right) == AOP_LIT) &&
2623 (AOP_TYPE(result) == AOP_CRY) &&
2624 (AOP_TYPE(left) != AOP_CRY)){
2629 /* if left is same as result */
2630 if(sameRegs(AOP(result),AOP(left))){
2631 for(;size--; offset++) {
2632 if(AOP_TYPE(right) == AOP_LIT){
2633 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2636 emitcode("or","%s,%s; 5",
2637 aopGet(AOP(left),offset,FALSE),
2638 aopGet(AOP(right),offset,FALSE));
2640 if (AOP_TYPE(left) == AOP_ACC)
2641 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2643 MOVA(aopGet(AOP(right),offset,FALSE));
2644 emitcode("or","a,%s ; 7",
2645 aopGet(AOP(left),offset,FALSE));
2646 aopPut(AOP(result),"a ; 8", offset);
2651 // left & result in different registers
2652 if(AOP_TYPE(result) == AOP_CRY){
2654 } else for(;(size--);offset++){
2656 // result = left & right
2657 if(AOP_TYPE(right) == AOP_LIT){
2658 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2660 aopGet(AOP(left),offset,FALSE),
2665 // faster than result <- left, anl result,right
2666 // and better if result is SFR
2667 if (AOP_TYPE(left) == AOP_ACC)
2668 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2670 MOVA(aopGet(AOP(right),offset,FALSE));
2671 emitcode("or","a,%s",
2672 aopGet(AOP(left),offset,FALSE));
2674 aopPut(AOP(result),"a",offset);
2675 /* PENDING: something weird is going on here. Add exception. */
2676 if (AOP_TYPE(result) == AOP_ACC)
2682 freeAsmop(left,NULL,ic);
2683 freeAsmop(right,NULL,ic);
2684 freeAsmop(result,NULL,ic);
2687 /*-----------------------------------------------------------------*/
2688 /* genXor - code for xclusive or */
2689 /*-----------------------------------------------------------------*/
2690 static void genXor (iCode *ic, iCode *ifx)
2692 operand *left, *right, *result;
2694 unsigned long lit = 0L;
2696 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2697 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2698 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2700 /* if left is a literal & right is not then exchange them */
2701 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2702 AOP_NEEDSACC(left)) {
2703 operand *tmp = right ;
2708 /* if result = right then exchange them */
2709 if(sameRegs(AOP(result),AOP(right))){
2710 operand *tmp = right ;
2715 /* if right is bit then exchange them */
2716 if (AOP_TYPE(right) == AOP_CRY &&
2717 AOP_TYPE(left) != AOP_CRY){
2718 operand *tmp = right ;
2722 if(AOP_TYPE(right) == AOP_LIT)
2723 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2725 size = AOP_SIZE(result);
2727 if (AOP_TYPE(left) == AOP_CRY){
2732 if((AOP_TYPE(right) == AOP_LIT) &&
2733 (AOP_TYPE(result) == AOP_CRY) &&
2734 (AOP_TYPE(left) != AOP_CRY)){
2739 /* if left is same as result */
2740 if(sameRegs(AOP(result),AOP(left))){
2741 for(;size--; offset++) {
2742 if(AOP_TYPE(right) == AOP_LIT){
2743 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2746 MOVA(aopGet(AOP(right),offset,FALSE));
2747 emitcode("xor","a,%s",
2748 aopGet(AOP(left),offset,FALSE));
2749 aopPut(AOP(result),"a",0);
2752 if (AOP_TYPE(left) == AOP_ACC)
2753 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2755 MOVA(aopGet(AOP(right),offset,FALSE));
2756 emitcode("xor","a,%s",
2757 aopGet(AOP(left),offset,FALSE));
2758 aopPut(AOP(result),"a",0);
2763 // left & result in different registers
2764 if(AOP_TYPE(result) == AOP_CRY){
2766 } else for(;(size--);offset++){
2768 // result = left & right
2769 if(AOP_TYPE(right) == AOP_LIT){
2770 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2772 aopGet(AOP(left),offset,FALSE),
2777 // faster than result <- left, anl result,right
2778 // and better if result is SFR
2779 if (AOP_TYPE(left) == AOP_ACC)
2780 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2782 MOVA(aopGet(AOP(right),offset,FALSE));
2783 emitcode("xor","a,%s",
2784 aopGet(AOP(left),offset,FALSE));
2785 aopPut(AOP(result),"a",0);
2787 aopPut(AOP(result),"a",offset);
2792 freeAsmop(left,NULL,ic);
2793 freeAsmop(right,NULL,ic);
2794 freeAsmop(result,NULL,ic);
2797 /*-----------------------------------------------------------------*/
2798 /* genInline - write the inline code out */
2799 /*-----------------------------------------------------------------*/
2800 static void genInline (iCode *ic)
2802 char buffer[MAX_INLINEASM];
2806 inLine += (!options.asmpeep);
2807 strcpy(buffer,IC_INLINE(ic));
2809 /* emit each line as a code */
2828 /* emitcode("",buffer); */
2829 inLine -= (!options.asmpeep);
2832 /*-----------------------------------------------------------------*/
2833 /* genRRC - rotate right with carry */
2834 /*-----------------------------------------------------------------*/
2835 static void genRRC (iCode *ic)
2840 /*-----------------------------------------------------------------*/
2841 /* genRLC - generate code for rotate left with carry */
2842 /*-----------------------------------------------------------------*/
2843 static void genRLC (iCode *ic)
2848 /*-----------------------------------------------------------------*/
2849 /* shiftR2Left2Result - shift right two bytes from left to result */
2850 /*-----------------------------------------------------------------*/
2851 static void shiftR2Left2Result (operand *left, int offl,
2852 operand *result, int offr,
2853 int shCount, int sign)
2855 if(sameRegs(AOP(result), AOP(left)) &&
2856 ((offl + MSB16) == offr)){
2859 movLeft2Result(left, offl, result, offr, 0);
2860 movLeft2Result(left, offl+1, result, offr+1, 0);
2867 /* if (AOP(result)->type == AOP_REG) {*/
2870 symbol *tlbl , *tlbl1;
2873 /* Left is already in result - so now do the shift */
2875 emitcode("ld","a,#%u+1", shCount);
2876 tlbl = newiTempLabel(NULL);
2877 tlbl1 = newiTempLabel(NULL);
2878 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
2879 emitcode("", LABEL_STR ":",tlbl->key+100);
2882 emitcode("or", "a,a");
2885 l = aopGet(AOP(result), --offset, FALSE);
2886 emitcode("rr","%s", l);
2889 emitcode("", LABEL_STR ":",tlbl1->key+100);
2890 emitcode("dec", "a");
2891 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
2896 /*-----------------------------------------------------------------*/
2897 /* shiftL2Left2Result - shift left two bytes from left to result */
2898 /*-----------------------------------------------------------------*/
2899 static void shiftL2Left2Result (operand *left, int offl,
2900 operand *result, int offr, int shCount)
2902 if(sameRegs(AOP(result), AOP(left)) &&
2903 ((offl + MSB16) == offr)){
2906 /* Copy left into result */
2907 movLeft2Result(left, offl, result, offr, 0);
2908 movLeft2Result(left, offl+1, result, offr+1, 0);
2910 /* PENDING: for now just see if it'll work. */
2911 /*if (AOP(result)->type == AOP_REG) { */
2915 symbol *tlbl , *tlbl1;
2918 /* Left is already in result - so now do the shift */
2920 emitcode("ld","a,#%u+1", shCount);
2921 tlbl = newiTempLabel(NULL);
2922 tlbl1 = newiTempLabel(NULL);
2923 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
2924 emitcode("", LABEL_STR ":",tlbl->key+100);
2927 emitcode("or", "a,a");
2929 l = aopGet(AOP(result),offset++,FALSE);
2930 emitcode("rl","%s", l);
2933 emitcode("", LABEL_STR ":",tlbl1->key+100);
2934 emitcode("dec", "a");
2935 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
2940 /*-----------------------------------------------------------------*/
2941 /* AccRol - rotate left accumulator by known count */
2942 /*-----------------------------------------------------------------*/
2943 static void AccRol (int shCount)
2945 shCount &= 0x0007; // shCount : 0..7
2982 /*-----------------------------------------------------------------*/
2983 /* AccLsh - left shift accumulator by known count */
2984 /*-----------------------------------------------------------------*/
2985 static void AccLsh (int shCount)
2989 emitcode("add","a,a");
2992 emitcode("add","a,a");
2993 emitcode("add","a,a");
2995 /* rotate left accumulator */
2997 /* and kill the lower order bits */
2998 emitcode("and","a,#0x%02x", SLMask[shCount]);
3003 /*-----------------------------------------------------------------*/
3004 /* shiftL1Left2Result - shift left one byte from left to result */
3005 /*-----------------------------------------------------------------*/
3006 static void shiftL1Left2Result (operand *left, int offl,
3007 operand *result, int offr, int shCount)
3010 l = aopGet(AOP(left),offl,FALSE);
3012 /* shift left accumulator */
3014 aopPut(AOP(result),"a",offr);
3018 /*-----------------------------------------------------------------*/
3019 /* genlshTwo - left shift two bytes by known amount != 0 */
3020 /*-----------------------------------------------------------------*/
3021 static void genlshTwo (operand *result,operand *left, int shCount)
3023 int size = AOP_SIZE(result);
3027 /* if shCount >= 8 */
3033 movLeft2Result(left, LSB, result, MSB16, 0);
3034 aopPut(AOP(result),zero, 0);
3035 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
3038 movLeft2Result(left, LSB, result, MSB16, 0);
3039 aopPut(AOP(result),zero, 0);
3042 aopPut(AOP(result),zero,LSB);
3044 /* 1 <= shCount <= 7 */
3050 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3055 /*-----------------------------------------------------------------*/
3056 /* genlshOne - left shift a one byte quantity by known count */
3057 /*-----------------------------------------------------------------*/
3058 static void genlshOne (operand *result, operand *left, int shCount)
3060 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3063 /*-----------------------------------------------------------------*/
3064 /* genLeftShiftLiteral - left shifting by known count */
3065 /*-----------------------------------------------------------------*/
3066 static void genLeftShiftLiteral (operand *left,
3071 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3074 freeAsmop(right,NULL,ic);
3076 aopOp(left,ic,FALSE);
3077 aopOp(result,ic,FALSE);
3079 size = getSize(operandType(result));
3082 emitcode("; shift left ","result %d, left %d",size,
3086 /* I suppose that the left size >= result size */
3091 else if(shCount >= (size * 8))
3093 aopPut(AOP(result),zero,size);
3097 genlshOne (result,left,shCount);
3100 genlshTwo (result,left,shCount);
3109 freeAsmop(left,NULL,ic);
3110 freeAsmop(result,NULL,ic);
3113 /*-----------------------------------------------------------------*/
3114 /* genLeftShift - generates code for left shifting */
3115 /*-----------------------------------------------------------------*/
3116 static void genLeftShift (iCode *ic)
3120 symbol *tlbl , *tlbl1;
3121 operand *left,*right, *result;
3123 right = IC_RIGHT(ic);
3125 result = IC_RESULT(ic);
3127 aopOp(right,ic,FALSE);
3129 /* if the shift count is known then do it
3130 as efficiently as possible */
3131 if (AOP_TYPE(right) == AOP_LIT) {
3132 genLeftShiftLiteral (left,right,result,ic);
3136 /* shift count is unknown then we have to form a loop get the loop
3137 count in B : Note: we take only the lower order byte since
3138 shifting more that 32 bits make no sense anyway, ( the largest
3139 size of an object can be only 32 bits ) */
3140 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3141 emitcode("inc","a");
3142 freeAsmop (right,NULL,ic);
3143 aopOp(left,ic,FALSE);
3144 aopOp(result,ic,FALSE);
3146 /* now move the left to the result if they are not the
3149 if (!sameRegs(AOP(left),AOP(result))) {
3151 size = AOP_SIZE(result);
3154 l = aopGet(AOP(left),offset,FALSE);
3155 aopPut(AOP(result),l,offset);
3160 size = AOP_SIZE(result);
3163 l = aopGet(AOP(left),offset,FALSE);
3164 aopPut(AOP(result),l,offset);
3170 tlbl = newiTempLabel(NULL);
3171 size = AOP_SIZE(result);
3173 tlbl1 = newiTempLabel(NULL);
3175 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3176 emitcode("", LABEL_STR ":",tlbl->key+100);
3177 l = aopGet(AOP(result),offset,FALSE);
3178 emitcode("or", "a,a");
3180 l = aopGet(AOP(result),offset++,FALSE);
3181 emitcode("rl","%s", l);
3183 emitcode("", LABEL_STR ":",tlbl1->key+100);
3184 emitcode("dec", "a");
3185 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3187 freeAsmop(left,NULL,ic);
3188 freeAsmop(result,NULL,ic);
3191 /* genlshTwo - left shift two bytes by known amount != 0 */
3192 /*-----------------------------------------------------------------*/
3193 static void genrshOne (operand *result,operand *left, int shCount)
3196 int size = AOP_SIZE(result);
3202 l = aopGet(AOP(left),0,FALSE);
3203 if (AOP(result)->type == AOP_REG) {
3204 aopPut(AOP(result), l, 0);
3205 l = aopGet(AOP(result), 0, FALSE);
3207 emitcode("srl", "%s", l);
3212 emitcode("srl", "a");
3214 aopPut(AOP(result),"a",0);
3218 /*-----------------------------------------------------------------*/
3219 /* AccRsh - right shift accumulator by known count */
3220 /*-----------------------------------------------------------------*/
3221 static void AccRsh (int shCount)
3228 /* rotate right accumulator */
3229 AccRol(8 - shCount);
3230 /* and kill the higher order bits */
3231 emitcode("and","a,#0x%02x", SRMask[shCount]);
3236 /*-----------------------------------------------------------------*/
3237 /* shiftR1Left2Result - shift right one byte from left to result */
3238 /*-----------------------------------------------------------------*/
3239 static void shiftR1Left2Result (operand *left, int offl,
3240 operand *result, int offr,
3241 int shCount, int sign)
3243 MOVA(aopGet(AOP(left),offl,FALSE));
3250 aopPut(AOP(result),"a",offr);
3253 /*-----------------------------------------------------------------*/
3254 /* genrshTwo - right shift two bytes by known amount != 0 */
3255 /*-----------------------------------------------------------------*/
3256 static void genrshTwo (operand *result,operand *left,
3257 int shCount, int sign)
3259 /* if shCount >= 8 */
3264 shiftR1Left2Result(left, MSB16, result, LSB,
3268 movLeft2Result(left, MSB16, result, LSB, sign);
3269 aopPut(AOP(result),zero,1);
3272 /* 1 <= shCount <= 7 */
3274 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3278 /*-----------------------------------------------------------------*/
3279 /* genRightShiftLiteral - left shifting by known count */
3280 /*-----------------------------------------------------------------*/
3281 static void genRightShiftLiteral (operand *left,
3286 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3289 freeAsmop(right,NULL,ic);
3291 aopOp(left,ic,FALSE);
3292 aopOp(result,ic,FALSE);
3294 size = getSize(operandType(result));
3296 emitcode("; shift right ","result %d, left %d",size,
3299 /* I suppose that the left size >= result size */
3304 else if(shCount >= (size * 8))
3306 aopPut(AOP(result),zero,size);
3310 genrshOne(result, left, shCount);
3313 /* PENDING: sign support */
3314 genrshTwo(result, left, shCount, FALSE);
3323 freeAsmop(left,NULL,ic);
3324 freeAsmop(result,NULL,ic);
3327 /*-----------------------------------------------------------------*/
3328 /* genRightShift - generate code for right shifting */
3329 /*-----------------------------------------------------------------*/
3330 static void genRightShift (iCode *ic)
3332 operand *left,*right, *result;
3334 right = IC_RIGHT(ic);
3336 result = IC_RESULT(ic);
3338 aopOp(right,ic,FALSE);
3340 /* if the shift count is known then do it
3341 as efficiently as possible */
3342 if (AOP_TYPE(right) == AOP_LIT) {
3343 genRightShiftLiteral (left,right,result,ic);
3351 /*-----------------------------------------------------------------*/
3352 /* genGenPointerGet - gget value from generic pointer space */
3353 /*-----------------------------------------------------------------*/
3354 static void genGenPointerGet (operand *left,
3355 operand *result, iCode *ic)
3358 link *retype = getSpec(operandType(result));
3359 const char *ptr = "hl";
3364 aopOp(left,ic,FALSE);
3365 aopOp(result,ic,FALSE);
3367 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3369 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3370 aopPut(AOP(result),"a", 0);
3371 freeAsmop(left,NULL,ic);
3375 /* For now we always load into IY */
3376 /* if this is remateriazable */
3377 if (AOP_TYPE(left) == AOP_IMMD)
3378 emitcode("ld","%s,%s", ptr, aopGet(AOP(left),0,TRUE));
3379 else { /* we need to get it byte by byte */
3381 emitcode("ld", "e,%s", aopGet(AOP(left), 0, FALSE));
3382 emitcode("ld", "d,%s", aopGet(AOP(left), 1, FALSE));
3387 /* so iy now contains the address */
3388 freeAsmop(left,NULL,ic);
3390 /* if bit then unpack */
3391 if (IS_BITVAR(retype)) {
3395 size = AOP_SIZE(result);
3399 /* PENDING: make this better */
3400 if (!IS_GB && AOP(result)->type == AOP_REG) {
3401 aopPut(AOP(result),"(hl)",offset++);
3404 emitcode("ld", "a,(%s)", ptr, offset);
3405 aopPut(AOP(result),"a",offset++);
3408 emitcode("inc", "%s", ptr);
3414 freeAsmop(result,NULL,ic);
3417 /*-----------------------------------------------------------------*/
3418 /* genPointerGet - generate code for pointer get */
3419 /*-----------------------------------------------------------------*/
3420 static void genPointerGet (iCode *ic)
3422 operand *left, *result ;
3426 result = IC_RESULT(ic) ;
3428 /* depending on the type of pointer we need to
3429 move it to the correct pointer register */
3430 type = operandType(left);
3431 etype = getSpec(type);
3433 genGenPointerGet (left,result,ic);
3436 bool isRegOrLit(asmop *aop)
3438 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3443 /*-----------------------------------------------------------------*/
3444 /* genGenPointerSet - stores the value into a pointer location */
3445 /*-----------------------------------------------------------------*/
3446 static void genGenPointerSet (operand *right,
3447 operand *result, iCode *ic)
3450 link *retype = getSpec(operandType(right));
3451 const char *ptr = "hl";
3453 aopOp(result,ic,FALSE);
3454 aopOp(right,ic,FALSE);
3459 /* Handle the exceptions first */
3460 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3462 char *l = aopGet(AOP(right), 0, FALSE);
3464 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3465 freeAsmop(result,NULL,ic);
3469 /* if the operand is already in dptr
3470 then we do nothing else we move the value to dptr */
3471 if (AOP_TYPE(result) != AOP_STR) {
3472 /* if this is remateriazable */
3473 if (AOP_TYPE(result) == AOP_IMMD) {
3474 emitcode("", "; Error 2");
3475 emitcode("ld", "%s,%s", ptr, aopGet(AOP(result), 0, TRUE));
3477 else { /* we need to get it byte by byte */
3479 emitcode("ld", "e,%s", aopGet(AOP(result), 0, TRUE));
3480 emitcode("ld", "d,%s", aopGet(AOP(result), 1, TRUE));
3483 /* PENDING: do this better */
3484 fetchHL(AOP(result));
3488 /* so hl know contains the address */
3489 freeAsmop(result,NULL,ic);
3491 /* if bit then unpack */
3492 if (IS_BITVAR(retype)) {
3496 size = AOP_SIZE(right);
3500 char *l = aopGet(AOP(right),offset,FALSE);
3501 if (isRegOrLit(AOP(right)) && !IS_GB) {
3502 emitcode("ld", "(%s),%s", l);
3506 emitcode("ld", "(%s),a", ptr, offset);
3509 emitcode("inc", ptr);
3515 freeAsmop(right,NULL,ic);
3518 /*-----------------------------------------------------------------*/
3519 /* genPointerSet - stores the value into a pointer location */
3520 /*-----------------------------------------------------------------*/
3521 static void genPointerSet (iCode *ic)
3523 operand *right, *result ;
3526 right = IC_RIGHT(ic);
3527 result = IC_RESULT(ic) ;
3529 /* depending on the type of pointer we need to
3530 move it to the correct pointer register */
3531 type = operandType(result);
3532 etype = getSpec(type);
3534 genGenPointerSet (right,result,ic);
3537 /*-----------------------------------------------------------------*/
3538 /* genIfx - generate code for Ifx statement */
3539 /*-----------------------------------------------------------------*/
3540 static void genIfx (iCode *ic, iCode *popIc)
3542 operand *cond = IC_COND(ic);
3545 aopOp(cond,ic,FALSE);
3547 /* get the value into acc */
3548 if (AOP_TYPE(cond) != AOP_CRY)
3552 /* the result is now in the accumulator */
3553 freeAsmop(cond,NULL,ic);
3555 /* if there was something to be popped then do it */
3559 /* if the condition is a bit variable */
3560 if (isbit && IS_ITEMP(cond) &&
3562 genIfxJump(ic,SPIL_LOC(cond)->rname);
3564 if (isbit && !IS_ITEMP(cond))
3565 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3572 /*-----------------------------------------------------------------*/
3573 /* genAddrOf - generates code for address of */
3574 /*-----------------------------------------------------------------*/
3575 static void genAddrOf (iCode *ic)
3577 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3579 aopOp(IC_RESULT(ic),ic,FALSE);
3581 /* if the operand is on the stack then we
3582 need to get the stack offset of this
3585 /* if it has an offset then we need to compute it */
3587 emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _pushed, _spoffset);
3588 emitcode("ld", "d,h");
3589 emitcode("ld", "e,l");
3590 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3591 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3595 emitcode("push", "de");
3596 emitcode("push", "ix");
3597 emitcode("pop", "hl");
3598 emitcode("ld", "de,#%d", sym->stack);
3599 emitcode("add", "hl,de");
3600 emitcode("pop", "de");
3604 emitcode("ld", "hl,#%s", sym->rname);
3606 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3607 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3609 freeAsmop(IC_RESULT(ic),NULL,ic);
3612 /*-----------------------------------------------------------------*/
3613 /* genAssign - generate code for assignment */
3614 /*-----------------------------------------------------------------*/
3615 static void genAssign (iCode *ic)
3617 operand *result, *right;
3619 unsigned long lit = 0L;
3621 result = IC_RESULT(ic);
3622 right = IC_RIGHT(ic) ;
3625 /* Dont bother assigning if they are the same */
3626 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3627 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3632 aopOp(right,ic,FALSE);
3633 aopOp(result,ic,TRUE);
3635 /* if they are the same registers */
3636 if (sameRegs(AOP(right),AOP(result))) {
3637 emitcode("", "; (registers are the same)");
3641 /* if the result is a bit */
3642 if (AOP_TYPE(result) == AOP_CRY) {
3647 size = AOP_SIZE(result);
3650 if(AOP_TYPE(right) == AOP_LIT)
3651 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3653 (AOP_TYPE(result) != AOP_REG) &&
3654 (AOP_TYPE(right) == AOP_LIT) &&
3655 !IS_FLOAT(operandType(right)) &&
3657 bool fXored = FALSE;
3659 /* Work from the top down.
3660 Done this way so that we can use the cached copy of 0
3661 in A for a fast clear */
3663 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3664 if (!fXored && size>1) {
3665 emitcode("xor", "a,a");
3669 aopPut(AOP(result),"a",offset);
3672 aopPut(AOP(result), "#0", offset);
3677 aopGet(AOP(right),offset,FALSE),
3682 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
3683 /* Special case. Load into a and d, then load out. */
3684 MOVA(aopGet(AOP(right), 0, FALSE));
3685 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
3686 aopPut(AOP(result), "a", 0);
3687 aopPut(AOP(result), "e", 1);
3691 aopGet(AOP(right),offset,FALSE),
3698 freeAsmop(right,NULL,ic);
3699 freeAsmop(result,NULL,ic);
3702 /*-----------------------------------------------------------------*/
3703 /* genJumpTab - genrates code for jump table */
3704 /*-----------------------------------------------------------------*/
3705 static void genJumpTab (iCode *ic)
3710 aopOp(IC_JTCOND(ic),ic,FALSE);
3711 /* get the condition into accumulator */
3712 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3715 emitcode("push", "de");
3716 emitcode("ld", "e,%s", l);
3717 emitcode("ld", "d,#0");
3718 jtab = newiTempLabel(NULL);
3719 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3720 emitcode("add", "hl,de");
3721 emitcode("add", "hl,de");
3722 emitcode("add", "hl,de");
3723 freeAsmop(IC_JTCOND(ic),NULL,ic);
3725 emitcode("pop", "de");
3726 emitcode("jp", "(hl)");
3727 emitcode("","%05d$:",jtab->key+100);
3728 /* now generate the jump labels */
3729 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3730 jtab = setNextItem(IC_JTLABELS(ic)))
3731 emitcode("jp", LABEL_STR, jtab->key+100);
3734 /*-----------------------------------------------------------------*/
3735 /* genCast - gen code for casting */
3736 /*-----------------------------------------------------------------*/
3737 static void genCast (iCode *ic)
3739 operand *result = IC_RESULT(ic);
3740 link *ctype = operandType(IC_LEFT(ic));
3741 operand *right = IC_RIGHT(ic);
3744 /* if they are equivalent then do nothing */
3745 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3748 aopOp(right,ic,FALSE) ;
3749 aopOp(result,ic,FALSE);
3751 /* if the result is a bit */
3752 if (AOP_TYPE(result) == AOP_CRY) {
3756 /* if they are the same size : or less */
3757 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3759 /* if they are in the same place */
3760 if (sameRegs(AOP(right),AOP(result)))
3763 /* if they in different places then copy */
3764 size = AOP_SIZE(result);
3768 aopGet(AOP(right),offset,FALSE),
3775 /* PENDING: should be OK. */
3777 /* if the result is of type pointer */
3778 if (IS_PTR(ctype)) {
3783 /* so we now know that the size of destination is greater
3784 than the size of the source */
3785 /* we move to result for the size of source */
3786 size = AOP_SIZE(right);
3790 aopGet(AOP(right),offset,FALSE),
3795 /* now depending on the sign of the destination */
3796 size = AOP_SIZE(result) - AOP_SIZE(right);
3797 /* Unsigned or not an integral type - right fill with zeros */
3798 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3800 aopPut(AOP(result),zero,offset++);
3802 /* we need to extend the sign :{ */
3803 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3806 emitcode("", "; genCast: sign extend untested.");
3807 emitcode("rla", "");
3808 emitcode("sbc", "a,a");
3810 aopPut(AOP(result),"a",offset++);
3814 freeAsmop(right, NULL, ic);
3815 freeAsmop(result, NULL, ic);
3818 /*-----------------------------------------------------------------*/
3819 /* genReceive - generate code for a receive iCode */
3820 /*-----------------------------------------------------------------*/
3821 static void genReceive (iCode *ic)
3823 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3824 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3825 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3829 aopOp(IC_RESULT(ic),ic,FALSE);
3831 assignResultValue(IC_RESULT(ic));
3834 freeAsmop(IC_RESULT(ic),NULL,ic);
3837 /*-----------------------------------------------------------------*/
3838 /* genZ80Code - generate code for Z80 based controllers */
3839 /*-----------------------------------------------------------------*/
3840 void genZ80Code (iCode *lic)
3847 _fReturn = _gbz80_return;
3848 _fTmp = _gbz80_return;
3852 _fReturn = _z80_return;
3853 _fTmp = _z80_return;
3857 lineHead = lineCurr = NULL;
3859 /* if debug information required */
3860 if (options.debug && currFunc) {
3861 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3863 if (IS_STATIC(currFunc->etype))
3864 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3866 emitcode("","G$%s$0$0 ==.",currFunc->name);
3869 /* stack pointer name */
3873 for (ic = lic ; ic ; ic = ic->next ) {
3875 if ( cln != ic->lineno ) {
3876 if ( options.debug ) {
3878 emitcode("","C$%s$%d$%d$%d ==.",
3879 ic->filename,ic->lineno,
3880 ic->level,ic->block);
3883 emitcode(";","%s %d",ic->filename,ic->lineno);
3886 /* if the result is marked as
3887 spilt and rematerializable or code for
3888 this has already been generated then
3890 if (resultRemat(ic) || ic->generated )
3893 /* depending on the operation */
3896 emitcode("", "; genNot");
3901 emitcode("", "; genCpl");
3906 emitcode("", "; genUminus");
3911 emitcode("", "; genIpush");
3916 /* IPOP happens only when trying to restore a
3917 spilt live range, if there is an ifx statement
3918 following this pop then the if statement might
3919 be using some of the registers being popped which
3920 would destory the contents of the register so
3921 we need to check for this condition and handle it */
3923 ic->next->op == IFX &&
3924 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3925 emitcode("", "; genIfx");
3926 genIfx (ic->next,ic);
3929 emitcode("", "; genIpop");
3935 emitcode("", "; genCall");
3940 emitcode("", "; genPcall");
3945 emitcode("", "; genFunction");
3950 emitcode("", "; genEndFunction");
3951 genEndFunction (ic);
3955 emitcode("", "; genRet");
3960 emitcode("", "; genLabel");
3965 emitcode("", "; genGoto");
3970 emitcode("", "; genPlus");
3975 emitcode("", "; genMinus");
3980 emitcode("", "; genMult");
3985 emitcode("", "; genDiv");
3990 emitcode("", "; genMod");
3995 emitcode("", "; genCmpGt");
3996 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4000 emitcode("", "; genCmpLt");
4001 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4008 /* note these two are xlated by algebraic equivalence
4009 during parsing SDCC.y */
4010 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4011 "got '>=' or '<=' shouldn't have come here");
4015 emitcode("", "; genCmpEq");
4016 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4020 emitcode("", "; genAndOp");
4025 emitcode("", "; genOrOp");
4030 emitcode("", "; genXor");
4031 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4035 emitcode("", "; genOr");
4036 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4040 emitcode("", "; genAnd");
4041 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4045 emitcode("", "; genInline");
4050 emitcode("", "; genRRC");
4055 emitcode("", "; genRLC");
4060 emitcode("", "; genHBIT");
4064 emitcode("", "; genLeftShift");
4069 emitcode("", "; genRightShift");
4073 case GET_VALUE_AT_ADDRESS:
4074 emitcode("", "; genPointerGet");
4080 if (POINTER_SET(ic)) {
4081 emitcode("", "; genAssign (pointer)");
4085 emitcode("", "; genAssign");
4091 emitcode("", "; genIfx");
4096 emitcode("", "; genAddrOf");
4101 emitcode("", "; genJumpTab");
4106 emitcode("", "; genCast");
4111 emitcode("", "; genReceive");
4116 emitcode("", "; addSet");
4117 addSet(&sendSet,ic);
4122 /* piCode(ic,stdout); */
4128 /* now we are ready to call the
4129 peep hole optimizer */
4130 if (!options.nopeep)
4131 peepHole (&lineHead);
4133 /* now do the actual printing */
4134 printLine (lineHead,codeOutFile);