📄 moon.c
字号:
case divr: rk = fetchreg(ir.fmta.rk); if (rk == 0) runtimeerror("division by zero"); else { storereg(ir.fmta.ri, fetchreg(ir.fmta.rj) / rk); newreg = ir.fmta.ri; } break; /* mod Ri, Rj, Rk */ case mod: rk = fetchreg(ir.fmta.rk); if (rk == 0) runtimeerror("modulus with zero operand"); else { storereg(ir.fmta.ri, fetchreg(ir.fmta.rj) % rk); newreg = ir.fmta.ri; } break; /* and Ri, Rj, Rk (32-bit logical AND) */ case and: storereg(ir.fmta.ri, fetchreg(ir.fmta.rj) & fetchreg(ir.fmta.rk)); newreg = ir.fmta.ri; break; /* or Ri, Rj, Rk (32-bit logical OR) */ case or: storereg(ir.fmta.ri, fetchreg(ir.fmta.rj) | fetchreg(ir.fmta.rk)); newreg = ir.fmta.ri; break; /* ceq Ri, Rj, Rk (Rj = Rk) */ case ceq: storereg(ir.fmta.ri, fetchreg(ir.fmta.rj) == fetchreg(ir.fmta.rk)); newreg = ir.fmta.ri; break; /* cne Ri, Rj, Rk */ case cne: storereg(ir.fmta.ri, fetchreg(ir.fmta.rj) != fetchreg(ir.fmta.rk)); newreg = ir.fmta.ri; break; /* clt Ri, Rj, Rk */ case clt: storereg(ir.fmta.ri, fetchreg(ir.fmta.rj) < fetchreg(ir.fmta.rk)); newreg = ir.fmta.ri; break; /* cle Ri, Rj, Rk */ case cle: storereg(ir.fmta.ri, fetchreg(ir.fmta.rj) <= fetchreg(ir.fmta.rk)); newreg = ir.fmta.ri; break; /* cgt Ri, Rj, Rk */ case cgt: storereg(ir.fmta.ri, fetchreg(ir.fmta.rj) > fetchreg(ir.fmta.rk)); newreg = ir.fmta.ri; break; /* cge Ri, Rj, Rk */ case cge: storereg(ir.fmta.ri, fetchreg(ir.fmta.rj) >= fetchreg(ir.fmta.rk)); newreg = ir.fmta.ri; break; /* not Ri, Rj (32-bit complement) */ case not: if (fetchreg(ir.fmta.rj) == 0) storereg(ir.fmta.ri, 1); else storereg(ir.fmta.ri, 0); newreg = ir.fmta.ri; break; /* jlr Ri, Rj (Jump to register and link) */ case jlr: storereg(ir.fmta.ri, ic); ic = fetchreg(ir.fmta.rj); newreg = ir.fmta.ri; break; /* nop */ case nop: break; /* hlt */ case hlt: running = FALSE; break; } break; /* Format B instructions have a 16-bit immediate operand. */ case 'b': switch (ir.fmtb.op) { /* lw Ri, K(Rj) (Load word) */ case lw: storereg(ir.fmtb.ri, getmemword(fetchreg(ir.fmtb.rj) + (long) ir.fmtb.k)); newreg = ir.fmtb.ri; break; /* lb Ri, K(Rj) (Load byte) */ case lb: w1 = getmembyte(fetchreg(ir.fmtb.rj) + (long) ir.fmtb.k); w2 = fetchreg(ir.fmtb.ri); storereg(ir.fmtb.ri, (w1) | (w2 & ~255)); newreg = ir.fmtb.ri; break; /* sw K(Rj), Ri (Store word) */ case sw: newmem = fetchreg(ir.fmtb.rj) + (long) ir.fmtb.k; putmemword(newmem, fetchreg(ir.fmtb.ri)); break; /* sb K(Rj), Ri (Store byte) */ case sb: newmem = fetchreg(ir.fmtb.rj) + (long) ir.fmtb.k; putmembyte(newmem, (BYTE) (fetchreg(ir.fmtb.ri) & 255)); break; /* addi Ri, Rj, K (Add immediate) */ case addi: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) + (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* subi Ri, Rj, K */ case subi: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) - (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* muli Ri, Rj, K */ case muli: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) * (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* divi Ri, Rj, K */ case divi: k = (long) ir.fmtb.k; if (k == 0) runtimeerror("division by zero"); else { storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) / k); newreg = ir.fmtb.ri; } break; /* modi Ri, Rj, K */ case modi: k = (long) ir.fmtb.k; if (k == 0) runtimeerror("division by zero"); else { storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) % k); newreg = ir.fmtb.ri; } break; /* andi Ri, Rj, K */ case andi: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) & (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* ori Ri, Rj, K */ case ori: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) | (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* ceqi Ri, Rj, K */ case ceqi: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) == (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* cnei Ri, Rj, K */ case cnei: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) != (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* clti Ri, Rj, K */ case clti: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) < (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* clei Ri, Rj, K */ case clei: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) <= (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* cgti Ri, Rj, K */ case cgti: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) > (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* cgei Ri, Rj, K */ case cgei: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.rj) >= (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* sl Ri, K (Shift left logical) */ case sl: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.ri) << (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* sr Ri, K (Shift right logical) */ case sr: storereg(ir.fmtb.ri, fetchreg(ir.fmtb.ri) >> (long) ir.fmtb.k); newreg = ir.fmtb.ri; break; /* bz Ri, K (Branch to K if Ri == 0) */ case bz: if (fetchreg(ir.fmtb.ri) == 0) ic = (long) ir.fmtb.k; break; /* bnz Ri, K (Branch to K if Ri != 0) */ case bnz: if (fetchreg(ir.fmtb.ri) != 0) ic = (long) ir.fmtb.k; break; /* jl Ri, K (Branch to K with link in Ri) */ case jl: storereg(ir.fmtb.ri, ic); ic = (long) ir.fmtb.k; newreg = ir.fmtb.ri; break; /* getc Ri (Read one character to Ri) */ case gtc: if (tracing) { char buf [256]; printf("\nEnter data for getc: "); fgets(buf, 256, stdin); if (buf[0] == '\0') ch = '\n'; else ch = buf[0]; } else ch = (BYTE) getchar(); storereg(ir.fmtb.ri, ch); newreg = ir.fmtb.ri; break; /* putc Ri (Write the character in Ri) */ case ptc: if (tracing) printf(" Output from putc: %c", fetchreg(ir.fmtb.ri)); else printf("%c", fetchreg(ir.fmtb.ri)); break; /* jr Ri (Jump to Ri) */ case jr: ic = fetchreg(ir.fmtb.ri); break; /* j K (Jump to K) */ case j: ic = (long) ir.fmtb.k; break; } break; } }/* Dump words of memory from addr-10 to addr+10. */void dump (long addr) { long first = (addr - RANGE) & ~3; long last = (addr + RANGE) & ~3; if (first < 0) first = 0; if (last > MEMSIZE) last = MEMSIZE; for (addr = first; addr < last; addr += 4) { showword(addr); printf("\n"); } }/* Display a register. */void showreg (short regnum) { wordtype word; char charbuf [5]; word.data = regs[regnum]; printf(" r%d = %08lX %s %4ld", regnum, word.data, wordtochars(charbuf, word), word.data); }/* Execute one instruction in trace mode. */void traceinstr () { char charbuf [5]; showword(ic); execinstr(TRUE); if (running) { if (newreg >= 0) showreg(newreg); else if (newmem >= 0) { long addr = newmem >> 2; printf(" M[%ld] = %08lX %s %ld", newmem, mem[addr].word.data, wordtochars(charbuf, mem[addr].word), mem[addr].word.data); } printf("\n"); if (mem[ic >> 2].breakpoint) { printf("%5ld Breakpoint\n", ic); running = FALSE; } } }/* Execute <steps> instructions in trace mode. */void runfor (long steps) { long cnt; running = TRUE; for (cnt = 0; cnt < steps; cnt++) { traceinstr(); if (!running) break; } }/* Fetch the operand of a trace instruction. The operand should be * either a number or a symbol. */long getoperand (char *cp) { char *first; long val; while (*cp == ' ' || *cp == '\t') cp++; first = cp; if (isdigit(*cp)) { if (sscanf(first, "%ld", &val) == 1) return val; else { printf("?\n"); return -1; } } else if (isalpha(*cp)) { val = getsymbolval(cp); if (val < 0) printf("?\n"); return val; } else { printf("?\n"); return - 1; } }/* Show tracing instructions. */void showtraceusage() { printf("The tracer prompts with `IC:-\'. IC is the instruction counter.\n"); printf("Upper or lower case letters are accepted. n must be positive.\n"); printf("\n"); printf("<cr> Trace K instructions.\n"); printf("n Trace n instructions.\n"); printf("B Display breakpoints.\n"); printf("Bn Set a breakpoint at n.\n"); printf("C Clear all breakpoints.\n"); printf("Cn Clear the breakpoint at n.\n"); printf("D Dump memory near IC.\n"); printf("Dn Dump memory near n.\n"); printf("I Set IC to entry point.\n"); printf("In Set IC to n.\n"); printf("K Set K (# steps executed by <cr>) to 10.\n"); printf("Kn Set K to n.\n"); printf("Q Quit.\n"); printf("R Show registers.\n"); printf("S Show symbols.\n"); printf("X Run to next break point.\n"); printf("Xn Run until IC = n.\n"); printf("\n"); }/* Execute the program with tracing. */void exectrace () { char cmd [BUFLEN]; long addr; short regnum; ic = entrypoint; numsteps = 10; running = TRUE; while (1) { printf("%5ld:- ", ic); fgets(cmd, BUFLEN, stdin); if (!strcmp(cmd, "q") || !strcmp(cmd, "Q")) break; else if (!strcmp(cmd, "")) runfor(numsteps); else if (isdigit(*cmd)) { long steps = getoperand(cmd); if (steps > 0) runfor(steps); } else { char *cp = cmd; switch (*cp++) { /* B = show all breakpoints; Bn = set breakpoint. */ case 'b': case 'B': if (*cp == '\0') { printf("Breakpoints are at: "); for (addr = 0; addr < MEMSIZE; addr++) { if (mem[addr].breakpoint) printf("%ld ", addr << 2); } printf("\n"); } else { addr = getoperand(cp); if (addr >= 0) mem[addr >> 2].breakpoint = TRUE; } break; /* C = clear all breakpoints; Cn = clear a breakpoint. */ case 'c': case 'C': if (*cp == '\0') { for (addr = 0; addr < MEMSIZE; addr++) mem[addr].breakpoint = FALSE; } else { addr = getoperand(cp); if (addr >= 0) mem[addr >> 2].breakpoint = FALSE; } break; /* D = dump memory near <ic>; Dn = dump memory near n. */ case 'd': case 'D': if (*cp == '\0') dump(ic); else { addr = getoperand(cp); if (addr >= 0) dump(addr); } break; /* Explain how to use it. */ case 'h': case 'H': case '?': showtraceusage(); break; /* I = set <ic> to entry point; In = set <ic> to n. */ case 'i': case 'I': if (*cp == '\0') ic = entrypoint; else { addr = getoperand(cp); if (addr >= 0) ic = addr; } break; /* K = set steps to 10; Kn = set steps to n. */ case 'k': case 'K': if (*cp == '\0') numsteps = 10; else { numsteps = getoperand(cp); if (numsteps < 0) numsteps = 10; } break; /* R = show registers. */ case 'r': case 'R': for (regnum = 0; regnum < MAXREG; regnum++) { showreg(regnum); printf("\n"); } break; /* S = show symbols. */ case 's': case 'S': showsymbols(); break; /* X = run to next breakpoint; Xn = run to n. */ case 'x': case 'X': if (*cp == '\0') { running = TRUE; while (running) { execinstr(FALSE); if (mem[ic >> 2].breakpoint) { printf("%5ld Breakpoint\n", ic); break; } } } else { addr = getoperand(cp); if (addr < 0) printf("?\n"); else { running = TRUE; while (running) { execinstr(FALSE); if (ic == addr) break; } } } break; default: printf("?\n"); break; } } } printf("\n%ld cycles.\n", cycles); }/* Execute the program without tracing. */void exec () { ic = entrypoint; running = TRUE; while (running) { execinstr(FALSE); } printf("\n%ld cycles.\n", cycles); }/******************************* PARSING ***********************************/enum tokentype { T_BAD, T_REG, T_OP, T_SYM, T_NUM, T_STR, T_COMMA, T_LP, T_RP, T_NULL };struct { char symval [TOKLEN]; /* Characters of the token */ enum tokentype kind; /* Chosen from the enumeration */ char *pos; /* Pointer to start of token */ short reg; /* Register number for T_REG */ short op; /* Op code for T_OP */ long intval; /* Value for T_NUM */ } token;char oldval [TOKLEN];char errmes [BUFLEN]; /* Error message */int errorcount = 0; /* Number of errors detected. */char *bp; /* Buffer pointer *//* Record an error for reporting later; only the first error is recorded. */void syntaxerror (char *message) { errorcount++; if (!strcmp(errmes, "")) { strcpy(errmes, "Error at `"); strcat(errmes, oldval); strcat(errmes, " "); strcat(errmes, token.symval); strcat(errmes, "': "); strcat(errmes, message); } }/* True if character can occur in a symbol */short issymchar (char c) { return (isalnum(c) || c == '_'); }/* True if the string is a valid register name. */short isreg (char *p) { long regnum = 0; if (!(*p == 'R' || *p == 'r')) return FALSE; p++; while (*p) { if (isdigit(*p)) regnum = 10 * regnum + *p - '0'; else return FALSE; p++; } if (regnum < MAXREG) { token.reg = (short) regnum; return TRUE; } else { syntaxerror("Illegal symbol"); return FALSE; } }/* Read a token and store appropriate values in the structure <token>. * For error reporting, the token repesenting the string must be left * in <token.symval>. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -