#ifndef _execute_fs
#define _execute_fs
/******************************************************************************
** FILE: execute.fs
** This file defines the exec() function to evaulate instruction operations.
*/
#include "ops.h"
#include "sparc_v9_regs.fs"
#include "instq.fs"
#include "flags.fs"
#include "funits.fs"
#include "rename_exec.fs"
extern save_regs(cwp_t,cwp_t) : void;
extern restore_regs(cwp_t) : void;
extern flush_windows(cwp_t,cwp_t) : void;
extern trap_sparc(ulong,cwp_t,cwp_t): void;
#define TAG_OVERFLOW 0x23?ext(32)
#define INVALID 0x21?ext(32)
extern no_instruction() : void;
fun _z(vv) { return vv == 0?ext(64); }
fun _lez(vv) { return vv <= 0?ext(64); }
fun _lz(vv) { return vv < 0?ext(64); }
fun _nz(vv) { return vv != 0?ext(64); }
fun _gz(vv) { return vv > 0?ext(64); }
fun _gez(vv) { return vv >= 0?ext(64); }
fun f_u(vv) { return vv?bits(2) == 0b11; }
fun f_g(vv) { return vv?bits(2) == 0b10; }
fun f_ug(vv) { return vv?bit(1); }
fun f_l(vv) { return vv?bits(2) == 0b01; }
fun f_ul(vv) { return vv?bit(0); }
fun f_lg(vv) { val xx = vv?bits(2); return xx==0b01 || xx==0b10; }
fun f_ne(vv) { return vv?bits(2) != 0b00; }
fun f_e(vv) { return vv?bits(2) == 0b00; }
fun f_ue(vv) { val xx = vv?bits(2); return xx==0b00 || xx==0b11; }
fun f_ge(vv) { return !vv?bit(0); }
fun f_uge(vv) { return vv?bits(2) != 0b01; }
fun f_le(vv) { return !vv?bit(1); }
fun f_ule(vv) { return vv?bits(2) != 0b10; }
fun f_o(vv) { return vv?bits(2) != 0b11; }
#define C(ccr) ccr?bit(0)
#define V(ccr) ccr?bit(1)
#define Z(ccr) ccr?bit(2)
#define N(ccr) ccr?bit(3)
fun i_ne(vv) { return !Z(vv); }
fun i_e(vv) { return Z(vv); }
fun i_g(vv) { return !(Z(vv)|(N(vv)^V(vv))); }
fun i_le(vv) { return Z(vv)|(N(vv)^V(vv)); }
fun i_ge(vv) { return !(N(vv)^V(vv)); }
fun i_l(vv) { return N(vv)^V(vv); }
fun i_gu(vv) { return !(C(vv)|Z(vv)); }
fun i_leu(vv) { return C(vv)|Z(vv); }
fun i_cc(vv) { return !C(vv); }
fun i_cs(vv) { return C(vv); }
fun i_pos(vv) { return !N(vv); }
fun i_neg(vv) { return N(vv); }
fun i_vc(vv) { return !V(vv); }
fun i_vs(vv) { return V(vv); }
fun u_div32(x1,x2,var ccr : cc) {
val xx = x1 / x2?ext(64);
if(xx > 1?ext(64)<<32) {
xx = 0xffffffff?ext(64);
ccr = (ccr?bits(8) | 0x02)?cvt(cc);
}
return xx;
}
fun s_div32(x1,x2,var ccr : cc) {
val xx = (+x1 / +x2?sext(64))?cast(unsigned[64]);
if(+xx > +(1?ext(64)<<31)) {
xx = 0x7fffffff?ext(64);
ccr = (ccr?bits(8) | 0x02)?cvt(cc);
} else if(+xx < +((-1)?sext(64)<<31)) {
xx = 0x80000000?sext(64);
ccr = (ccr?bits(8) | 0x02)?cvt(cc);
}
return xx;
}
fun get_div_mul_cc(xx,ccr0) {
val ccr = ccr0?bits(8) | 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;
}
fun execute(var inst : InstOp, inum)
{
val ftime = inst.ftime;
if(ftime <= 0?cvt(uchar)) {
inst.ftype = FU_DONE?cvt(uchar);
return false; // stop if done
}
if(inst.trap) { if(inum > 0) return false; } // in order traps
if(!srcs_ready(inst.srcq,inum)) return false; // sources ready?
val ftype = inst.ftype;
if(!fu_alloc(ftype)) return false; // can we allocate a FU?
ftime = ftime - 1?cvt(uchar); // decrement countdown timer
inst.ftime = ftime;
if(ftime > 0?cvt(uchar)) return false; // wait for countdown
if(!fu_finish(ftype,inst,inum)) // update functional unit data
return false; // return if skipping exec
///////////////////////////////////////////////////////////////////////////
// Get source values. This is done here to minimize the code generated
// by inlining (I don't want rmap_read() inlined too many times).
//
//
// Interpret source data as various types.
fun i1_src(ii) { return rmap_read(inst.srcq[+ii],inum)?cvt(uchar); }
fun i2_src(ii) { return rmap_read(inst.srcq[+ii],inum)?cvt(ushort); }
fun i4_src(ii) { return rmap_read(inst.srcq[+ii],inum)?cvt(ulong); }
fun x8_src(ii) { return rmap_read(inst.srcq[+ii],inum)?cvt(ullong); }
fun i8_src(ii) {
return ((rmap_read(inst.srcq[+ii],inum)<<32) |
(rmap_read(inst.srcq[+(ii+1)],inum)&0xffffffff?ext(64)));
}
fun f4_src(ii) {
return rmap_read(inst.srcq[+ii],inum)?bits(32)?cast(float);
}
fun f8_src(ii) {
return ((rmap_read(inst.srcq[+(ii+1)],inum)&0xffffffff?ext(64)) |
(rmap_read(inst.srcq[+ii],inum)<<32))?cast(double);
}
fun cc_src(ii) { return rmap_read(inst.srcq[+ii],inum)?cvt(cc); }
// Abreviation for writing instruction result.
fun dest(outnum,value) { rmap_write(outnum,value,inum); }
fun ddest(outnum,value) {
rmap_write(outnum,value?cast(unsigned[64])?bits(32,63),inum);
rmap_write(outnum+1,value?cast(unsigned[64])?bits(32),inum);
}
// Call extern system call handler.
fun trap(tnum) {
if(tnum == 3) {
flush_windows(CWP,CANRESTORE);
CANSAVE = (NWINDOWS - 2)?cvt(cwp_t);
CANRESTORE = 0?cvt(cwp_t);
} else {
trap_sparc(tnum+256,CWP,CANRESTORE);
}
is_trap = false;
}
///////////////////////////////////////////////////////////////////////////
// Do instruction operations:
//
val ccr;
switch(inst.op?cvt(ulong)) {
case OP_NOP: ;
//
// branch/call instructions
case OP_BRZ: if(_z(x8_src(0)) != inst.taken) rollback = true;
case OP_BRLEZ: if(_lez(x8_src(0)) != inst.taken) rollback = true;
case OP_BRLZ: if(_lz(x8_src(0)) != inst.taken) rollback = true;
case OP_BRNZ: if(_nz(x8_src(0)) != inst.taken) rollback = true;
case OP_BRGZ: if(_gz(x8_src(0)) != inst.taken) rollback = true;
case OP_BRGEZ: if(_gez(x8_src(0)) != inst.taken) rollback = true;
case OP_FBU: if(f_u(cc_src(0)) != inst.taken) rollback = true;
case OP_FBG: if(f_g(cc_src(0)) != inst.taken) rollback = true;
case OP_FBUG: if(f_ug(cc_src(0)) != inst.taken) rollback = true;
case OP_FBL: if(f_l(cc_src(0)) != inst.taken) rollback = true;
case OP_FBUL: if(f_ul(cc_src(0)) != inst.taken) rollback = true;
case OP_FBLG: if(f_lg(cc_src(0)) != inst.taken) rollback = true;
case OP_FBNE: if(f_ne(cc_src(0)) != inst.taken) rollback = true;
case OP_FBE: if(f_e(cc_src(0)) != inst.taken) rollback = true;
case OP_FBUE: if(f_ue(cc_src(0)) != inst.taken) rollback = true;
case OP_FBGE: if(f_ge(cc_src(0)) != inst.taken) rollback = true;
case OP_FBUGE: if(f_uge(cc_src(0)) != inst.taken) rollback = true;
case OP_FBLE: if(f_le(cc_src(0)) != inst.taken) rollback = true;
case OP_FBULE: if(f_ule(cc_src(0)) != inst.taken) rollback = true;
case OP_FBO: if(f_o(cc_src(0)) != inst.taken) rollback = true;
case OP_BNE: if(i_ne(cc_src(0)) != inst.taken) rollback = true;
case OP_BE: if(i_e(cc_src(0)) != inst.taken) rollback = true;
case OP_BG: if(i_g(cc_src(0)) != inst.taken) rollback = true;
case OP_BLE: if(i_le(cc_src(0)) != inst.taken) rollback = true;
case OP_BGE: if(i_ge(cc_src(0)) != inst.taken) rollback = true;
case OP_BL: if(i_l(cc_src(0)) != inst.taken) rollback = true;
case OP_BGU: if(i_gu(cc_src(0)) != inst.taken) rollback = true;
case OP_BLEU: if(i_leu(cc_src(0)) != inst.taken) rollback = true;
case OP_BCC: if(i_cc(cc_src(0)) != inst.taken) rollback = true;
case OP_BCS: if(i_cs(cc_src(0)) != inst.taken) rollback = true;
case OP_BPOS: if(i_pos(cc_src(0)) != inst.taken) rollback = true;
case OP_BNEG: if(i_neg(cc_src(0)) != inst.taken) rollback = true;
case OP_BVC: if(i_vc(cc_src(0)) != inst.taken) rollback = true;
case OP_BVS: if(i_vs(cc_src(0)) != inst.taken) rollback = true;
//
// Conditional moves
case OP_MOVA: dest(0,x8_src(0));
case OP_MOVNE: if(i_ne(cc_src(0))) dest(0,x8_src(1));
case OP_MOVE: if(i_e(cc_src(0))) dest(0,x8_src(1));
case OP_MOVG: if(i_g(cc_src(0))) dest(0,x8_src(1));
case OP_MOVLE: if(i_le(cc_src(0))) dest(0,x8_src(1));
case OP_MOVGE: if(i_ge(cc_src(0))) dest(0,x8_src(1));
case OP_MOVL: if(i_l(cc_src(0))) dest(0,x8_src(1));
case OP_MOVGU: if(i_gu(cc_src(0))) dest(0,x8_src(1));
case OP_MOVLEU: if(i_leu(cc_src(0))) dest(0,x8_src(1));
case OP_MOVCC: if(i_cc(cc_src(0))) dest(0,x8_src(1));
case OP_MOVCS: if(i_cs(cc_src(0))) dest(0,x8_src(1));
case OP_MOVPOS: if(i_pos(cc_src(0))) dest(0,x8_src(1));
case OP_MOVNEG: if(i_neg(cc_src(0))) dest(0,x8_src(1));
case OP_MOVVC: if(i_vc(cc_src(0))) dest(0,x8_src(1));
case OP_MOVVS: if(i_vs(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFU: if(f_u(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFG: if(f_g(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFUG: if(f_ug(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFL: if(f_l(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFUL: if(f_ul(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFLG: if(f_lg(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFNE: if(f_ne(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFE: if(f_e(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFUE: if(f_ue(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFGE: if(f_ge(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFUGE: if(f_uge(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFLE: if(f_le(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFULE: if(f_ule(cc_src(0))) dest(0,x8_src(1));
case OP_MOVFO: if(f_o(cc_src(0))) dest(0,x8_src(1));
case OP_MOVRZ: if(_z(x8_src(0))) dest(0,x8_src(1));
case OP_MOVRLEZ: if(_lez(x8_src(0))) dest(0,x8_src(1));
case OP_MOVRLZ: if(_lz(x8_src(0))) dest(0,x8_src(1));
case OP_MOVRNZ: if(_nz(x8_src(0))) dest(0,x8_src(1));
case OP_MOVRGZ: if(_gz(x8_src(0))) dest(0,x8_src(1));
case OP_MOVRGEZ: if(_gez(x8_src(0))) dest(0,x8_src(1));
//
// System traps
case OP_TA: trap(i4_src(0));
case OP_TNE: if(i_ne(cc_src(0))) trap(i4_src(1));
case OP_TE: if(i_e(cc_src(0))) trap(i4_src(1));
case OP_TG: if(i_g(cc_src(0))) trap(i4_src(1));
case OP_TLE: if(i_le(cc_src(0))) trap(i4_src(1));
case OP_TGE: if(i_ge(cc_src(0))) trap(i4_src(1));
case OP_TL: if(i_l(cc_src(0))) trap(i4_src(1));
case OP_TGU: if(i_gu(cc_src(0))) trap(i4_src(1));
case OP_TLEU: if(i_leu(cc_src(0))) trap(i4_src(1));
case OP_TCC: if(i_cc(cc_src(0))) trap(i4_src(1));
case OP_TCS: if(i_cs(cc_src(0))) trap(i4_src(1));
case OP_TPOS: if(i_pos(cc_src(0))) trap(i4_src(1));
case OP_TNEG: if(i_neg(cc_src(0))) trap(i4_src(1));
case OP_TVC: if(i_vc(cc_src(0))) trap(i4_src(1));
case OP_TVS: if(i_vs(cc_src(0))) trap(i4_src(1));
//
// Arithmetic ops
case OP_ADD: dest(0, x8_src(0) + x8_src(1));
case OP_SUB: dest(0, x8_src(0) - x8_src(1));
case OP_AND: dest(0, x8_src(0) & x8_src(1));
case OP_ANDN: dest(0, x8_src(0) & ~x8_src(1));
case OP_OR: dest(0, x8_src(0) | x8_src(1));
case OP_ORN: dest(0, x8_src(0) | ~x8_src(1));
case OP_XOR: dest(0, x8_src(0) ^ x8_src(1));
case OP_XNOR: dest(0, x8_src(0) ^ ~x8_src(1));
case OP_ADDCC: dest(0, (x8_src(0) + x8_src(1))?cc(ccr));
dest(1, ccr?bits(8)?cvt(unsigned[64]));
case OP_SUBCC: dest(0, (x8_src(0) - x8_src(1))?cc(ccr));
dest(1, ccr?bits(8)?cvt(unsigned[64]));
case OP_ANDCC: dest(0, (x8_src(0) & x8_src(1))?cc(ccr));
dest(1, ccr?bits(8)?cvt(unsigned[64]));
case OP_ANDNCC: dest(0, (x8_src(0) & ~x8_src(1))?cc(ccr));
dest(1, ccr?bits(8)?cvt(unsigned[64]));
case OP_ORCC: dest(0, (x8_src(0) | x8_src(1))?cc(ccr));
dest(1, ccr?bits(8)?cvt(unsigned[64]));
case OP_ORNCC: dest(0, (x8_src(0) | ~x8_src(1))?cc(ccr));
dest(1, ccr?bits(8)?cvt(unsigned[64]));
case OP_XORCC: dest(0, (x8_src(0) ^ x8_src(1))?cc(ccr));
dest(1, ccr?bits(8)?cvt(unsigned[64]));
case OP_XNORCC: dest(0, (x8_src(0) ^ ~x8_src(1))?cc(ccr));
dest(1, ccr?bits(8)?cvt(unsigned[64]));
case OP_ADDC:
dest(0, x8_src(0) + x8_src(1) + cc_src(2)?bit(0)?ext(64));
case OP_SUBC:
dest(0, x8_src(0) - x8_src(1) - cc_src(2)?bit(0)?ext(64));
case OP_ADDCCC:
val ccr2 = 0x00?cvt(cc);
val x1 = x8_src(0); val x2 = x8_src(1);
val xx = ((x1 + x2)?cc(ccr2) + cc_src(2)?bit(0)?ext(64))?cc(ccr);
dest(0, xx);
dest(1, ((ccr?bits(8) & 0b11011101) | (ccr2?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(unsigned[64]));
case OP_SUBCCC:
val ccr2 = 0x00?cvt(cc);
val x1 = x8_src(0); val x2 = x8_src(1);
val xx = ((x1 - x2)?cc(ccr2) - cc_src(2)?bit(0)?ext(64))?cc(ccr);
dest(0, xx);
dest(1, ((ccr?bits(8) & 0b11011101) | (ccr2?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(unsigned[64]));
case OP_MULX: dest(0, x8_src(0) * x8_src(1));
case OP_UDIVX: dest(0, x8_src(0) / x8_src(1));
case OP_SDIVX: dest(0, (+x8_src(0) / +x8_src(1))
? cast(unsigned[64]));
case OP_SLL: dest(0, x8_src(0) << x8_src(1)?bits(5));
case OP_SRL: dest(0, i4_src(0) >> x8_src(1)?bits(5));
case OP_SRA: dest(0, (+i4_src(0) >> x8_src(1)?bits(5))
? sext(64));
case OP_SLLX: dest(0, x8_src(0) << x8_src(1)?bits(6));
case OP_SRLX: dest(0, x8_src(0) >> x8_src(1)?bits(6));
case OP_SRAX: dest(0, (+x8_src(0) >> x8_src(1)?bits(6))
? cast(unsigned[64]));
case OP_TADDCC:
val x1 = x8_src(0); val x2 = x8_src(1);
dest(0, (x1 + x2)?cc(ccr));
if(x1?bits(2)!=0b00 || x2?bits(2)!=0b00)
ccr = (ccr?bits(8) | 0x02)?cvt(cc);
dest(1, ccr?bits(8)?cvt(unsigned[64]));
case OP_TADDCCTV:
val x1 = x8_src(0); val x2 = x8_src(1);
dest(0, (x1 + x2)?cc(ccr));
if(x1?bits(2)!=0b00 || x2?bits(2)!=0b00)
ccr = (ccr?bits(8) | 0x02)?cvt(cc);
dest(1, ccr?bits(8)?cvt(unsigned[64]));
if(ccr?bit(1)) trap(TAG_OVERFLOW);
case OP_TSUBCC:
val x1 = x8_src(0); val x2 = x8_src(1);
dest(0, (x1 - x2)?cc(ccr));
if(x1?bits(2)!=0b00 || x2?bits(2)!=0b00)
ccr = (ccr?bits(8) | 0x02)?cvt(cc);
dest(1, ccr?bits(8)?cvt(unsigned[64]));
case OP_TSUBCCTV:
val x1 = x8_src(0); val x2 = x8_src(1);
dest(0, (x1 - x2)?cc(ccr));
if(x1?bits(2)!=0b00 || x2?bits(2)!=0b00)
ccr = (ccr?bits(8) | 0x02)?cvt(cc);
dest(1, ccr?bits(8)?cvt(unsigned[64]));
if(ccr?bit(1)) trap(TAG_OVERFLOW);
case OP_UDIV:
val xx = (x8_src(0)<<32) | (x8_src(1)&((-1)?ext(64)));
dest(0, u_div32(xx,x8_src(2),ccr));
case OP_SDIV:
val xx = (x8_src(0)<<32) | (x8_src(1)&((-1)?ext(64)));
dest(0, s_div32(xx,x8_src(2),ccr));
case OP_UMUL:
val xx = (x8_src(0)&((-1)?ext(64))) * (x8_src(1)&((-1)?ext(64)));
dest(0, xx >> 32); dest(1, xx?bits(32)?sext(64));
case OP_SMUL:
val xx = +x8_src(0)?bits(32)?sext(64) * +x8_src(1)?bits(32)?sext(64);
dest(0, xx >> 32); dest(1, xx?bits(32)?sext(64));
case OP_UDIVCC:
val xx = (x8_src(0)<<32) | (x8_src(1)&((-1)?ext(64)));
xx = u_div32(xx,x8_src(2),ccr); dest(0, xx);
dest(1, get_div_mul_cc(xx,ccr));
case OP_SDIVCC:
val xx = (x8_src(0)<<32) | (x8_src(1)&((-1)?ext(64)));
xx = s_div32(xx,x8_src(2),ccr); dest(0, xx);
dest(1, get_div_mul_cc(xx,ccr));
case OP_MULSCC:
val y0 = x8_src(0)?bit(0); ccr = cc_src(3);
dest(0, (x8_src(0)>>1) | ((x8_src(1)&1?ext(64))<<31));
val xx = (i4_src(1)>>1) | ((ccr?bit(3)^ccr?bit(1))?ext(32)<<31);
if(y0) dest(1, (xx + i4_src(2)?bits(32))?cc(ccr));
else dest(1, (xx + 0)?cc(ccr));
dest(2, ccr?bits(8));
case OP_POPC:
val xx = x8_src(0);
val ii=0; val count=0?ext(64);
while(ii < 64) {
count = count + ((xx >> ii) & 0x1?ext(64));
ii = ii + 1;
}
dest(0, count);
case OP_FLUSH: cache_flush();
case OP_FLUSHW: trap(3);
case OP_RD: dest(0, x8_src(0));
case OP_WR: dest(0, x8_src(0) ^ x8_src(1));
//
// Floating-point arithmetic
case OP_FADDS: dest(0, f4_src(0) + f4_src(1));
case OP_FADDD: ddest(0, f8_src(0) + f8_src(2));
case OP_FSUBS: dest(0, f4_src(0) - f4_src(1));
case OP_FSUBD: ddest(0, f8_src(0) - f8_src(2));
case OP_FCMPS: (f4_src(0) - f4_src(1))?cc(ccr); dest(0, ccr?bits(8));
case OP_FCMPD: (f8_src(0) - f8_src(2))?cc(ccr); dest(0, ccr?bits(8));
case OP_FCMPES: (f4_src(0) - f4_src(1))?cc(ccr); dest(0, ccr?bits(8));
if(f_u(ccr)) trap(INVALID);
case OP_FCMPED: (f8_src(0) - f8_src(2))?cc(ccr); dest(0, ccr?bits(8));
if(f_u(ccr)) trap(INVALID);
case OP_FSTOX: ddest(0, f4_src(0)?cvt(signed[64]));
case OP_FDTOX: ddest(0, f8_src(0)?cvt(signed[64]));
case OP_FSTOI: dest(0, f4_src(0)?cvt(signed[32]));
case OP_FDTOI: dest(0, f8_src(0)?cvt(signed[32]));
case OP_FSTOD: ddest(0, f4_src(0)?cvt(double));
case OP_FXTOS: dest(0, i8_src(0)?cast(signed[_])?cvt(float));
case OP_FXTOD: ddest(0, i8_src(0)?cast(signed[_])?cvt(double));
case OP_FITOS: dest(0, i4_src(0)?cast(signed[_])?cvt(float));
case OP_FITOD: ddest(0, i4_src(0)?cast(signed[_])?cvt(double));
case OP_FDTOS: dest(0, f8_src(0)?cvt(float));
case OP_FMOVS: dest(0, f4_src(0));
case OP_FMOVD: ddest(0, f8_src(0));
case OP_FNEGS: dest(0, -f4_src(0));
case OP_FNEGD: ddest(0, -f8_src(0));
case OP_FABSS: if(f4_src(0) < 0?cvt(float)) dest(0, -f4_src(0));
else dest(0, f4_src(0));
case OP_FABSD: if(f8_src(0) < 0?cvt(double)) ddest(0, -f8_src(0));
else ddest(0, f8_src(0));
case OP_FMULS: dest(0, f4_src(0) * f4_src(1));
case OP_FMULD: ddest(0, f8_src(0) * f8_src(2));
case OP_FDIVS: dest(0, f4_src(0) / f4_src(1));
case OP_FDIVD: ddest(0, f8_src(0) / f8_src(2));
case OP_FSMULD: ddest(0, f4_src(0)?cvt(double)
* f4_src(1)?cvt(double));
case OP_FSQRTS: dest(0, sqrt(f4_src(0)));
case OP_FSQRTD: ddest(0, sqrt(f8_src(0)));
//
// Load, store, etc.
case OP_LDSB: dest(0, M1s(x8_src(0) + x8_src(1)));
case OP_LDSH: dest(0, M2s(x8_src(0) + x8_src(1)));
case OP_LDSW: dest(0, M4s(x8_src(0) + x8_src(1)));
case OP_LDUB: dest(0, M1(x8_src(0) + x8_src(1)));
case OP_LDUH: dest(0, M2(x8_src(0) + x8_src(1)));
case OP_LDUW: dest(0, M4(x8_src(0) + x8_src(1)));
case OP_LDX: dest(0, M8(x8_src(0) + x8_src(1)));
case OP_LDD:
val xx = M8(x8_src(0) + x8_src(1));
dest(0, xx >> 32); dest(1, xx & (-1)?ext(64));
case OP_STB: M1(x8_src(0) + x8_src(1), i1_src(2));
case OP_STH: M2(x8_src(0) + x8_src(1), i2_src(2));
case OP_STW: M4(x8_src(0) + x8_src(1), i4_src(2));
case OP_STX: M8(x8_src(0) + x8_src(1), x8_src(2));
case OP_STD: M8(x8_src(0) + x8_src(1), i8_src(2));
case OP_CASA:
val aa = x8_src(0); val xx = M4(aa);
if((x8_src(1)&(-1)?ext(64)) == xx) M4(aa,i4_src(2));
dest(0, xx);
case OP_CASXA:
val aa = x8_src(0); val xx = M8(aa);
if(x8_src(1) == xx) M8(aa,x8_src(2));
dest(0, xx);
case OP_LDSTUB:
val aa = x8_src(0) + x8_src(1);
dest(0, M1(aa)); M1(aa,0xff);
case OP_SWAP:
val aa = x8_src(0) + x8_src(1); val xx = M4(aa);
M4(aa,i4_src(2)); dest(0, xx);
case OP_LDFSR: set_FSR4(M4(x8_src(0)+x8_src(1))?bits(32));
is_trap = false;
case OP_LDXFSR: set_FSR8(M8(x8_src(0)+x8_src(1))); is_trap = false;
case OP_STFSR: M4(x8_src(0)+x8_src(1),get_FSR4()); is_trap = false;
case OP_STXFSR: M8(x8_src(0)+x8_src(1),get_FSR8()); is_trap = false;
case OP_SAVE:
dest(0, x8_src(0) + x8_src(1));
if(inst.trap) {
save_regs(CWP0,CANRESTORE);
CANSAVE = (CANRESTORE?cvt(ulong) - 1)?cvt(cwp_t);
CANRESTORE = 1?cvt(cwp_t);
is_trap = false;
}
case OP_RESTORE:
dest(0, x8_src(0) + x8_src(1));
if(inst.trap) {
restore_regs(CWP0);
if(CANSAVE?cvt(ulong) < NWINDOWS-2)
CANSAVE = (CANSAVE?cvt(ulong) + 1)?cvt(cwp_t);
is_trap = false;
}
case OP_RETRN:
val npc = (x8_src(0) + x8_src(1))?cvt(stream)?static;
if(inst.trap) {
restore_regs(CWP0);
if(CANSAVE?cvt(ulong) < NWINDOWS-2)
CANSAVE = (CANSAVE?cvt(ulong) + 1)?cvt(cwp_t);
is_trap = false;
}
if(instq?length() == inum+1) nPC = npc;
else {
assert(instq?length() == inum+2);
instq[-1].npc = npc; PC = npc;
if(!instq[-1].taken) nPC = PC + 4;
}
case OP_JMPL:
val npc = (x8_src(0) + x8_src(1))?cvt(stream)?static;
if(instq?length() == inum+1) nPC = npc;
else {
assert(instq?length() == inum+2);
instq[-1].npc = npc; PC = npc;
if(!instq[-1].taken) nPC = PC + 4;
}
case OP_ILL: no_instruction(); is_trap = false;
}
return true;
}
#endif