I would say so, but then I was on the new architecture team when the
instruction was created :-)
Here's the simulator version of the instruction:
/**
* Branch Reinstate Virtual (Rev B).
*
* @param opp The operation descriptor
* @return false
*/
bool
c_processor::op_brv(struct _op *opp)
{
mem_addr_t sb = c_system::self()->get_subbase();
mem_addr_t rleaddr = sb + 6002;
mem_addr_t rle;
struct timeval end_time;
flush_mcp_data();
if (!is_control()
|| !is_kernel()) {
instruction_error(IE_PRIV_VIOLATION);
}
if (p_bfl == 1) {
rle = get_address(7, getdigits(p_operands[0]->getaddress()+2, 6));
if (gethex(rle+RLIST_WAIT_FIELD, RLIST_WAIT_FIELD_LEN) == 0x800000) {
ulong tp = gethex(sb+6000, 8);
puthex(rle+RLIST_NEXT, RLIST_NEXT_LEN, tp);
puthex(sb+6000, 2, 0xc7);
putdigits(rleaddr, 6, rle-sb);
puthex(rle+RLIST_WAIT_FIELD, 1,
(gethex(rle+RLIST_WAIT_FIELD, 1) & ~0x8));
}
}
//
// Select next task from the ready-list
//
while (!is_nullptr(rleaddr)) {
rle = getdigits(rleaddr, 6)+sb;
//
// If the task is not runnable, delink it from the ready-list. If
// the task is runnable, set the current processor number into the
// owning process field and drop through to the reinstate code.
//
if (gethex(rle+RLIST_WAIT_FIELD, RLIST_WAIT_FIELD_LEN) == 0) {
putdigits(rle+RLIST_PROC_NUM, RLIST_PROC_NUM_LEN, p_procnum);
} else {
if (getdigits(rle+RLIST_PROC_NUM, RLIST_PROC_NUM_LEN) != 0) {
rleaddr = rle+RLIST_NEXT+2;
continue;
}
puthex(rle+RLIST_WAIT_FIELD, 1, gethex(rle+RLIST_WAIT_FIELD, 1)|8);
puthex(rleaddr, 6, gethex(rle+RLIST_NEXT+2, 6));
//
// On to next ready-list element
//
continue;
}
//
// Reinstate the top runnable ready-list task
//
p_curtask = rle;
p_curtasknum = getdigits(p_curtask+RLIST_TASKNUM, RLIST_TASKNUM_LEN);
set_mode(MODE_EXECUTING);
p_kerneltime += difftime_usec(&end_time, &p_kernstart);
c_system::self()->unlock_kernel(); // Release kernel lock
if (!p_accumulator.load(p_curtask+RLIST_ACCUM, &p_rd)) {
handle_fault();
}
p_mop.load(p_curtask+RLIST_MOP);
p_imask.load(p_curtask+RLIST_IMASK);
#if defined(VSIM_DEBUG)
p_logger->trace("[%1.1lu/%4.4lu] set Imask=%3.3lx\n",
p_procnum, p_curtasknum, p_imask.get_val());
#endif
for(ulong i=4, source=p_curtask+RLIST_MOBIX; i < 8; i++, source += 8) {
p_ix[i]->load(source);
}
p_toggles.load(p_curtask+RLIST_MODE);
p_com_ovf = gethex(p_curtask+RLIST_COMS, RLIST_COMS_LEN);
if (!p_active_env.load(p_curtask+RLIST_ACTIVE_ENV)) {
address_error(AE_EO_INV_MSD);
}
load_mat(p_curtask, false);
p_ip = getdigits(p_curtask+RLIST_IP, RLIST_IP_LEN);
gettimeofday(&p_taskstart, NULL);
//
// The real hardware has a running timer that will trigger when the
// top digit hits zero. We'll do it here, instead. The timer has plenty
// of room to continue to run, and the task will be charged accordingly.
//
if (p_mp->getdigit(p_curtask+RLIST_TSR) == 0) {
p_interrupts.raise_timer_interrupt();
}
//
// Update the task number at base+82 (the rev B spec doesn't say this!)
// --- How will this work with multiple processors
// XXX Maybe this only needs to be done on entry to
// interrupt procedure?
//
putdigits(sb+82, 4,
getdigits(p_curtask+RLIST_TASKNUM, RLIST_TASKNUM_LEN));
if (is_soft_fault_enabled()) {
if (getdigits(p_curtask+8, 1) != 0) {
p_logger->trace("Soft Fault Hardware Call invoked\n");
soft_fault();
hardware_call(opp, false, 0);
}
}
p_taken = true;
alarm_check();
return false;
}
idle(opp);
return false;
}