@@ -270,16 +270,18 @@ class FloatRegisters {
270
270
ft11 = f31
271
271
};
272
272
273
- enum Kind : uint8_t { Double, NumTypes, Single };
273
+ enum Kind : uint8_t { Double, Single, NumTypes };
274
+
275
+ // (invalid << 7) | (kind << 5) | encoding
276
+ using Code = uint8_t ;
277
+ using Encoding = FPRegisterID;
274
278
275
- typedef FPRegisterID Code;
276
- typedef FPRegisterID Encoding;
277
279
union RegisterContent {
278
280
float s;
279
281
double d;
280
282
};
281
283
282
- static const char * GetName (uint32_t code) {
284
+ static const char * GetName (Code code) {
283
285
static const char * const Names[] = {
284
286
" ft0" , " ft1" , " ft2" , " ft3" , " ft4" , " ft5" , " ft6" , " ft7" ,
285
287
" fs0" , " fs2" , " fa0" , " fa1" , " fa2" , " fa3" , " fa4" , " fa5" ,
@@ -289,37 +291,51 @@ class FloatRegisters {
289
291
if (code >= Total) {
290
292
return " invalid" ;
291
293
}
292
- return Names[code];
294
+ return Names[code & 0x1f ];
293
295
}
294
296
295
297
static Code FromName (const char * name);
296
298
297
- typedef uint32_t SetType;
299
+ using SetType = uint64_t ;
298
300
299
- static const Code Invalid = invalid_reg;
300
- static const uint32_t Total = 32 ;
301
+ static const Code Invalid = Code(0b10000000 );
301
302
static const uint32_t TotalPhys = 32 ;
303
+ static const uint32_t Total = TotalPhys * NumTypes;
302
304
static const uint32_t Allocatable = 23 ;
303
- static const SetType AllPhysMask = 0xFFFFFFFF ;
304
- static const SetType AllMask = 0xFFFFFFFF ;
305
- static const SetType AllDoubleMask = AllMask;
306
- // Single values are stored as 64 bits values (NaN-boxed) when pushing them to
307
- // the stack, we do not require making distinctions between the 2 types, and
308
- // therefore the masks are overlapping.See The RISC-V Instruction Set Manual
309
- // for 14.2 NaN Boxing of Narrower Values.
310
- static const SetType AllSingleMask = AllMask;
305
+
306
+ static_assert (sizeof (SetType) * 8 >= Total,
307
+ " SetType should be large enough to enumerate all registers." );
308
+
309
+ // Magic values which are used to duplicate a mask of physical register for
310
+ // a specific type of register. A multiplication is used to copy and shift
311
+ // the bits of the physical register mask.
312
+ static const SetType SpreadSingle = SetType(1 )
313
+ << (uint32_t (Kind::Single) * TotalPhys);
314
+ static const SetType SpreadDouble = SetType(1 )
315
+ << (uint32_t (Kind::Double) * TotalPhys);
316
+ static const SetType Spread = SpreadSingle | SpreadDouble;
317
+
318
+ static const SetType AllPhysMask = ((SetType(1 ) << TotalPhys) - 1 );
319
+ static const SetType AllMask = AllPhysMask * Spread;
320
+ static const SetType AllSingleMask = AllPhysMask * SpreadSingle;
321
+ static const SetType AllDoubleMask = AllPhysMask * SpreadDouble;
322
+ static const SetType NoneMask = SetType(0 );
323
+
311
324
static const SetType NonVolatileMask =
312
325
SetType ((1 << FloatRegisters::fs0) | (1 << FloatRegisters::fs1) |
313
326
(1 << FloatRegisters::fs2) | (1 << FloatRegisters::fs3) |
314
327
(1 << FloatRegisters::fs4) | (1 << FloatRegisters::fs5) |
315
328
(1 << FloatRegisters::fs6) | (1 << FloatRegisters::fs7) |
316
329
(1 << FloatRegisters::fs8) | (1 << FloatRegisters::fs9) |
317
- (1 << FloatRegisters::fs10) | (1 << FloatRegisters::fs11));
330
+ (1 << FloatRegisters::fs10) | (1 << FloatRegisters::fs11)) *
331
+ Spread;
318
332
static const SetType VolatileMask = AllMask & ~NonVolatileMask;
319
333
320
334
// fs11/ft10 is the scratch register.
321
335
static const SetType NonAllocatableMask =
322
- SetType ((1 << FloatRegisters::fs11) | (1 << FloatRegisters::ft10));
336
+ ((SetType(1 ) << FloatRegisters::fs11) |
337
+ (SetType(1 ) << FloatRegisters::ft10)) *
338
+ Spread;
323
339
324
340
static const SetType AllocatableMask = AllMask & ~NonAllocatableMask;
325
341
};
@@ -329,29 +345,32 @@ class TypedRegisterSet;
329
345
330
346
struct FloatRegister {
331
347
public:
332
- typedef FloatRegisters Codes;
333
- typedef Codes::Code Code;
334
- typedef Codes::Encoding Encoding;
335
- typedef Codes::SetType SetType;
348
+ using Codes = FloatRegisters ;
349
+ using Code = Codes::Code;
350
+ using Encoding = Codes::Encoding;
351
+ using SetType = Codes::SetType;
336
352
337
353
static uint32_t SetSize (SetType x) {
338
- static_assert (sizeof (SetType) == 4 , " SetType must be 32 bits" );
354
+ static_assert (sizeof (SetType) == 8 , " SetType must be 64 bits" );
355
+ x |= x >> FloatRegisters::TotalPhys;
339
356
x &= FloatRegisters::AllPhysMask;
340
357
return mozilla::CountPopulation32 (x);
341
358
}
342
359
343
360
static uint32_t FirstBit (SetType x) {
344
- static_assert (sizeof (SetType) == 4 , " SetType" );
361
+ static_assert (sizeof (SetType) == 8 , " SetType must be 64 bits " );
345
362
return mozilla::CountTrailingZeroes64 (x);
346
363
}
347
364
static uint32_t LastBit (SetType x) {
348
- static_assert (sizeof (SetType) == 4 , " SetType" );
349
- return 31 - mozilla::CountLeadingZeroes64 (x);
365
+ static_assert (sizeof (SetType) == 8 , " SetType must be 64 bits " );
366
+ return 63 - mozilla::CountLeadingZeroes64 (x);
350
367
}
351
368
352
- static FloatRegister FromCode (uint32_t i) {
353
- uint32_t code = i & 0x1f ;
354
- return FloatRegister (Code (code));
369
+ static FloatRegister FromCode (Code code) {
370
+ MOZ_ASSERT (code < Codes::Total);
371
+ const Encoding encoding = Encoding (code & 0x1f );
372
+ const Kind kind = Kind ((code >> 5 ) & 0x3 );
373
+ return FloatRegister (encoding, kind);
355
374
}
356
375
bool isSimd128 () const { return false ; }
357
376
bool isInvalid () const { return invalid_; }
@@ -366,10 +385,11 @@ struct FloatRegister {
366
385
FloatRegister asSimd128 () const { MOZ_CRASH (); }
367
386
constexpr Code code () const {
368
387
MOZ_ASSERT (!invalid_);
369
- return encoding_;
388
+ return Code ((invalid_ << 7 ) | ((static_cast <uint8_t >(kind_) & 0x3 ) << 5 ) |
389
+ (static_cast <uint8_t >(encoding_) & 0x1f ));
370
390
}
371
- Encoding encoding () const { return encoding_; }
372
- const char * name () const { return FloatRegisters::GetName (code ()); }
391
+ constexpr Encoding encoding () const { return encoding_; }
392
+ const char * name () const { return FloatRegisters::GetName (encoding ()); }
373
393
bool volatile_ () const {
374
394
MOZ_ASSERT (!invalid_);
375
395
return !!((SetType (1 ) << code ()) & FloatRegisters::VolatileMask);
@@ -379,10 +399,12 @@ struct FloatRegister {
379
399
bool aliases (FloatRegister other) const {
380
400
return other.encoding_ == encoding_;
381
401
}
382
- uint32_t numAliased () const { return 1 ; }
402
+ uint32_t numAliased () const { return FloatRegisters::NumTypes ; }
383
403
FloatRegister aliased (uint32_t aliasIdx) const {
384
- MOZ_ASSERT (aliasIdx == 0 );
385
- return *this ;
404
+ MOZ_ASSERT (!invalid_);
405
+ MOZ_ASSERT (aliasIdx < numAliased ());
406
+ return FloatRegister (Encoding (encoding_),
407
+ Kind ((aliasIdx + kind_) % numAliased ()));
386
408
}
387
409
// Ensure that two floating point registers' types are equivalent.
388
410
bool equiv (FloatRegister other) const {
@@ -402,7 +424,9 @@ struct FloatRegister {
402
424
MOZ_ASSERT (aliasIdx < numAliased ());
403
425
return aliased (aliasIdx);
404
426
}
405
- SetType alignedOrDominatedAliasedSet () const { return SetType (1 ) << code (); }
427
+ SetType alignedOrDominatedAliasedSet () const {
428
+ return Codes::Spread << encoding_;
429
+ }
406
430
static constexpr RegTypeName DefaultType = RegTypeName::Float64;
407
431
408
432
template <RegTypeName Name = DefaultType>
@@ -427,7 +451,7 @@ struct FloatRegister {
427
451
# error "Needs more careful logic if SIMD is enabled"
428
452
#endif
429
453
430
- return code () * sizeof (double );
454
+ return encoding () * sizeof (double );
431
455
}
432
456
static Code FromName (const char * name);
433
457
@@ -436,7 +460,7 @@ struct FloatRegister {
436
460
static uint32_t GetPushSizeInBytes (const TypedRegisterSet<FloatRegister>& s);
437
461
438
462
private:
439
- typedef Codes::Kind Kind;
463
+ using Kind = Codes::Kind;
440
464
// These fields only hold valid values: an invalid register is always
441
465
// represented as a valid encoding and kind with the invalid_ bit set.
442
466
Encoding encoding_; // 32 encodings
@@ -461,16 +485,13 @@ struct FloatRegister {
461
485
462
486
bool isSingle () const {
463
487
MOZ_ASSERT (!invalid_);
464
- // On riscv64 arch, float register and double register using the same
465
- // register file.
466
- return kind_ == FloatRegisters::Single || kind_ == FloatRegisters::Double;
488
+ return kind_ == FloatRegisters::Single;
467
489
}
490
+
468
491
bool isDouble () const {
469
492
MOZ_ASSERT (!invalid_);
470
493
return kind_ == FloatRegisters::Double;
471
494
}
472
-
473
- Encoding code () { return encoding_; }
474
495
};
475
496
476
497
template <>
0 commit comments