#ifndef _sparc_v9_decode_fs
#define _sparc_v9_decode_fs
/******************************************************************************
** FILE: sparc_v9_decode.fs
** Facile description file for the SPARC v.9 instruction semantics.
** This file includes the SPARC v.9 encoding and register desriptions.
*/

#include "param.h"
#include "ops.h"
#include "rename_regs.h"
#include "rename_decode.fs"
#include "rename_exec.fs"
#include "sparc_v9_enc.fs"
#include "sparc_v9_regs.fs"
#include "instq.fs"
#include "flags.fs"
#include "funits.fs"
#include "branch.fs"

// The decoded instruction record
val new_inst : InstOp;

//
// Helper functions:

fun window_save(var inst : InstOp) {
    inst.delta = 1?cvt(char);
    CWP = ((CWP?cvt(ulong) + 1) % NWINDOWS)?bits(5);
    if(CANSAVE?cvt(ulong) > 0) {
	CANSAVE = (CANSAVE?cvt(ulong) - 1)?cvt(cwp_t);
	CANRESTORE = (CANRESTORE?cvt(ulong) + 1)?cvt(cwp_t);
    } else { is_trap = true; }
}

fun window_restore(var inst : InstOp) {
    inst.delta = (-1)?cvt(char);
    CWP = ((CWP?cvt(ulong) + NWINDOWS - 1) % NWINDOWS)?bits(5);
    if(CANRESTORE?cvt(ulong) > 0) {
	CANSAVE = (CANSAVE?cvt(ulong) + 1)?cvt(cwp_t);
	CANRESTORE = (CANRESTORE?cvt(ulong) - 1)?cvt(cwp_t);
    } else { is_trap = true; }
}

// The ftime value to use when instruction need no further execution
#define FT_DONE		0

fun set_op(var inst : InstOp, Op, ftype, ftime)
{
    inst.op = Op?cvt(ushort);
    inst.ftype = ftype?cvt(uchar);
    inst.ftime = ftime?cvt(uchar);
}

fun set_src2(var inst : InstOp, i, rs2, simm)
{
    if(i) inst.srcq?push_back(literal_src(simm?sext(64)));
    else Rx_src(inst,rs2);
}

#define SRC2 set_src2(new_inst,i,rs2,simm13)

fun predict(pc)
{
    if(in_init) return is_taken;
    return branch_predict(pc)?static;
}

//
// Default instruction semantics:

sem default {
    set_op(new_inst,OP_ILL,FU_ALU,1);
    is_trap = true;
};

//
// branch/call instructions

sem call {
    set_op(new_inst,OP_NOP,FU_NONE,FT_DONE); Rx_dest(new_inst,15);
    rmap_write(0,PC?addr,instq?length());
    nPC2 = PC + disp30?sext(32)<<2;
    new_inst.taken = true;
    is_call = true;
};

sem jmpl {
    set_op(new_inst,OP_JMPL,FU_ALU,1);
    Rx_src(new_inst,rs1); SRC2; Rx_dest(new_inst,rd);
    rmap_write(0,PC?addr,instq?length());
    new_inst.taken = true;
    is_jmpl = true;
};

sem retrn {
    set_op(new_inst,OP_RETRN,FU_ALU,1);
    Rx_src(new_inst,rs1); SRC2;
    window_restore(new_inst);
    new_inst.taken = true;
    is_jmpl = true;
};

sem [	brz	brlez	brlz	brnz	brgz	brgez	] {
    set_op(new_inst,Op,FU_ALU,1);
    Rx_src(new_inst,rs1);
    val target = PC+(d16hi?sext(32)<<16)|(d16lo?ext(32)<<2);
    new_inst.srcq?push_back(literal_src(target?addr));
    if(predict(PC?addr)) { nPC2 = target; new_inst.taken = true; }
    is_ccti = true;
} where Op in [ OP_BRZ OP_BRLEZ OP_BRLZ OP_BRNZ OP_BRGZ OP_BRGEZ ];

