| ... | @@ -499,20 +499,29 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -499,20 +499,29 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 499 | .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub), | 499 | .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub), |
| 500 | | 500 | |
| 501 | .add => try self.airBinOp(inst, .add), | 501 | .add => try self.airBinOp(inst, .add), |
| 502 | .addwrap => @panic("TODO try self.airAddWrap(inst)"), | 502 | .addwrap => try self.airBinOp(inst, .addwrap), |
| | 503 | .sub => try self.airBinOp(inst, .sub), |
| | 504 | .subwrap => try self.airBinOp(inst, .subwrap), |
| | 505 | .mul => try self.airBinOp(inst, .mul), |
| | 506 | .mulwrap => try self.airBinOp(inst, .mulwrap), |
| | 507 | .shl => try self.airBinOp(inst, .shl), |
| | 508 | .shl_exact => try self.airBinOp(inst, .shl_exact), |
| | 509 | .shr => try self.airBinOp(inst, .shr), |
| | 510 | .shr_exact => try self.airBinOp(inst, .shr_exact), |
| | 511 | .bool_and => try self.airBinOp(inst, .bool_and), |
| | 512 | .bool_or => try self.airBinOp(inst, .bool_or), |
| | 513 | .bit_and => try self.airBinOp(inst, .bit_and), |
| | 514 | .bit_or => try self.airBinOp(inst, .bit_or), |
| | 515 | .xor => try self.airBinOp(inst, .xor), |
| | 516 | |
| 503 | .add_sat => @panic("TODO try self.airAddSat(inst)"), | 517 | .add_sat => @panic("TODO try self.airAddSat(inst)"), |
| 504 | .sub => @panic("TODO try self.airBinOp(inst)"), | | |
| 505 | .subwrap => @panic("TODO try self.airSubWrap(inst)"), | | |
| 506 | .sub_sat => @panic("TODO try self.airSubSat(inst)"), | 518 | .sub_sat => @panic("TODO try self.airSubSat(inst)"), |
| 507 | .mul => @panic("TODO try self.airMul(inst)"), | | |
| 508 | .mulwrap => @panic("TODO try self.airMulWrap(inst)"), | | |
| 509 | .mul_sat => @panic("TODO try self.airMulSat(inst)"), | 519 | .mul_sat => @panic("TODO try self.airMulSat(inst)"), |
| 510 | .rem => try self.airRem(inst), | | |
| 511 | .mod => try self.airMod(inst), | | |
| 512 | .shl, .shl_exact => @panic("TODO try self.airShl(inst)"), | | |
| 513 | .shl_sat => @panic("TODO try self.airShlSat(inst)"), | 520 | .shl_sat => @panic("TODO try self.airShlSat(inst)"), |
| 514 | .min => @panic("TODO try self.airMin(inst)"), | 521 | .min => @panic("TODO try self.airMin(inst)"), |
| 515 | .max => @panic("TODO try self.airMax(inst)"), | 522 | .max => @panic("TODO try self.airMax(inst)"), |
| | 523 | .rem => try self.airRem(inst), |
| | 524 | .mod => try self.airMod(inst), |
| 516 | .slice => try self.airSlice(inst), | 525 | .slice => try self.airSlice(inst), |
| 517 | | 526 | |
| 518 | .sqrt, | 527 | .sqrt, |
| ... | @@ -548,13 +557,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -548,13 +557,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 548 | .cmp_vector => @panic("TODO try self.airCmpVector(inst)"), | 557 | .cmp_vector => @panic("TODO try self.airCmpVector(inst)"), |
| 549 | .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst), | 558 | .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst), |
| 550 | | 559 | |
| 551 | .bool_and => try self.airBinOp(inst, .bool_and), | | |
| 552 | .bool_or => try self.airBinOp(inst, .bool_or), | | |
| 553 | .bit_and => try self.airBinOp(inst, .bit_and), | | |
| 554 | .bit_or => try self.airBinOp(inst, .bit_or), | | |
| 555 | .xor => try self.airBinOp(inst, .xor), | | |
| 556 | .shr, .shr_exact => @panic("TODO try self.airShr(inst)"), | | |
| 557 | | | |
| 558 | .alloc => try self.airAlloc(inst), | 560 | .alloc => try self.airAlloc(inst), |
| 559 | .ret_ptr => try self.airRetPtr(inst), | 561 | .ret_ptr => try self.airRetPtr(inst), |
| 560 | .arg => try self.airArg(inst), | 562 | .arg => try self.airArg(inst), |
| ... | @@ -2397,6 +2399,10 @@ fn binOp( | ... | @@ -2397,6 +2399,10 @@ fn binOp( |
| 2397 | switch (tag) { | 2399 | switch (tag) { |
| 2398 | .add, | 2400 | .add, |
| 2399 | .sub, | 2401 | .sub, |
| | 2402 | .mul, |
| | 2403 | .bit_and, |
| | 2404 | .bit_or, |
| | 2405 | .xor, |
| 2400 | .cmp_eq, | 2406 | .cmp_eq, |
| 2401 | => { | 2407 | => { |
| 2402 | switch (lhs_ty.zigTypeTag()) { | 2408 | switch (lhs_ty.zigTypeTag()) { |
| ... | @@ -2411,12 +2417,20 @@ fn binOp( | ... | @@ -2411,12 +2417,20 @@ fn binOp( |
| 2411 | // operands | 2417 | // operands |
| 2412 | const lhs_immediate_ok = switch (tag) { | 2418 | const lhs_immediate_ok = switch (tag) { |
| 2413 | .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12), | 2419 | .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12), |
| | 2420 | .mul => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12), |
| | 2421 | .bit_and => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12), |
| | 2422 | .bit_or => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12), |
| | 2423 | .xor => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12), |
| 2414 | .sub, .cmp_eq => false, | 2424 | .sub, .cmp_eq => false, |
| 2415 | else => unreachable, | 2425 | else => unreachable, |
| 2416 | }; | 2426 | }; |
| 2417 | const rhs_immediate_ok = switch (tag) { | 2427 | const rhs_immediate_ok = switch (tag) { |
| 2418 | .add, | 2428 | .add, |
| 2419 | .sub, | 2429 | .sub, |
| | 2430 | .mul, |
| | 2431 | .bit_and, |
| | 2432 | .bit_or, |
| | 2433 | .xor, |
| 2420 | .cmp_eq, | 2434 | .cmp_eq, |
| 2421 | => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12), | 2435 | => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12), |
| 2422 | else => unreachable, | 2436 | else => unreachable, |
| ... | @@ -2425,6 +2439,10 @@ fn binOp( | ... | @@ -2425,6 +2439,10 @@ fn binOp( |
| 2425 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 2439 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 2426 | .add => .add, | 2440 | .add => .add, |
| 2427 | .sub => .sub, | 2441 | .sub => .sub, |
| | 2442 | .mul => .mulx, |
| | 2443 | .bit_and => .@"and", |
| | 2444 | .bit_or => .@"or", |
| | 2445 | .xor => .xor, |
| 2428 | .cmp_eq => .cmp, | 2446 | .cmp_eq => .cmp, |
| 2429 | else => unreachable, | 2447 | else => unreachable, |
| 2430 | }; | 2448 | }; |
| ... | @@ -2446,72 +2464,60 @@ fn binOp( | ... | @@ -2446,72 +2464,60 @@ fn binOp( |
| 2446 | } | 2464 | } |
| 2447 | }, | 2465 | }, |
| 2448 | | 2466 | |
| 2449 | .div_trunc => { | 2467 | .addwrap, |
| | 2468 | .subwrap, |
| | 2469 | .mulwrap, |
| | 2470 | => { |
| | 2471 | const base_tag: Air.Inst.Tag = switch (tag) { |
| | 2472 | .addwrap => .add, |
| | 2473 | .subwrap => .sub, |
| | 2474 | .mulwrap => .mul, |
| | 2475 | else => unreachable, |
| | 2476 | }; |
| | 2477 | |
| | 2478 | // Generate the base operation |
| | 2479 | const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); |
| | 2480 | |
| | 2481 | // Truncate if necessary |
| 2450 | switch (lhs_ty.zigTypeTag()) { | 2482 | switch (lhs_ty.zigTypeTag()) { |
| 2451 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2483 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 2452 | .Int => { | 2484 | .Int => { |
| 2453 | assert(lhs_ty.eql(rhs_ty, mod)); | | |
| 2454 | const int_info = lhs_ty.intInfo(self.target.*); | 2485 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2455 | if (int_info.bits <= 64) { | 2486 | if (int_info.bits <= 64) { |
| 2456 | const rhs_immediate_ok = switch (tag) { | 2487 | const result_reg = result.register; |
| 2457 | .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12), | 2488 | try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits); |
| 2458 | else => unreachable, | 2489 | return result; |
| 2459 | }; | | |
| 2460 | | | |
| 2461 | const mir_tag: Mir.Inst.Tag = switch (tag) { | | |
| 2462 | .div_trunc => switch (int_info.signedness) { | | |
| 2463 | .signed => Mir.Inst.Tag.sdivx, | | |
| 2464 | .unsigned => Mir.Inst.Tag.udivx, | | |
| 2465 | }, | | |
| 2466 | else => unreachable, | | |
| 2467 | }; | | |
| 2468 | | | |
| 2469 | if (rhs_immediate_ok) { | | |
| 2470 | return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, true, metadata); | | |
| 2471 | } else { | | |
| 2472 | return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); | | |
| 2473 | } | | |
| 2474 | } else { | 2490 | } else { |
| 2475 | return self.fail("TODO binary operations on int with bits > 64", .{}); | 2491 | return self.fail("TODO binary operations on integers > u64/i64", .{}); |
| 2476 | } | 2492 | } |
| 2477 | }, | 2493 | }, |
| 2478 | else => unreachable, | 2494 | else => unreachable, |
| 2479 | } | 2495 | } |
| 2480 | }, | 2496 | }, |
| 2481 | | 2497 | |
| 2482 | .mul => { | 2498 | .div_trunc => { |
| 2483 | switch (lhs_ty.zigTypeTag()) { | 2499 | switch (lhs_ty.zigTypeTag()) { |
| 2484 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2500 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 2485 | .Int => { | 2501 | .Int => { |
| 2486 | assert(lhs_ty.eql(rhs_ty, mod)); | 2502 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2487 | const int_info = lhs_ty.intInfo(self.target.*); | 2503 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2488 | if (int_info.bits <= 64) { | 2504 | if (int_info.bits <= 64) { |
| 2489 | // Only say yes if the operation is | | |
| 2490 | // commutative, i.e. we can swap both of the | | |
| 2491 | // operands | | |
| 2492 | const lhs_immediate_ok = switch (tag) { | | |
| 2493 | .mul => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12), | | |
| 2494 | else => unreachable, | | |
| 2495 | }; | | |
| 2496 | const rhs_immediate_ok = switch (tag) { | 2505 | const rhs_immediate_ok = switch (tag) { |
| 2497 | .mul => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12), | 2506 | .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12), |
| 2498 | else => unreachable, | 2507 | else => unreachable, |
| 2499 | }; | 2508 | }; |
| 2500 | | 2509 | |
| 2501 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 2510 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 2502 | .mul => .mulx, | 2511 | .div_trunc => switch (int_info.signedness) { |
| | 2512 | .signed => Mir.Inst.Tag.sdivx, |
| | 2513 | .unsigned => Mir.Inst.Tag.udivx, |
| | 2514 | }, |
| 2503 | else => unreachable, | 2515 | else => unreachable, |
| 2504 | }; | 2516 | }; |
| 2505 | | 2517 | |
| 2506 | if (rhs_immediate_ok) { | 2518 | if (rhs_immediate_ok) { |
| 2507 | // At this point, rhs is an immediate | 2519 | return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, true, metadata); |
| 2508 | return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata); | | |
| 2509 | } else if (lhs_immediate_ok) { | | |
| 2510 | // swap lhs and rhs | | |
| 2511 | // At this point, lhs is an immediate | | |
| 2512 | return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata); | | |
| 2513 | } else { | 2520 | } else { |
| 2514 | // TODO convert large immediates to register before adding | | |
| 2515 | return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); | 2521 | return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); |
| 2516 | } | 2522 | } |
| 2517 | } else { | 2523 | } else { |
| ... | @@ -2552,58 +2558,6 @@ fn binOp( | ... | @@ -2552,58 +2558,6 @@ fn binOp( |
| 2552 | } | 2558 | } |
| 2553 | }, | 2559 | }, |
| 2554 | | 2560 | |
| 2555 | .bit_and, | | |
| 2556 | .bit_or, | | |
| 2557 | .xor, | | |
| 2558 | => { | | |
| 2559 | switch (lhs_ty.zigTypeTag()) { | | |
| 2560 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | | |
| 2561 | .Int => { | | |
| 2562 | assert(lhs_ty.eql(rhs_ty, mod)); | | |
| 2563 | const int_info = lhs_ty.intInfo(self.target.*); | | |
| 2564 | if (int_info.bits <= 64) { | | |
| 2565 | // Only say yes if the operation is | | |
| 2566 | // commutative, i.e. we can swap both of the | | |
| 2567 | // operands | | |
| 2568 | const lhs_immediate_ok = switch (tag) { | | |
| 2569 | .bit_and, | | |
| 2570 | .bit_or, | | |
| 2571 | .xor, | | |
| 2572 | => lhs == .immediate and lhs.immediate <= std.math.maxInt(u13), | | |
| 2573 | else => unreachable, | | |
| 2574 | }; | | |
| 2575 | const rhs_immediate_ok = switch (tag) { | | |
| 2576 | .bit_and, | | |
| 2577 | .bit_or, | | |
| 2578 | .xor, | | |
| 2579 | => rhs == .immediate and rhs.immediate <= std.math.maxInt(u13), | | |
| 2580 | else => unreachable, | | |
| 2581 | }; | | |
| 2582 | | | |
| 2583 | const mir_tag: Mir.Inst.Tag = switch (tag) { | | |
| 2584 | .bit_and => .@"and", | | |
| 2585 | .bit_or => .@"or", | | |
| 2586 | .xor => .xor, | | |
| 2587 | else => unreachable, | | |
| 2588 | }; | | |
| 2589 | | | |
| 2590 | if (rhs_immediate_ok) { | | |
| 2591 | return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata); | | |
| 2592 | } else if (lhs_immediate_ok) { | | |
| 2593 | // swap lhs and rhs | | |
| 2594 | return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata); | | |
| 2595 | } else { | | |
| 2596 | // TODO convert large immediates to register before adding | | |
| 2597 | return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); | | |
| 2598 | } | | |
| 2599 | } else { | | |
| 2600 | return self.fail("TODO binary operations on int with bits > 64", .{}); | | |
| 2601 | } | | |
| 2602 | }, | | |
| 2603 | else => unreachable, | | |
| 2604 | } | | |
| 2605 | }, | | |
| 2606 | | | |
| 2607 | .bool_and, | 2561 | .bool_and, |
| 2608 | .bool_or, | 2562 | .bool_or, |
| 2609 | => { | 2563 | => { |
| ... | @@ -2624,36 +2578,41 @@ fn binOp( | ... | @@ -2624,36 +2578,41 @@ fn binOp( |
| 2624 | } | 2578 | } |
| 2625 | }, | 2579 | }, |
| 2626 | | 2580 | |
| 2627 | .shl => { | 2581 | .shl, |
| | 2582 | .shr, |
| | 2583 | => { |
| 2628 | const base_tag: Air.Inst.Tag = switch (tag) { | 2584 | const base_tag: Air.Inst.Tag = switch (tag) { |
| 2629 | .shl => .shl_exact, | 2585 | .shl => .shl_exact, |
| | 2586 | .shr => .shr_exact, |
| 2630 | else => unreachable, | 2587 | else => unreachable, |
| 2631 | }; | 2588 | }; |
| 2632 | | 2589 | |
| 2633 | // Generate a shl_exact/shr_exact | 2590 | // Generate the base operation |
| 2634 | const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); | 2591 | const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); |
| 2635 | | 2592 | |
| 2636 | // Truncate if necessary | 2593 | // Truncate if necessary |
| 2637 | switch (tag) { | 2594 | switch (lhs_ty.zigTypeTag()) { |
| 2638 | .shl => switch (lhs_ty.zigTypeTag()) { | 2595 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 2639 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2596 | .Int => { |
| 2640 | .Int => { | 2597 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2641 | const int_info = lhs_ty.intInfo(self.target.*); | 2598 | if (int_info.bits <= 64) { |
| 2642 | if (int_info.bits <= 64) { | 2599 | // 32 and 64 bit operands doesn't need truncating |
| 2643 | const result_reg = result.register; | 2600 | if (int_info.bits == 32 or int_info.bits == 64) return result; |
| 2644 | try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits); | 2601 | |
| 2645 | return result; | 2602 | const result_reg = result.register; |
| 2646 | } else { | 2603 | try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits); |
| 2647 | return self.fail("TODO binary operations on integers > u64/i64", .{}); | 2604 | return result; |
| 2648 | } | 2605 | } else { |
| 2649 | }, | 2606 | return self.fail("TODO binary operations on integers > u64/i64", .{}); |
| 2650 | else => unreachable, | 2607 | } |
| 2651 | }, | 2608 | }, |
| 2652 | else => unreachable, | 2609 | else => unreachable, |
| 2653 | } | 2610 | } |
| 2654 | }, | 2611 | }, |
| 2655 | | 2612 | |
| 2656 | .shl_exact => { | 2613 | .shl_exact, |
| | 2614 | .shr_exact, |
| | 2615 | => { |
| 2657 | switch (lhs_ty.zigTypeTag()) { | 2616 | switch (lhs_ty.zigTypeTag()) { |
| 2658 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2617 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 2659 | .Int => { | 2618 | .Int => { |
| ... | @@ -2662,7 +2621,11 @@ fn binOp( | ... | @@ -2662,7 +2621,11 @@ fn binOp( |
| 2662 | const rhs_immediate_ok = rhs == .immediate; | 2621 | const rhs_immediate_ok = rhs == .immediate; |
| 2663 | | 2622 | |
| 2664 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 2623 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 2665 | .shl_exact => .sllx, | 2624 | .shl_exact => if (int_info.bits <= 32) Mir.Inst.Tag.sll else Mir.Inst.Tag.sllx, |
| | 2625 | .shr_exact => switch (int_info.signedness) { |
| | 2626 | .signed => if (int_info.bits <= 32) Mir.Inst.Tag.sra else Mir.Inst.Tag.srax, |
| | 2627 | .unsigned => if (int_info.bits <= 32) Mir.Inst.Tag.srl else Mir.Inst.Tag.srlx, |
| | 2628 | }, |
| 2666 | else => unreachable, | 2629 | else => unreachable, |
| 2667 | }; | 2630 | }; |
| 2668 | | 2631 | |
| ... | @@ -2769,7 +2732,21 @@ fn binOpImmediate( | ... | @@ -2769,7 +2732,21 @@ fn binOpImmediate( |
| 2769 | .rs2_or_imm = .{ .imm = @intCast(u12, rhs.immediate) }, | 2732 | .rs2_or_imm = .{ .imm = @intCast(u12, rhs.immediate) }, |
| 2770 | }, | 2733 | }, |
| 2771 | }, | 2734 | }, |
| 2772 | .sllx => .{ | 2735 | .sll, |
| | 2736 | .srl, |
| | 2737 | .sra, |
| | 2738 | => .{ |
| | 2739 | .shift = .{ |
| | 2740 | .is_imm = true, |
| | 2741 | .rd = dest_reg, |
| | 2742 | .rs1 = lhs_reg, |
| | 2743 | .rs2_or_imm = .{ .imm = @intCast(u5, rhs.immediate) }, |
| | 2744 | }, |
| | 2745 | }, |
| | 2746 | .sllx, |
| | 2747 | .srlx, |
| | 2748 | .srax, |
| | 2749 | => .{ |
| 2773 | .shift = .{ | 2750 | .shift = .{ |
| 2774 | .is_imm = true, | 2751 | .is_imm = true, |
| 2775 | .rd = dest_reg, | 2752 | .rd = dest_reg, |
| ... | @@ -2893,7 +2870,13 @@ fn binOpRegister( | ... | @@ -2893,7 +2870,13 @@ fn binOpRegister( |
| 2893 | .rs2_or_imm = .{ .rs2 = rhs_reg }, | 2870 | .rs2_or_imm = .{ .rs2 = rhs_reg }, |
| 2894 | }, | 2871 | }, |
| 2895 | }, | 2872 | }, |
| 2896 | .sllx => .{ | 2873 | .sll, |
| | 2874 | .srl, |
| | 2875 | .sra, |
| | 2876 | .sllx, |
| | 2877 | .srlx, |
| | 2878 | .srax, |
| | 2879 | => .{ |
| 2897 | .shift = .{ | 2880 | .shift = .{ |
| 2898 | .is_imm = false, | 2881 | .is_imm = false, |
| 2899 | .rd = dest_reg, | 2882 | .rd = dest_reg, |