Source file src/cmd/internal/obj/arm64/inst_test.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package arm64
     6  
     7  import (
     8  	"math/bits"
     9  	"testing"
    10  
    11  	"cmd/internal/obj"
    12  )
    13  
    14  // decodeLogicalImmArrEncoding is translated from DecodeBitMasks in ARM64
    15  // ASL. It implements the decoding logic of imm13 defined by ARM64 specification.
    16  func decodeLogicalImmArrEncoding(imm13 uint32, arr uint32) (uint64, bool) {
    17  	n := (imm13 >> 12) & 1
    18  	immr := (imm13 >> 6) & 0x3F
    19  	imms := imm13 & 0x3F
    20  
    21  	notImms := (^imms) & 0x3F
    22  	combined := (n << 6) | notImms
    23  
    24  	// if immN::NOT(imms) == '000000x' then Undefined(); end;
    25  	if combined <= 1 {
    26  		return 0, false
    27  	}
    28  
    29  	lenVal := bits.Len32(uint32(combined)) - 1
    30  	esize := uint64(1 << lenVal)
    31  
    32  	levels := uint32((1 << lenVal) - 1)
    33  	// if immediate && (imms AND levels) == levels then Undefined(); end;
    34  	if (imms & levels) == levels {
    35  		return 0, false
    36  	}
    37  
    38  	s := uint64(imms & levels)
    39  	r := uint64(immr & levels)
    40  
    41  	// welem has s + 1 ones
    42  	welem := (uint64(1) << (s + 1)) - 1
    43  
    44  	// Rotate right welem by r bits within esize bits window
    45  	rotated := welem
    46  	mask := (uint64(1) << esize) - 1
    47  	if r > 0 {
    48  		r %= esize
    49  		rotated = ((welem >> r) | (welem << (esize - r))) & mask
    50  	}
    51  
    52  	// Replicate rotated to fill 64 bits (as encode replicates to 64 bits)
    53  	wmask := uint64(0)
    54  	for i := uint64(0); i < 64; i += esize {
    55  		wmask |= rotated << i
    56  	}
    57  
    58  	// Now mask back to the arrangement's lane size M
    59  	var M uint64
    60  	switch arr {
    61  	case ARNG_B:
    62  		M = 8
    63  	case ARNG_H:
    64  		M = 16
    65  	case ARNG_S:
    66  		M = 32
    67  	case ARNG_D:
    68  		M = 64
    69  	default:
    70  		return 0, false
    71  	}
    72  
    73  	mask = (uint64(1) << M) - 1
    74  	return wmask & mask, true
    75  }
    76  
    77  func FuzzLogicalImmArrEncoding(f *testing.F) {
    78  	f.Add(uint64(0x55), uint32(ARNG_B))
    79  	f.Add(uint64(0xAA), uint32(ARNG_B))
    80  	f.Add(uint64(0x0F), uint32(ARNG_B))
    81  	f.Add(uint64(0x0101), uint32(ARNG_H))
    82  	f.Add(uint64(0x00FF), uint32(ARNG_H))
    83  	f.Add(uint64(0x0000FFFF), uint32(ARNG_S))
    84  	f.Add(uint64(0x55555555), uint32(ARNG_S))
    85  	f.Add(uint64(0x0000FFFF), uint32(ARNG_D))
    86  	f.Add(uint64(0x0101010101010101), uint32(ARNG_D))
    87  
    88  	f.Fuzz(func(t *testing.T, v uint64, arr uint32) {
    89  		if arr != ARNG_B && arr != ARNG_H && arr != ARNG_S && arr != ARNG_D {
    90  			return
    91  		}
    92  		adjacentAddr := &obj.Addr{
    93  			Type: obj.TYPE_REG,
    94  			Reg:  int16(REG_ZARNG) + 0 + (int16(arr) << 5),
    95  		}
    96  
    97  		encoded, ok := encodeLogicalImmArrEncoding(v, adjacentAddr)
    98  		if !ok {
    99  			return
   100  		}
   101  
   102  		imm13 := encoded >> 5
   103  		decoded, ok := decodeLogicalImmArrEncoding(imm13, arr)
   104  		if !ok {
   105  			t.Errorf("Failed to decode imm13=0x%x arr=%d", imm13, arr)
   106  			return
   107  		}
   108  
   109  		var mask uint64
   110  		switch arr {
   111  		case ARNG_B:
   112  			mask = 0xFF
   113  		case ARNG_H:
   114  			mask = 0xFFFF
   115  		case ARNG_S:
   116  			mask = 0xFFFFFFFF
   117  		case ARNG_D:
   118  			mask = 0xFFFFFFFFFFFFFFFF
   119  		}
   120  		expected := v & mask
   121  
   122  		if decoded != expected {
   123  			t.Errorf("Fuzz roundtrip failed for v=0x%x arr=%d. Expected 0x%x, got 0x%x (imm13=0x%x)", v, arr, expected, decoded, imm13)
   124  		}
   125  	})
   126  }
   127  

View as plain text