sem [ fba ba ] {
    set_op(new_inst,OP_NOP,FU_NONE,FT_DONE);
    nPC2 = PC + disp22?sext(32)<<2;
    new_inst.taken = true;
    if(a) { nPC = nPC2; nPC2 = nPC + 4; }
};

sem [ fbpa bpa ] {
    set_op(new_inst,OP_NOP,FU_NONE,FT_DONE);
    nPC2 = PC + disp19?sext(32)<<2;
    new_inst.taken = true;
    if(a) { nPC = nPC2; nPC2 = nPC + 4; }
};

sem [ fbn fbpn bn bpn ] {
    set_op(new_inst,OP_NOP,FU_NONE,FT_DONE);
    if(a) { nPC = nPC2; nPC2 = nPC + 4; }
};

sem [			fbu	fbg	fbug	fbl	fbul	fblg
	fbne	fbe	fbue	fbge	fbuge	fble	fbule	fbo	] {
    set_op(new_inst,Op,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_FCC,0));
    val target = PC+disp22?sext(32)<<2;
    new_inst.srcq?push_back(literal_src(target?addr));
    if(predict(PC?addr)) {
	nPC2 = target; new_inst.taken = true;
    } else if(a) { nPC = nPC2; nPC2 = nPC + 4; }
    is_ccti = true;
} where Op in [		OP_FBU	OP_FBG	OP_FBUG	OP_FBL	OP_FBUL	OP_FBLG
	OP_FBNE	OP_FBE	OP_FBUE	OP_FBGE	OP_FBUGE OP_FBLE OP_FBULE OP_FBO ];

sem [			fbpu	fbpg	fbpug	fbpl	fbpul	fbplg
	fbpne	fbpe	fbpue	fbpge	fbpuge	fbple	fbpule	fbpo	] {
    set_op(new_inst,Op,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_FCC,bpccr));
    val target = PC+disp19?sext(32)<<2;
    new_inst.srcq?push_back(literal_src(target?addr));
    if(predict(PC?addr)) {
	nPC2 = target; new_inst.taken = true;
    } else if(a) { nPC = nPC2; nPC2 = nPC + 4; }
    is_ccti = true;
} where Op in [		OP_FBU	OP_FBG	OP_FBUG	OP_FBL	OP_FBUL	OP_FBLG
	OP_FBNE	OP_FBE	OP_FBUE	OP_FBGE	OP_FBUGE OP_FBLE OP_FBULE OP_FBO ];

sem [			bne	be	bg	ble	bge	bl
	bgu	bleu	bcc	bcs	bpos	bneg	bvc	bvs	] {
    set_op(new_inst,Op,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_CCR,0));
    val target = PC+disp22?sext(32)<<2;
    new_inst.srcq?push_back(literal_src(target?addr));
    if(predict(PC?addr)) {
	nPC2 = target; new_inst.taken = true;
    } else if(a) { nPC = nPC2; nPC2 = nPC + 4; }
    is_ccti = true;
} where Op in [		OP_BNE	OP_BE	OP_BG	OP_BLE	OP_BGE	OP_BL
	OP_BGU	OP_BLEU	OP_BCC	OP_BCS	OP_BPOS	OP_BNEG	OP_BVC	OP_BVS	];

sem [			bpne	bpe	bpg	bple	bpge	bpl
	bpgu	bpleu	bpcc	bpcs	bppos	bpneg	bpvc	bpvs	] {
    set_op(new_inst,Op,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_CCR,bpcc1));
    val target = PC+disp19?sext(32)<<2;
    new_inst.srcq?push_back(literal_src(target?addr));
    if(predict(PC?addr)) {
	nPC2 = target; new_inst.taken = true;
    } else if(a) { nPC = nPC2; nPC2 = nPC + 4; }
    is_ccti = true;
} where Op in [		OP_BNE	OP_BE	OP_BG	OP_BLE	OP_BGE	OP_BL
	OP_BGU	OP_BLEU	OP_BCC	OP_BCS	OP_BPOS	OP_BNEG	OP_BVC	OP_BVS	];

//
// Conditional moves:

sem [ fmovfsn fmovfdn fmovsn fmovdn] {
    set_op(new_inst,OP_NOP,FU_NONE,FT_DONE);
};

