/******************************************************************************
** FILE: sparc_v9_enc.fs
*/

#define NUM_REGISTER_WINDOWS 8
#define LOG2_REGISTER_WINDOWS 3

token instruction[32] fields
    op 30:31, op2 22:24, op3 19:24, opf 5:13, rd 25:29, rs1 14:18, rs2 0:4,
    opf_cc 11:13, opf_low 5:10, cond 25:28, mcond 14:17, rcond 10:12,
    disp30 0:29, disp22 0:21, disp19 0:18, d16hi 20:21, d16lo 0:13,
    imm22 0:21, simm13 0:12, simm11 0:10, simm10 0:9, imm_asi 5:12,
    shcnt32 0:4, shcnt64 0:5, sw_trap 0:6,
    movcc2 18:18, movccr 11:12, movcc1 12:12, movcc0 11:11,
    bpccr 20:21, bpcc1 21:21, bpcc0 20:20,
    a 29:29, p 19:19, i 13:13, x 12:12;

pat reg_imm13 = (i==0 && instruction?bits(5,12)==0) || i==1;
pat reg_imm11 = (i==0 && instruction?bits(5,10)==0) || i==1;
pat reg_imm10 = (i==0 && instruction?bits(5,9)==0) || i==1;

pat reg_shcnt64 = (i==0 && instruction?bits(5,11)==0) ||
		  (i==1 && instruction?bits(6,11)==0);

pat reg_trap = (i==0 && instruction?bits(5,10)==0) ||
	       (i==1 && instruction?bits(7,10)==0);

pat reg_imm13_inv = (i==1 && instruction?bits(5,12)==0) || i==0;

//
// Op0 instructions:

pat [	_trap	_bpcc	bicc	bpr	sethi	fbpfcc	fbfcc	_	]
    = op==0 && op2 in [0..7];

pat illtrap = _trap && rd==0;

pat [	_	brz	brlez	brlz	_	brnz	brgz	brgez	]
    = bpr && cond in [0x0..0x7];

pat [	fbn	fbne	fblg	fbul	fbl	fbug	fbg	fbu
	fba	fbe	fbue	fbge	fbuge	fble	fbule	fbo	]
    = fbfcc && cond in [0x0..0xf];

pat [	fbpn	fbpne	fbplg	fbpul	fbpl	fbpug	fbpg	fbpu
	fbpa	fbpe	fbpue	fbpge	fbpuge	fbple	fbpule	fbpo	]
    = fbpfcc && cond in [0x0..0xf];

pat [	bn	be	ble	bl	bleu	bcs	bneg	bvs
	ba	bne	bg	bge	bgu	bcc	bpos	bvc	]
    = bicc && cond in [0x0..0xf];

pat [	bpn	bpe	bple	bpl	bpleu	bpcs	bpneg	bpvs
	bpa	bpne	bpg	bpge	bpgu	bpcc	bppos	bpvc	]
    = _bpcc && cond in [0x0..0xf] && bpcc0==0;

//
// Op2 instruction:

pat [	add	and	or	xor	sub	andn	orn	xnor
	addc	mulx	umul	smul	subc	udivx	udiv	sdiv
	addcc	andcc	orcc	xorcc	subcc	andncc	orncc	xnorcc
	addccc	_	umulcc	smulcc	subccc	_	udivcc	sdivcc
	taddcc	tsubcc	taddcctv tsubcctv mulscc _	_	_
	_	_	_	_	_	sdivx	_popc	_
	wr	_	_	_	_	_	_	_
	jmpl	_retrn	_	_flush	save	restore	_	_	]
    = op==2 && op3 in [0x0..0x3f] && reg_imm13;

pat flush = _flush && rd==0;
pat flushw = op==2 && op3==0x2b && rd==0 && instruction?bits(0,18)==0;
	
pat impdep1 = op==2 && op3==0x36;
pat impdep2 = op==2 && op3==0x37;

pat [	movfn	movfne	movflg	movful	movfl	movfug	movfg	movfu
	movfa	movfe	movfue	movfge	movfuge	movfle	movfule	movfo	]
    = op==2 && op3==0x2c && mcond in [0x0..0xf] && i==0 && reg_imm11;

pat [	movn	move	movle	movl	movleu	movcs	movneg	movvs
	mova	movne	movg	movge	movgu	movcc	movpos	movvc	]
    = op==2 && op3==0x2c && mcond in [0x0..0xf] && i==1 && reg_imm11;

pat [	_	movrz	movrlez	movrlz	_	movrnz	movrgz	movrgez	]
    = op==2 && op3==0x2f && rcond in [0..7] && reg_imm10;

pat popc = _popc && rs1==0;

pat rd = op==2 && op3==0x28 && instruction?bits(0,13)==0;

pat retrn = _retrn && rd==0;

pat [ sll srl sra ]
    = op==2 && op3 in [0x25..0x27] && x==0 && instruction?bits(5,11)==0;
pat [ sllx srlx srax ] = op==2 && op3 in [0x25..0x27] && x==1 && reg_shcnt64;

pat stbar = op==2 && op3==0x28 && rd==0 && rs1==0x0f &&
	    instruction?bits(0,13)==0;

pat [	tn	te	tle	tl	tleu	tcs	tneg	tvs
	ta	tne	tg	tge	tgu	tcc	tpos	tvc	]
    = op==2 && op3==0x3a && cond in [0x0..0xf] && a==0 && reg_trap;

//
// Floating-point instructions (also Op2):

pat fpop1 = op==2 && op3==0b110100;
pat fpop2 = op==2 && op3==0b110101;

