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
5package ppc64asm
6
7import (
8	"encoding/binary"
9	"fmt"
10	"log"
11)
12
13const 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.
21type 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.
32type argField struct {
33	Type  ArgType
34	Shift uint8
35	BitFields
36}
37
38// Parse parses the Arg out from the given binary instruction i.
39func (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
72type ArgType int8
73
74const (
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
91func (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
124func (t ArgType) GoString() string {
125	s := t.String()
126	if t > 0 && t < TypeLast {
127		return "Type" + s
128	}
129	return s
130}
131
132var (
133	// Errors
134	errShort   = fmt.Errorf("truncated instruction")
135	errUnknown = fmt.Errorf("unknown instruction")
136)
137
138var decoderCover []bool
139
140// Decode decodes the leading bytes in src as a single instruction using
141// byte order ord.
142func 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