/******************************************************************************
** FILE: sparc_v9.fs
** Facile description file for the SPARC v.9 instruction semantics.
** This file includes the SPARC v.9 encoding and register desriptions.
*/
#include "sparc_v9_enc.fs"
#include "sparc_v9_reg.fs"
#include "pipeline.fs"
extern save_regs(cwp_t,cwp_t) : void;
extern restore_regs(cwp_t) : void;
extern flush_windows(cwp_t,cwp_t) : void;
fun _flushw() {
flush_windows(CWP,CANRESTORE);
CANSAVE = (NWINDOWS - 2)?cvt(cwp_t);
CANRESTORE = 0?cvt(cwp_t);
}
#define FLUSHW _flushw()
extern trap_sparc(ulong,cwp_t,cwp_t): void;
fun _trap(iflag,rs2,imm7) {
val tnum;
if(iflag) tnum = imm7?ext(32);
else tnum = Rx(rs2)?cvt(ulong) & 0x7f?ext(32);
if(tnum == 3) FLUSHW;
else trap_sparc(tnum+256,CWP,CANRESTORE);
}
#define TRAP _trap(i,rs2,sw_trap)
#define TAG_OVERFLOW 0x23?ext(32)
#define INVALID 0x21?ext(32)
fun annul() {
nPC = nPC2;
nPC2 = nPC + 4;
}
fun get_src2(iflag,rs2,simm) {
if(iflag) return simm?sext(64);
else return Rx(rs2);
}
#define SRC2 get_src2(i,rs2,simm13)
//
// branch/call instructions
sem call {
nPC2 = PC + disp30?sext(32)<<2;
Rx(15,PC?addr?ext(64));
schedule(alu);
};
sem jmpl {
nPC2 = (Rx(rs1) + SRC2)?cvt(stream);
Rx(rd,PC?addr?ext(64));
schedule(alu);
};
sem retrn {
nPC2 = (Rx(rs1) + SRC2)?cvt(stream);
if(CANRESTORE?cvt(ulong) > 0) {
CANSAVE = (CANSAVE?cvt(ulong) + 1)?cvt(cwp_t);
CANRESTORE = (CANRESTORE?cvt(ulong) - 1)?cvt(cwp_t);
} else {
restore_regs(CWP);
if(CANSAVE?cvt(ulong) < NWINDOWS-2)
CANSAVE = (CANSAVE?cvt(ulong) + 1)?cvt(cwp_t);
}
CWP = ((CWP?cvt(ulong) + NWINDOWS - 1) % NWINDOWS)?bits(5);
schedule(alu);
};
sem [ brz brlez brlz brnz brgz brgez ] {
if(test(Rx(rs1),0?cvt(ullong)))
nPC2 = PC + ((d16hi?sext(32)<<16) | (d16lo?ext(32)<<2));
else if(a) annul();
schedule(alu);
} where test in [ == <= < != > >= ];
fun f_u(nn) { return fcc[nn]?bits(2) == 0b11; }
fun f_g(nn) { return fcc[nn]?bits(2) == 0b10; }
fun f_ug(nn) { return fcc[nn]?bit(1); }
fun f_l(nn) { return fcc[nn]?bits(2) == 0b01; }
fun f_ul(nn) { return fcc[nn]?bit(0); }
fun f_lg(nn) { val xx = fcc[nn]?bits(2); return xx==0b01 || xx==0b10; }
fun f_ne(nn) { return fcc[nn]?bits(2) != 0b00; }
fun f_e(nn) { return fcc[nn]?bits(2) == 0b00; }
fun f_ue(nn) { val xx = fcc[nn]?bits(2); return xx==0b00 || xx==0b11; }
fun f_ge(nn) { return !fcc[nn]?bit(0); }
fun f_uge(nn) { return fcc[nn]?bits(2) != 0b01; }
fun f_le(nn) { return !fcc[nn]?bit(1); }
fun f_ule(nn) { return fcc[nn]?bits(2) != 0b10; }
fun f_o(nn) { return fcc[nn]?bits(2) != 0b11; }
sem [ fba ba ] {
nPC2 = PC + disp22?sext(32)<<2;
if(a) annul();
schedule(alu);
};
sem [ fbpa bpa ] {
nPC2 = PC + disp19?sext(32)<<2;
if(a) annul();
schedule(alu);
};
sem [ fbn fbpn bn bpn ] {
if(a) annul();
schedule(alu);
};
sem [ fbu fbg fbug fbl fbul fblg
fbne fbe fbue fbge fbuge fble fbule fbo ] {
if(cond(0)) nPC2 = PC + disp22?sext(32)<<2;
else if(a) annul();
srcQ?push_back(513?cvt(ushort)); schedule(alu);
} where cond in [ f_u f_g f_ug f_l f_ul f_lg
f_ne f_e f_ue f_ge f_uge f_le f_ule f_o ];
sem [ fbpu fbpg fbpug fbpl fbpul fbplg
fbpne fbpe fbpue fbpge fbpuge fbple fbpule fbpo ] {
if(cond(bpccr)) nPC2 = PC + disp19?sext(32)<<2;
else if(a) annul();
srcQ?push_back(513?cvt(ushort)); schedule(alu);
} where cond in [ f_u f_g f_ug f_l f_ul f_lg
f_ne f_e f_ue f_ge f_uge f_le f_ule f_o ];
#define C CCR?bit(0)
#define V CCR?bit(1)
#define Z CCR?bit(2)
#define N CCR?bit(3)
#define Cx CCR?bit(4)
#define Vx CCR?bit(5)
#define Zx CCR?bit(6)
#define Nx CCR?bit(7)
#define i_ne (!Z)
#define i_e (Z)
#define i_g (!(Z|(N^V)))
#define i_le (Z|(N^V))
#define i_ge (!(N^V))
#define i_l (N^V)
#define i_gu (!(C|Z))
#define i_leu (C|Z)
#define i_cc (!C)
#define i_cs (C)
#define i_pos (!N)
#define i_neg (N)
#define i_vc (!V)
#define i_vs (V)
#define x_ne (!Zx)
#define x_e (Zx)
#define x_g (!(Zx|(Nx^Vx)))
#define x_le (Zx|(Nx^Vx))
#define x_ge (!(Nx^Vx))
#define x_l (Nx^Vx)
#define x_gu (!(Cx|Zx))
#define x_leu (Cx|Zx)
#define x_cc (!Cx)
#define x_cs (Cx)
#define x_pos (!Nx)
#define x_neg (Nx)
#define x_vc (!Vx)
#define x_vs (Vx)
sem [ bne be bg ble bge bl
bgu bleu bcc bcs bpos bneg bvc bvs ] {
if(cond) nPC2 = PC + disp22?sext(32)<<2;
else if(a) annul();
srcQ?push_back(512?cvt(ushort)); schedule(alu);
} where cond in [ i_ne i_e i_g i_le i_ge i_l
i_gu i_leu i_cc i_cs i_pos i_neg i_vc i_vs ];
sem [ bpne bpe bpg bple bpge bpl
bpgu bpleu bpcc bpcs bppos bpneg bpvc bpvs ] {
if(bpcc1) {
if(cond_xcc) nPC2 = PC + disp19?sext(32)<<2;
else if(a) annul();
} else if(cond_icc) nPC2 = PC + disp19?sext(32)<<2;
else if(a) annul();
srcQ?push_back(512?cvt(ushort)); schedule(alu);
} where cond_xcc in [ x_ne x_e x_g x_le x_ge x_l
x_gu x_leu x_cc x_cs x_pos x_neg x_vc x_vs ],
cond_icc in [ i_ne i_e i_g i_le i_ge i_l
i_gu i_leu i_cc i_cs i_pos i_neg i_vc i_vs ];
//
// Conditional moves:
sem [ fmovfsn fmovfdn fmovsn fmovdn] { schedule(alu); };
sem [ fmovfsa fmovfda fmovsa fmovda ] { fd(rd,fs(rs2)); schedule(alu); }
where fs in [ F4 F8 F4 F8 ], fd in [ F4 F8 F4 F8 ];
sem [ fmovsne fmovse
fmovsg fmovsle fmovsge fmovsl
fmovsgu fmovsleu fmovscc fmovscs
fmovspos fmovsneg fmovsvc fmovsvs ] {
if(bpcc1) { if(cond_xcc) F4(rd,F4(rs2)); }
else if(cond_icc) F4(rd,F4(rs2));
srcQ?push_back(512?cvt(ushort)); schedule(alu);
} where cond_xcc in [ x_ne x_e x_g x_le x_ge x_l
x_gu x_leu x_cc x_cs x_pos x_neg x_vc x_vs ],
cond_icc in [ i_ne i_e i_g i_le i_ge i_l
i_gu i_leu i_cc i_cs i_pos i_neg i_vc i_vs ];
sem [ fmovdne fmovde
fmovdg fmovdle fmovdge fmovdl
fmovdgu fmovdleu fmovdcc fmovdcs
fmovdpos fmovdneg fmovdvc fmovdvs ] {
if(bpcc1) { if(cond_xcc) F8(rd,F8(rs2)); }
else if(cond_icc) F8(rd,F8(rs2));
srcQ?push_back(512?cvt(ushort)); schedule(alu);
} where cond_xcc in [ x_ne x_e x_g x_le x_ge x_l
x_gu x_leu x_cc x_cs x_pos x_neg x_vc x_vs ],
cond_icc in [ i_ne i_e i_g i_le i_ge i_l
i_gu i_leu i_cc i_cs i_pos i_neg i_vc i_vs ];
sem [ fmovfsu fmovfsg
fmovfsug fmovfsl fmovfsul fmovfslg
fmovfsne fmovfse fmovfsue fmovfsge
fmovfsuge fmovfsle fmovfsule fmovfso ] {
if(cond(bpccr)) F4(rd,F4(rs2));
srcQ?push_back(513?cvt(ushort)); schedule(alu);
} where cond in [ f_u f_g f_ug f_l f_ul f_lg
f_ne f_e f_ue f_ge f_uge f_le f_ule f_o ];
sem [ fmovfdu fmovfdg
fmovfdug fmovfdl fmovfdul fmovfdlg
fmovfdne fmovfde fmovfdue fmovfdge
fmovfduge fmovfdle fmovfdule fmovfdo ] {
if(cond(bpccr)) F8(rd,F8(rs2));
srcQ?push_back(513?cvt(ushort)); schedule(alu);
} where cond in [ f_u f_g f_ug f_l f_ul f_lg
f_ne f_e f_ue f_ge f_uge f_le f_ule f_o ];
sem [ fmovrsz fmovrslez fmovrslz fmovrsnz fmovrsgz fmovrsgez ] {
if(test(Rx(rs1),0?cvt(ullong))) F4(rd,F4(rs2));
schedule(alu);
} where test in [ == <= < != > >= ];
sem [ fmovrdz fmovrdlez fmovrdlz fmovrdnz fmovrdgz fmovrdgez ] {
if(test(Rx(rs1),0?cvt(ullong))) F8(rd,F8(rs2));
schedule(alu);
} where test in [ == <= < != > >= ];
sem [ mova movfa ] { Rx(rd,Rx(rs2)); schedule(alu); };
sem [ movn movfn ] { schedule(alu); };
sem [ movne move
movg movle movge movl
movgu movleu movcc movcs
movpos movneg movvc movvs ] {
if(bpcc1) { if(cond_xcc) Rx(rd,Rx(rs2)); }
else if(cond_icc) Rx(rd,Rx(rs2));
srcQ?push_back(512?cvt(ushort)); schedule(alu);
} where cond_xcc in [ x_ne x_e x_g x_le x_ge x_l
x_gu x_leu x_cc x_cs x_pos x_neg x_vc x_vs ],
cond_icc in [ i_ne i_e i_g i_le i_ge i_l
i_gu i_leu i_cc i_cs i_pos i_neg i_vc i_vs ];
sem [ movfu movfg movfug movfl movful movflg
movfne movfe movfue movfge movfuge movfle movfule movfo ] {
if(cond(bpccr)) Rx(rd,Rx(rs2));
srcQ?push_back(513?cvt(ushort)); schedule(alu);
} where cond in [ f_u f_g f_ug f_l f_ul f_lg
f_ne f_e f_ue f_ge f_uge f_le f_ule f_o ];
sem [ movrz movrlez movrlz movrnz movrgz movrgez ] {
if(test(Rx(rs1),0?cvt(ullong))) Rx(rd,Rx(rs2));
schedule(alu);
} where test in [ == <= < != > >= ];
//
// System traps:
sem ta { TRAP; schedule(alu); };
sem tn { schedule(alu); };
sem [ tne te tg tle tge tl
tgu tleu tcc tcs tpos tneg tvc tvs ] {
if(bpcc1) { if(cond_xcc) TRAP; }
else if(cond_icc) TRAP;
schedule(alu);
} where cond_xcc in [ x_ne x_e x_g x_le x_ge x_l
x_gu x_leu x_cc x_cs x_pos x_neg x_vc x_vs ],
cond_icc in [ i_ne i_e i_g i_le i_ge i_l
i_gu i_leu i_cc i_cs i_pos i_neg i_vc i_vs ];
//
// Arithmetic ops:
#define C64 (CCR?bit(0)?ext(64))
sem [ add sub and or xor ]
{ Rx(rd, op(Rx(rs1),SRC2)); schedule(alu); }
where op in [ + - & | ^ ];
sem [ addcc subcc andcc orcc xorcc ] {
Rx(rd, op(Rx(rs1),SRC2)?cc(CCR));
destQ?push_back(512?cvt(ushort)); schedule(alu);
} where op in [ + - & | ^ ];
sem addc {
Rx(rd, Rx(rs1) + SRC2 + C64);
srcQ?push_back(512?cvt(ushort)); schedule(alu);
};
sem subc {
Rx(rd, Rx(rs1) - SRC2 - C64);
srcQ?push_back(512?cvt(ushort)); schedule(alu);
};
sem addccc {
val ccr = 0x00?cvt(cc);
val x1 = Rx(rs1); val x2 = SRC2;
val xx = ((x1 + x2)?cc(ccr) + C64)?cc(CCR);
CCR = ((CCR?bits(8) & 0b11011101) | (ccr?bits(8) & 0x11) |
(((x1?bit(31)==x2?bit(31))&&(xx?bit(31)!=x1?bit(31)))?ext(8)<<1) |
(((x1?bit(63)==x2?bit(63))&&(xx?bit(63)!=x1?bit(63)))?ext(8)<<5))
? cvt(cc);
Rx(rd, xx);
srcQ?push_back(512?cvt(ushort));
destQ?push_back(512?cvt(ushort));
schedule(alu);
};
sem subccc {
val ccr = 0x00?cvt(cc);
val x1 = Rx(rs1); val x2 = SRC2;
val xx = ((x1 - x2)?cc(ccr) - C64)?cc(CCR);
CCR = ((CCR?bits(8) & 0b11011101) | (ccr?bits(8) & 0x11) |
(((x1?bit(31)!=x2?bit(31))&&(xx?bit(31)!=x1?bit(31)))?ext(8)<<1) |
(((x1?bit(63)!=x2?bit(63))&&(xx?bit(63)!=x1?bit(63)))?ext(8)<<5))
? cvt(cc);
Rx(rd, xx);
srcQ?push_back(512?cvt(ushort));
destQ?push_back(512?cvt(ushort));
schedule(alu);
};
sem [ andn orn xnor ]
{ Rx(rd, op(Rx(rs1),~SRC2)); schedule(alu); }
where op in [ & | ^ ];
sem [ andncc orncc xnorcc ] {
Rx(rd, op(Rx(rs1),~SRC2)?cc(CCR));
destQ?push_back(512?cvt(ushort)); schedule(alu);
} where op in [ & | ^ ];
sem [ mulx udivx ]
{ Rx(rd,op(Rx(rs1),SRC2)); schedule(alu); }
where op in [ * / ];
sem sdivx { Rx(rd,(+Rx(rs1) / +SRC2)?cast(ullong)); schedule(alu); };
sem sll { Rx(rd, Rx(rs1) << SRC2?bits(5)); schedule(alu); };
sem srl { R4(rd, R4(rs1) >> SRC2?bits(5)); schedule(alu); };
sem sra { Rx(rd,(+R4(rs1) >> SRC2?bits(5))?sext(64)); schedule(alu); };
sem sllx { Rx(rd, Rx(rs1) << SRC2?bits(6)); schedule(alu); };
sem srlx { Rx(rd, Rx(rs1) >> SRC2?bits(6)); schedule(alu); };
sem srax { Rx(rd,(+Rx(rs1) >> SRC2?bits(6))?cast(ullong)); schedule(alu); };
sem taddcc {
val x1 = Rx(rs1); val x2 = SRC2;
Rx(rd, (x1 + x2)?cc(CCR));
if(x1?bits(2)!=0b00 || x2?bits(2)!=0b00)
CCR = (CCR?bits(8) | 0x02)?cvt(cc);
destQ?push_back(512?cvt(ushort));
schedule(alu);
};
sem taddcctv {
val x1 = Rx(rs1); val x2 = SRC2;
Rx(rd, (x1 + x2)?cc(CCR));
if(x1?bits(2)!=0b00 || x2?bits(2)!=0b00)
CCR = (CCR?bits(8) | 0x02)?cvt(cc);
if(CCR?bit(1)) trap_sparc(TAG_OVERFLOW,CWP,CANRESTORE);
destQ?push_back(512?cvt(ushort));
schedule(alu);
};
sem tsubcc {
val x1 = Rx(rs1); val x2 = SRC2;
Rx(rd, (x1 - x2)?cc(CCR));
if(x1?bits(2)!=0b00 || x2?bits(2)!=0b00)
CCR = (CCR?bits(8) | 0x02)?cvt(cc);
destQ?push_back(512?cvt(ushort));
schedule(alu);
};
sem tsubcctv {
val x1 = Rx(rs1); val x2 = SRC2;
Rx(rd, (x1 - x2)?cc(CCR));
if(x1?bits(2)!=0b00 || x2?bits(2)!=0b00)
CCR = (CCR?bits(8) | 0x02)?cvt(cc);
if(CCR?bit(1)) trap_sparc(TAG_OVERFLOW,CWP,CANRESTORE);
destQ?push_back(512?cvt(ushort));
schedule(alu);
};
fun u_div32(x1,x2,var ccr) {
val xx = x1 / x2?ext(64);
if(xx > 1?ext(64)<<32) { xx = 0xffffffff?ext(64); ccr = ccr | 0x02; }
return xx;
}
fun s_div32(x1,x2,var ccr) {
val xx = (+x1 / +x2?sext(64))?cast(ullong);
if(+xx > +(1?ext(64)<<31)) { xx = 0x7fffffff?ext(64); ccr = ccr | 0x02; }
else if(+xx < +((-1)?sext(64)<<31)) {
xx = 0x80000000?sext(64);
ccr = ccr | 0x02;
}
return xx;
}
sem [ udiv sdiv ] {
val ccr = 0x00;
val xx = ((Y?ext(64)<<32) | R4(rs1)?ext(64));
if(i) xx = _div(xx,simm13?sext(32)?ext(64),ccr);
else xx = _div(xx,R4(rs2)?ext(64),ccr);
Rx(rd,xx); schedule(alu);
} where _div in [u_div32 s_div32];
sem umul {
val xx = (Rx(rs1)&0xffffffff?ext(64)) * (SRC2&0xffffffff?ext(64));
Y = (xx >> 32)?bits(32); R4(rd,xx?bits(32)); schedule(alu);
};
sem smul {
val xx = +Rx(rs1)?bits(32)?sext(64) * +SRC2?bits(32)?sext(64);
Y = (xx >> 32)?bits(32); R4(rd,xx?bits(32)); schedule(alu);
};
fun get_div_mul_cc(xx,ccr0) {
val ccr = ccr0 | xx?bit(63)?ext(8) << 7;
ccr = ccr | (xx==0?ext(64))?ext(8) << 6;
ccr = ccr | xx?bit(31)?ext(8) << 3;
return ccr | (xx?bits(32)==0)?ext(8) << 2;
}
sem [ udivcc sdivcc ] {
val ccr = 0x00;
val xx = ((Y?ext(64)<<32) | R4(rs1)?ext(64));
if(i) xx = _div(xx,simm13?sext(32),ccr);
else xx = _div(xx,R4(rs2),ccr);
CCR = get_div_mul_cc(xx,ccr)?cvt(cc);
Rx(rd,xx);
destQ?push_back(512?cvt(ushort));
schedule(alu);
} where _div in [u_div32 s_div32];
sem umulcc {
val xx = (Rx(rs1)&0xffffffff?ext(64)) * (SRC2&0xffffffff?ext(64));
CCR = get_div_mul_cc(xx,0x00)?cvt(cc);
Y = (xx >> 32)?bits(32); R4(rd,xx?bits(32));
destQ?push_back(512?cvt(ushort));
schedule(alu);
};
sem smulcc {
val xx = (+Rx(rs1)?bits(32)?sext(64) *
+SRC2?bits(32)?sext(64))?cast(ullong);
CCR = get_div_mul_cc(xx,0x00)?cvt(cc);
Y = (xx >> 32)?bits(32); R4(rd,xx?bits(32));
destQ?push_back(512?cvt(ushort));
schedule(alu);
};
sem mulscc {
val y0 = Y?bit(0); Y = (Y>>1) | (R4(rs1)?bit(0)?ext(32)<<31);
val xx = (R4(rs1)>>1) | ((CCR?bit(3)^CCR?bit(1))?ext(32)<<31);
if(y0) R4(rd, (xx + SRC2?bits(32))?cc(CCR));
else R4(rd,(xx+0)?cc(CCR));
destQ?push_back(512?cvt(ushort));
schedule(alu);
};
sem popc {
val xx = Rx(rs2);
val ii=0; val count=0?ext(64);
while(ii < 64) {
count = count + ((xx >> ii) & 0x1?ext(64));
ii = ii + 1;
}
Rx(rd,count);
schedule(alu);
};
sem flush { schedule(alu); };
sem flushw { FLUSHW; schedule(alu); };
sem rd {
switch(rs1?ext(32)) {
case 0: Rx(rd,Y?ext(64));
case 2: Rx(rd,CCR?bits(8)?ext(64));
srcQ?push_back(512?cvt(ushort));
case 5: Rx(rd,PC?addr?ext(64));
case 15: assert(rd?ext(32)==0);
default:
/* not implemented */
assert(false);
}
schedule(alu);
};
sem wr {
switch(rd?ext(32)) {
case 0: Y = (Rx(rs1) ^ SRC2)?bits(32);
case 2: CCR = (Rx(rs1) ^ SRC2)?cvt(cc);
destQ?push_back(512?cvt(ushort));
default:
/* not implemented */
assert(false);
}
schedule(alu);
};
sem save {
val xx = Rx(rs1) + SRC2;
if(CANSAVE?cvt(ulong) <= 0) {
save_regs(CWP,CANRESTORE);
CANSAVE = CANRESTORE; CANRESTORE = 0?cvt(cwp_t);
}
CWP = ((CWP?cvt(ulong) + 1) % NWINDOWS)?bits(5);
CANSAVE = (CANSAVE?cvt(ulong) - 1)?cvt(cwp_t);
CANRESTORE = (CANRESTORE?cvt(ulong) + 1)?cvt(cwp_t);
Rx(rd,xx); schedule(alu);
};
sem restore {
val xx = Rx(rs1) + SRC2;
if(CANRESTORE?cvt(ulong) > 0) {
CANSAVE = (CANSAVE?cvt(ulong) + 1)?cvt(cwp_t);
CANRESTORE = (CANRESTORE?cvt(ulong) - 1)?cvt(cwp_t);
} else {
restore_regs(CWP);
if(CANSAVE?cvt(ulong) < NWINDOWS-2)
CANSAVE = (CANSAVE?cvt(ulong) + 1)?cvt(cwp_t);
}
CWP = ((CWP?cvt(ulong) + NWINDOWS - 1) % NWINDOWS)?bits(5);
Rx(rd,xx); schedule(alu);
};
sem sethi { Rx(rd,imm22?ext(64)<<10); schedule(alu); };
//
// Floating-point arithmetic:
sem [ fadds fsubs fmuls fdivs ]
{ F4(rd, op(F4(rs1),F4(rs2))); schedule(fpu); }
where op in [ + - * / ];
sem [ faddd fsubd fmuld fdivd ]
{ F8(rd, op(F8(rs1),F8(rs2))); schedule(fpu); }
where op in [ + - * / ];
sem [ fcmps fcmpd ] { (f(rs1)-f(rs2))?cc(fcc[cond]); } where f in [F4 F8];
sem [ fcmpes fcmped ] {
(f(rs1)-f(rs2))?cc(fcc[cond]);
if(f_u(cond)) trap_sparc(INVALID,CWP,CANRESTORE);
destQ?push_back(513?cvt(ushort)); schedule(fpu);
} where f in [F4 F8];
sem fstox { F8(rd,F4(rs2)?cvt(llong)?cast(ullong)); schedule(fpu); };
sem fdtox { F8(rd,F8(rs2)?cvt(llong)?cast(ullong)); schedule(fpu); };
sem fstoi { F4(rd,F4(rs2)?cvt(long)?cast(ulong)); schedule(fpu); };
sem fdtoi { F4(rd,F8(rs2)?cvt(long)?cast(ulong)); schedule(fpu); };
sem fstod { F8(rd,F4(rs2)?cvt(double)); schedule(fpu); };
sem fxtos { F4(rd,F8(rs2)?cast(llong)?cvt(float)); schedule(fpu); };
sem fxtod { F8(rd,F8(rs2)?cast(llong)?cvt(double)); schedule(fpu); };
sem fitos { F4(rd,F4(rs2)?cast(long)?cvt(float)); schedule(fpu); };
sem fitod { F8(rd,F4(rs2)?cast(long)?cvt(double)); schedule(fpu); };
sem fdtos { F4(rd,F8(rs2)?cvt(float)); schedule(fpu); };
sem [ fmovs fmovd ]
{ fd(rd,fs(rs2)); schedule(fpu); }
where fs in [F4 F8], fd in [F4 F8];
sem [ fnegs fnegd ]
{ fd(rd,-fs(rs2)); schedule(fpu); }
where fs in [F4 F8], fd in [F4 F8];
sem [ fabss fabsd ]
{ if(fs(rs2)<z) fd(rd,-fs(rs2)); else fd(rd,fs(rs2)); schedule(fpu); }
where fs in [F4 F8], fd in [F4 F8], z in [ (0?cvt(float)) (0?cvt(double)) ];
sem fsmuld { F8(rd,F4(rs1)?cvt(double)*F4(rs2)?cvt(double)); schedule(fpu); };
sem [fsqrts fsqrtd]
{ fd(rd,sqrt(fs(rs2))); schedule(fpu); }
where fs in [F4 F8], fd in [F4 F8];
//
// Load, store, etc.:
sem [ ldf lddf ldfa lddfa
ldsb ldsh ldsw ldub lduh lduw ldx ldd
ldsba ldsha ldswa lduba lduha lduwa ldxa ldda ] {
address = (Rx(rs1) + SRC2)?cvt(ulong);
r(rd, m(address)); schedule(load);
} where r in [ F4 F8 F4 F8
Rx Rx Rx Rx Rx Rx Rx R8
Rx Rx Rx Rx Rx Rx Rx R8 ],
m in [ M4 M8 M4 M8
M1s M2s M4s M1 M2 M4 M8 M8
M1s M2s M4s M1 M2 M4 M8 M8 ];
sem [ stf stdf stb sth stw stx std
stfa stdfa stba stha stwa stxa stda ] {
address = (Rx(rs1) + SRC2)?cvt(ulong);
m(address, r(rd,storeQ)); schedule(store);
} where r in [ F4 F8 Rx Rx Rx Rx R8
F4 F8 Rx Rx Rx Rx R8 ],
m in [ M4 M8 M1 M2 M4 M8 M8
M4 M8 M1 M2 M4 M8 M8 ];
sem [ casa casxa ] {
address = Rx(rs1)?cvt(ulong); val xx = ms(address);
if(rsrc(rs2,srcQ)?ext(64) == xx) md(address,rsrc(rd,destQ));
rdest(rd,xx); schedule(store);
} where rsrc in [R4 Rx], rdest in [R4 Rx],
ms in [M4 M8], md in [M4 M8];
sem [ ldstub ldstuba ] {
address = (Rx(rs1) + SRC2)?cvt(ulong);
Rx(rd,M1(address)); M1(address,0xff);
schedule(store);
};
sem [ prefetch prefetcha ] { schedule(alu); };
sem [ swap swapa ] {
address = (Rx(rs1) + SRC2)?cvt(ulong); val xx = M4(address);
M4(address,R4(rd,storeQ)); R4(rd,xx); schedule(store);
};
sem ldfsr {
address = (Rx(rs1) + SRC2)?cvt(ulong);
set_FSR4(M4(address)?bits(32)); schedule(load);
};
sem ldxfsr {
address = (Rx(rs1) + SRC2)?cvt(ulong);
set_FSR8(M8(address)); schedule(load);
};
sem [ stfsr stxfsr ] {
address = (Rx(rs1) + SRC2)?cvt(ulong);
m(address, r()); schedule(store);
} where r in [ get_FSR4 get_FSR8 ], m in [ M4 M8 ];