ppc/svp64: share SVP64 context via libopcodes
[binutils-gdb.git] / gas / config / tc-ppc-svp64.c
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.
4
5 This file is part of GAS, the GNU Assembler.
6
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)
10 any later version.
11
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.
16
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
20 02110-1301, USA. */
21
22 #include <setjmp.h>
23
24 enum svp64_type {
25 SVP64_TYPE_NONE,
26 SVP64_TYPE_LD,
27 SVP64_TYPE_ST,
28 SVP64_TYPE_BC,
29 };
30
31 enum svp64_predicate {
32 /* Integer */
33 SVP64_PREDICATE_1BIT_R3,
34 SVP64_PREDICATE_R3,
35 SVP64_PREDICATE_R3_INV,
36 SVP64_PREDICATE_R10,
37 SVP64_PREDICATE_R10_INV,
38 SVP64_PREDICATE_R30,
39 SVP64_PREDICATE_R30_INV,
40 /* CR */
41 SVP64_PREDICATE_LT,
42 SVP64_PREDICATE_NL,
43 SVP64_PREDICATE_GE = SVP64_PREDICATE_NL,
44 SVP64_PREDICATE_GT,
45 SVP64_PREDICATE_NG,
46 SVP64_PREDICATE_LE = SVP64_PREDICATE_NG,
47 SVP64_PREDICATE_EQ,
48 SVP64_PREDICATE_NE,
49 SVP64_PREDICATE_SO,
50 SVP64_PREDICATE_UN = SVP64_PREDICATE_SO,
51 SVP64_PREDICATE_NS,
52 SVP64_PREDICATE_NU = SVP64_PREDICATE_NS,
53 /* RC1 */
54 SVP64_PREDICATE_RC1,
55 SVP64_PREDICATE_RC1_INV,
56 };
57
58 static void
59 svp64_operand (expressionS *exp)
60 {
61 bool caret = false;
62 bool vector = false;
63 bool compat = false;
64 char *origin = input_line_pointer;
65
66 if (input_line_pointer[0] == '*')
67 {
68 vector = true;
69 if (ISDIGIT (input_line_pointer[1]))
70 {
71 input_line_pointer[0] = 'r';
72 compat = true;
73 }
74 else
75 ++input_line_pointer;
76 }
77 else if (input_line_pointer[0] == '^')
78 {
79 caret = true;
80 ++input_line_pointer;
81 }
82
83 if (!vector && !compat && !reg_names_p &&
84 (input_line_pointer[0] != '%' || !ISALPHA (input_line_pointer[1])))
85 return;
86
87 if (!compat && (*input_line_pointer == '%'))
88 ++input_line_pointer;
89
90 ppc_operand_common (exp, svp64_regs, svp64_num_regs);
91
92 if (exp->X_op == O_absent)
93 input_line_pointer = origin;
94 else if (exp->X_op == O_register)
95 {
96 if (caret)
97 {
98 if (exp->X_add_number == 3)
99 {
100 exp->X_op = O_predicate;
101 exp->X_add_number = SVP64_PREDICATE_1BIT_R3;
102 }
103 else
104 exp->X_op = O_illegal;
105 }
106 else if (vector)
107 exp->X_op = O_vector;
108 }
109 else if ((exp->X_op == O_constant) && vector)
110 exp->X_op = O_vector;
111
112 if (compat)
113 *origin = '*';
114 }
115
116 static bool
117 svp64_special_expr (expressionS *exp)
118 {
119 return ((exp->X_op == O_vector) || (exp->X_op == O_predicate));
120 }
121
122 static jmp_buf svp64_exception;
123
124 #define svp64_raise(...) \
125 do { \
126 as_bad (__VA_ARGS__); \
127 longjmp (svp64_exception, 1); \
128 } while (0)
129
130 #define svp64_raise_if(COND, ...) \
131 do { \
132 if (!!(COND)) \
133 svp64_raise (__VA_ARGS__); \
134 } while (0)
135
136 static htab_t svp64_hash;
137
138 static void
139 svp64_setup_records (void)
140 {
141 const struct svp64_record *record;
142 const struct svp64_record *records_end;
143
144 svp64_hash = str_htab_create ();
145
146 records_end = (svp64_records + svp64_nr_records);
147 for (record = svp64_records; record < records_end; ++record)
148 {
149 const struct svp64_desc *desc = &record->desc;
150 const char *name = (record->name + (sizeof ("sv.") - 1));
151
152 if (str_hash_insert (svp64_hash, name, desc, 0) != NULL)
153 as_fatal (_("duplicate %s"), name);
154 }
155 }
156
157 #define SVP64_SEP '/'
158
159 static inline char *
160 svp64_expression (char *str, expressionS *exp)
161 {
162 char old_sep;
163 char *str_tail;
164 char *str_head = str;
165 char *old_ilp = input_line_pointer;
166
167 memset (exp, 0, sizeof *exp);
168
169 while (! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
170 ++str;
171 if (*str != '\0')
172 *str++ = '\0';
173 str_tail = str;
174 old_sep = *str;
175 str = str_head;
176 input_line_pointer = str;
177
178 expression (exp);
179
180 input_line_pointer = old_ilp;
181 *str_tail = old_sep;
182
183 return ((exp->X_op == O_absent) ? str_head : str_tail);
184 }
185
186 struct svp64_predicate_cr_map {
187 const char *str;
188 unsigned int len : 3;
189 unsigned int id : 5;
190 };
191 #define SVP64_PREDICATE_CR_MAP(STR, ID) \
192 { STR, (sizeof (STR) - 1), ID }
193
194 static bool
195 svp64_parse_predicate_cr (const char *name, expressionS *exp)
196 {
197 size_t i;
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),
212 };
213
214 for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i)
215 {
216 const struct svp64_predicate_cr_map *entry = &table[i];
217
218 if (strncmp (str, entry->str, entry->len) != 0)
219 continue;
220
221 str += entry->len;
222 if (! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
223 {
224 str -= entry->len;
225 continue;
226 }
227
228 exp->X_op = O_predicate;
229 exp->X_add_number = entry->id;
230
231 return true;
232 }
233
234 return false;
235 }
236
237 static bool
238 svp64_parse_predicate_RC1 (const char *name, expressionS *exp)
239 {
240 if (strcmp (name, "RC1") == 0)
241 {
242 exp->X_op = O_predicate;
243 exp->X_add_number = SVP64_PREDICATE_RC1;
244 return true;
245 }
246 else
247 return false;
248 }
249
250 static void
251 svp64_parse_name (const char *name, expressionS *exp, enum expr_mode mode)
252 {
253 exp->X_op = O_absent;
254 exp->X_op_symbol = NULL;
255 exp->X_add_symbol = NULL;
256
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);
260 }
261
262 static char *
263 svp64_decode_predicate (char *str, bool *cr, unsigned int *mask)
264 {
265 char *origin;
266 expressionS exp;
267
268 origin = str;
269 str = svp64_expression (str, &exp);
270 if (str != origin)
271 {
272 expressionS *sym_exp = NULL;
273 static const struct {
274 unsigned int cr : 1;
275 unsigned int mask : 3 + 2; /* 3-bit plus RC1 */
276 } table[] = {
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},
294 };
295 enum svp64_predicate predicate;
296
297 if (exp.X_add_symbol)
298 sym_exp = symbol_get_value_expression (exp.X_add_symbol);
299
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)))
304 {
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;
312 }
313 else if ((exp.X_op == O_bit_not) && (sym_exp != NULL))
314 {
315 if (sym_exp->X_op == O_register)
316 {
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;
323 }
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;
327 }
328 else if (exp.X_op != O_predicate)
329 return NULL;
330
331 predicate = (enum svp64_predicate)exp.X_add_number;
332 *cr = (table[predicate].cr ? true : false);
333 *mask = table[predicate].mask;
334
335 return str;
336 }
337
338 return NULL;
339 }
340
341 struct svp64_decoder {
342 char *(*call)(char *str, struct svp64_ctx *svp64);
343 const char *str;
344 size_t len;
345 };
346 #define SVP64_DECODER(STR, CALL) \
347 { CALL, STR, (sizeof (STR) - 1) }
348
349 static char *
350 svp64_decode_m (char *str, struct svp64_ctx *svp64)
351 {
352 char *iter;
353 bool cr;
354 unsigned int pmmode;
355 unsigned int pmask;
356
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);
361
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;
369
370 return iter;
371 }
372
373 static char *
374 svp64_decode_dm (char *str, struct svp64_ctx *svp64)
375 {
376 char *iter;
377 bool cr;
378 unsigned int pmmode;
379 unsigned int pmask;
380
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);
385
386 pmmode = (cr ? 1 : 0);
387 svp64->pmmode = pmmode;
388 svp64->pmask = pmask;
389 svp64->mmode = pmmode;
390 svp64->has_pmask = 1;
391
392 return iter;
393 }
394
395 static char *
396 svp64_decode_sm (char *str, struct svp64_ctx *svp64)
397 {
398 char *iter;
399 bool cr;
400 unsigned int smmode;
401 unsigned int smask;
402
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);
407
408 smmode = (cr ? 1 : 0);
409 svp64->smmode = smmode;
410 svp64->smask = smask;
411 svp64->mmode = smmode;
412 svp64->has_smask = 1;
413
414 return iter;
415 }
416
417 static char *
418 svp64_decode_vec (char *str, struct svp64_ctx *svp64)
419 {
420 char *subvl;
421
422 str += (sizeof ("vec") - 1);
423 if ( ISSPACE (*str) || *str == SVP64_SEP || *str == '\0')
424 return NULL;
425
426 subvl = str++;
427 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
428 return NULL;
429
430 switch (*subvl)
431 {
432 case '2':
433 svp64->subvl = 1;
434 break;
435 case '3':
436 svp64->subvl = 2;
437 break;
438 case '4':
439 svp64->subvl = 3;
440 break;
441 default:
442 return NULL;
443 }
444
445 *str++ = '\0';
446
447 return str;
448 }
449
450 struct svp64_width_map {
451 const char *str;
452 unsigned int len : 2;
453 unsigned int num : 6;
454 unsigned int width : 8;
455 };
456 #define SVP64_WIDTH_MAP(NUM, WIDTH) \
457 { #NUM, (sizeof (#NUM) - 1), NUM, WIDTH }
458
459 static char *
460 svp64_decode_width (char *str, unsigned int *width)
461 {
462 size_t i;
463 char *origin;
464 expressionS exp;
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),
469 };
470
471 origin = str;
472 str = svp64_expression (str, &exp);
473 if ((str != origin) && (exp.X_op == O_constant))
474 {
475 for (i = 0; i < (sizeof (table) / sizeof (table[0])); ++i)
476 {
477 const struct svp64_width_map *entry = &table[i];
478
479 if (entry->num == exp.X_add_number)
480 {
481 *width = entry->width;
482 return str;
483 }
484 }
485 }
486
487 return NULL;
488 }
489
490 static char *
491 svp64_decode_w (char *str, struct svp64_ctx *svp64)
492 {
493 char *iter;
494 unsigned int width;
495
496 str += (sizeof ("w=") - 1);
497 iter = svp64_decode_width (str, &width);
498 if (!iter)
499 svp64_raise (_("unrecognized mode: `%s'"), str);
500
501 svp64->srcwid = width;
502 svp64->destwid = width;
503
504 return iter;
505 }
506
507 static char *
508 svp64_decode_dw (char *str, struct svp64_ctx *svp64)
509 {
510 char *iter;
511 unsigned int width;
512
513 str += (sizeof ("dw=") - 1);
514 iter = svp64_decode_width (str, &width);
515 if (!iter)
516 svp64_raise (_("unrecognized mode: `%s'"), str);
517
518 svp64->destwid = width;
519
520 return iter;
521 }
522
523 static char *
524 svp64_decode_sw (char *str, struct svp64_ctx *svp64)
525 {
526 char *iter;
527 unsigned int width;
528
529 str += (sizeof ("sw=") - 1);
530 iter = svp64_decode_width (str, &width);
531 if (!iter)
532 svp64_raise (_("unrecognized mode: `%s'"), str);
533
534 svp64->srcwid = width;
535
536 return iter;
537 }
538
539 static char *
540 svp64_decode_els (char *str, struct svp64_ctx *svp64)
541 {
542 str += (sizeof ("els") - 1);
543 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
544 return NULL;
545
546 svp64->ldst_elstride = 1;
547
548 *str++ = '\0';
549
550 return str;
551 }
552
553 static char *
554 svp64_decode_sat (char *str, struct svp64_ctx *svp64)
555 {
556 unsigned char mode;
557
558 str += (sizeof ("sat") - 1);
559 if ((*str != 's') && (*str != 'u'))
560 return NULL;
561
562 mode = *str++;
563 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
564 return NULL;
565
566 if (svp64->sv_mode_explicit)
567 svp64_raise (_("SV mode conflict: `%s'"), str);
568
569 svp64->sv_mode_explicit = 1;
570 svp64->sv_mode = 2;
571 svp64->sat = (mode == 's');
572
573 *str++ = '\0';
574
575 return str;
576 }
577
578 static char *
579 svp64_decode_sz (char *str, struct svp64_ctx *svp64)
580 {
581 str += (sizeof ("sz") - 1);
582 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
583 return NULL;
584
585 svp64->src_zero = 1;
586
587 *str++ = '\0';
588
589 return str;
590 }
591
592 static char *
593 svp64_decode_dz (char *str, struct svp64_ctx *svp64)
594 {
595 str += (sizeof ("dz") - 1);
596 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
597 return NULL;
598
599 svp64->dst_zero = 1;
600
601 *str++ = '\0';
602
603 return str;
604 }
605
606 static char *
607 svp64_decode_ff (char *str, struct svp64_ctx *svp64)
608 {
609 char *iter;
610 bool cr;
611 unsigned int mask;
612
613 str += (sizeof ("ff=") - 1);
614 if (svp64->sv_mode_explicit)
615 svp64_raise (_("SV mode conflict: `%s'"), str);
616
617 iter = svp64_decode_predicate (str, &cr, &mask);
618 if (!iter || !(cr || ((mask & SVP64_RC1_ACTIVE) != 0)))
619 svp64_raise (_("unrecognized mode: `%s'"), str);
620
621 svp64->sv_mode_explicit = 1;
622 svp64->sv_mode = 0x1;
623 svp64->ff = mask;
624
625 return iter;
626 }
627
628 static char *
629 svp64_decode_pr (char *str, struct svp64_ctx *svp64)
630 {
631 char *iter;
632 bool cr;
633 unsigned int mask;
634
635 str += (sizeof ("pr=") - 1);
636 if (svp64->sv_mode_explicit)
637 svp64_raise (_("SV mode conflict: `%s'"), str);
638
639 iter = svp64_decode_predicate (str, &cr, &mask);
640 if (!iter || !(cr || ((mask & SVP64_RC1_ACTIVE) != 0)))
641 svp64_raise (_("unrecognized mode: `%s'"), str);
642
643 svp64->sv_mode_explicit = 1;
644 svp64->sv_mode = 0x3;
645 svp64->pr = mask;
646
647 return iter;
648 }
649
650 static char *
651 svp64_decode_mr (char *str, struct svp64_ctx *svp64)
652 {
653 str += (sizeof ("mr") - 1);
654 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
655 return NULL;
656
657 svp64->sv_mode_explicit = 1;
658 svp64->sv_mode = 0;
659 svp64->mr = 1;
660
661 *str++ = '\0';
662
663 return str;
664 }
665
666 static char *
667 svp64_decode_mrr (char *str, struct svp64_ctx *svp64)
668 {
669 str += (sizeof ("mrr") - 1);
670 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
671 return NULL;
672
673 svp64->sv_mode_explicit = 1;
674 svp64->sv_mode = 0;
675 svp64->mr = 1;
676 svp64->rg = 1;
677
678 *str++ = '\0';
679
680 return str;
681 }
682
683 static char *
684 svp64_decode_crm (char *str, struct svp64_ctx *svp64)
685 {
686 str += (sizeof ("crm") - 1);
687 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
688 return NULL;
689
690 svp64->sv_mode_explicit = 1;
691 svp64->sv_mode = 0;
692 svp64->crm = 1;
693
694 *str++ = '\0';
695
696 return str;
697 }
698
699 static char *
700 svp64_decode_mode (char *str, struct svp64_ctx *svp64)
701 {
702 size_t i;
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),
723 };
724
725 for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i)
726 {
727 const struct svp64_decoder *entry = &table[i];
728
729 if (strncmp (str, entry->str, entry->len) == 0)
730 return entry->call (str, svp64);
731 }
732
733 return NULL;
734 }
735
736 struct svp64_str_map {
737 const char *str;
738 size_t len;
739 };
740 #define SVP64_STR_MAP(STR) \
741 { STR, (sizeof (STR) - 1) }
742
743 static bool
744 svp64_str_map_cmp(const char *str, size_t len,
745 const struct svp64_str_map *map, size_t cnt)
746 {
747 size_t i;
748
749 for (i = 0; i < cnt; ++i) {
750 const struct svp64_str_map *entry = &map[i];
751
752 if ((entry->len == len) && (memcmp(entry->str, str, len) == 0))
753 return true;
754 }
755
756 return false;
757 }
758 #define SVP64_STR_MAP_CMP(STR, LEN, MAP) \
759 svp64_str_map_cmp(STR, LEN, MAP, (sizeof (MAP) / sizeof (*MAP)))
760
761 static bool
762 svp64_is_ld(const char *str, size_t len)
763 {
764 static const struct svp64_str_map table[] = {
765 /* load byte */
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"),
771 /* load double */
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"),
778 /* FP load single */
779 SVP64_STR_MAP ("lfs"),
780 SVP64_STR_MAP ("lfsx"),
781 SVP64_STR_MAP ("lfsu"),
782 SVP64_STR_MAP ("lfsux"),
783 /* FP load double */
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"),
790 /* load half */
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"),
801 /* load word */
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"),
812 };
813
814 return SVP64_STR_MAP_CMP(str, len, table);
815 }
816
817 static bool
818 svp64_is_st(const char *str, size_t len)
819 {
820 static const struct svp64_str_map table[] = {
821 /* store byte */
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"),
828 /* store double */
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"),
846 /* store half */
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"),
853 /* store word */
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"),
860 };
861
862 return SVP64_STR_MAP_CMP(str, len, table);
863 }
864
865 static bool
866 svp64_is_bc(const char *str, size_t len)
867 {
868 static const struct svp64_str_map table[] = {
869 SVP64_STR_MAP ("bc"),
870 SVP64_STR_MAP ("bclr"),
871 };
872
873 return SVP64_STR_MAP_CMP(str, len, table);
874 }
875
876 static inline bool
877 svp64_is_rc (const char *str, size_t len)
878 {
879 return (str[len - 1] == '.');
880 }
881
882 static void
883 svp64_decode (char *str, struct svp64_ctx *svp64)
884 {
885 char *opc;
886 size_t opclen;
887 char *args;
888 size_t argslen;
889 char *iter;
890 char *base = str;
891
892 str += (sizeof ("sv.") - 1);
893 if (! ISALPHA (*str))
894 svp64_raise (_("unrecognized opcode: `%s'"), str);
895
896 opc = str;
897 for (; ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0'; ++str)
898 ;
899 opclen = (str - opc);
900 if (*str != '\0')
901 *str++ = '\0';
902
903 if (svp64_is_rc (opc, opclen))
904 svp64->rc = 1;
905
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;
912
913 for (; (iter = svp64_decode_mode (str, svp64)) != NULL; str = iter)
914 ;
915 args = str;
916 argslen = strlen (args);
917
918 svp64->desc = (const struct svp64_desc *) str_hash_find (svp64_hash, opc);
919 if (!svp64->desc)
920 svp64_raise (_("unrecognized opcode: `%s'"), str);
921
922 iter = base;
923 memmove (iter, opc, opclen);
924 iter += opclen;
925 *iter++ = ' ';
926
927 memmove (iter, args, argslen);
928 iter += argslen;
929 *iter++ = '\0';
930 }
931
932 static void
933 svp64_validate_and_fix_mode_bc (struct svp64_ctx *svp64)
934 {
935 /*
936 * Create mode and (overridden) src/dst widths.
937 * TODO: sanity-check BC modes.
938 */
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);
944 }
945
946 static void
947 svp64_validate_and_fix_mode_mr (struct svp64_ctx *svp64)
948 {
949 svp64->mode |= (1U << SVP64_MODE_REDUCE);
950 svp64_raise_if (svp64->dst_zero,
951 "dest-zero not allowed in mr mode");
952
953 if (svp64->rg)
954 svp64->mode |= (1U << SVP64_MODE_RG);
955
956 if (svp64->crm)
957 {
958 svp64->mode |= (1U << SVP64_MODE_CRM);
959 svp64_raise_if (!svp64->rc, "CRM only allowed when Rc=1");
960 }
961
962 /*
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)
965 */
966 if (svp64->subvl == 0)
967 svp64->mode |= (svp64->dst_zero << SVP64_MODE_DZ);
968 }
969
970 static void
971 svp64_validate_and_fix_mode_ff(struct svp64_ctx *svp64)
972 {
973 svp64_raise_if (svp64->src_zero,
974 "dest-zero not allowed in ff mode");
975
976 if (svp64->ff & SVP64_RC1_ACTIVE)
977 {
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);
984 }
985 else
986 {
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);
992 }
993 }
994
995 static void
996 svp64_validate_and_fix_mode_sat(struct svp64_ctx *svp64)
997 {
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);
1001 }
1002
1003 static void
1004 svp64_validate_and_fix_mode_pr(struct svp64_ctx *svp64)
1005 {
1006 svp64_raise_if (svp64->src_zero,
1007 "dest-zero not allowed in pr mode");
1008
1009 if (svp64->pr & SVP64_RC1_ACTIVE)
1010 {
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);
1017 }
1018 else
1019 {
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);
1025 }
1026 }
1027
1028 static void
1029 svp64_validate_and_fix_mode_explicit(struct svp64_ctx *svp64)
1030 {
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,
1036 };
1037
1038 return table[svp64->sv_mode] (svp64);
1039 }
1040
1041 static void
1042 svp64_validate_and_fix_mode_normal (struct svp64_ctx *svp64)
1043 {
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))
1048 {
1049 /* TODO: for now, LD/ST-indexed is ignored. */
1050 svp64->mode |= (svp64->ldst_elstride << SVP64_MODE_ELS_NORMAL);
1051 }
1052 else
1053 {
1054 /*
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
1058 */
1059 }
1060 svp64->sv_mode = 0;
1061 }
1062
1063 /*
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).
1067 *
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 |
1080 *
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 |
1091 *
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 |
1100 *
1101 * ...and branches/cr_ops are still in development.
1102 */
1103 static void
1104 svp64_validate_and_fix_mode (struct svp64_ctx *svp64)
1105 {
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);
1110 else
1111 svp64_validate_and_fix_mode_normal (svp64);
1112 }
1113
1114 static void
1115 svp64_validate_and_fix (struct svp64_ctx *svp64)
1116 {
1117 if (svp64->desc->ptype == SVP64_PTYPE_P2)
1118 {
1119 /*
1120 * Since m=xx takes precedence (overrides) sm=xx and dm=xx,
1121 * treat them as mutually exclusive.
1122 */
1123 if (svp64->mask_m_specified)
1124 {
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");
1129 }
1130
1131 /*
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.
1135 */
1136 if (svp64->has_pmask && (svp64->pmmode == 1))
1137 {
1138 svp64_raise_if (!svp64->has_smask,
1139 "need explicit source-mask in CR twin predication");
1140 }
1141 if (svp64->has_smask && (svp64->smmode == 1))
1142 {
1143 svp64_raise_if (!svp64->has_pmask,
1144 "need explicit dest-mask in CR twin predication");
1145 }
1146
1147 /* Sanity-check that 2Pred mask is same mode. */
1148 if (svp64->has_pmask && svp64->has_smask)
1149 {
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);
1153 }
1154 else if (svp64->desc->ptype == SVP64_PTYPE_P1)
1155 {
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");
1160 }
1161 }
1162
1163 if (svp64->src_zero)
1164 {
1165 svp64_raise_if (!svp64->has_smask && !svp64->mask_m_specified,
1166 "src zeroing requires a source predicate");
1167 }
1168 if (svp64->dst_zero)
1169 {
1170 svp64_raise_if (!svp64->has_pmask && !svp64->mask_m_specified,
1171 "dest zeroing requires a dest predicate");
1172 }
1173
1174 svp64_validate_and_fix_mode (svp64);
1175 }
1176
1177 static void
1178 svp64_remap_extra (struct svp64_ctx *svp64,
1179 ppc_opindex_t opindex, uint32_t value)
1180 {
1181 const struct svp64_extra_desc *desc;
1182
1183 desc = svp64_extra_desc (svp64->desc, opindex);
1184 svp64_raise_if ((desc == NULL), "cannot remap EXTRA");
1185
1186 return (*desc->set) (&svp64->insn, value);
1187 }
1188
1189 static int64_t
1190 svp64_remap_reg (struct svp64_ctx *svp64, int64_t value,
1191 ppc_opindex_t opindex, bool vector)
1192 {
1193 uint32_t field;
1194 uint32_t sv_extra;
1195
1196 svp64_raise_if (((value < 0) || (value > 127)),
1197 "register does not fit the expected range 0..127");
1198 field = (uint32_t)value;
1199
1200 if (vector)
1201 {
1202 /* cut into 5-bits 2-bits FFFFF SS */
1203 sv_extra = (field & 0x3);
1204 field >>= 2;
1205 }
1206 else
1207 {
1208 /* cut into 2-bits 5-bits SS FFFFF */
1209 sv_extra = (field >> 5);
1210 field &= 0x1F;
1211 }
1212
1213 if (svp64->desc->etype == SVP64_ETYPE_EXTRA2)
1214 {
1215 if (vector)
1216 {
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));
1221 }
1222 else
1223 {
1224 /* range is r0-r63 in increments of 1 */
1225 svp64_raise_if ( ((sv_extra >> 1) != 0),
1226 "scalar register cannot fit into EXTRA2");
1227 sv_extra &= 0x1;
1228 }
1229 }
1230 else if (vector)
1231 {
1232 /* EXTRA3 vector bit needs marking */
1233 sv_extra |= 0x4;
1234 }
1235
1236 svp64_remap_extra (svp64, opindex, sv_extra);
1237
1238 return field;
1239 }
1240
1241 static int64_t
1242 svp64_remap_gpr (struct svp64_ctx *svp64, int64_t value,
1243 ppc_opindex_t opindex, bool vector)
1244 {
1245 return svp64_remap_reg (svp64, value, opindex, vector);
1246 }
1247
1248 static int64_t
1249 svp64_remap_fpr (struct svp64_ctx *svp64, int64_t value,
1250 ppc_opindex_t opindex, bool vector)
1251 {
1252 return svp64_remap_reg (svp64, value, opindex, vector);
1253 }
1254
1255 static int64_t
1256 svp64_remap_cr (struct svp64_ctx *svp64, int64_t value,
1257 ppc_opindex_t opindex, bool vector, bool cr_bit)
1258 {
1259 uint32_t field;
1260 uint32_t subfield;
1261 uint32_t sv_extra;
1262
1263 svp64_raise_if (((value < 0) || (value > 127)),
1264 "register does not fit the expected range 0..127");
1265 field = (uint32_t)value;
1266
1267 if (cr_bit)
1268 {
1269 subfield = (field & 0x3);
1270 field >>= 2;
1271 }
1272
1273 if (vector)
1274 {
1275 /* cut into 3-bits 4-bits FFF SSSS but will cut 2 zeros off later */
1276 sv_extra = (field & 0xf);
1277 field >>= 4;
1278 }
1279 else
1280 {
1281 /* cut into 2-bits 3-bits SS FFF */
1282 sv_extra = (field >> 3);
1283 field &= 0x7;
1284 }
1285
1286 if (svp64->desc->etype == SVP64_ETYPE_EXTRA2)
1287 {
1288 if (vector)
1289 {
1290 svp64_raise_if (((sv_extra & 0x7) != 0),
1291 "vector CR cannot fit into EXTRA2");
1292 sv_extra = (0x2 | (sv_extra >> 3));
1293 }
1294 else
1295 {
1296 svp64_raise_if (((sv_extra >> 1) != 0),
1297 "scalar CR cannot fit into EXTRA2");
1298 sv_extra &= 0x1;
1299 }
1300 }
1301 else
1302 {
1303 if (vector)
1304 {
1305 svp64_raise_if (((sv_extra & 0x3) != 0),
1306 "vector CR cannot fit into EXTRA3");
1307 sv_extra = (0x4 | (sv_extra >> 2));
1308 }
1309 else
1310 {
1311 svp64_raise_if (((sv_extra >> 2) != 0),
1312 "scalar CR cannot fit into EXTRA3");
1313 sv_extra &= 0x3;
1314 }
1315 }
1316
1317 if (cr_bit)
1318 field = ((field << 2) | subfield);
1319
1320 svp64_remap_extra (svp64, opindex, sv_extra);
1321
1322 return field;
1323 }
1324
1325 static int64_t
1326 svp64_remap (struct svp64_ctx *ctx, int64_t value,
1327 const struct powerpc_operand *operand, bool vector)
1328 {
1329 const ppc_opindex_t opindex = (ppc_opindex_t)(operand - powerpc_operands);
1330
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)
1336 {
1337 bool cr_bit = ((operand->flags & PPC_OPERAND_CR_BIT) != 0);
1338
1339 return svp64_remap_cr (ctx, value, opindex, vector, cr_bit);
1340 }
1341
1342 return value;
1343 }
1344
1345 static void
1346 svp64_assemble (char *str)
1347 {
1348 struct svp64_ctx svp64;
1349
1350 if (setjmp (svp64_exception) != 0)
1351 return;
1352
1353 memset (&svp64, 0, sizeof (svp64));
1354
1355 svp64_decode (str, &svp64);
1356 svp64_validate_and_fix (&svp64);
1357
1358 svp64_insn_set_prefix_po (&svp64.insn, 0x1);
1359 svp64_insn_set_prefix_id (&svp64.insn, 0x3);
1360
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);
1369
1370 ppc_assemble (str, &svp64);
1371 }