#ifndef _rename_exec_fs
#define _rename_exec_fs
/******************************************************************************
** FILE: rename_exec.fs
** Functions to access register values durring execution,
** and to do necessary cleanup when instructions retire.
*/

#include "param.h"
#include "funits.h"
#include "rename_regs.h"
#include "rename_types.fs"
#include "rename_alloc.fs"
#include "rename_data.fs"
#include "sparc_v9_regs.fs"

///////////////////////////////////////////////////////////////////////////////
// Determine if the data read by an instruction is ready
//

fun srcs_ready(var srcq : SrcRef queue, inum)
{
    for(src in srcq) {
	if(0?cvt(uchar) < src.bypass && src.bypass <= inum?cvt(uchar))
	    if(instq[+(inum?cvt(uchar)-src.bypass)].ftype!=FU_DONE?cvt(uchar))
		return false;
    }
    return true;
}

///////////////////////////////////////////////////////////////////////////////
// Read & write data values from physical registers.
//

fun rmap_read(var src : SrcRef, inum) : unsigned[64]
{
    if(src.bypass == 0?cvt(uchar) || src.bypass > inum?cvt(uchar)) {
	switch(src.rtype?cvt(ulong)) {
	 case REG_LITERAL:
	    return src.literal?sext(64);
	 case REG_GLOBAL:
	    return global_registers[src.regnum];
	 case REG_WINDOW:
	    return register_windows[src.regnum];
	 case REG_FP:
	    return fregs[src.regnum]?ext(64);
	 case REG_CCR:
	    if(src.regnum == 0?cvt(uchar))
		return CCR?bits(8)?cvt(unsigned[64]);
	    return CCR?bits(4,7)?cvt(unsigned[64]);
	 case REG_FCC:
	    return fcc[src.regnum]?bits(2)?cvt(unsigned[64]);
	 case REG_Y:
	    return Y?ext(64);
	}
    }

    return destq[+(inum?cvt(uchar)-src.bypass)][src.outnum];
}

fun rmap_write(outnum, value, inum)
{
    destq[+inum][outnum] = value?cast(unsigned[_])?cvt(unsigned[64]);
}

///////////////////////////////////////////////////////////////////////////////
// rmap_retire() -- Retiring instructions. Under the current scheme,
//	destination data must be moved to architectural registers here.
//

fun rmap_retire(num)
{
    val ii = 0;
    while(ii < num) {
	val jj = 0;
	while(jj < instq[+ii].destq?length()) {
	    val dest = instq[+ii].destq[+jj];
	    switch(dest.rtype?cvt(ulong)) {
	     case REG_LITERAL: ;	// throw this data away
	     case REG_GLOBAL:
		global_registers[dest.regnum] = destq[+ii][jj];
	     case REG_WINDOW:
		register_windows[dest.regnum] = destq[+ii][jj];
	     case REG_FP:
		fregs[dest.regnum] = destq[+ii][jj]?bits(32);
	     case REG_CCR:
		assert(dest.regnum == 0?cvt(uchar));
		CCR = destq[+ii][jj]?cvt(cc);
	     case REG_FCC:
		fcc[dest.regnum] = destq[+ii][jj]?cvt(cc);
	     case REG_Y:
		Y = destq[+ii][jj]?bits(32);
	     case REG_FSR: ;		// handled in execute()
	    }

	    jj = jj + 1;
	}

	ii = ii + 1;
    }

    destq?pop_front(num);
}

///////////////////////////////////////////////////////////////////////////////
// Rollback the rmap. (Support for speculative execution.)
//

fun rmap_rollback(inum)
{
    destq?pop_back(destq?length() - inum);
}

#endif