1 # SPDX-License-Identifier: LGPL-3-or-later
2 # Copyright 2023 Jacob Lifshay programmerjake@gmail.com
4 # Funded by NLnet Assure Programme 2021-02-052, https://nlnet.nl/assure part
5 # of Horizon 2020 EU Programme 957073.
7 from openpower
.test
.common
import TestAccumulatorBase
, skip_case
8 from openpower
.test
.state
import ExpectedState
9 from openpower
.test
.util
import assemble
10 from openpower
.decoder
.isa
.caller
import SVP64State
11 from nmutil
.plain_data
import plain_data
15 _SCALAR_EXTRA2
= range(64)
16 _VECTOR_EXTRA2
= range(0, 128, 2)
17 _SCALAR_EXTRA3
= range(128)
18 _VECTOR_EXTRA3
= range(128)
21 @plain_data(unsafe_hash
=True, frozen
=True)
23 __slots__
= "alloc_pass",
25 def __init__(self
, alloc_pass
):
27 self
.alloc_pass
= alloc_pass
30 raise NotImplementedError
34 def __gen_all_args(cur_out
, output
, args
, regs
, step
):
36 output
.append((cur_out
.copy(), regs
.copy()))
40 for out
in arg
.gen(regs
):
42 _Arg
.__gen
_all
_args
(cur_out
, output
, args
, regs
, step
=step
+ 1)
45 def gen_all_args(args
):
47 args
= sorted(enumerate(args
), key
=lambda arg
: arg
[1].alloc_pass
)
49 cur_out
= [""] * len(args
)
50 _Arg
.__gen
_all
_args
(cur_out
, output
, args
, regs
={}, step
=0)
54 _DEFAULT_TEST_VALUES
= 0x123456789ABCDEF0,
57 @plain_data(unsafe_hash
=True, frozen
=True)
59 __slots__
= "vec", "regs", "values", "all_regs"
61 def __init__(self
, vec
, regs
, values
, all_regs
):
62 # type: (bool, range, list[int] | tuple[int, ...], bool) -> None
65 self
.values
= tuple(values
)
66 self
.all_regs
= all_regs
67 super().__init
__(0 if all_regs
else 1)
70 def const(value
, vec
=False, regs
=range(4, 32, 2)):
71 # type: (int, bool, range) -> _ArgReg
72 return _ArgReg(vec
, regs
, values
=(value
,), all_regs
=False)
75 def reg_range(vec
, regs
, values
=_DEFAULT_TEST_VALUES
, skip_r0
=False):
76 # type: (bool, range, list[int] | tuple[int, ...], bool) -> _ArgReg
78 assert regs
.start
== 0
79 regs
= range(regs
.start
+ regs
.step
,
81 return _ArgReg(vec
, regs
, values
, all_regs
=True)
84 def s_extra2(values
=_DEFAULT_TEST_VALUES
, skip_r0
=False):
85 # type: (list[int] | tuple[int, ...], bool) -> _ArgReg
86 return _ArgReg
.reg_range(vec
=False, regs
=_SCALAR_EXTRA2
,
87 values
=values
, skip_r0
=skip_r0
)
90 def v_extra2(values
=_DEFAULT_TEST_VALUES
, skip_r0
=False):
91 # type: (list[int] | tuple[int, ...], bool) -> _ArgReg
92 return _ArgReg
.reg_range(vec
=True, regs
=_VECTOR_EXTRA2
,
93 values
=values
, skip_r0
=skip_r0
)
96 def s_extra3(values
=_DEFAULT_TEST_VALUES
, skip_r0
=False):
97 # type: (list[int] | tuple[int, ...], bool) -> _ArgReg
98 return _ArgReg
.reg_range(vec
=False, regs
=_SCALAR_EXTRA3
,
99 values
=values
, skip_r0
=skip_r0
)
102 def v_extra3(values
=_DEFAULT_TEST_VALUES
, skip_r0
=False):
103 # type: (list[int] | tuple[int, ...], bool) -> _ArgReg
104 return _ArgReg
.reg_range(vec
=True, regs
=_VECTOR_EXTRA3
,
105 values
=values
, skip_r0
=skip_r0
)
108 for reg
in self
.regs
:
111 regs
[reg
] = self
.values
117 if not self
.all_regs
:
121 @plain_data(unsafe_hash
=True, frozen
=True)
122 class _ArgLiteral(_Arg
):
125 def __init__(self
, text
):
126 # type: (str) -> None
131 yield (None, self
.text
)
134 class SVP64EncodingsCases(TestAccumulatorBase
):
135 def do_check(self
, insn
, args
, gen_expected
, src_loc_at
=0):
136 UNINIT
= int.from_bytes(b
"uninit..", "little")
137 all_args
= _Arg
.gen_all_args(args
)
138 for cur_args
, cur_regs
in all_args
:
139 asm
= insn
+ " " + ", ".join(map(lambda v
: v
[1], cur_args
))
140 with self
.subTest(asm
=asm
):
141 prog
= assemble([asm
])
142 for values
in itertools
.product(*cur_regs
.values()):
143 gprs
= [UNINIT
] * 128
144 for reg
, v
in zip(cur_regs
.keys(), values
):
146 svstate
= SVP64State()
149 e
= gen_expected(cur_args
, gprs
)
152 for reg
in sorted(cur_regs
.keys()):
155 input_gprs
.append(f
"r{reg} = 0x{iv:X}")
156 expected_gprs
.append(f
"r{reg} = 0x{ev:X}")
157 expected_gprs
= "\n".join(expected_gprs
)
158 input_gprs
= "\n".join(input_gprs
)
160 expected_gprs
=expected_gprs
, input_gprs
=input_gprs
,
162 self
.add_case(prog
, gprs
, expected
=e
,
163 initial_svstate
=svstate
,
164 src_loc_at
=src_loc_at
+ 1)
169 def __sv_add_gen_expected(cur_args
, gprs
):
170 e
= ExpectedState(pc
=8, int_regs
=gprs
)
171 RT_reg
= cur_args
[0][0]
172 RA_reg
= cur_args
[1][0]
173 RB_reg
= cur_args
[2][0]
176 e
.intregs
[RT_reg
] = (RA
+ RB
) % 2 ** 64
179 def case_sv_add_vvs_rt(self
):
180 self
.do_check("sv.add", [
182 _ArgReg
.const(1, vec
=True),
183 _ArgReg
.const(1)], self
.__sv
_add
_gen
_expected
)
185 def case_sv_add_vvs_ra(self
):
186 self
.do_check("sv.add", [
187 _ArgReg
.const(0, vec
=True),
189 _ArgReg
.const(1)], self
.__sv
_add
_gen
_expected
)
191 def case_sv_add_vvs_rb(self
):
192 self
.do_check("sv.add", [
193 _ArgReg
.const(0, vec
=True),
194 _ArgReg
.const(1, vec
=True),
195 _ArgReg
.s_extra3()], self
.__sv
_add
_gen
_expected
)
200 def __sv_maddedu_gen_expected(cur_args
, gprs
):
201 e
= ExpectedState(pc
=8, int_regs
=gprs
)
202 RT_reg
= cur_args
[0][0]
203 RA_reg
= cur_args
[1][0]
204 RB_reg
= cur_args
[2][0]
205 RC_reg
= cur_args
[3][0]
211 RS
= v
>> 64 # can't overflow, so no need for wrapping
212 e
.intregs
[RT_reg
] = RT
213 e
.intregs
[RC_reg
] = RS
216 def case_sv_maddedu_vvss_rt(self
):
217 self
.do_check("sv.maddedu", [
219 _ArgReg
.const(1, vec
=True),
221 _ArgReg
.const(0)], self
.__sv
_maddedu
_gen
_expected
)
223 def case_sv_maddedu_vvss_ra(self
):
224 self
.do_check("sv.maddedu", [
225 _ArgReg
.const(0, vec
=True),
228 _ArgReg
.const(0)], self
.__sv
_maddedu
_gen
_expected
)
230 def case_sv_maddedu_vvss_rb(self
):
231 self
.do_check("sv.maddedu", [
232 _ArgReg
.const(0, vec
=True),
233 _ArgReg
.const(1, vec
=True),
235 _ArgReg
.const(0)], self
.__sv
_maddedu
_gen
_expected
)
237 def case_sv_maddedu_vvss_rc(self
):
238 self
.do_check("sv.maddedu", [
239 _ArgReg
.const(0, vec
=True),
240 _ArgReg
.const(0, vec
=True),
242 _ArgReg
.s_extra2()], self
.__sv
_maddedu
_gen
_expected
)