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
21 Michael Hope <michaelh@earthling.net> 2000
22 Based on the mcs51 generator -
23 Sandeep Dutta . sandeep.dutta@usa.net (1998)
24 and - Jean-Louis VERN.jlvern@writeme.com (1999)
26 This program is free software; you can redistribute it and/or modify it
27 under the terms of the GNU General Public License as published by the
28 Free Software Foundation; either version 2, or (at your option) any
31 This program is distributed in the hope that it will be useful,
32 but WITHOUT ANY WARRANTY; without even the implied warranty of
33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 GNU General Public License for more details.
37 You should have received a copy of the GNU General Public License
38 along with this program; if not, write to the Free Software
39 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 In other words, you are welcome to use, share and improve this program.
42 You are forbidden to forbid anyone else to use, share and improve
43 what you give them. Help stamp out software-hoarding!
45 -------------------------------------------------------------------------*/
52 #ifdef HAVE_SYS_ISA_DEFS_H
53 #include <sys/isa_defs.h>
57 #include "SDCCpeeph.h"
61 /* this is the down and dirty file with all kinds of kludgy & hacky
62 stuff. This is what it is all about CODE GENERATION for a specific MCU.
63 Some of the routines may be reusable, will have to see */
66 static char *_z80_return[] = {"l", "h", "e", "d" };
67 static char *_gbz80_return[] = { "e", "d", "l", "h" };
68 static char **_fReturn;
74 static char *accUse[] = {"a" };
75 static char *hlUse[] = { "l", "h" };
81 extern int ptrRegReq ;
83 extern FILE *codeOutFile;
100 } _pairs[NUM_PAIRS] = {
105 { "iy", "iy.l?", "iy.h?" },
106 { "ix", "ix.l?", "ix.h?" }
109 #define RESULTONSTACK(x) \
110 (IC_RESULT(x) && IC_RESULT(x)->aop && \
111 IC_RESULT(x)->aop->type == AOP_STK )
113 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
114 #define CLRC emitcode("xor","a,a");
116 lineNode *lineHead = NULL;
117 lineNode *lineCurr = NULL;
119 static const unsigned char SLMask[] =
120 {0xFF ,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
121 static const unsigned char SRMask[] =
122 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
155 static char *aopGet(asmop *aop, int offset, bool bit16);
157 static void _tidyUp(char *buf)
159 /* Clean up the line so that it is 'prettier' */
160 if (strchr(buf, ':')) {
161 /* Is a label - cant do anything */
164 /* Change the first (and probably only) ' ' to a tab so
176 static void emit2(const char *szFormat, ...)
181 va_start(ap, szFormat);
183 tvsprintf(buffer, szFormat, ap);
186 lineCurr = (lineCurr ?
187 connectLine(lineCurr,newLineNode(buffer)) :
188 (lineHead = newLineNode(buffer)));
190 lineCurr->isInline = inLine;
191 lineCurr->isDebug = debugLine;
194 /*-----------------------------------------------------------------*/
195 /* emitcode - writes the code into a file : for now it is simple */
196 /*-----------------------------------------------------------------*/
197 void emitcode (const char *inst, const char *fmt, ...)
200 char lb[MAX_INLINEASM];
206 sprintf(lb,"%s\t",inst);
207 vsprintf(lb+(strlen(lb)),fmt,ap);
211 while (isspace(*lbp)) lbp++;
214 lineCurr = (lineCurr ?
215 connectLine(lineCurr,newLineNode(lb)) :
216 (lineHead = newLineNode(lb)));
217 lineCurr->isInline = inLine;
218 lineCurr->isDebug = debugLine;
235 emitcode("ld", "sp,ix");
236 emitcode("pop", "ix");
237 emitcode("pop", "de");
242 const char *getPairName(asmop *aop)
244 if (aop->type == AOP_REG) {
245 switch (aop->aopu.aop_reg[0]->rIdx) {
257 else if (aop->type == AOP_STR) {
258 switch (*aop->aopu.aop_str[0]) {
274 static PAIR_ID getPairId(asmop *aop)
276 if (aop->size == 2) {
277 if (aop->type == AOP_REG) {
278 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
281 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
284 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
288 if (aop->type == AOP_STR) {
289 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
292 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
295 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
303 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
304 bool isPair(asmop *aop)
306 return (getPairId(aop) != PAIR_INVALID);
309 bool isPtrPair(asmop *aop)
311 PAIR_ID pairId = getPairId(aop);
321 /** Push a register pair onto the stack */
322 void genPairPush(asmop *aop)
324 emitcode("push", "%s", getPairName(aop));
328 /*-----------------------------------------------------------------*/
329 /* newAsmop - creates a new asmOp */
330 /*-----------------------------------------------------------------*/
331 static asmop *newAsmop (short type)
335 ALLOC(aop,sizeof(asmop));
340 /*-----------------------------------------------------------------*/
341 /* aopForSym - for a true symbol */
342 /*-----------------------------------------------------------------*/
343 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool requires_a)
352 space = SPEC_OCLS(sym->etype);
354 /* if already has one */
358 /* Assign depending on the storage class */
359 if (sym->onStack || sym->iaccess) {
360 emitcode("", "; AOP_STK for %s", sym->rname);
361 sym->aop = aop = newAsmop(AOP_STK);
362 aop->size = getSize(sym->type);
363 aop->aopu.aop_stk = sym->stack;
367 /* special case for a function */
368 if (IS_FUNC(sym->type)) {
369 sym->aop = aop = newAsmop(AOP_IMMD);
370 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
371 strcpy(aop->aopu.aop_immd,sym->rname);
377 /* if it is in direct space */
378 if (IN_REGSP(space) && !requires_a) {
379 sym->aop = aop = newAsmop (AOP_SFR);
380 aop->aopu.aop_dir = sym->rname ;
381 aop->size = getSize(sym->type);
382 emitcode("", "; AOP_SFR for %s", sym->rname);
387 /* only remaining is far space */
388 /* in which case DPTR gets the address */
390 emitcode("", "; AOP_HL for %s", sym->rname);
391 sym->aop = aop = newAsmop(AOP_HL);
394 sym->aop = aop = newAsmop(AOP_IY);
396 aop->size = getSize(sym->type);
397 aop->aopu.aop_dir = sym->rname;
399 /* if it is in code space */
400 if (IN_CODESPACE(space))
406 /*-----------------------------------------------------------------*/
407 /* aopForRemat - rematerialzes an object */
408 /*-----------------------------------------------------------------*/
409 static asmop *aopForRemat (symbol *sym)
412 iCode *ic = sym->rematiCode;
413 asmop *aop = newAsmop(AOP_IMMD);
416 /* if plus or minus print the right hand side */
417 if (ic->op == '+' || ic->op == '-') {
418 /* PENDING: for re-target */
419 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
422 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
425 /* we reached the end */
426 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
430 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
431 strcpy(aop->aopu.aop_immd,buffer);
435 /*-----------------------------------------------------------------*/
436 /* regsInCommon - two operands have some registers in common */
437 /*-----------------------------------------------------------------*/
438 bool regsInCommon (operand *op1, operand *op2)
443 /* if they have registers in common */
444 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
447 sym1 = OP_SYMBOL(op1);
448 sym2 = OP_SYMBOL(op2);
450 if (sym1->nRegs == 0 || sym2->nRegs == 0)
453 for (i = 0 ; i < sym1->nRegs ; i++) {
458 for (j = 0 ; j < sym2->nRegs ;j++ ) {
462 if (sym2->regs[j] == sym1->regs[i])
470 /*-----------------------------------------------------------------*/
471 /* operandsEqu - equivalent */
472 /*-----------------------------------------------------------------*/
473 bool operandsEqu ( operand *op1, operand *op2)
477 /* if they not symbols */
478 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
481 sym1 = OP_SYMBOL(op1);
482 sym2 = OP_SYMBOL(op2);
484 /* if both are itemps & one is spilt
485 and the other is not then false */
486 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
487 sym1->isspilt != sym2->isspilt )
490 /* if they are the same */
494 if (strcmp(sym1->rname,sym2->rname) == 0)
498 /* if left is a tmp & right is not */
502 (sym1->usl.spillLoc == sym2))
509 (sym2->usl.spillLoc == sym1))
515 /*-----------------------------------------------------------------*/
516 /* sameRegs - two asmops have the same registers */
517 /*-----------------------------------------------------------------*/
518 bool sameRegs (asmop *aop1, asmop *aop2 )
522 if (aop1->type == AOP_SFR ||
523 aop2->type == AOP_SFR)
529 if (aop1->type != AOP_REG ||
530 aop2->type != AOP_REG )
533 if (aop1->size != aop2->size)
536 for (i = 0 ; i < aop1->size ; i++ )
537 if (aop1->aopu.aop_reg[i] !=
538 aop2->aopu.aop_reg[i] )
544 /*-----------------------------------------------------------------*/
545 /* aopOp - allocates an asmop for an operand : */
546 /*-----------------------------------------------------------------*/
547 static void aopOp (operand *op, iCode *ic, bool result, bool requires_a)
556 /* if this a literal */
557 if (IS_OP_LITERAL(op)) {
558 op->aop = aop = newAsmop(AOP_LIT);
559 aop->aopu.aop_lit = op->operand.valOperand;
560 aop->size = getSize(operandType(op));
564 /* if already has a asmop then continue */
568 /* if the underlying symbol has a aop */
569 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
570 op->aop = OP_SYMBOL(op)->aop;
574 /* if this is a true symbol */
575 if (IS_TRUE_SYMOP(op)) {
576 op->aop = aopForSym(ic, OP_SYMBOL(op), result, requires_a);
580 /* this is a temporary : this has
586 e) can be a return use only */
590 /* if the type is a conditional */
591 if (sym->regType == REG_CND) {
592 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
597 /* if it is spilt then two situations
599 b) has a spill location */
600 if (sym->isspilt || sym->nRegs == 0) {
601 /* rematerialize it NOW */
603 sym->aop = op->aop = aop =
605 aop->size = getSize(sym->type);
611 if (sym->accuse == ACCUSE_A) {
612 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
613 aop->size = getSize(sym->type);
614 for ( i = 0 ; i < 2 ; i++ )
615 aop->aopu.aop_str[i] = accUse[i];
617 else if (sym->accuse == ACCUSE_HL) {
619 aop = op->aop = sym->aop = newAsmop(AOP_HLREG);
620 aop->size = getSize(sym->type);
621 for ( i = 0 ; i < 2 ; i++ )
622 aop->aopu.aop_str[i] = hlUse[i];
631 aop = op->aop = sym->aop = newAsmop(AOP_STR);
632 aop->size = getSize(sym->type);
633 for ( i = 0 ; i < 4 ; i++ )
634 aop->aopu.aop_str[i] = _fReturn[i];
638 /* else spill location */
639 sym->aop = op->aop = aop =
640 aopForSym(ic,sym->usl.spillLoc,result, requires_a);
641 aop->size = getSize(sym->type);
645 /* must be in a register */
646 sym->aop = op->aop = aop = newAsmop(AOP_REG);
647 aop->size = sym->nRegs;
648 for ( i = 0 ; i < sym->nRegs ;i++)
649 aop->aopu.aop_reg[i] = sym->regs[i];
652 /*-----------------------------------------------------------------*/
653 /* freeAsmop - free up the asmop given to an operand */
654 /*----------------------------------------------------------------*/
655 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
673 /* all other cases just dealloc */
677 OP_SYMBOL(op)->aop = NULL;
678 /* if the symbol has a spill */
680 SPIL_LOC(op)->aop = NULL;
685 bool isLitWord(asmop *aop)
687 /* if (aop->size != 2)
698 char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
704 if (aop->size != 2 && aop->type != AOP_HL)
707 /* depending on type */
712 /* PENDING: for re-target */
714 tsprintf(s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
716 tsprintf(s, "%s + %d", aop->aopu.aop_immd, offset);
717 ALLOC_ATOMIC(rs,strlen(s)+1);
721 value * val = aop->aopu.aop_lit;
722 /* if it is a float then it gets tricky */
723 /* otherwise it is fairly simple */
724 if (!IS_FLOAT(val->type)) {
725 unsigned long v = floatFromVal(val);
729 tsprintf(buffer, "!immedword", v);
731 tsprintf(buffer, "!constword", v);
732 ALLOC_ATOMIC(rs,strlen(buffer)+1);
733 return strcpy (rs,buffer);
738 convertFloat(&f, floatFromVal(val));
740 tsprintf(buffer, "!immedword", f.w[offset/2]);
742 tsprintf(buffer, "!constword", f.w[offset/2]);
743 ALLOC_ATOMIC(rs,strlen(buffer)+1);
744 return strcpy (rs,buffer);
752 char *aopGetWord(asmop *aop, int offset)
754 return aopGetLitWordLong(aop, offset, TRUE);
757 bool isPtr(const char *s)
759 if (!strcmp(s, "hl"))
761 if (!strcmp(s, "ix"))
763 if (!strcmp(s, "iy"))
768 static void adjustPair(const char *pair, int *pold, int new)
772 while (*pold < new) {
773 emitcode("inc", "%s", pair);
776 while (*pold > new) {
777 emitcode("dec", "%s", pair);
782 static void spillPair(PAIR_ID pairId)
784 _G.pairs[pairId].last_type = AOP_INVALID;
785 _G.pairs[pairId].lit = NULL;
788 static void spillCached(void)
794 static bool requiresHL(asmop *aop)
805 static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
808 const char *pair = _pairs[pairId].name;
809 l = aopGetLitWordLong(left, 0, FALSE);
813 if (pairId == PAIR_HL || pairId == PAIR_IY) {
814 if (_G.pairs[pairId].last_type == left->type) {
815 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
816 if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
817 adjustPair(pair, &_G.pairs[pairId].offset, offset);
820 if (pairId == PAIR_IY && abs(offset)<127) {
826 _G.pairs[pairId].last_type = left->type;
827 _G.pairs[pairId].lit = gc_strdup(l);
828 _G.pairs[pairId].offset = offset;
830 if (IS_GB && pairId == PAIR_DE && 0) {
831 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
832 if (abs(_G.pairs[pairId].offset - offset) < 3) {
833 adjustPair(pair, &_G.pairs[pairId].offset, offset);
837 _G.pairs[pairId].last_type = left->type;
838 _G.pairs[pairId].lit = gc_strdup(l);
839 _G.pairs[pairId].offset = offset;
841 /* Both a lit on the right and a true symbol on the left */
843 emit2("ld %s,!hashedstr + %u", pair, l, offset);
845 emit2("ld %s,!hashedstr", pair, l);
848 static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
850 /* if this is remateriazable */
851 if (isLitWord(aop)) {
852 fetchLitPair(pairId, aop, offset);
854 else { /* we need to get it byte by byte */
855 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
856 aopGet(aop, offset, FALSE);
860 emit2("ld h,!immedbyte", 0);
868 emit2("; WARNING: mlh woosed out. This code is invalid.");
871 else if (IS_Z80 && aop->type == AOP_IY) {
872 /* Instead of fetching relative to IY, just grab directly
873 from the address IY refers to */
874 char *l = aopGetLitWordLong(aop, offset, FALSE);
876 emit2("ld %s,(%s)", _pairs[pairId].name, l);
879 emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE));
880 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, offset+1, FALSE));
882 /* PENDING: check? */
883 if (pairId == PAIR_HL)
888 static void fetchPair(PAIR_ID pairId, asmop *aop)
890 fetchPairLong(pairId, aop, 0);
893 static void fetchHL(asmop *aop)
895 fetchPair(PAIR_HL, aop);
898 static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
900 assert(pairId == PAIR_HL || pairId == PAIR_IY);
904 fetchLitPair(pairId, aop, 0);
907 fetchLitPair(pairId, aop, offset);
908 _G.pairs[pairId].offset = offset;
911 /* Doesnt include _G.stack.pushed */
912 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
913 if (aop->aopu.aop_stk > 0) {
914 abso += _G.stack.param_offset;
916 assert(pairId == PAIR_HL);
917 /* In some cases we can still inc or dec hl */
918 if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
919 adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
922 emit2("!ldahlsp", abso +_G.stack.pushed);
924 _G.pairs[pairId].offset = abso;
930 _G.pairs[pairId].last_type = aop->type;
933 static void emitLabel(int key)
935 emit2("!tlabeldef", key);
939 /*-----------------------------------------------------------------*/
940 /* aopGet - for fetching value of the aop */
941 /*-----------------------------------------------------------------*/
942 static char *aopGet(asmop *aop, int offset, bool bit16)
947 /* offset is greater than size then zero */
948 /* PENDING: this seems a bit screwed in some pointer cases. */
949 if (offset > (aop->size - 1) &&
950 aop->type != AOP_LIT)
953 /* depending on type */
956 /* PENDING: re-target */
958 tsprintf (s,"!immedwords", aop->aopu.aop_immd);
962 tsprintf(s, "!bankimmeds", aop->aopu.aop_immd);
965 tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
968 tsprintf(s, "!lsbimmeds", aop->aopu.aop_immd);
973 ALLOC_ATOMIC(rs,strlen(s)+1);
979 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
981 ALLOC_ATOMIC(rs,strlen(s)+1);
987 emitcode("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
989 ALLOC_ATOMIC(rs,strlen(s)+1);
994 return aop->aopu.aop_reg[offset]->name;
998 setupPair(PAIR_HL, aop, offset);
1000 return gc_strdup(s);
1004 setupPair(PAIR_IY, aop, offset);
1005 tsprintf(s,"!*iyx", offset);
1006 ALLOC_ATOMIC(rs,strlen(s)+1);
1012 setupPair(PAIR_HL, aop, offset);
1013 tsprintf(s, "!*hl");
1016 tsprintf(s,"!*ixx", aop->aopu.aop_stk+offset);
1018 ALLOC_ATOMIC(rs,strlen(s)+1);
1032 wassert(offset < 2);
1033 return aop->aopu.aop_str[offset];
1036 return aopLiteral (aop->aopu.aop_lit,offset);
1040 return aop->aopu.aop_str[offset];
1044 wassertl(0, "aopget got unsupported aop->type");
1048 bool isRegString(const char *s)
1050 if (!strcmp(s, "b") ||
1061 bool isConstant(const char *s)
1063 /* This is a bit of a hack... */
1064 return (*s == '#' || *s == '$');
1067 bool canAssignToPtr(const char *s)
1076 /*-----------------------------------------------------------------*/
1077 /* aopPut - puts a string for a aop */
1078 /*-----------------------------------------------------------------*/
1079 static void aopPut (asmop *aop, const char *s, int offset)
1081 if (aop->size && offset > ( aop->size - 1)) {
1082 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1083 "aopPut got offset > aop->size");
1087 /* will assign value to value */
1088 /* depending on where it is ofcourse */
1089 switch (aop->type) {
1094 emitcode("ld", "a,%s", s);
1095 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1101 emitcode("ld", "a,%s", s);
1102 emitcode("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
1106 if (!strcmp(s, "!*hl"))
1107 emit2("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1110 aop->aopu.aop_reg[offset]->name, s);
1115 setupPair(PAIR_IY, aop, offset);
1116 if (!canAssignToPtr(s)) {
1117 emit2("ld a,%s", s);
1118 emit2("ld !*iyx,a", offset);
1121 emit2("ld !*iyx,%s", offset, s);
1126 /* PENDING: for re-target */
1127 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1131 setupPair(PAIR_HL, aop, offset);
1133 emit2("ld !*hl,%s", s);
1138 /* PENDING: re-target */
1139 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1143 setupPair(PAIR_HL, aop, offset);
1144 if (!canAssignToPtr(s)) {
1145 emit2("ld a,%s", s);
1149 emit2("ld !*hl,%s", s);
1152 if (!canAssignToPtr(s)) {
1153 emit2("ld a,%s", s);
1154 emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
1157 emit2("ld !*ixx,%s", aop->aopu.aop_stk+offset, s);
1162 /* if bit variable */
1163 if (!aop->aopu.aop_dir) {
1167 /* In bit space but not in C - cant happen */
1174 if (strcmp(aop->aopu.aop_str[offset],s)) {
1175 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1181 if (!offset && (strcmp(s,"acc") == 0))
1185 emitcode("", "; Error aopPut AOP_ACC");
1188 if (strcmp(aop->aopu.aop_str[offset],s))
1189 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1194 wassert(offset < 2);
1195 emit2("ld %s,%s", aop->aopu.aop_str[offset], s);
1199 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1200 "aopPut got unsupported aop->type");
1205 #define AOP(op) op->aop
1206 #define AOP_TYPE(op) AOP(op)->type
1207 #define AOP_SIZE(op) AOP(op)->size
1208 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1210 static void commitPair(asmop *aop, PAIR_ID id)
1212 if (id == PAIR_HL && requiresHL(aop)) {
1215 aopPut(aop, "a", 0);
1216 aopPut(aop, "d", 1);
1219 aopPut(aop, _pairs[id].l, 0);
1220 aopPut(aop, _pairs[id].h, 1);
1224 /*-----------------------------------------------------------------*/
1225 /* getDataSize - get the operand data size */
1226 /*-----------------------------------------------------------------*/
1227 int getDataSize(operand *op)
1230 size = AOP_SIZE(op);
1238 /*-----------------------------------------------------------------*/
1239 /* movLeft2Result - move byte from left to result */
1240 /*-----------------------------------------------------------------*/
1241 static void movLeft2Result (operand *left, int offl,
1242 operand *result, int offr, int sign)
1245 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1246 l = aopGet(AOP(left),offl,FALSE);
1249 aopPut(AOP(result),l,offr);
1258 /** Put Acc into a register set
1260 void outAcc(operand *result)
1263 size = getDataSize(result);
1265 aopPut(AOP(result),"a",0);
1268 /* unsigned or positive */
1270 aopPut(AOP(result), zero, offset++);
1275 /** Take the value in carry and put it into a register
1277 void outBitC(operand *result)
1279 /* if the result is bit */
1280 if (AOP_TYPE(result) == AOP_CRY) {
1281 emitcode("", "; Note: outBitC form 1");
1282 aopPut(AOP(result),"blah",0);
1285 emit2("ld a,!zero");
1291 /*-----------------------------------------------------------------*/
1292 /* toBoolean - emit code for orl a,operator(sizeop) */
1293 /*-----------------------------------------------------------------*/
1294 void toBoolean(operand *oper)
1296 int size = AOP_SIZE(oper);
1299 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1302 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1305 if (AOP(oper)->type != AOP_ACC) {
1307 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1312 /*-----------------------------------------------------------------*/
1313 /* genNot - generate code for ! operation */
1314 /*-----------------------------------------------------------------*/
1315 static void genNot (iCode *ic)
1317 link *optype = operandType(IC_LEFT(ic));
1319 /* assign asmOps to operand & result */
1320 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
1321 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1323 /* if in bit space then a special case */
1324 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1328 /* if type float then do float */
1329 if (IS_FLOAT(optype)) {
1333 toBoolean(IC_LEFT(ic));
1338 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1339 emit2("sub a,!one");
1340 outBitC(IC_RESULT(ic));
1342 /* release the aops */
1343 freeAsmop(IC_LEFT(ic),NULL,ic);
1344 freeAsmop(IC_RESULT(ic),NULL,ic);
1347 /*-----------------------------------------------------------------*/
1348 /* genCpl - generate code for complement */
1349 /*-----------------------------------------------------------------*/
1350 static void genCpl (iCode *ic)
1356 /* assign asmOps to operand & result */
1357 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1358 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1360 /* if both are in bit space then
1362 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1363 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1367 size = AOP_SIZE(IC_RESULT(ic));
1369 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1372 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1375 /* release the aops */
1376 freeAsmop(IC_LEFT(ic),NULL,ic);
1377 freeAsmop(IC_RESULT(ic),NULL,ic);
1380 /*-----------------------------------------------------------------*/
1381 /* genUminus - unary minus code generation */
1382 /*-----------------------------------------------------------------*/
1383 static void genUminus (iCode *ic)
1386 link *optype, *rtype;
1389 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1390 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
1392 /* if both in bit space then special
1394 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1395 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1400 optype = operandType(IC_LEFT(ic));
1401 rtype = operandType(IC_RESULT(ic));
1403 /* if float then do float stuff */
1404 if (IS_FLOAT(optype)) {
1409 /* otherwise subtract from zero */
1410 size = AOP_SIZE(IC_LEFT(ic));
1414 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1415 emit2("ld a,!zero");
1416 emit2("sbc a,%s",l);
1417 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1420 /* if any remaining bytes in the result */
1421 /* we just need to propagate the sign */
1422 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1426 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1430 /* release the aops */
1431 freeAsmop(IC_LEFT(ic),NULL,ic);
1432 freeAsmop(IC_RESULT(ic),NULL,ic);
1435 static void _push(PAIR_ID pairId)
1437 emit2("push %s", _pairs[pairId].name);
1438 _G.stack.pushed += 2;
1441 static void _pop(PAIR_ID pairId)
1443 emit2("pop %s", _pairs[pairId].name);
1444 _G.stack.pushed -= 2;
1448 /*-----------------------------------------------------------------*/
1449 /* assignResultValue - */
1450 /*-----------------------------------------------------------------*/
1451 void assignResultValue(operand * oper)
1453 int size = AOP_SIZE(oper);
1457 topInA = requiresHL(AOP(oper));
1463 if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
1464 /* We do it the hard way here. */
1466 aopPut(AOP(oper), _fReturn[0], 0);
1467 aopPut(AOP(oper), _fReturn[1], 1);
1468 emitcode("pop", "de");
1469 _G.stack.pushed -= 2;
1470 aopPut(AOP(oper), _fReturn[0], 2);
1471 aopPut(AOP(oper), _fReturn[1], 3);
1475 aopPut(AOP(oper), _fReturn[size], size);
1480 /*-----------------------------------------------------------------*/
1481 /* genIpush - genrate code for pushing this gets a little complex */
1482 /*-----------------------------------------------------------------*/
1483 static void genIpush (iCode *ic)
1485 int size, offset = 0 ;
1488 /* if this is not a parm push : ie. it is spill push
1489 and spill push is always done on the local stack */
1490 if (!ic->parmPush) {
1491 /* and the item is spilt then do nothing */
1492 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1495 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1496 size = AOP_SIZE(IC_LEFT(ic));
1497 /* push it on the stack */
1498 if (isPair(AOP(IC_LEFT(ic)))) {
1499 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1500 _G.stack.pushed += 2;
1505 /* Simple for now - load into A and PUSH AF */
1506 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1507 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1509 emit2("ld a,(%s)", l);
1512 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1513 emit2("ld a,%s", l);
1523 /* Hmmm... what about saving the currently used registers
1526 /* then do the push */
1527 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1529 size = AOP_SIZE(IC_LEFT(ic));
1531 if (isPair(AOP(IC_LEFT(ic)))) {
1533 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1537 fetchHL(AOP(IC_LEFT(ic)));
1538 emitcode("push", "hl");
1540 _G.stack.pushed += 2;
1544 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
1545 emitcode("push", "hl");
1547 _G.stack.pushed += 2;
1548 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 0);
1549 emitcode("push", "hl");
1551 _G.stack.pushed += 2;
1556 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1557 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1559 emit2("ld a,(%s)", l);
1562 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1563 emit2("ld a,%s", l);
1565 emitcode("push", "af");
1566 emitcode("inc", "sp");
1571 freeAsmop(IC_LEFT(ic),NULL,ic);
1574 /*-----------------------------------------------------------------*/
1575 /* genIpop - recover the registers: can happen only for spilling */
1576 /*-----------------------------------------------------------------*/
1577 static void genIpop (iCode *ic)
1582 /* if the temp was not pushed then */
1583 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1586 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1587 size = AOP_SIZE(IC_LEFT(ic));
1589 if (isPair(AOP(IC_LEFT(ic)))) {
1590 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1594 emitcode("dec", "sp");
1595 emitcode("pop", "hl");
1597 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1601 freeAsmop(IC_LEFT(ic),NULL,ic);
1604 static int _isPairUsed(iCode *ic, PAIR_ID pairId)
1609 if (bitVectBitValue(ic->rUsed, D_IDX))
1611 if (bitVectBitValue(ic->rUsed, E_IDX))
1620 static int _opUsesPair(operand *op, iCode *ic, PAIR_ID pairId)
1624 symbol *sym = OP_SYMBOL(op);
1626 if (sym->isspilt || sym->nRegs == 0)
1629 aopOp(op, ic, FALSE, FALSE);
1632 if (aop->type == AOP_REG) {
1634 for (i=0; i < aop->size; i++) {
1635 if (pairId == PAIR_DE) {
1636 emit2("; name %s", aop->aopu.aop_reg[i]->name);
1637 if (!strcmp(aop->aopu.aop_reg[i]->name, "e"))
1639 if (!strcmp(aop->aopu.aop_reg[i]->name, "d"))
1648 freeAsmop(IC_LEFT(ic),NULL,ic);
1652 /* This is quite unfortunate */
1653 static void setArea(int inHome)
1655 static int lastArea = 0;
1658 if (_G.in_home != inHome) {
1660 const char *sz = port->mem.code_name;
1661 port->mem.code_name = "HOME";
1662 emit2("!area", CODE_NAME);
1663 port->mem.code_name = sz;
1666 emit2("!area", CODE_NAME);*/
1667 _G.in_home = inHome;
1671 static bool isInHome(void)
1676 /** Emit the code for a call statement
1678 static void emitCall(iCode *ic, bool ispcall)
1681 link *detype = getSpec(operandType(IC_LEFT(ic)));
1683 /* if caller saves & we have not saved then */
1684 if (!ic->regsSaved) {
1688 /* if send set is not empty then assign */
1692 int n = elementsInSet(sendSet);
1693 if (IS_Z80 && n == 2 && _isPairUsed(ic, PAIR_DE)) {
1694 /* Only push de if it is used and if it's not used
1695 in the return value */
1696 /* Panic if partly used */
1697 if (_opUsesPair(IC_RESULT(ic), ic, PAIR_DE) == 1) {
1698 emit2("; Warning: de crossover");
1700 else if (!_opUsesPair(IC_RESULT(ic), ic, PAIR_DE)) {
1707 if (IS_Z80 && n == 2 ) {
1708 /* Want to load HL first, then DE as HL may = DE */
1709 sic = setFirstItem(sendSet);
1710 sic = setNextItem(sendSet);
1711 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1712 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1714 freeAsmop (IC_LEFT(sic),NULL,sic);
1715 sic = setFirstItem(sendSet);
1716 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1717 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1719 freeAsmop (IC_LEFT(sic),NULL,sic);
1722 for (sic = setFirstItem(sendSet) ; sic ;
1723 sic = setNextItem(sendSet)) {
1725 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1726 size = AOP_SIZE(IC_LEFT(sic));
1728 /* Always send in pairs */
1731 if (IS_Z80 && n == 1)
1732 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1734 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1737 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1740 /* Send set too big */
1744 freeAsmop (IC_LEFT(sic),NULL,sic);
1753 if (IS_BANKEDCALL(detype)) {
1754 werror(W_INDIR_BANKED);
1756 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1758 if (isLitWord(AOP(IC_LEFT(ic)))) {
1759 emitcode("", "; Special case where the pCall is to a constant");
1760 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1763 symbol *rlbl = newiTempLabel(NULL);
1765 emit2("ld hl,!immed!tlabel", (rlbl->key+100));
1766 emitcode("push", "hl");
1767 _G.stack.pushed += 2;
1769 fetchHL(AOP(IC_LEFT(ic)));
1771 emit2("!tlabeldef", (rlbl->key+100));
1772 _G.stack.pushed -= 2;
1774 freeAsmop(IC_LEFT(ic),NULL,ic);
1777 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1778 OP_SYMBOL(IC_LEFT(ic))->rname :
1779 OP_SYMBOL(IC_LEFT(ic))->name;
1780 if (IS_BANKEDCALL(detype)) {
1781 emit2("call banked_call");
1782 emit2("!dws", name);
1783 emit2("!dw !bankimmeds", name);
1787 emit2("call %s", name);
1792 /* if we need assign a result value */
1793 if ((IS_ITEMP(IC_RESULT(ic)) &&
1794 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1795 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1796 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1799 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1802 assignResultValue(IC_RESULT(ic));
1804 freeAsmop(IC_RESULT(ic),NULL, ic);
1807 /* adjust the stack for parameters if required */
1808 if (IC_LEFT(ic)->parmBytes) {
1809 int i = IC_LEFT(ic)->parmBytes;
1810 _G.stack.pushed -= i;
1812 emit2("!ldaspsp", i);
1817 emitcode("ld", "hl,#%d", i);
1818 emitcode("add", "hl,sp");
1819 emitcode("ld", "sp,hl");
1823 emitcode("pop", "hl");
1827 emitcode("inc", "sp");
1836 /*-----------------------------------------------------------------*/
1837 /* genCall - generates a call statement */
1838 /*-----------------------------------------------------------------*/
1839 static void genCall (iCode *ic)
1841 link *detype = getSpec(operandType(IC_LEFT(ic)));
1842 emitCall(ic, FALSE);
1845 /*-----------------------------------------------------------------*/
1846 /* genPcall - generates a call by pointer statement */
1847 /*-----------------------------------------------------------------*/
1848 static void genPcall (iCode *ic)
1853 /*-----------------------------------------------------------------*/
1854 /* resultRemat - result is rematerializable */
1855 /*-----------------------------------------------------------------*/
1856 static int resultRemat (iCode *ic)
1858 if (SKIP_IC(ic) || ic->op == IFX)
1861 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1862 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1863 if (sym->remat && !POINTER_SET(ic))
1870 extern set *publics;
1872 /*-----------------------------------------------------------------*/
1873 /* genFunction - generated code for function entry */
1874 /*-----------------------------------------------------------------*/
1875 static void genFunction (iCode *ic)
1877 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1881 setArea(IS_NONBANKED(sym->etype));
1884 if (!IS_STATIC(sym->etype)) {
1885 addSetIfnotP(&publics, sym);
1888 /* create the function header */
1889 emit2("!functionheader", sym->name);
1890 /* PENDING: portability. */
1891 emit2("__%s_start:", sym->rname);
1892 emit2("!functionlabeldef", sym->rname);
1894 fetype = getSpec(operandType(IC_LEFT(ic)));
1896 /* if critical function then turn interrupts off */
1897 if (SPEC_CRTCL(fetype))
1900 /* if this is an interrupt service routine then
1901 save acc, b, dpl, dph */
1902 if (IS_ISR(sym->etype)) {
1905 /* PENDING: callee-save etc */
1907 /* If BC or DE are used, then push */
1908 _G.stack.pushed_bc = 0;
1909 _G.stack.pushed_de = 0;
1910 _G.stack.param_offset = 0;
1911 if (sym->regsUsed) {
1913 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1914 if (bitVectBitValue(sym->regsUsed, i)) {
1918 _G.stack.pushed_bc = 1;
1923 _G.stack.pushed_de = 1;
1928 if (_G.stack.pushed_bc) {
1930 _G.stack.param_offset += 2;
1932 if (_G.stack.pushed_de) {
1934 _G.stack.param_offset += 2;
1938 /* adjust the stack for the function */
1939 _G.stack.last = sym->stack;
1942 emit2("!enterx", sym->stack);
1945 _G.stack.offset = sym->stack;
1948 /*-----------------------------------------------------------------*/
1949 /* genEndFunction - generates epilogue for functions */
1950 /*-----------------------------------------------------------------*/
1951 static void genEndFunction (iCode *ic)
1953 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1955 if (IS_ISR(sym->etype)) {
1959 if (SPEC_CRTCL(sym->etype))
1962 /* PENDING: calleeSave */
1964 /* if debug then send end of function */
1965 if (options.debug && currFunc) {
1967 emitcode("","C$%s$%d$%d$%d ==.",
1968 ic->filename,currFunc->lastLine,
1969 ic->level,ic->block);
1970 if (IS_STATIC(currFunc->etype))
1971 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1973 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1976 if (_G.stack.offset)
1977 emit2("!leavex", _G.stack.offset);
1981 if (_G.stack.pushed_de)
1983 if (_G.stack.pushed_bc)
1985 /* Both baned and non-banked just ret */
1988 /* PENDING: portability. */
1989 emit2("__%s_end:", sym->rname);
1991 _G.flush_statics = 1;
1992 _G.stack.pushed = 0;
1993 _G.stack.offset = 0;
1996 /*-----------------------------------------------------------------*/
1997 /* genRet - generate code for return statement */
1998 /*-----------------------------------------------------------------*/
1999 static void genRet (iCode *ic)
2002 /* Errk. This is a hack until I can figure out how
2003 to cause dehl to spill on a call */
2004 int size,offset = 0;
2006 /* if we have no return value then
2007 just generate the "ret" */
2011 /* we have something to return then
2012 move the return value into place */
2013 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2014 size = AOP_SIZE(IC_LEFT(ic));
2016 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
2018 emitcode("ld", "de,%s", l);
2021 emitcode("ld", "hl,%s", l);
2025 if (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
2026 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2027 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
2031 l = aopGet(AOP(IC_LEFT(ic)),offset,
2033 if (strcmp(_fReturn[offset],l))
2034 emitcode("ld","%s,%s", _fReturn[offset++],l);
2038 freeAsmop (IC_LEFT(ic),NULL,ic);
2041 /* generate a jump to the return label
2042 if the next is not the return statement */
2043 if (!(ic->next && ic->next->op == LABEL &&
2044 IC_LABEL(ic->next) == returnLabel))
2046 emit2("jp !tlabel", returnLabel->key+100);
2049 /*-----------------------------------------------------------------*/
2050 /* genLabel - generates a label */
2051 /*-----------------------------------------------------------------*/
2052 static void genLabel (iCode *ic)
2054 /* special case never generate */
2055 if (IC_LABEL(ic) == entryLabel)
2058 emitLabel(IC_LABEL(ic)->key+100);
2061 /*-----------------------------------------------------------------*/
2062 /* genGoto - generates a ljmp */
2063 /*-----------------------------------------------------------------*/
2064 static void genGoto (iCode *ic)
2066 emit2("jp !tlabel", IC_LABEL(ic)->key+100);
2069 /*-----------------------------------------------------------------*/
2070 /* genPlusIncr :- does addition with increment if possible */
2071 /*-----------------------------------------------------------------*/
2072 static bool genPlusIncr (iCode *ic)
2074 unsigned int icount ;
2075 unsigned int size = getDataSize(IC_RESULT(ic));
2076 PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
2078 /* will try to generate an increment */
2079 /* if the right side is not a literal
2081 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2084 emitcode("", "; genPlusIncr");
2086 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2088 /* If result is a pair */
2089 if (resultId != PAIR_INVALID) {
2090 if (isLitWord(AOP(IC_LEFT(ic)))) {
2091 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
2094 if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
2095 fetchPair(resultId, AOP(IC_RIGHT(ic)));
2096 emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
2102 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2105 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2106 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2109 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
2114 /* if the literal value of the right hand side
2115 is greater than 4 then it is not worth it */
2119 /* if increment 16 bits in register */
2120 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2125 symbol *tlbl = NULL;
2126 tlbl = newiTempLabel(NULL);
2128 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)), offset++, FALSE));
2130 emit2("!shortjp nz,!tlabel", tlbl->key+100);
2133 emitLabel(tlbl->key+100);
2137 /* if the sizes are greater than 1 then we cannot */
2138 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2139 AOP_SIZE(IC_LEFT(ic)) > 1 )
2142 /* we can if the aops of the left & result match or
2143 if they are in registers and the registers are the
2145 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2147 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
2154 /*-----------------------------------------------------------------*/
2155 /* outBitAcc - output a bit in acc */
2156 /*-----------------------------------------------------------------*/
2157 void outBitAcc(operand *result)
2159 symbol *tlbl = newiTempLabel(NULL);
2160 /* if the result is a bit */
2161 if (AOP_TYPE(result) == AOP_CRY){
2165 emit2("!shortjp z,!tlabel", tlbl->key+100);
2167 emitLabel(tlbl->key+100);
2172 /*-----------------------------------------------------------------*/
2173 /* genPlus - generates code for addition */
2174 /*-----------------------------------------------------------------*/
2175 static void genPlus (iCode *ic)
2177 int size, offset = 0;
2179 /* special cases :- */
2181 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2182 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2183 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2185 /* Swap the left and right operands if:
2187 if literal, literal on the right or
2188 if left requires ACC or right is already
2191 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2192 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2193 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2194 operand *t = IC_RIGHT(ic);
2195 IC_RIGHT(ic) = IC_LEFT(ic);
2199 /* if both left & right are in bit
2201 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2202 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2207 /* if left in bit space & right literal */
2208 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2209 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2210 /* Can happen I guess */
2214 /* if I can do an increment instead
2215 of add then GOOD for ME */
2216 if (genPlusIncr (ic) == TRUE)
2219 emit2("; genPlusIncr failed");
2221 size = getDataSize(IC_RESULT(ic));
2223 /* Special case when left and right are constant */
2224 if (isPair(AOP(IC_RESULT(ic)))) {
2227 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
2228 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
2229 if (left && right) {
2233 sprintf(buffer, "#(%s + %s)", left, right);
2234 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
2239 if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
2240 /* Fetch into HL then do the add */
2242 fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
2243 emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
2248 ld hl,sp+n trashes C so we cant afford to do it during an
2249 add with stack based varibles. Worst case is:
2262 So you cant afford to load up hl if either left, right, or result
2263 is on the stack (*sigh*) The alt is:
2271 Combinations in here are:
2272 * If left or right are in bc then the loss is small - trap later
2273 * If the result is in bc then the loss is also small
2276 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2277 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2278 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2279 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2280 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2281 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2282 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2283 if (getPairId(AOP(IC_RIGHT(ic))) == PAIR_BC) {
2284 /* Swap left and right */
2285 operand *t = IC_RIGHT(ic);
2286 IC_RIGHT(ic) = IC_LEFT(ic);
2289 if (getPairId(AOP(IC_LEFT(ic))) == PAIR_BC) {
2290 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2294 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2295 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2298 commitPair(AOP(IC_RESULT(ic)), PAIR_HL);
2301 else if (size == 4) {
2302 emit2("; WARNING: This add is probably broken.\n");
2308 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2309 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2312 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2315 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2317 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2320 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2323 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2325 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2329 freeAsmop(IC_LEFT(ic),NULL,ic);
2330 freeAsmop(IC_RIGHT(ic),NULL,ic);
2331 freeAsmop(IC_RESULT(ic),NULL,ic);
2335 /*-----------------------------------------------------------------*/
2336 /* genMinusDec :- does subtraction with deccrement if possible */
2337 /*-----------------------------------------------------------------*/
2338 static bool genMinusDec (iCode *ic)
2340 unsigned int icount ;
2341 unsigned int size = getDataSize(IC_RESULT(ic));
2343 /* will try to generate an increment */
2344 /* if the right side is not a literal we cannot */
2345 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2348 /* if the literal value of the right hand side
2349 is greater than 4 then it is not worth it */
2350 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2353 size = getDataSize(IC_RESULT(ic));
2356 /* if increment 16 bits in register */
2357 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2360 symbol *tlbl = newiTempLabel(NULL);
2361 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
2362 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
2364 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
2368 emitLabel(tlbl->key+100);
2373 /* if decrement 16 bits in register */
2374 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2375 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
2377 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2381 /* If result is a pair */
2382 if (isPair(AOP(IC_RESULT(ic)))) {
2383 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2384 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2386 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2390 /* if the sizes are greater than 1 then we cannot */
2391 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2392 AOP_SIZE(IC_LEFT(ic)) > 1 )
2395 /* we can if the aops of the left & result match or if they are in
2396 registers and the registers are the same */
2397 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2399 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
2406 /*-----------------------------------------------------------------*/
2407 /* genMinus - generates code for subtraction */
2408 /*-----------------------------------------------------------------*/
2409 static void genMinus (iCode *ic)
2411 int size, offset = 0;
2412 unsigned long lit = 0L;
2414 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2415 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2416 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2418 /* special cases :- */
2419 /* if both left & right are in bit space */
2420 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2421 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2426 /* if I can do an decrement instead of subtract then GOOD for ME */
2427 if (genMinusDec (ic) == TRUE)
2430 size = getDataSize(IC_RESULT(ic));
2432 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2435 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2439 /* Same logic as genPlus */
2441 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2442 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2443 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2444 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2445 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2446 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2447 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2448 PAIR_ID left = getPairId(AOP(IC_LEFT(ic)));
2449 PAIR_ID right = getPairId(AOP(IC_RIGHT(ic)));
2451 if (left == PAIR_INVALID && right == PAIR_INVALID) {
2455 else if (right == PAIR_INVALID)
2457 else if (left == PAIR_INVALID)
2460 fetchPair(left, AOP(IC_LEFT(ic)));
2461 /* Order is important. Right may be HL */
2462 fetchPair(right, AOP(IC_RIGHT(ic)));
2464 emit2("ld a,%s", _pairs[left].l);
2465 emit2("sub a,%s", _pairs[right].l);
2467 emit2("ld a,%s", _pairs[left].h);
2468 emit2("sbc a,%s", _pairs[right].h);
2470 aopPut(AOP(IC_RESULT(ic)), "a", 1);
2471 aopPut(AOP(IC_RESULT(ic)), "e", 0);
2474 else if (size == 4) {
2475 emit2("; WARNING: This sub is probably broken.\n");
2480 /* if literal, add a,#-lit, else normal subb */
2482 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2483 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2485 emitcode("sub","a,%s",
2486 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2488 emitcode("sbc","a,%s",
2489 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2492 /* first add without previous c */
2494 emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL));
2496 emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2498 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2501 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2502 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2503 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2507 freeAsmop(IC_LEFT(ic),NULL,ic);
2508 freeAsmop(IC_RIGHT(ic),NULL,ic);
2509 freeAsmop(IC_RESULT(ic),NULL,ic);
2512 /*-----------------------------------------------------------------*/
2513 /* genMult - generates code for multiplication */
2514 /*-----------------------------------------------------------------*/
2515 static void genMult (iCode *ic)
2517 /* Shouldn't occur - all done through function calls */
2521 /*-----------------------------------------------------------------*/
2522 /* genDiv - generates code for division */
2523 /*-----------------------------------------------------------------*/
2524 static void genDiv (iCode *ic)
2526 /* Shouldn't occur - all done through function calls */
2530 /*-----------------------------------------------------------------*/
2531 /* genMod - generates code for division */
2532 /*-----------------------------------------------------------------*/
2533 static void genMod (iCode *ic)
2535 /* Shouldn't occur - all done through function calls */
2539 /*-----------------------------------------------------------------*/
2540 /* genIfxJump :- will create a jump depending on the ifx */
2541 /*-----------------------------------------------------------------*/
2542 static void genIfxJump (iCode *ic, char *jval)
2547 /* if true label then we jump if condition
2549 if ( IC_TRUE(ic) ) {
2551 if (!strcmp(jval, "a")) {
2554 else if (!strcmp(jval, "c")) {
2558 /* The buffer contains the bit on A that we should test */
2563 /* false label is present */
2564 jlbl = IC_FALSE(ic) ;
2565 if (!strcmp(jval, "a")) {
2568 else if (!strcmp(jval, "c")) {
2572 /* The buffer contains the bit on A that we should test */
2576 /* Z80 can do a conditional long jump */
2577 if (!strcmp(jval, "a")) {
2578 emitcode("or", "a,a");
2580 else if (!strcmp(jval, "c")) {
2583 emitcode("bit", "%s,a", jval);
2585 emit2("jp %s,!tlabel", inst, jlbl->key+100);
2587 /* mark the icode as generated */
2591 /** Generic compare for > or <
2593 static void genCmp (operand *left,operand *right,
2594 operand *result, iCode *ifx, int sign)
2596 int size, offset = 0 ;
2597 unsigned long lit = 0L;
2599 /* if left & right are bit variables */
2600 if (AOP_TYPE(left) == AOP_CRY &&
2601 AOP_TYPE(right) == AOP_CRY ) {
2602 /* Cant happen on the Z80 */
2605 /* subtract right from left if at the
2606 end the carry flag is set then we know that
2607 left is greater than right */
2608 size = max(AOP_SIZE(left),AOP_SIZE(right));
2610 /* if unsigned char cmp with lit, just compare */
2612 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2613 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2615 emit2("xor a,!immedbyte", 0x80);
2616 emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80);
2619 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
2622 if(AOP_TYPE(right) == AOP_LIT) {
2623 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2624 /* optimize if(x < 0) or if(x >= 0) */
2627 /* No sign so it's always false */
2631 /* Just load in the top most bit */
2632 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2633 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2634 genIfxJump (ifx,"7");
2638 emitcode("rlc","a");
2644 /* First setup h and l contaning the top most bytes XORed */
2645 bool fDidXor = FALSE;
2646 if (AOP_TYPE(left) == AOP_LIT){
2647 unsigned long lit = (unsigned long)
2648 floatFromVal(AOP(left)->aopu.aop_lit);
2649 emit2("ld %s,!immedbyte", _fTmp[0],
2650 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2653 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2654 emit2("xor a,!immedbyte", 0x80);
2655 emitcode("ld", "%s,a", _fTmp[0]);
2658 if (AOP_TYPE(right) == AOP_LIT) {
2659 unsigned long lit = (unsigned long)
2660 floatFromVal(AOP(right)->aopu.aop_lit);
2661 emit2("ld %s,!immedbyte", _fTmp[1],
2662 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2665 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2666 emit2("xor a,!immedbyte", 0x80);
2667 emitcode("ld", "%s,a", _fTmp[1]);
2677 /* Do a long subtract */
2678 if (!sign || size ) {
2679 MOVA(aopGet(AOP(left),offset,FALSE));
2681 if (sign && size == 0) {
2682 emitcode("ld", "a,%s", _fTmp[0]);
2683 emitcode("sbc", "a,%s", _fTmp[1]);
2686 /* Subtract through, propagating the carry */
2687 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2694 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2697 /* if the result is used in the next
2698 ifx conditional branch then generate
2699 code a little differently */
2701 genIfxJump (ifx,"c");
2704 /* leave the result in acc */
2708 /*-----------------------------------------------------------------*/
2709 /* genCmpGt :- greater than comparison */
2710 /*-----------------------------------------------------------------*/
2711 static void genCmpGt (iCode *ic, iCode *ifx)
2713 operand *left, *right, *result;
2714 link *letype , *retype;
2718 right= IC_RIGHT(ic);
2719 result = IC_RESULT(ic);
2721 letype = getSpec(operandType(left));
2722 retype =getSpec(operandType(right));
2723 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2724 /* assign the amsops */
2725 aopOp (left,ic,FALSE, FALSE);
2726 aopOp (right,ic,FALSE, FALSE);
2727 aopOp (result,ic,TRUE, FALSE);
2729 genCmp(right, left, result, ifx, sign);
2731 freeAsmop(left,NULL,ic);
2732 freeAsmop(right,NULL,ic);
2733 freeAsmop(result,NULL,ic);
2736 /*-----------------------------------------------------------------*/
2737 /* genCmpLt - less than comparisons */
2738 /*-----------------------------------------------------------------*/
2739 static void genCmpLt (iCode *ic, iCode *ifx)
2741 operand *left, *right, *result;
2742 link *letype , *retype;
2746 right= IC_RIGHT(ic);
2747 result = IC_RESULT(ic);
2749 letype = getSpec(operandType(left));
2750 retype =getSpec(operandType(right));
2751 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2753 /* assign the amsops */
2754 aopOp (left,ic,FALSE, FALSE);
2755 aopOp (right,ic,FALSE, FALSE);
2756 aopOp (result,ic,TRUE, FALSE);
2758 genCmp(left, right, result, ifx, sign);
2760 freeAsmop(left,NULL,ic);
2761 freeAsmop(right,NULL,ic);
2762 freeAsmop(result,NULL,ic);
2765 /*-----------------------------------------------------------------*/
2766 /* gencjneshort - compare and jump if not equal */
2767 /*-----------------------------------------------------------------*/
2768 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2770 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2772 unsigned long lit = 0L;
2774 /* Swap the left and right if it makes the computation easier */
2775 if (AOP_TYPE(left) == AOP_LIT) {
2781 if(AOP_TYPE(right) == AOP_LIT)
2782 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2784 /* if the right side is a literal then anything goes */
2785 if (AOP_TYPE(right) == AOP_LIT &&
2786 AOP_TYPE(left) != AOP_DIR ) {
2788 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2793 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2797 emitcode("or", "a,a");
2799 emit2("jp nz,!tlabel", lbl->key+100);
2803 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2804 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2805 emitcode("or", "a,a");
2807 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2808 emit2("jp nz,!tlabel", lbl->key+100);
2813 /* if the right side is in a register or in direct space or
2814 if the left is a pointer register & right is not */
2815 else if (AOP_TYPE(right) == AOP_REG ||
2816 AOP_TYPE(right) == AOP_DIR ||
2817 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2819 MOVA(aopGet(AOP(left),offset,FALSE));
2820 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2821 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2823 emit2("jp nz,!tlabel", lbl->key+100);
2825 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2826 emit2("jp nz,!tlabel", lbl->key+100);
2831 /* right is a pointer reg need both a & b */
2832 /* PENDING: is this required? */
2834 MOVA(aopGet(AOP(right),offset,FALSE));
2835 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2836 emit2("!shortjp nz,!tlabel", lbl->key+100);
2842 /*-----------------------------------------------------------------*/
2843 /* gencjne - compare and jump if not equal */
2844 /*-----------------------------------------------------------------*/
2845 static void gencjne(operand *left, operand *right, symbol *lbl)
2847 symbol *tlbl = newiTempLabel(NULL);
2849 gencjneshort(left, right, lbl);
2853 emit2("!shortjp !tlabel", tlbl->key+100);
2854 emitLabel(lbl->key+100);
2855 emitcode("xor","a,a");
2856 emitLabel(tlbl->key+100);
2859 /*-----------------------------------------------------------------*/
2860 /* genCmpEq - generates code for equal to */
2861 /*-----------------------------------------------------------------*/
2862 static void genCmpEq (iCode *ic, iCode *ifx)
2864 operand *left, *right, *result;
2866 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
2867 aopOp((right=IC_RIGHT(ic)),ic,FALSE, FALSE);
2868 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
2870 /* Swap operands if it makes the operation easier. ie if:
2871 1. Left is a literal.
2873 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2874 operand *t = IC_RIGHT(ic);
2875 IC_RIGHT(ic) = IC_LEFT(ic);
2879 if (ifx && !AOP_SIZE(result)){
2881 /* if they are both bit variables */
2882 if (AOP_TYPE(left) == AOP_CRY &&
2883 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2886 tlbl = newiTempLabel(NULL);
2887 gencjneshort(left, right, tlbl);
2888 if ( IC_TRUE(ifx) ) {
2889 emit2("jp !tlabel", IC_TRUE(ifx)->key+100);
2890 emitLabel(tlbl->key+100);
2892 /* PENDING: do this better */
2893 symbol *lbl = newiTempLabel(NULL);
2894 emit2("!shortjp !tlabel", lbl->key+100);
2895 emitLabel(tlbl->key+100);
2896 emit2("jp !tlabel", IC_FALSE(ifx)->key+100);
2897 emitLabel(lbl->key+100);
2900 /* mark the icode as generated */
2905 /* if they are both bit variables */
2906 if (AOP_TYPE(left) == AOP_CRY &&
2907 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2910 gencjne(left,right,newiTempLabel(NULL));
2911 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2915 genIfxJump(ifx,"a");
2918 /* if the result is used in an arithmetic operation
2919 then put the result in place */
2920 if (AOP_TYPE(result) != AOP_CRY) {
2923 /* leave the result in acc */
2927 freeAsmop(left,NULL,ic);
2928 freeAsmop(right,NULL,ic);
2929 freeAsmop(result,NULL,ic);
2932 /*-----------------------------------------------------------------*/
2933 /* ifxForOp - returns the icode containing the ifx for operand */
2934 /*-----------------------------------------------------------------*/
2935 static iCode *ifxForOp ( operand *op, iCode *ic )
2937 /* if true symbol then needs to be assigned */
2938 if (IS_TRUE_SYMOP(op))
2941 /* if this has register type condition and
2942 the next instruction is ifx with the same operand
2943 and live to of the operand is upto the ifx only then */
2945 ic->next->op == IFX &&
2946 IC_COND(ic->next)->key == op->key &&
2947 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2953 /*-----------------------------------------------------------------*/
2954 /* genAndOp - for && operation */
2955 /*-----------------------------------------------------------------*/
2956 static void genAndOp (iCode *ic)
2958 operand *left,*right, *result;
2961 /* note here that && operations that are in an if statement are
2962 taken away by backPatchLabels only those used in arthmetic
2963 operations remain */
2964 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
2965 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
2966 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
2968 /* if both are bit variables */
2969 if (AOP_TYPE(left) == AOP_CRY &&
2970 AOP_TYPE(right) == AOP_CRY ) {
2973 tlbl = newiTempLabel(NULL);
2975 emit2("!shortjp z,!tlabel", tlbl->key+100);
2977 emitLabel(tlbl->key+100);
2981 freeAsmop(left,NULL,ic);
2982 freeAsmop(right,NULL,ic);
2983 freeAsmop(result,NULL,ic);
2986 /*-----------------------------------------------------------------*/
2987 /* genOrOp - for || operation */
2988 /*-----------------------------------------------------------------*/
2989 static void genOrOp (iCode *ic)
2991 operand *left,*right, *result;
2994 /* note here that || operations that are in an
2995 if statement are taken away by backPatchLabels
2996 only those used in arthmetic operations remain */
2997 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
2998 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
2999 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
3001 /* if both are bit variables */
3002 if (AOP_TYPE(left) == AOP_CRY &&
3003 AOP_TYPE(right) == AOP_CRY ) {
3006 tlbl = newiTempLabel(NULL);
3008 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3010 emitLabel(tlbl->key+100);
3014 freeAsmop(left,NULL,ic);
3015 freeAsmop(right,NULL,ic);
3016 freeAsmop(result,NULL,ic);
3019 /*-----------------------------------------------------------------*/
3020 /* isLiteralBit - test if lit == 2^n */
3021 /*-----------------------------------------------------------------*/
3022 int isLiteralBit(unsigned long lit)
3024 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3025 0x100L,0x200L,0x400L,0x800L,
3026 0x1000L,0x2000L,0x4000L,0x8000L,
3027 0x10000L,0x20000L,0x40000L,0x80000L,
3028 0x100000L,0x200000L,0x400000L,0x800000L,
3029 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3030 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3033 for(idx = 0; idx < 32; idx++)
3039 /*-----------------------------------------------------------------*/
3040 /* jmpTrueOrFalse - */
3041 /*-----------------------------------------------------------------*/
3042 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3044 // ugly but optimized by peephole
3046 symbol *nlbl = newiTempLabel(NULL);
3047 emit2("jp !tlabel", nlbl->key+100);
3048 emitLabel(tlbl->key+100);
3049 emit2("jp !tlabel", IC_TRUE(ic)->key+100);
3050 emitLabel(nlbl->key+100);
3053 emit2("jp !tlabel", IC_FALSE(ic)->key+100);
3054 emitLabel(tlbl->key+100);
3059 /*-----------------------------------------------------------------*/
3060 /* genAnd - code for and */
3061 /*-----------------------------------------------------------------*/
3062 static void genAnd (iCode *ic, iCode *ifx)
3064 operand *left, *right, *result;
3066 unsigned long lit = 0L;
3069 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3070 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3071 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3074 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3076 AOP_TYPE(left), AOP_TYPE(right));
3077 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3079 AOP_SIZE(left), AOP_SIZE(right));
3082 /* if left is a literal & right is not then exchange them */
3083 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3084 AOP_NEEDSACC(left)) {
3085 operand *tmp = right ;
3090 /* if result = right then exchange them */
3091 if(sameRegs(AOP(result),AOP(right))){
3092 operand *tmp = right ;
3097 /* if right is bit then exchange them */
3098 if (AOP_TYPE(right) == AOP_CRY &&
3099 AOP_TYPE(left) != AOP_CRY){
3100 operand *tmp = right ;
3104 if(AOP_TYPE(right) == AOP_LIT)
3105 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3107 size = AOP_SIZE(result);
3109 if (AOP_TYPE(left) == AOP_CRY){
3114 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3115 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3116 if((AOP_TYPE(right) == AOP_LIT) &&
3117 (AOP_TYPE(result) == AOP_CRY) &&
3118 (AOP_TYPE(left) != AOP_CRY)) {
3119 int posbit = isLiteralBit(lit);
3123 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
3127 emitcode("mov","c,acc.%d",posbit&0x07);
3132 sprintf(buffer, "%d", posbit&0x07);
3133 genIfxJump(ifx, buffer);
3141 symbol *tlbl = newiTempLabel(NULL);
3142 int sizel = AOP_SIZE(left);
3145 emitcode("setb","c");
3148 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3149 MOVA( aopGet(AOP(left),offset,FALSE));
3151 if((posbit = isLiteralBit(bytelit)) != 0) {
3153 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3156 if(bytelit != 0x0FFL)
3157 emitcode("and","a,%s",
3158 aopGet(AOP(right),offset,FALSE));
3162 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3167 // bit = left & literal
3169 emitcode("clr","c");
3170 emit2("!tlabeldef", tlbl->key+100);
3172 // if(left & literal)
3175 jmpTrueOrFalse(ifx, tlbl);
3183 /* if left is same as result */
3184 if(sameRegs(AOP(result),AOP(left))){
3185 for(;size--; offset++) {
3186 if(AOP_TYPE(right) == AOP_LIT){
3187 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3191 aopPut(AOP(result),zero,offset);
3193 MOVA(aopGet(AOP(left),offset,FALSE));
3194 emitcode("and","a,%s",
3195 aopGet(AOP(right),offset,FALSE));
3196 aopPut(AOP(left), "a", offset);
3201 if (AOP_TYPE(left) == AOP_ACC) {
3205 MOVA(aopGet(AOP(left),offset,FALSE));
3206 emitcode("and","a,%s",
3207 aopGet(AOP(right),offset,FALSE));
3208 aopPut(AOP(left), "a", offset);
3213 // left & result in different registers
3214 if(AOP_TYPE(result) == AOP_CRY){
3217 for(;(size--);offset++) {
3219 // result = left & right
3220 if(AOP_TYPE(right) == AOP_LIT){
3221 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3223 aopGet(AOP(left),offset,FALSE),
3226 } else if(bytelit == 0){
3227 aopPut(AOP(result),zero,offset);
3231 // faster than result <- left, anl result,right
3232 // and better if result is SFR
3233 if (AOP_TYPE(left) == AOP_ACC)
3234 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
3236 MOVA(aopGet(AOP(left),offset,FALSE));
3237 emitcode("and","a,%s",
3238 aopGet(AOP(right),offset,FALSE));
3240 aopPut(AOP(result),"a",offset);
3247 freeAsmop(left,NULL,ic);
3248 freeAsmop(right,NULL,ic);
3249 freeAsmop(result,NULL,ic);
3252 /*-----------------------------------------------------------------*/
3253 /* genOr - code for or */
3254 /*-----------------------------------------------------------------*/
3255 static void genOr (iCode *ic, iCode *ifx)
3257 operand *left, *right, *result;
3259 unsigned long lit = 0L;
3261 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3262 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3263 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3266 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3268 AOP_TYPE(left), AOP_TYPE(right));
3269 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3271 AOP_SIZE(left), AOP_SIZE(right));
3274 /* if left is a literal & right is not then exchange them */
3275 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3276 AOP_NEEDSACC(left)) {
3277 operand *tmp = right ;
3282 /* if result = right then exchange them */
3283 if(sameRegs(AOP(result),AOP(right))){
3284 operand *tmp = right ;
3289 /* if right is bit then exchange them */
3290 if (AOP_TYPE(right) == AOP_CRY &&
3291 AOP_TYPE(left) != AOP_CRY){
3292 operand *tmp = right ;
3296 if(AOP_TYPE(right) == AOP_LIT)
3297 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3299 size = AOP_SIZE(result);
3301 if (AOP_TYPE(left) == AOP_CRY){
3306 if((AOP_TYPE(right) == AOP_LIT) &&
3307 (AOP_TYPE(result) == AOP_CRY) &&
3308 (AOP_TYPE(left) != AOP_CRY)){
3313 /* if left is same as result */
3314 if(sameRegs(AOP(result),AOP(left))){
3315 for(;size--; offset++) {
3316 if(AOP_TYPE(right) == AOP_LIT){
3317 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3320 MOVA(aopGet(AOP(left),offset,FALSE));
3321 emitcode("or","a,%s",
3322 aopGet(AOP(right),offset,FALSE));
3323 aopPut(AOP(result),"a", offset);
3326 if (AOP_TYPE(left) == AOP_ACC)
3327 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3329 MOVA(aopGet(AOP(left),offset,FALSE));
3330 emitcode("or","a,%s",
3331 aopGet(AOP(right),offset,FALSE));
3332 aopPut(AOP(result),"a", offset);
3337 // left & result in different registers
3338 if(AOP_TYPE(result) == AOP_CRY){
3340 } else for(;(size--);offset++){
3342 // result = left & right
3343 if(AOP_TYPE(right) == AOP_LIT){
3344 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3346 aopGet(AOP(left),offset,FALSE),
3351 // faster than result <- left, anl result,right
3352 // and better if result is SFR
3353 if (AOP_TYPE(left) == AOP_ACC)
3354 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3356 MOVA(aopGet(AOP(left),offset,FALSE));
3357 emitcode("or","a,%s",
3358 aopGet(AOP(right),offset,FALSE));
3360 aopPut(AOP(result),"a",offset);
3361 /* PENDING: something weird is going on here. Add exception. */
3362 if (AOP_TYPE(result) == AOP_ACC)
3368 freeAsmop(left,NULL,ic);
3369 freeAsmop(right,NULL,ic);
3370 freeAsmop(result,NULL,ic);
3373 /*-----------------------------------------------------------------*/
3374 /* genXor - code for xclusive or */
3375 /*-----------------------------------------------------------------*/
3376 static void genXor (iCode *ic, iCode *ifx)
3378 operand *left, *right, *result;
3380 unsigned long lit = 0L;
3382 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3383 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3384 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3386 /* if left is a literal & right is not then exchange them */
3387 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3388 AOP_NEEDSACC(left)) {
3389 operand *tmp = right ;
3394 /* if result = right then exchange them */
3395 if(sameRegs(AOP(result),AOP(right))){
3396 operand *tmp = right ;
3401 /* if right is bit then exchange them */
3402 if (AOP_TYPE(right) == AOP_CRY &&
3403 AOP_TYPE(left) != AOP_CRY){
3404 operand *tmp = right ;
3408 if(AOP_TYPE(right) == AOP_LIT)
3409 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3411 size = AOP_SIZE(result);
3413 if (AOP_TYPE(left) == AOP_CRY){
3418 if((AOP_TYPE(right) == AOP_LIT) &&
3419 (AOP_TYPE(result) == AOP_CRY) &&
3420 (AOP_TYPE(left) != AOP_CRY)){
3425 /* if left is same as result */
3426 if(sameRegs(AOP(result),AOP(left))){
3427 for(;size--; offset++) {
3428 if(AOP_TYPE(right) == AOP_LIT){
3429 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3432 MOVA(aopGet(AOP(right),offset,FALSE));
3433 emitcode("xor","a,%s",
3434 aopGet(AOP(left),offset,FALSE));
3435 aopPut(AOP(result),"a",0);
3438 if (AOP_TYPE(left) == AOP_ACC)
3439 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3441 MOVA(aopGet(AOP(right),offset,FALSE));
3442 emitcode("xor","a,%s",
3443 aopGet(AOP(left),offset,FALSE));
3444 aopPut(AOP(result),"a",0);
3449 // left & result in different registers
3450 if(AOP_TYPE(result) == AOP_CRY){
3452 } else for(;(size--);offset++){
3454 // result = left & right
3455 if(AOP_TYPE(right) == AOP_LIT){
3456 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3458 aopGet(AOP(left),offset,FALSE),
3463 // faster than result <- left, anl result,right
3464 // and better if result is SFR
3465 if (AOP_TYPE(left) == AOP_ACC)
3466 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3468 MOVA(aopGet(AOP(right),offset,FALSE));
3469 emitcode("xor","a,%s",
3470 aopGet(AOP(left),offset,FALSE));
3471 aopPut(AOP(result),"a",0);
3473 aopPut(AOP(result),"a",offset);
3478 freeAsmop(left,NULL,ic);
3479 freeAsmop(right,NULL,ic);
3480 freeAsmop(result,NULL,ic);
3483 /*-----------------------------------------------------------------*/
3484 /* genInline - write the inline code out */
3485 /*-----------------------------------------------------------------*/
3486 static void genInline (iCode *ic)
3488 char buffer[MAX_INLINEASM];
3492 inLine += (!options.asmpeep);
3493 strcpy(buffer,IC_INLINE(ic));
3495 /* emit each line as a code */
3514 /* emitcode("",buffer); */
3515 inLine -= (!options.asmpeep);
3518 /*-----------------------------------------------------------------*/
3519 /* genRRC - rotate right with carry */
3520 /*-----------------------------------------------------------------*/
3521 static void genRRC (iCode *ic)
3526 /*-----------------------------------------------------------------*/
3527 /* genRLC - generate code for rotate left with carry */
3528 /*-----------------------------------------------------------------*/
3529 static void genRLC (iCode *ic)
3534 /*-----------------------------------------------------------------*/
3535 /* shiftR2Left2Result - shift right two bytes from left to result */
3536 /*-----------------------------------------------------------------*/
3537 static void shiftR2Left2Result (operand *left, int offl,
3538 operand *result, int offr,
3539 int shCount, int sign)
3541 movLeft2Result(left, offl, result, offr, 0);
3542 movLeft2Result(left, offl+1, result, offr+1, 0);
3548 /* if (AOP(result)->type == AOP_REG) {*/
3551 symbol *tlbl , *tlbl1;
3554 tlbl = newiTempLabel(NULL);
3555 tlbl1 = newiTempLabel(NULL);
3557 /* Left is already in result - so now do the shift */
3559 emit2("ld a,!immedbyte+1", shCount);
3560 emit2("!shortjp !tlabel", tlbl1->key+100);
3561 emitLabel(tlbl->key+100);
3564 emitcode("or", "a,a");
3567 l = aopGet(AOP(result), --offset, FALSE);
3568 emitcode("rr","%s", l);
3571 emitLabel(tlbl1->key+100);
3572 emitcode("dec", "a");
3573 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3578 /*-----------------------------------------------------------------*/
3579 /* shiftL2Left2Result - shift left two bytes from left to result */
3580 /*-----------------------------------------------------------------*/
3581 static void shiftL2Left2Result (operand *left, int offl,
3582 operand *result, int offr, int shCount)
3584 if(sameRegs(AOP(result), AOP(left)) &&
3585 ((offl + MSB16) == offr)){
3588 /* Copy left into result */
3589 movLeft2Result(left, offl, result, offr, 0);
3590 movLeft2Result(left, offl+1, result, offr+1, 0);
3592 /* PENDING: for now just see if it'll work. */
3593 /*if (AOP(result)->type == AOP_REG) { */
3597 symbol *tlbl , *tlbl1;
3600 tlbl = newiTempLabel(NULL);
3601 tlbl1 = newiTempLabel(NULL);
3603 /* Left is already in result - so now do the shift */
3605 emit2("ld a,!immedbyte+1", shCount);
3606 emit2("!shortjp !tlabel", tlbl1->key+100);
3607 emitLabel(tlbl->key+100);
3610 emitcode("or", "a,a");
3612 l = aopGet(AOP(result),offset++,FALSE);
3613 emitcode("rl","%s", l);
3616 emitLabel(tlbl1->key+100);
3617 emitcode("dec", "a");
3618 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3623 /*-----------------------------------------------------------------*/
3624 /* AccRol - rotate left accumulator by known count */
3625 /*-----------------------------------------------------------------*/
3626 static void AccRol (int shCount)
3628 shCount &= 0x0007; // shCount : 0..7
3665 /*-----------------------------------------------------------------*/
3666 /* AccLsh - left shift accumulator by known count */
3667 /*-----------------------------------------------------------------*/
3668 static void AccLsh (int shCount)
3672 emitcode("add","a,a");
3674 else if(shCount == 2) {
3675 emitcode("add","a,a");
3676 emitcode("add","a,a");
3678 /* rotate left accumulator */
3680 /* and kill the lower order bits */
3681 emit2("and a,!immedbyte", SLMask[shCount]);
3686 /*-----------------------------------------------------------------*/
3687 /* shiftL1Left2Result - shift left one byte from left to result */
3688 /*-----------------------------------------------------------------*/
3689 static void shiftL1Left2Result (operand *left, int offl,
3690 operand *result, int offr, int shCount)
3693 l = aopGet(AOP(left),offl,FALSE);
3695 /* shift left accumulator */
3697 aopPut(AOP(result),"a",offr);
3701 /*-----------------------------------------------------------------*/
3702 /* genlshTwo - left shift two bytes by known amount != 0 */
3703 /*-----------------------------------------------------------------*/
3704 static void genlshTwo (operand *result,operand *left, int shCount)
3706 int size = AOP_SIZE(result);
3710 /* if shCount >= 8 */
3715 movLeft2Result(left, LSB, result, MSB16, 0);
3716 aopPut(AOP(result),zero, 0);
3717 shiftL1Left2Result(left, MSB16, result, MSB16, shCount);
3720 movLeft2Result(left, LSB, result, MSB16, 0);
3721 aopPut(AOP(result),zero, 0);
3725 aopPut(AOP(result),zero,LSB);
3728 /* 1 <= shCount <= 7 */
3734 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3739 /*-----------------------------------------------------------------*/
3740 /* genlshOne - left shift a one byte quantity by known count */
3741 /*-----------------------------------------------------------------*/
3742 static void genlshOne (operand *result, operand *left, int shCount)
3744 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3747 /*-----------------------------------------------------------------*/
3748 /* genLeftShiftLiteral - left shifting by known count */
3749 /*-----------------------------------------------------------------*/
3750 static void genLeftShiftLiteral (operand *left,
3755 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3758 freeAsmop(right,NULL,ic);
3760 aopOp(left,ic,FALSE, FALSE);
3761 aopOp(result,ic,FALSE, FALSE);
3763 size = getSize(operandType(result));
3766 emitcode("; shift left ","result %d, left %d",size,
3770 /* I suppose that the left size >= result size */
3775 else if(shCount >= (size * 8))
3777 aopPut(AOP(result),zero,size);
3781 genlshOne (result,left,shCount);
3784 genlshTwo (result,left,shCount);
3793 freeAsmop(left,NULL,ic);
3794 freeAsmop(result,NULL,ic);
3797 /*-----------------------------------------------------------------*/
3798 /* genLeftShift - generates code for left shifting */
3799 /*-----------------------------------------------------------------*/
3800 static void genLeftShift (iCode *ic)
3804 symbol *tlbl , *tlbl1;
3805 operand *left,*right, *result;
3807 right = IC_RIGHT(ic);
3809 result = IC_RESULT(ic);
3811 aopOp(right,ic,FALSE, FALSE);
3813 /* if the shift count is known then do it
3814 as efficiently as possible */
3815 if (AOP_TYPE(right) == AOP_LIT) {
3816 genLeftShiftLiteral (left,right,result,ic);
3820 /* shift count is unknown then we have to form a loop get the loop
3821 count in B : Note: we take only the lower order byte since
3822 shifting more that 32 bits make no sense anyway, ( the largest
3823 size of an object can be only 32 bits ) */
3824 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3825 emitcode("inc","a");
3826 freeAsmop (right,NULL,ic);
3827 aopOp(left,ic,FALSE, FALSE);
3828 aopOp(result,ic,FALSE, FALSE);
3830 /* now move the left to the result if they are not the
3833 if (!sameRegs(AOP(left),AOP(result))) {
3835 size = AOP_SIZE(result);
3838 l = aopGet(AOP(left),offset,FALSE);
3839 aopPut(AOP(result),l,offset);
3844 size = AOP_SIZE(result);
3847 l = aopGet(AOP(left),offset,FALSE);
3848 aopPut(AOP(result),l,offset);
3854 tlbl = newiTempLabel(NULL);
3855 size = AOP_SIZE(result);
3857 tlbl1 = newiTempLabel(NULL);
3859 emit2("!shortjp !tlabel", tlbl1->key+100);
3860 emitLabel(tlbl->key+100);
3861 l = aopGet(AOP(result),offset,FALSE);
3862 emitcode("or", "a,a");
3864 l = aopGet(AOP(result),offset++,FALSE);
3865 emitcode("rl","%s", l);
3867 emitLabel(tlbl1->key+100);
3868 emitcode("dec", "a");
3869 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3871 freeAsmop(left,NULL,ic);
3872 freeAsmop(result,NULL,ic);
3875 /*-----------------------------------------------------------------*/
3876 /* genrshOne - left shift two bytes by known amount != 0 */
3877 /*-----------------------------------------------------------------*/
3878 static void genrshOne (operand *result,operand *left, int shCount)
3881 int size = AOP_SIZE(result);
3887 l = aopGet(AOP(left),0,FALSE);
3888 if (AOP(result)->type == AOP_REG) {
3889 aopPut(AOP(result), l, 0);
3890 l = aopGet(AOP(result), 0, FALSE);
3892 emitcode("srl", "%s", l);
3897 emitcode("srl", "a");
3899 aopPut(AOP(result),"a",0);
3903 /*-----------------------------------------------------------------*/
3904 /* AccRsh - right shift accumulator by known count */
3905 /*-----------------------------------------------------------------*/
3906 static void AccRsh (int shCount)
3909 /* rotate right accumulator */
3910 AccRol(8 - shCount);
3911 /* and kill the higher order bits */
3912 emit2("and a,!immedbyte", SRMask[shCount]);
3916 /*-----------------------------------------------------------------*/
3917 /* shiftR1Left2Result - shift right one byte from left to result */
3918 /*-----------------------------------------------------------------*/
3919 static void shiftR1Left2Result (operand *left, int offl,
3920 operand *result, int offr,
3921 int shCount, int sign)
3923 MOVA(aopGet(AOP(left),offl,FALSE));
3930 aopPut(AOP(result),"a",offr);
3933 /*-----------------------------------------------------------------*/
3934 /* genrshTwo - right shift two bytes by known amount != 0 */
3935 /*-----------------------------------------------------------------*/
3936 static void genrshTwo (operand *result,operand *left,
3937 int shCount, int sign)
3939 /* if shCount >= 8 */
3943 shiftR1Left2Result(left, MSB16, result, LSB,
3947 movLeft2Result(left, MSB16, result, LSB, sign);
3949 aopPut(AOP(result),zero,1);
3951 /* 1 <= shCount <= 7 */
3953 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3957 /*-----------------------------------------------------------------*/
3958 /* genRightShiftLiteral - left shifting by known count */
3959 /*-----------------------------------------------------------------*/
3960 static void genRightShiftLiteral (operand *left,
3965 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3968 freeAsmop(right,NULL,ic);
3970 aopOp(left,ic,FALSE, FALSE);
3971 aopOp(result,ic,FALSE, FALSE);
3973 size = getSize(operandType(result));
3975 emitcode("; shift right ","result %d, left %d",size,
3978 /* I suppose that the left size >= result size */
3983 else if(shCount >= (size * 8))
3985 aopPut(AOP(result),zero,size);
3989 genrshOne(result, left, shCount);
3992 /* PENDING: sign support */
3993 genrshTwo(result, left, shCount, FALSE);
4002 freeAsmop(left,NULL,ic);
4003 freeAsmop(result,NULL,ic);
4006 /*-----------------------------------------------------------------*/
4007 /* genRightShift - generate code for right shifting */
4008 /*-----------------------------------------------------------------*/
4009 static void genRightShift (iCode *ic)
4011 operand *right, *left, *result;
4013 int size, offset, first = 1;
4017 symbol *tlbl, *tlbl1 ;
4019 /* if signed then we do it the hard way preserve the
4020 sign bit moving it inwards */
4021 retype = getSpec(operandType(IC_RESULT(ic)));
4023 is_signed = !SPEC_USIGN(retype);
4025 /* signed & unsigned types are treated the same : i.e. the
4026 signed is NOT propagated inwards : quoting from the
4027 ANSI - standard : "for E1 >> E2, is equivalent to division
4028 by 2**E2 if unsigned or if it has a non-negative value,
4029 otherwise the result is implementation defined ", MY definition
4030 is that the sign does not get propagated */
4032 right = IC_RIGHT(ic);
4034 result = IC_RESULT(ic);
4036 aopOp(right,ic,FALSE, FALSE);
4038 /* if the shift count is known then do it
4039 as efficiently as possible */
4040 if (AOP_TYPE(right) == AOP_LIT) {
4041 genRightShiftLiteral(left,right,result,ic);
4045 aopOp(left,ic,FALSE, FALSE);
4046 aopOp(result,ic,FALSE, FALSE);
4048 /* now move the left to the result if they are not the
4050 if (!sameRegs(AOP(left),AOP(result)) &&
4051 AOP_SIZE(result) > 1) {
4053 size = AOP_SIZE(result);
4056 l = aopGet(AOP(left),offset,FALSE);
4057 aopPut(AOP(result),l,offset);
4062 emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
4063 emitcode("inc","a");
4064 freeAsmop (right, NULL, ic);
4066 tlbl = newiTempLabel(NULL);
4067 tlbl1= newiTempLabel(NULL);
4068 size = AOP_SIZE(result);
4071 emit2("!shortjp !tlabel", tlbl1->key+100);
4072 emitLabel(tlbl->key+100);
4074 l = aopGet(AOP(result),offset--,FALSE);
4077 emitcode("sra", "%s", l);
4079 emitcode("srl", "%s", l);
4083 emitcode("rr", "%s", l);
4085 emitLabel(tlbl1->key+100);
4086 emitcode("dec", "a");
4087 emit2("!shortjp nz,!tlabel", tlbl->key+100);
4089 freeAsmop(left,NULL,ic);
4090 freeAsmop(result,NULL,ic);
4093 /*-----------------------------------------------------------------*/
4094 /* genGenPointerGet - get value from generic pointer space */
4095 /*-----------------------------------------------------------------*/
4096 static void genGenPointerGet (operand *left,
4097 operand *result, iCode *ic)
4100 link *retype = getSpec(operandType(result));
4106 aopOp(left,ic,FALSE, FALSE);
4107 aopOp(result,ic,FALSE, FALSE);
4109 if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
4111 if (isPtrPair(AOP(left)))
4113 tsprintf(buffer, "!*pair", getPairName(AOP(left)));
4114 aopPut(AOP(result), buffer, 0);
4117 emit2("ld a,!*pair", getPairName(AOP(left)));
4118 aopPut(AOP(result),"a", 0);
4120 freeAsmop(left,NULL,ic);
4124 /* For now we always load into IY */
4125 /* if this is remateriazable */
4126 fetchPair(pair, AOP(left));
4128 /* so iy now contains the address */
4129 freeAsmop(left,NULL,ic);
4131 /* if bit then unpack */
4132 if (IS_BITVAR(retype)) {
4136 size = AOP_SIZE(result);
4140 /* PENDING: make this better */
4141 if (!IS_GB && AOP(result)->type == AOP_REG) {
4142 aopPut(AOP(result), "!*hl", offset++);
4145 emit2("ld a,!*pair", _pairs[pair].name);
4146 aopPut(AOP(result),"a",offset++);
4149 emit2("inc %s", _pairs[pair].name);
4150 _G.pairs[pair].offset++;
4156 freeAsmop(result,NULL,ic);
4159 /*-----------------------------------------------------------------*/
4160 /* genPointerGet - generate code for pointer get */
4161 /*-----------------------------------------------------------------*/
4162 static void genPointerGet (iCode *ic)
4164 operand *left, *result ;
4168 result = IC_RESULT(ic) ;
4170 /* depending on the type of pointer we need to
4171 move it to the correct pointer register */
4172 type = operandType(left);
4173 etype = getSpec(type);
4175 genGenPointerGet (left,result,ic);
4178 bool isRegOrLit(asmop *aop)
4180 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4185 /*-----------------------------------------------------------------*/
4186 /* genGenPointerSet - stores the value into a pointer location */
4187 /*-----------------------------------------------------------------*/
4188 static void genGenPointerSet (operand *right,
4189 operand *result, iCode *ic)
4192 link *retype = getSpec(operandType(right));
4193 PAIR_ID pairId = PAIR_HL;
4195 aopOp(result,ic,FALSE, FALSE);
4196 aopOp(right,ic,FALSE, FALSE);
4201 /* Handle the exceptions first */
4202 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
4204 char *l = aopGet(AOP(right), 0, FALSE);
4205 const char *pair = getPairName(AOP(result));
4206 if (canAssignToPtr(l) && isPtr(pair)) {
4207 emit2("ld !*pair,%s", pair, l);
4211 emit2("ld !*pair,a", pair);
4216 /* if the operand is already in dptr
4217 then we do nothing else we move the value to dptr */
4218 if (AOP_TYPE(result) != AOP_STR) {
4219 fetchPair(pairId, AOP(result));
4221 /* so hl know contains the address */
4222 freeAsmop(result,NULL,ic);
4224 /* if bit then unpack */
4225 if (IS_BITVAR(retype)) {
4229 size = AOP_SIZE(right);
4233 char *l = aopGet(AOP(right),offset,FALSE);
4234 if (isRegOrLit(AOP(right)) && !IS_GB) {
4235 emit2("ld !*pair,%s", _pairs[pairId].name, l);
4239 emit2("ld !*pair,a", _pairs[pairId].name);
4242 emitcode("inc", _pairs[pairId].name);
4243 _G.pairs[pairId].offset++;
4249 freeAsmop(right,NULL,ic);
4252 /*-----------------------------------------------------------------*/
4253 /* genPointerSet - stores the value into a pointer location */
4254 /*-----------------------------------------------------------------*/
4255 static void genPointerSet (iCode *ic)
4257 operand *right, *result ;
4260 right = IC_RIGHT(ic);
4261 result = IC_RESULT(ic) ;
4263 /* depending on the type of pointer we need to
4264 move it to the correct pointer register */
4265 type = operandType(result);
4266 etype = getSpec(type);
4268 genGenPointerSet (right,result,ic);
4271 /*-----------------------------------------------------------------*/
4272 /* genIfx - generate code for Ifx statement */
4273 /*-----------------------------------------------------------------*/
4274 static void genIfx (iCode *ic, iCode *popIc)
4276 operand *cond = IC_COND(ic);
4279 aopOp(cond,ic,FALSE, TRUE);
4281 /* get the value into acc */
4282 if (AOP_TYPE(cond) != AOP_CRY)
4286 /* the result is now in the accumulator */
4287 freeAsmop(cond,NULL,ic);
4289 /* if there was something to be popped then do it */
4293 /* if the condition is a bit variable */
4294 if (isbit && IS_ITEMP(cond) &&
4296 genIfxJump(ic,SPIL_LOC(cond)->rname);
4298 if (isbit && !IS_ITEMP(cond))
4299 genIfxJump(ic,OP_SYMBOL(cond)->rname);
4306 /*-----------------------------------------------------------------*/
4307 /* genAddrOf - generates code for address of */
4308 /*-----------------------------------------------------------------*/
4309 static void genAddrOf (iCode *ic)
4311 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4313 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4315 /* if the operand is on the stack then we
4316 need to get the stack offset of this
4321 if (sym->stack <= 0) {
4322 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
4325 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
4327 emitcode("ld", "d,h");
4328 emitcode("ld", "e,l");
4331 emit2("ld de,!hashedstr", sym->rname);
4333 aopPut(AOP(IC_RESULT(ic)), "e", 0);
4334 aopPut(AOP(IC_RESULT(ic)), "d", 1);
4339 /* if it has an offset then we need to compute it */
4340 emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
4341 emitcode("add", "hl,sp");
4344 emitcode("ld", "hl,#%s", sym->rname);
4346 aopPut(AOP(IC_RESULT(ic)), "l", 0);
4347 aopPut(AOP(IC_RESULT(ic)), "h", 1);
4349 freeAsmop(IC_RESULT(ic),NULL,ic);
4352 /*-----------------------------------------------------------------*/
4353 /* genAssign - generate code for assignment */
4354 /*-----------------------------------------------------------------*/
4355 static void genAssign (iCode *ic)
4357 operand *result, *right;
4359 unsigned long lit = 0L;
4361 result = IC_RESULT(ic);
4362 right = IC_RIGHT(ic) ;
4365 /* Dont bother assigning if they are the same */
4366 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
4367 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
4372 aopOp(right,ic,FALSE, FALSE);
4373 aopOp(result,ic,TRUE, FALSE);
4375 /* if they are the same registers */
4376 if (sameRegs(AOP(right),AOP(result))) {
4377 emitcode("", "; (registers are the same)");
4381 /* if the result is a bit */
4382 if (AOP_TYPE(result) == AOP_CRY) {
4387 size = AOP_SIZE(result);
4390 if(AOP_TYPE(right) == AOP_LIT)
4391 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4392 if (isPair(AOP(result))) {
4393 fetchPair(getPairId(AOP(result)), AOP(right));
4395 else if((size > 1) &&
4396 (AOP_TYPE(result) != AOP_REG) &&
4397 (AOP_TYPE(right) == AOP_LIT) &&
4398 !IS_FLOAT(operandType(right)) &&
4400 bool fXored = FALSE;
4402 /* Work from the top down.
4403 Done this way so that we can use the cached copy of 0
4404 in A for a fast clear */
4406 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
4407 if (!fXored && size>1) {
4408 emitcode("xor", "a,a");
4412 aopPut(AOP(result),"a",offset);
4415 aopPut(AOP(result), zero, offset);
4420 aopGet(AOP(right),offset,FALSE),
4425 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result)) && IS_GB) {
4426 /* Special case. Load into a and d, then load out. */
4427 MOVA(aopGet(AOP(right), 0, FALSE));
4428 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
4429 aopPut(AOP(result), "a", 0);
4430 aopPut(AOP(result), "e", 1);
4433 /* PENDING: do this check better */
4434 if (requiresHL(AOP(right)) && requiresHL(AOP(result))) {
4435 MOVA(aopGet(AOP(right), offset, FALSE));
4436 aopPut(AOP(result), "a", offset);
4440 aopGet(AOP(right),offset,FALSE),
4447 freeAsmop(right,NULL,ic);
4448 freeAsmop(result,NULL,ic);
4451 /*-----------------------------------------------------------------*/
4452 /* genJumpTab - genrates code for jump table */
4453 /*-----------------------------------------------------------------*/
4454 static void genJumpTab (iCode *ic)
4459 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
4460 /* get the condition into accumulator */
4461 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
4463 emitcode("push", "de");
4464 emitcode("ld", "e,%s", l);
4465 emit2("ld d,!zero");
4466 jtab = newiTempLabel(NULL);
4468 emit2("ld hl,!immed!tlabel", jtab->key+100);
4469 emitcode("add", "hl,de");
4470 emitcode("add", "hl,de");
4471 emitcode("add", "hl,de");
4472 freeAsmop(IC_JTCOND(ic),NULL,ic);
4474 emitcode("pop", "de");
4476 emitLabel(jtab->key+100);
4477 /* now generate the jump labels */
4478 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4479 jtab = setNextItem(IC_JTLABELS(ic)))
4480 emit2("jp !tlabel", jtab->key+100);
4483 /*-----------------------------------------------------------------*/
4484 /* genCast - gen code for casting */
4485 /*-----------------------------------------------------------------*/
4486 static void genCast (iCode *ic)
4488 operand *result = IC_RESULT(ic);
4489 link *ctype = operandType(IC_LEFT(ic));
4490 operand *right = IC_RIGHT(ic);
4493 /* if they are equivalent then do nothing */
4494 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4497 aopOp(right,ic,FALSE, FALSE);
4498 aopOp(result,ic,FALSE, FALSE);
4500 /* if the result is a bit */
4501 if (AOP_TYPE(result) == AOP_CRY) {
4505 /* if they are the same size : or less */
4506 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4508 /* if they are in the same place */
4509 if (sameRegs(AOP(right),AOP(result)))
4512 /* if they in different places then copy */
4513 size = AOP_SIZE(result);
4517 aopGet(AOP(right),offset,FALSE),
4524 /* PENDING: should be OK. */
4526 /* if the result is of type pointer */
4527 if (IS_PTR(ctype)) {
4532 /* so we now know that the size of destination is greater
4533 than the size of the source */
4534 /* we move to result for the size of source */
4535 size = AOP_SIZE(right);
4539 aopGet(AOP(right),offset,FALSE),
4544 /* now depending on the sign of the destination */
4545 size = AOP_SIZE(result) - AOP_SIZE(right);
4546 /* Unsigned or not an integral type - right fill with zeros */
4547 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4549 aopPut(AOP(result),zero,offset++);
4551 /* we need to extend the sign :{ */
4552 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4555 emitcode("", "; genCast: sign extend untested.");
4556 emitcode("rla", "");
4557 emitcode("sbc", "a,a");
4559 aopPut(AOP(result),"a",offset++);
4563 freeAsmop(right, NULL, ic);
4564 freeAsmop(result, NULL, ic);
4567 /*-----------------------------------------------------------------*/
4568 /* genReceive - generate code for a receive iCode */
4569 /*-----------------------------------------------------------------*/
4570 static void genReceive (iCode *ic)
4572 if (isOperandInFarSpace(IC_RESULT(ic)) &&
4573 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4574 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4578 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4580 assignResultValue(IC_RESULT(ic));
4583 freeAsmop(IC_RESULT(ic),NULL,ic);
4586 /*-----------------------------------------------------------------*/
4587 /* genZ80Code - generate code for Z80 based controllers */
4588 /*-----------------------------------------------------------------*/
4589 void genZ80Code (iCode *lic)
4596 _fReturn = _gbz80_return;
4597 _fTmp = _gbz80_return;
4600 _fReturn = _z80_return;
4601 _fTmp = _z80_return;
4603 tsprintf(zero, "!zero");
4605 lineHead = lineCurr = NULL;
4607 /* if debug information required */
4608 if (options.debug && currFunc) {
4609 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4611 if (IS_STATIC(currFunc->etype))
4612 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4614 emitcode("","G$%s$0$0 ==.",currFunc->name);
4617 /* stack pointer name */
4621 for (ic = lic ; ic ; ic = ic->next ) {
4623 if ( cln != ic->lineno ) {
4624 if ( options.debug ) {
4626 emitcode("","C$%s$%d$%d$%d ==.",
4627 ic->filename,ic->lineno,
4628 ic->level,ic->block);
4631 emitcode(";","%s %d",ic->filename,ic->lineno);
4634 /* if the result is marked as
4635 spilt and rematerializable or code for
4636 this has already been generated then
4638 if (resultRemat(ic) || ic->generated )
4641 /* depending on the operation */
4644 emitcode("", "; genNot");
4649 emitcode("", "; genCpl");
4654 emitcode("", "; genUminus");
4659 emitcode("", "; genIpush");
4664 /* IPOP happens only when trying to restore a
4665 spilt live range, if there is an ifx statement
4666 following this pop then the if statement might
4667 be using some of the registers being popped which
4668 would destory the contents of the register so
4669 we need to check for this condition and handle it */
4671 ic->next->op == IFX &&
4672 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4673 emitcode("", "; genIfx");
4674 genIfx (ic->next,ic);
4677 emitcode("", "; genIpop");
4683 emitcode("", "; genCall");
4688 emitcode("", "; genPcall");
4693 emitcode("", "; genFunction");
4698 emitcode("", "; genEndFunction");
4699 genEndFunction (ic);
4703 emitcode("", "; genRet");
4708 emitcode("", "; genLabel");
4713 emitcode("", "; genGoto");
4718 emitcode("", "; genPlus");
4723 emitcode("", "; genMinus");
4728 emitcode("", "; genMult");
4733 emitcode("", "; genDiv");
4738 emitcode("", "; genMod");
4743 emitcode("", "; genCmpGt");
4744 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4748 emitcode("", "; genCmpLt");
4749 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4756 /* note these two are xlated by algebraic equivalence
4757 during parsing SDCC.y */
4758 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4759 "got '>=' or '<=' shouldn't have come here");
4763 emitcode("", "; genCmpEq");
4764 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4768 emitcode("", "; genAndOp");
4773 emitcode("", "; genOrOp");
4778 emitcode("", "; genXor");
4779 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4783 emitcode("", "; genOr");
4784 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4788 emitcode("", "; genAnd");
4789 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4793 emitcode("", "; genInline");
4798 emitcode("", "; genRRC");
4803 emitcode("", "; genRLC");
4808 emitcode("", "; genHBIT");
4812 emitcode("", "; genLeftShift");
4817 emitcode("", "; genRightShift");
4821 case GET_VALUE_AT_ADDRESS:
4822 emitcode("", "; genPointerGet");
4828 if (POINTER_SET(ic)) {
4829 emitcode("", "; genAssign (pointer)");
4833 emitcode("", "; genAssign");
4839 emitcode("", "; genIfx");
4844 emitcode("", "; genAddrOf");
4849 emitcode("", "; genJumpTab");
4854 emitcode("", "; genCast");
4859 emitcode("", "; genReceive");
4864 emitcode("", "; addSet");
4865 addSet(&sendSet,ic);
4870 /* piCode(ic,stdout); */
4876 /* now we are ready to call the
4877 peep hole optimizer */
4878 if (!options.nopeep)
4879 peepHole (&lineHead);
4881 /* This is unfortunate */
4882 /* now do the actual printing */
4884 FILE *fp = codeOutFile;
4885 if (isInHome() && codeOutFile == code->oFile)
4886 codeOutFile = home->oFile;
4887 printLine (lineHead, codeOutFile);
4888 if (_G.flush_statics) {
4890 _G.flush_statics = 0;