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
31 enum svp64_predicate
{
33 SVP64_PREDICATE_1BIT_R3
,
35 SVP64_PREDICATE_R3_INV
,
37 SVP64_PREDICATE_R10_INV
,
39 SVP64_PREDICATE_R30_INV
,
43 SVP64_PREDICATE_GE
= SVP64_PREDICATE_NL
,
46 SVP64_PREDICATE_LE
= SVP64_PREDICATE_NG
,
50 SVP64_PREDICATE_UN
= SVP64_PREDICATE_SO
,
52 SVP64_PREDICATE_NU
= SVP64_PREDICATE_NS
,
55 SVP64_PREDICATE_RC1_INV
,
59 svp64_operand (expressionS
*exp
)
64 char *origin
= input_line_pointer
;
66 if (input_line_pointer
[0] == '*')
69 if (ISDIGIT (input_line_pointer
[1]))
71 input_line_pointer
[0] = 'r';
77 else if (input_line_pointer
[0] == '^')
83 if (!vector
&& !compat
&& !reg_names_p
&&
84 (input_line_pointer
[0] != '%' || !ISALPHA (input_line_pointer
[1])))
87 if (!compat
&& (*input_line_pointer
== '%'))
90 ppc_operand_common (exp
, svp64_regs
, svp64_num_regs
);
92 if (exp
->X_op
== O_absent
)
93 input_line_pointer
= origin
;
94 else if (exp
->X_op
== O_register
)
98 if (exp
->X_add_number
== 3)
100 exp
->X_op
= O_predicate
;
101 exp
->X_add_number
= SVP64_PREDICATE_1BIT_R3
;
104 exp
->X_op
= O_illegal
;
107 exp
->X_op
= O_vector
;
109 else if ((exp
->X_op
== O_constant
) && vector
)
110 exp
->X_op
= O_vector
;
117 svp64_special_expr (expressionS
*exp
)
119 return ((exp
->X_op
== O_vector
) || (exp
->X_op
== O_predicate
));
122 static jmp_buf svp64_exception
;
124 #define svp64_raise(...) \
126 as_bad (__VA_ARGS__); \
127 longjmp (svp64_exception, 1); \
130 #define svp64_raise_if(COND, ...) \
133 svp64_raise (__VA_ARGS__); \
136 static htab_t svp64_hash
;
139 svp64_setup_records (void)
141 const struct svp64_record
*record
;
142 const struct svp64_record
*records_end
;
144 svp64_hash
= str_htab_create ();
146 records_end
= (svp64_records
+ svp64_nr_records
);
147 for (record
= svp64_records
; record
< records_end
; ++record
)
149 const struct svp64_desc
*desc
= &record
->desc
;
150 const char *name
= (record
->name
+ (sizeof ("sv.") - 1));
152 if (str_hash_insert (svp64_hash
, name
, desc
, 0) != NULL
)
153 as_fatal (_("duplicate %s"), name
);
157 #define SVP64_SEP '/'
160 svp64_expression (char *str
, expressionS
*exp
)
164 char *str_head
= str
;
165 char *old_ilp
= input_line_pointer
;
167 memset (exp
, 0, sizeof *exp
);
169 while (! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
176 input_line_pointer
= str
;
180 input_line_pointer
= old_ilp
;
183 return ((exp
->X_op
== O_absent
) ? str_head
: str_tail
);
186 struct svp64_predicate_cr_map
{
188 unsigned int len
: 3;
191 #define SVP64_PREDICATE_CR_MAP(STR, ID) \
192 { STR, (sizeof (STR) - 1), ID }
195 svp64_parse_predicate_cr (const char *name
, expressionS
*exp
)
198 const char *str
= name
;
199 static const struct svp64_predicate_cr_map table
[] = {
200 SVP64_PREDICATE_CR_MAP ("lt", SVP64_PREDICATE_LT
),
201 SVP64_PREDICATE_CR_MAP ("nl", SVP64_PREDICATE_NL
),
202 SVP64_PREDICATE_CR_MAP ("ge", SVP64_PREDICATE_GE
),
203 SVP64_PREDICATE_CR_MAP ("gt", SVP64_PREDICATE_GT
),
204 SVP64_PREDICATE_CR_MAP ("ng", SVP64_PREDICATE_NG
),
205 SVP64_PREDICATE_CR_MAP ("le", SVP64_PREDICATE_LE
),
206 SVP64_PREDICATE_CR_MAP ("eq", SVP64_PREDICATE_EQ
),
207 SVP64_PREDICATE_CR_MAP ("ne", SVP64_PREDICATE_NE
),
208 SVP64_PREDICATE_CR_MAP ("so", SVP64_PREDICATE_SO
),
209 SVP64_PREDICATE_CR_MAP ("un", SVP64_PREDICATE_UN
),
210 SVP64_PREDICATE_CR_MAP ("ns", SVP64_PREDICATE_NS
),
211 SVP64_PREDICATE_CR_MAP ("nu", SVP64_PREDICATE_NU
),
214 for (i
= 0; i
< sizeof (table
) / sizeof (table
[0]); ++i
)
216 const struct svp64_predicate_cr_map
*entry
= &table
[i
];
218 if (strncmp (str
, entry
->str
, entry
->len
) != 0)
222 if (! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
228 exp
->X_op
= O_predicate
;
229 exp
->X_add_number
= entry
->id
;
238 svp64_parse_predicate_RC1 (const char *name
, expressionS
*exp
)
240 if (strcmp (name
, "RC1") == 0)
242 exp
->X_op
= O_predicate
;
243 exp
->X_add_number
= SVP64_PREDICATE_RC1
;
251 svp64_parse_name (const char *name
, expressionS
*exp
, enum expr_mode mode
)
253 exp
->X_op
= O_absent
;
254 exp
->X_op_symbol
= NULL
;
255 exp
->X_add_symbol
= NULL
;
257 if ((svp64_parse_predicate_cr (name
, exp
)
258 || svp64_parse_predicate_RC1 (name
, exp
)) == 0)
259 ppc_parse_name_common (name
, exp
, mode
, false, svp64_regs
, svp64_num_regs
);
263 svp64_decode_predicate (char *str
, bool *cr
, unsigned int *mask
)
269 str
= svp64_expression (str
, &exp
);
272 expressionS
*sym_exp
= NULL
;
273 static const struct {
275 unsigned int mask
: 3 + 2; /* 3-bit plus RC1 */
277 /* SVP64_PREDICATE_1BIT_R3 */ {0, 1},
278 /* SVP64_PREDICATE_R3 */ {0, 2},
279 /* SVP64_PREDICATE_R3_INV */ {0, 3},
280 /* SVP64_PREDICATE_R10 */ {0, 4},
281 /* SVP64_PREDICATE_R10_INV */ {0, 5},
282 /* SVP64_PREDICATE_R30 */ {0, 6},
283 /* SVP64_PREDICATE_R30_INV */ {0, 7},
284 /* SVP64_PREDICATE_LT */ {1, 0},
285 /* SVP64_PREDICATE_NL */ {1, 1},
286 /* SVP64_PREDICATE_GT */ {1, 2},
287 /* SVP64_PREDICATE_NG */ {1, 3},
288 /* SVP64_PREDICATE_EQ */ {1, 4},
289 /* SVP64_PREDICATE_NE */ {1, 5},
290 /* SVP64_PREDICATE_SO */ {1, 6},
291 /* SVP64_PREDICATE_NS */ {1, 7},
292 /* {SVP64_PREDICATE_RC1*/ {0, SVP64_RC1_ACTIVE
},
293 /* SVP64_PREDICATE_RC1_INV */ {0, SVP64_RC1_INVERT
},
295 enum svp64_predicate predicate
;
297 if (exp
.X_add_symbol
)
298 sym_exp
= symbol_get_value_expression (exp
.X_add_symbol
);
300 if ((exp
.X_op
== O_register
) &&
301 ((exp
.X_add_number
== 3)
302 || (exp
.X_add_number
== 10)
303 || (exp
.X_add_number
== 30)))
305 exp
.X_op
= O_predicate
;
306 if (exp
.X_add_number
== 3)
307 exp
.X_add_number
= SVP64_PREDICATE_R3
;
308 else if (exp
.X_add_number
== 10)
309 exp
.X_add_number
= SVP64_PREDICATE_R10
;
310 else if (exp
.X_add_number
== 30)
311 exp
.X_add_number
= SVP64_PREDICATE_R30
;
313 else if ((exp
.X_op
== O_bit_not
) && (sym_exp
!= NULL
))
315 if (sym_exp
->X_op
== O_register
)
317 if (sym_exp
->X_add_number
== 3)
318 exp
.X_add_number
= SVP64_PREDICATE_R3_INV
;
319 else if (sym_exp
->X_add_number
== 10)
320 exp
.X_add_number
= SVP64_PREDICATE_R10_INV
;
321 else if (sym_exp
->X_add_number
== 30)
322 exp
.X_add_number
= SVP64_PREDICATE_R30_INV
;
324 else if ((sym_exp
->X_op
== O_predicate
)
325 && (sym_exp
->X_add_number
== SVP64_PREDICATE_RC1
))
326 exp
.X_add_number
= SVP64_PREDICATE_RC1_INV
;
328 else if (exp
.X_op
!= O_predicate
)
331 predicate
= (enum svp64_predicate
)exp
.X_add_number
;
332 *cr
= (table
[predicate
].cr
? true : false);
333 *mask
= table
[predicate
].mask
;
341 struct svp64_decoder
{
342 char *(*call
)(char *str
, struct svp64_ctx
*svp64
);
346 #define SVP64_DECODER(STR, CALL) \
347 { CALL, STR, (sizeof (STR) - 1) }
350 svp64_decode_m (char *str
, struct svp64_ctx
*svp64
)
357 str
+= (sizeof ("m=") - 1);
358 iter
= svp64_decode_predicate (str
, &cr
, &pmask
);
359 if (!iter
|| ((pmask
& SVP64_RC1_ACTIVE
) != 0))
360 svp64_raise (_("unrecognized mode: `%s'"), str
);
362 pmmode
= (cr
? 1 : 0);
363 svp64
->pmmode
= pmmode
;
364 svp64
->pmask
= pmask
;
365 svp64
->smmode
= pmmode
;
366 svp64
->smask
= pmask
;
367 svp64
->mmode
= pmmode
;
368 svp64
->mask_m_specified
= 1;
374 svp64_decode_dm (char *str
, struct svp64_ctx
*svp64
)
381 str
+= (sizeof ("dm=") - 1);
382 iter
= svp64_decode_predicate (str
, &cr
, &pmask
);
383 if (!iter
|| ((pmask
& SVP64_RC1_ACTIVE
) != 0))
384 svp64_raise (_("unrecognized mode: `%s'"), str
);
386 pmmode
= (cr
? 1 : 0);
387 svp64
->pmmode
= pmmode
;
388 svp64
->pmask
= pmask
;
389 svp64
->mmode
= pmmode
;
390 svp64
->has_pmask
= 1;
396 svp64_decode_sm (char *str
, struct svp64_ctx
*svp64
)
403 str
+= (sizeof ("sm=") - 1);
404 iter
= svp64_decode_predicate (str
, &cr
, &smask
);
405 if (!iter
|| ((smask
& SVP64_RC1_ACTIVE
) != 0))
406 svp64_raise (_("unrecognized mode: `%s'"), str
);
408 smmode
= (cr
? 1 : 0);
409 svp64
->smmode
= smmode
;
410 svp64
->smask
= smask
;
411 svp64
->mmode
= smmode
;
412 svp64
->has_smask
= 1;
418 svp64_decode_vec (char *str
, struct svp64_ctx
*svp64
)
422 str
+= (sizeof ("vec") - 1);
423 if ( ISSPACE (*str
) || *str
== SVP64_SEP
|| *str
== '\0')
427 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
450 struct svp64_width_map
{
452 unsigned int len
: 2;
453 unsigned int num
: 6;
454 unsigned int width
: 8;
456 #define SVP64_WIDTH_MAP(NUM, WIDTH) \
457 { #NUM, (sizeof (#NUM) - 1), NUM, WIDTH }
460 svp64_decode_width (char *str
, unsigned int *width
)
465 static const struct svp64_width_map table
[] = {
466 SVP64_WIDTH_MAP (8, 3),
467 SVP64_WIDTH_MAP (16, 2),
468 SVP64_WIDTH_MAP (32, 1),
472 str
= svp64_expression (str
, &exp
);
473 if ((str
!= origin
) && (exp
.X_op
== O_constant
))
475 for (i
= 0; i
< (sizeof (table
) / sizeof (table
[0])); ++i
)
477 const struct svp64_width_map
*entry
= &table
[i
];
479 if (entry
->num
== exp
.X_add_number
)
481 *width
= entry
->width
;
491 svp64_decode_w (char *str
, struct svp64_ctx
*svp64
)
496 str
+= (sizeof ("w=") - 1);
497 iter
= svp64_decode_width (str
, &width
);
499 svp64_raise (_("unrecognized mode: `%s'"), str
);
501 svp64
->srcwid
= width
;
502 svp64
->destwid
= width
;
508 svp64_decode_dw (char *str
, struct svp64_ctx
*svp64
)
513 str
+= (sizeof ("dw=") - 1);
514 iter
= svp64_decode_width (str
, &width
);
516 svp64_raise (_("unrecognized mode: `%s'"), str
);
518 svp64
->destwid
= width
;
524 svp64_decode_sw (char *str
, struct svp64_ctx
*svp64
)
529 str
+= (sizeof ("sw=") - 1);
530 iter
= svp64_decode_width (str
, &width
);
532 svp64_raise (_("unrecognized mode: `%s'"), str
);
534 svp64
->srcwid
= width
;
540 svp64_decode_els (char *str
, struct svp64_ctx
*svp64
)
542 str
+= (sizeof ("els") - 1);
543 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
546 svp64
->ldst_elstride
= 1;
554 svp64_decode_sat (char *str
, struct svp64_ctx
*svp64
)
558 str
+= (sizeof ("sat") - 1);
559 if ((*str
!= 's') && (*str
!= 'u'))
563 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
566 if (svp64
->sv_mode_explicit
)
567 svp64_raise (_("SV mode conflict: `%s'"), str
);
569 svp64
->sv_mode_explicit
= 1;
571 svp64
->sat
= (mode
== 's');
579 svp64_decode_sz (char *str
, struct svp64_ctx
*svp64
)
581 str
+= (sizeof ("sz") - 1);
582 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
593 svp64_decode_dz (char *str
, struct svp64_ctx
*svp64
)
595 str
+= (sizeof ("dz") - 1);
596 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
607 svp64_decode_ff (char *str
, struct svp64_ctx
*svp64
)
613 str
+= (sizeof ("ff=") - 1);
614 if (svp64
->sv_mode_explicit
)
615 svp64_raise (_("SV mode conflict: `%s'"), str
);
617 iter
= svp64_decode_predicate (str
, &cr
, &mask
);
618 if (!iter
|| !(cr
|| ((mask
& SVP64_RC1_ACTIVE
) != 0)))
619 svp64_raise (_("unrecognized mode: `%s'"), str
);
621 svp64
->sv_mode_explicit
= 1;
622 svp64
->sv_mode
= 0x1;
629 svp64_decode_pr (char *str
, struct svp64_ctx
*svp64
)
635 str
+= (sizeof ("pr=") - 1);
636 if (svp64
->sv_mode_explicit
)
637 svp64_raise (_("SV mode conflict: `%s'"), str
);
639 iter
= svp64_decode_predicate (str
, &cr
, &mask
);
640 if (!iter
|| !(cr
|| ((mask
& SVP64_RC1_ACTIVE
) != 0)))
641 svp64_raise (_("unrecognized mode: `%s'"), str
);
643 svp64
->sv_mode_explicit
= 1;
644 svp64
->sv_mode
= 0x3;
651 svp64_decode_mr (char *str
, struct svp64_ctx
*svp64
)
653 str
+= (sizeof ("mr") - 1);
654 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
657 svp64
->sv_mode_explicit
= 1;
667 svp64_decode_mrr (char *str
, struct svp64_ctx
*svp64
)
669 str
+= (sizeof ("mrr") - 1);
670 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
673 svp64
->sv_mode_explicit
= 1;
684 svp64_decode_crm (char *str
, struct svp64_ctx
*svp64
)
686 str
+= (sizeof ("crm") - 1);
687 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
690 svp64
->sv_mode_explicit
= 1;
700 svp64_decode_mode (char *str
, struct svp64_ctx
*svp64
)
703 static const struct svp64_decoder table
[] = {
704 SVP64_DECODER ("m=" , svp64_decode_m
),
705 SVP64_DECODER ("dm=" , svp64_decode_dm
),
706 SVP64_DECODER ("sm=" , svp64_decode_sm
),
707 SVP64_DECODER ("vec2", svp64_decode_vec
),
708 SVP64_DECODER ("vec3", svp64_decode_vec
),
709 SVP64_DECODER ("vec4", svp64_decode_vec
),
710 SVP64_DECODER ("w=" , svp64_decode_w
),
711 SVP64_DECODER ("dw=" , svp64_decode_dw
),
712 SVP64_DECODER ("sw=" , svp64_decode_sw
),
713 SVP64_DECODER ("els" , svp64_decode_els
),
714 SVP64_DECODER ("sats", svp64_decode_sat
),
715 SVP64_DECODER ("satu", svp64_decode_sat
),
716 SVP64_DECODER ("sz" , svp64_decode_sz
),
717 SVP64_DECODER ("dz" , svp64_decode_dz
),
718 SVP64_DECODER ("ff=" , svp64_decode_ff
),
719 SVP64_DECODER ("pr=" , svp64_decode_pr
),
720 SVP64_DECODER ("mr" , svp64_decode_mr
),
721 SVP64_DECODER ("mrr" , svp64_decode_mrr
),
722 SVP64_DECODER ("crm" , svp64_decode_crm
),
725 for (i
= 0; i
< sizeof (table
) / sizeof (table
[0]); ++i
)
727 const struct svp64_decoder
*entry
= &table
[i
];
729 if (strncmp (str
, entry
->str
, entry
->len
) == 0)
730 return entry
->call (str
, svp64
);
736 struct svp64_str_map
{
740 #define SVP64_STR_MAP(STR) \
741 { STR, (sizeof (STR) - 1) }
744 svp64_str_map_cmp(const char *str
, size_t len
,
745 const struct svp64_str_map
*map
, size_t cnt
)
749 for (i
= 0; i
< cnt
; ++i
) {
750 const struct svp64_str_map
*entry
= &map
[i
];
752 if ((entry
->len
== len
) && (memcmp(entry
->str
, str
, len
) == 0))
758 #define SVP64_STR_MAP_CMP(STR, LEN, MAP) \
759 svp64_str_map_cmp(STR, LEN, MAP, (sizeof (MAP) / sizeof (*MAP)))
762 svp64_is_ld(const char *str
, size_t len
)
764 static const struct svp64_str_map table
[] = {
766 SVP64_STR_MAP ("lbarx"),
767 SVP64_STR_MAP ("lbz"),
768 SVP64_STR_MAP ("lbzu"),
769 SVP64_STR_MAP ("lbzux"),
770 SVP64_STR_MAP ("lbzx"),
772 SVP64_STR_MAP ("ld"),
773 SVP64_STR_MAP ("ldarx"),
774 SVP64_STR_MAP ("ldbrx"),
775 SVP64_STR_MAP ("ldu"),
776 SVP64_STR_MAP ("ldux"),
777 SVP64_STR_MAP ("ldx"),
779 SVP64_STR_MAP ("lfs"),
780 SVP64_STR_MAP ("lfsx"),
781 SVP64_STR_MAP ("lfsu"),
782 SVP64_STR_MAP ("lfsux"),
784 SVP64_STR_MAP ("lfd"),
785 SVP64_STR_MAP ("lfdx"),
786 SVP64_STR_MAP ("lfdu"),
787 SVP64_STR_MAP ("lfdux"),
788 SVP64_STR_MAP ("lfiwzx"),
789 SVP64_STR_MAP ("lfiwax"),
791 SVP64_STR_MAP ("lha"),
792 SVP64_STR_MAP ("lharx"),
793 SVP64_STR_MAP ("lhau"),
794 SVP64_STR_MAP ("lhaux"),
795 SVP64_STR_MAP ("lhax"),
796 SVP64_STR_MAP ("lhbrx"),
797 SVP64_STR_MAP ("lhz"),
798 SVP64_STR_MAP ("lhzu"),
799 SVP64_STR_MAP ("lhzux"),
800 SVP64_STR_MAP ("lhzx"),
802 SVP64_STR_MAP ("lwa"),
803 SVP64_STR_MAP ("lwarx"),
804 SVP64_STR_MAP ("lwaux"),
805 SVP64_STR_MAP ("lwax"),
806 SVP64_STR_MAP ("lwbrx"),
807 SVP64_STR_MAP ("lwz"),
808 SVP64_STR_MAP ("lwzcix"),
809 SVP64_STR_MAP ("lwzu"),
810 SVP64_STR_MAP ("lwzux"),
811 SVP64_STR_MAP ("lwzx"),
814 return SVP64_STR_MAP_CMP(str
, len
, table
);
818 svp64_is_st(const char *str
, size_t len
)
820 static const struct svp64_str_map table
[] = {
822 SVP64_STR_MAP ("stb"),
823 SVP64_STR_MAP ("stbcix"),
824 SVP64_STR_MAP ("stbcx"),
825 SVP64_STR_MAP ("stbu"),
826 SVP64_STR_MAP ("stbux"),
827 SVP64_STR_MAP ("stbx"),
829 SVP64_STR_MAP ("std"),
830 SVP64_STR_MAP ("stdbrx"),
831 SVP64_STR_MAP ("stdcx"),
832 SVP64_STR_MAP ("stdu"),
833 SVP64_STR_MAP ("stdux"),
834 SVP64_STR_MAP ("stdx"),
835 /* FP store single */
836 SVP64_STR_MAP ("stfs"),
837 SVP64_STR_MAP ("stfsx"),
838 SVP64_STR_MAP ("stfsu"),
839 SVP64_STR_MAP ("stfux"),
840 /* FP store double */
841 SVP64_STR_MAP ("stfd"),
842 SVP64_STR_MAP ("stfdx"),
843 SVP64_STR_MAP ("stfdu"),
844 SVP64_STR_MAP ("stfdux"),
845 SVP64_STR_MAP ("stfiwx"),
847 SVP64_STR_MAP ("sth"),
848 SVP64_STR_MAP ("sthbrx"),
849 SVP64_STR_MAP ("sthcx"),
850 SVP64_STR_MAP ("sthu"),
851 SVP64_STR_MAP ("sthux"),
852 SVP64_STR_MAP ("sthx"),
854 SVP64_STR_MAP ("stw"),
855 SVP64_STR_MAP ("stwbrx"),
856 SVP64_STR_MAP ("stwcx"),
857 SVP64_STR_MAP ("stwu"),
858 SVP64_STR_MAP ("stwux"),
859 SVP64_STR_MAP ("stwx"),
862 return SVP64_STR_MAP_CMP(str
, len
, table
);
866 svp64_is_bc(const char *str
, size_t len
)
868 static const struct svp64_str_map table
[] = {
869 SVP64_STR_MAP ("bc"),
870 SVP64_STR_MAP ("bclr"),
873 return SVP64_STR_MAP_CMP(str
, len
, table
);
877 svp64_is_rc (const char *str
, size_t len
)
879 return (str
[len
- 1] == '.');
883 svp64_decode (char *str
, struct svp64_ctx
*svp64
)
892 str
+= (sizeof ("sv.") - 1);
893 if (! ISALPHA (*str
))
894 svp64_raise (_("unrecognized opcode: `%s'"), str
);
897 for (; ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0'; ++str
)
899 opclen
= (str
- opc
);
903 if (svp64_is_rc (opc
, opclen
))
906 if (svp64_is_ld (opc
, opclen
))
907 svp64
->type
= SVP64_TYPE_LD
;
908 else if (svp64_is_st (opc
, opclen
))
909 svp64
->type
= SVP64_TYPE_ST
;
910 else if (svp64_is_bc (opc
, opclen
))
911 svp64
->type
= SVP64_TYPE_BC
;
913 for (; (iter
= svp64_decode_mode (str
, svp64
)) != NULL
; str
= iter
)
916 argslen
= strlen (args
);
918 svp64
->desc
= (const struct svp64_desc
*) str_hash_find (svp64_hash
, opc
);
920 svp64_raise (_("unrecognized opcode: `%s'"), str
);
923 memmove (iter
, opc
, opclen
);
927 memmove (iter
, args
, argslen
);
933 svp64_validate_and_fix_mode_bc (struct svp64_ctx
*svp64
)
936 * Create mode and (overridden) src/dst widths.
937 * TODO: sanity-check BC modes.
939 svp64
->sv_mode
= ((svp64
->bc_svstep
<< SVP64_MODE_MOD2_MSB
) |
940 (svp64
->bc_vlset
<< SVP64_MODE_MOD2_LSB
) |
941 (svp64
->bc_snz
<< SVP64_MODE_BC_SNZ
));
942 svp64
->srcwid
= ((svp64
->bc_vsb
<< 1) | svp64
->bc_lru
);
943 svp64
->destwid
= ((svp64
->bc_lru
<< 1) | svp64
->bc_all
);
947 svp64_validate_and_fix_mode_mr (struct svp64_ctx
*svp64
)
949 svp64
->mode
|= (1U << SVP64_MODE_REDUCE
);
950 svp64_raise_if (svp64
->dst_zero
,
951 "dest-zero not allowed in mr mode");
954 svp64
->mode
|= (1U << SVP64_MODE_RG
);
958 svp64
->mode
|= (1U << SVP64_MODE_CRM
);
959 svp64_raise_if (!svp64
->rc
, "CRM only allowed when Rc=1");
963 * Bit of weird encoding to jam zero-pred or SVM mode in.
964 * SVM mode can be enabled only when SUBVL=2/3/4 (vec2/3/4)
966 if (svp64
->subvl
== 0)
967 svp64
->mode
|= (svp64
->dst_zero
<< SVP64_MODE_DZ
);
971 svp64_validate_and_fix_mode_ff(struct svp64_ctx
*svp64
)
973 svp64_raise_if (svp64
->src_zero
,
974 "dest-zero not allowed in ff mode");
976 if (svp64
->ff
& SVP64_RC1_ACTIVE
)
978 svp64
->mode
|= (1U << SVP64_MODE_RC1
);
979 svp64
->mode
|= (svp64
->dst_zero
<< SVP64_MODE_DZ
);
980 svp64_raise_if (svp64
->rc
,
981 "ffirst RC1/~RC1 only possible when Rc=0");
982 if (svp64
->ff
& SVP64_RC1_INVERT
)
983 svp64
->mode
|= (1U << SVP64_MODE_INV
);
987 svp64_raise_if (svp64
->dst_zero
,
988 "dst-zero not allowed in ffirst BO");
989 svp64_raise_if (!svp64
->rc
,
990 "ffirst BO only possible when Rc=1");
991 svp64
->mode
|= (svp64
->ff
<< SVP64_MODE_BO_LSB
);
996 svp64_validate_and_fix_mode_sat(struct svp64_ctx
*svp64
)
998 svp64
->mode
|= (svp64
->src_zero
<< SVP64_MODE_SZ
);
999 svp64
->mode
|= (svp64
->dst_zero
<< SVP64_MODE_DZ
);
1000 svp64
->mode
|= (svp64
->sat
<< SVP64_MODE_N
);
1004 svp64_validate_and_fix_mode_pr(struct svp64_ctx
*svp64
)
1006 svp64_raise_if (svp64
->src_zero
,
1007 "dest-zero not allowed in pr mode");
1009 if (svp64
->pr
& SVP64_RC1_ACTIVE
)
1011 svp64
->mode
|= (1U << SVP64_MODE_RC1
);
1012 svp64
->mode
|= (svp64
->dst_zero
<< SVP64_MODE_DZ
);
1013 svp64_raise_if (svp64
->rc
,
1014 "pr-mode RC1/~RC1 only possible when Rc=0");
1015 if (svp64
->pr
& SVP64_RC1_INVERT
)
1016 svp64
->mode
|= (1U << SVP64_MODE_INV
);
1020 svp64_raise_if (svp64
->dst_zero
,
1021 "dst-zero not allowed in pr-mode BO");
1022 svp64_raise_if (!svp64
->rc
,
1023 "pr-mode BO only possible when Rc=1");
1024 svp64
->mode
|= (svp64
->pr
<< SVP64_MODE_BO_LSB
);
1029 svp64_validate_and_fix_mode_explicit(struct svp64_ctx
*svp64
)
1031 static void (*const table
[])(struct svp64_ctx
*svp64
) = {
1032 svp64_validate_and_fix_mode_mr
,
1033 svp64_validate_and_fix_mode_ff
,
1034 svp64_validate_and_fix_mode_sat
,
1035 svp64_validate_and_fix_mode_pr
,
1038 return table
[svp64
->sv_mode
] (svp64
);
1042 svp64_validate_and_fix_mode_normal (struct svp64_ctx
*svp64
)
1044 svp64
->mode
|= (svp64
->src_zero
<< SVP64_MODE_SZ
);
1045 svp64
->mode
|= (svp64
->dst_zero
<< SVP64_MODE_DZ
);
1046 if ((svp64
->type
== SVP64_TYPE_LD
) ||
1047 (svp64
->type
== SVP64_TYPE_ST
))
1049 /* TODO: for now, LD/ST-indexed is ignored. */
1050 svp64
->mode
|= (svp64
->ldst_elstride
<< SVP64_MODE_ELS_NORMAL
);
1055 * TODO: reduce and subvector mode.
1056 * 00 1 dz CRM reduce mode (mr), SUBVL=1
1057 * 00 1 SVM CRM subvector reduce mode, SUBVL>1
1064 * There are 4 different modes, here, which will be partly-merged-in:
1065 * is_ldst is merged in with "normal", but is_bc is so different it's
1066 * done separately. Likewise is_cr (when it is done).
1068 * "normal" arithmetic: https://libre-soc.org/openpower/sv/normal
1069 * | 0-1 | 2 | 3 4 | description |
1070 * | --- | --- |---------|------------------------------------------ |
1071 * | 00 | 0 | dz sz | normal mode |
1072 * | 00 | 1 | 0 RG | scalar reduce mode (mr), SUBVL=1 |
1073 * | 00 | 1 | 1 / | parallel reduce mode (mr), SUBVL=1 |
1074 * | 00 | 1 | SVM RG | subvector reduce mode, SUBVL>1 |
1075 * | 01 | inv | CR-bit | Rc=1: ffirst CR sel |
1076 * | 01 | inv | VLi RC1 | Rc=0: ffirst z/nonz |
1077 * | 10 | N | dz sz | sat mode: N=0/1 u/s |
1078 * | 11 | inv | CR-bit | Rc=1: pred-result CR sel |
1079 * | 11 | inv | dz RC1 | Rc=0: pred-result z/nonz |
1081 * LD/ST-immediate: https://libre-soc.org/openpower/sv/ldst
1082 * | 0-1 | 2 | 3 4 | description |
1083 * | --- | --- |---------|------------------------------------------ |
1084 * | 00 | 0 | dz els | normal mode |
1085 * | 00 | 1 | dz shf | shift mode |
1086 * | 01 | inv | CR-bit | Rc=1: ffirst CR sel |
1087 * | 01 | inv | els RC1 | Rc=0: ffirst z/nonz |
1088 * | 10 | N | dz els | sat mode: N=0/1 u/s |
1089 * | 11 | inv | CR-bit | Rc=1: pred-result CR sel |
1090 * | 11 | inv | els RC1 | Rc=0: pred-result z/nonz |
1092 * LD/ST-indexed (RA+RB): https://libre-soc.org/openpower/sv/ldst
1093 * | 0-1 | 2 | 3 4 | description |
1094 * | --- | --- |---------|------------------------------------------ |
1095 * | 00 | SEA | dz sz | normal mode |
1096 * | 01 | SEA | dz sz | Strided (scalar only source) |
1097 * | 10 | N | dz sz | sat mode: N=0/1 u/s |
1098 * | 11 | inv | CR-bit | Rc=1: pred-result CR sel |
1099 * | 11 | inv | dz RC1 | Rc=0: pred-result z/nonz |
1101 * ...and branches/cr_ops are still in development.
1104 svp64_validate_and_fix_mode (struct svp64_ctx
*svp64
)
1106 if (svp64
->type
== SVP64_TYPE_BC
)
1107 svp64_validate_and_fix_mode_bc (svp64
);
1108 else if (svp64
->sv_mode_explicit
)
1109 svp64_validate_and_fix_mode_explicit (svp64
);
1111 svp64_validate_and_fix_mode_normal (svp64
);
1115 svp64_validate_and_fix (struct svp64_ctx
*svp64
)
1117 if (svp64
->desc
->ptype
== SVP64_PTYPE_P2
)
1120 * Since m=xx takes precedence (overrides) sm=xx and dm=xx,
1121 * treat them as mutually exclusive.
1123 if (svp64
->mask_m_specified
)
1125 svp64_raise_if (svp64
->has_smask
,
1126 "cannot have both source-mask and predicate mask");
1127 svp64_raise_if (svp64
->has_pmask
,
1128 "cannot have both dest-mask and predicate mask");
1132 * Since the default is INT predication (ALWAYS), if you
1133 * specify one CR mask, you must specify both, to avoid
1134 * mixing INT and CR reg types.
1136 if (svp64
->has_pmask
&& (svp64
->pmmode
== 1))
1138 svp64_raise_if (!svp64
->has_smask
,
1139 "need explicit source-mask in CR twin predication");
1141 if (svp64
->has_smask
&& (svp64
->smmode
== 1))
1143 svp64_raise_if (!svp64
->has_pmask
,
1144 "need explicit dest-mask in CR twin predication");
1147 /* Sanity-check that 2Pred mask is same mode. */
1148 if (svp64
->has_pmask
&& svp64
->has_smask
)
1150 svp64_raise_if (svp64
->smmode
!= svp64
->pmmode
,
1151 "predicate masks mismatch: pmmode=0x%08x, smmode=0x%08x",
1152 (unsigned int)svp64
->pmmode
, (unsigned int)svp64
->smmode
);
1154 else if (svp64
->desc
->ptype
== SVP64_PTYPE_P1
)
1156 svp64_raise_if (svp64
->has_smask
,
1157 "source-mask can only be specified on Twin-predicate ops");
1158 svp64_raise_if (svp64
->has_pmask
,
1159 "dest-mask can only be specified on Twin-predicate ops");
1163 if (svp64
->src_zero
)
1165 svp64_raise_if (!svp64
->has_smask
&& !svp64
->mask_m_specified
,
1166 "src zeroing requires a source predicate");
1168 if (svp64
->dst_zero
)
1170 svp64_raise_if (!svp64
->has_pmask
&& !svp64
->mask_m_specified
,
1171 "dest zeroing requires a dest predicate");
1174 svp64_validate_and_fix_mode (svp64
);
1178 svp64_remap_extra (struct svp64_ctx
*svp64
,
1179 ppc_opindex_t opindex
, uint32_t value
)
1181 const struct svp64_extra_desc
*desc
;
1183 desc
= svp64_extra_desc (svp64
->desc
, opindex
);
1184 svp64_raise_if ((desc
== NULL
), "cannot remap EXTRA");
1186 return (*desc
->set
) (&svp64
->insn
, value
);
1190 svp64_remap_reg (struct svp64_ctx
*svp64
, int64_t value
,
1191 ppc_opindex_t opindex
, bool vector
)
1196 svp64_raise_if (((value
< 0) || (value
> 127)),
1197 "register does not fit the expected range 0..127");
1198 field
= (uint32_t)value
;
1202 /* cut into 5-bits 2-bits FFFFF SS */
1203 sv_extra
= (field
& 0x3);
1208 /* cut into 2-bits 5-bits SS FFFFF */
1209 sv_extra
= (field
>> 5);
1213 if (svp64
->desc
->etype
== SVP64_ETYPE_EXTRA2
)
1217 /* range is r0-r127 in increments of 2 (r0 r2 ... r126) */
1218 svp64_raise_if ( ((sv_extra
& 1) != 0),
1219 "vector register cannot fit into EXTRA2");
1220 sv_extra
= (0x2 | (sv_extra
>> 1));
1224 /* range is r0-r63 in increments of 1 */
1225 svp64_raise_if ( ((sv_extra
>> 1) != 0),
1226 "scalar register cannot fit into EXTRA2");
1232 /* EXTRA3 vector bit needs marking */
1236 svp64_remap_extra (svp64
, opindex
, sv_extra
);
1242 svp64_remap_gpr (struct svp64_ctx
*svp64
, int64_t value
,
1243 ppc_opindex_t opindex
, bool vector
)
1245 return svp64_remap_reg (svp64
, value
, opindex
, vector
);
1249 svp64_remap_fpr (struct svp64_ctx
*svp64
, int64_t value
,
1250 ppc_opindex_t opindex
, bool vector
)
1252 return svp64_remap_reg (svp64
, value
, opindex
, vector
);
1256 svp64_remap_cr (struct svp64_ctx
*svp64
, int64_t value
,
1257 ppc_opindex_t opindex
, bool vector
, bool cr_bit
)
1263 svp64_raise_if (((value
< 0) || (value
> 127)),
1264 "register does not fit the expected range 0..127");
1265 field
= (uint32_t)value
;
1269 subfield
= (field
& 0x3);
1275 /* cut into 3-bits 4-bits FFF SSSS but will cut 2 zeros off later */
1276 sv_extra
= (field
& 0xf);
1281 /* cut into 2-bits 3-bits SS FFF */
1282 sv_extra
= (field
>> 3);
1286 if (svp64
->desc
->etype
== SVP64_ETYPE_EXTRA2
)
1290 svp64_raise_if (((sv_extra
& 0x7) != 0),
1291 "vector CR cannot fit into EXTRA2");
1292 sv_extra
= (0x2 | (sv_extra
>> 3));
1296 svp64_raise_if (((sv_extra
>> 1) != 0),
1297 "scalar CR cannot fit into EXTRA2");
1305 svp64_raise_if (((sv_extra
& 0x3) != 0),
1306 "vector CR cannot fit into EXTRA3");
1307 sv_extra
= (0x4 | (sv_extra
>> 2));
1311 svp64_raise_if (((sv_extra
>> 2) != 0),
1312 "scalar CR cannot fit into EXTRA3");
1318 field
= ((field
<< 2) | subfield
);
1320 svp64_remap_extra (svp64
, opindex
, sv_extra
);
1326 svp64_remap (struct svp64_ctx
*ctx
, int64_t value
,
1327 const struct powerpc_operand
*operand
, bool vector
)
1329 const ppc_opindex_t opindex
= (ppc_opindex_t
)(operand
- powerpc_operands
);
1331 if ((operand
->flags
& (PPC_OPERAND_GPR
| PPC_OPERAND_GPR_0
)) != 0)
1332 return svp64_remap_gpr (ctx
, value
, opindex
, vector
);
1333 else if ((operand
->flags
& PPC_OPERAND_FPR
) != 0)
1334 return svp64_remap_fpr (ctx
, value
, opindex
, vector
);
1335 else if ((operand
->flags
& (PPC_OPERAND_CR_BIT
| PPC_OPERAND_CR_REG
)) != 0)
1337 bool cr_bit
= ((operand
->flags
& PPC_OPERAND_CR_BIT
) != 0);
1339 return svp64_remap_cr (ctx
, value
, opindex
, vector
, cr_bit
);
1346 svp64_assemble (char *str
)
1348 struct svp64_ctx svp64
;
1350 if (setjmp (svp64_exception
) != 0)
1353 memset (&svp64
, 0, sizeof (svp64
));
1355 svp64_decode (str
, &svp64
);
1356 svp64_validate_and_fix (&svp64
);
1358 svp64_insn_set_prefix_po (&svp64
.insn
, 0x1);
1359 svp64_insn_set_prefix_id (&svp64
.insn
, 0x3);
1361 svp64_insn_set_prefix_rm_mode (&svp64
.insn
, svp64
.mode
);
1362 if (svp64
.desc
->ptype
== SVP64_PTYPE_P2
)
1363 svp64_insn_set_prefix_rm_smask (&svp64
.insn
, svp64
.smask
);
1364 svp64_insn_set_prefix_rm_mmode (&svp64
.insn
, svp64
.mmode
);
1365 svp64_insn_set_prefix_rm_mask (&svp64
.insn
, svp64
.pmask
);
1366 svp64_insn_set_prefix_rm_subvl (&svp64
.insn
, svp64
.subvl
);
1367 svp64_insn_set_prefix_rm_ewsrc (&svp64
.insn
, svp64
.srcwid
);
1368 svp64_insn_set_prefix_rm_elwidth (&svp64
.insn
, svp64
.destwid
);
1370 ppc_assemble (str
, &svp64
);