static bool doTermScan (lineNode **pl, const char *what) { const char *operand, *op1start, *op2start; for (; *pl; *pl = (*pl)->next) { operand = nextToken((*pl)->line); if(! (op1start = nextToken(NULL)) ) continue; if(EQUALS(operand, "ld") || EQUALS(operand, "mov") || EQUALS(operand, "clr")) return(EQUALS(op1start, what)); if(EQUALS(op1start, what)) return(FALSE); /*if(op2start && EQUALS(op2start, what)) TODO: enable this (but make op2start point somewhere first) return(FALSE);*/ if(EQUALS(operand, "ret") || EQUALS(operand, "iret")) return(FALSE); /* TODO */ if(ISINST(operand, "jp") || ISINST(operand, "jr")) return(FALSE); if(ISINST(operand, "call")) return(FALSE); } return(FALSE); }
static int instructionSize(char *inst, char *op1, char *op2) { #define ISINST(s) (strncmp(inst, (s), sizeof(s)-1) == 0) #define IS_A(s) (*(s) == 'a' && *(s+1) == '\0') #define IS_C(s) (*(s) == 'c' && *(s+1) == '\0') #define IS_Rn(s) (*(s) == 'r' && *(s+1) >= '0' && *(s+1) <= '7') #define IS_atRi(s) (*(s) == '@' && *(s+1) == 'r') /* Based on the current (2003-08-22) code generation for the small library, the top instruction probability is: 57% mov/movx/movc 6% push 6% pop 4% inc 4% lcall 4% add 3% clr 2% subb */ /* mov, push, & pop are the 69% of the cases. Check them first! */ if (ISINST ("mov")) { if (*(inst+3)=='x') return 1; /* movx */ if (*(inst+3)=='c') return 1; /* movc */ if (IS_C (op1) || IS_C (op2)) return 2; if (IS_A (op1)) { if (IS_Rn (op2) || IS_atRi (op2)) return 1; return 2; } if (IS_Rn(op1) || IS_atRi(op1)) { if (IS_A(op2)) return 1; return 2; } if (strcmp (op1, "dptr") == 0) return 3; if (IS_A (op2) || IS_Rn (op2) || IS_atRi (op2)) return 2; return 3; } if (ISINST ("push")) return 2; if (ISINST ("pop")) return 2; if (ISINST ("lcall")) return 3; if (ISINST ("ret")) return 1; if (ISINST ("ljmp")) return 3; if (ISINST ("sjmp")) return 2; if (ISINST ("rlc")) return 1; if (ISINST ("rrc")) return 1; if (ISINST ("rl")) return 1; if (ISINST ("rr")) return 1; if (ISINST ("swap")) return 1; if (ISINST ("jc")) return 2; if (ISINST ("jnc")) return 2; if (ISINST ("jb")) return 3; if (ISINST ("jnb")) return 3; if (ISINST ("jbc")) return 3; if (ISINST ("jmp")) return 1; // always jmp @a+dptr if (ISINST ("jz")) return 2; if (ISINST ("jnz")) return 2; if (ISINST ("cjne")) return 3; if (ISINST ("mul")) return 1; if (ISINST ("div")) return 1; if (ISINST ("da")) return 1; if (ISINST ("xchd")) return 1; if (ISINST ("reti")) return 1; if (ISINST ("nop")) return 1; if (ISINST ("acall")) return 2; if (ISINST ("ajmp")) return 2; if (ISINST ("add") || ISINST ("addc") || ISINST ("subb") || ISINST ("xch")) { if (IS_Rn(op2) || IS_atRi(op2)) return 1; return 2; } if (ISINST ("inc") || ISINST ("dec")) { if (IS_A(op1) || IS_Rn(op1) || IS_atRi(op1)) return 1; if (strcmp(op1, "dptr") == 0) return 1; return 2; } if (ISINST ("anl") || ISINST ("orl") || ISINST ("xrl")) { if (IS_C(op1)) return 2; if (IS_A(op1)) { if (IS_Rn(op2) || IS_atRi(op2)) return 1; return 2; } else { if (IS_A(op2)) return 2; return 3; } } if (ISINST ("clr") || ISINST ("setb") || ISINST ("cpl")) { if (IS_A(op1) || IS_C(op1)) return 1; return 2; } if (ISINST ("djnz")) { if (IS_Rn(op1)) return 2; return 3; } /* If the instruction is unrecognized, we shouldn't try to optimize. */ /* Return a large value to discourage optimization. */ return 999; }
int stm8instructionSize(const lineNode *pl) { char *operand; char *op1start; char *op2start; int i = 0; operand = nextToken(pl->line); op1start = nextToken(NULL); op2start = nextToken(NULL); //fprintf(stderr, "op1start=%s op2start=%s\n", op1start, op2start); while(op2start && isspace(*op2start)) op2start++; //printf("operand=%s op1start=%s op2start=%s\n", operand, op1start, op2start); /* arity=1 */ if(EQUALS(operand, "clr") || EQUALS(operand, "dec") || EQUALS(operand, "inc") || EQUALS(operand, "push") || EQUALS(operand, "swap") || EQUALS(operand, "jp") || EQUALS(operand, "cpl") || EQUALS(operand, "tnz")) { if(!op1start) return(3); if(op1start[0] == 'a' || op1start[1] == 'x') return(1); if(op1start[1] == 'y') return(2); if(op1start[0] == '(') op1start++; if(strstr(op1start, ",y)")) i++; // costs extra byte for operating with y if(isLabel(op1start)) return(3); if(readint(op1start) <= 0xFF) return(2+i); /* op1 > 0xFF */ if(EQUALS(operand, "jp") && !strchr(op1start, 'y')) return(3); return(4); } if(EQUALS(operand, "exg")) { if(isReg(op2start)) return(1); else return(3); } if(EQUALS(operand, "addw") || EQUALS(operand, "subw")) { if(isImmediate(op2start) && op1start[0] == 'y') return(4); if(isImmediate(op2start)) return(3); if(isSpIndexed(op2start)) return(3); if(isLongoff(op2start, "x")) return(4); } if(EQUALS(operand, "cplw")) { if(op1start[0] == 'y') return(2); else return(1); } if(EQUALS(operand, "ldf")) { if(isRelativeAddr(op1start, "y") || isRelativeAddr(op2start, "y")) return(5); else return(4); } /* Operations that costs 2 or 3 bytes for immediate */ if(ISINST(operand, "ld") || EQUALS(operand, "cp") || EQUALS(operand, "cpw") || ISINST(operand, "adc") || EQUALS(operand, "add") || ISINST(operand, "and") || ISINST(operand, "bcp") || ISINST(operand, "call") || ISINST(operand, "callr") || ISINST(operand, "jr") || ISINST(operand, "or") || ISINST(operand, "sbc") || EQUALS(operand, "sub") || ISINST(operand, "xor")) { char suffix; if(!op1start || !op2start) return(4); suffix = operand[strlen(operand)-1]; if(suffix == 'w' && isImmediate(op2start)) i++; // costs extra byte if(isSpIndexed(op1start) || isSpIndexed(op2start)) return(2); if(!strcmp(op1start, "(x)") || !strcmp(op2start, "(x)")) return(1); if(!strcmp(op1start, "(y)") || !strcmp(op2start, "(y)")) return(2); if(isLabel(op1start) || isLabel(op2start)) return(3+i); if(isShortoff(op1start, "x") || isShortoff(op2start, "x")) return(2); if(isShortoff(op1start, "y") || isShortoff(op2start, "y")) return(3); if(isLongoff(op1start, "x") || isLongoff(op2start, "x")) return(3); if(isRelativeAddr(op1start, "y")) return(4); if(strchr(op1start, 'y') || (strchr(op2start, 'y') && !EQUALS(operand, "ldw"))) i++; // costs extra byte for operating with y if(isReg(op1start) && isReg(op2start)) return(1+i); if(op2start[0] == '#') return(2+i); // ld reg, #immd if(readint(op2start) <= 0xFF) return(2+i); return(3+i); } /* mov costs 3, 4 or 5 bytes depending on it's addressing mode */ if(EQUALS(operand, "mov")) { if(op2start && op2start[0] == '#') return(4); if(op2start && isLabel(op2start)) return(5); if(op2start && readint(op2start) <= 0xFF) return(3); if(op2start && readint(op2start) > 0xFF) return(5); } /* Operations that always costs 1 byte */ if(EQUALS(operand, "ccf") || EQUALS(operand, "divw") || EQUALS(operand, "exgw") || EQUALS(operand, "iret") || EQUALS(operand, "nop") || EQUALS(operand, "rcf") || EQUALS(operand, "ret") || EQUALS(operand, "retf") || EQUALS(operand, "rvf") || EQUALS(operand, "scf")) { return(1); } /* Operations that costs 2 or 1 bytes depending on is the Y or X register used */ if(EQUALS(operand, "clrw") || EQUALS(operand, "decw") || EQUALS(operand, "div") || EQUALS(operand, "incw") || EQUALS(operand, "mul") || EQUALS(operand, "negw") || EQUALS(operand, "popw") || EQUALS(operand, "pushw") || EQUALS(operand, "rlcw") || EQUALS(operand, "rlwa") || EQUALS(operand, "rrcw") || EQUALS(operand, "rrwa") || EQUALS(operand, "sllw") || EQUALS(operand, "slaw") || EQUALS(operand, "sraw") || EQUALS(operand, "srlw") || EQUALS(operand, "swapw") || EQUALS(operand, "tnzw")) { if((op1start && !strcmp(op1start, "y")) || (op2start && !strcmp(op2start, "y"))) return(2); else return(1); } return(4); }