sem [ fmovfsa fmovsa ] {
    set_op(new_inst,OP_MOVA,FU_ALU,1);
    F4_src(new_inst,rs2); F4_dest(new_inst,rd);
};

sem [ fmovfda fmovda ] {
    set_op(new_inst,OP_MOVA,FU_ALU,1);
    F8_src(new_inst,rs2); F8_dest(new_inst,rd);
};

sem [					fmovsne		fmovse
	fmovsg		fmovsle		fmovsge		fmovsl
	fmovsgu		fmovsleu	fmovscc		fmovscs
	fmovspos	fmovsneg	fmovsvc		fmovsvs	] {
    set_op(new_inst,Op,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_CCR,bpcc1));
    F4_src(new_inst,rs2); F4_dest(new_inst,rd);
} where Op in [				OP_MOVNE	OP_MOVE
	OP_MOVG		OP_MOVLE	OP_MOVGE	OP_MOVL
	OP_MOVGU	OP_MOVLEU	OP_MOVCC	OP_MOVCS
	OP_MOVPOS	OP_MOVNEG	OP_MOVVC	OP_MOVVS ];

sem [					fmovdne		fmovde
	fmovdg		fmovdle		fmovdge		fmovdl
	fmovdgu		fmovdleu	fmovdcc		fmovdcs
	fmovdpos	fmovdneg	fmovdvc		fmovdvs	] {
    set_op(new_inst,Op,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_CCR,bpcc1));
    F8_src(new_inst,rs2); F8_dest(new_inst,rd);
} where Op in [				OP_MOVNE	OP_MOVE
	OP_MOVG		OP_MOVLE	OP_MOVGE	OP_MOVL
	OP_MOVGU	OP_MOVLEU	OP_MOVCC	OP_MOVCS
	OP_MOVPOS	OP_MOVNEG	OP_MOVVC	OP_MOVVS ];

sem [					fmovfsu		fmovfsg
	fmovfsug	fmovfsl		fmovfsul	fmovfslg
	fmovfsne	fmovfse		fmovfsue	fmovfsge
	fmovfsuge	fmovfsle	fmovfsule	fmovfso	] {
    set_op(new_inst,Op,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_FCC,bpccr));
    F4_src(new_inst,rs2); F4_dest(new_inst,rd);
} where Op in [				OP_MOVFU	OP_MOVFG
	OP_MOVFUG	OP_MOVFL	OP_MOVFUL	OP_MOVFLG
	OP_MOVFNE	OP_MOVFE	OP_MOVFUE	OP_MOVFGE
	OP_MOVFUGE	OP_MOVFLE	OP_MOVFULE	OP_MOVFO ];

sem [					fmovfdu		fmovfdg
	fmovfdug	fmovfdl		fmovfdul	fmovfdlg
	fmovfdne	fmovfde		fmovfdue	fmovfdge
	fmovfduge	fmovfdle	fmovfdule	fmovfdo	] {
    set_op(new_inst,Op,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_FCC,bpccr));
    F8_src(new_inst,rs2); F8_dest(new_inst,rd);
} where Op in [				OP_MOVFU	OP_MOVFG
	OP_MOVFUG	OP_MOVFL	OP_MOVFUL	OP_MOVFLG
	OP_MOVFNE	OP_MOVFE	OP_MOVFUE	OP_MOVFGE
	OP_MOVFUGE	OP_MOVFLE	OP_MOVFULE	OP_MOVFO ];

sem [ fmovrsz fmovrslez fmovrslz fmovrsnz fmovrsgz fmovrsgez ] {
    set_op(new_inst,Op,FU_ALU,1);
    Rx_src(new_inst,rs1); F4_src(new_inst,rs2);
    F4_dest(new_inst,rd);
} where Op in [OP_MOVRZ OP_MOVRLEZ OP_MOVRLZ OP_MOVRNZ OP_MOVRGZ OP_MOVRGEZ];

