fun main(var pc1, var npc1, var cwp1,
var cansave1, var canrestore1,
var fuQ : FU_Data queue,
var jmpQ : stream queue)
{
PC = pc1;
nPC = npc1;
CWP0 = cwp1;
CWP = CWP0;
CANSAVE = cansave1;
CANRESTORE = canrestore1;
instq?clear();
nPC2 = 0?cvt(stream);
is_ccti = false;
is_jmpl = false;
is_call = false;
rollback = false;
fu_num_allocated = array(4 ) { 0 };
is_spec = false;
no_loads = true;
unk_load_addr = false;
unk_store_addr = false;
new_inst = struct { pc = 0?cvt(stream), npc = 0?cvt(stream),
srcq = queue{}, destq = queue{},
op = 0?cvt(ushort), ftype = 0?cvt(uchar),
ftime = 0?cvt(uchar), taken = false,
delta = 0?cvt(char), trap = false,
done = false, align = 0?cvt(uchar) };
is_trap = false;
in_init = fuQ?length()>0;
is_taken = false;
val done = false;
val finish = false;
while(!done) {
val num_to_fetch = 4 ;
if(is_trap) num_to_fetch = 0;
else if(in_init) num_to_fetch = num_to_fetch + fuQ?length();
if(num_to_fetch > (32 - instq?length()))
num_to_fetch = 32 - instq?length();
while(num_to_fetch > 0) {
if(instq?length() > 1) {
switch(instq[-2].pc) {
case (pat jmpl || retrn):
if(instq[-2].ftime > 0?cvt(uchar)) break;
var inst = instq[-1];
val inum = instq?length() - 2;
PC = inst.npc;
if(!inst.taken) nPC = PC + 4;
default: ;
}
}
nPC2 = nPC + 4;
num_to_fetch = num_to_fetch - 1;
init_inst(new_inst,PC,nPC);
if(!in_init) rmap_fetch();
else {
is_taken = init_taken(fuQ[+0]);
}
is_ccti = false;
is_jmpl = false;
is_call = false;
PC?exec();
instq?push_back(new_inst);
var inst = instq[-1];
if(in_init) {
inst.ftype = init_ftype(fuQ[+0]);
inst.ftime = fuQ[+0].ftime;
fuQ?pop_front();
in_init = fuQ?length() > 0;
if(is_jmpl) {
if(jmpQ?length() > 0)
nPC2 = jmpQ?pop_front();
}
} else if(is_jmpl) {
if(num_to_fetch > 1) num_to_fetch = 1;
}
if(is_trap) {
assert(!in_init);
if(inst.ftime <= 0?cvt(uchar))
is_trap = false;
else {
inst.trap = true;
num_to_fetch = 0;
}
}
if(is_ccti || is_jmpl || is_call) finish = true;
PC = nPC; nPC = nPC2;
if(finish) if(PC+4 == nPC)
{ inst.done = true; finish = false; }
}
assert(fuQ?length() == 0 && jmpQ?length() == 0);
no_loads = true;
unk_load_addr = false;
unk_store_addr = false;
val branch_inum = 0; val _branch_inum = 0;
is_spec = false; val _is_spec = false;
val do_rollback = false; val _do_rollback = false;
val ii = 0; fu_clear();
while(ii < instq?length()) {
var inst = instq[+ii];
rollback = false;
val executed = execute(inst,ii);
branch_inum = _branch_inum; is_spec = _is_spec;
do_rollback = _do_rollback;
_do_rollback = rollback;
if(rollback) _branch_inum = ii;
val op = inst.op?cvt(ulong);
if(164 <= op && op <= 173 ) {
no_loads = false;
if(inst.ftype == 3 ?cvt(uchar)) {
unk_load_addr = true;
}
} else if((174 <= op && op <= 180 ) ||
(181 <= op && op <= 184 )) {
if(inst.ftype == 3 ?cvt(uchar)) {
unk_store_addr = true;
}
} else if(1 <= op && op <= 34 ) {
if(inst.ftime > 0?cvt(uchar)) _is_spec = true;
switch(inst.pc) {
case (pat a==0b1):
branch_inum = _branch_inum; is_spec = _is_spec;
do_rollback = _do_rollback; _do_rollback = false;
default:
;
}
}
ii = ii + 1;
if(do_rollback) break;
}
if(_do_rollback) {
assert(!do_rollback);
branch_inum = _branch_inum;
do_rollback = true;
}
if(do_rollback) {
in_init = true;
var branch_inst = instq[+branch_inum];
PC = branch_inst.pc;
nPC = branch_inst.npc;
val fu : FU_Data;
fu.ftype = branch_inst.ftype | (!branch_inst.taken)?ext(8)<<7;
fu.ftime = 0?cvt(uchar); fuQ?push_back(fu);
assert(ii > branch_inum && ii <= branch_inum + 2);
val jj = branch_inum + 1;
while(jj < ii) {
var inst = instq[+jj];
fu.ftype = inst.taken?ext(8)<<7 | inst.ftype;
fu.ftime = inst.ftime;
fuQ?push_back(fu);
jj = jj + 1;
}
while(jj < instq?length()) {
val op = instq[+jj].op?cvt(ulong);
if((174 <= op && op <= 180 ) ||
(181 <= op && op <= 184 )) {
if(instq[+jj].ftype == 5 ?cvt(uchar)) {
cache_store_rollback(jj);
}
}
jj = jj + 1;
}
rmap_rollback(ii);
while(branch_inum < instq?length()) {
var inst = instq[-1];
CWP = ((CWP?cvt(char) + 8 ?cvt(char) - inst.delta)
% 8 ?cvt(char))?bits(5);
if(!inst.trap) {
CANSAVE = ((CANSAVE?cvt(char) + 8 ?cvt(char) +
inst.delta) % 8 ?cvt(char))?bits(5);
CANRESTORE = ((CANRESTORE?cvt(char) + 8 ?cvt(char) -
inst.delta) % 8 ?cvt(char))?bits(5);
} else is_trap = false;
instq?pop_back();
}
}
val num_retired = 0;
while(num_retired < instq?length()) {
var inst = instq[+num_retired];
if(inst.ftime > 0?cvt(uchar)) break;
if(inst.done) done = true;
CWP0 = ((CWP0?cvt(char) + 8 ?cvt(char) + inst.delta)
% 8 ?cvt(char))?bits(5);
val op = inst.op?cvt(ulong);
if(1 <= op && op <= 34 )
branch_direction(inst.pc?addr,inst.taken);
num_retired = num_retired + 1;
}
if(num_retired > 0) {
rmap_retire(num_retired);
cache_retire(num_retired);
instq?pop_front(num_retired);
num_insts_retired = (num_insts_retired +
num_retired?cvt(unsigned[64]));
}
CPU_cycle = CPU_cycle + 1?ext(64);
}
if(instq?length() > 0) {
var inst = instq[+0];
pc1 = inst.pc; npc1 = inst.npc;
} else { pc1 = PC; npc1 = nPC; }
cwp1 = CWP0;
while(instq?length() > 0) {
var inst = instq[-1];
val fu = struct { ftype = inst.taken?ext(8)<<7 | inst.ftype,
ftime = inst.ftime };
fuQ?push_front(fu);
switch(inst.pc) {
case (pat jmpl || retrn):
if(inst.ftime <= 0?cvt(uchar)) {
val target = (rmap_read(inst.srcq[+0],instq?length()-1) +
rmap_read(inst.srcq[+1],instq?length()-1));
jmpQ?push_front(target?cvt(stream));
}
default: ;
}
if(!inst.trap) {
CANSAVE = ((CANSAVE?cvt(char) + 8 ?cvt(char) +
inst.delta) % 8 ?cvt(char))?bits(5);
CANRESTORE = ((CANRESTORE?cvt(char) + 8 ?cvt(char) -
inst.delta) % 8 ?cvt(char))?bits(5);
}
instq?pop_back();
}
cansave1 = CANSAVE;
canrestore1 = CANRESTORE;
}