1 /* tc-ppc-svp64.c -- Assemble for the PowerPC SVP64 extension.
2 Copyright (C) 2022 Free Software Foundation, Inc.
3 Written by Dmitry Selyutin aka ghostmansd.
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
25 const struct svp64_desc
*desc
;
26 struct svp64_insn insn
;
27 unsigned int pmmode
: 1;
28 unsigned int pmask
: 3;
29 unsigned int smmode
: 1;
30 unsigned int smask
: 3;
31 unsigned int mmode
: 1;
32 unsigned int has_pmask
: 1;
33 unsigned int has_smask
: 1;
34 unsigned int mask_m_specified
: 1;
35 unsigned int subvl
: 2;
36 unsigned int destwid
: 2;
37 unsigned int srcwid
: 2;
38 unsigned int ldst_elstride
: 1;
39 unsigned int sv_mode_explicit
: 1;
40 unsigned int sv_mode
: 2;
42 unsigned int src_zero
: 1;
43 unsigned int dst_zero
: 1;
44 unsigned int ff
: 3 + 2; /* 3-bit plus RC1 */
45 unsigned int pr
: 3 + 2; /* 3-bit plus RC1 */
49 unsigned int type
: 2;
51 unsigned int mode
: 5;
53 /* These are not implemented yet. */
54 unsigned int bc_all
: 1;
55 unsigned int bc_lru
: 1;
56 unsigned int bc_brc
: 1;
57 unsigned int bc_svstep
: 1;
58 unsigned int bc_vsb
: 1;
59 unsigned int bc_vlset
: 1;
60 unsigned int bc_vli
: 1;
61 unsigned int bc_snz
: 1;
64 #define SVP64_RC1_ACTIVE (1U << 3U)
65 #define SVP64_RC1_INVERT (SVP64_RC1_ACTIVE | (1U << 4U))
74 enum svp64_predicate
{
76 SVP64_PREDICATE_1BIT_R3
,
78 SVP64_PREDICATE_R3_INV
,
80 SVP64_PREDICATE_R10_INV
,
82 SVP64_PREDICATE_R30_INV
,
86 SVP64_PREDICATE_GE
= SVP64_PREDICATE_NL
,
89 SVP64_PREDICATE_LE
= SVP64_PREDICATE_NG
,
93 SVP64_PREDICATE_UN
= SVP64_PREDICATE_SO
,
95 SVP64_PREDICATE_NU
= SVP64_PREDICATE_NS
,
98 SVP64_PREDICATE_RC1_INV
,
102 svp64_operand (expressionS
*exp
)
107 char *origin
= input_line_pointer
;
109 if (input_line_pointer
[0] == '*')
112 if (ISDIGIT (input_line_pointer
[1]))
114 input_line_pointer
[0] = 'r';
118 ++input_line_pointer
;
120 else if (input_line_pointer
[0] == '^')
123 ++input_line_pointer
;
126 if (!vector
&& !compat
&& !reg_names_p
&&
127 (input_line_pointer
[0] != '%' || !ISALPHA (input_line_pointer
[1])))
130 if (!compat
&& (*input_line_pointer
== '%'))
131 ++input_line_pointer
;
133 ppc_operand_common (exp
, svp64_regs
, svp64_num_regs
);
135 if (exp
->X_op
== O_absent
)
136 input_line_pointer
= origin
;
137 else if (exp
->X_op
== O_register
)
141 if (exp
->X_add_number
== 3)
143 exp
->X_op
= O_predicate
;
144 exp
->X_add_number
= SVP64_PREDICATE_1BIT_R3
;
147 exp
->X_op
= O_illegal
;
150 exp
->X_op
= O_vector
;
152 else if ((exp
->X_op
== O_constant
) && vector
)
153 exp
->X_op
= O_vector
;
160 svp64_special_expr (expressionS
*exp
)
162 return ((exp
->X_op
== O_vector
) || (exp
->X_op
== O_predicate
));
165 static jmp_buf svp64_exception
;
167 #define svp64_raise(...) \
169 as_bad (__VA_ARGS__); \
170 longjmp (svp64_exception, 1); \
173 #define svp64_raise_if(COND, ...) \
176 svp64_raise (__VA_ARGS__); \
179 static htab_t svp64_hash
;
182 svp64_setup_records (void)
184 const struct svp64_record
*record
;
185 const struct svp64_record
*records_end
;
187 svp64_hash
= str_htab_create ();
189 records_end
= (svp64_records
+ svp64_nr_records
);
190 for (record
= svp64_records
; record
< records_end
; ++record
)
192 const struct svp64_desc
*desc
= &record
->desc
;
193 const char *name
= (record
->name
+ (sizeof ("sv.") - 1));
195 if (str_hash_insert (svp64_hash
, name
, desc
, 0) != NULL
)
196 as_fatal (_("duplicate %s"), name
);
200 #define SVP64_SEP '/'
203 svp64_expression (char *str
, expressionS
*exp
)
207 char *str_head
= str
;
208 char *old_ilp
= input_line_pointer
;
210 memset (exp
, 0, sizeof *exp
);
212 while (! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
219 input_line_pointer
= str
;
223 input_line_pointer
= old_ilp
;
226 return ((exp
->X_op
== O_absent
) ? str_head
: str_tail
);
229 struct svp64_predicate_cr_map
{
231 unsigned int len
: 3;
234 #define SVP64_PREDICATE_CR_MAP(STR, ID) \
235 { STR, (sizeof (STR) - 1), ID }
238 svp64_parse_predicate_cr (const char *name
, expressionS
*exp
)
241 const char *str
= name
;
242 static const struct svp64_predicate_cr_map table
[] = {
243 SVP64_PREDICATE_CR_MAP ("lt", SVP64_PREDICATE_LT
),
244 SVP64_PREDICATE_CR_MAP ("nl", SVP64_PREDICATE_NL
),
245 SVP64_PREDICATE_CR_MAP ("ge", SVP64_PREDICATE_GE
),
246 SVP64_PREDICATE_CR_MAP ("gt", SVP64_PREDICATE_GT
),
247 SVP64_PREDICATE_CR_MAP ("ng", SVP64_PREDICATE_NG
),
248 SVP64_PREDICATE_CR_MAP ("le", SVP64_PREDICATE_LE
),
249 SVP64_PREDICATE_CR_MAP ("eq", SVP64_PREDICATE_EQ
),
250 SVP64_PREDICATE_CR_MAP ("ne", SVP64_PREDICATE_NE
),
251 SVP64_PREDICATE_CR_MAP ("so", SVP64_PREDICATE_SO
),
252 SVP64_PREDICATE_CR_MAP ("un", SVP64_PREDICATE_UN
),
253 SVP64_PREDICATE_CR_MAP ("ns", SVP64_PREDICATE_NS
),
254 SVP64_PREDICATE_CR_MAP ("nu", SVP64_PREDICATE_NU
),
257 for (i
= 0; i
< sizeof (table
) / sizeof (table
[0]); ++i
)
259 const struct svp64_predicate_cr_map
*entry
= &table
[i
];
261 if (strncmp (str
, entry
->str
, entry
->len
) != 0)
265 if (! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
271 exp
->X_op
= O_predicate
;
272 exp
->X_add_number
= entry
->id
;
281 svp64_parse_predicate_RC1 (const char *name
, expressionS
*exp
)
283 if (strcmp (name
, "RC1") == 0)
285 exp
->X_op
= O_predicate
;
286 exp
->X_add_number
= SVP64_PREDICATE_RC1
;
294 svp64_parse_name (const char *name
, expressionS
*exp
, enum expr_mode mode
)
296 exp
->X_op
= O_absent
;
297 exp
->X_op_symbol
= NULL
;
298 exp
->X_add_symbol
= NULL
;
300 if ((svp64_parse_predicate_cr (name
, exp
)
301 || svp64_parse_predicate_RC1 (name
, exp
)) == 0)
302 ppc_parse_name_common (name
, exp
, mode
, false, svp64_regs
, svp64_num_regs
);
306 svp64_decode_predicate (char *str
, bool *cr
, unsigned int *mask
)
312 str
= svp64_expression (str
, &exp
);
315 expressionS
*sym_exp
= NULL
;
316 static const struct {
318 unsigned int mask
: 3 + 2; /* 3-bit plus RC1 */
320 /* SVP64_PREDICATE_1BIT_R3 */ {0, 1},
321 /* SVP64_PREDICATE_R3 */ {0, 2},
322 /* SVP64_PREDICATE_R3_INV */ {0, 3},
323 /* SVP64_PREDICATE_R10 */ {0, 4},
324 /* SVP64_PREDICATE_R10_INV */ {0, 5},
325 /* SVP64_PREDICATE_R30 */ {0, 6},
326 /* SVP64_PREDICATE_R30_INV */ {0, 7},
327 /* SVP64_PREDICATE_LT */ {1, 0},
328 /* SVP64_PREDICATE_NL */ {1, 1},
329 /* SVP64_PREDICATE_GT */ {1, 2},
330 /* SVP64_PREDICATE_NG */ {1, 3},
331 /* SVP64_PREDICATE_EQ */ {1, 4},
332 /* SVP64_PREDICATE_NE */ {1, 5},
333 /* SVP64_PREDICATE_SO */ {1, 6},
334 /* SVP64_PREDICATE_NS */ {1, 7},
335 /* {SVP64_PREDICATE_RC1*/ {0, SVP64_RC1_ACTIVE
},
336 /* SVP64_PREDICATE_RC1_INV */ {0, SVP64_RC1_INVERT
},
338 enum svp64_predicate predicate
;
340 if (exp
.X_add_symbol
)
341 sym_exp
= symbol_get_value_expression (exp
.X_add_symbol
);
343 if ((exp
.X_op
== O_register
) &&
344 ((exp
.X_add_number
== 3)
345 || (exp
.X_add_number
== 10)
346 || (exp
.X_add_number
== 30)))
348 exp
.X_op
= O_predicate
;
349 if (exp
.X_add_number
== 3)
350 exp
.X_add_number
= SVP64_PREDICATE_R3
;
351 else if (exp
.X_add_number
== 10)
352 exp
.X_add_number
= SVP64_PREDICATE_R10
;
353 else if (exp
.X_add_number
== 30)
354 exp
.X_add_number
= SVP64_PREDICATE_R30
;
356 else if ((exp
.X_op
== O_bit_not
) && (sym_exp
!= NULL
))
358 if (sym_exp
->X_op
== O_register
)
360 if (sym_exp
->X_add_number
== 3)
361 exp
.X_add_number
= SVP64_PREDICATE_R3_INV
;
362 else if (sym_exp
->X_add_number
== 10)
363 exp
.X_add_number
= SVP64_PREDICATE_R10_INV
;
364 else if (sym_exp
->X_add_number
== 30)
365 exp
.X_add_number
= SVP64_PREDICATE_R30_INV
;
367 else if ((sym_exp
->X_op
== O_predicate
)
368 && (sym_exp
->X_add_number
== SVP64_PREDICATE_RC1
))
369 exp
.X_add_number
= SVP64_PREDICATE_RC1_INV
;
371 else if (exp
.X_op
!= O_predicate
)
374 predicate
= (enum svp64_predicate
)exp
.X_add_number
;
375 *cr
= (table
[predicate
].cr
? true : false);
376 *mask
= table
[predicate
].mask
;
384 struct svp64_decoder
{
385 char *(*call
)(char *str
, struct svp64_ctx
*svp64
);
389 #define SVP64_DECODER(STR, CALL) \
390 { CALL, STR, (sizeof (STR) - 1) }
393 svp64_decode_m (char *str
, struct svp64_ctx
*svp64
)
400 str
+= (sizeof ("m=") - 1);
401 iter
= svp64_decode_predicate (str
, &cr
, &pmask
);
402 if (!iter
|| ((pmask
& SVP64_RC1_ACTIVE
) != 0))
403 svp64_raise (_("unrecognized mode: `%s'"), str
);
405 pmmode
= (cr
? 1 : 0);
406 svp64
->pmmode
= pmmode
;
407 svp64
->pmask
= pmask
;
408 svp64
->smmode
= pmmode
;
409 svp64
->smask
= pmask
;
410 svp64
->mmode
= pmmode
;
411 svp64
->mask_m_specified
= 1;
417 svp64_decode_dm (char *str
, struct svp64_ctx
*svp64
)
424 str
+= (sizeof ("dm=") - 1);
425 iter
= svp64_decode_predicate (str
, &cr
, &pmask
);
426 if (!iter
|| ((pmask
& SVP64_RC1_ACTIVE
) != 0))
427 svp64_raise (_("unrecognized mode: `%s'"), str
);
429 pmmode
= (cr
? 1 : 0);
430 svp64
->pmmode
= pmmode
;
431 svp64
->pmask
= pmask
;
432 svp64
->mmode
= pmmode
;
433 svp64
->has_pmask
= 1;
439 svp64_decode_sm (char *str
, struct svp64_ctx
*svp64
)
446 str
+= (sizeof ("sm=") - 1);
447 iter
= svp64_decode_predicate (str
, &cr
, &smask
);
448 if (!iter
|| ((smask
& SVP64_RC1_ACTIVE
) != 0))
449 svp64_raise (_("unrecognized mode: `%s'"), str
);
451 smmode
= (cr
? 1 : 0);
452 svp64
->smmode
= smmode
;
453 svp64
->smask
= smask
;
454 svp64
->mmode
= smmode
;
455 svp64
->has_smask
= 1;
461 svp64_decode_vec (char *str
, struct svp64_ctx
*svp64
)
465 str
+= (sizeof ("vec") - 1);
466 if ( ISSPACE (*str
) || *str
== SVP64_SEP
|| *str
== '\0')
470 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
493 struct svp64_width_map
{
495 unsigned int len
: 2;
496 unsigned int num
: 6;
497 unsigned int width
: 8;
499 #define SVP64_WIDTH_MAP(NUM, WIDTH) \
500 { #NUM, (sizeof (#NUM) - 1), NUM, WIDTH }
503 svp64_decode_width (char *str
, unsigned int *width
)
508 static const struct svp64_width_map table
[] = {
509 SVP64_WIDTH_MAP (8, 3),
510 SVP64_WIDTH_MAP (16, 2),
511 SVP64_WIDTH_MAP (32, 1),
515 str
= svp64_expression (str
, &exp
);
516 if ((str
!= origin
) && (exp
.X_op
== O_constant
))
518 for (i
= 0; i
< (sizeof (table
) / sizeof (table
[0])); ++i
)
520 const struct svp64_width_map
*entry
= &table
[i
];
522 if (entry
->num
== exp
.X_add_number
)
524 *width
= entry
->width
;
534 svp64_decode_w (char *str
, struct svp64_ctx
*svp64
)
539 str
+= (sizeof ("w=") - 1);
540 iter
= svp64_decode_width (str
, &width
);
542 svp64_raise (_("unrecognized mode: `%s'"), str
);
544 svp64
->srcwid
= width
;
545 svp64
->destwid
= width
;
551 svp64_decode_dw (char *str
, struct svp64_ctx
*svp64
)
556 str
+= (sizeof ("dw=") - 1);
557 iter
= svp64_decode_width (str
, &width
);
559 svp64_raise (_("unrecognized mode: `%s'"), str
);
561 svp64
->destwid
= width
;
567 svp64_decode_sw (char *str
, struct svp64_ctx
*svp64
)
572 str
+= (sizeof ("sw=") - 1);
573 iter
= svp64_decode_width (str
, &width
);
575 svp64_raise (_("unrecognized mode: `%s'"), str
);
577 svp64
->srcwid
= width
;
583 svp64_decode_els (char *str
, struct svp64_ctx
*svp64
)
585 str
+= (sizeof ("els") - 1);
586 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
589 svp64
->ldst_elstride
= 1;
597 svp64_decode_sat (char *str
, struct svp64_ctx
*svp64
)
601 str
+= (sizeof ("sat") - 1);
602 if ((*str
!= 's') && (*str
!= 'u'))
606 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
609 if (svp64
->sv_mode_explicit
)
610 svp64_raise (_("SV mode conflict: `%s'"), str
);
612 svp64
->sv_mode_explicit
= 1;
614 svp64
->sat
= (mode
== 's');
622 svp64_decode_sz (char *str
, struct svp64_ctx
*svp64
)
624 str
+= (sizeof ("sz") - 1);
625 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
636 svp64_decode_dz (char *str
, struct svp64_ctx
*svp64
)
638 str
+= (sizeof ("dz") - 1);
639 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
650 svp64_decode_ff (char *str
, struct svp64_ctx
*svp64
)
656 str
+= (sizeof ("ff=") - 1);
657 if (svp64
->sv_mode_explicit
)
658 svp64_raise (_("SV mode conflict: `%s'"), str
);
660 iter
= svp64_decode_predicate (str
, &cr
, &mask
);
661 if (!iter
|| !(cr
|| ((mask
& SVP64_RC1_ACTIVE
) != 0)))
662 svp64_raise (_("unrecognized mode: `%s'"), str
);
664 svp64
->sv_mode_explicit
= 1;
665 svp64
->sv_mode
= 0x1;
672 svp64_decode_pr (char *str
, struct svp64_ctx
*svp64
)
678 str
+= (sizeof ("pr=") - 1);
679 if (svp64
->sv_mode_explicit
)
680 svp64_raise (_("SV mode conflict: `%s'"), str
);
682 iter
= svp64_decode_predicate (str
, &cr
, &mask
);
683 if (!iter
|| !(cr
|| ((mask
& SVP64_RC1_ACTIVE
) != 0)))
684 svp64_raise (_("unrecognized mode: `%s'"), str
);
686 svp64
->sv_mode_explicit
= 1;
687 svp64
->sv_mode
= 0x3;
694 svp64_decode_mr (char *str
, struct svp64_ctx
*svp64
)
696 str
+= (sizeof ("mr") - 1);
697 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
700 svp64
->sv_mode_explicit
= 1;
710 svp64_decode_mrr (char *str
, struct svp64_ctx
*svp64
)
712 str
+= (sizeof ("mrr") - 1);
713 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
716 svp64
->sv_mode_explicit
= 1;
727 svp64_decode_crm (char *str
, struct svp64_ctx
*svp64
)
729 str
+= (sizeof ("crm") - 1);
730 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
733 svp64
->sv_mode_explicit
= 1;
743 svp64_decode_mode (char *str
, struct svp64_ctx
*svp64
)
746 static const struct svp64_decoder table
[] = {
747 SVP64_DECODER ("m=" , svp64_decode_m
),
748 SVP64_DECODER ("dm=" , svp64_decode_dm
),
749 SVP64_DECODER ("sm=" , svp64_decode_sm
),
750 SVP64_DECODER ("vec2", svp64_decode_vec
),
751 SVP64_DECODER ("vec3", svp64_decode_vec
),
752 SVP64_DECODER ("vec4", svp64_decode_vec
),
753 SVP64_DECODER ("w=" , svp64_decode_w
),
754 SVP64_DECODER ("dw=" , svp64_decode_dw
),
755 SVP64_DECODER ("sw=" , svp64_decode_sw
),
756 SVP64_DECODER ("els" , svp64_decode_els
),
757 SVP64_DECODER ("sats", svp64_decode_sat
),
758 SVP64_DECODER ("satu", svp64_decode_sat
),
759 SVP64_DECODER ("sz" , svp64_decode_sz
),
760 SVP64_DECODER ("dz" , svp64_decode_dz
),
761 SVP64_DECODER ("ff=" , svp64_decode_ff
),
762 SVP64_DECODER ("pr=" , svp64_decode_pr
),
763 SVP64_DECODER ("mr" , svp64_decode_mr
),
764 SVP64_DECODER ("mrr" , svp64_decode_mrr
),
765 SVP64_DECODER ("crm" , svp64_decode_crm
),
768 for (i
= 0; i
< sizeof (table
) / sizeof (table
[0]); ++i
)
770 const struct svp64_decoder
*entry
= &table
[i
];
772 if (strncmp (str
, entry
->str
, entry
->len
) == 0)
773 return entry
->call (str
, svp64
);
779 struct svp64_str_map
{
783 #define SVP64_STR_MAP(STR) \
784 { STR, (sizeof (STR) - 1) }
787 svp64_str_map_cmp(const char *str
, size_t len
,
788 const struct svp64_str_map
*map
, size_t cnt
)
792 for (i
= 0; i
< cnt
; ++i
) {
793 const struct svp64_str_map
*entry
= &map
[i
];
795 if ((entry
->len
== len
) && (memcmp(entry
->str
, str
, len
) == 0))
801 #define SVP64_STR_MAP_CMP(STR, LEN, MAP) \
802 svp64_str_map_cmp(STR, LEN, MAP, (sizeof (MAP) / sizeof (*MAP)))
805 svp64_is_ld(const char *str
, size_t len
)
807 static const struct svp64_str_map table
[] = {
809 SVP64_STR_MAP ("lbarx"),
810 SVP64_STR_MAP ("lbz"),
811 SVP64_STR_MAP ("lbzu"),
812 SVP64_STR_MAP ("lbzux"),
813 SVP64_STR_MAP ("lbzx"),
815 SVP64_STR_MAP ("ld"),
816 SVP64_STR_MAP ("ldarx"),
817 SVP64_STR_MAP ("ldbrx"),
818 SVP64_STR_MAP ("ldu"),
819 SVP64_STR_MAP ("ldux"),
820 SVP64_STR_MAP ("ldx"),
822 SVP64_STR_MAP ("lfs"),
823 SVP64_STR_MAP ("lfsx"),
824 SVP64_STR_MAP ("lfsu"),
825 SVP64_STR_MAP ("lfsux"),
827 SVP64_STR_MAP ("lfd"),
828 SVP64_STR_MAP ("lfdx"),
829 SVP64_STR_MAP ("lfdu"),
830 SVP64_STR_MAP ("lfdux"),
831 SVP64_STR_MAP ("lfiwzx"),
832 SVP64_STR_MAP ("lfiwax"),
834 SVP64_STR_MAP ("lha"),
835 SVP64_STR_MAP ("lharx"),
836 SVP64_STR_MAP ("lhau"),
837 SVP64_STR_MAP ("lhaux"),
838 SVP64_STR_MAP ("lhax"),
839 SVP64_STR_MAP ("lhbrx"),
840 SVP64_STR_MAP ("lhz"),
841 SVP64_STR_MAP ("lhzu"),
842 SVP64_STR_MAP ("lhzux"),
843 SVP64_STR_MAP ("lhzx"),
845 SVP64_STR_MAP ("lwa"),
846 SVP64_STR_MAP ("lwarx"),
847 SVP64_STR_MAP ("lwaux"),
848 SVP64_STR_MAP ("lwax"),
849 SVP64_STR_MAP ("lwbrx"),
850 SVP64_STR_MAP ("lwz"),
851 SVP64_STR_MAP ("lwzcix"),
852 SVP64_STR_MAP ("lwzu"),
853 SVP64_STR_MAP ("lwzux"),
854 SVP64_STR_MAP ("lwzx"),
857 return SVP64_STR_MAP_CMP(str
, len
, table
);
861 svp64_is_st(const char *str
, size_t len
)
863 static const struct svp64_str_map table
[] = {
865 SVP64_STR_MAP ("stb"),
866 SVP64_STR_MAP ("stbcix"),
867 SVP64_STR_MAP ("stbcx"),
868 SVP64_STR_MAP ("stbu"),
869 SVP64_STR_MAP ("stbux"),
870 SVP64_STR_MAP ("stbx"),
872 SVP64_STR_MAP ("std"),
873 SVP64_STR_MAP ("stdbrx"),
874 SVP64_STR_MAP ("stdcx"),
875 SVP64_STR_MAP ("stdu"),
876 SVP64_STR_MAP ("stdux"),
877 SVP64_STR_MAP ("stdx"),
878 /* FP store single */
879 SVP64_STR_MAP ("stfs"),
880 SVP64_STR_MAP ("stfsx"),
881 SVP64_STR_MAP ("stfsu"),
882 SVP64_STR_MAP ("stfux"),
883 /* FP store double */
884 SVP64_STR_MAP ("stfd"),
885 SVP64_STR_MAP ("stfdx"),
886 SVP64_STR_MAP ("stfdu"),
887 SVP64_STR_MAP ("stfdux"),
888 SVP64_STR_MAP ("stfiwx"),
890 SVP64_STR_MAP ("sth"),
891 SVP64_STR_MAP ("sthbrx"),
892 SVP64_STR_MAP ("sthcx"),
893 SVP64_STR_MAP ("sthu"),
894 SVP64_STR_MAP ("sthux"),
895 SVP64_STR_MAP ("sthx"),
897 SVP64_STR_MAP ("stw"),
898 SVP64_STR_MAP ("stwbrx"),
899 SVP64_STR_MAP ("stwcx"),
900 SVP64_STR_MAP ("stwu"),
901 SVP64_STR_MAP ("stwux"),
902 SVP64_STR_MAP ("stwx"),
905 return SVP64_STR_MAP_CMP(str
, len
, table
);
909 svp64_is_bc(const char *str
, size_t len
)
911 static const struct svp64_str_map table
[] = {
912 SVP64_STR_MAP ("bc"),
913 SVP64_STR_MAP ("bclr"),
916 return SVP64_STR_MAP_CMP(str
, len
, table
);
920 svp64_is_rc (const char *str
, size_t len
)
922 return (str
[len
- 1] == '.');
926 svp64_decode (char *str
, struct svp64_ctx
*svp64
)
935 str
+= (sizeof ("sv.") - 1);
936 if (! ISALPHA (*str
))
937 svp64_raise (_("unrecognized opcode: `%s'"), str
);
940 for (; ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0'; ++str
)
942 opclen
= (str
- opc
);
946 if (svp64_is_rc (opc
, opclen
))
949 if (svp64_is_ld (opc
, opclen
))
950 svp64
->type
= SVP64_TYPE_LD
;
951 else if (svp64_is_st (opc
, opclen
))
952 svp64
->type
= SVP64_TYPE_ST
;
953 else if (svp64_is_bc (opc
, opclen
))
954 svp64
->type
= SVP64_TYPE_BC
;
956 for (; (iter
= svp64_decode_mode (str
, svp64
)) != NULL
; str
= iter
)
959 argslen
= strlen (args
);
961 svp64
->desc
= (const struct svp64_desc
*) str_hash_find (svp64_hash
, opc
);
963 svp64_raise (_("unrecognized opcode: `%s'"), str
);
966 memmove (iter
, opc
, opclen
);
970 memmove (iter
, args
, argslen
);
976 svp64_validate_and_fix_mode_bc (struct svp64_ctx
*svp64
)
979 * Create mode and (overridden) src/dst widths.
980 * TODO: sanity-check BC modes.
982 svp64
->sv_mode
= ((svp64
->bc_svstep
<< SVP64_MODE_MOD2_MSB
) |
983 (svp64
->bc_vlset
<< SVP64_MODE_MOD2_LSB
) |
984 (svp64
->bc_snz
<< SVP64_MODE_BC_SNZ
));
985 svp64
->srcwid
= ((svp64
->bc_vsb
<< 1) | svp64
->bc_lru
);
986 svp64
->destwid
= ((svp64
->bc_lru
<< 1) | svp64
->bc_all
);
990 svp64_validate_and_fix_mode_mr (struct svp64_ctx
*svp64
)
992 svp64
->mode
|= (1U << SVP64_MODE_REDUCE
);
993 svp64_raise_if (svp64
->dst_zero
,
994 "dest-zero not allowed in mr mode");
997 svp64
->mode
|= (1U << SVP64_MODE_RG
);
1001 svp64
->mode
|= (1U << SVP64_MODE_CRM
);
1002 svp64_raise_if (!svp64
->rc
, "CRM only allowed when Rc=1");
1006 * Bit of weird encoding to jam zero-pred or SVM mode in.
1007 * SVM mode can be enabled only when SUBVL=2/3/4 (vec2/3/4)
1009 if (svp64
->subvl
== 0)
1010 svp64
->mode
|= (svp64
->dst_zero
<< SVP64_MODE_DZ
);
1014 svp64_validate_and_fix_mode_ff(struct svp64_ctx
*svp64
)
1016 svp64_raise_if (svp64
->src_zero
,
1017 "dest-zero not allowed in ff mode");
1019 if (svp64
->ff
& SVP64_RC1_ACTIVE
)
1021 svp64
->mode
|= (1U << SVP64_MODE_RC1
);
1022 svp64
->mode
|= (svp64
->dst_zero
<< SVP64_MODE_DZ
);
1023 svp64_raise_if (svp64
->rc
,
1024 "ffirst RC1/~RC1 only possible when Rc=0");
1025 if (svp64
->ff
& SVP64_RC1_INVERT
)
1026 svp64
->mode
|= (1U << SVP64_MODE_INV
);
1030 svp64_raise_if (svp64
->dst_zero
,
1031 "dst-zero not allowed in ffirst BO");
1032 svp64_raise_if (!svp64
->rc
,
1033 "ffirst BO only possible when Rc=1");
1034 svp64
->mode
|= (svp64
->ff
<< SVP64_MODE_BO_LSB
);
1039 svp64_validate_and_fix_mode_sat(struct svp64_ctx
*svp64
)
1041 svp64
->mode
|= (svp64
->src_zero
<< SVP64_MODE_SZ
);
1042 svp64
->mode
|= (svp64
->dst_zero
<< SVP64_MODE_DZ
);
1043 svp64
->mode
|= (svp64
->sat
<< SVP64_MODE_N
);
1047 svp64_validate_and_fix_mode_pr(struct svp64_ctx
*svp64
)
1049 svp64_raise_if (svp64
->src_zero
,
1050 "dest-zero not allowed in pr mode");
1052 if (svp64
->pr
& SVP64_RC1_ACTIVE
)
1054 svp64
->mode
|= (1U << SVP64_MODE_RC1
);
1055 svp64
->mode
|= (svp64
->dst_zero
<< SVP64_MODE_DZ
);
1056 svp64_raise_if (svp64
->rc
,
1057 "pr-mode RC1/~RC1 only possible when Rc=0");
1058 if (svp64
->pr
& SVP64_RC1_INVERT
)
1059 svp64
->mode
|= (1U << SVP64_MODE_INV
);
1063 svp64_raise_if (svp64
->dst_zero
,
1064 "dst-zero not allowed in pr-mode BO");
1065 svp64_raise_if (!svp64
->rc
,
1066 "pr-mode BO only possible when Rc=1");
1067 svp64
->mode
|= (svp64
->pr
<< SVP64_MODE_BO_LSB
);
1072 svp64_validate_and_fix_mode_explicit(struct svp64_ctx
*svp64
)
1074 static void (*const table
[])(struct svp64_ctx
*svp64
) = {
1075 svp64_validate_and_fix_mode_mr
,
1076 svp64_validate_and_fix_mode_ff
,
1077 svp64_validate_and_fix_mode_sat
,
1078 svp64_validate_and_fix_mode_pr
,
1081 return table
[svp64
->sv_mode
] (svp64
);
1085 svp64_validate_and_fix_mode_normal (struct svp64_ctx
*svp64
)
1087 svp64
->mode
|= (svp64
->src_zero
<< SVP64_MODE_SZ
);
1088 svp64
->mode
|= (svp64
->dst_zero
<< SVP64_MODE_DZ
);
1089 if ((svp64
->type
== SVP64_TYPE_LD
) ||
1090 (svp64
->type
== SVP64_TYPE_ST
))
1092 /* TODO: for now, LD/ST-indexed is ignored. */
1093 svp64
->mode
|= (svp64
->ldst_elstride
<< SVP64_MODE_ELS_NORMAL
);
1098 * TODO: reduce and subvector mode.
1099 * 00 1 dz CRM reduce mode (mr), SUBVL=1
1100 * 00 1 SVM CRM subvector reduce mode, SUBVL>1
1107 * There are 4 different modes, here, which will be partly-merged-in:
1108 * is_ldst is merged in with "normal", but is_bc is so different it's
1109 * done separately. Likewise is_cr (when it is done).
1111 * "normal" arithmetic: https://libre-soc.org/openpower/sv/normal
1112 * | 0-1 | 2 | 3 4 | description |
1113 * | --- | --- |---------|------------------------------------------ |
1114 * | 00 | 0 | dz sz | normal mode |
1115 * | 00 | 1 | 0 RG | scalar reduce mode (mr), SUBVL=1 |
1116 * | 00 | 1 | 1 / | parallel reduce mode (mr), SUBVL=1 |
1117 * | 00 | 1 | SVM RG | subvector reduce mode, SUBVL>1 |
1118 * | 01 | inv | CR-bit | Rc=1: ffirst CR sel |
1119 * | 01 | inv | VLi RC1 | Rc=0: ffirst z/nonz |
1120 * | 10 | N | dz sz | sat mode: N=0/1 u/s |
1121 * | 11 | inv | CR-bit | Rc=1: pred-result CR sel |
1122 * | 11 | inv | dz RC1 | Rc=0: pred-result z/nonz |
1124 * LD/ST-immediate: https://libre-soc.org/openpower/sv/ldst
1125 * | 0-1 | 2 | 3 4 | description |
1126 * | --- | --- |---------|------------------------------------------ |
1127 * | 00 | 0 | dz els | normal mode |
1128 * | 00 | 1 | dz shf | shift mode |
1129 * | 01 | inv | CR-bit | Rc=1: ffirst CR sel |
1130 * | 01 | inv | els RC1 | Rc=0: ffirst z/nonz |
1131 * | 10 | N | dz els | sat mode: N=0/1 u/s |
1132 * | 11 | inv | CR-bit | Rc=1: pred-result CR sel |
1133 * | 11 | inv | els RC1 | Rc=0: pred-result z/nonz |
1135 * LD/ST-indexed (RA+RB): https://libre-soc.org/openpower/sv/ldst
1136 * | 0-1 | 2 | 3 4 | description |
1137 * | --- | --- |---------|------------------------------------------ |
1138 * | 00 | SEA | dz sz | normal mode |
1139 * | 01 | SEA | dz sz | Strided (scalar only source) |
1140 * | 10 | N | dz sz | sat mode: N=0/1 u/s |
1141 * | 11 | inv | CR-bit | Rc=1: pred-result CR sel |
1142 * | 11 | inv | dz RC1 | Rc=0: pred-result z/nonz |
1144 * ...and branches/cr_ops are still in development.
1147 svp64_validate_and_fix_mode (struct svp64_ctx
*svp64
)
1149 if (svp64
->type
== SVP64_TYPE_BC
)
1150 svp64_validate_and_fix_mode_bc (svp64
);
1151 else if (svp64
->sv_mode_explicit
)
1152 svp64_validate_and_fix_mode_explicit (svp64
);
1154 svp64_validate_and_fix_mode_normal (svp64
);
1158 svp64_validate_and_fix (struct svp64_ctx
*svp64
)
1160 if (svp64
->desc
->ptype
== SVP64_PTYPE_P2
)
1163 * Since m=xx takes precedence (overrides) sm=xx and dm=xx,
1164 * treat them as mutually exclusive.
1166 if (svp64
->mask_m_specified
)
1168 svp64_raise_if (svp64
->has_smask
,
1169 "cannot have both source-mask and predicate mask");
1170 svp64_raise_if (svp64
->has_pmask
,
1171 "cannot have both dest-mask and predicate mask");
1175 * Since the default is INT predication (ALWAYS), if you
1176 * specify one CR mask, you must specify both, to avoid
1177 * mixing INT and CR reg types.
1179 if (svp64
->has_pmask
&& (svp64
->pmmode
== 1))
1181 svp64_raise_if (!svp64
->has_smask
,
1182 "need explicit source-mask in CR twin predication");
1184 if (svp64
->has_smask
&& (svp64
->smmode
== 1))
1186 svp64_raise_if (!svp64
->has_pmask
,
1187 "need explicit dest-mask in CR twin predication");
1190 /* Sanity-check that 2Pred mask is same mode. */
1191 if (svp64
->has_pmask
&& svp64
->has_smask
)
1193 svp64_raise_if (svp64
->smmode
!= svp64
->pmmode
,
1194 "predicate masks mismatch: pmmode=0x%08x, smmode=0x%08x",
1195 (unsigned int)svp64
->pmmode
, (unsigned int)svp64
->smmode
);
1197 else if (svp64
->desc
->ptype
== SVP64_PTYPE_P1
)
1199 svp64_raise_if (svp64
->has_smask
,
1200 "source-mask can only be specified on Twin-predicate ops");
1201 svp64_raise_if (svp64
->has_pmask
,
1202 "dest-mask can only be specified on Twin-predicate ops");
1206 if (svp64
->src_zero
)
1208 svp64_raise_if (!svp64
->has_smask
&& !svp64
->mask_m_specified
,
1209 "src zeroing requires a source predicate");
1211 if (svp64
->dst_zero
)
1213 svp64_raise_if (!svp64
->has_pmask
&& !svp64
->mask_m_specified
,
1214 "dest zeroing requires a dest predicate");
1217 svp64_validate_and_fix_mode (svp64
);
1221 svp64_remap_extra (struct svp64_ctx
*svp64
,
1222 ppc_opindex_t opindex
, uint32_t value
)
1224 const struct svp64_extra_desc
*desc
;
1226 desc
= svp64_extra_desc (svp64
->desc
, opindex
);
1227 svp64_raise_if ((desc
== NULL
), "cannot remap EXTRA");
1229 return (*desc
->set
) (&svp64
->insn
, value
);
1233 svp64_remap_reg (struct svp64_ctx
*svp64
, int64_t value
,
1234 ppc_opindex_t opindex
, bool vector
)
1239 svp64_raise_if (((value
< 0) || (value
> 127)),
1240 "register does not fit the expected range 0..127");
1241 field
= (uint32_t)value
;
1245 /* cut into 5-bits 2-bits FFFFF SS */
1246 sv_extra
= (field
& 0x3);
1251 /* cut into 2-bits 5-bits SS FFFFF */
1252 sv_extra
= (field
>> 5);
1256 if (svp64
->desc
->etype
== SVP64_ETYPE_EXTRA2
)
1260 /* range is r0-r127 in increments of 2 (r0 r2 ... r126) */
1261 svp64_raise_if ( ((sv_extra
& 1) != 0),
1262 "vector register cannot fit into EXTRA2");
1263 sv_extra
= (0x2 | (sv_extra
>> 1));
1267 /* range is r0-r63 in increments of 1 */
1268 svp64_raise_if ( ((sv_extra
>> 1) != 0),
1269 "scalar register cannot fit into EXTRA2");
1275 /* EXTRA3 vector bit needs marking */
1279 svp64_remap_extra (svp64
, opindex
, sv_extra
);
1285 svp64_remap_gpr (struct svp64_ctx
*svp64
, int64_t value
,
1286 ppc_opindex_t opindex
, bool vector
)
1288 return svp64_remap_reg (svp64
, value
, opindex
, vector
);
1292 svp64_remap_fpr (struct svp64_ctx
*svp64
, int64_t value
,
1293 ppc_opindex_t opindex
, bool vector
)
1295 return svp64_remap_reg (svp64
, value
, opindex
, vector
);
1299 svp64_remap_cr (struct svp64_ctx
*svp64
, int64_t value
,
1300 ppc_opindex_t opindex
, bool vector
, bool cr_bit
)
1306 svp64_raise_if (((value
< 0) || (value
> 127)),
1307 "register does not fit the expected range 0..127");
1308 field
= (uint32_t)value
;
1312 subfield
= (field
& 0x3);
1318 /* cut into 3-bits 4-bits FFF SSSS but will cut 2 zeros off later */
1319 sv_extra
= (field
& 0xf);
1324 /* cut into 2-bits 3-bits SS FFF */
1325 sv_extra
= (field
>> 3);
1329 if (svp64
->desc
->etype
== SVP64_ETYPE_EXTRA2
)
1333 svp64_raise_if (((sv_extra
& 0x7) != 0),
1334 "vector CR cannot fit into EXTRA2");
1335 sv_extra
= (0x2 | (sv_extra
>> 3));
1339 svp64_raise_if (((sv_extra
>> 1) != 0),
1340 "scalar CR cannot fit into EXTRA2");
1348 svp64_raise_if (((sv_extra
& 0x3) != 0),
1349 "vector CR cannot fit into EXTRA3");
1350 sv_extra
= (0x4 | (sv_extra
>> 2));
1354 svp64_raise_if (((sv_extra
>> 2) != 0),
1355 "scalar CR cannot fit into EXTRA3");
1361 field
= ((field
<< 2) | subfield
);
1363 svp64_remap_extra (svp64
, opindex
, sv_extra
);
1369 svp64_remap (struct svp64_ctx
*ctx
, int64_t value
,
1370 const struct powerpc_operand
*operand
, bool vector
)
1372 const ppc_opindex_t opindex
= (ppc_opindex_t
)(operand
- powerpc_operands
);
1374 if ((operand
->flags
& (PPC_OPERAND_GPR
| PPC_OPERAND_GPR_0
)) != 0)
1375 return svp64_remap_gpr (ctx
, value
, opindex
, vector
);
1376 else if ((operand
->flags
& PPC_OPERAND_FPR
) != 0)
1377 return svp64_remap_fpr (ctx
, value
, opindex
, vector
);
1378 else if ((operand
->flags
& (PPC_OPERAND_CR_BIT
| PPC_OPERAND_CR_REG
)) != 0)
1380 bool cr_bit
= ((operand
->flags
& PPC_OPERAND_CR_BIT
) != 0);
1382 return svp64_remap_cr (ctx
, value
, opindex
, vector
, cr_bit
);
1389 svp64_assemble (char *str
)
1391 struct svp64_ctx svp64
;
1393 if (setjmp (svp64_exception
) != 0)
1396 memset (&svp64
, 0, sizeof (svp64
));
1398 svp64_decode (str
, &svp64
);
1399 svp64_validate_and_fix (&svp64
);
1401 svp64_insn_set_prefix_po (&svp64
.insn
, 0x1);
1402 svp64_insn_set_prefix_id (&svp64
.insn
, 0x3);
1404 svp64_insn_set_prefix_rm_mode (&svp64
.insn
, svp64
.mode
);
1405 if (svp64
.desc
->ptype
== SVP64_PTYPE_P2
)
1406 svp64_insn_set_prefix_rm_smask (&svp64
.insn
, svp64
.smask
);
1407 svp64_insn_set_prefix_rm_mmode (&svp64
.insn
, svp64
.mmode
);
1408 svp64_insn_set_prefix_rm_mask (&svp64
.insn
, svp64
.pmask
);
1409 svp64_insn_set_prefix_rm_subvl (&svp64
.insn
, svp64
.subvl
);
1410 svp64_insn_set_prefix_rm_ewsrc (&svp64
.insn
, svp64
.srcwid
);
1411 svp64_insn_set_prefix_rm_elwidth (&svp64
.insn
, svp64
.destwid
);
1413 ppc_assemble (str
, &svp64
);