| // 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 | |
| }{ | |
| {0xfffff001, -4095, 32, 32, true}, | |
| {0xfffff801, -2047, 32, 32, true}, | |
| {0xfffffff1, -15, 32, 32, true}, | |
| {0xffffffff, -1, 0, 32, true}, | |
| {0xfffffffe, 0x7fffffff, 1, 0, true}, | |
| {0x80a9b553, -2136361645, 32, 32, true}, | |
| {0x100000000, 1, 32, 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, -1412584499, 32, 4, true}, | |
| {-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) | |
| } | |
| }) | |
| } | |
| } |