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; }