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

View as plain text