sem [ fmovrdz fmovrdlez fmovrdlz fmovrdnz fmovrdgz fmovrdgez ] {
    set_op(new_inst,Op,FU_ALU,1); Rx_src(new_inst,rs1);
    F8_src(new_inst,rs2); F8_dest(new_inst,rd);
} where Op in [OP_MOVRZ OP_MOVRLEZ OP_MOVRLZ OP_MOVRNZ OP_MOVRGZ OP_MOVRGEZ];

sem [ movn movfn ] {};
sem [ mova movfa ] {
    set_op(new_inst,OP_MOVA,FU_ALU,1);
    Rx_src(new_inst,rs2); Rx_dest(new_inst,rd);
};

sem [					movne		move
	movg		movle		movge		movl
	movgu		movleu		movcc		movcs
	movpos		movneg		movvc		movvs	] {
    set_op(new_inst,Op,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_CCR,bpcc1));
    Rx_src(new_inst,rs2); Rx_dest(new_inst,rd);
} where Op in [				OP_MOVNE	OP_MOVE
	OP_MOVG		OP_MOVLE	OP_MOVGE	OP_MOVL
	OP_MOVGU	OP_MOVLEU	OP_MOVCC	OP_MOVCS
	OP_MOVPOS	OP_MOVNEG	OP_MOVVC	OP_MOVVS ];

sem [			movfu	movfg	movfug	movfl	movful	movflg
	movfne	movfe	movfue	movfge	movfuge	movfle	movfule	movfo	] {
    set_op(new_inst,Op,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_FCC,bpccr));
    Rx_src(new_inst,rs2); Rx_dest(new_inst,rd);
} where Op in [				OP_MOVFU	OP_MOVFG
	OP_MOVFUG	OP_MOVFL	OP_MOVFUL	OP_MOVFLG
	OP_MOVFNE	OP_MOVFE	OP_MOVFUE	OP_MOVFGE
	OP_MOVFUGE	OP_MOVFLE	OP_MOVFULE	OP_MOVFO ];

sem [ movrz movrlez movrlz movrnz movrgz movrgez ] {
    set_op(new_inst,Op,FU_ALU,1); Rx_src(new_inst,rs1);
    Rx_src(new_inst,rs2); Rx_dest(new_inst,rd);
} where Op in [OP_MOVRZ OP_MOVRLEZ OP_MOVRLZ OP_MOVRNZ OP_MOVRGZ OP_MOVRGEZ];

//
// System traps:

sem tn {
    set_op(new_inst,OP_NOP,FU_NONE,FT_DONE);
};

sem ta {
    set_op(new_inst,OP_TA,FU_ALU,1);
    if(i) new_inst.srcq?push_back(literal_src(sw_trap));
    else Rx_src(new_inst,rs2);
    is_trap = true;
};

sem [			tne	te	tg	tle	tge	tl
	tgu	tleu	tcc	tcs	tpos	tneg	tvc	tvs	] {
    set_op(new_inst,Op,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_CCR,bpcc1));
    if(i) new_inst.srcq?push_back(literal_src(sw_trap));
    else Rx_src(new_inst,rs2);
    is_trap = true;
} where Op in [		OP_TNE	OP_TE	OP_TG	OP_TLE	OP_TGE	OP_TL
	OP_TGU	OP_TLEU	OP_TCC	OP_TCS	OP_TPOS	OP_TNEG	OP_TVC	OP_TVS	];

//
// Arithmetic ops:

sem [		add	sub	and	andn	or	orn	xor	xnor
		sll	srl	sra		sllx	srlx	srax
		mulx		sdivx		udivx			] {
    set_op(new_inst,Op,FU_ALU,ft);
    Rx_src(new_inst,rs1); SRC2; Rx_dest(new_inst,rd);
} where Op in [	OP_ADD	OP_SUB	OP_AND	OP_ANDN	OP_OR	OP_ORN	OP_XOR	OP_XNOR
		OP_SLL	OP_SRL	OP_SRA		OP_SLLX	OP_SRLX	OP_SRAX
		OP_MULX		OP_SDIVX	OP_UDIVX		],
	ft in [	1	1	1	1	1	1	1	1
		1	1	1		1	1	1
		2		10		10			];

