@@ -2533,3 +2533,119 @@ static bool trans_vid_v(DisasContext *s, arg_vid_v *a)
2533
2533
}
2534
2534
return false;
2535
2535
}
2536
+
2537
+ /*
2538
+ *** Vector Permutation Instructions
2539
+ */
2540
+
2541
+ /* Integer Extract Instruction */
2542
+
2543
+ static void load_element (TCGv_i64 dest , TCGv_ptr base ,
2544
+ int ofs , int sew )
2545
+ {
2546
+ switch (sew ) {
2547
+ case MO_8 :
2548
+ tcg_gen_ld8u_i64 (dest , base , ofs );
2549
+ break ;
2550
+ case MO_16 :
2551
+ tcg_gen_ld16u_i64 (dest , base , ofs );
2552
+ break ;
2553
+ case MO_32 :
2554
+ tcg_gen_ld32u_i64 (dest , base , ofs );
2555
+ break ;
2556
+ case MO_64 :
2557
+ tcg_gen_ld_i64 (dest , base , ofs );
2558
+ break ;
2559
+ default :
2560
+ g_assert_not_reached ();
2561
+ break ;
2562
+ }
2563
+ }
2564
+
2565
+ /* offset of the idx element with base regsiter r */
2566
+ static uint32_t endian_ofs (DisasContext * s , int r , int idx )
2567
+ {
2568
+ #ifdef HOST_WORDS_BIGENDIAN
2569
+ return vreg_ofs (s , r ) + ((idx ^ (7 >> s -> sew )) << s -> sew );
2570
+ #else
2571
+ return vreg_ofs (s , r ) + (idx << s -> sew );
2572
+ #endif
2573
+ }
2574
+
2575
+ /* adjust the index according to the endian */
2576
+ static void endian_adjust (TCGv_i32 ofs , int sew )
2577
+ {
2578
+ #ifdef HOST_WORDS_BIGENDIAN
2579
+ tcg_gen_xori_i32 (ofs , ofs , 7 >> sew );
2580
+ #endif
2581
+ }
2582
+
2583
+ /* Load idx >= VLMAX ? 0 : vreg[idx] */
2584
+ static void vec_element_loadx (DisasContext * s , TCGv_i64 dest ,
2585
+ int vreg , TCGv idx , int vlmax )
2586
+ {
2587
+ TCGv_i32 ofs = tcg_temp_new_i32 ();
2588
+ TCGv_ptr base = tcg_temp_new_ptr ();
2589
+ TCGv_i64 t_idx = tcg_temp_new_i64 ();
2590
+ TCGv_i64 t_vlmax , t_zero ;
2591
+
2592
+ /*
2593
+ * Mask the index to the length so that we do
2594
+ * not produce an out-of-range load.
2595
+ */
2596
+ tcg_gen_trunc_tl_i32 (ofs , idx );
2597
+ tcg_gen_andi_i32 (ofs , ofs , vlmax - 1 );
2598
+
2599
+ /* Convert the index to an offset. */
2600
+ endian_adjust (ofs , s -> sew );
2601
+ tcg_gen_shli_i32 (ofs , ofs , s -> sew );
2602
+
2603
+ /* Convert the index to a pointer. */
2604
+ tcg_gen_ext_i32_ptr (base , ofs );
2605
+ tcg_gen_add_ptr (base , base , cpu_env );
2606
+
2607
+ /* Perform the load. */
2608
+ load_element (dest , base ,
2609
+ vreg_ofs (s , vreg ), s -> sew );
2610
+ tcg_temp_free_ptr (base );
2611
+ tcg_temp_free_i32 (ofs );
2612
+
2613
+ /* Flush out-of-range indexing to zero. */
2614
+ t_vlmax = tcg_const_i64 (vlmax );
2615
+ t_zero = tcg_const_i64 (0 );
2616
+ tcg_gen_extu_tl_i64 (t_idx , idx );
2617
+
2618
+ tcg_gen_movcond_i64 (TCG_COND_LTU , dest , t_idx ,
2619
+ t_vlmax , dest , t_zero );
2620
+
2621
+ tcg_temp_free_i64 (t_vlmax );
2622
+ tcg_temp_free_i64 (t_zero );
2623
+ tcg_temp_free_i64 (t_idx );
2624
+ }
2625
+
2626
+ static void vec_element_loadi (DisasContext * s , TCGv_i64 dest ,
2627
+ int vreg , int idx )
2628
+ {
2629
+ load_element (dest , cpu_env , endian_ofs (s , vreg , idx ), s -> sew );
2630
+ }
2631
+
2632
+ static bool trans_vext_x_v (DisasContext * s , arg_r * a )
2633
+ {
2634
+ TCGv_i64 tmp = tcg_temp_new_i64 ();
2635
+ TCGv dest = tcg_temp_new ();
2636
+
2637
+ if (a -> rs1 == 0 ) {
2638
+ /* Special case vmv.x.s rd, vs2. */
2639
+ vec_element_loadi (s , tmp , a -> rs2 , 0 );
2640
+ } else {
2641
+ /* This instruction ignores LMUL and vector register groups */
2642
+ int vlmax = s -> vlen >> (3 + s -> sew );
2643
+ vec_element_loadx (s , tmp , a -> rs2 , cpu_gpr [a -> rs1 ], vlmax );
2644
+ }
2645
+ tcg_gen_trunc_i64_tl (dest , tmp );
2646
+ gen_set_gpr (a -> rd , dest );
2647
+
2648
+ tcg_temp_free (dest );
2649
+ tcg_temp_free_i64 (tmp );
2650
+ return true;
2651
+ }
0 commit comments