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
17 Michael Hope <michaelh@earthling.net> 2000
18 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
19 and - Jean-Louis VERN.jlvern@writeme.com (1999)
21 This program is free software; you can redistribute it and/or modify it
22 under the terms of the GNU General Public License as published by the
23 Free Software Foundation; either version 2, or (at your option) any
26 This program is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 GNU General Public License for more details.
31 You should have received a copy of the GNU General Public License
32 along with this program; if not, write to the Free Software
33 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 In other words, you are welcome to use, share and improve this program.
36 You are forbidden to forbid anyone else to use, share and improve
37 what you give them. Help stamp out software-hoarding!
39 -------------------------------------------------------------------------*/
45 #include "SDCCglobl.h"
47 #ifdef HAVE_SYS_ISA_DEFS_H
48 #include <sys/isa_defs.h>
54 #include "SDCChasht.h"
57 #include "SDCCicode.h"
58 #include "SDCClabel.h"
59 #include "SDCCBBlock.h"
62 #include "SDCCcflow.h"
63 #include "SDCCdflow.h"
64 #include "SDCClrange.h"
67 #include "SDCCpeeph.h"
68 #include "SDCCglue.h" /* drdani Jan 30 2000 */
70 /* this is the down and dirty file with all kinds of kludgy & hacky
71 stuff. This is what it is all about CODE GENERATION for a specific MCU.
72 Some of the routines may be reusable, will have to see */
74 static char *zero = "#0x00";
75 static char *one = "#0x01";
77 static char *fReturn[] = {"l", "h", "e", "d" };
78 static char *accUse[] = {"a" };
84 extern int ptrRegReq ;
86 extern FILE *codeOutFile;
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
93 #define CLRC emitcode("xor","a,a");
95 #define LABEL_STR "%05d$"
97 lineNode *lineHead = NULL;
98 lineNode *lineCurr = NULL;
100 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
101 0xE0, 0xC0, 0x80, 0x00};
102 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
103 0x07, 0x03, 0x01, 0x00};
105 static int _lastStack = 0;
120 /*-----------------------------------------------------------------*/
121 /* emitcode - writes the code into a file : for now it is simple */
122 /*-----------------------------------------------------------------*/
123 void emitcode (const char *inst, const char *fmt, ...)
126 char lb[MAX_INLINEASM];
132 sprintf(lb,"%s\t",inst);
133 vsprintf(lb+(strlen(lb)),fmt,ap);
137 while (isspace(*lbp)) lbp++;
140 lineCurr = (lineCurr ?
141 connectLine(lineCurr,newLineNode(lb)) :
142 (lineHead = newLineNode(lb)));
143 lineCurr->isInline = inLine;
144 lineCurr->isDebug = debugLine;
148 const char *getPairName(asmop *aop)
150 if (aop->type == AOP_REG) {
151 switch (aop->aopu.aop_reg[0]->rIdx) {
163 else if (aop->type == AOP_STR) {
164 switch (*aop->aopu.aop_str[0]) {
180 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
181 bool isPair(asmop *aop)
183 if (aop->size == 2) {
184 if (aop->type == AOP_REG) {
185 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
188 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
191 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
195 if (aop->type == AOP_STR) {
196 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
199 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
202 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
210 /** Push a register pair onto the stack */
211 void genPairPush(asmop *aop)
213 emitcode("push", "%s", getPairName(aop));
216 /*-----------------------------------------------------------------*/
217 /* newAsmop - creates a new asmOp */
218 /*-----------------------------------------------------------------*/
219 static asmop *newAsmop (short type)
223 ALLOC(aop,sizeof(asmop));
228 /*-----------------------------------------------------------------*/
229 /* aopForSym - for a true symbol */
230 /*-----------------------------------------------------------------*/
231 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
234 memmap *space= SPEC_OCLS(sym->etype);
236 /* if already has one */
240 /* Assign depending on the storage class */
241 if (sym->onStack || sym->iaccess) {
242 sym->aop = aop = newAsmop(AOP_STK);
243 aop->size = getSize(sym->type);
245 aop->aopu.aop_stk = sym->stack;
249 /* special case for a function */
250 if (IS_FUNC(sym->type)) {
251 sym->aop = aop = newAsmop(AOP_IMMD);
252 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
253 strcpy(aop->aopu.aop_immd,sym->rname);
258 /* only remaining is far space */
259 /* in which case DPTR gets the address */
260 sym->aop = aop = newAsmop(AOP_IY);
261 emitcode ("ld","iy,#%s", sym->rname);
262 aop->size = getSize(sym->type);
263 aop->aopu.aop_dir = sym->rname;
265 /* if it is in code space */
266 if (IN_CODESPACE(space))
272 /*-----------------------------------------------------------------*/
273 /* aopForRemat - rematerialzes an object */
274 /*-----------------------------------------------------------------*/
275 static asmop *aopForRemat (symbol *sym)
278 iCode *ic = sym->rematiCode;
279 asmop *aop = newAsmop(AOP_IMMD);
282 /* if plus or minus print the right hand side */
283 if (ic->op == '+' || ic->op == '-') {
284 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
287 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
290 /* we reached the end */
291 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
295 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
296 strcpy(aop->aopu.aop_immd,buffer);
300 /*-----------------------------------------------------------------*/
301 /* regsInCommon - two operands have some registers in common */
302 /*-----------------------------------------------------------------*/
303 bool regsInCommon (operand *op1, operand *op2)
308 /* if they have registers in common */
309 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
312 sym1 = OP_SYMBOL(op1);
313 sym2 = OP_SYMBOL(op2);
315 if (sym1->nRegs == 0 || sym2->nRegs == 0)
318 for (i = 0 ; i < sym1->nRegs ; i++) {
323 for (j = 0 ; j < sym2->nRegs ;j++ ) {
327 if (sym2->regs[j] == sym1->regs[i])
335 /*-----------------------------------------------------------------*/
336 /* operandsEqu - equivalent */
337 /*-----------------------------------------------------------------*/
338 bool operandsEqu ( operand *op1, operand *op2)
342 /* if they not symbols */
343 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
346 sym1 = OP_SYMBOL(op1);
347 sym2 = OP_SYMBOL(op2);
349 /* if both are itemps & one is spilt
350 and the other is not then false */
351 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
352 sym1->isspilt != sym2->isspilt )
355 /* if they are the same */
359 if (strcmp(sym1->rname,sym2->rname) == 0)
363 /* if left is a tmp & right is not */
367 (sym1->usl.spillLoc == sym2))
374 (sym2->usl.spillLoc == sym1))
380 /*-----------------------------------------------------------------*/
381 /* sameRegs - two asmops have the same registers */
382 /*-----------------------------------------------------------------*/
383 bool sameRegs (asmop *aop1, asmop *aop2 )
390 if (aop1->type != AOP_REG ||
391 aop2->type != AOP_REG )
394 if (aop1->size != aop2->size)
397 for (i = 0 ; i < aop1->size ; i++ )
398 if (aop1->aopu.aop_reg[i] !=
399 aop2->aopu.aop_reg[i] )
405 /*-----------------------------------------------------------------*/
406 /* aopOp - allocates an asmop for an operand : */
407 /*-----------------------------------------------------------------*/
408 static void aopOp (operand *op, iCode *ic, bool result)
417 /* if this a literal */
418 if (IS_OP_LITERAL(op)) {
419 op->aop = aop = newAsmop(AOP_LIT);
420 aop->aopu.aop_lit = op->operand.valOperand;
421 aop->size = getSize(operandType(op));
425 /* if already has a asmop then continue */
429 /* if the underlying symbol has a aop */
430 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
431 op->aop = OP_SYMBOL(op)->aop;
435 /* if this is a true symbol */
436 if (IS_TRUE_SYMOP(op)) {
437 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
441 /* this is a temporary : this has
447 e) can be a return use only */
451 /* if the type is a conditional */
452 if (sym->regType == REG_CND) {
453 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
458 /* if it is spilt then two situations
460 b) has a spill location */
461 if (sym->isspilt || sym->nRegs == 0) {
462 /* rematerialize it NOW */
464 sym->aop = op->aop = aop =
466 aop->size = getSize(sym->type);
472 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
473 aop->size = getSize(sym->type);
474 for ( i = 0 ; i < 2 ; i++ )
475 aop->aopu.aop_str[i] = accUse[i];
481 aop = op->aop = sym->aop = newAsmop(AOP_STR);
482 aop->size = getSize(sym->type);
483 for ( i = 0 ; i < 4 ; i++ )
484 aop->aopu.aop_str[i] = fReturn[i];
488 /* else spill location */
489 sym->aop = op->aop = aop =
490 aopForSym(ic,sym->usl.spillLoc,result);
491 aop->size = getSize(sym->type);
495 /* must be in a register */
496 sym->aop = op->aop = aop = newAsmop(AOP_REG);
497 aop->size = sym->nRegs;
498 for ( i = 0 ; i < sym->nRegs ;i++)
499 aop->aopu.aop_reg[i] = sym->regs[i];
502 /*-----------------------------------------------------------------*/
503 /* freeAsmop - free up the asmop given to an operand */
504 /*----------------------------------------------------------------*/
505 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
528 /* all other cases just dealloc */
532 OP_SYMBOL(op)->aop = NULL;
533 /* if the symbol has a spill */
535 SPIL_LOC(op)->aop = NULL;
540 char *aopGetWord(asmop *aop, int offset)
545 assert(aop->size == 2);
548 /* depending on type */
551 sprintf (s,"#%s",aop->aopu.aop_immd);
552 ALLOC_ATOMIC(rs,strlen(s)+1);
557 value * val = aop->aopu.aop_lit;
558 /* if it is a float then it gets tricky */
559 /* otherwise it is fairly simple */
560 if (!IS_FLOAT(val->type)) {
561 unsigned long v = floatFromVal(val);
563 sprintf(buffer,"#0x%04lx", v);
564 ALLOC_ATOMIC(rs,strlen(buffer)+1);
565 return strcpy (rs,buffer);
574 /*-----------------------------------------------------------------*/
575 /* aopGet - for fetching value of the aop */
576 /*-----------------------------------------------------------------*/
577 static char *aopGet (asmop *aop, int offset, bool bit16)
582 /* offset is greater than size then zero */
583 if (offset > (aop->size - 1) &&
584 aop->type != AOP_LIT)
587 /* depending on type */
591 sprintf (s,"#%s",aop->aopu.aop_immd);
601 ALLOC_ATOMIC(rs,strlen(s)+1);
607 emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
609 ALLOC_ATOMIC(rs,strlen(s)+1);
614 return aop->aopu.aop_reg[offset]->name;
617 sprintf(s,"%d(iy)", offset);
618 ALLOC_ATOMIC(rs,strlen(s)+1);
623 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
624 ALLOC_ATOMIC(rs,strlen(s)+1);
638 return aopLiteral (aop->aopu.aop_lit,offset);
642 return aop->aopu.aop_str[offset];
645 fprintf(stderr, "Type %u\n", aop->type);
647 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
648 "aopget got unsupported aop->type");
652 bool isRegString(char *s)
654 if (!strcmp(s, "b") ||
665 bool isConstant(char *s)
670 bool canAssignToPtr(char *s)
679 /*-----------------------------------------------------------------*/
680 /* aopPut - puts a string for a aop */
681 /*-----------------------------------------------------------------*/
682 static void aopPut (asmop *aop, char *s, int offset)
686 if (aop->size && offset > ( aop->size - 1)) {
687 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
688 "aopPut got offset > aop->size");
692 /* will assign value to value */
693 /* depending on where it is ofcourse */
698 emitcode("ld", "a,%s", s);
699 emitcode("ld", "(%s+%d),a", d, offset);
703 /* Dont bother if it's a ld x,x */
704 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
705 emitcode("ld","%s,%s",
706 aop->aopu.aop_reg[offset]->name,s);
711 if (!canAssignToPtr(s)) {
712 emitcode("ld", "a,%s", s);
713 emitcode("ld", "%d(iy),a", offset);
716 emitcode("ld", "%d(iy),%s", offset, s);
720 if (!canAssignToPtr(s)) {
721 emitcode("ld", "a,%s", s);
722 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
725 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
729 /* if bit variable */
730 if (!aop->aopu.aop_dir) {
731 emitcode("ld", "a,#0");
734 /* In bit space but not in C - cant happen */
741 if (strcmp(aop->aopu.aop_str[offset],s)) {
742 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
748 if (!offset && (strcmp(s,"acc") == 0))
752 emitcode("", "; Error aopPut AOP_ACC");
755 if (strcmp(aop->aopu.aop_str[offset],s))
756 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
761 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
762 "aopPut got unsupported aop->type");
767 #define AOP(op) op->aop
768 #define AOP_TYPE(op) AOP(op)->type
769 #define AOP_SIZE(op) AOP(op)->size
770 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
772 /*-----------------------------------------------------------------*/
773 /* getDataSize - get the operand data size */
774 /*-----------------------------------------------------------------*/
775 int getDataSize(operand *op)
786 /*-----------------------------------------------------------------*/
787 /* movLeft2Result - move byte from left to result */
788 /*-----------------------------------------------------------------*/
789 static void movLeft2Result (operand *left, int offl,
790 operand *result, int offr, int sign)
793 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
794 l = aopGet(AOP(left),offl,FALSE);
797 aopPut(AOP(result),l,offr);
806 /** Put Acc into a register set
808 void outAcc(operand *result)
811 size = getDataSize(result);
813 aopPut(AOP(result),"a",0);
816 /* unsigned or positive */
818 aopPut(AOP(result),zero,offset++);
823 /** Take the value in carry and put it into a register
825 void outBitC(operand *result)
827 /* if the result is bit */
828 if (AOP_TYPE(result) == AOP_CRY) {
829 emitcode("", "; Note: outBitC form 1");
830 aopPut(AOP(result),"blah",0);
833 emitcode("ld", "a,#0");
839 /*-----------------------------------------------------------------*/
840 /* toBoolean - emit code for orl a,operator(sizeop) */
841 /*-----------------------------------------------------------------*/
842 void toBoolean(operand *oper)
844 int size = AOP_SIZE(oper);
847 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
850 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
854 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
858 /*-----------------------------------------------------------------*/
859 /* genNot - generate code for ! operation */
860 /*-----------------------------------------------------------------*/
861 static void genNot (iCode *ic)
863 link *optype = operandType(IC_LEFT(ic));
865 /* assign asmOps to operand & result */
866 aopOp (IC_LEFT(ic),ic,FALSE);
867 aopOp (IC_RESULT(ic),ic,TRUE);
869 /* if in bit space then a special case */
870 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
874 /* if type float then do float */
875 if (IS_FLOAT(optype)) {
879 toBoolean(IC_LEFT(ic));
884 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
885 emitcode("sub", "a,#0x01");
886 outBitC(IC_RESULT(ic));
888 /* release the aops */
889 freeAsmop(IC_LEFT(ic),NULL,ic);
890 freeAsmop(IC_RESULT(ic),NULL,ic);
893 /*-----------------------------------------------------------------*/
894 /* genCpl - generate code for complement */
895 /*-----------------------------------------------------------------*/
896 static void genCpl (iCode *ic)
902 /* assign asmOps to operand & result */
903 aopOp (IC_LEFT(ic),ic,FALSE);
904 aopOp (IC_RESULT(ic),ic,TRUE);
906 /* if both are in bit space then
908 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
909 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
913 size = AOP_SIZE(IC_RESULT(ic));
915 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
918 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
921 /* release the aops */
922 freeAsmop(IC_LEFT(ic),NULL,ic);
923 freeAsmop(IC_RESULT(ic),NULL,ic);
926 /*-----------------------------------------------------------------*/
927 /* genUminus - unary minus code generation */
928 /*-----------------------------------------------------------------*/
929 static void genUminus (iCode *ic)
932 link *optype, *rtype;
935 aopOp(IC_LEFT(ic),ic,FALSE);
936 aopOp(IC_RESULT(ic),ic,TRUE);
938 /* if both in bit space then special
940 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
941 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
946 optype = operandType(IC_LEFT(ic));
947 rtype = operandType(IC_RESULT(ic));
949 /* if float then do float stuff */
950 if (IS_FLOAT(optype)) {
955 /* otherwise subtract from zero */
956 size = AOP_SIZE(IC_LEFT(ic));
960 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
961 emitcode("ld", "a,#0");
962 emitcode("sbc","a,%s",l);
963 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
966 /* if any remaining bytes in the result */
967 /* we just need to propagate the sign */
968 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
970 emitcode("sbc","a,a");
972 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
976 /* release the aops */
977 freeAsmop(IC_LEFT(ic),NULL,ic);
978 freeAsmop(IC_RESULT(ic),NULL,ic);
982 /*-----------------------------------------------------------------*/
983 /* assignResultValue - */
984 /*-----------------------------------------------------------------*/
985 void assignResultValue(operand * oper)
988 int size = AOP_SIZE(oper);
990 aopPut(AOP(oper),fReturn[offset],offset);
995 /*-----------------------------------------------------------------*/
996 /* genIpush - genrate code for pushing this gets a little complex */
997 /*-----------------------------------------------------------------*/
998 static void genIpush (iCode *ic)
1000 int size, offset = 0 ;
1004 /* if this is not a parm push : ie. it is spill push
1005 and spill push is always done on the local stack */
1006 if (!ic->parmPush) {
1007 /* and the item is spilt then do nothing */
1008 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1011 aopOp(IC_LEFT(ic),ic,FALSE);
1012 size = AOP_SIZE(IC_LEFT(ic));
1013 /* push it on the stack */
1014 if (isPair(AOP(IC_LEFT(ic)))) {
1015 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1020 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1021 /* Simple for now - load into A and PUSH AF */
1022 emitcode("ld", "a,%s", l);
1023 emitcode("push", "af");
1024 emitcode("inc", "sp");
1030 /* Hmmm... what about saving the currently used registers
1033 /* then do the push */
1034 aopOp(IC_LEFT(ic),ic,FALSE);
1036 size = AOP_SIZE(IC_LEFT(ic));
1038 if (isPair(AOP(IC_LEFT(ic)))) {
1039 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1043 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1045 emitcode("ld", "hl,%s", s);
1046 emitcode("push", "hl");
1049 /* Optimise here - load into HL then push HL */
1050 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0, FALSE));
1051 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1, FALSE));
1052 emitcode("push", "hl");
1058 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1059 emitcode("ld", "a,%s", l);
1060 emitcode("push", "af");
1061 emitcode("inc", "sp");
1065 freeAsmop(IC_LEFT(ic),NULL,ic);
1068 /*-----------------------------------------------------------------*/
1069 /* genIpop - recover the registers: can happen only for spilling */
1070 /*-----------------------------------------------------------------*/
1071 static void genIpop (iCode *ic)
1076 /* if the temp was not pushed then */
1077 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1080 aopOp(IC_LEFT(ic),ic,FALSE);
1081 size = AOP_SIZE(IC_LEFT(ic));
1083 if (isPair(AOP(IC_LEFT(ic)))) {
1084 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1088 emitcode("dec", "sp");
1089 emitcode("pop", "hl");
1090 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1094 freeAsmop(IC_LEFT(ic),NULL,ic);
1097 /** Emit the code for a call statement
1099 static void emitCall (iCode *ic, bool ispcall)
1101 /* if caller saves & we have not saved then */
1102 if (!ic->regsSaved) {
1106 /* if send set is not empty then assign */
1110 for (sic = setFirstItem(sendSet) ; sic ;
1111 sic = setNextItem(sendSet)) {
1112 int size, offset = 0;
1113 aopOp(IC_LEFT(sic),sic,FALSE);
1114 size = AOP_SIZE(IC_LEFT(sic));
1116 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1118 if (strcmp(l,fReturn[offset]))
1119 emitcode("ld","%s,%s",
1124 freeAsmop (IC_LEFT(sic),NULL,sic);
1130 symbol *rlbl = newiTempLabel(NULL);
1132 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1133 emitcode("push", "hl");
1135 aopOp(IC_LEFT(ic),ic,FALSE);
1136 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1137 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1138 freeAsmop(IC_LEFT(ic),NULL,ic);
1140 emitcode("jp", "(hl)");
1141 emitcode("","%05d$:",(rlbl->key+100));
1145 emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1146 OP_SYMBOL(IC_LEFT(ic))->rname :
1147 OP_SYMBOL(IC_LEFT(ic))->name));
1150 /* if we need assign a result value */
1151 if ((IS_ITEMP(IC_RESULT(ic)) &&
1152 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1153 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1154 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1157 aopOp(IC_RESULT(ic),ic,FALSE);
1160 assignResultValue(IC_RESULT(ic));
1162 freeAsmop(IC_RESULT(ic),NULL, ic);
1165 /* adjust the stack for parameters if required */
1166 if (IC_LEFT(ic)->parmBytes) {
1167 int i = IC_LEFT(ic)->parmBytes;
1169 emitcode("ld", "hl,#%d", i);
1170 emitcode("add", "hl,sp");
1171 emitcode("ld", "sp,hl");
1175 emitcode("pop", "hl");
1179 emitcode("inc", "sp");
1185 /*-----------------------------------------------------------------*/
1186 /* genCall - generates a call statement */
1187 /*-----------------------------------------------------------------*/
1188 static void genCall (iCode *ic)
1190 emitCall(ic, FALSE);
1193 /*-----------------------------------------------------------------*/
1194 /* genPcall - generates a call by pointer statement */
1195 /*-----------------------------------------------------------------*/
1196 static void genPcall (iCode *ic)
1201 /*-----------------------------------------------------------------*/
1202 /* resultRemat - result is rematerializable */
1203 /*-----------------------------------------------------------------*/
1204 static int resultRemat (iCode *ic)
1206 if (SKIP_IC(ic) || ic->op == IFX)
1209 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1210 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1211 if (sym->remat && !POINTER_SET(ic))
1218 /*-----------------------------------------------------------------*/
1219 /* genFunction - generated code for function entry */
1220 /*-----------------------------------------------------------------*/
1221 static void genFunction (iCode *ic)
1227 /* create the function header */
1228 emitcode(";","-----------------------------------------");
1229 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1230 emitcode(";","-----------------------------------------");
1232 emitcode("","%s:",sym->rname);
1233 fetype = getSpec(operandType(IC_LEFT(ic)));
1235 /* if critical function then turn interrupts off */
1236 if (SPEC_CRTCL(fetype))
1239 /* if this is an interrupt service routine then
1240 save acc, b, dpl, dph */
1241 if (IS_ISR(sym->etype)) {
1242 emitcode("push", "af");
1243 emitcode("push", "bc");
1244 emitcode("push", "de");
1245 emitcode("push", "hl");
1247 /* PENDING: callee-save etc */
1249 /* adjust the stack for the function */
1250 emitcode("push", "de");
1251 emitcode("push", "bc");
1252 emitcode("push", "ix");
1253 emitcode("ld", "ix,#0");
1254 emitcode("add", "ix,sp");
1256 _lastStack = sym->stack;
1259 emitcode("ld", "hl,#-%d", sym->stack);
1260 emitcode("add", "hl,sp");
1261 emitcode("ld", "sp,hl");
1265 /*-----------------------------------------------------------------*/
1266 /* genEndFunction - generates epilogue for functions */
1267 /*-----------------------------------------------------------------*/
1268 static void genEndFunction (iCode *ic)
1270 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1272 if (IS_ISR(sym->etype)) {
1276 if (SPEC_CRTCL(sym->etype))
1279 /* PENDING: calleeSave */
1281 /* if debug then send end of function */
1282 if (options.debug && currFunc) {
1284 emitcode("","C$%s$%d$%d$%d ==.",
1285 ic->filename,currFunc->lastLine,
1286 ic->level,ic->block);
1287 if (IS_STATIC(currFunc->etype))
1288 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1290 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1293 emitcode("ld", "sp,ix");
1294 emitcode("pop", "ix");
1295 emitcode("pop", "bc");
1296 emitcode("pop", "de");
1297 emitcode("ret", "");
1302 /*-----------------------------------------------------------------*/
1303 /* genRet - generate code for return statement */
1304 /*-----------------------------------------------------------------*/
1305 static void genRet (iCode *ic)
1308 /* Errk. This is a hack until I can figure out how
1309 to cause dehl to spill on a call */
1310 int size,offset = 0;
1312 /* if we have no return value then
1313 just generate the "ret" */
1317 /* we have something to return then
1318 move the return value into place */
1319 aopOp(IC_LEFT(ic),ic,FALSE);
1320 size = AOP_SIZE(IC_LEFT(ic));
1322 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1323 emitcode("ld", "hl,%s", l);
1327 l = aopGet(AOP(IC_LEFT(ic)),offset,
1329 if (strcmp(fReturn[offset],l))
1330 emitcode("ld","%s,%s",fReturn[offset++],l);
1333 freeAsmop (IC_LEFT(ic),NULL,ic);
1336 /* generate a jump to the return label
1337 if the next is not the return statement */
1338 if (!(ic->next && ic->next->op == LABEL &&
1339 IC_LABEL(ic->next) == returnLabel))
1341 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1344 /*-----------------------------------------------------------------*/
1345 /* genLabel - generates a label */
1346 /*-----------------------------------------------------------------*/
1347 static void genLabel (iCode *ic)
1349 /* special case never generate */
1350 if (IC_LABEL(ic) == entryLabel)
1353 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1356 /*-----------------------------------------------------------------*/
1357 /* genGoto - generates a ljmp */
1358 /*-----------------------------------------------------------------*/
1359 static void genGoto (iCode *ic)
1361 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1364 /*-----------------------------------------------------------------*/
1365 /* genPlusIncr :- does addition with increment if possible */
1366 /*-----------------------------------------------------------------*/
1367 static bool genPlusIncr (iCode *ic)
1369 unsigned int icount ;
1370 unsigned int size = getDataSize(IC_RESULT(ic));
1372 /* will try to generate an increment */
1373 /* if the right side is not a literal
1375 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1378 /* if the literal value of the right hand side
1379 is greater than 4 then it is not worth it */
1380 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
1384 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1385 isPair(AOP(IC_RESULT(ic)))) {
1387 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1391 /* if increment 16 bits in register */
1392 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1395 symbol *tlbl = newiTempLabel(NULL);
1396 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1397 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1399 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1403 emitcode("", LABEL_STR ":",tlbl->key+100);
1407 /* If result is a pair */
1408 if (isPair(AOP(IC_RESULT(ic)))) {
1409 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1410 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1412 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1416 /* if the sizes are greater than 1 then we cannot */
1417 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1418 AOP_SIZE(IC_LEFT(ic)) > 1 )
1421 /* we can if the aops of the left & result match or
1422 if they are in registers and the registers are the
1424 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1426 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1434 /*-----------------------------------------------------------------*/
1435 /* outBitAcc - output a bit in acc */
1436 /*-----------------------------------------------------------------*/
1437 void outBitAcc(operand *result)
1439 symbol *tlbl = newiTempLabel(NULL);
1440 /* if the result is a bit */
1441 if (AOP_TYPE(result) == AOP_CRY){
1445 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1446 emitcode("ld","a,%s",one);
1447 emitcode("", LABEL_STR ":",tlbl->key+100);
1452 /*-----------------------------------------------------------------*/
1453 /* genPlus - generates code for addition */
1454 /*-----------------------------------------------------------------*/
1455 static void genPlus (iCode *ic)
1457 int size, offset = 0;
1459 /* special cases :- */
1461 aopOp (IC_LEFT(ic),ic,FALSE);
1462 aopOp (IC_RIGHT(ic),ic,FALSE);
1463 aopOp (IC_RESULT(ic),ic,TRUE);
1465 /* Swap the left and right operands if:
1467 if literal, literal on the right or
1468 if left requires ACC or right is already
1471 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1472 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1473 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1474 operand *t = IC_RIGHT(ic);
1475 IC_RIGHT(ic) = IC_LEFT(ic);
1479 /* if both left & right are in bit
1481 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1482 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1487 /* if left in bit space & right literal */
1488 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1489 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1490 /* Can happen I guess */
1494 /* if I can do an increment instead
1495 of add then GOOD for ME */
1496 if (genPlusIncr (ic) == TRUE)
1499 size = getDataSize(IC_RESULT(ic));
1502 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1503 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1505 emitcode("add","a,%s",
1506 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1508 emitcode("adc","a,%s",
1509 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1511 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1513 emitcode("add","a,%s",
1514 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1516 emitcode("adc","a,%s",
1517 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1519 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1522 /* Some kind of pointer arith. */
1523 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1524 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1525 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1528 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1529 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1530 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1535 freeAsmop(IC_LEFT(ic),NULL,ic);
1536 freeAsmop(IC_RIGHT(ic),NULL,ic);
1537 freeAsmop(IC_RESULT(ic),NULL,ic);
1541 /*-----------------------------------------------------------------*/
1542 /* genMinusDec :- does subtraction with deccrement if possible */
1543 /*-----------------------------------------------------------------*/
1544 static bool genMinusDec (iCode *ic)
1546 unsigned int icount ;
1547 unsigned int size = getDataSize(IC_RESULT(ic));
1549 /* will try to generate an increment */
1550 /* if the right side is not a literal we cannot */
1551 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1554 /* if the literal value of the right hand side
1555 is greater than 4 then it is not worth it */
1556 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1559 size = getDataSize(IC_RESULT(ic));
1560 /* if decrement 16 bits in register */
1561 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1562 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1564 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1568 /* If result is a pair */
1569 if (isPair(AOP(IC_RESULT(ic)))) {
1570 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1571 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1573 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1577 /* if the sizes are greater than 1 then we cannot */
1578 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1579 AOP_SIZE(IC_LEFT(ic)) > 1 )
1582 /* we can if the aops of the left & result match or if they are in
1583 registers and the registers are the same */
1584 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1586 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1593 /*-----------------------------------------------------------------*/
1594 /* genMinus - generates code for subtraction */
1595 /*-----------------------------------------------------------------*/
1596 static void genMinus (iCode *ic)
1598 int size, offset = 0;
1599 unsigned long lit = 0L;
1601 aopOp (IC_LEFT(ic),ic,FALSE);
1602 aopOp (IC_RIGHT(ic),ic,FALSE);
1603 aopOp (IC_RESULT(ic),ic,TRUE);
1605 /* special cases :- */
1606 /* if both left & right are in bit space */
1607 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1608 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1613 /* if I can do an decrement instead of subtract then GOOD for ME */
1614 if (genMinusDec (ic) == TRUE)
1617 size = getDataSize(IC_RESULT(ic));
1619 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1623 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1628 /* if literal, add a,#-lit, else normal subb */
1630 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1631 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1632 emitcode("sbc","a,%s",
1633 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1635 /* first add without previous c */
1637 emitcode("add","a,#0x%02x",
1638 (unsigned int)(lit & 0x0FFL));
1640 emitcode("adc","a,#0x%02x",
1641 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1643 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1646 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1647 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1648 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1652 freeAsmop(IC_LEFT(ic),NULL,ic);
1653 freeAsmop(IC_RIGHT(ic),NULL,ic);
1654 freeAsmop(IC_RESULT(ic),NULL,ic);
1657 /*-----------------------------------------------------------------*/
1658 /* genMult - generates code for multiplication */
1659 /*-----------------------------------------------------------------*/
1660 static void genMult (iCode *ic)
1662 /* Shouldn't occur - all done through function calls */
1666 /*-----------------------------------------------------------------*/
1667 /* genDiv - generates code for division */
1668 /*-----------------------------------------------------------------*/
1669 static void genDiv (iCode *ic)
1671 /* Shouldn't occur - all done through function calls */
1675 /*-----------------------------------------------------------------*/
1676 /* genMod - generates code for division */
1677 /*-----------------------------------------------------------------*/
1678 static void genMod (iCode *ic)
1680 /* Shouldn't occur - all done through function calls */
1684 /*-----------------------------------------------------------------*/
1685 /* genIfxJump :- will create a jump depending on the ifx */
1686 /*-----------------------------------------------------------------*/
1687 static void genIfxJump (iCode *ic, char *jval)
1692 /* if true label then we jump if condition
1694 if ( IC_TRUE(ic) ) {
1696 if (!strcmp(jval, "a")) {
1699 else if (!strcmp(jval, "c")) {
1703 /* The buffer contains the bit on A that we should test */
1708 /* false label is present */
1709 jlbl = IC_FALSE(ic) ;
1710 if (!strcmp(jval, "a")) {
1713 else if (!strcmp(jval, "c")) {
1717 /* The buffer contains the bit on A that we should test */
1721 /* Z80 can do a conditional long jump */
1722 if (!strcmp(jval, "a")) {
1723 emitcode("or", "a,a");
1725 else if (!strcmp(jval, "c")) {
1728 emitcode("bit", "%s,a", jval);
1730 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1732 /* mark the icode as generated */
1736 /** Generic compare for > or <
1738 static void genCmp (operand *left,operand *right,
1739 operand *result, iCode *ifx, int sign)
1741 int size, offset = 0 ;
1742 unsigned long lit = 0L;
1744 /* if left & right are bit variables */
1745 if (AOP_TYPE(left) == AOP_CRY &&
1746 AOP_TYPE(right) == AOP_CRY ) {
1747 /* Cant happen on the Z80 */
1750 /* subtract right from left if at the
1751 end the carry flag is set then we know that
1752 left is greater than right */
1753 size = max(AOP_SIZE(left),AOP_SIZE(right));
1755 /* if unsigned char cmp with lit, just compare */
1756 if((size == 1) && !sign &&
1757 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1758 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1759 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1762 if(AOP_TYPE(right) == AOP_LIT) {
1763 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1764 /* optimize if(x < 0) or if(x >= 0) */
1767 /* No sign so it's always false */
1771 /* Just load in the top most bit */
1772 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1773 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1774 genIfxJump (ifx,"7");
1778 emitcode("rlc","a");
1785 /* Do a long subtract */
1786 MOVA(aopGet(AOP(left),offset,FALSE));
1787 if (sign && size == 0) {
1789 emitcode("push", "af");
1790 emitcode("xor", "a,#0x80");
1791 emitcode("ld", "l,a");
1792 emitcode("pop", "af");
1793 emitcode("ld", "a,l");
1794 if (AOP_TYPE(right) == AOP_LIT){
1795 unsigned long lit = (unsigned long)
1796 floatFromVal(AOP(right)->aopu.aop_lit);
1797 emitcode("sbc","a,#0x%02x",
1798 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1800 emitcode("push", "af");
1801 emitcode("ld", "a,%s",aopGet(AOP(right),offset++,FALSE));
1802 emitcode("xor", "a,#0x80");
1803 emitcode("ld", "l,a");
1804 emitcode("pop", "af");
1805 emitcode("sbc", "a,l");
1809 /* Subtract through, propagating the carry */
1810 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1817 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1820 /* if the result is used in the next
1821 ifx conditional branch then generate
1822 code a little differently */
1824 genIfxJump (ifx,"c");
1827 /* leave the result in acc */
1831 /*-----------------------------------------------------------------*/
1832 /* genCmpGt :- greater than comparison */
1833 /*-----------------------------------------------------------------*/
1834 static void genCmpGt (iCode *ic, iCode *ifx)
1836 operand *left, *right, *result;
1837 link *letype , *retype;
1841 right= IC_RIGHT(ic);
1842 result = IC_RESULT(ic);
1844 letype = getSpec(operandType(left));
1845 retype =getSpec(operandType(right));
1846 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1847 /* assign the amsops */
1848 aopOp (left,ic,FALSE);
1849 aopOp (right,ic,FALSE);
1850 aopOp (result,ic,TRUE);
1852 genCmp(right, left, result, ifx, sign);
1854 freeAsmop(left,NULL,ic);
1855 freeAsmop(right,NULL,ic);
1856 freeAsmop(result,NULL,ic);
1859 /*-----------------------------------------------------------------*/
1860 /* genCmpLt - less than comparisons */
1861 /*-----------------------------------------------------------------*/
1862 static void genCmpLt (iCode *ic, iCode *ifx)
1864 operand *left, *right, *result;
1865 link *letype , *retype;
1869 right= IC_RIGHT(ic);
1870 result = IC_RESULT(ic);
1872 letype = getSpec(operandType(left));
1873 retype =getSpec(operandType(right));
1874 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1876 /* assign the amsops */
1877 aopOp (left,ic,FALSE);
1878 aopOp (right,ic,FALSE);
1879 aopOp (result,ic,TRUE);
1881 genCmp(left, right, result, ifx, sign);
1883 freeAsmop(left,NULL,ic);
1884 freeAsmop(right,NULL,ic);
1885 freeAsmop(result,NULL,ic);
1888 /*-----------------------------------------------------------------*/
1889 /* gencjneshort - compare and jump if not equal */
1890 /*-----------------------------------------------------------------*/
1891 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1893 int size = max(AOP_SIZE(left),AOP_SIZE(right));
1895 unsigned long lit = 0L;
1897 /* Swap the left and right if it makes the computation easier */
1898 if (AOP_TYPE(left) == AOP_LIT) {
1904 if(AOP_TYPE(right) == AOP_LIT)
1905 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1907 /* if the right side is a literal then anything goes */
1908 if (AOP_TYPE(right) == AOP_LIT &&
1909 AOP_TYPE(left) != AOP_DIR ) {
1911 emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1912 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1913 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1917 /* if the right side is in a register or in direct space or
1918 if the left is a pointer register & right is not */
1919 else if (AOP_TYPE(right) == AOP_REG ||
1920 AOP_TYPE(right) == AOP_DIR ||
1921 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1923 MOVA(aopGet(AOP(left),offset,FALSE));
1924 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1925 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1927 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1929 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1930 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1935 /* right is a pointer reg need both a & b */
1936 /* PENDING: is this required? */
1938 char *l = aopGet(AOP(left),offset,FALSE);
1939 MOVA(aopGet(AOP(right),offset,FALSE));
1940 emitcode("cp", "%s", l);
1941 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
1947 /*-----------------------------------------------------------------*/
1948 /* gencjne - compare and jump if not equal */
1949 /*-----------------------------------------------------------------*/
1950 static void gencjne(operand *left, operand *right, symbol *lbl)
1952 symbol *tlbl = newiTempLabel(NULL);
1954 gencjneshort(left, right, lbl);
1957 emitcode("ld","a,%s",one);
1958 emitcode("jp", LABEL_STR ,tlbl->key+100);
1959 emitcode("", LABEL_STR ":",lbl->key+100);
1960 emitcode("xor","a,a");
1961 emitcode("", LABEL_STR ":",tlbl->key+100);
1964 /*-----------------------------------------------------------------*/
1965 /* genCmpEq - generates code for equal to */
1966 /*-----------------------------------------------------------------*/
1967 static void genCmpEq (iCode *ic, iCode *ifx)
1969 operand *left, *right, *result;
1971 aopOp((left=IC_LEFT(ic)),ic,FALSE);
1972 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1973 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1975 /* Swap operands if it makes the operation easier. ie if:
1976 1. Left is a literal.
1978 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1979 operand *t = IC_RIGHT(ic);
1980 IC_RIGHT(ic) = IC_LEFT(ic);
1984 if (ifx && !AOP_SIZE(result)){
1986 /* if they are both bit variables */
1987 if (AOP_TYPE(left) == AOP_CRY &&
1988 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1991 tlbl = newiTempLabel(NULL);
1992 gencjneshort(left, right, tlbl);
1993 if ( IC_TRUE(ifx) ) {
1994 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
1995 emitcode("", LABEL_STR ":",tlbl->key+100);
1997 /* PENDING: do this better */
1998 symbol *lbl = newiTempLabel(NULL);
1999 emitcode("jp", LABEL_STR ,lbl->key+100);
2000 emitcode("", LABEL_STR ":",tlbl->key+100);
2001 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2002 emitcode("", LABEL_STR ":",lbl->key+100);
2005 /* mark the icode as generated */
2010 /* if they are both bit variables */
2011 if (AOP_TYPE(left) == AOP_CRY &&
2012 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2015 gencjne(left,right,newiTempLabel(NULL));
2016 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2020 genIfxJump(ifx,"a");
2023 /* if the result is used in an arithmetic operation
2024 then put the result in place */
2025 if (AOP_TYPE(result) != AOP_CRY) {
2028 /* leave the result in acc */
2032 freeAsmop(left,NULL,ic);
2033 freeAsmop(right,NULL,ic);
2034 freeAsmop(result,NULL,ic);
2037 /*-----------------------------------------------------------------*/
2038 /* ifxForOp - returns the icode containing the ifx for operand */
2039 /*-----------------------------------------------------------------*/
2040 static iCode *ifxForOp ( operand *op, iCode *ic )
2042 /* if true symbol then needs to be assigned */
2043 if (IS_TRUE_SYMOP(op))
2046 /* if this has register type condition and
2047 the next instruction is ifx with the same operand
2048 and live to of the operand is upto the ifx only then */
2050 ic->next->op == IFX &&
2051 IC_COND(ic->next)->key == op->key &&
2052 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2058 /*-----------------------------------------------------------------*/
2059 /* genAndOp - for && operation */
2060 /*-----------------------------------------------------------------*/
2061 static void genAndOp (iCode *ic)
2063 operand *left,*right, *result;
2066 /* note here that && operations that are in an if statement are
2067 taken away by backPatchLabels only those used in arthmetic
2068 operations remain */
2069 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2070 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2071 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2073 /* if both are bit variables */
2074 if (AOP_TYPE(left) == AOP_CRY &&
2075 AOP_TYPE(right) == AOP_CRY ) {
2078 tlbl = newiTempLabel(NULL);
2080 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2082 emitcode("", LABEL_STR ":",tlbl->key+100);
2086 freeAsmop(left,NULL,ic);
2087 freeAsmop(right,NULL,ic);
2088 freeAsmop(result,NULL,ic);
2091 /*-----------------------------------------------------------------*/
2092 /* genOrOp - for || operation */
2093 /*-----------------------------------------------------------------*/
2094 static void genOrOp (iCode *ic)
2096 operand *left,*right, *result;
2099 /* note here that || operations that are in an
2100 if statement are taken away by backPatchLabels
2101 only those used in arthmetic operations remain */
2102 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2103 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2104 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2106 /* if both are bit variables */
2107 if (AOP_TYPE(left) == AOP_CRY &&
2108 AOP_TYPE(right) == AOP_CRY ) {
2111 tlbl = newiTempLabel(NULL);
2113 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2115 emitcode("", LABEL_STR,tlbl->key+100);
2119 freeAsmop(left,NULL,ic);
2120 freeAsmop(right,NULL,ic);
2121 freeAsmop(result,NULL,ic);
2124 /*-----------------------------------------------------------------*/
2125 /* isLiteralBit - test if lit == 2^n */
2126 /*-----------------------------------------------------------------*/
2127 int isLiteralBit(unsigned long lit)
2129 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2130 0x100L,0x200L,0x400L,0x800L,
2131 0x1000L,0x2000L,0x4000L,0x8000L,
2132 0x10000L,0x20000L,0x40000L,0x80000L,
2133 0x100000L,0x200000L,0x400000L,0x800000L,
2134 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2135 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2138 for(idx = 0; idx < 32; idx++)
2144 /*-----------------------------------------------------------------*/
2145 /* genAnd - code for and */
2146 /*-----------------------------------------------------------------*/
2147 static void genAnd (iCode *ic, iCode *ifx)
2149 operand *left, *right, *result;
2151 unsigned long lit = 0L;
2154 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2155 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2156 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2159 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2161 AOP_TYPE(left), AOP_TYPE(right));
2162 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2164 AOP_SIZE(left), AOP_SIZE(right));
2167 /* if left is a literal & right is not then exchange them */
2168 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2169 AOP_NEEDSACC(left)) {
2170 operand *tmp = right ;
2175 /* if result = right then exchange them */
2176 if(sameRegs(AOP(result),AOP(right))){
2177 operand *tmp = right ;
2182 /* if right is bit then exchange them */
2183 if (AOP_TYPE(right) == AOP_CRY &&
2184 AOP_TYPE(left) != AOP_CRY){
2185 operand *tmp = right ;
2189 if(AOP_TYPE(right) == AOP_LIT)
2190 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2192 size = AOP_SIZE(result);
2194 if (AOP_TYPE(left) == AOP_CRY){
2199 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2200 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2201 if((AOP_TYPE(right) == AOP_LIT) &&
2202 (AOP_TYPE(result) == AOP_CRY) &&
2203 (AOP_TYPE(left) != AOP_CRY)) {
2204 int posbit = isLiteralBit(lit);
2208 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2212 emitcode("mov","c,acc.%d",posbit&0x07);
2217 sprintf(buffer, "%d", posbit&0x07);
2218 genIfxJump(ifx, buffer);
2226 symbol *tlbl = newiTempLabel(NULL);
2227 int sizel = AOP_SIZE(left);
2230 emitcode("setb","c");
2233 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2234 MOVA( aopGet(AOP(left),offset,FALSE));
2236 if((posbit = isLiteralBit(bytelit)) != 0) {
2238 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2241 if(bytelit != 0x0FFL)
2242 emitcode("and","a,%s",
2243 aopGet(AOP(right),offset,FALSE));
2244 emitcode("jr","nz, %05d$",tlbl->key+100);
2249 // bit = left & literal
2251 emitcode("clr","c");
2252 emitcode("","%05d$:",tlbl->key+100);
2254 // if(left & literal)
2258 jmpTrueOrFalse(ifx, tlbl);
2269 /* if left is same as result */
2270 if(sameRegs(AOP(result),AOP(left))){
2271 for(;size--; offset++) {
2272 if(AOP_TYPE(right) == AOP_LIT){
2273 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2277 aopPut(AOP(result),zero,offset);
2279 MOVA(aopGet(AOP(left),offset,FALSE));
2280 emitcode("and","a,%s",
2281 aopGet(AOP(right),offset,FALSE));
2282 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2287 if (AOP_TYPE(left) == AOP_ACC) {
2291 MOVA(aopGet(AOP(right),offset,FALSE));
2292 emitcode("and","%s,a",
2293 aopGet(AOP(left),offset,FALSE));
2298 // left & result in different registers
2299 if(AOP_TYPE(result) == AOP_CRY){
2302 for(;(size--);offset++) {
2304 // result = left & right
2305 if(AOP_TYPE(right) == AOP_LIT){
2306 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2308 aopGet(AOP(left),offset,FALSE),
2311 } else if(bytelit == 0){
2312 aopPut(AOP(result),zero,offset);
2316 // faster than result <- left, anl result,right
2317 // and better if result is SFR
2318 if (AOP_TYPE(left) == AOP_ACC)
2319 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2321 MOVA(aopGet(AOP(right),offset,FALSE));
2322 emitcode("and","a,%s",
2323 aopGet(AOP(left),offset,FALSE));
2325 aopPut(AOP(result),"a",offset);
2332 freeAsmop(left,NULL,ic);
2333 freeAsmop(right,NULL,ic);
2334 freeAsmop(result,NULL,ic);
2337 /*-----------------------------------------------------------------*/
2338 /* genOr - code for or */
2339 /*-----------------------------------------------------------------*/
2340 static void genOr (iCode *ic, iCode *ifx)
2342 operand *left, *right, *result;
2344 unsigned long lit = 0L;
2346 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2347 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2348 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2351 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2353 AOP_TYPE(left), AOP_TYPE(right));
2354 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2356 AOP_SIZE(left), AOP_SIZE(right));
2359 /* if left is a literal & right is not then exchange them */
2360 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2361 AOP_NEEDSACC(left)) {
2362 operand *tmp = right ;
2367 /* if result = right then exchange them */
2368 if(sameRegs(AOP(result),AOP(right))){
2369 operand *tmp = right ;
2374 /* if right is bit then exchange them */
2375 if (AOP_TYPE(right) == AOP_CRY &&
2376 AOP_TYPE(left) != AOP_CRY){
2377 operand *tmp = right ;
2381 if(AOP_TYPE(right) == AOP_LIT)
2382 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2384 size = AOP_SIZE(result);
2386 if (AOP_TYPE(left) == AOP_CRY){
2391 if((AOP_TYPE(right) == AOP_LIT) &&
2392 (AOP_TYPE(result) == AOP_CRY) &&
2393 (AOP_TYPE(left) != AOP_CRY)){
2398 /* if left is same as result */
2399 if(sameRegs(AOP(result),AOP(left))){
2400 for(;size--; offset++) {
2401 if(AOP_TYPE(right) == AOP_LIT){
2402 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2405 emitcode("or","%s,%s; 5",
2406 aopGet(AOP(left),offset,FALSE),
2407 aopGet(AOP(right),offset,FALSE));
2409 if (AOP_TYPE(left) == AOP_ACC)
2410 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2412 MOVA(aopGet(AOP(right),offset,FALSE));
2413 emitcode("or","a,%s ; 7",
2414 aopGet(AOP(left),offset,FALSE));
2415 aopPut(AOP(result),"a ; 8",0);
2420 // left & result in different registers
2421 if(AOP_TYPE(result) == AOP_CRY){
2423 } else for(;(size--);offset++){
2425 // result = left & right
2426 if(AOP_TYPE(right) == AOP_LIT){
2427 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2429 aopGet(AOP(left),offset,FALSE),
2434 // faster than result <- left, anl result,right
2435 // and better if result is SFR
2436 if (AOP_TYPE(left) == AOP_ACC)
2437 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2439 MOVA(aopGet(AOP(right),offset,FALSE));
2440 emitcode("or","a,%s",
2441 aopGet(AOP(left),offset,FALSE));
2443 aopPut(AOP(result),"a",offset);
2444 /* PENDING: something weird is going on here. Add exception. */
2445 if (AOP_TYPE(result) == AOP_ACC)
2451 freeAsmop(left,NULL,ic);
2452 freeAsmop(right,NULL,ic);
2453 freeAsmop(result,NULL,ic);
2456 /*-----------------------------------------------------------------*/
2457 /* genXor - code for xclusive or */
2458 /*-----------------------------------------------------------------*/
2459 static void genXor (iCode *ic, iCode *ifx)
2461 operand *left, *right, *result;
2463 unsigned long lit = 0L;
2465 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2466 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2467 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2469 /* if left is a literal & right is not then exchange them */
2470 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2471 AOP_NEEDSACC(left)) {
2472 operand *tmp = right ;
2477 /* if result = right then exchange them */
2478 if(sameRegs(AOP(result),AOP(right))){
2479 operand *tmp = right ;
2484 /* if right is bit then exchange them */
2485 if (AOP_TYPE(right) == AOP_CRY &&
2486 AOP_TYPE(left) != AOP_CRY){
2487 operand *tmp = right ;
2491 if(AOP_TYPE(right) == AOP_LIT)
2492 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2494 size = AOP_SIZE(result);
2496 if (AOP_TYPE(left) == AOP_CRY){
2501 if((AOP_TYPE(right) == AOP_LIT) &&
2502 (AOP_TYPE(result) == AOP_CRY) &&
2503 (AOP_TYPE(left) != AOP_CRY)){
2508 /* if left is same as result */
2509 if(sameRegs(AOP(result),AOP(left))){
2510 for(;size--; offset++) {
2511 if(AOP_TYPE(right) == AOP_LIT){
2512 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2515 MOVA(aopGet(AOP(right),offset,FALSE));
2516 emitcode("xor","a,%s",
2517 aopGet(AOP(left),offset,FALSE));
2518 aopPut(AOP(result),"a",0);
2521 if (AOP_TYPE(left) == AOP_ACC)
2522 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2524 MOVA(aopGet(AOP(right),offset,FALSE));
2525 emitcode("xor","a,%s",
2526 aopGet(AOP(left),offset,FALSE));
2527 aopPut(AOP(result),"a",0);
2532 // left & result in different registers
2533 if(AOP_TYPE(result) == AOP_CRY){
2535 } else for(;(size--);offset++){
2537 // result = left & right
2538 if(AOP_TYPE(right) == AOP_LIT){
2539 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2541 aopGet(AOP(left),offset,FALSE),
2546 // faster than result <- left, anl result,right
2547 // and better if result is SFR
2548 if (AOP_TYPE(left) == AOP_ACC)
2549 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2551 MOVA(aopGet(AOP(right),offset,FALSE));
2552 emitcode("xor","a,%s",
2553 aopGet(AOP(left),offset,FALSE));
2554 aopPut(AOP(result),"a",0);
2556 aopPut(AOP(result),"a",offset);
2561 freeAsmop(left,NULL,ic);
2562 freeAsmop(right,NULL,ic);
2563 freeAsmop(result,NULL,ic);
2566 /*-----------------------------------------------------------------*/
2567 /* genInline - write the inline code out */
2568 /*-----------------------------------------------------------------*/
2569 static void genInline (iCode *ic)
2571 char buffer[MAX_INLINEASM];
2575 inLine += (!options.asmpeep);
2576 strcpy(buffer,IC_INLINE(ic));
2578 /* emit each line as a code */
2597 /* emitcode("",buffer); */
2598 inLine -= (!options.asmpeep);
2601 /*-----------------------------------------------------------------*/
2602 /* genRRC - rotate right with carry */
2603 /*-----------------------------------------------------------------*/
2604 static void genRRC (iCode *ic)
2609 /*-----------------------------------------------------------------*/
2610 /* genRLC - generate code for rotate left with carry */
2611 /*-----------------------------------------------------------------*/
2612 static void genRLC (iCode *ic)
2617 /*-----------------------------------------------------------------*/
2618 /* shiftR2Left2Result - shift right two bytes from left to result */
2619 /*-----------------------------------------------------------------*/
2620 static void shiftR2Left2Result (operand *left, int offl,
2621 operand *result, int offr,
2622 int shCount, int sign)
2624 if(sameRegs(AOP(result), AOP(left)) &&
2625 ((offl + MSB16) == offr)){
2628 movLeft2Result(left, offl, result, offr, 0);
2629 movLeft2Result(left, offl+1, result, offr+1, 0);
2636 /* if (AOP(result)->type == AOP_REG) {*/
2639 symbol *tlbl , *tlbl1;
2642 /* Left is already in result - so now do the shift */
2644 emitcode("ld","a,#%u+1", shCount);
2645 tlbl = newiTempLabel(NULL);
2646 tlbl1 = newiTempLabel(NULL);
2647 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2648 emitcode("", LABEL_STR ":",tlbl->key+100);
2651 emitcode("or", "a,a");
2654 l = aopGet(AOP(result), --offset, FALSE);
2655 emitcode("rr","%s", l);
2658 emitcode("", LABEL_STR ":",tlbl1->key+100);
2659 emitcode("dec", "a");
2660 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2665 /*-----------------------------------------------------------------*/
2666 /* shiftL2Left2Result - shift left two bytes from left to result */
2667 /*-----------------------------------------------------------------*/
2668 static void shiftL2Left2Result (operand *left, int offl,
2669 operand *result, int offr, int shCount)
2671 if(sameRegs(AOP(result), AOP(left)) &&
2672 ((offl + MSB16) == offr)){
2675 /* Copy left into result */
2676 movLeft2Result(left, offl, result, offr, 0);
2677 movLeft2Result(left, offl+1, result, offr+1, 0);
2679 /* PENDING: for now just see if it'll work. */
2680 /*if (AOP(result)->type == AOP_REG) { */
2684 symbol *tlbl , *tlbl1;
2687 /* Left is already in result - so now do the shift */
2689 emitcode("ld","a,#%u+1", shCount);
2690 tlbl = newiTempLabel(NULL);
2691 tlbl1 = newiTempLabel(NULL);
2692 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2693 emitcode("", LABEL_STR ":",tlbl->key+100);
2696 emitcode("or", "a,a");
2698 l = aopGet(AOP(result),offset++,FALSE);
2699 emitcode("rl","%s", l);
2702 emitcode("", LABEL_STR ":",tlbl1->key+100);
2703 emitcode("dec", "a");
2704 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2709 /*-----------------------------------------------------------------*/
2710 /* AccRol - rotate left accumulator by known count */
2711 /*-----------------------------------------------------------------*/
2712 static void AccRol (int shCount)
2714 shCount &= 0x0007; // shCount : 0..7
2751 /*-----------------------------------------------------------------*/
2752 /* AccLsh - left shift accumulator by known count */
2753 /*-----------------------------------------------------------------*/
2754 static void AccLsh (int shCount)
2758 emitcode("add","a,a");
2761 emitcode("add","a,a");
2762 emitcode("add","a,a");
2764 /* rotate left accumulator */
2766 /* and kill the lower order bits */
2767 emitcode("and","a,#0x%02x", SLMask[shCount]);
2772 /*-----------------------------------------------------------------*/
2773 /* shiftL1Left2Result - shift left one byte from left to result */
2774 /*-----------------------------------------------------------------*/
2775 static void shiftL1Left2Result (operand *left, int offl,
2776 operand *result, int offr, int shCount)
2779 l = aopGet(AOP(left),offl,FALSE);
2781 /* shift left accumulator */
2783 aopPut(AOP(result),"a",offr);
2787 /*-----------------------------------------------------------------*/
2788 /* genlshTwo - left shift two bytes by known amount != 0 */
2789 /*-----------------------------------------------------------------*/
2790 static void genlshTwo (operand *result,operand *left, int shCount)
2792 int size = AOP_SIZE(result);
2796 /* if shCount >= 8 */
2802 movLeft2Result(left, LSB, result, MSB16, 0);
2803 aopPut(AOP(result),zero, 0);
2804 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2807 movLeft2Result(left, LSB, result, MSB16, 0);
2808 aopPut(AOP(result),zero, 0);
2811 aopPut(AOP(result),zero,LSB);
2813 /* 1 <= shCount <= 7 */
2819 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2824 /*-----------------------------------------------------------------*/
2825 /* genlshOne - left shift a one byte quantity by known count */
2826 /*-----------------------------------------------------------------*/
2827 static void genlshOne (operand *result, operand *left, int shCount)
2829 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2832 /*-----------------------------------------------------------------*/
2833 /* genLeftShiftLiteral - left shifting by known count */
2834 /*-----------------------------------------------------------------*/
2835 static void genLeftShiftLiteral (operand *left,
2840 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2843 freeAsmop(right,NULL,ic);
2845 aopOp(left,ic,FALSE);
2846 aopOp(result,ic,FALSE);
2848 size = getSize(operandType(result));
2851 emitcode("; shift left ","result %d, left %d",size,
2855 /* I suppose that the left size >= result size */
2860 else if(shCount >= (size * 8))
2862 aopPut(AOP(result),zero,size);
2866 genlshOne (result,left,shCount);
2869 genlshTwo (result,left,shCount);
2878 freeAsmop(left,NULL,ic);
2879 freeAsmop(result,NULL,ic);
2882 /*-----------------------------------------------------------------*/
2883 /* genLeftShift - generates code for left shifting */
2884 /*-----------------------------------------------------------------*/
2885 static void genLeftShift (iCode *ic)
2889 symbol *tlbl , *tlbl1;
2890 operand *left,*right, *result;
2892 right = IC_RIGHT(ic);
2894 result = IC_RESULT(ic);
2896 aopOp(right,ic,FALSE);
2898 /* if the shift count is known then do it
2899 as efficiently as possible */
2900 if (AOP_TYPE(right) == AOP_LIT) {
2901 genLeftShiftLiteral (left,right,result,ic);
2905 /* shift count is unknown then we have to form a loop get the loop
2906 count in B : Note: we take only the lower order byte since
2907 shifting more that 32 bits make no sense anyway, ( the largest
2908 size of an object can be only 32 bits ) */
2909 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2910 emitcode("inc","a");
2911 freeAsmop (right,NULL,ic);
2912 aopOp(left,ic,FALSE);
2913 aopOp(result,ic,FALSE);
2915 /* now move the left to the result if they are not the
2918 if (!sameRegs(AOP(left),AOP(result))) {
2920 size = AOP_SIZE(result);
2923 l = aopGet(AOP(left),offset,FALSE);
2924 aopPut(AOP(result),l,offset);
2929 size = AOP_SIZE(result);
2932 l = aopGet(AOP(left),offset,FALSE);
2933 aopPut(AOP(result),l,offset);
2939 tlbl = newiTempLabel(NULL);
2940 size = AOP_SIZE(result);
2942 tlbl1 = newiTempLabel(NULL);
2944 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2945 emitcode("", LABEL_STR ":",tlbl->key+100);
2946 l = aopGet(AOP(result),offset,FALSE);
2947 emitcode("or", "a,a");
2949 l = aopGet(AOP(result),offset++,FALSE);
2950 emitcode("rl","%s", l);
2952 emitcode("", LABEL_STR ":",tlbl1->key+100);
2953 emitcode("dec", "a");
2954 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2956 freeAsmop(left,NULL,ic);
2957 freeAsmop(result,NULL,ic);
2960 /* genlshTwo - left shift two bytes by known amount != 0 */
2961 /*-----------------------------------------------------------------*/
2962 static void genrshOne (operand *result,operand *left, int shCount)
2965 int size = AOP_SIZE(result);
2971 l = aopGet(AOP(left),0,FALSE);
2972 if (AOP(result)->type == AOP_REG) {
2973 aopPut(AOP(result), l, 0);
2974 l = aopGet(AOP(result), 0, FALSE);
2976 emitcode("srl", "%s", l);
2981 emitcode("srl", "a");
2983 aopPut(AOP(result),"a",0);
2987 /*-----------------------------------------------------------------*/
2988 /* AccRsh - right shift accumulator by known count */
2989 /*-----------------------------------------------------------------*/
2990 static void AccRsh (int shCount)
2997 /* rotate right accumulator */
2998 AccRol(8 - shCount);
2999 /* and kill the higher order bits */
3000 emitcode("and","a,#0x%02x", SRMask[shCount]);
3005 /*-----------------------------------------------------------------*/
3006 /* shiftR1Left2Result - shift right one byte from left to result */
3007 /*-----------------------------------------------------------------*/
3008 static void shiftR1Left2Result (operand *left, int offl,
3009 operand *result, int offr,
3010 int shCount, int sign)
3012 MOVA(aopGet(AOP(left),offl,FALSE));
3019 aopPut(AOP(result),"a",offr);
3022 /*-----------------------------------------------------------------*/
3023 /* genrshTwo - right shift two bytes by known amount != 0 */
3024 /*-----------------------------------------------------------------*/
3025 static void genrshTwo (operand *result,operand *left,
3026 int shCount, int sign)
3028 /* if shCount >= 8 */
3033 shiftR1Left2Result(left, MSB16, result, LSB,
3037 movLeft2Result(left, MSB16, result, LSB, sign);
3038 aopPut(AOP(result),zero,1);
3041 /* 1 <= shCount <= 7 */
3043 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3047 /*-----------------------------------------------------------------*/
3048 /* genRightShiftLiteral - left shifting by known count */
3049 /*-----------------------------------------------------------------*/
3050 static void genRightShiftLiteral (operand *left,
3055 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3058 freeAsmop(right,NULL,ic);
3060 aopOp(left,ic,FALSE);
3061 aopOp(result,ic,FALSE);
3063 size = getSize(operandType(result));
3065 emitcode("; shift right ","result %d, left %d",size,
3068 /* I suppose that the left size >= result size */
3073 else if(shCount >= (size * 8))
3075 aopPut(AOP(result),zero,size);
3079 genrshOne(result, left, shCount);
3082 /* PENDING: sign support */
3083 genrshTwo(result, left, shCount, FALSE);
3092 freeAsmop(left,NULL,ic);
3093 freeAsmop(result,NULL,ic);
3096 /*-----------------------------------------------------------------*/
3097 /* genRightShift - generate code for right shifting */
3098 /*-----------------------------------------------------------------*/
3099 static void genRightShift (iCode *ic)
3101 operand *left,*right, *result;
3103 right = IC_RIGHT(ic);
3105 result = IC_RESULT(ic);
3107 aopOp(right,ic,FALSE);
3109 /* if the shift count is known then do it
3110 as efficiently as possible */
3111 if (AOP_TYPE(right) == AOP_LIT) {
3112 genRightShiftLiteral (left,right,result,ic);
3120 /*-----------------------------------------------------------------*/
3121 /* genGenPointerGet - gget value from generic pointer space */
3122 /*-----------------------------------------------------------------*/
3123 static void genGenPointerGet (operand *left,
3124 operand *result, iCode *ic)
3127 link *retype = getSpec(operandType(result));
3129 aopOp(left,ic,FALSE);
3130 aopOp(result,ic,FALSE);
3132 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3134 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3135 aopPut(AOP(result),"a", 0);
3136 freeAsmop(left,NULL,ic);
3140 /* For now we always load into IY */
3141 /* if this is remateriazable */
3142 if (AOP_TYPE(left) == AOP_IMMD)
3143 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3144 else { /* we need to get it byte by byte */
3145 emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3146 emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3148 /* so iy now contains the address */
3149 freeAsmop(left,NULL,ic);
3151 /* if bit then unpack */
3152 if (IS_BITVAR(retype)) {
3156 size = AOP_SIZE(result);
3160 /* PENDING: make this better */
3161 if (AOP(result)->type == AOP_REG) {
3162 aopPut(AOP(result),"(hl)",offset++);
3165 emitcode("ld", "a,(hl)", offset);
3166 aopPut(AOP(result),"a",offset++);
3169 emitcode("inc", "hl");
3175 freeAsmop(result,NULL,ic);
3178 /*-----------------------------------------------------------------*/
3179 /* genPointerGet - generate code for pointer get */
3180 /*-----------------------------------------------------------------*/
3181 static void genPointerGet (iCode *ic)
3183 operand *left, *result ;
3187 result = IC_RESULT(ic) ;
3189 /* depending on the type of pointer we need to
3190 move it to the correct pointer register */
3191 type = operandType(left);
3192 etype = getSpec(type);
3194 genGenPointerGet (left,result,ic);
3197 bool isRegOrLit(asmop *aop)
3199 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3204 /*-----------------------------------------------------------------*/
3205 /* genGenPointerSet - stores the value into a pointer location */
3206 /*-----------------------------------------------------------------*/
3207 static void genGenPointerSet (operand *right,
3208 operand *result, iCode *ic)
3211 link *retype = getSpec(operandType(right));
3213 aopOp(result,ic,FALSE);
3214 aopOp(right,ic,FALSE);
3216 /* Handle the exceptions first */
3217 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3219 char *l = aopGet(AOP(right), 0, FALSE);
3221 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3222 freeAsmop(result,NULL,ic);
3226 /* if the operand is already in dptr
3227 then we do nothing else we move the value to dptr */
3228 if (AOP_TYPE(result) != AOP_STR) {
3229 /* if this is remateriazable */
3230 if (AOP_TYPE(result) == AOP_IMMD) {
3231 emitcode("", "; Error 2");
3232 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3234 else { /* we need to get it byte by byte */
3235 /* PENDING: do this better */
3236 emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3237 emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3240 /* so hl know contains the address */
3241 freeAsmop(result,NULL,ic);
3243 /* if bit then unpack */
3244 if (IS_BITVAR(retype)) {
3248 size = AOP_SIZE(right);
3252 char *l = aopGet(AOP(right),offset,FALSE);
3254 if (isRegOrLit(AOP(right))) {
3255 emitcode("ld", "(hl),%s", l);
3259 emitcode("ld", "(hl),a", offset);
3262 emitcode("inc", "hl");
3268 freeAsmop(right,NULL,ic);
3271 /*-----------------------------------------------------------------*/
3272 /* genPointerSet - stores the value into a pointer location */
3273 /*-----------------------------------------------------------------*/
3274 static void genPointerSet (iCode *ic)
3276 operand *right, *result ;
3279 right = IC_RIGHT(ic);
3280 result = IC_RESULT(ic) ;
3282 /* depending on the type of pointer we need to
3283 move it to the correct pointer register */
3284 type = operandType(result);
3285 etype = getSpec(type);
3287 genGenPointerSet (right,result,ic);
3290 /*-----------------------------------------------------------------*/
3291 /* genIfx - generate code for Ifx statement */
3292 /*-----------------------------------------------------------------*/
3293 static void genIfx (iCode *ic, iCode *popIc)
3295 operand *cond = IC_COND(ic);
3298 aopOp(cond,ic,FALSE);
3300 /* get the value into acc */
3301 if (AOP_TYPE(cond) != AOP_CRY)
3305 /* the result is now in the accumulator */
3306 freeAsmop(cond,NULL,ic);
3308 /* if there was something to be popped then do it */
3312 /* if the condition is a bit variable */
3313 if (isbit && IS_ITEMP(cond) &&
3315 genIfxJump(ic,SPIL_LOC(cond)->rname);
3317 if (isbit && !IS_ITEMP(cond))
3318 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3325 /*-----------------------------------------------------------------*/
3326 /* genAddrOf - generates code for address of */
3327 /*-----------------------------------------------------------------*/
3328 static void genAddrOf (iCode *ic)
3330 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3332 aopOp(IC_RESULT(ic),ic,FALSE);
3334 /* if the operand is on the stack then we
3335 need to get the stack offset of this
3338 /* if it has an offset then we need to compute it */
3339 emitcode("push", "de");
3340 emitcode("push", "ix");
3341 emitcode("pop", "hl");
3342 emitcode("ld", "de,#%d", sym->stack);
3343 emitcode("add", "hl,de");
3344 emitcode("pop", "de");
3347 emitcode("ld", "hl,#%s", sym->rname);
3349 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3350 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3352 freeAsmop(IC_RESULT(ic),NULL,ic);
3355 /*-----------------------------------------------------------------*/
3356 /* genAssign - generate code for assignment */
3357 /*-----------------------------------------------------------------*/
3358 static void genAssign (iCode *ic)
3360 operand *result, *right;
3362 unsigned long lit = 0L;
3364 result = IC_RESULT(ic);
3365 right = IC_RIGHT(ic) ;
3368 /* Dont bother assigning if they are the same */
3369 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3370 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3375 aopOp(right,ic,FALSE);
3376 aopOp(result,ic,TRUE);
3378 /* if they are the same registers */
3379 if (sameRegs(AOP(right),AOP(result))) {
3380 emitcode("", "; (registers are the same)");
3384 /* if the result is a bit */
3385 if (AOP_TYPE(result) == AOP_CRY) {
3390 size = AOP_SIZE(result);
3393 if(AOP_TYPE(right) == AOP_LIT)
3394 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3396 (AOP_TYPE(result) != AOP_REG) &&
3397 (AOP_TYPE(right) == AOP_LIT) &&
3398 !IS_FLOAT(operandType(right)) &&
3400 emitcode("xor","a,a");
3401 /* Work from the top down.
3402 Done this way so that we can use the cached copy of 0
3403 in A for a fast clear */
3405 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
3406 aopPut(AOP(result),"a",size);
3409 aopGet(AOP(right),size,FALSE),
3415 aopGet(AOP(right),offset,FALSE),
3422 freeAsmop(right,NULL,ic);
3423 freeAsmop(result,NULL,ic);
3426 /*-----------------------------------------------------------------*/
3427 /* genJumpTab - genrates code for jump table */
3428 /*-----------------------------------------------------------------*/
3429 static void genJumpTab (iCode *ic)
3434 aopOp(IC_JTCOND(ic),ic,FALSE);
3435 /* get the condition into accumulator */
3436 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3438 emitcode("push", "de");
3439 emitcode("ld", "e,%s", l);
3440 emitcode("ld", "d,#0");
3441 jtab = newiTempLabel(NULL);
3442 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3443 emitcode("add", "hl,de");
3444 emitcode("add", "hl,de");
3445 freeAsmop(IC_JTCOND(ic),NULL,ic);
3446 emitcode("pop", "de");
3447 emitcode("jp", "(hl)");
3448 emitcode("","%05d$:",jtab->key+100);
3449 /* now generate the jump labels */
3450 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3451 jtab = setNextItem(IC_JTLABELS(ic)))
3452 emitcode("jp", LABEL_STR, jtab->key+100);
3455 /*-----------------------------------------------------------------*/
3456 /* genCast - gen code for casting */
3457 /*-----------------------------------------------------------------*/
3458 static void genCast (iCode *ic)
3460 operand *result = IC_RESULT(ic);
3461 link *ctype = operandType(IC_LEFT(ic));
3462 operand *right = IC_RIGHT(ic);
3465 /* if they are equivalent then do nothing */
3466 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3469 aopOp(right,ic,FALSE) ;
3470 aopOp(result,ic,FALSE);
3472 /* if the result is a bit */
3473 if (AOP_TYPE(result) == AOP_CRY) {
3477 /* if they are the same size : or less */
3478 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3480 /* if they are in the same place */
3481 if (sameRegs(AOP(right),AOP(result)))
3484 /* if they in different places then copy */
3485 size = AOP_SIZE(result);
3489 aopGet(AOP(right),offset,FALSE),
3496 /* if the result is of type pointer */
3497 if (IS_PTR(ctype)) {
3501 /* so we now know that the size of destination is greater
3502 than the size of the source */
3503 /* we move to result for the size of source */
3504 size = AOP_SIZE(right);
3508 aopGet(AOP(right),offset,FALSE),
3513 /* now depending on the sign of the destination */
3514 size = AOP_SIZE(result) - AOP_SIZE(right);
3515 /* Unsigned or not an integral type - right fill with zeros */
3516 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3518 aopPut(AOP(result),zero,offset++);
3520 /* we need to extend the sign :{ */
3521 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3524 emitcode("", "; genCast: sign extend untested.");
3525 emitcode("rla", "");
3526 emitcode("sbc", "a,a");
3528 aopPut(AOP(result),"a",offset++);
3532 freeAsmop(right, NULL, ic);
3533 freeAsmop(result, NULL, ic);
3536 /*-----------------------------------------------------------------*/
3537 /* genReceive - generate code for a receive iCode */
3538 /*-----------------------------------------------------------------*/
3539 static void genReceive (iCode *ic)
3541 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3542 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3543 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3547 aopOp(IC_RESULT(ic),ic,FALSE);
3549 assignResultValue(IC_RESULT(ic));
3552 freeAsmop(IC_RESULT(ic),NULL,ic);
3555 /*-----------------------------------------------------------------*/
3556 /* genZ80Code - generate code for Z80 based controllers */
3557 /*-----------------------------------------------------------------*/
3558 void genZ80Code (iCode *lic)
3563 lineHead = lineCurr = NULL;
3565 /* if debug information required */
3566 if (options.debug && currFunc) {
3567 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3569 if (IS_STATIC(currFunc->etype))
3570 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3572 emitcode("","G$%s$0$0 ==.",currFunc->name);
3575 /* stack pointer name */
3579 for (ic = lic ; ic ; ic = ic->next ) {
3581 if ( cln != ic->lineno ) {
3582 if ( options.debug ) {
3584 emitcode("","C$%s$%d$%d$%d ==.",
3585 ic->filename,ic->lineno,
3586 ic->level,ic->block);
3589 emitcode(";","%s %d",ic->filename,ic->lineno);
3592 /* if the result is marked as
3593 spilt and rematerializable or code for
3594 this has already been generated then
3596 if (resultRemat(ic) || ic->generated )
3599 /* depending on the operation */
3602 emitcode("", "; genNot");
3607 emitcode("", "; genCpl");
3612 emitcode("", "; genUminus");
3617 emitcode("", "; genIpush");
3622 /* IPOP happens only when trying to restore a
3623 spilt live range, if there is an ifx statement
3624 following this pop then the if statement might
3625 be using some of the registers being popped which
3626 would destory the contents of the register so
3627 we need to check for this condition and handle it */
3629 ic->next->op == IFX &&
3630 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3631 emitcode("", "; genIfx");
3632 genIfx (ic->next,ic);
3635 emitcode("", "; genIpop");
3641 emitcode("", "; genCall");
3646 emitcode("", "; genPcall");
3651 emitcode("", "; genFunction");
3656 emitcode("", "; genEndFunction");
3657 genEndFunction (ic);
3661 emitcode("", "; genRet");
3666 emitcode("", "; genLabel");
3671 emitcode("", "; genGoto");
3676 emitcode("", "; genPlus");
3681 emitcode("", "; genMinus");
3686 emitcode("", "; genMult");
3691 emitcode("", "; genDiv");
3696 emitcode("", "; genMod");
3701 emitcode("", "; genCmpGt");
3702 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3706 emitcode("", "; genCmpLt");
3707 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3714 /* note these two are xlated by algebraic equivalence
3715 during parsing SDCC.y */
3716 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3717 "got '>=' or '<=' shouldn't have come here");
3721 emitcode("", "; genCmpEq");
3722 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3726 emitcode("", "; genAndOp");
3731 emitcode("", "; genOrOp");
3736 emitcode("", "; genXor");
3737 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3741 emitcode("", "; genOr");
3742 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3746 emitcode("", "; genAnd");
3747 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3751 emitcode("", "; genInline");
3756 emitcode("", "; genRRC");
3761 emitcode("", "; genRLC");
3766 emitcode("", "; genHBIT");
3770 emitcode("", "; genLeftShift");
3775 emitcode("", "; genRightShift");
3779 case GET_VALUE_AT_ADDRESS:
3780 emitcode("", "; genPointerGet");
3786 if (POINTER_SET(ic)) {
3787 emitcode("", "; genAssign (pointer)");
3791 emitcode("", "; genAssign");
3797 emitcode("", "; genIfx");
3802 emitcode("", "; genAddrOf");
3807 emitcode("", "; genJumpTab");
3812 emitcode("", "; genCast");
3817 emitcode("", "; genReceive");
3822 emitcode("", "; addSet");
3823 addSet(&sendSet,ic);
3828 /* piCode(ic,stdout); */
3834 /* now we are ready to call the
3835 peep hole optimizer */
3836 /* if (!options.nopeep)
3837 peepHole (&lineHead); */
3839 /* now do the actual printing */
3840 printLine (lineHead,codeOutFile);