pat [	_	fadds	faddd	faddq	_	fsubs	fsubd	fsubq	]
    = fpop1 && opf in [0x40..0x47];

pat [	_	fcmps	fcmpd	fcmpq	_	fcmpes	fcmped	fcmpeq	]
    = fpop2 && opf in [0x50..0x57] && instruction?bits(27,29)==0;

pat [	fstox	fdtox	fqtox	fstoi	fdtoi	fqtoi
	fstod	fstoq	fdtos	fdtoq	fqtos	fqtod
	fxtos	fxtod	fxtoq	fitos	fitod	fitoq	]
    = fpop1 && rs1==0 && opf in
    [	0x81	0x82	0x83	0xd1	0xd2	0xd3
	0xc9	0xcd	0xc6	0xce	0xc7	0xcb
	0x84	0x88	0x8c	0xc4	0xc8	0xcc	];

pat [	_	fmovs	fmovd	fmovq
	_	fnegs	fnegd	fnegq
	_	fabss	fabsd	fabsq	]
    = fpop1 && opf in [0x0..0xb] && rs1==0;

pat [ fmuls fmuld fmulq fsmuld fdmulq fdivs fdivd fdivq ]
    = fpop1 && opf in [0x49 0x4a 0x4b 0x69 0x6e 0x4d 0x4e 0x4f];

pat [	_	fsqrts	fsqrtd	fsqrtq	]
    = fpop1 && opf in [0x28..0x2b] && rs1==0;

pat [	fmovfsn fmovfsne fmovfslg fmovfsul fmovfsl fmovfsug fmovfsg fmovfsu
	fmovfsa fmovfse fmovfsue fmovfsge fmovfsuge fmovfsle fmovfsule fmovfso
	fmovfdn fmovfdne fmovfdlg fmovfdul fmovfdl fmovfdug fmovfdg fmovfdu
	fmovfda fmovfde fmovfdue fmovfdge fmovfduge fmovfdle fmovfdule fmovfdo
	fmovfqn fmovfqne fmovfqlg fmovfqul fmovfql fmovfqug fmovfqg fmovfqu
	fmovfqa fmovfqe fmovfque fmovfqge fmovfquge fmovfqle fmovfqule fmovfqo
    ] = fpop2 && opf_low in [1 2 3] && rs1 in [0x0..0xf] && i==0;

pat [	fmovsn	fmovse	fmovsle	fmovsl	fmovsleu fmovscs fmovsneg fmovsvs
	fmovsa	fmovsne	fmovsg	fmovsge	fmovsgu	fmovscc	fmovspos fmovsvc
	fmovdn	fmovde	fmovdle	fmovdl	fmovdleu fmovdcs fmovdneg fmovdvs
	fmovda	fmovdne	fmovdg	fmovdge	fmovdgu	fmovdcc	fmovdpos fmovdvc
	fmovqn	fmovqe	fmovqle	fmovql	fmovqleu fmovqcs fmovqneg fmovqvs
	fmovqa	fmovqne	fmovqg	fmovqge	fmovqgu	fmovqcc	fmovqpos fmovqvc ]
    = fpop2 && opf_low in [1 2 3] && rs1 in [0x0..0xf] && i==1 && movcc0==0;

pat [	_	fmovrsz	fmovrslez fmovrslz _	fmovrsnz fmovrsgz fmovrsgez
	_	fmovrdz	fmovrdlez fmovrdlz _	fmovrdnz fmovrdgz fmovrdgez
	_	fmovrqz	fmovrqlez fmovrqlz _	fmovrqnz fmovrqgz fmovrqgez ]
    = fpop2 && opf_low in [0x5..0x7] && rcond in [0..7] && i==0;

//
// Op1 instruction: CALL

pat call = op==1;

//
// Op3 instructions:

pat [ casa casxa ] = op==3 && op3 in [0x3c 0x3e] && reg_imm13_inv;

pat [	ldf	_ldfsr	_ldqf	lddf	stf	_stfsr	_stqf	stdf
	_	_	_	_	_	prefetch _	_	]
    = op==3 && op3 in [0x20..0x2f] && reg_imm13;

pat [ ldfsr ldxfsr ] = _ldfsr && rd in [0 1];
pat [ stfsr stxfsr ] = _stfsr && rd in [0 1];
pat ldqf = _ldqf && rd?bit(1)==0;
pat stqf = _stqf && rd?bit(1)==0;

pat [	ldfa	_	_ldqfa	lddfa	stfa	_	_stqfa	stdfa
	_	_	_	_	_	prefetcha _	_	]
    = op==3 && op3 in [0x30..0x3f];

pat ldqfa = _ldqfa && rd?bit(0)==0;
pat stqfa = _stqfa && rd?bit(0)==0;

pat [	lduw	ldub	lduh	_ldd	stw	stb	sth	_std
	ldsw	ldsb	ldsh	ldx	_	ldstub	stx	swap	]
    = op==3 && op3 in [0x00..0x0f] && reg_imm13;

pat ldd = _ldd && rd?bit(0)==0;
pat std = _std && rd?bit(0)==0;

pat [	lduwa	lduba	lduha	_ldda	stwa	stba	stha	_stda
	ldswa	ldsba	ldsha	ldxa	_	ldstuba	stxa	swapa	]
    = op==3 && op3 in [0x00..0x0f];

pat ldda = _ldda && rd?bit(0)==0;
pat stda = _stda && rd?bit(0)==0;

//
// UltraSPARC specific

pat alignaddress = impdep1 && opf==0x18;