blob: 87b31e5a896c24f8291ff04e5ca4825906af1c7c [file] [log] [blame] [edit]
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package riscv
import (
"fmt"
"testing"
)
func TestSplitShiftConst(t *testing.T) {
tests := []struct {
v int64
wantImm int64
wantLsh int
wantRsh int
wantOk bool
}{
{0x100000000, 1, 32, 0, true},
{0xfffff001, 0, 0, 0, false},
{0xfffff801, -2047, 32, 32, true},
{0xfffffff1, -15, 32, 32, true},
{0xffffffff, -1, 0, 32, true},
{0xfffffffe, 0x7fffffff, 1, 0, true},
{0xfffffffffffda, -19, 13, 12, true},
{0xfffffffffffde, -17, 13, 12, true},
{0x000003ffffffffff, -1, 0, 22, true},
{0x0007ffffffffffff, -1, 0, 13, true},
{0x7fffffff00000000, 0x7fffffff, 32, 0, true},
{0x7fffffffffffffff, -1, 0, 1, true},
{0x7f7f7f7f7f7f7f7f, 0, 0, 0, false},
{0x0080000010000000, 0x8000001, 28, 0, true},
{0x0abcdabcd0000000, 0, 0, 0, false},
{-4503599610593281, 0, 0, 0, false}, // 0x8abcdabcd0000000
{-7543254330000000, 0, 0, 0, false}, // 0xfff0000000ffffff
}
for _, test := range tests {
t.Run(fmt.Sprintf("0x%x", test.v), func(t *testing.T) {
c, l, r, ok := splitShiftConst(test.v)
if got, want := c, test.wantImm; got != want {
t.Errorf("Got immediate %d, want %d", got, want)
}
if got, want := l, test.wantLsh; got != want {
t.Errorf("Got left shift %d, want %d", got, want)
}
if got, want := r, test.wantRsh; got != want {
t.Errorf("Got right shift %d, want %d", got, want)
}
switch {
case !ok && test.wantOk:
t.Error("Failed to split shift constant, want success")
case ok && !test.wantOk:
t.Error("Successfully split shift constant, want failure")
}
if !ok || ok != test.wantOk {
return
}
// Reconstruct as either a 12 bit or 32 bit signed constant.
s := 64 - 12
v := int64((uint64(((c << s) >> s)) << l) >> r)
if test.wantImm != ((test.wantImm << s) >> s) {
v = int64((uint64(int32(test.wantImm)) << l) >> r)
}
if v != test.v {
t.Errorf("Got v = %d (%x), want v = %d (%x)", v, v, test.v, test.v)
}
})
}
}