ec0fda793c8a15834a4c0fced5bb98ce7a5c51c5
[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 struct svp64_ctx {
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;
41 unsigned int sat : 1;
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 */
46 unsigned int mr : 1;
47 unsigned int rg : 1;
48 unsigned int crm : 1;
49 unsigned int type : 2;
50 unsigned int rc : 1;
51 unsigned int mode : 5;
52
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;
62 };
63
64 #define SVP64_RC1_ACTIVE (1U << 3U)
65 #define SVP64_RC1_INVERT (SVP64_RC1_ACTIVE | (1U << 4U))
66
67 enum svp64_type {
68 SVP64_TYPE_NONE,
69 SVP64_TYPE_LD,
70 SVP64_TYPE_ST,
71 SVP64_TYPE_BC,
72 };
73
74 enum svp64_predicate {
75 /* Integer */
76 SVP64_PREDICATE_1BIT_R3,
77 SVP64_PREDICATE_R3,
78 SVP64_PREDICATE_R3_INV,
79 SVP64_PREDICATE_R10,
80 SVP64_PREDICATE_R10_INV,
81 SVP64_PREDICATE_R30,
82 SVP64_PREDICATE_R30_INV,
83 /* CR */
84 SVP64_PREDICATE_LT,
85 SVP64_PREDICATE_NL,
86 SVP64_PREDICATE_GE = SVP64_PREDICATE_NL,
87 SVP64_PREDICATE_GT,
88 SVP64_PREDICATE_NG,
89 SVP64_PREDICATE_LE = SVP64_PREDICATE_NG,
90 SVP64_PREDICATE_EQ,
91 SVP64_PREDICATE_NE,
92 SVP64_PREDICATE_SO,
93 SVP64_PREDICATE_UN = SVP64_PREDICATE_SO,
94 SVP64_PREDICATE_NS,
95 SVP64_PREDICATE_NU = SVP64_PREDICATE_NS,
96 /* RC1 */
97 SVP64_PREDICATE_RC1,
98 SVP64_PREDICATE_RC1_INV,
99 };
100
101 static void
102 svp64_operand (expressionS *exp)
103 {
104 bool caret = false;
105 bool vector = false;
106 bool compat = false;
107 char *origin = input_line_pointer;
108
109 if (input_line_pointer[0] == '*')
110 {
111 vector = true;
112 if (ISDIGIT (input_line_pointer[1]))
113 {
114 input_line_pointer[0] = 'r';
115 compat = true;
116 }
117 else
118 ++input_line_pointer;
119 }
120 else if (input_line_pointer[0] == '^')
121 {
122 caret = true;
123 ++input_line_pointer;
124 }
125
126 if (!vector && !compat && !reg_names_p &&
127 (input_line_pointer[0] != '%' || !ISALPHA (input_line_pointer[1])))
128 return;
129
130 if (!compat && (*input_line_pointer == '%'))
131 ++input_line_pointer;
132
133 ppc_operand_common (exp, svp64_regs, svp64_num_regs);
134
135 if (exp->X_op == O_absent)
136 input_line_pointer = origin;
137 else if (exp->X_op == O_register)
138 {
139 if (caret)
140 {
141 if (exp->X_add_number == 3)
142 {
143 exp->X_op = O_predicate;
144 exp->X_add_number = SVP64_PREDICATE_1BIT_R3;
145 }
146 else
147 exp->X_op = O_illegal;
148 }
149 else if (vector)
150 exp->X_op = O_vector;
151 }
152 else if ((exp->X_op == O_constant) && vector)
153 exp->X_op = O_vector;
154
155 if (compat)
156 *origin = '*';
157 }
158
159 static bool
160 svp64_special_expr (expressionS *exp)
161 {
162 return ((exp->X_op == O_vector) || (exp->X_op == O_predicate));
163 }
164
165 static jmp_buf svp64_exception;
166
167 #define svp64_raise(...) \
168 do { \
169 as_bad (__VA_ARGS__); \
170 longjmp (svp64_exception, 1); \
171 } while (0)
172
173 #define svp64_raise_if(COND, ...) \
174 do { \
175 if (!!(COND)) \
176 svp64_raise (__VA_ARGS__); \
177 } while (0)
178
179 static htab_t svp64_hash;
180
181 static void
182 svp64_setup_records (void)
183 {
184 const struct svp64_record *record;
185 const struct svp64_record *records_end;
186
187 svp64_hash = str_htab_create ();
188
189 records_end = (svp64_records + svp64_nr_records);
190 for (record = svp64_records; record < records_end; ++record)
191 {
192 const struct svp64_desc *desc = &record->desc;
193 const char *name = (record->name + (sizeof ("sv.") - 1));
194
195 if (str_hash_insert (svp64_hash, name, desc, 0) != NULL)
196 as_fatal (_("duplicate %s"), name);
197 }
198 }
199
200 #define SVP64_SEP '/'
201
202 static inline char *
203 svp64_expression (char *str, expressionS *exp)
204 {
205 char old_sep;
206 char *str_tail;
207 char *str_head = str;
208 char *old_ilp = input_line_pointer;
209
210 memset (exp, 0, sizeof *exp);
211
212 while (! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
213 ++str;
214 if (*str != '\0')
215 *str++ = '\0';
216 str_tail = str;
217 old_sep = *str;
218 str = str_head;
219 input_line_pointer = str;
220
221 expression (exp);
222
223 input_line_pointer = old_ilp;
224 *str_tail = old_sep;
225
226 return ((exp->X_op == O_absent) ? str_head : str_tail);
227 }
228
229 struct svp64_predicate_cr_map {
230 const char *str;
231 unsigned int len : 3;
232 unsigned int id : 5;
233 };
234 #define SVP64_PREDICATE_CR_MAP(STR, ID) \
235 { STR, (sizeof (STR) - 1), ID }
236
237 static bool
238 svp64_parse_predicate_cr (const char *name, expressionS *exp)
239 {
240 size_t i;
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),
255 };
256
257 for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i)
258 {
259 const struct svp64_predicate_cr_map *entry = &table[i];
260
261 if (strncmp (str, entry->str, entry->len) != 0)
262 continue;
263
264 str += entry->len;
265 if (! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
266 {
267 str -= entry->len;
268 continue;
269 }
270
271 exp->X_op = O_predicate;
272 exp->X_add_number = entry->id;
273
274 return true;
275 }
276
277 return false;
278 }
279
280 static bool
281 svp64_parse_predicate_RC1 (const char *name, expressionS *exp)
282 {
283 if (strcmp (name, "RC1") == 0)
284 {
285 exp->X_op = O_predicate;
286 exp->X_add_number = SVP64_PREDICATE_RC1;
287 return true;
288 }
289 else
290 return false;
291 }
292
293 static void
294 svp64_parse_name (const char *name, expressionS *exp, enum expr_mode mode)
295 {
296 exp->X_op = O_absent;
297 exp->X_op_symbol = NULL;
298 exp->X_add_symbol = NULL;
299
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);
303 }
304
305 static char *
306 svp64_decode_predicate (char *str, bool *cr, unsigned int *mask)
307 {
308 char *origin;
309 expressionS exp;
310
311 origin = str;
312 str = svp64_expression (str, &exp);
313 if (str != origin)
314 {
315 expressionS *sym_exp = NULL;
316 static const struct {
317 unsigned int cr : 1;
318 unsigned int mask : 3 + 2; /* 3-bit plus RC1 */
319 } table[] = {
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},
337 };
338 enum svp64_predicate predicate;
339
340 if (exp.X_add_symbol)
341 sym_exp = symbol_get_value_expression (exp.X_add_symbol);
342
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)))
347 {
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;
355 }
356 else if ((exp.X_op == O_bit_not) && (sym_exp != NULL))
357 {
358 if (sym_exp->X_op == O_register)
359 {
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;
366 }
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;
370 }
371 else if (exp.X_op != O_predicate)
372 return NULL;
373
374 predicate = (enum svp64_predicate)exp.X_add_number;
375 *cr = (table[predicate].cr ? true : false);
376 *mask = table[predicate].mask;
377
378 return str;
379 }
380
381 return NULL;
382 }
383
384 struct svp64_decoder {
385 char *(*call)(char *str, struct svp64_ctx *svp64);
386 const char *str;
387 size_t len;
388 };
389 #define SVP64_DECODER(STR, CALL) \
390 { CALL, STR, (sizeof (STR) - 1) }
391
392 static char *
393 svp64_decode_m (char *str, struct svp64_ctx *svp64)
394 {
395 char *iter;
396 bool cr;
397 unsigned int pmmode;
398 unsigned int pmask;
399
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);
404
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;
412
413 return iter;
414 }
415
416 static char *
417 svp64_decode_dm (char *str, struct svp64_ctx *svp64)
418 {
419 char *iter;
420 bool cr;
421 unsigned int pmmode;
422 unsigned int pmask;
423
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);
428
429 pmmode = (cr ? 1 : 0);
430 svp64->pmmode = pmmode;
431 svp64->pmask = pmask;
432 svp64->mmode = pmmode;
433 svp64->has_pmask = 1;
434
435 return iter;
436 }
437
438 static char *
439 svp64_decode_sm (char *str, struct svp64_ctx *svp64)
440 {
441 char *iter;
442 bool cr;
443 unsigned int smmode;
444 unsigned int smask;
445
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);
450
451 smmode = (cr ? 1 : 0);
452 svp64->smmode = smmode;
453 svp64->smask = smask;
454 svp64->mmode = smmode;
455 svp64->has_smask = 1;
456
457 return iter;
458 }
459
460 static char *
461 svp64_decode_vec (char *str, struct svp64_ctx *svp64)
462 {
463 char *subvl;
464
465 str += (sizeof ("vec") - 1);
466 if ( ISSPACE (*str) || *str == SVP64_SEP || *str == '\0')
467 return NULL;
468
469 subvl = str++;
470 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
471 return NULL;
472
473 switch (*subvl)
474 {
475 case '2':
476 svp64->subvl = 1;
477 break;
478 case '3':
479 svp64->subvl = 2;
480 break;
481 case '4':
482 svp64->subvl = 3;
483 break;
484 default:
485 return NULL;
486 }
487
488 *str++ = '\0';
489
490 return str;
491 }
492
493 struct svp64_width_map {
494 const char *str;
495 unsigned int len : 2;
496 unsigned int num : 6;
497 unsigned int width : 8;
498 };
499 #define SVP64_WIDTH_MAP(NUM, WIDTH) \
500 { #NUM, (sizeof (#NUM) - 1), NUM, WIDTH }
501
502 static char *
503 svp64_decode_width (char *str, unsigned int *width)
504 {
505 size_t i;
506 char *origin;
507 expressionS exp;
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),
512 };
513
514 origin = str;
515 str = svp64_expression (str, &exp);
516 if ((str != origin) && (exp.X_op == O_constant))
517 {
518 for (i = 0; i < (sizeof (table) / sizeof (table[0])); ++i)
519 {
520 const struct svp64_width_map *entry = &table[i];
521
522 if (entry->num == exp.X_add_number)
523 {
524 *width = entry->width;
525 return str;
526 }
527 }
528 }
529
530 return NULL;
531 }
532
533 static char *
534 svp64_decode_w (char *str, struct svp64_ctx *svp64)
535 {
536 char *iter;
537 unsigned int width;
538
539 str += (sizeof ("w=") - 1);
540 iter = svp64_decode_width (str, &width);
541 if (!iter)
542 svp64_raise (_("unrecognized mode: `%s'"), str);
543
544 svp64->srcwid = width;
545 svp64->destwid = width;
546
547 return iter;
548 }
549
550 static char *
551 svp64_decode_dw (char *str, struct svp64_ctx *svp64)
552 {
553 char *iter;
554 unsigned int width;
555
556 str += (sizeof ("dw=") - 1);
557 iter = svp64_decode_width (str, &width);
558 if (!iter)
559 svp64_raise (_("unrecognized mode: `%s'"), str);
560
561 svp64->destwid = width;
562
563 return iter;
564 }
565
566 static char *
567 svp64_decode_sw (char *str, struct svp64_ctx *svp64)
568 {
569 char *iter;
570 unsigned int width;
571
572 str += (sizeof ("sw=") - 1);
573 iter = svp64_decode_width (str, &width);
574 if (!iter)
575 svp64_raise (_("unrecognized mode: `%s'"), str);
576
577 svp64->srcwid = width;
578
579 return iter;
580 }
581
582 static char *
583 svp64_decode_els (char *str, struct svp64_ctx *svp64)
584 {
585 str += (sizeof ("els") - 1);
586 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
587 return NULL;
588
589 svp64->ldst_elstride = 1;
590
591 *str++ = '\0';
592
593 return str;
594 }
595
596 static char *
597 svp64_decode_sat (char *str, struct svp64_ctx *svp64)
598 {
599 unsigned char mode;
600
601 str += (sizeof ("sat") - 1);
602 if ((*str != 's') && (*str != 'u'))
603 return NULL;
604
605 mode = *str++;
606 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
607 return NULL;
608
609 if (svp64->sv_mode_explicit)
610 svp64_raise (_("SV mode conflict: `%s'"), str);
611
612 svp64->sv_mode_explicit = 1;
613 svp64->sv_mode = 2;
614 svp64->sat = (mode == 's');
615
616 *str++ = '\0';
617
618 return str;
619 }
620
621 static char *
622 svp64_decode_sz (char *str, struct svp64_ctx *svp64)
623 {
624 str += (sizeof ("sz") - 1);
625 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
626 return NULL;
627
628 svp64->src_zero = 1;
629
630 *str++ = '\0';
631
632 return str;
633 }
634
635 static char *
636 svp64_decode_dz (char *str, struct svp64_ctx *svp64)
637 {
638 str += (sizeof ("dz") - 1);
639 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
640 return NULL;
641
642 svp64->dst_zero = 1;
643
644 *str++ = '\0';
645
646 return str;
647 }
648
649 static char *
650 svp64_decode_ff (char *str, struct svp64_ctx *svp64)
651 {
652 char *iter;
653 bool cr;
654 unsigned int mask;
655
656 str += (sizeof ("ff=") - 1);
657 if (svp64->sv_mode_explicit)
658 svp64_raise (_("SV mode conflict: `%s'"), str);
659
660 iter = svp64_decode_predicate (str, &cr, &mask);
661 if (!iter || !(cr || ((mask & SVP64_RC1_ACTIVE) != 0)))
662 svp64_raise (_("unrecognized mode: `%s'"), str);
663
664 svp64->sv_mode_explicit = 1;
665 svp64->sv_mode = 0x1;
666 svp64->ff = mask;
667
668 return iter;
669 }
670
671 static char *
672 svp64_decode_pr (char *str, struct svp64_ctx *svp64)
673 {
674 char *iter;
675 bool cr;
676 unsigned int mask;
677
678 str += (sizeof ("pr=") - 1);
679 if (svp64->sv_mode_explicit)
680 svp64_raise (_("SV mode conflict: `%s'"), str);
681
682 iter = svp64_decode_predicate (str, &cr, &mask);
683 if (!iter || !(cr || ((mask & SVP64_RC1_ACTIVE) != 0)))
684 svp64_raise (_("unrecognized mode: `%s'"), str);
685
686 svp64->sv_mode_explicit = 1;
687 svp64->sv_mode = 0x3;
688 svp64->pr = mask;
689
690 return iter;
691 }
692
693 static char *
694 svp64_decode_mr (char *str, struct svp64_ctx *svp64)
695 {
696 str += (sizeof ("mr") - 1);
697 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
698 return NULL;
699
700 svp64->sv_mode_explicit = 1;
701 svp64->sv_mode = 0;
702 svp64->mr = 1;
703
704 *str++ = '\0';
705
706 return str;
707 }
708
709 static char *
710 svp64_decode_mrr (char *str, struct svp64_ctx *svp64)
711 {
712 str += (sizeof ("mrr") - 1);
713 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
714 return NULL;
715
716 svp64->sv_mode_explicit = 1;
717 svp64->sv_mode = 0;
718 svp64->mr = 1;
719 svp64->rg = 1;
720
721 *str++ = '\0';
722
723 return str;
724 }
725
726 static char *
727 svp64_decode_crm (char *str, struct svp64_ctx *svp64)
728 {
729 str += (sizeof ("crm") - 1);
730 if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
731 return NULL;
732
733 svp64->sv_mode_explicit = 1;
734 svp64->sv_mode = 0;
735 svp64->crm = 1;
736
737 *str++ = '\0';
738
739 return str;
740 }
741
742 static char *
743 svp64_decode_mode (char *str, struct svp64_ctx *svp64)
744 {
745 size_t i;
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),
766 };
767
768 for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i)
769 {
770 const struct svp64_decoder *entry = &table[i];
771
772 if (strncmp (str, entry->str, entry->len) == 0)
773 return entry->call (str, svp64);
774 }
775
776 return NULL;
777 }
778
779 struct svp64_str_map {
780 const char *str;
781 size_t len;
782 };
783 #define SVP64_STR_MAP(STR) \
784 { STR, (sizeof (STR) - 1) }
785
786 static bool
787 svp64_str_map_cmp(const char *str, size_t len,
788 const struct svp64_str_map *map, size_t cnt)
789 {
790 size_t i;
791
792 for (i = 0; i < cnt; ++i) {
793 const struct svp64_str_map *entry = &map[i];
794
795 if ((entry->len == len) && (memcmp(entry->str, str, len) == 0))
796 return true;
797 }
798
799 return false;
800 }
801 #define SVP64_STR_MAP_CMP(STR, LEN, MAP) \
802 svp64_str_map_cmp(STR, LEN, MAP, (sizeof (MAP) / sizeof (*MAP)))
803
804 static bool
805 svp64_is_ld(const char *str, size_t len)
806 {
807 static const struct svp64_str_map table[] = {
808 /* load byte */
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"),
814 /* load double */
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"),
821 /* FP load single */
822 SVP64_STR_MAP ("lfs"),
823 SVP64_STR_MAP ("lfsx"),
824 SVP64_STR_MAP ("lfsu"),
825 SVP64_STR_MAP ("lfsux"),
826 /* FP load double */
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"),
833 /* load half */
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"),
844 /* load word */
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"),
855 };
856
857 return SVP64_STR_MAP_CMP(str, len, table);
858 }
859
860 static bool
861 svp64_is_st(const char *str, size_t len)
862 {
863 static const struct svp64_str_map table[] = {
864 /* store byte */
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"),
871 /* store double */
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"),
889 /* store half */
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"),
896 /* store word */
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"),
903 };
904
905 return SVP64_STR_MAP_CMP(str, len, table);
906 }
907
908 static bool
909 svp64_is_bc(const char *str, size_t len)
910 {
911 static const struct svp64_str_map table[] = {
912 SVP64_STR_MAP ("bc"),
913 SVP64_STR_MAP ("bclr"),
914 };
915
916 return SVP64_STR_MAP_CMP(str, len, table);
917 }
918
919 static inline bool
920 svp64_is_rc (const char *str, size_t len)
921 {
922 return (str[len - 1] == '.');
923 }
924
925 static void
926 svp64_decode (char *str, struct svp64_ctx *svp64)
927 {
928 char *opc;
929 size_t opclen;
930 char *args;
931 size_t argslen;
932 char *iter;
933 char *base = str;
934
935 str += (sizeof ("sv.") - 1);
936 if (! ISALPHA (*str))
937 svp64_raise (_("unrecognized opcode: `%s'"), str);
938
939 opc = str;
940 for (; ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0'; ++str)
941 ;
942 opclen = (str - opc);
943 if (*str != '\0')
944 *str++ = '\0';
945
946 if (svp64_is_rc (opc, opclen))
947 svp64->rc = 1;
948
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;
955
956 for (; (iter = svp64_decode_mode (str, svp64)) != NULL; str = iter)
957 ;
958 args = str;
959 argslen = strlen (args);
960
961 svp64->desc = (const struct svp64_desc *) str_hash_find (svp64_hash, opc);
962 if (!svp64->desc)
963 svp64_raise (_("unrecognized opcode: `%s'"), str);
964
965 iter = base;
966 memmove (iter, opc, opclen);
967 iter += opclen;
968 *iter++ = ' ';
969
970 memmove (iter, args, argslen);
971 iter += argslen;
972 *iter++ = '\0';
973 }
974
975 static void
976 svp64_validate_and_fix_mode_bc (struct svp64_ctx *svp64)
977 {
978 /*
979 * Create mode and (overridden) src/dst widths.
980 * TODO: sanity-check BC modes.
981 */
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);
987 }
988
989 static void
990 svp64_validate_and_fix_mode_mr (struct svp64_ctx *svp64)
991 {
992 svp64->mode |= (1U << SVP64_MODE_REDUCE);
993 svp64_raise_if (svp64->dst_zero,
994 "dest-zero not allowed in mr mode");
995
996 if (svp64->rg)
997 svp64->mode |= (1U << SVP64_MODE_RG);
998
999 if (svp64->crm)
1000 {
1001 svp64->mode |= (1U << SVP64_MODE_CRM);
1002 svp64_raise_if (!svp64->rc, "CRM only allowed when Rc=1");
1003 }
1004
1005 /*
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)
1008 */
1009 if (svp64->subvl == 0)
1010 svp64->mode |= (svp64->dst_zero << SVP64_MODE_DZ);
1011 }
1012
1013 static void
1014 svp64_validate_and_fix_mode_ff(struct svp64_ctx *svp64)
1015 {
1016 svp64_raise_if (svp64->src_zero,
1017 "dest-zero not allowed in ff mode");
1018
1019 if (svp64->ff & SVP64_RC1_ACTIVE)
1020 {
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);
1027 }
1028 else
1029 {
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);
1035 }
1036 }
1037
1038 static void
1039 svp64_validate_and_fix_mode_sat(struct svp64_ctx *svp64)
1040 {
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);
1044 }
1045
1046 static void
1047 svp64_validate_and_fix_mode_pr(struct svp64_ctx *svp64)
1048 {
1049 svp64_raise_if (svp64->src_zero,
1050 "dest-zero not allowed in pr mode");
1051
1052 if (svp64->pr & SVP64_RC1_ACTIVE)
1053 {
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);
1060 }
1061 else
1062 {
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);
1068 }
1069 }
1070
1071 static void
1072 svp64_validate_and_fix_mode_explicit(struct svp64_ctx *svp64)
1073 {
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,
1079 };
1080
1081 return table[svp64->sv_mode] (svp64);
1082 }
1083
1084 static void
1085 svp64_validate_and_fix_mode_normal (struct svp64_ctx *svp64)
1086 {
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))
1091 {
1092 /* TODO: for now, LD/ST-indexed is ignored. */
1093 svp64->mode |= (svp64->ldst_elstride << SVP64_MODE_ELS_NORMAL);
1094 }
1095 else
1096 {
1097 /*
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
1101 */
1102 }
1103 svp64->sv_mode = 0;
1104 }
1105
1106 /*
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).
1110 *
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 |
1123 *
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 |
1134 *
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 |
1143 *
1144 * ...and branches/cr_ops are still in development.
1145 */
1146 static void
1147 svp64_validate_and_fix_mode (struct svp64_ctx *svp64)
1148 {
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);
1153 else
1154 svp64_validate_and_fix_mode_normal (svp64);
1155 }
1156
1157 static void
1158 svp64_validate_and_fix (struct svp64_ctx *svp64)
1159 {
1160 if (svp64->desc->ptype == SVP64_PTYPE_P2)
1161 {
1162 /*
1163 * Since m=xx takes precedence (overrides) sm=xx and dm=xx,
1164 * treat them as mutually exclusive.
1165 */
1166 if (svp64->mask_m_specified)
1167 {
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");
1172 }
1173
1174 /*
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.
1178 */
1179 if (svp64->has_pmask && (svp64->pmmode == 1))
1180 {
1181 svp64_raise_if (!svp64->has_smask,
1182 "need explicit source-mask in CR twin predication");
1183 }
1184 if (svp64->has_smask && (svp64->smmode == 1))
1185 {
1186 svp64_raise_if (!svp64->has_pmask,
1187 "need explicit dest-mask in CR twin predication");
1188 }
1189
1190 /* Sanity-check that 2Pred mask is same mode. */
1191 if (svp64->has_pmask && svp64->has_smask)
1192 {
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);
1196 }
1197 else if (svp64->desc->ptype == SVP64_PTYPE_P1)
1198 {
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");
1203 }
1204 }
1205
1206 if (svp64->src_zero)
1207 {
1208 svp64_raise_if (!svp64->has_smask && !svp64->mask_m_specified,
1209 "src zeroing requires a source predicate");
1210 }
1211 if (svp64->dst_zero)
1212 {
1213 svp64_raise_if (!svp64->has_pmask && !svp64->mask_m_specified,
1214 "dest zeroing requires a dest predicate");
1215 }
1216
1217 svp64_validate_and_fix_mode (svp64);
1218 }
1219
1220 static void
1221 svp64_remap_extra (struct svp64_ctx *svp64,
1222 ppc_opindex_t opindex, uint32_t value)
1223 {
1224 const struct svp64_extra_desc *desc;
1225
1226 desc = svp64_extra_desc (svp64->desc, opindex);
1227 svp64_raise_if ((desc == NULL), "cannot remap EXTRA");
1228
1229 return (*desc->set) (&svp64->insn, value);
1230 }
1231
1232 static int64_t
1233 svp64_remap_reg (struct svp64_ctx *svp64, int64_t value,
1234 ppc_opindex_t opindex, bool vector)
1235 {
1236 uint32_t field;
1237 uint32_t sv_extra;
1238
1239 svp64_raise_if (((value < 0) || (value > 127)),
1240 "register does not fit the expected range 0..127");
1241 field = (uint32_t)value;
1242
1243 if (vector)
1244 {
1245 /* cut into 5-bits 2-bits FFFFF SS */
1246 sv_extra = (field & 0x3);
1247 field >>= 2;
1248 }
1249 else
1250 {
1251 /* cut into 2-bits 5-bits SS FFFFF */
1252 sv_extra = (field >> 5);
1253 field &= 0x1F;
1254 }
1255
1256 if (svp64->desc->etype == SVP64_ETYPE_EXTRA2)
1257 {
1258 if (vector)
1259 {
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));
1264 }
1265 else
1266 {
1267 /* range is r0-r63 in increments of 1 */
1268 svp64_raise_if ( ((sv_extra >> 1) != 0),
1269 "scalar register cannot fit into EXTRA2");
1270 sv_extra &= 0x1;
1271 }
1272 }
1273 else if (vector)
1274 {
1275 /* EXTRA3 vector bit needs marking */
1276 sv_extra |= 0x4;
1277 }
1278
1279 svp64_remap_extra (svp64, opindex, sv_extra);
1280
1281 return field;
1282 }
1283
1284 static int64_t
1285 svp64_remap_gpr (struct svp64_ctx *svp64, int64_t value,
1286 ppc_opindex_t opindex, bool vector)
1287 {
1288 return svp64_remap_reg (svp64, value, opindex, vector);
1289 }
1290
1291 static int64_t
1292 svp64_remap_fpr (struct svp64_ctx *svp64, int64_t value,
1293 ppc_opindex_t opindex, bool vector)
1294 {
1295 return svp64_remap_reg (svp64, value, opindex, vector);
1296 }
1297
1298 static int64_t
1299 svp64_remap_cr (struct svp64_ctx *svp64, int64_t value,
1300 ppc_opindex_t opindex, bool vector, bool cr_bit)
1301 {
1302 uint32_t field;
1303 uint32_t subfield;
1304 uint32_t sv_extra;
1305
1306 svp64_raise_if (((value < 0) || (value > 127)),
1307 "register does not fit the expected range 0..127");
1308 field = (uint32_t)value;
1309
1310 if (cr_bit)
1311 {
1312 subfield = (field & 0x3);
1313 field >>= 2;
1314 }
1315
1316 if (vector)
1317 {
1318 /* cut into 3-bits 4-bits FFF SSSS but will cut 2 zeros off later */
1319 sv_extra = (field & 0xf);
1320 field >>= 4;
1321 }
1322 else
1323 {
1324 /* cut into 2-bits 3-bits SS FFF */
1325 sv_extra = (field >> 3);
1326 field &= 0x7;
1327 }
1328
1329 if (svp64->desc->etype == SVP64_ETYPE_EXTRA2)
1330 {
1331 if (vector)
1332 {
1333 svp64_raise_if (((sv_extra & 0x7) != 0),
1334 "vector CR cannot fit into EXTRA2");
1335 sv_extra = (0x2 | (sv_extra >> 3));
1336 }
1337 else
1338 {
1339 svp64_raise_if (((sv_extra >> 1) != 0),
1340 "scalar CR cannot fit into EXTRA2");
1341 sv_extra &= 0x1;
1342 }
1343 }
1344 else
1345 {
1346 if (vector)
1347 {
1348 svp64_raise_if (((sv_extra & 0x3) != 0),
1349 "vector CR cannot fit into EXTRA3");
1350 sv_extra = (0x4 | (sv_extra >> 2));
1351 }
1352 else
1353 {
1354 svp64_raise_if (((sv_extra >> 2) != 0),
1355 "scalar CR cannot fit into EXTRA3");
1356 sv_extra &= 0x3;
1357 }
1358 }
1359
1360 if (cr_bit)
1361 field = ((field << 2) | subfield);
1362
1363 svp64_remap_extra (svp64, opindex, sv_extra);
1364
1365 return field;
1366 }
1367
1368 static int64_t
1369 svp64_remap (struct svp64_ctx *ctx, int64_t value,
1370 const struct powerpc_operand *operand, bool vector)
1371 {
1372 const ppc_opindex_t opindex = (ppc_opindex_t)(operand - powerpc_operands);
1373
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)
1379 {
1380 bool cr_bit = ((operand->flags & PPC_OPERAND_CR_BIT) != 0);
1381
1382 return svp64_remap_cr (ctx, value, opindex, vector, cr_bit);
1383 }
1384
1385 return value;
1386 }
1387
1388 static void
1389 svp64_assemble (char *str)
1390 {
1391 struct svp64_ctx svp64;
1392
1393 if (setjmp (svp64_exception) != 0)
1394 return;
1395
1396 memset (&svp64, 0, sizeof (svp64));
1397
1398 svp64_decode (str, &svp64);
1399 svp64_validate_and_fix (&svp64);
1400
1401 svp64_insn_set_prefix_po (&svp64.insn, 0x1);
1402 svp64_insn_set_prefix_id (&svp64.insn, 0x3);
1403
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);
1412
1413 ppc_assemble (str, &svp64);
1414 }