// 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) } }) } }