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