SPARC: Various changes

- additional patterns
 - minor instruction fixes in mul/div/64-bit math
 - do not pass g0 to zeroflags
 - conditional trap
This commit is contained in:
mumbel 2024-09-09 14:38:35 -05:00
parent c8a455e197
commit 34e1329595
2 changed files with 180 additions and 124 deletions

View File

@ -492,8 +492,9 @@ macro unpackflags(ccr) {
:addcc RS1,regorimm,RD is op=2 & RD & op3=0x10 & RS1 & regorimm
{
addflags(RS1,regorimm);
RD = RS1 + regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 + regorimm;
zeroflags(res);
RD = res;
}
:addc RS1,regorimm,RD is op=2 & RD & op3=0x8 & RS1 & regorimm {RD = RS1 + regorimm + zext(i_cf);}
@ -502,8 +503,9 @@ macro unpackflags(ccr) {
{
local original_i_cf:$(SIZE) = zext(i_cf);
addCarryFlags(RS1,regorimm);
RD = RS1 + regorimm + original_i_cf;
zeroflags(RD);
local res:$(SIZE) = RS1 + regorimm + original_i_cf;
zeroflags(res);
RD = res;
}
#-----------------------
:and RS1,regorimm,RD is op=2 & RD & op3=0x1 & RS1 & regorimm {RD = RS1 & regorimm;}
@ -511,16 +513,18 @@ macro unpackflags(ccr) {
:andcc RS1,regorimm,RD is op=2 & RD & op3=0x11 & RS1 & regorimm
{
logicflags();
RD = RS1 & regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 & regorimm;
zeroflags(res);
RD = res;
}
:andn RS1,regorimm,RD is op=2 & RD & op3=0x5 & RS1 & regorimm {RD = RS1 & ~regorimm;}
:andncc RS1,regorimm,RD is op=2 & RD & op3=0x15 & RS1 & regorimm
{
logicflags();
RD = RS1 & ~regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 & ~regorimm;
zeroflags(res);
RD = res;
}
:or RS1,regorimm,RD is op=2 & RD & op3=0x2 & RS1 & regorimm {RD = RS1 | regorimm;}
@ -528,24 +532,27 @@ macro unpackflags(ccr) {
:orcc RS1,regorimm,RD is op=2 & RD & op3=0x12 & RS1 & regorimm
{
logicflags();
RD = RS1 | regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 | regorimm;
zeroflags(res);
RD = res;
}
:orn RS1,regorimm,RD is op=2 & RD & op3=0x6 & RS1 & regorimm {RD = RS1 | ~regorimm;}
:orncc RS1,regorimm,RD is op=2 & RD & op3=0x16 & RS1 & regorimm
{
logicflags();
RD = RS1 | ~regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 | ~regorimm;
zeroflags(res);
RD = res;
}
:xor RS1,regorimm,RD is op=2 & RD & op3=0x3 & RS1 & regorimm {RD = RS1 ^ regorimm;}
:xorcc RS1,regorimm,RD is op=2 & RD & op3=0x13 & RS1 & regorimm
{
logicflags();
RD = RS1 ^ regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 ^ regorimm;
zeroflags(res);
RD = res;
}
:xnor RS1,regorimm,RD is op=2 & RD & op3=0x7 & RS1 & regorimm {RD = RS1 ^ ~regorimm;}
@ -553,8 +560,9 @@ macro unpackflags(ccr) {
:xnorcc RS1,regorimm,RD is op=2 & RD & op3=0x17 & RS1 & regorimm
{
logicflags();
RD = RS1 ^ ~regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 ^ ~regorimm;
zeroflags(res);
RD = res;
}
# ---------------
@ -615,8 +623,9 @@ macro unpackflags(ccr) {
:subcc RS1,regorimm,RD is op=2 & RD & op3=0x14 & RS1 & regorimm
{
subflags(RS1,regorimm);
RD = RS1 - regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 - regorimm;
zeroflags(res);
RD = res;
}
:subc RS1,regorimm,RD is op=2 & RD & op3=0xc & RS1 & regorimm
@ -628,8 +637,9 @@ macro unpackflags(ccr) {
{
local original_cf:$(SIZE) = zext(i_cf);
subCarryFlags(RS1,regorimm);
RD = RS1 - regorimm - original_cf;
zeroflags(RD);
local res:$(SIZE) = RS1 - regorimm - original_cf;
zeroflags(res);
RD = res;
}
# ---------------
@ -641,8 +651,8 @@ macro unpackflags(ccr) {
:cmp RS1,regorimm is op=0x2 & rd=0x0 & op3=0x14 & RS1 & regorimm
{
subflags(RS1,regorimm);
local tmp = RS1 - regorimm;
zeroflags(tmp);
local res:$(SIZE) = RS1 - regorimm;
zeroflags(res);
}
@ -825,43 +835,65 @@ callreloff: reloc is disp30 [reloc=inst_start+4*disp30;] { export *:$(SIZE) rel
#----------------MULTIPLY 32 bit
@if SIZE=="8"
:umul RS1,regorimm,RD is op=2 & RD & op3=0x0a & RS1 & regorimm {RD = zext(RS1:4) * zext(regorimm:4); Y=RD>>32;}
:smul RS1,regorimm,RD is op=2 & RD & op3=0x0b & RS1 & regorimm {RD = sext(RS1:4) * sext(regorimm:4); Y=RD>>32;}
:umulcc RS1,regorimm,RD is op=2 & RD & op3=0x1a & RS1 & regorimm {RD = zext(RS1:4) * zext(regorimm:4); Y=RD>>32; zeroflags(RD); logicflags();}
:smulcc RS1,regorimm,RD is op=2 & RD & op3=0x1b & RS1 & regorimm {RD = sext(RS1:4) * sext(regorimm:4); Y=RD>>32; zeroflags(RD); logicflags();}
:umul RS1,regorimm,RD is op=2 & RD & op3=0x0a & RS1 & regorimm
{
local res:8 = zext(RS1:4) * zext(regorimm:4);
Y = res >> 32;
RD = res:4;
}
:smul RS1,regorimm,RD is op=2 & RD & op3=0x0b & RS1 & regorimm
{
local res:8 = sext(RS1:4) * sext(regorimm:4);
Y = res s>> 32;
RD = res:4;
}
:umulcc RS1,regorimm,RD is op=2 & RD & op3=0x1a & RS1 & regorimm
{
local res:8 = zext(RS1:4) * zext(regorimm:4);
Y = res >> 32;
zeroflags(res:4);
RD = res:4;
logicflags();
}
:smulcc RS1,regorimm,RD is op=2 & RD & op3=0x1b & RS1 & regorimm
{
local res:8 = sext(RS1:4) * sext(regorimm:4);
Y = res s>> 32;
zeroflags(res:4);
RD = res:4;
logicflags();
}
@else
# size = 4
:umul RS1,regorimm,RD is op=2 & RD & op3=0x0a & RS1 & regorimm
{
tmp_RS1:8 = zext(RS1);
tmp_regorimm:8 = zext(regorimm);
tmp:8 = tmp_RS1 * tmp_regorimm;
RD = tmp:4; tmp2:8 = tmp >> 32;
Y = tmp2:4;
local res:8 = zext(RS1:4) * zext(regorimm:4);
Y = res[32,32];
RD = res:4;
}
:smul RS1,regorimm,RD is op=2 & RD & op3=0x0b & RS1 & regorimm
{
tmp_RS1:8 = sext(RS1);
tmp_regorimm:8 = sext(regorimm);
tmp:8 = tmp_RS1 * tmp_regorimm;
RD = tmp:4; tmp2:8 = tmp >> 32;
Y = tmp2:4;
local res:8 = sext(RS1:4) * sext(regorimm:4);
Y = res[32,32];
RD = res:4;
}
:umulcc RS1,regorimm,RD is op=2 & RD & op3=0x1a & RS1 & regorimm
{
RD = zext(RS1:4) * zext(regorimm:4);
Y=RD>>32;
zeroflags(RD);
local res:8 = zext(RS1:4) * zext(regorimm:4);
Y = res[32,32];
zeroflags(res:4);
RD = res:4;
logicflags();
}
:smulcc RS1,regorimm,RD is op=2 & RD & op3=0x1b & RS1 & regorimm
{
RD = zext(RS1:4) * zext(regorimm:4);
Y=RD>>32;
zeroflags(RD);
local res:8 = sext(RS1:4) * sext(regorimm:4);
Y = res[32,32];
zeroflags(res:4);
RD = res:4;
logicflags();
}
@ -883,8 +915,9 @@ callreloff: reloc is disp30 [reloc=inst_start+4*disp30;] { export *:$(SIZE) rel
addflags32(addend,shifted);
#upper 32 bits of RD are undefined according to the manual
local tbit:4 = (RS1:4 & 0x1:4) << 31;
RD = zext(sum);
zeroflags(RD);
local res:$(SIZE) = zext(sum);
zeroflags(res);
RD = res;
#Y is 64 bits in Sparc 9 but the high 32 are fixed to 0
Y = zext((Y:4 >> 1:4) | tbit);
}
@ -896,35 +929,39 @@ callreloff: reloc is disp30 [reloc=inst_start+4*disp30;] { export *:$(SIZE) rel
:udiv RS1,regorimm,RD is op=2 & RD & op3=0x0e & RS1 & regorimm
{
numerator:$(SIZE)= (Y << 32) + (RS1 & 0xffffffff);
denom:$(SIZE) = regorimm & 0xffffffff;
RD = numerator / denom;
numerator:8 = (zext(Y) << 32) + zext(RS1);
denom:8 = zext(regorimm:4);
local res:8 = numerator / denom;
RD = zext(res:4);
}
:sdiv RS1,regorimm,RD is op=2 & RD & op3=0x0f & RS1 & regorimm
{
numerator:$(SIZE)= (Y << 32) + (RS1 & 0xffffffff);
denom:$(SIZE) = regorimm & 0xffffffff;
RD = numerator s/ denom;
numerator:8 = (sext(Y) << 32) + zext(RS1:4);
denom:8 = sext(regorimm:4);
local res:8 = numerator s/ denom;
RD = sext(res:4);
}
:udivcc RS1,regorimm,RD is op=2 & RD & op3=0x1e & RS1 & regorimm
{
numerator:$(SIZE)= ( Y << 32) + (RS1 & 0xffffffff);
denom:$(SIZE) = regorimm & 0xffffffff;
RD = numerator / denom;
zeroflags(RD);
i_vf = RD > 0xffffffff;
numerator:8 = (zext(Y) << 32) + zext(RS1:4);
denom:8 = zext(regorimm:4);
local res:8 = numerator / denom;
zeroflags(res:4);
RD = zext(res:4);
i_vf = res > 0xffffffff;
i_cf = 0;
x_vf = 0;
x_cf = 0;
}
:sdivcc RS1,regorimm,RD is op=2 & RD & op3=0x1f & RS1 & regorimm
{
numerator:$(SIZE)= (Y << 32) + (RS1 & 0xffffffff);
denom:$(SIZE) = regorimm & 0xffffffff;
RD = numerator s/ denom;
zeroflags(RD);
i_vf = (RD s>= 0x80000000) || (RD s<= -0x7fffffff);
numerator:8 = (sext(Y) << 32) + (zext(RS1) & 0xffffffff);
denom:8 = sext(regorimm:4);
local res:8 = numerator s/ denom;
zeroflags(res:4);
RD = sext(res:4);
i_vf = (res s>= 0x80000000) || (res s<= -0x7ffffffff);
i_cf = 0;
x_vf = 0;
x_cf = 0;
@ -990,6 +1027,12 @@ sethidisp: "%hi("^hi^")" is udisp22 [hi=udisp22<<10;] { export *[const]:$(SIZE)
:restore RS1,regorimm,RD is op=0x2 & RD & op3=0x3d & RS1 & regorimm { local tmp = RS1 + regorimm; restore(); didrestore=1; RD = tmp; }
:restore is op=0x2 & rd=0 & op3=0x3d { restore(); didrestore=1; }
# FIXME 'jmpl' can have 'return' in the delayslot to return from a user trap handler
# - jmpl sets the trapped PC supplied to user trap handler
# - return sets the trapped nPC supplied to user trap handler
# Nothing in instruction encoding defines this, requiring a context register;
# or a fake 8-byte instruction, requiring logic for 64-bits of tokens
:return retea is op=0x2 & op3=0x39 & retea { build retea; restore(); delayslot(1); didrestore=1; return [retea]; }
:jmpl retea,RD is op=0x2 & RD & op3=0x38 & retea { build retea; RD = inst_start; delayslot(1); goto [retea]; }
@ -1013,52 +1056,70 @@ casa_ea: [RS1]%ASI is i=1 & RS1 & ASI { local tmp = RS1+segment(ASI); ex
:casa casa_ea,RS2,RD is op=0x3 & RD & op3=0x3c & casa_ea & RS2
{
local tmp:4=RD:4;
RD=zext(*:4 casa_ea);
if ((RS2 & 0xFFFFFFFF)!=RD) goto <end>;
*:4 casa_ea=tmp;
local tmp2:$(SIZE) = RS2;
local tmp_ea:$(SIZE) = casa_ea;
RD=zext(*:4 tmp_ea);
if ((tmp2 & 0xFFFFFFFF)!=RD) goto <end>;
*:4 tmp_ea=tmp;
<end>
}
:casxa casa_ea,RS2,RD is op=0x3 & RD & op3=0x3e & casa_ea & RS2
{
local tmp=RD;
RD=*:$(SIZE) casa_ea;
if (RS2!=RD) goto <end>;
*:$(SIZE) casa_ea=tmp;
local tmp2:$(SIZE) = RS2;
local tmp_ea:$(SIZE) = casa_ea;
RD=*:$(SIZE) tmp_ea;
if (tmp2!=RD) goto <end>;
*:$(SIZE) tmp_ea=tmp;
<end>
}
:impdef1 is op=0x2 & op3=0x36 unimpl
:impdef2 is op=0x2 & op3=0x37 unimpl
:ldstub ea,RD is op=0x3 & RD & op3=0xd & ea { RD = zext(*:1 ea); *:1 ea = 0xFF; }
:ldstuba ea_alt,RD is op=0x3 & RD & op3=0x1d & ea_alt { RD = zext(*:1 ea_alt); *:1 ea_alt = 0xFF; }
:ldstub ea,RD is op=0x3 & RD & op3=0xd & ea
{
local tmp_ea:$(SIZE) = ea;
RD = zext(*:1 tmp_ea);
*:1 tmp_ea = 0xFF;
}
:ldstuba ea_alt,RD is op=0x3 & RD & op3=0x1d & ea_alt
{
local tmp_ea:$(SIZE) = ea_alt;
RD = zext(*:1 tmp_ea);
*:1 tmp_ea = 0xFF;
}
:swap ea,RD is op=0x3 & RD & op3=0xF & ea { tmp:4=RD:4; RD = zext(*:4 ea); *:4 ea = tmp; }
:swapa ea_alt,RD is op=0x3 & RD & op3=0x1F & ea_alt { tmp:4=RD:4; RD = zext(*:4 ea_alt); *:4 ea_alt = tmp; }
:swap ea,RD is op=0x3 & RD & op3=0xF & ea { local tmp_ea:$(SIZE) = ea; tmp:4=RD:4; RD = zext(*:4 tmp_ea); *:4 tmp_ea = tmp; }
:swapa ea_alt,RD is op=0x3 & RD & op3=0x1F & ea_alt { local tmp_ea:$(SIZE) = ea_alt; tmp:4=RD:4; RD = zext(*:4 tmp_ea); *:4 tmp_ea = tmp; }
:taddcc RS1,regorimm,RD is op=2 & RD & op3=0x20 & RS1 & regorimm
{
taddflags(RS1,regorimm);
RD = RS1 + regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 + regorimm;
zeroflags(res);
RD = res;
}
:taddcctv RS1,regorimm,RD is op=2 & RD & op3=0x22 & RS1 & regorimm
{
taddflags(RS1,regorimm);
RD = RS1 + regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 + regorimm;
zeroflags(res);
RD = res;
}
:tsubcc RS1,regorimm,RD is op=2 & RD & op3=0x21 & RS1 & regorimm
{
tsubflags(RS1,regorimm);
RD = RS1 - regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 - regorimm;
zeroflags(res);
RD = res;
}
:tsubcctv RS1,regorimm,RD is op=2 & RD & op3=0x23 & RS1 & regorimm
{
tsubflags(RS1,regorimm);
RD = RS1 - regorimm;
zeroflags(RD);
local res:$(SIZE) = RS1 - regorimm;
zeroflags(res);
RD = res;
}
tcc: icc is cc1_4=0 & cc0_4=0 & icc { export icc; }
@ -1070,7 +1131,11 @@ TICC: "%xcc" is cc1_4=1 &cc0_4=0 { }
trap: RS1+RS2 is i=0 & RS1 & RS2 { local tmp = ((RS1 + RS2) & 0x7F); export tmp; }
trap: RS1+swtrap is i=1 & RS1 & swtrap { local tmp = ((RS1 + swtrap) & 0x7F); export tmp; }
:t^tcc TICC, trap is op=0x2 & op3=0x3a & tcc & TICC & trap { sw_trap(trap); }
:t^tcc TICC, trap is op=0x2 & op3=0x3a & tcc & TICC & trap
{
if (!tcc) goto inst_next;
sw_trap(trap);
}
membar_mask: is cmask & mmask { tmp:1 = (cmask << 4) | mmask; export tmp; }

View File

@ -2,30 +2,21 @@
<patternpairs totalbits="32" postbits="16">
<prepatterns>
<data>0x81f00000 </data> <!-- done -->
<data>0x81c7e008 0x........ </data> <!-- RET : delayslot filler -->
<data>0x81c7e008 0x........ 0x00000000 </data> <!-- RET : delayslot filler -->
<data>0x81c7e008 0x........ 0x00000000 0x00000000 </data> <!-- RET : delayslot filler -->
<data>0x81c7e008 0x........ 0x00000000 0x00000000 0x00000000 </data> <!-- RET : delayslot filler -->
<data>0x81c7e008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RET : delayslot filler -->
<data>0x81c7e008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RET : delayslot filler -->
<data>0x81c7e008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RET : delayslot filler -->
<data>0x81c7e008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RET : delayslot filler -->
<data>0x81c3e008 0x........ </data> <!-- RETL : delayslot filler -->
<data>0x81c3e008 0x........ 0x00000000 </data> <!-- RETL : delayslot filler -->
<data>0x81c3e008 0x........ 0x00000000 0x00000000 </data> <!-- RETL : delayslot filler -->
<data>0x81c3e008 0x........ 0x00000000 0x00000000 0x00000000 </data> <!-- RETL : delayslot filler -->
<data>0x81c3e008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RETL : delayslot filler -->
<data>0x81c3e008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RETL : delayslot filler -->
<data>0x81c3e008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RETL : delayslot filler -->
<data>0x81c3e008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RETL : delayslot filler -->
<data>0x81cfe008 0x........ </data> <!-- RETURN : delayslot filler -->
<data>0x81cfe008 0x........ 0x00000000 </data> <!-- RETURN : delayslot filler -->
<data>0x81cfe008 0x........ 0x00000000 0x00000000 </data> <!-- RETURN : delayslot filler -->
<data>0x81cfe008 0x........ 0x00000000 0x00000000 0x00000000 </data> <!-- RETURN : delayslot filler -->
<data>0x81cfe008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RETURN : delayslot filler -->
<data>0x81cfe008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RETURN : delayslot filler -->
<data>0x81cfe008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RETURN : delayslot filler -->
<data>0x81cfe008 0x........ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 </data> <!-- RETURN : delayslot filler -->
<data>0x81c7e008 0x........ </data> <!-- RET : delayslot -->
<data>0x81c7e008 0x........ 0000000. 0x000000 </data> <!-- RET : delayslot filler/nop -->
<data>0x81c3e008 0x........ </data> <!-- RETL : delayslot -->
<data>0x81c3e008 0x........ 0000000. 0x000000 </data> <!-- RETL : delayslot filler/nop -->
<data>0x81cfe008 0x........ </data> <!-- RETURN : delayslot -->
<data>0x81cfe008 0x........ 0000000. 0x000000 </data> <!-- RETURN : delayslot filler/nop -->
<data>0x10 101..... 0x.... 0x........ </data> <!-- BA -label : delayslot -->
<data>0x10 101..... 0x.... 0x........ 0000000. 0x000000 </data> <!-- BA -label : delayslot filler/nop -->
<data>0x30 101..... 0x.... </data> <!-- BA,A -label (no delayslot)-->
<data>0x30 101..... 0x.... 0000000. 0x000000 </data> <!-- BA,A -label (no delayslot): filler/nop -->
<data>01...... 0x...... 10.....1 11101... 0x.... </data> <!-- CALL label; RESTORE : filler/nop -->
<data>01...... 0x...... 10.....1 11101... 0x.... 0000000. 0x000000 </data> <!-- CALL label; RESTORE : filler/nop -->
<data>01...... 0x...... 0x9E 00010... 0x.... </data> <!-- CALL label; OR rs1,rs2,o7 : filler/nop -->
<data>01...... 0x...... 0x9E 00010... 0x.... 0000000. 0x000000 </data> <!-- CALL label; OR rs1,rs2,o7 : filler/nop -->
<data>0000000. 0x000000 0000000. 0x000000 </data> <!-- filler/nop -->
</prepatterns>
<postpatterns>
<data>10011101 11100011 10111... ........</data> <!-- save sp, xx, sp -->