-
Notifications
You must be signed in to change notification settings - Fork 19
/
disassembly_entry.go
124 lines (102 loc) · 3.67 KB
/
disassembly_entry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
package arm
import (
"fmt"
"strings"
)
// The string that will be in the Operator field in the case of a decoding error
const DisasmEntryErrorOperator = "error:"
// DisasmEntry implements the CartCoProcDisasmEntry interface.
type DisasmEntry struct {
// the address value. the formatted value is in the Address field
Addr uint32
// the opcode for the instruction. in the case of a 32bit instruction, this
// will be the second word of the opcode
Opcode uint16
// instruction is 32bit and the high opcode
Is32bit bool
OpcodeHi uint16
// -----------
// formated address for use by disassemblies. more convenient that the Addr
// field in some contexts
Address string
// the operator is the instruction specified by the Opcode field (and
// OpcodeHi if the instruction is 32bit)
//
// the operand is the specific details of the instruction. what registers
// and what values are used, etc.
//
// in the case of an error Operator will contain the DisasmEntryErrorOperator
// string and the Operand will be the detaled message of the error
Operator string
Operand string
// -----------
// the values of the remaining fields are not defined unless the
// instruction has been executed
// basic notes about the last execution of the entry
ExecutionNotes string
// snapshot of CPU registers at the result of the instruction
Registers [NumRegisters]uint32
// basic cycle information
Cycles int
CyclesSequence string
// cycle details
MAMCR int
BranchTrail BranchTrail
MergedIS bool
// whether this entry was executed in immediate mode. if this field is true
// then the Cycles and "cycle details" fields will be zero
ImmediateMode bool
}
// Key implements the CartCoProcDisasmEntry interface.
func (e DisasmEntry) Key() string {
return e.Address
}
// CSV implements the CartCoProcDisasmEntry interface. Outputs CSV friendly
// entries, albeit seprated by semicolons rather than commas.
func (e DisasmEntry) CSV() string {
mergedIS := ""
if e.MergedIS {
mergedIS = "merged IS"
}
return fmt.Sprintf("%s;%s;%s;%d;%s;%s;%s", e.Address, e.Operator, e.Operand, e.Cycles, e.ExecutionNotes, mergedIS, e.CyclesSequence)
}
// String implements the CartCoProcDisasmEntry interface. Returns a very simple
// representation of the disassembly entry.
func (e DisasmEntry) String() string {
if e.Operator == "" {
return e.Operand
}
return fmt.Sprintf("%s %s", e.Operator, e.Operand)
}
// Size implements the CartCoProcDisasmEntry interface.
func (e DisasmEntry) Size() int {
if e.Is32bit {
return 4
}
return 2
}
// fillDisasmEntry sets the DisasmEntry fields using information from the
// emulated ARM. the other fields are not touched so can be set before or after
// calling the function
func fillDisasmEntry(arm *ARM, e *DisasmEntry, opcode uint16) {
e.Addr = arm.state.instructionPC
e.Opcode = opcode
e.Is32bit = arm.state.function32bitDecoding
e.OpcodeHi = arm.state.function32bitOpcodeHi
e.Address = fmt.Sprintf("%08x", arm.state.instructionPC)
e.Operator = strings.ToLower(e.Operator)
}