sem [		addcc		subcc		andcc		andncc
		orcc		orncc		xorcc		xnorcc	] {
    set_op(new_inst,Op,FU_ALU,1);
    Rx_src(new_inst,rs1); SRC2; Rx_dest(new_inst,rd);
    new_inst.destq?push_back(rmap_dest(REG_CCR,0));
} where Op in [	OP_ADDCC	OP_SUBCC	OP_ANDCC	OP_ANDNCC
		OP_ORCC		OP_ORNCC	OP_XORCC	OP_XNORCC ];

sem [		addc		subc	] {
    set_op(new_inst,Op,FU_ALU,1);
    Rx_src(new_inst,rs1); SRC2; Rx_dest(new_inst,rd);
    new_inst.srcq?push_back(rmap_src(REG_CCR,0));
} where Op in [	OP_ADDC		OP_SUBC	];

sem [		addccc		subccc
		taddcc		taddcctv
		tsubcc		tsubcctv	] {
    set_op(new_inst,Op,FU_ALU,1);
    Rx_src(new_inst,rs1); SRC2; Rx_dest(new_inst,rd);
    new_inst.srcq?push_back(rmap_src(REG_CCR,0));
    new_inst.destq?push_back(rmap_dest(REG_CCR,0));
} where Op in [	OP_ADDCCC	OP_SUBCCC
		OP_TADDCC	OP_TADDCCTV
		OP_TSUBCC	OP_TSUBCCTV	];

sem [ udiv sdiv ] {
    set_op(new_inst,Op,FU_ALU,10);
    new_inst.srcq?push_back(rmap_src(REG_Y,0));
    Rx_src(new_inst,rs1); SRC2; Rx_dest(new_inst,rd);
} where Op in [OP_UDIV OP_SDIV];

sem [ umul smul ] {
    set_op(new_inst,Op,FU_ALU,2);
    Rx_src(new_inst,rs1); SRC2;
    new_inst.destq?push_back(rmap_dest(REG_Y,0));
    Rx_dest(new_inst,rd);
} where Op in [OP_UMUL OP_SMUL];

sem [ udivcc sdivcc ] {
    set_op(new_inst,Op,FU_ALU,10);
    new_inst.srcq?push_back(rmap_src(REG_Y,0));
    Rx_src(new_inst,rs1); SRC2; Rx_dest(new_inst,rd);
    new_inst.destq?push_back(rmap_dest(REG_CCR,0));
} where Op in [OP_UDIVCC OP_SDIVCC];

sem [ umulcc smulcc ] {
    set_op(new_inst,Op,FU_ALU,2);
    Rx_src(new_inst,rs1); SRC2;
    new_inst.destq?push_back(rmap_dest(REG_Y,0));
    Rx_dest(new_inst,rd);
    new_inst.destq?push_back(rmap_dest(REG_CCR,0));
} where Op in [OP_UMULCC OP_SMULCC];

sem mulscc {
    set_op(new_inst,OP_MULSCC,FU_ALU,1);
    new_inst.srcq?push_back(rmap_src(REG_Y,0));
    Rx_src(new_inst,rs1); SRC2;
    new_inst.srcq?push_back(rmap_src(REG_CCR,0));
    new_inst.destq?push_back(rmap_dest(REG_Y,0));
    Rx_dest(new_inst,rd);
    new_inst.destq?push_back(rmap_dest(REG_CCR,0));
};

sem popc {
    set_op(new_inst,OP_POPC,FU_ALU,1);
    Rx_src(new_inst,rs1); Rx_dest(new_inst,rd);
};

sem flush { set_op(new_inst,OP_NOP,FU_NONE,FT_DONE); };
sem flushw { set_op(new_inst,OP_FLUSHW,FU_NONE,FT_DONE); is_trap = true; };

