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

View as plain text