📄 machine.c
字号:
int argtype, amode, argno, argval; String r; Boolean indexf; enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; argval = 0; indexf = false; addr = startaddr; found_a_vec_inst = false; iread(&ins, addr, sizeof(ins)); switch (ins) { /* * It used to be that unconditional jumps and branches were handled * by taking their destination address as the next address. While * saving the cost of starting up the process, this approach * doesn't work when jumping indirect (since the value in the * register might not yet have been set). * * So unconditional jumps and branches are now handled the same way * as conditional jumps and branches. * case O_BRB: case O_BRW: addrstatus = BRANCH; break; * */ case O_BSBB: case O_BSBW: case O_JSB: case O_CALLG: case O_CALLS: addrstatus = KNOWN; stepto(addr); pstep(process, DEFSIG); addr = reg(PROGCTR); pc = addr; setcurfunc(whatblock(pc)); if (not isbperr()) { printstatus(); /* NOTREACHED */ } bpact(); if (isnext or skipfunc(ins, curfunc)) { addrstatus = KNOWN; addr = return_addr(); stepto(addr); bpact(); } else { callnews(/* iscall = */ true); } break; case O_RSB: case O_RET: addrstatus = KNOWN; stepto(addr); callnews(/* iscall = */ false); pstep(process, DEFSIG); addr = reg(PROGCTR); pc = addr; if (not isbperr()) { printstatus(); } bpact(); break; case O_BRB: case O_BRW: case O_JMP: /* because it may be jmp (r1) */ case O_BNEQ: case O_BEQL: case O_BGTR: case O_BLEQ: case O_BGEQ: case O_BLSS: case O_BGTRU: case O_BLEQU: case O_BVC: case O_BVS: case O_BCC: case O_BCS: case O_CASEB: case O_CASEW: case O_CASEL: case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: case O_BBSC: case O_BBCC: case O_BBSSI: case O_BBCCI: case O_BLBS: case O_BLBC: case O_ACBL: case O_AOBLSS: case O_AOBLEQ: case O_SOBGEQ: case O_SOBGTR: addrstatus = KNOWN; stepto(addr); pstep(process, DEFSIG); addr = reg(PROGCTR); pc = addr; if (not isbperr()) { printstatus(); } bpact(); break; default: addrstatus = SEQUENTIAL; break; } if (addrstatus != KNOWN) { addr += 1; op = optab[ins]; argno= 0; if (ins == O_ESCD) { iread(&ins2, addr, sizeof(ins)); addr += 1; op = eoptab[ins2-FIRST_EOP]; if ((ins2 == O_MTVP) || (ins2 == O_MFVP) || (ins2 == O_VSYNC)) { argno = 1; addr += 1; found_a_vec_inst = true; } if (op.fmt != 0) { argno = 1; addr += 3; found_a_vec_inst = true; } } for (argno; argno < op.numargs; argno++) { if (indexf == true) { indexf = false; } argtype = op.argtype[argno]; if (is_branch_disp(argtype)) { mode = 0xAF + (typelen(argtype) << 5); } else { iread(&mode, addr, sizeof(mode)); addr += 1; } r = regname[regnm(mode)]; amode = addrmode(mode); switch (amode) { case LITSHORT: case LITUPTO31: case LITUPTO47: case LITUPTO63: argval = mode; break; case INDEX: indexf = true; --argno; break; case REG: case REGDEF: case AUTODEC: break; case AUTOINC: if (r == regname[PROGCTR]) { switch (typelen(argtype)) { case TYPB: argval = getdisp(addr, 1, r, amode); addr += 1; break; case TYPW: argval = getdisp(addr, 2, r, amode); addr += 2; break; case TYPL: argval = getdisp(addr, 4, r, amode); addr += 4; break; case TYPF: iread(&argval, addr, sizeof(argval)); addr += 4; break; case TYPQ: case TYPD: case TYPG: iread(&argval, addr+4, sizeof(argval)); addr += 8; break; } } break; case AUTOINCDEF: if (r == regname[PROGCTR]) { argval = getdisp(addr, 4, r, amode); addr += 4; } break; case BYTEDISP: case BYTEDISPDEF: argval = getdisp(addr, 1, r, amode); addr += 1; break; case WORDDISP: case WORDDISPDEF: argval = getdisp(addr, 2, r, amode); addr += 2; break; case LONGDISP: case LONGDISPDEF: argval = getdisp(addr, 4, r, amode); addr += 4; break; } } if (ins == O_CALLS or ins == O_CALLG) { argval += 2; } if (addrstatus == BRANCH) { addr = argval; } } return addr;}/* * Get the displacement of an instruction that uses displacement addressing. */private int getdisp(addr, nbytes, reg, mode)Address addr;int nbytes;String reg;int mode;{ char byte; short hword; int argval; switch (nbytes) { case 1: iread(&byte, addr, sizeof(byte)); argval = byte; break; case 2: iread(&hword, addr, sizeof(hword)); argval = hword; break; case 4: iread(&argval, addr, sizeof(argval)); break; } if (reg == regname[PROGCTR] && mode >= BYTEDISP) { argval += addr + nbytes; } return argval;}#define BP_OP O_BPT /* breakpoint trap */#define BP_ERRNO SIGTRAP /* signal received at a breakpoint *//* * Setting a breakpoint at a location consists of saving * the word at the location and poking a BP_OP there. * * We save the locations and words on a list for use in unsetting. */typedef struct Savelist *Savelist;struct Savelist { Address location; Byte save; Byte refcount; Savelist link;};private Savelist savelist;/* * Set a breakpoint at the given address. Only save the word there * if it's not already a breakpoint. */public setbp(addr)Address addr;{ Byte w; Byte save; register Savelist newsave, s; for (s = savelist; s != nil; s = s->link) { if (s->location == addr) { s->refcount++; return; } } iread(&save, addr, sizeof(save)); newsave = new(Savelist); newsave->location = addr; newsave->save = save; newsave->refcount = 1; newsave->link = savelist; savelist = newsave; w = BP_OP; iwrite(&w, addr, sizeof(w));}/* * Unset a breakpoint; unfortunately we have to search the SAVELIST * to find the saved value. The assumption is that the SAVELIST will * usually be quite small. */public unsetbp(addr)Address addr;{ register Savelist s, prev; prev = nil; for (s = savelist; s != nil; s = s->link) { if (s->location == addr) { iwrite(&s->save, addr, sizeof(s->save)); s->refcount--; if (s->refcount == 0) { if (prev == nil) { savelist = s->link; } else { prev->link = s->link; } dispose(s); } return; } prev = s; } panic("unsetbp: couldn't find address %d", addr);}/* * Enter a procedure by creating and executing a call instruction. */#define CALLSIZE 7 /* size of call instruction */public beginproc(p, argc)Symbol p;Integer argc;{ char save[CALLSIZE]; struct { VaxOpcode op; unsigned char numargs; unsigned char mode; char addr[sizeof(long)]; /* unaligned long */ } call; long dest; pc = 2; iread(save, pc, sizeof(save)); call.op = O_CALLS; call.numargs = argc; call.mode = 0xef; dest = codeloc(p) - 2 - (pc + 7); mov(&dest, call.addr, sizeof(call.addr)); iwrite(&call, pc, sizeof(call)); setreg(PROGCTR, pc); pstep(process, DEFSIG); iwrite(save, pc, sizeof(save)); pc = reg(PROGCTR); if (not isbperr()) { printstatus(); }}/* * Create and execute sync instruction. */#define SYNCSIZE 4/* size of sync instruction */public execsync(sync_type)int sync_type;{ char save[SYNCSIZE]; struct { VaxOpcode op1; VaxOpcode op2; unsigned char sync_type; unsigned char mode; } sync_inst; Address saved_pc = pc; Word saved_r0 = reg(0); iread(save, pc, sizeof(save)); sync_inst.op1 = O_ESCD; /* set sync instr two */ sync_inst.op2 = O_MFVP; /* byte opcode */ sync_inst.sync_type = sync_type; /* 1st operand - literal 4 or 5 */ sync_inst.mode = 0x50; /* 2nd operand = r0 as operand */ iwrite(&sync_inst, pc, sizeof(sync_inst)); setreg(PROGCTR, pc); /* reset program counter */ pstep(process, DEFSIG); /* execute sync instruction */ pc = saved_pc; /* restore saved program counter */ iwrite(save, pc, sizeof(save)); /* restore saved code */ setreg(PROGCTR, pc); /* reset program counter */ setreg(0, saved_r0); /* reset register zero */ printstatus();}/* * Display vector instruction modifiers */private printmod (op, modifiers)VaxOpcode op;unsigned modifiers;{ int cnt = 0; if (modifiers != 0) { printf("/"); cnt++; if (modifiers & mi) { if ((op == O_VLDL) || (op == O_VLDQ) || (op == O_VGATHL) || (op == O_VGATHQ)) { printf("m"); cnt++; } else { printf("u(v)"); cnt += 4; } } if (modifiers & moe) { if (modifiers & mtf) { printf("1"); cnt++; } else { printf("0"); cnt++; } } else { if ((op == O_VVMERGE) || (op == O_VSMERGE) || (op == O_IOTA)) { if (modifiers & mtf) { printf("1"); cnt++; } else { printf("0"); cnt++; } } } } return(cnt);}typedef int INTFUNC();#define ERR_IGNORE ((INTFUNC *) 0)#define ERR_CATCH ((INTFUNC *) 1)/* * test if the machine is vector capable and set the global * vectorcapable, return vectorcapable. */public boolean is_vector_capable(){ long vptotal = 0; #ifndef NOVECTORS onsyserr(EINVAL, ERR_IGNORE); if(getsysinfo(GSI_VPTOTAL, (char *)&vptotal, sizeof(long), 0, NULL ) <= 0) {#endif /* NOVECTORS */ vectorcapable = false;#ifndef NOVECTORS } else { if(vptotal > 0) { if(!vectorcapable) { fprintf(stderr, "machine is now vector capable\n"); vectorcapable = true; } } else { if(vectorcapable) { fprintf(stderr, "machine is now NOT vector capable\n"); vectorcapable = false; } } } onsyserr(EINVAL, ERR_CATCH);#endif /* NOVECTORS */ return(vectorcapable);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -