/* * Misc. useful functions for rasm */ #include #include #include #include #include "rasm.h" #include "util.h" #include "symtab.h" #include "compile.h" int is_number(char *str) { int len = strlen(str); char *last; char *ptr; int base = 10; if (len == 0) return 0; last = str + len - 1; if (*last == 'h') base = 16; if (*last == 'b') base = 2; strtol(str, &ptr, base); if (ptr == str+len) return 1; if ((base == 2 || base == 16) && ptr == str+len-1) return 1; return 0; } int str_to_int(char *str) { char *last; int value, base = 10; if (strlen(str) == 0) return 0; last = str + strlen(str) - 1; if (*last == 'h') base = 16; if (*last == 'b') base = 2; value = strtol(str, &str, base); return value; } reftype gettype(char *refin) { char *ref = alias_resolve(refin); if (0 == strcasecmp(ref, "dptr")) return REF_DPTR; if (0 == strcasecmp(ref, "@dptr")) return REF_IDPTR; if (*ref == '@') return REF_INDIR; if (*ref == '#') { char *newref = ref+1; newref = alias_resolve(newref); if (is_number(newref)) return REF_IMMED; if (symtab_lookup(newref) != -1) return REF_IMMED; if (strlen(newref) == 3 && newref[0] == '\'' && newref[2] == '\'') return REF_IMMED; } if (0 == strcasecmp(ref, "a")) return REF_ACCUM; if (0 == strcasecmp(ref, "c")) return REF_CARRY; if (strlen(ref) == 2 && (ref[0] == 'r' || ref[0] == 'R') && isdigit((int)ref[1])) return REF_REG; if (symtab_lookup(ref) != -1) return REF_DIRECT; if (is_number(ref)) return REF_DIRECT; return REF_UNKNOWN; } int getvalue(char *refin) { char *ref = alias_resolve(refin); reftype type = gettype(ref); if (type == REF_INDIR) { if (0 == strcasecmp(ref+1, "r0")) return 0; if (0 == strcasecmp(ref+1, "r1")) return 1; compile_error("can only indirect r0 and r1"); } if (type == REF_IMMED) { char *newref = ref+1; newref = alias_resolve(newref); if (is_number(newref)) return str_to_int(newref); if (strlen(newref) == 3 && newref[0] == '\'' && newref[2] == '\'') return newref[1]; return symtab_lookup(newref); } if (type == REF_ACCUM || type == REF_CARRY) return 0; if (type == REF_REG) return atoi(ref+1); if (type == REF_DIRECT) { int value = symtab_lookup(ref); if (value != -1) return value; return str_to_int(ref); } /** USE gettype() TO CHECK VALIDITY */ return 0; } int resolve_bit_address(char *ba_str) { char arg[BUFSIZE]; char *alias = alias_resolve(ba_str); char *dot; int dotval = 0; unsigned char bitaddr; reftype ba_type; int ba_val; strncpy(arg, alias, sizeof(arg)); dot = strchr(arg, '.'); if (dot) { *dot = '\0'; dot++; dotval=atoi(dot); } ba_type = gettype(arg); if (ba_type != REF_DIRECT) return -1; ba_val = getvalue(arg); if (ba_val >= 0x20 && ba_val < 0x30) { /* Magic bit-addressable memory */ bitaddr = ba_val-0x20; bitaddr <<= 3; bitaddr |= dotval; } else { /* Assume bit-addressable SFR? */ bitaddr = ba_val+dotval; } return bitaddr; }