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 unsigned int pmmode
: 1;
27 unsigned int pmask
: 3;
28 unsigned int smmode
: 1;
29 unsigned int smask
: 3;
30 unsigned int mmode
: 1;
31 unsigned int has_pmask
: 1;
32 unsigned int has_smask
: 1;
33 unsigned int mask_m_specified
: 1;
34 unsigned int subvl
: 2;
35 unsigned int destwid
: 2;
36 unsigned int srcwid
: 2;
37 unsigned int ldst_elstride
: 1;
38 unsigned int sv_mode_explicit
: 1;
39 unsigned int sv_mode
: 2;
41 unsigned int src_zero
: 1;
42 unsigned int dst_zero
: 1;
43 unsigned int ff
: 3 + 2; /* 3-bit plus RC1 */
44 unsigned int pr
: 3 + 2; /* 3-bit plus RC1 */
47 #define SVP64_RC1_ACTIVE (1U << 3U)
48 #define SVP64_RC1_INVERT (SVP64_RC1_ACTIVE | (1U << 4U))
50 static jmp_buf svp64_exception
;
52 #define svp64_raise(...) \
54 as_bad (__VA_ARGS__); \
55 longjmp (svp64_exception, 1); \
58 #define svp64_raise_if(COND, ...) \
61 svp64_raise (__VA_ARGS__); \
64 static htab_t svp64_hash
;
67 svp64_setup_records (void)
69 const struct svp64_record
*record
;
70 const struct svp64_record
*records_end
;
72 svp64_hash
= str_htab_create ();
74 records_end
= (svp64_records
+ svp64_nr_records
);
75 for (record
= svp64_records
; record
< records_end
; ++record
)
77 const struct svp64_desc
*desc
= &record
->desc
;
78 const char *name
= (record
->name
+ (sizeof ("sv.") - 1));
80 if (str_hash_insert (svp64_hash
, name
, desc
, 0) != NULL
)
81 as_fatal (_("duplicate %s"), name
);
87 struct svp64_predicate_map
{
91 unsigned int mask
: 3 + 2; /* 3-bit plus RC1 */
93 #define SVP64_PREDICATE_MAP(STR, MODE, MASK) \
94 { STR, (sizeof (STR) - 1), MODE, MASK }
97 svp64_decode_predicate (char *str
, bool *cr
, unsigned int *mask
)
100 static const struct svp64_predicate_map table
[] = {
102 SVP64_PREDICATE_MAP ("1<<r3", 0, 1),
103 SVP64_PREDICATE_MAP ("r3" , 0, 2),
104 SVP64_PREDICATE_MAP ("~r3" , 0, 3),
105 SVP64_PREDICATE_MAP ("r10" , 0, 4),
106 SVP64_PREDICATE_MAP ("~r10" , 0, 5),
107 SVP64_PREDICATE_MAP ("r30" , 0, 6),
108 SVP64_PREDICATE_MAP ("~r30" , 0, 7),
110 SVP64_PREDICATE_MAP ("lt" , 1, 0),
111 SVP64_PREDICATE_MAP ("nl" , 1, 1),
112 SVP64_PREDICATE_MAP ("ge" , 1, 1), /* same value as nl */
113 SVP64_PREDICATE_MAP ("gt" , 1, 2),
114 SVP64_PREDICATE_MAP ("ng" , 1, 3),
115 SVP64_PREDICATE_MAP ("le" , 1, 3), /* same value as ng */
116 SVP64_PREDICATE_MAP ("eq" , 1, 4),
117 SVP64_PREDICATE_MAP ("ne" , 1, 5),
118 SVP64_PREDICATE_MAP ("so" , 1, 6),
119 SVP64_PREDICATE_MAP ("un" , 1, 6), /* same value as so */
120 SVP64_PREDICATE_MAP ("ns" , 1, 7),
121 SVP64_PREDICATE_MAP ("nu" , 1, 7), /* same value as ns */
123 SVP64_PREDICATE_MAP ("RC1" , 0, SVP64_RC1_ACTIVE
),
124 SVP64_PREDICATE_MAP ("~RC1" , 0, SVP64_RC1_INVERT
),
127 for (i
= 0; i
< sizeof (table
) / sizeof (table
[0]); ++i
)
129 const struct svp64_predicate_map
*entry
= &table
[i
];
131 if (strncmp (str
, entry
->str
, entry
->len
) != 0)
135 if (! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
152 struct svp64_decoder
{
153 char *(*call
)(char *str
, struct svp64_ctx
*svp64
);
157 #define SVP64_DECODER(STR, CALL) \
158 { CALL, STR, (sizeof (STR) - 1) }
161 svp64_decode_m (char *str
, struct svp64_ctx
*svp64
)
168 str
+= (sizeof ("m=") - 1);
169 iter
= svp64_decode_predicate (str
, &cr
, &pmask
);
170 if (!iter
|| ((pmask
& SVP64_RC1_ACTIVE
) != 0))
171 svp64_raise (_("unrecognized mode: `%s'"), str
);
173 pmmode
= (cr
? 1 : 0);
174 svp64
->pmmode
= pmmode
;
175 svp64
->pmask
= pmask
;
176 svp64
->smmode
= pmmode
;
177 svp64
->smask
= pmask
;
178 svp64
->mmode
= pmmode
;
179 svp64
->mask_m_specified
= 1;
185 svp64_decode_dm (char *str
, struct svp64_ctx
*svp64
)
192 str
+= (sizeof ("dm=") - 1);
193 iter
= svp64_decode_predicate (str
, &cr
, &pmask
);
194 if (!iter
|| ((pmask
& SVP64_RC1_ACTIVE
) != 0))
195 svp64_raise (_("unrecognized mode: `%s'"), str
);
197 pmmode
= (cr
? 1 : 0);
198 svp64
->pmmode
= pmmode
;
199 svp64
->pmask
= pmask
;
200 svp64
->mmode
= pmmode
;
201 svp64
->has_pmask
= 1;
207 svp64_decode_sm (char *str
, struct svp64_ctx
*svp64
)
214 str
+= (sizeof ("sm=") - 1);
215 iter
= svp64_decode_predicate (str
, &cr
, &smask
);
216 if (!iter
|| ((smask
& SVP64_RC1_ACTIVE
) != 0))
217 svp64_raise (_("unrecognized mode: `%s'"), str
);
219 smmode
= (cr
? 1 : 0);
220 svp64
->smmode
= smmode
;
221 svp64
->smask
= smask
;
222 svp64
->mmode
= smmode
;
223 svp64
->has_smask
= 1;
229 svp64_decode_vec (char *str
, struct svp64_ctx
*svp64
)
233 str
+= (sizeof ("vec") - 1);
234 if ( ISSPACE (*str
) || *str
== SVP64_SEP
|| *str
== '\0')
238 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
261 struct svp64_width_map
{
266 #define SVP64_WIDTH_MAP(STR, WIDTH) \
267 { STR, (sizeof (STR) - 1), WIDTH }
270 svp64_decode_width (char *str
, unsigned int *width
)
273 static const struct svp64_width_map table
[] = {
274 SVP64_WIDTH_MAP ("8", 3),
275 SVP64_WIDTH_MAP ("16", 2),
276 SVP64_WIDTH_MAP ("32", 1),
279 for (i
= 0; i
< (sizeof (table
) / sizeof (table
[0])); ++i
)
281 const struct svp64_width_map
*entry
= &table
[i
];
283 if (strncmp (str
, entry
->str
, entry
->len
) != 0)
287 if (! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
293 *width
= entry
->width
;
304 svp64_decode_w (char *str
, struct svp64_ctx
*svp64
)
309 str
+= (sizeof ("w=") - 1);
310 iter
= svp64_decode_width (str
, &width
);
312 svp64_raise (_("unrecognized mode: `%s'"), str
);
314 svp64
->srcwid
= width
;
315 svp64
->destwid
= width
;
321 svp64_decode_dw (char *str
, struct svp64_ctx
*svp64
)
326 str
+= (sizeof ("dw=") - 1);
327 iter
= svp64_decode_width (str
, &width
);
329 svp64_raise (_("unrecognized mode: `%s'"), str
);
331 svp64
->destwid
= width
;
337 svp64_decode_sw (char *str
, struct svp64_ctx
*svp64
)
342 str
+= (sizeof ("sw=") - 1);
343 iter
= svp64_decode_width (str
, &width
);
345 svp64_raise (_("unrecognized mode: `%s'"), str
);
347 svp64
->srcwid
= width
;
353 svp64_decode_els (char *str
, struct svp64_ctx
*svp64
)
355 str
+= (sizeof ("els") - 1);
356 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
359 svp64
->ldst_elstride
= 1;
367 svp64_decode_sat (char *str
, struct svp64_ctx
*svp64
)
371 str
+= (sizeof ("sat") - 1);
372 if ((*str
!= 's') && (*str
!= 'u'))
376 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
379 if (svp64
->sv_mode_explicit
)
380 svp64_raise (_("SV mode conflict: `%s'"), str
);
382 svp64
->sv_mode_explicit
= 1;
384 svp64
->sat
= (mode
== 's');
392 svp64_decode_sz (char *str
, struct svp64_ctx
*svp64
)
394 str
+= (sizeof ("sz") - 1);
395 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
406 svp64_decode_dz (char *str
, struct svp64_ctx
*svp64
)
408 str
+= (sizeof ("dz") - 1);
409 if ( ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0')
420 svp64_decode_ff (char *str
, struct svp64_ctx
*svp64
)
426 str
+= (sizeof ("ff=") - 1);
427 if (svp64
->sv_mode_explicit
)
428 svp64_raise (_("SV mode conflict: `%s'"), str
);
430 iter
= svp64_decode_predicate (str
, &cr
, &mask
);
431 if (!iter
|| !(cr
|| ((mask
& SVP64_RC1_ACTIVE
) != 0)))
432 svp64_raise (_("unrecognized mode: `%s'"), str
);
434 svp64
->sv_mode_explicit
= 1;
435 svp64
->sv_mode
= 0x1;
442 svp64_decode_pr (char *str
, struct svp64_ctx
*svp64
)
448 str
+= (sizeof ("pr=") - 1);
449 if (svp64
->sv_mode_explicit
)
450 svp64_raise (_("SV mode conflict: `%s'"), str
);
452 iter
= svp64_decode_predicate (str
, &cr
, &mask
);
453 if (!iter
|| !(cr
|| ((mask
& SVP64_RC1_ACTIVE
) != 0)))
454 svp64_raise (_("unrecognized mode: `%s'"), str
);
456 svp64
->sv_mode_explicit
= 1;
457 svp64
->sv_mode
= 0x3;
464 svp64_decode_mode (char *str
, struct svp64_ctx
*svp64
)
467 static const struct svp64_decoder table
[] = {
468 SVP64_DECODER ("m=" , svp64_decode_m
),
469 SVP64_DECODER ("dm=" , svp64_decode_dm
),
470 SVP64_DECODER ("sm=" , svp64_decode_sm
),
471 SVP64_DECODER ("vec2", svp64_decode_vec
),
472 SVP64_DECODER ("vec3", svp64_decode_vec
),
473 SVP64_DECODER ("vec4", svp64_decode_vec
),
474 SVP64_DECODER ("w=" , svp64_decode_w
),
475 SVP64_DECODER ("dw=" , svp64_decode_dw
),
476 SVP64_DECODER ("sw=" , svp64_decode_sw
),
477 SVP64_DECODER ("els" , svp64_decode_els
),
478 SVP64_DECODER ("sats", svp64_decode_sat
),
479 SVP64_DECODER ("satu", svp64_decode_sat
),
480 SVP64_DECODER ("sz" , svp64_decode_sz
),
481 SVP64_DECODER ("dz" , svp64_decode_dz
),
482 SVP64_DECODER ("ff=" , svp64_decode_ff
),
483 SVP64_DECODER ("pr=" , svp64_decode_pr
),
486 for (i
= 0; i
< sizeof (table
) / sizeof (table
[0]); ++i
)
488 const struct svp64_decoder
*entry
= &table
[i
];
490 if (strncmp (str
, entry
->str
, entry
->len
) == 0)
491 return entry
->call (str
, svp64
);
498 svp64_decode (char *str
, struct svp64_ctx
*svp64
)
503 str
+= (sizeof ("sv.") - 1);
504 if (! ISALPHA (*str
))
505 svp64_raise (_("unrecognized opcode: `%s'"), str
);
508 for (; ! ISSPACE (*str
) && *str
!= SVP64_SEP
&& *str
!= '\0'; ++str
)
513 for (; (iter
= svp64_decode_mode (str
, svp64
)) != NULL
; str
= iter
)
516 svp64
->desc
= (const struct svp64_desc
*) str_hash_find (svp64_hash
, opc
);
518 svp64_raise (_("unrecognized opcode: `%s'"), str
);
522 svp64_assemble (char *str
)
524 struct svp64_ctx svp64
;
526 if (setjmp (svp64_exception
) != 0)
529 memset (&svp64
, 0, sizeof (svp64
));
531 svp64_decode (str
, &svp64
);
533 as_warn (_("opcode ignored (desc=%p)"), svp64
.desc
);
534 memcpy (str
, "nop", sizeof ("nop"));