/******************************************************************************
** FILE: sparc_v9_reg.fs
** Facile description file for the SPARC v.9 registers.
*/
#include "pipeline.fs"
#define NWINDOWS 8
val PC = 0?cvt(stream); // program counter
val nPC = 0?cvt(stream); // next program counter
val nPC2 = 0?cvt(stream); // next next program counter
val CCR = 0?cvt(cc); // integer condition codes
val fcc = array(4) { 0?cvt(cc) }; // FP condition codes
val Y : ulong = 0; // Y register for multiply & divide
// Floating status register (implemented externally)
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(NWINDOWS) { array(16) { 0?ext(64) } };
type cwp_t = unsigned[5];
val CWP = 0?bits(5); // current window pointer
val CANSAVE = (NWINDOWS-2)?bits(5);
val CANRESTORE = 0?bits(5);
val OTHERWIN = 0?bits(5);
val CLEANWIN = (NWINDOWS-1)?bits(5);
fun Rx(i0, var Q : ushort queue) { // get 64-bit register value
val ii = i0?ext(32);
if(ii == 0) return 0?ext(64);
else if(ii < 8) {
Q?push_back(ii?cvt(ushort));
return global_registers[ii-1];
} else {
val win = (CWP?cvt(ulong) - (ii / 16) + NWINDOWS) % NWINDOWS;
ii = ii & 0xf?ext(32);
Q?push_back((16*win+ii?cvt(ulong)+8)?cvt(ushort));
return register_windows[win][ii];
}
}
fun Rx(i0) { return Rx(i0,srcQ); }
fun Rx(i0,vv) { // set 64-bit register value
val ii = i0?ext(32);
if(ii >= 8) {
val win = (CWP?cvt(ulong) - (ii / 16) + NWINDOWS) % NWINDOWS;
ii = ii & 0xf?ext(32);
destQ?push_back((16*win+ii?cvt(ulong)+8)?cvt(ushort));
register_windows[win][ii] = vv;
} else if(ii > 0) {
destQ?push_back(ii?cvt(ushort));
global_registers[ii-1] = vv;
}
}
fun R4(ii,var Q) { return Rx(ii,Q)?bits(32); } // get 32-bit register value
fun R4(ii) { return R4(ii,srcQ); }
fun R4(ii,vv) { Rx(ii, vv?sext(64)); } // set 32-bit register value
fun R8(i0,var Q) { // make a 64-bit value from two 32-bit register
val ii = i0?ext(32);
val xx = (Rx(ii,Q) & 0xffffffff?ext(64)) << 32;
return xx | (Rx(ii+1,Q) & 0xffffffff?ext(64));
}
fun R8(i0) { return R8(i0,srcQ); }
fun R8(i0,vv) { // set two 32-bit registers from a 64 bit value
val ii = i0?ext(32);
Rx(ii, vv >> 32);
Rx(ii+1, vv & 0xffffffff?ext(64));
}
//
// floating-point registers:
val fregs = array(64) { 0?ext(32) };
fun F4(ii, var Q : ushort queue) {
Q?push_back(ii?cvt(ushort) + 256?cvt(ushort));
return fregs[ii]?cast(float);
}
fun F4(ii) { return F4(ii,srcQ); }
fun F4(ii,vv) {
destQ?push_back(ii?cvt(ushort) + 256?cvt(ushort));
fregs[ii] = vv?cast(unsigned[_])?cvt(ulong);
}
// get concatination of two 32-bit fp-registers
fun F8(i0, var Q : ushort queue) {
val ii = i0?ext(32)&(~1) | (i0?bit(0)?ext(32)<<5);
Q?push_back(ii?cvt(ushort) + 256?cvt(ushort));
Q?push_back(ii?cvt(ushort) + 257?cvt(ushort));
val xx = fregs[ii]?ext(64) << 32;
return (xx | fregs[ii+1]?ext(64))?cast(double);
}
fun F8(i0) { return F8(i0,srcQ); }
// set two 32-bit fp-registers
fun F8(i0, vv) {
val ii = i0?ext(32)&(~1) | (i0?bit(0)?ext(32)<<5);
destQ?push_back(ii?cvt(ushort) + 256?cvt(ushort));
destQ?push_back(ii?cvt(ushort) + 257?cvt(ushort));
fregs[ii] = vv?cast(unsigned[64])?bits(32,63);
fregs[ii+1] = vv?cast(unsigned[64])?bits(32);
}
//
// 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[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[win][ii] = vv?sext(64);
} else if(ii > 0) {
global_registers[ii-1] = vv?sext(64);
}
}