@@ -40,6 +40,37 @@ macro_rules! debug_assert_valid_regpair {
40
40
} ;
41
41
}
42
42
43
+ macro_rules! debug_assert_valid_fp_regpair {
44
+ ( $hi: expr, $lo: expr) => {
45
+ if cfg!( debug_assertions) {
46
+ match ( $hi. to_real_reg( ) , $lo. to_real_reg( ) ) {
47
+ ( Some ( hi) , Some ( lo) ) => {
48
+ assert!(
49
+ hi. hw_enc( ) & 2 == 0 ,
50
+ "High register is not valid: {}" ,
51
+ show_reg( $hi)
52
+ ) ;
53
+ assert_eq!(
54
+ hi. hw_enc( ) + 2 ,
55
+ lo. hw_enc( ) ,
56
+ "Low register is not valid: {}, {}" ,
57
+ show_reg( $hi) ,
58
+ show_reg( $lo)
59
+ ) ;
60
+ }
61
+
62
+ _ => {
63
+ panic!(
64
+ "Expected real registers for {} {}" ,
65
+ show_reg( $hi) ,
66
+ show_reg( $lo)
67
+ ) ;
68
+ }
69
+ }
70
+ }
71
+ } ;
72
+ }
73
+
43
74
const OPCODE_BRAS : u16 = 0xa75 ;
44
75
const OPCODE_BCR : u16 = 0xa74 ;
45
76
const OPCODE_LDR : u16 = 0x28 ;
@@ -2396,24 +2427,29 @@ impl Inst {
2396
2427
let ( opcode, m3, m4, m5, opcode_fpr) = match fpu_op {
2397
2428
FPUOp1 :: Abs32 => ( 0xe7cc , 2 , 8 , 2 , Some ( 0xb300 ) ) , // WFPSO, LPEBR
2398
2429
FPUOp1 :: Abs64 => ( 0xe7cc , 3 , 8 , 2 , Some ( 0xb310 ) ) , // WFPSO, LPDBR
2430
+ FPUOp1 :: Abs128 => ( 0xe7cc , 4 , 8 , 2 , None ) , // WFPSO
2399
2431
FPUOp1 :: Abs32x4 => ( 0xe7cc , 2 , 0 , 2 , None ) , // VFPSO
2400
2432
FPUOp1 :: Abs64x2 => ( 0xe7cc , 3 , 0 , 2 , None ) , // VFPSO
2401
2433
FPUOp1 :: Neg32 => ( 0xe7cc , 2 , 8 , 0 , Some ( 0xb303 ) ) , // WFPSO, LCEBR
2402
2434
FPUOp1 :: Neg64 => ( 0xe7cc , 3 , 8 , 0 , Some ( 0xb313 ) ) , // WFPSO, LCDBR
2435
+ FPUOp1 :: Neg128 => ( 0xe7cc , 4 , 8 , 0 , None ) , // WFPSO
2403
2436
FPUOp1 :: Neg32x4 => ( 0xe7cc , 2 , 0 , 0 , None ) , // VFPSO
2404
2437
FPUOp1 :: Neg64x2 => ( 0xe7cc , 3 , 0 , 0 , None ) , // VFPSO
2405
2438
FPUOp1 :: NegAbs32 => ( 0xe7cc , 2 , 8 , 1 , Some ( 0xb301 ) ) , // WFPSO, LNEBR
2406
2439
FPUOp1 :: NegAbs64 => ( 0xe7cc , 3 , 8 , 1 , Some ( 0xb311 ) ) , // WFPSO, LNDBR
2440
+ FPUOp1 :: NegAbs128 => ( 0xe7cc , 4 , 8 , 1 , None ) , // WFPSO
2407
2441
FPUOp1 :: NegAbs32x4 => ( 0xe7cc , 2 , 0 , 1 , None ) , // VFPSO
2408
2442
FPUOp1 :: NegAbs64x2 => ( 0xe7cc , 3 , 0 , 1 , None ) , // VFPSO
2409
2443
FPUOp1 :: Sqrt32 => ( 0xe7ce , 2 , 8 , 0 , Some ( 0xb314 ) ) , // WFSQ, SQEBR
2410
2444
FPUOp1 :: Sqrt64 => ( 0xe7ce , 3 , 8 , 0 , Some ( 0xb315 ) ) , // WFSQ, SQDBR
2445
+ FPUOp1 :: Sqrt128 => ( 0xe7ce , 4 , 8 , 0 , None ) , // WFSQ
2411
2446
FPUOp1 :: Sqrt32x4 => ( 0xe7ce , 2 , 0 , 0 , None ) , // VFSQ
2412
2447
FPUOp1 :: Sqrt64x2 => ( 0xe7ce , 3 , 0 , 0 , None ) , // VFSQ
2413
2448
FPUOp1 :: Cvt32To64 => ( 0xe7c4 , 2 , 8 , 0 , Some ( 0xb304 ) ) , // WFLL, LDEBR
2414
2449
FPUOp1 :: Cvt32x4To64x2 => ( 0xe7c4 , 2 , 0 , 0 , None ) , // VFLL
2450
+ FPUOp1 :: Cvt64To128 => ( 0xe7c4 , 3 , 8 , 0 , None ) , // WFLL
2415
2451
} ;
2416
- if m4 == 8 && is_fpr ( rd. to_reg ( ) ) && is_fpr ( rn) {
2452
+ if m4 == 8 && opcode_fpr . is_some ( ) && is_fpr ( rd. to_reg ( ) ) && is_fpr ( rn) {
2417
2453
put ( sink, & enc_rre ( opcode_fpr. unwrap ( ) , rd. to_reg ( ) , rn) ) ;
2418
2454
} else {
2419
2455
put ( sink, & enc_vrr_a ( opcode, rd. to_reg ( ) , rn, m3, m4, m5) ) ;
@@ -2423,34 +2459,42 @@ impl Inst {
2423
2459
let ( opcode, m4, m5, m6, opcode_fpr) = match fpu_op {
2424
2460
FPUOp2 :: Add32 => ( 0xe7e3 , 2 , 8 , 0 , Some ( 0xb30a ) ) , // WFA, AEBR
2425
2461
FPUOp2 :: Add64 => ( 0xe7e3 , 3 , 8 , 0 , Some ( 0xb31a ) ) , // WFA, ADBR
2462
+ FPUOp2 :: Add128 => ( 0xe7e3 , 4 , 8 , 0 , None ) , // WFA
2426
2463
FPUOp2 :: Add32x4 => ( 0xe7e3 , 2 , 0 , 0 , None ) , // VFA
2427
2464
FPUOp2 :: Add64x2 => ( 0xe7e3 , 3 , 0 , 0 , None ) , // VFA
2428
2465
FPUOp2 :: Sub32 => ( 0xe7e2 , 2 , 8 , 0 , Some ( 0xb30b ) ) , // WFS, SEBR
2429
2466
FPUOp2 :: Sub64 => ( 0xe7e2 , 3 , 8 , 0 , Some ( 0xb31b ) ) , // WFS, SDBR
2467
+ FPUOp2 :: Sub128 => ( 0xe7e2 , 4 , 8 , 0 , None ) , // WFS
2430
2468
FPUOp2 :: Sub32x4 => ( 0xe7e2 , 2 , 0 , 0 , None ) , // VFS
2431
2469
FPUOp2 :: Sub64x2 => ( 0xe7e2 , 3 , 0 , 0 , None ) , // VFS
2432
2470
FPUOp2 :: Mul32 => ( 0xe7e7 , 2 , 8 , 0 , Some ( 0xb317 ) ) , // WFM, MEEBR
2433
2471
FPUOp2 :: Mul64 => ( 0xe7e7 , 3 , 8 , 0 , Some ( 0xb31c ) ) , // WFM, MDBR
2472
+ FPUOp2 :: Mul128 => ( 0xe7e7 , 4 , 8 , 0 , None ) , // WFM
2434
2473
FPUOp2 :: Mul32x4 => ( 0xe7e7 , 2 , 0 , 0 , None ) , // VFM
2435
2474
FPUOp2 :: Mul64x2 => ( 0xe7e7 , 3 , 0 , 0 , None ) , // VFM
2436
2475
FPUOp2 :: Div32 => ( 0xe7e5 , 2 , 8 , 0 , Some ( 0xb30d ) ) , // WFD, DEBR
2437
2476
FPUOp2 :: Div64 => ( 0xe7e5 , 3 , 8 , 0 , Some ( 0xb31d ) ) , // WFD, DDBR
2477
+ FPUOp2 :: Div128 => ( 0xe7e5 , 4 , 8 , 0 , None ) , // WFD
2438
2478
FPUOp2 :: Div32x4 => ( 0xe7e5 , 2 , 0 , 0 , None ) , // VFD
2439
2479
FPUOp2 :: Div64x2 => ( 0xe7e5 , 3 , 0 , 0 , None ) , // VFD
2440
2480
FPUOp2 :: Max32 => ( 0xe7ef , 2 , 8 , 1 , None ) , // WFMAX
2441
2481
FPUOp2 :: Max64 => ( 0xe7ef , 3 , 8 , 1 , None ) , // WFMAX
2482
+ FPUOp2 :: Max128 => ( 0xe7ef , 4 , 8 , 1 , None ) , // WFMAX
2442
2483
FPUOp2 :: Max32x4 => ( 0xe7ef , 2 , 0 , 1 , None ) , // VFMAX
2443
2484
FPUOp2 :: Max64x2 => ( 0xe7ef , 3 , 0 , 1 , None ) , // VFMAX
2444
2485
FPUOp2 :: Min32 => ( 0xe7ee , 2 , 8 , 1 , None ) , // WFMIN
2445
2486
FPUOp2 :: Min64 => ( 0xe7ee , 3 , 8 , 1 , None ) , // WFMIN
2487
+ FPUOp2 :: Min128 => ( 0xe7ee , 4 , 8 , 1 , None ) , // WFMIN
2446
2488
FPUOp2 :: Min32x4 => ( 0xe7ee , 2 , 0 , 1 , None ) , // VFMIN
2447
2489
FPUOp2 :: Min64x2 => ( 0xe7ee , 3 , 0 , 1 , None ) , // VFMIN
2448
2490
FPUOp2 :: MaxPseudo32 => ( 0xe7ef , 2 , 8 , 3 , None ) , // WFMAX
2449
2491
FPUOp2 :: MaxPseudo64 => ( 0xe7ef , 3 , 8 , 3 , None ) , // WFMAX
2492
+ FPUOp2 :: MaxPseudo128 => ( 0xe7ef , 4 , 8 , 3 , None ) , // WFMAX
2450
2493
FPUOp2 :: MaxPseudo32x4 => ( 0xe7ef , 2 , 0 , 3 , None ) , // VFMAX
2451
2494
FPUOp2 :: MaxPseudo64x2 => ( 0xe7ef , 3 , 0 , 3 , None ) , // VFMAX
2452
2495
FPUOp2 :: MinPseudo32 => ( 0xe7ee , 2 , 8 , 3 , None ) , // WFMIN
2453
2496
FPUOp2 :: MinPseudo64 => ( 0xe7ee , 3 , 8 , 3 , None ) , // WFMIN
2497
+ FPUOp2 :: MinPseudo128 => ( 0xe7ee , 4 , 8 , 3 , None ) , // WFMIN
2454
2498
FPUOp2 :: MinPseudo32x4 => ( 0xe7ee , 2 , 0 , 3 , None ) , // VFMIN
2455
2499
FPUOp2 :: MinPseudo64x2 => ( 0xe7ee , 3 , 0 , 3 , None ) , // VFMIN
2456
2500
} ;
@@ -2471,14 +2515,22 @@ impl Inst {
2471
2515
let ( opcode, m5, m6, opcode_fpr) = match fpu_op {
2472
2516
FPUOp3 :: MAdd32 => ( 0xe78f , 8 , 2 , Some ( 0xb30e ) ) , // WFMA, MAEBR
2473
2517
FPUOp3 :: MAdd64 => ( 0xe78f , 8 , 3 , Some ( 0xb31e ) ) , // WFMA, MADBR
2518
+ FPUOp3 :: MAdd128 => ( 0xe78f , 8 , 4 , None ) , // WFMA
2474
2519
FPUOp3 :: MAdd32x4 => ( 0xe78f , 0 , 2 , None ) , // VFMA
2475
2520
FPUOp3 :: MAdd64x2 => ( 0xe78f , 0 , 3 , None ) , // VFMA
2476
2521
FPUOp3 :: MSub32 => ( 0xe78e , 8 , 2 , Some ( 0xb30f ) ) , // WFMS, MSEBR
2477
2522
FPUOp3 :: MSub64 => ( 0xe78e , 8 , 3 , Some ( 0xb31f ) ) , // WFMS, MSDBR
2523
+ FPUOp3 :: MSub128 => ( 0xe78e , 8 , 4 , None ) , // WFMS
2478
2524
FPUOp3 :: MSub32x4 => ( 0xe78e , 0 , 2 , None ) , // VFMS
2479
2525
FPUOp3 :: MSub64x2 => ( 0xe78e , 0 , 3 , None ) , // VFMS
2480
2526
} ;
2481
- if m5 == 8 && rd. to_reg ( ) == ra && is_fpr ( rn) && is_fpr ( rm) && is_fpr ( ra) {
2527
+ if m5 == 8
2528
+ && opcode_fpr. is_some ( )
2529
+ && rd. to_reg ( ) == ra
2530
+ && is_fpr ( rn)
2531
+ && is_fpr ( rm)
2532
+ && is_fpr ( ra)
2533
+ {
2482
2534
put ( sink, & enc_rrd ( opcode_fpr. unwrap ( ) , rd. to_reg ( ) , rm, rn) ) ;
2483
2535
} else {
2484
2536
put ( sink, & enc_vrr_e ( opcode, rd. to_reg ( ) , rn, rm, ra, m5, m6) ) ;
@@ -2497,8 +2549,10 @@ impl Inst {
2497
2549
let ( opcode, m3, m4, opcode_fpr) = match op {
2498
2550
FpuRoundOp :: Cvt64To32 => ( 0xe7c5 , 3 , 8 , Some ( 0xb344 ) ) , // WFLR, LEDBR(A)
2499
2551
FpuRoundOp :: Cvt64x2To32x4 => ( 0xe7c5 , 3 , 0 , None ) , // VFLR
2552
+ FpuRoundOp :: Cvt128To64 => ( 0xe7c5 , 4 , 8 , None ) , // WFLR
2500
2553
FpuRoundOp :: Round32 => ( 0xe7c7 , 2 , 8 , Some ( 0xb357 ) ) , // WFI, FIEBR
2501
2554
FpuRoundOp :: Round64 => ( 0xe7c7 , 3 , 8 , Some ( 0xb35f ) ) , // WFI, FIDBR
2555
+ FpuRoundOp :: Round128 => ( 0xe7c7 , 4 , 8 , None ) , // WFI
2502
2556
FpuRoundOp :: Round32x4 => ( 0xe7c7 , 2 , 0 , None ) , // VFI
2503
2557
FpuRoundOp :: Round64x2 => ( 0xe7c7 , 3 , 0 , None ) , // VFI
2504
2558
FpuRoundOp :: ToSInt32 => ( 0xe7c2 , 2 , 8 , None ) , // WCSFP
@@ -2527,6 +2581,50 @@ impl Inst {
2527
2581
put ( sink, & enc_vrr_a ( opcode, rd. to_reg ( ) , rn, m3, m4, mode) ) ;
2528
2582
}
2529
2583
}
2584
+ & Inst :: FpuConv128FromInt { op, mode, rd, rn } => {
2585
+ let rd1 = rd. hi ;
2586
+ let rd2 = rd. lo ;
2587
+ debug_assert_valid_fp_regpair ! ( rd1. to_reg( ) , rd2. to_reg( ) ) ;
2588
+
2589
+ let mode = match mode {
2590
+ FpuRoundMode :: Current => 0 ,
2591
+ FpuRoundMode :: ToNearest => 1 ,
2592
+ FpuRoundMode :: ShorterPrecision => 3 ,
2593
+ FpuRoundMode :: ToNearestTiesToEven => 4 ,
2594
+ FpuRoundMode :: ToZero => 5 ,
2595
+ FpuRoundMode :: ToPosInfinity => 6 ,
2596
+ FpuRoundMode :: ToNegInfinity => 7 ,
2597
+ } ;
2598
+ let opcode = match op {
2599
+ FpuConv128Op :: SInt32 => 0xb396 , // CXFBRA
2600
+ FpuConv128Op :: SInt64 => 0xb3a6 , // CXGBRA
2601
+ FpuConv128Op :: UInt32 => 0xb392 , // CXLFBR
2602
+ FpuConv128Op :: UInt64 => 0xb3a2 , // CXLGBR
2603
+ } ;
2604
+ put ( sink, & enc_rrf_cde ( opcode, rd1. to_reg ( ) , rn, mode, 0 ) ) ;
2605
+ }
2606
+ & Inst :: FpuConv128ToInt { op, mode, rd, rn } => {
2607
+ let rn1 = rn. hi ;
2608
+ let rn2 = rn. lo ;
2609
+ debug_assert_valid_fp_regpair ! ( rn1, rn2) ;
2610
+
2611
+ let mode = match mode {
2612
+ FpuRoundMode :: Current => 0 ,
2613
+ FpuRoundMode :: ToNearest => 1 ,
2614
+ FpuRoundMode :: ShorterPrecision => 3 ,
2615
+ FpuRoundMode :: ToNearestTiesToEven => 4 ,
2616
+ FpuRoundMode :: ToZero => 5 ,
2617
+ FpuRoundMode :: ToPosInfinity => 6 ,
2618
+ FpuRoundMode :: ToNegInfinity => 7 ,
2619
+ } ;
2620
+ let opcode = match op {
2621
+ FpuConv128Op :: SInt32 => 0xb39a , // CFXBRA
2622
+ FpuConv128Op :: SInt64 => 0xb3aa , // CGXBRA
2623
+ FpuConv128Op :: UInt32 => 0xb39e , // CLFXBR
2624
+ FpuConv128Op :: UInt64 => 0xb3ae , // CLGXBR
2625
+ } ;
2626
+ put ( sink, & enc_rrf_cde ( opcode, rd. to_reg ( ) , rn1, mode, 0 ) ) ;
2627
+ }
2530
2628
& Inst :: FpuCmp32 { rn, rm } => {
2531
2629
if is_fpr ( rn) && is_fpr ( rm) {
2532
2630
let opcode = 0xb309 ; // CEBR
@@ -2545,6 +2643,10 @@ impl Inst {
2545
2643
put ( sink, & enc_vrr_a ( opcode, rn, rm, 3 , 0 , 0 ) ) ;
2546
2644
}
2547
2645
}
2646
+ & Inst :: FpuCmp128 { rn, rm } => {
2647
+ let opcode = 0xe7cb ; // WFC
2648
+ put ( sink, & enc_vrr_a ( opcode, rn, rm, 4 , 0 , 0 ) ) ;
2649
+ }
2548
2650
2549
2651
& Inst :: VecRRR { op, rd, rn, rm } => {
2550
2652
let ( opcode, m4) = match op {
0 commit comments