Source file src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/decode.go

     1  // Copyright 2014 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 ppc64asm
     6  
     7  import (
     8  	"encoding/binary"
     9  	"fmt"
    10  	"log"
    11  	"sort"
    12  	"sync"
    13  )
    14  
    15  const debugDecode = false
    16  
    17  const prefixOpcode = 1
    18  
    19  // instFormat is a decoding rule for one specific instruction form.
    20  // an instruction ins matches the rule if ins&Mask == Value
    21  // DontCare bits should be zero, but the machine might not reject
    22  // ones in those bits, they are mainly reserved for future expansion
    23  // of the instruction set.
    24  // The Args are stored in the same order as the instruction manual.
    25  //
    26  // Prefixed instructions are stored as:
    27  //
    28  //	prefix << 32 | suffix,
    29  //
    30  // Regular instructions are:
    31  //
    32  //	inst << 32
    33  type instFormat struct {
    34  	Op       Op
    35  	Mask     uint64
    36  	Value    uint64
    37  	DontCare uint64
    38  	Args     [6]*argField
    39  }
    40  
    41  // argField indicate how to decode an argument to an instruction.
    42  // First parse the value from the BitFields, shift it left by Shift
    43  // bits to get the actual numerical value.
    44  type argField struct {
    45  	Type  ArgType
    46  	Shift uint8
    47  	BitFields
    48  }
    49  
    50  // Parse parses the Arg out from the given binary instruction i.
    51  func (a argField) Parse(i [2]uint32) Arg {
    52  	switch a.Type {
    53  	default:
    54  		return nil
    55  	case TypeUnknown:
    56  		return nil
    57  	case TypeReg:
    58  		return R0 + Reg(a.BitFields.Parse(i))
    59  	case TypeCondRegBit:
    60  		return Cond0LT + CondReg(a.BitFields.Parse(i))
    61  	case TypeCondRegField:
    62  		return CR0 + CondReg(a.BitFields.Parse(i))
    63  	case TypeFPReg:
    64  		return F0 + Reg(a.BitFields.Parse(i))
    65  	case TypeVecReg:
    66  		return V0 + Reg(a.BitFields.Parse(i))
    67  	case TypeVecSReg:
    68  		return VS0 + Reg(a.BitFields.Parse(i))
    69  	case TypeVecSpReg:
    70  		return VS0 + Reg(a.BitFields.Parse(i))*2
    71  	case TypeMMAReg:
    72  		return A0 + Reg(a.BitFields.Parse(i))
    73  	case TypeSpReg:
    74  		return SpReg(a.BitFields.Parse(i))
    75  	case TypeImmSigned:
    76  		return Imm(a.BitFields.ParseSigned(i) << a.Shift)
    77  	case TypeImmUnsigned:
    78  		return Imm(a.BitFields.Parse(i) << a.Shift)
    79  	case TypePCRel:
    80  		return PCRel(a.BitFields.ParseSigned(i) << a.Shift)
    81  	case TypeLabel:
    82  		return Label(a.BitFields.ParseSigned(i) << a.Shift)
    83  	case TypeOffset:
    84  		return Offset(a.BitFields.ParseSigned(i) << a.Shift)
    85  	case TypeNegOffset:
    86  		// An oddball encoding of offset for hashchk and similar.
    87  		// e.g hashchk offset is 0b1111111000000000 | DX << 8 | D << 3
    88  		off := a.BitFields.ParseSigned(i) << a.Shift
    89  		neg := int64(-1) << (int(a.Shift) + a.BitFields.NumBits())
    90  		return Offset(neg | off)
    91  	}
    92  }
    93  
    94  type ArgType int8
    95  
    96  const (
    97  	TypeUnknown      ArgType = iota
    98  	TypePCRel                // PC-relative address
    99  	TypeLabel                // absolute address
   100  	TypeReg                  // integer register
   101  	TypeCondRegBit           // conditional register bit (0-31)
   102  	TypeCondRegField         // conditional register field (0-7)
   103  	TypeFPReg                // floating point register
   104  	TypeVecReg               // vector register
   105  	TypeVecSReg              // VSX register
   106  	TypeVecSpReg             // VSX register pair (even only encoding)
   107  	TypeMMAReg               // MMA register
   108  	TypeSpReg                // special register (depends on Op)
   109  	TypeImmSigned            // signed immediate
   110  	TypeImmUnsigned          // unsigned immediate/flag/mask, this is the catch-all type
   111  	TypeOffset               // signed offset in load/store
   112  	TypeNegOffset            // A negative 16 bit value 0b1111111xxxxx000 encoded as 0bxxxxx (e.g in the hashchk instruction)
   113  	TypeLast                 // must be the last one
   114  )
   115  
   116  type InstMaskMap struct {
   117  	mask uint64
   118  	insn map[uint64]*instFormat
   119  }
   120  
   121  // Note, plxv/pstxv have a 5 bit opcode in the second instruction word. Only match the most significant 5 of 6 bits of the second primary opcode.
   122  const lookupOpcodeMask = uint64(0xFC000000F8000000)
   123  
   124  // Three level lookup for any instruction:
   125  //  1. Primary opcode map to a list of secondary opcode maps.
   126  //  2. A list of opcodes with distinct masks, sorted by largest to smallest mask.
   127  //  3. A map to a specific opcodes with a given mask.
   128  var getLookupMap = sync.OnceValue(func() map[uint64][]InstMaskMap {
   129  	lMap := make(map[uint64][]InstMaskMap)
   130  	for idx, _ := range instFormats {
   131  		i := &instFormats[idx]
   132  		pop := i.Value & lookupOpcodeMask
   133  		var me *InstMaskMap
   134  		masks := lMap[pop]
   135  		for im, m := range masks {
   136  			if m.mask == i.Mask {
   137  				me = &masks[im]
   138  				break
   139  			}
   140  		}
   141  		if me == nil {
   142  			me = &InstMaskMap{i.Mask, map[uint64]*instFormat{}}
   143  			masks = append(masks, *me)
   144  		}
   145  		me.insn[i.Value] = i
   146  		lMap[pop] = masks
   147  	}
   148  	// Reverse sort masks to ensure extended mnemonics match before more generic forms of an opcode (e.x nop over ori 0,0,0)
   149  	for _, v := range lMap {
   150  		sort.Slice(v, func(i, j int) bool {
   151  			return v[i].mask > v[j].mask
   152  		})
   153  	}
   154  	return lMap
   155  })
   156  
   157  func (t ArgType) String() string {
   158  	switch t {
   159  	default:
   160  		return fmt.Sprintf("ArgType(%d)", int(t))
   161  	case TypeUnknown:
   162  		return "Unknown"
   163  	case TypeReg:
   164  		return "Reg"
   165  	case TypeCondRegBit:
   166  		return "CondRegBit"
   167  	case TypeCondRegField:
   168  		return "CondRegField"
   169  	case TypeFPReg:
   170  		return "FPReg"
   171  	case TypeVecReg:
   172  		return "VecReg"
   173  	case TypeVecSReg:
   174  		return "VecSReg"
   175  	case TypeVecSpReg:
   176  		return "VecSpReg"
   177  	case TypeMMAReg:
   178  		return "MMAReg"
   179  	case TypeSpReg:
   180  		return "SpReg"
   181  	case TypeImmSigned:
   182  		return "ImmSigned"
   183  	case TypeImmUnsigned:
   184  		return "ImmUnsigned"
   185  	case TypePCRel:
   186  		return "PCRel"
   187  	case TypeLabel:
   188  		return "Label"
   189  	case TypeOffset:
   190  		return "Offset"
   191  	case TypeNegOffset:
   192  		return "NegOffset"
   193  	}
   194  }
   195  
   196  func (t ArgType) GoString() string {
   197  	s := t.String()
   198  	if t > 0 && t < TypeLast {
   199  		return "Type" + s
   200  	}
   201  	return s
   202  }
   203  
   204  var (
   205  	// Errors
   206  	errShort   = fmt.Errorf("truncated instruction")
   207  	errUnknown = fmt.Errorf("unknown instruction")
   208  )
   209  
   210  var decoderCover []bool
   211  
   212  // Decode decodes the leading bytes in src as a single instruction using
   213  // byte order ord.
   214  func Decode(src []byte, ord binary.ByteOrder) (inst Inst, err error) {
   215  	if len(src) < 4 {
   216  		return inst, errShort
   217  	}
   218  	if decoderCover == nil {
   219  		decoderCover = make([]bool, len(instFormats))
   220  	}
   221  	inst.Len = 4
   222  	ui_extn := [2]uint32{ord.Uint32(src[:inst.Len]), 0}
   223  	ui := uint64(ui_extn[0]) << 32
   224  	inst.Enc = ui_extn[0]
   225  	opcode := inst.Enc >> 26
   226  	if opcode == prefixOpcode {
   227  		// This is a prefixed instruction
   228  		inst.Len = 8
   229  		if len(src) < 8 {
   230  			return inst, errShort
   231  		}
   232  		// Merge the suffixed word.
   233  		ui_extn[1] = ord.Uint32(src[4:inst.Len])
   234  		ui |= uint64(ui_extn[1])
   235  		inst.SuffixEnc = ui_extn[1]
   236  	}
   237  
   238  	fmts := getLookupMap()[ui&lookupOpcodeMask]
   239  	for i, masks := range fmts {
   240  		if _, fnd := masks.insn[masks.mask&ui]; !fnd {
   241  			continue
   242  		}
   243  		iform := masks.insn[masks.mask&ui]
   244  		if ui&iform.DontCare != 0 {
   245  			if debugDecode {
   246  				log.Printf("Decode(%#x): unused bit is 1 for Op %s", ui, iform.Op)
   247  			}
   248  			// to match GNU objdump (libopcodes), we ignore don't care bits
   249  		}
   250  		for i, argfield := range iform.Args {
   251  			if argfield == nil {
   252  				break
   253  			}
   254  			inst.Args[i] = argfield.Parse(ui_extn)
   255  		}
   256  		inst.Op = iform.Op
   257  		if debugDecode {
   258  			log.Printf("%#x: search entry %d", ui, i)
   259  			continue
   260  		}
   261  		break
   262  	}
   263  	if inst.Op == 0 && inst.Enc != 0 {
   264  		return inst, errUnknown
   265  	}
   266  	return inst, nil
   267  }
   268  

View as plain text