sem rd {
    set_op(new_inst,OP_RD,FU_ALU,1);
    switch(rs1?ext(32)) {
     case 0:	new_inst.srcq?push_back(rmap_src(REG_Y,0));
     case 2:	new_inst.srcq?push_back(rmap_src(REG_CCR,0));
     case 5:	new_inst.srcq?push_back(literal_src(PC?addr));
     case 15:	assert(rd?ext(32)==0); new_inst.op = OP_NOP?cvt(ushort);
     default:
	/* not implemented */
	assert(false);
    }
    Rx_dest(new_inst,rd);
};

sem wr {
    set_op(new_inst,OP_WR,FU_ALU,1);
    Rx_src(new_inst,rs1); SRC2;
    switch(rd?ext(32)) {
     case 0:	new_inst.destq?push_back(rmap_dest(REG_Y,0));
     case 2:	new_inst.destq?push_back(rmap_dest(REG_CCR,0));
     default:
	/* not implemented */
	assert(false);
    }
};

sem [ save restore ] {
    set_op(new_inst,Op,FU_ALU,1);
    Rx_src(new_inst,rs1); SRC2;
    adjust_window(new_inst);
    Rx_dest(new_inst,rd);
} where adjust_window in [ window_save window_restore ],
	Op in [ OP_SAVE OP_RESTORE ];

sem sethi {
    set_op(new_inst,OP_NOP,FU_NONE,FT_DONE);
    val literal = imm22?ext(64) << 10;
    new_inst.srcq?push_back(literal_src(literal));    
    Rx_dest(new_inst,rd);
    rmap_write(0,literal,instq?length());
};

//
// Floating-point arithmetic:

sem [		fadds		fsubs		fmuls		fdivs	] {
    set_op(new_inst,Op,FU_FPU,ft);
    F4_src(new_inst,rs1); F4_src(new_inst,rs2);
    F4_dest(new_inst,rd);
} where Op in [	OP_FADDS	OP_FSUBS	OP_FMULS	OP_FDIVS ],
	ft in [	1		1		2		10	];

sem [		faddd		fsubd		fmuld		fdivd	] {
    set_op(new_inst,Op,FU_FPU,ft);
    F8_src(new_inst,rs1); F8_src(new_inst,rs2);
    F8_dest(new_inst,rd);
} where Op in [	OP_FADDD	OP_FSUBD	OP_FMULD	OP_FDIVD ],
	ft in [	1		1		5		23	];

sem fsmuld {
    set_op(new_inst,OP_FSMULD,FU_FPU,2);
    F4_src(new_inst,rs1); F4_src(new_inst,rs2);
    F8_dest(new_inst,rd);
};

sem [		fcmps		fcmpes		] {
    set_op(new_inst,Op,FU_FPU,1);
    F4_src(new_inst,rs1); F4_src(new_inst,rs2);
    new_inst.destq?push_back(rmap_dest(REG_FCC,cond));
} where Op in [	OP_FCMPS	OP_FCMPES	];

sem [		fcmpd		fcmped		] {
    set_op(new_inst,Op,FU_FPU,1);
    F8_src(new_inst,rs1); F8_src(new_inst,rs2);
    new_inst.destq?push_back(rmap_dest(REG_FCC,cond));
} where Op in [	OP_FCMPD	OP_FCMPED	];

sem [		fstox		fitod		fstod	] {
    set_op(new_inst,Op,FU_FPU,1);
    F4_src(new_inst,rs2);
    F8_dest(new_inst,rd);
} where Op in [	OP_FSTOX	OP_FITOD	OP_FSTOD ];

sem [		fdtox		fxtod
		fmovd		fnegd		fabsd		fsqrtd	] {
    set_op(new_inst,Op,FU_FPU,1);
    F8_src(new_inst,rs2);
    F8_dest(new_inst,rd);
} where Op in [	OP_FDTOX	OP_FXTOD
		OP_FMOVD	OP_FNEGD	OP_FABSD	OP_FSQRTD ];

sem [		fxtos		fdtos		fdtoi		] {
    set_op(new_inst,Op,FU_FPU,1);
    F8_src(new_inst,rs2);
    F4_dest(new_inst,rd);
} where Op in [	OP_FXTOS	OP_FDTOS	OP_FDTOI	];

