#ifndef _sparc_v9_regs_fs
#define _sparc_v9_regs_fs
/******************************************************************************
** FILE: sparc_v9_regs.fs
** Facile description file for the SPARC v.9 registers.
*/
#include "instq.fs"
#include "rename_decode.fs"
#define NWINDOWS 8 // number of architectural register windows
#define NUM_WREGS 128 // total number of registers in windows
//
// Architectural registers
val PC : stream;
val nPC : stream;
val nPC2 : stream;
val CCR = 0?cvt(cc);
val fcc = array(4) { 0?cvt(cc) };
val Y : ulong = 0;
extern get_FSR4() : unsigned[32];
extern get_FSR8() : unsigned[64];
extern set_FSR4(unsigned[32]) : void;
extern set_FSR8(unsigned[64]) : void;
//
// integer registers:
val global_registers = array(7) { 0?ext(64) };
val register_windows = array(NUM_WREGS) { 0?ext(64) };
type cwp_t = unsigned[5];
val CWP = 0?bits(5);
val CWP0 = 0?bits(5);
val CANSAVE = (NWINDOWS-2)?bits(5);
val CANRESTORE = 0?bits(5);
val OTHERWIN = 0?bits(5);
val CLEANWIN = (NWINDOWS-1)?bits(5);
fun regs_init(sp) {
register_windows[14] = sp?sext(64);
}
fun Rx_src(var inst : InstOp, i0) {
val ii = i0?ext(32);
if(ii == 0) inst.srcq?push_back(literal_src(0));
else if(ii < 8) inst.srcq?push_back(rmap_src(REG_GLOBAL,ii-1));
else {
val win = (CWP?cvt(ulong) - (ii / 16) + NWINDOWS) % NWINDOWS;
ii = ii & 0xf?ext(32);
inst.srcq?push_back(rmap_src(REG_WINDOW,16*win+ii));
}
}
fun Rx_dest(var inst : InstOp, i0) {
val ii = i0?ext(32);
if(ii >= 8) {
val win = (CWP?cvt(ulong) - (ii / 16) + NWINDOWS) % NWINDOWS;
ii = ii & 0xf?ext(32);
inst.destq?push_back(rmap_dest(REG_WINDOW,16*win+ii));
} else if(ii > 0) {
inst.destq?push_back(rmap_dest(REG_GLOBAL,ii-1));
} else {
val dest : DestRef;
dest.rtype = REG_LITERAL?cvt(uchar);
dest.regnum = 0?cvt(uchar);
inst.destq?push_back(dest);
}
}
fun R8_src(var inst : InstOp, i0) {
val ii = i0?ext(32);
Rx_src(inst,ii);
Rx_src(inst,ii+1);
}
fun R8_dest(var inst : InstOp, i0) {
val ii = i0?ext(32);
Rx_dest(inst,ii);
Rx_dest(inst,ii+1);
}
//
// floating-point registers:
val fregs = array(64) { 0?ext(32) };
fun F4_src(var inst : InstOp, ii) {
inst.srcq?push_back(rmap_src(REG_FP,ii));
}
fun F4_dest(var inst : InstOp, ii) {
inst.destq?push_back(rmap_dest(REG_FP,ii));
}
fun F8_src(var inst : InstOp, i0) {
val ii = i0?ext(32)&(~1) | (i0?bit(0)?ext(32)<<5);
F4_src(inst,ii); F4_src(inst,ii+1);
}
fun F8_dest(var inst : InstOp, i0) {
val ii = i0?ext(32)&(~1) | (i0?bit(0)?ext(32)<<5);
F4_dest(inst,ii); F4_dest(inst,ii+1);
}
//
// Memory access:
fun M1(a) { return system?memory(1,a)?ext(64); }
fun M1s(a) { return system?memory(1,a)?sext(64); }
fun M1(a,vv) { system?memory(1,a) = vv?cast(unsigned[_])?bits(8); }
fun M2(a) { return system?memory(2,a)?ext(64); }
fun M2s(a) { return system?memory(2,a)?sext(64); }
fun M2(a,vv) { system?memory(2,a) = vv?cast(unsigned[_])?bits(16); }
fun M4(a) { return system?memory(4,a)?ext(64); }
fun M4s(a) { return system?memory(4,a)?sext(64); }
fun M4(a,vv) { system?memory(4,a) = vv?cast(unsigned[_])?bits(32); }
fun M8(a) { return system?memory(8,a); }
fun M8(a,vv) { system?memory(8,a) = vv?cast(unsigned[64]); }
///////////////////////////////////////////////////////////////////////////////
// External functions providing access to processor data structures.
//
extern get_CCR() : cc;
extern set_CCR(cc) : void;
fun get_CCR() : cc { return CCR; }
fun set_CCR(CCR1 : cc) : void { CCR = CCR1; }
extern get_fcc(ulong) : cc;
extern set_fcc(ulong,cc) : void;
fun get_fcc(ii : ulong) : cc { return fcc[ii]; }
fun set_fcc(ii : ulong, CC1 : cc) : void { fcc[ii] = CC1; }
extern get_R4(cwp_t,ulong) : ulong;
extern set_R4(cwp_t,ulong,ulong) : void;
fun get_R4(cwp : cwp_t, i0 : ulong) {
val ii = i0?ext(32);
if(ii == 0) return 0?ext(32);
else if(ii < 8) return global_registers[ii-1]?bits(32);
else {
val win = (cwp?cvt(ulong) - (ii / 16) + NWINDOWS) % NWINDOWS;
ii = ii & 0xf?ext(32); return register_windows[16*win+ii]?bits(32);
}
}
fun set_R4(cwp : cwp_t, i0 : ulong, vv : ulong) {
val ii = i0?ext(32);
if(ii >= 8) {
val win = (cwp?cvt(ulong) - (ii / 16) + NWINDOWS) % NWINDOWS;
ii = ii & 0xf?ext(32); register_windows[16*win+ii] = vv?sext(64);
} else if(ii > 0) {
global_registers[ii-1] = vv?sext(64);
}
}
#endif