mirror of
https://github.com/golang/go
synced 2024-11-18 17:54:57 -07:00
cmd/internal/obj/riscv: clean up immediate checking
Change immIFits to return an error in the case that it does not fit. This allows for deduplication and consistency of error messages. Additionally, since we've already calculated the min and max values, we can easily include these in the message. Also provide and use immEven, for the same reasons. Change-Id: Ie680558744f3e9bc19d6913c4144ce9ddbd0429c Reviewed-on: https://go-review.googlesource.com/c/go/+/523458 Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Mark Ryan <markdryan@rivosinc.com> Run-TryBot: M Zhuo <mzh@golangcn.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: M Zhuo <mzh@golangcn.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
561a507905
commit
38b2c06e14
@ -942,12 +942,12 @@ func signExtend(val int64, bit uint) int64 {
|
||||
// result. For example, high may be used in LUI and low in a following ADDI to
|
||||
// generate a full 32-bit constant.
|
||||
func Split32BitImmediate(imm int64) (low, high int64, err error) {
|
||||
if !immIFits(imm, 32) {
|
||||
return 0, 0, fmt.Errorf("immediate does not fit in 32 bits: %d", imm)
|
||||
if err := immIFits(imm, 32); err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
// Nothing special needs to be done if the immediate fits in 12 bits.
|
||||
if immIFits(imm, 12) {
|
||||
if err := immIFits(imm, 12); err == nil {
|
||||
return imm, 0, nil
|
||||
}
|
||||
|
||||
@ -1007,26 +1007,41 @@ func regFAddr(a obj.Addr) uint32 {
|
||||
return regAddr(a, REG_F0, REG_F31)
|
||||
}
|
||||
|
||||
// immIFits reports whether immediate value x fits in nbits bits
|
||||
// as a signed integer.
|
||||
func immIFits(x int64, nbits uint) bool {
|
||||
// immEven checks that the immediate is a multiple of two. If it
|
||||
// is not, an error is returned.
|
||||
func immEven(x int64) error {
|
||||
if x&1 != 0 {
|
||||
return fmt.Errorf("immediate %#x is not a multiple of two", x)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// immIFits checks whether the immediate value x fits in nbits bits
|
||||
// as a signed integer. If it does not, an error is returned.
|
||||
func immIFits(x int64, nbits uint) error {
|
||||
nbits--
|
||||
var min int64 = -1 << nbits
|
||||
var max int64 = 1<<nbits - 1
|
||||
return min <= x && x <= max
|
||||
min := int64(-1) << nbits
|
||||
max := int64(1)<<nbits - 1
|
||||
if x < min || x > max {
|
||||
if nbits <= 16 {
|
||||
return fmt.Errorf("signed immediate %d must be in range [%d, %d] (%d bits)", x, min, max, nbits)
|
||||
}
|
||||
return fmt.Errorf("signed immediate %#x must be in range [%#x, %#x] (%d bits)", x, min, max, nbits)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// immI extracts the signed integer of the specified size from an immediate.
|
||||
func immI(as obj.As, imm int64, nbits uint) uint32 {
|
||||
if !immIFits(imm, nbits) {
|
||||
panic(fmt.Sprintf("%v: signed immediate %d cannot fit in %d bits", as, imm, nbits))
|
||||
if err := immIFits(imm, nbits); err != nil {
|
||||
panic(fmt.Sprintf("%v: %v", as, err))
|
||||
}
|
||||
return uint32(imm)
|
||||
}
|
||||
|
||||
func wantImmI(ctxt *obj.Link, as obj.As, imm int64, nbits uint) {
|
||||
if !immIFits(imm, nbits) {
|
||||
ctxt.Diag("%v: signed immediate %d cannot be larger than %d bits", as, imm, nbits)
|
||||
if err := immIFits(imm, nbits); err != nil {
|
||||
ctxt.Diag("%v: %v", as, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1058,8 +1073,8 @@ func wantFloatReg(ctxt *obj.Link, as obj.As, pos string, r uint32) {
|
||||
|
||||
// wantEvenOffset checks that the offset is a multiple of two.
|
||||
func wantEvenOffset(ctxt *obj.Link, as obj.As, offset int64) {
|
||||
if offset%1 != 0 {
|
||||
ctxt.Diag("%v: jump offset %d must be a multiple of two", as, offset)
|
||||
if err := immEven(offset); err != nil {
|
||||
ctxt.Diag("%v: %v", as, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1368,62 +1383,62 @@ func encodeRawIns(ins *instruction) uint32 {
|
||||
}
|
||||
|
||||
func EncodeBImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 13) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 13 bits", imm)
|
||||
if err := immIFits(imm, 13); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if imm&1 != 0 {
|
||||
return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm)
|
||||
if err := immEven(imm); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(encodeBImmediate(uint32(imm))), nil
|
||||
}
|
||||
|
||||
func EncodeCBImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 9) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 9 bits", imm)
|
||||
if err := immIFits(imm, 9); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if imm&1 != 0 {
|
||||
return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm)
|
||||
if err := immEven(imm); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(encodeCBImmediate(uint32(imm))), nil
|
||||
}
|
||||
|
||||
func EncodeCJImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 12) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
|
||||
if err := immIFits(imm, 12); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if imm&1 != 0 {
|
||||
return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm)
|
||||
if err := immEven(imm); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(encodeCJImmediate(uint32(imm))), nil
|
||||
}
|
||||
|
||||
func EncodeIImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 12) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
|
||||
if err := immIFits(imm, 12); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return imm << 20, nil
|
||||
}
|
||||
|
||||
func EncodeJImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 21) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 21 bits", imm)
|
||||
if err := immIFits(imm, 21); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if imm&1 != 0 {
|
||||
return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm)
|
||||
if err := immEven(imm); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(encodeJImmediate(uint32(imm))), nil
|
||||
}
|
||||
|
||||
func EncodeSImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 12) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
|
||||
if err := immIFits(imm, 12); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
|
||||
}
|
||||
|
||||
func EncodeUImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 20) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 20 bits", imm)
|
||||
if err := immIFits(imm, 20); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return imm << 12, nil
|
||||
}
|
||||
@ -1975,9 +1990,9 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
|
||||
// MOV $1, X10
|
||||
// SLLI $63, X10, X10
|
||||
var insSLLI *instruction
|
||||
if !immIFits(ins.imm, 32) {
|
||||
if err := immIFits(ins.imm, 32); err != nil {
|
||||
ctz := bits.TrailingZeros64(uint64(ins.imm))
|
||||
if immIFits(ins.imm>>ctz, 32) {
|
||||
if err := immIFits(ins.imm>>ctz, 32); err == nil {
|
||||
ins.imm = ins.imm >> ctz
|
||||
insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(ctz)}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user