sem [		fitos		fstoi
		fmovs		fnegs		fabss		fsqrts	] {
    set_op(new_inst,Op,FU_FPU,1);
    F4_src(new_inst,rs2);
    F4_dest(new_inst,rd);
} where Op in [	OP_FITOS	OP_FSTOI
		OP_FMOVS	OP_FNEGS	OP_FABSS	OP_FSQRTS ];

//
// Load, store, etc.:

sem [ ldf ldfa ] {
    set_op(new_inst,OP_LDUW,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    F4_dest(new_inst,rd);
    new_inst.align = 2?cvt(uchar);
};

sem [ lddf lddfa ] {
    set_op(new_inst,OP_LDD,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    F8_dest(new_inst,rd);
    new_inst.align = 3?cvt(uchar);
};

sem [		ldsb	ldsh	ldsw	ldub	lduh	lduw	ldx
		ldsba	ldsha	ldswa	lduba	lduha	lduwa	ldxa	] {
    set_op(new_inst,Op,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    Rx_dest(new_inst,rd);
    new_inst.align = align?cvt(uchar);
} where Op in [	OP_LDSB	OP_LDSH	OP_LDSW	OP_LDUB	OP_LDUH	OP_LDUW	OP_LDX
		OP_LDSB	OP_LDSH	OP_LDSW	OP_LDUB	OP_LDUH	OP_LDUW	OP_LDX	],
     align in [	0	1	2	0	1	2	3
		0	1	2	0	1	2	3	];

sem [ ldd ldda ] {
    set_op(new_inst,OP_LDD,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    R8_dest(new_inst,rd);
    new_inst.align = 3?cvt(uchar);
};

sem [ stf stfa ] {
    set_op(new_inst,OP_STW,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    F4_src(new_inst,rd);
    new_inst.align = 2?cvt(uchar);
};

sem [ stdf stdfa ] {
    set_op(new_inst,OP_STD,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    F8_src(new_inst,rd);
    new_inst.align = 3?cvt(uchar);
};

sem [		stb		sth		stw		stx	] {
    set_op(new_inst,Op,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    Rx_src(new_inst,rd);
    new_inst.align = align?cvt(uchar);
} where Op in [ OP_STB		OP_STH		OP_STW		OP_STX	],
     align in [	0		1		2		3	];

sem [ std stda ] {
    set_op(new_inst,OP_STD,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    R8_src(new_inst,rd);
    new_inst.align = 3?cvt(uchar);
};

sem casa {
    set_op(new_inst,OP_CASA,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    Rx_src(new_inst,rd);
    Rx_dest(new_inst,rd);
    new_inst.align = 2?cvt(uchar);
};

sem casxa {
    set_op(new_inst,OP_CASXA,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    R8_src(new_inst,rd);
    R8_dest(new_inst,rd);
    new_inst.align = 3?cvt(uchar);
};

sem [ ldstub ldstuba ] {
    set_op(new_inst,OP_LDSTUB,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    Rx_dest(new_inst,rd);
    new_inst.align = 0?cvt(uchar);
};

sem [ prefetch prefetcha ] {
    set_op(new_inst,OP_NOP,FU_ADDR,FT_DONE);
};

sem [ swap swapa ] {
    set_op(new_inst,OP_SWAP,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    Rx_src(new_inst,rd);
    Rx_dest(new_inst,rd);
    new_inst.align = 2?cvt(uchar);
};

sem [		ldfsr		ldxfsr		] {
    set_op(new_inst,Op,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    new_inst.destq?push_back(rmap_dest(REG_FSR,0));
    new_inst.align = align?cvt(uchar);
    is_trap = true;
} where Op in [	OP_LDFSR	OP_LDXFSR	],
     align in [ 2		3		];

sem [		stfsr		stxfsr		] {
    set_op(new_inst,Op,FU_ADDR,1);
    Rx_src(new_inst,rs1); SRC2;
    new_inst.srcq?push_back(rmap_src(REG_FSR,0));
    new_inst.align = align?cvt(uchar);
    is_trap = true;
} where Op in [	OP_STFSR	OP_STXFSR	],
     align in [	2		3		];

#endif