@@ -17311,13 +17311,14 @@ void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
17311
17311
*
17312
17312
* Add an instruction referencing a register and a stack-based local variable.
17313
17313
*/
17314
- void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
17314
+ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs, insScalableOpts sopt /* = INS_SCALABLE_OPTS_NONE */ )
17315
17315
{
17316
17316
emitAttr size = EA_SIZE(attr);
17317
17317
insFormat fmt = IF_NONE;
17318
17318
int disp = 0;
17319
17319
unsigned scale = 0;
17320
17320
bool isLdrStr = false;
17321
+ bool isScalable = false;
17321
17322
17322
17323
assert(offs >= 0);
17323
17324
@@ -17353,6 +17354,31 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
17353
17354
scale = 0;
17354
17355
break;
17355
17356
17357
+ case INS_sve_ldr:
17358
+ assert(isVectorRegister(reg1) || isPredicateRegister(reg1));
17359
+ isScalable = true;
17360
+
17361
+ // TODO-SVE: This should probably be set earlier in the caller
17362
+ size = EA_SCALABLE;
17363
+ attr = size;
17364
+
17365
+ // TODO-SVE: Use register number instead of enum
17366
+ if (sopt == INS_SCALABLE_OPTS_UNPREDICATED)
17367
+ {
17368
+ fmt = IF_SVE_IE_2A;
17369
+ // TODO-SVE: Don't assume 128bit vectors
17370
+ scale = NaturalScale_helper(EA_16BYTE);
17371
+ }
17372
+ else
17373
+ {
17374
+ assert(insScalableOptsNone(sopt));
17375
+ fmt = IF_SVE_ID_2A;
17376
+ // TODO-SVE: Don't assume 128bit vectors
17377
+ // Predicate size is vector length / 8
17378
+ scale = NaturalScale_helper(EA_2BYTE);
17379
+ }
17380
+ break;
17381
+
17356
17382
default:
17357
17383
NYI("emitIns_R_S"); // FP locals?
17358
17384
return;
@@ -17363,6 +17389,7 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
17363
17389
ssize_t imm;
17364
17390
int base;
17365
17391
bool FPbased;
17392
+ insFormat scalarfmt = fmt;
17366
17393
17367
17394
base = emitComp->lvaFrameAddress(varx, &FPbased);
17368
17395
disp = base + offs;
@@ -17387,13 +17414,13 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
17387
17414
17388
17415
if (imm <= 0x0fff)
17389
17416
{
17390
- fmt = IF_DI_2A; // add reg1,reg2,#disp
17417
+ scalarfmt = IF_DI_2A; // add reg1,reg2,#disp
17391
17418
}
17392
17419
else
17393
17420
{
17394
17421
regNumber rsvdReg = codeGen->rsGetRsvdReg();
17395
17422
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
17396
- fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
17423
+ scalarfmt = IF_DR_3A; // add reg1,reg2,rsvdReg
17397
17424
}
17398
17425
}
17399
17426
else
@@ -17402,13 +17429,13 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
17402
17429
imm = disp;
17403
17430
if (imm == 0)
17404
17431
{
17405
- fmt = IF_LS_2A;
17432
+ scalarfmt = IF_LS_2A;
17406
17433
}
17407
17434
else if ((imm < 0) || ((imm & mask) != 0))
17408
17435
{
17409
17436
if ((imm >= -256) && (imm <= 255))
17410
17437
{
17411
- fmt = IF_LS_2C;
17438
+ scalarfmt = IF_LS_2C;
17412
17439
}
17413
17440
else
17414
17441
{
@@ -17417,11 +17444,13 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
17417
17444
}
17418
17445
else if (imm > 0)
17419
17446
{
17447
+ // TODO: We should be able to scale values <0 for all variants.
17448
+
17420
17449
if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
17421
17450
{
17422
17451
imm >>= scale; // The immediate is scaled by the size of the ld/st
17423
17452
17424
- fmt = IF_LS_2B;
17453
+ scalarfmt = IF_LS_2B;
17425
17454
}
17426
17455
else
17427
17456
{
@@ -17433,10 +17462,15 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
17433
17462
{
17434
17463
regNumber rsvdReg = codeGen->rsGetRsvdReg();
17435
17464
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
17436
- fmt = IF_LS_3A;
17465
+ scalarfmt = IF_LS_3A;
17437
17466
}
17438
17467
}
17439
17468
17469
+ // Set the format based on the immediate encoding
17470
+ if (!isScalable)
17471
+ {
17472
+ fmt = scalarfmt;
17473
+ }
17440
17474
assert(fmt != IF_NONE);
17441
17475
17442
17476
// Try to optimize a load/store with an alternative instruction.
@@ -17564,15 +17598,16 @@ void emitter::emitIns_R_R_S_S(
17564
17598
*
17565
17599
* Add an instruction referencing a stack-based local variable and a register
17566
17600
*/
17567
- void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
17601
+ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs, insScalableOpts sopt /* = INS_SCALABLE_OPTS_NONE */ )
17568
17602
{
17569
17603
assert(offs >= 0);
17570
- emitAttr size = EA_SIZE(attr);
17571
- insFormat fmt = IF_NONE;
17572
- int disp = 0;
17573
- unsigned scale = 0;
17574
- bool isVectorStore = false;
17575
- bool isStr = false;
17604
+ emitAttr size = EA_SIZE(attr);
17605
+ insFormat fmt = IF_NONE;
17606
+ int disp = 0;
17607
+ unsigned scale = 0;
17608
+ bool isVectorStore = false;
17609
+ bool isStr = false;
17610
+ bool isScalable = false;
17576
17611
17577
17612
// TODO-ARM64-CQ: use unscaled loads?
17578
17613
/* Figure out the encoding format of the instruction */
@@ -17604,6 +17639,31 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va
17604
17639
isStr = true;
17605
17640
break;
17606
17641
17642
+ case INS_sve_str:
17643
+ assert(isVectorRegister(reg1) || isPredicateRegister(reg1));
17644
+ isScalable = true;
17645
+
17646
+ // TODO-SVE: This should probably be set earlier in the caller
17647
+ size = EA_SCALABLE;
17648
+ attr = size;
17649
+
17650
+ // TODO-SVE: Use register number instead of enum
17651
+ if (sopt == INS_SCALABLE_OPTS_UNPREDICATED)
17652
+ {
17653
+ fmt = IF_SVE_JH_2A;
17654
+ // TODO-SVE: Don't assume 128bit vectors
17655
+ scale = NaturalScale_helper(EA_16BYTE);
17656
+ }
17657
+ else
17658
+ {
17659
+ assert(insScalableOptsNone(sopt));
17660
+ fmt = IF_SVE_JG_2A;
17661
+ // TODO-SVE: Don't assume 128bit vectors
17662
+ // Predicate size is vector length / 8
17663
+ scale = NaturalScale_helper(EA_2BYTE);
17664
+ }
17665
+ break;
17666
+
17607
17667
default:
17608
17668
NYI("emitIns_S_R"); // FP locals?
17609
17669
return;
@@ -17617,7 +17677,7 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va
17617
17677
base = emitComp->lvaFrameAddress(varx, &FPbased);
17618
17678
disp = base + offs;
17619
17679
assert(scale >= 0);
17620
- if (isVectorStore)
17680
+ if (isVectorStore || isScalable )
17621
17681
{
17622
17682
assert(scale <= 4);
17623
17683
}
@@ -17633,15 +17693,16 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va
17633
17693
bool useRegForImm = false;
17634
17694
ssize_t imm = disp;
17635
17695
ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
17696
+ insFormat scalarfmt = fmt;
17636
17697
if (imm == 0)
17637
17698
{
17638
- fmt = IF_LS_2A;
17699
+ scalarfmt = IF_LS_2A;
17639
17700
}
17640
17701
else if ((imm < 0) || ((imm & mask) != 0))
17641
17702
{
17642
- if ((imm >= -256) && (imm <= 255 ))
17703
+ if (isValidSimm9 (imm))
17643
17704
{
17644
- fmt = IF_LS_2C;
17705
+ scalarfmt = IF_LS_2C;
17645
17706
}
17646
17707
else
17647
17708
{
@@ -17650,11 +17711,12 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va
17650
17711
}
17651
17712
else if (imm > 0)
17652
17713
{
17714
+ // TODO: We should be able to scale values <0 for all variants.
17715
+
17653
17716
if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
17654
17717
{
17655
17718
imm >>= scale; // The immediate is scaled by the size of the ld/st
17656
-
17657
- fmt = IF_LS_2B;
17719
+ scalarfmt = IF_LS_2B;
17658
17720
}
17659
17721
else
17660
17722
{
@@ -17668,9 +17730,14 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va
17668
17730
// It is instead implicit when idSetIsLclVar() is set, with this encoding format.
17669
17731
regNumber rsvdReg = codeGen->rsGetRsvdReg();
17670
17732
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
17671
- fmt = IF_LS_3A;
17733
+ scalarfmt = IF_LS_3A;
17672
17734
}
17673
17735
17736
+ // Set the format based on the immediate encoding
17737
+ if (!isScalable)
17738
+ {
17739
+ fmt = scalarfmt;
17740
+ }
17674
17741
assert(fmt != IF_NONE);
17675
17742
17676
17743
// Try to optimize a store with an alternative instruction.
0 commit comments