assert(isValidImmCondFlags(emitGetInsSC(id)));
break;
+ case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
+ assert(isValidGeneralDatasize(id->idOpSize()));
+ assert(isVectorRegister(id->idReg1()));
+ assert(isVectorRegister(id->idReg2()));
+ break;
+
case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
assert(isValidGeneralDatasize(id->idOpSize()));
assert(isIntegerRegister(id->idReg1())); // SP
case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
+ case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
assert(isValidVectorDatasize(id->idOpSize()));
assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
assert(isVectorRegister(id->idReg1()));
assert(isVectorRegister(id->idReg3()));
break;
+ case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm
+ assert(isValidVectorDatasize(id->idOpSize()));
+ assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
+ assert(isVectorRegister(id->idReg1()));
+ assert(isVectorRegister(id->idReg2()));
+ assert(isVectorRegister(id->idReg3()));
+ break;
+
case IF_DV_4A: // DR_4A .........X.mmmmm .aaaaannnnnddddd Rd Rn Rm Ra (scalar)
assert(isValidGeneralDatasize(id->idOpSize()));
assert(isVectorRegister(id->idReg1()));
case IF_DR_3C: // DR_3C X..........mmmmm xxxsssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
+ case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - Vd both source and dest
case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
return true;
- case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
- case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
- case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
- case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
- case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
- case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
- case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
- case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
- case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
- case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
+ case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
+ case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
+ case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
+ case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
+ case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
+ case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
+ case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
+ case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
+ case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
+ case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
+ case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1) - Vd both source and
+ // destination
+
case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
case IF_DR_2G:
case IF_DR_2H:
case IF_DR_2I:
+ case IF_DR_2J:
case IF_DR_3A:
case IF_DR_3B:
case IF_DR_3C:
case IF_DV_2M:
case IF_DV_2N:
case IF_DV_2O:
+ case IF_DV_2P:
case IF_DV_3A:
case IF_DV_3AI:
case IF_DV_3B:
case IF_DV_3D:
case IF_DV_3DI:
case IF_DV_3E:
+ case IF_DV_3F:
case IF_DV_4A:
case IF_SN_0A:
case IF_SI_0A:
case INS_not:
assert(isVectorRegister(reg1));
assert(isVectorRegister(reg2));
- // for 'NOT' we can construct the arrangement: 8B or 16B
- if ((ins == INS_not) && insOptsNone(opt))
+ if (ins == INS_not)
{
assert(isValidVectorDatasize(size));
- elemsize = EA_1BYTE;
- opt = optMakeArrangement(size, elemsize);
+ // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
+ opt = optMakeArrangement(size, EA_1BYTE);
}
if (insOptsNone(opt))
{
assert(isValidVectorDatasize(size));
assert(isValidArrangement(size, opt));
elemsize = optGetElemsize(opt);
- if (ins == INS_not)
- {
- assert(elemsize == EA_1BYTE);
- }
- fmt = IF_DV_2M;
+ fmt = IF_DV_2M;
}
break;
if (isVectorRegister(reg1))
{
assert(isVectorRegister(reg2));
- // for 'mvn' we can construct the arrangement: 8B or 16b
- if ((ins == INS_mvn) && insOptsNone(opt))
+ if (ins == INS_mvn)
{
assert(isValidVectorDatasize(size));
- elemsize = EA_1BYTE;
- opt = optMakeArrangement(size, elemsize);
+ // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
+ opt = optMakeArrangement(size, EA_1BYTE);
}
if (insOptsNone(opt))
{
assert(isValidVectorDatasize(size));
assert(isValidArrangement(size, opt));
elemsize = optGetElemsize(opt);
- if (ins == INS_mvn)
- {
- assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
- }
- fmt = IF_DV_2M;
+ fmt = IF_DV_2M;
}
break;
}
assert(isValidVectorDatasize(size));
assert(isValidArrangement(size, opt));
elemsize = optGetElemsize(opt);
- assert(size != EA_16BYTE); // Narrowing must start with wide format
- assert(elemsize != EA_1BYTE); // Narrowing must start with more than one byte src
+ // size is determined by instruction
+ if (ins == INS_xtn)
+ {
+ assert(size == EA_8BYTE);
+ }
+ else // ins == INS_xtn2
+ {
+ assert(size == EA_16BYTE);
+ }
+ assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
fmt = IF_DV_2M;
break;
case INS_fcvtl:
case INS_fcvtl2:
- assert(isVectorRegister(reg1));
- assert(isVectorRegister(reg2));
- assert(isValidVectorDatasize(size));
- assert(isValidArrangement(size, opt));
- elemsize = optGetElemsize(opt);
- assert(elemsize == EA_4BYTE); // Widening from Float to Double, opt should correspond to src layout
- fmt = IF_DV_2G;
- break;
-
case INS_fcvtn:
case INS_fcvtn2:
assert(isVectorRegister(reg1));
assert(isVectorRegister(reg2));
assert(isValidVectorDatasize(size));
- assert(isValidArrangement(size, opt));
- elemsize = optGetElemsize(opt);
- assert(elemsize == EA_8BYTE); // Narrowing from Double to Float, opt should correspond to src layout
+ assert(insOptsNone(opt));
+ assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
fmt = IF_DV_2G;
break;
fmt = IF_DV_2J;
break;
+ case INS_cmeq:
+ case INS_cmge:
+ case INS_cmgt:
+ case INS_cmle:
+ case INS_cmlt:
+ assert(isVectorRegister(reg1));
+ assert(isVectorRegister(reg2));
+
+ if (isValidVectorDatasize(size))
+ {
+ // Vector operation
+ assert(insOptsAnyArrangement(opt));
+ assert(isValidArrangement(size, opt));
+ elemsize = optGetElemsize(opt);
+ fmt = IF_DV_2M;
+ }
+ else
+ {
+ NYI("Untested");
+ // Scalar operation
+ assert(size == EA_8BYTE); // Only Double supported
+ fmt = IF_DV_2L;
+ }
+ break;
+
+ case INS_fcmeq:
+ case INS_fcmge:
+ case INS_fcmgt:
+ case INS_fcmle:
+ case INS_fcmlt:
+ assert(isVectorRegister(reg1));
+ assert(isVectorRegister(reg2));
+
+ if (isValidVectorDatasize(size))
+ {
+ // Vector operation
+ assert(insOptsAnyArrangement(opt));
+ assert(isValidArrangement(size, opt));
+ elemsize = optGetElemsize(opt);
+ assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
+ assert(opt != INS_OPTS_1D); // Reserved encoding
+ fmt = IF_DV_2A;
+ }
+ else
+ {
+ NYI("Untested");
+ // Scalar operation
+ assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
+ fmt = IF_DV_2G;
+ }
+ break;
+ case INS_aesd:
+ case INS_aese:
+ case INS_aesmc:
+ case INS_aesimc:
+ assert(isVectorRegister(reg1));
+ assert(isVectorRegister(reg2));
+ assert(isValidVectorDatasize(size));
+ elemsize = optGetElemsize(opt);
+ assert(elemsize == EA_1BYTE);
+ fmt = IF_DV_2P;
+ break;
+
+ case INS_sha1h:
+ assert(insOptsNone(opt));
+ assert(isVectorRegister(reg1));
+ assert(isVectorRegister(reg2));
+ fmt = IF_DR_2J;
+ break;
+
+ case INS_sha256su0:
+ case INS_sha1su1:
+ assert(isVectorRegister(reg1));
+ assert(isVectorRegister(reg2));
+ assert(isValidVectorDatasize(size));
+ elemsize = optGetElemsize(opt);
+ assert(elemsize == EA_4BYTE);
+ fmt = IF_DV_2P;
+ break;
+
default:
unreached();
break;
fmt = IF_LS_3D;
break;
+ case INS_sha256h:
+ case INS_sha256h2:
+ case INS_sha256su1:
+ case INS_sha1su0:
+ case INS_sha1c:
+ case INS_sha1p:
+ case INS_sha1m:
+ assert(isValidVectorDatasize(size));
+ assert(isVectorRegister(reg1));
+ assert(isVectorRegister(reg2));
+ assert(isVectorRegister(reg3));
+ if (opt == INS_OPTS_NONE)
+ {
+ elemsize = EA_4BYTE;
+ opt = optMakeArrangement(size, elemsize);
+ }
+ assert(isValidArrangement(size, opt));
+ fmt = IF_DV_3F;
+ break;
+
default:
unreached();
break;
else
{
regNumber rsvdReg = codeGen->rsGetRsvdReg();
- codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
+ codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
}
}
if (useRegForImm)
{
regNumber rsvdReg = codeGen->rsGetRsvdReg();
- codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
+ codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
fmt = IF_LS_3A;
}
}
assert(isGeneralRegisterOrZR(reg2));
assert(offs >= 0);
- emitAttr size = EA_SIZE(attr1);
insFormat fmt = IF_LS_3B;
int disp = 0;
const unsigned scale = 3;
if (useRegForAdr)
{
regNumber rsvd = codeGen->rsGetRsvdReg();
- emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm);
+ emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
reg3 = rsvd;
imm = 0;
}
// The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
// It is instead implicit when idSetIsLclVar() is set, with this encoding format.
regNumber rsvdReg = codeGen->rsGetRsvdReg();
- codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
+ codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
fmt = IF_LS_3A;
}
assert(isGeneralRegisterOrZR(reg2));
assert(offs >= 0);
- emitAttr size = EA_SIZE(attr1);
insFormat fmt = IF_LS_3B;
int disp = 0;
const unsigned scale = 3;
if (useRegForAdr)
{
regNumber rsvd = codeGen->rsGetRsvdReg();
- emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm);
+ emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
reg3 = rsvd;
imm = 0;
}
{
savedSet |= RBM_PROFILER_RET_SCRATCH;
}
+
+#ifdef DEBUG
+ if (emitComp->verbose)
+ {
+ printf("NOGC Call: savedSet=");
+ printRegMaskInt(savedSet);
+ emitDispRegSet(savedSet);
+ printf("\n");
+ }
+#endif
}
else
{
#endif
assert(argSize % REGSIZE_BYTES == 0);
- argCnt = (int)(argSize / (int)sizeof(void*));
+ argCnt = (int)(argSize / (int)REGSIZE_BYTES);
/* Managed RetVal: emit sequence point for the call */
if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
}
break;
+ case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
+ code = emitInsCode(ins, fmt);
+ code |= insEncodeReg_Vd(id->idReg1()); // ddddd
+ code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
+ dst += emitOutput_Instr(dst, code);
+ break;
+
case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
code = emitInsCode(ins, fmt);
code |= insEncodeDatasize(id->idOpSize()); // X
dst += emitOutput_Instr(dst, code);
break;
+ case IF_DV_2P: // DV_2P ............... ......nnnnnddddd Vd Vn (aes*, sha1su1)
+ elemsize = optGetElemsize(id->idInsOpt());
+ code = emitInsCode(ins, fmt);
+ code |= insEncodeReg_Vd(id->idReg1()); // ddddd
+ code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
+ dst += emitOutput_Instr(dst, code);
+ break;
+
case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
code = emitInsCode(ins, fmt);
elemsize = optGetElemsize(id->idInsOpt());
break;
case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
+ case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - source dest regs overlap
code = emitInsCode(ins, fmt);
code |= insEncodeReg_Vd(id->idReg1()); // ddddd
code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
{
int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
- unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), sizeof(size_t));
+ unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
bool FPbased;
int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
if (id->idGCref() != GCT_NONE)
}
if (emitInsWritesToLclVarStackLocPair(id))
{
- unsigned ofs2 = ofs + sizeof(size_t);
+ unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
if (id->idGCrefReg2() != GCT_NONE)
{
emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
printf("#");
}
- // Munge any pointers if we want diff-able disassembly
+ // Munge any pointers if we want diff-able disassembly.
+ // Since some may be emitted as partial words, print as diffable anything that has
+ // significant bits beyond the lowest 8-bits.
if (emitComp->opts.disDiffable)
{
- ssize_t top44bits = (imm >> 20);
- if ((top44bits != 0) && (top44bits != -1))
+ ssize_t top56bits = (imm >> 8);
+ if ((top56bits != 0) && (top56bits != -1))
imm = 0xD1FFAB1E;
}
break;
case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
+ case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn
emitDispReg(id->idReg1(), size, true);
emitDispReg(id->idReg2(), size, false);
break;
case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
+ case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
break;
emitDispReg(id->idReg3(), size, false);
break;
+ case IF_DV_3F: // DV_3F ..........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
+ if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
+ {
+ // Qd, Sn, Vm (vector)
+ emitDispReg(id->idReg1(), size, true);
+ emitDispReg(id->idReg2(), EA_4BYTE, true);
+ emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
+ }
+ else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
+ {
+ // Qd Qn Vm (vector)
+ emitDispReg(id->idReg1(), size, true);
+ emitDispReg(id->idReg2(), size, true);
+ emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
+ }
+ else // INS_sha1su0, INS_sha256su1
+ {
+ // Vd, Vn, Vm (vector)
+ emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
+ emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
+ emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
+ }
+ break;
+
case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
emitDispReg(id->idReg1(), size, true);
emitDispReg(id->idReg2(), size, true);
}
}
-// Generates an integer data section constant and returns a field handle representing
-// the data offset to access the constant via a load instruction.
-// This is called during ngen for any relocatable constants
-//
-CORINFO_FIELD_HANDLE emitter::emitLiteralConst(ssize_t cnsValIn, emitAttr attr /*=EA_8BYTE*/)
-{
- ssize_t constValue = cnsValIn;
- void* cnsAddr = &constValue;
- bool dblAlign;
-
- if (attr == EA_4BYTE)
- {
- dblAlign = false;
- }
- else
- {
- assert(attr == EA_8BYTE);
- dblAlign = true;
- }
-
- // Access to inline data is 'abstracted' by a special type of static member
- // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
- // to constant data, not a real static field.
-
- UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
- UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
- return emitComp->eeFindJitDataOffs(cnum);
-}
-
-// Generates a float or double data section constant and returns field handle representing
-// the data offset to access the constant. This is called by emitInsBinary() in case
-// of contained float of double constants.
-CORINFO_FIELD_HANDLE emitter::emitFltOrDblConst(GenTreeDblCon* tree, emitAttr attr /*=EA_UNKNOWN*/)
-{
- if (attr == EA_UNKNOWN)
- {
- attr = emitTypeSize(tree->TypeGet());
- }
- else
- {
- assert(emitTypeSize(tree->TypeGet()) == attr);
- }
-
- double constValue = tree->gtDblCon.gtDconVal;
- void* cnsAddr;
- float f;
- bool dblAlign;
-
- if (attr == EA_4BYTE)
- {
- f = forceCastToFloat(constValue);
- cnsAddr = &f;
- dblAlign = false;
- }
- else
- {
- cnsAddr = &constValue;
- dblAlign = true;
- }
-
- // Access to inline data is 'abstracted' by a special type of static member
- // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
- // to constant data, not a real static field.
-
- UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
- UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
- return emitComp->eeFindJitDataOffs(cnum);
-}
-
// The callee must call genConsumeReg() for any non-contained srcs
// and genProduceReg() for any non-contained dsts.