rpicsim 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/Gemfile +7 -6
- data/Introduction.md +3 -1
- data/README.md +2 -2
- data/docs/ChangeLog.md +6 -0
- data/docs/Contributing.md +1 -1
- data/docs/DefiningSimulationClass.md +11 -10
- data/docs/HowMPLABXIsFound.md +1 -1
- data/docs/IntegrationTesting.md +1 -1
- data/docs/IntroductionToRSpec.md +8 -5
- data/docs/IntroductionToRuby.md +2 -2
- data/docs/KnownIssues.md +46 -57
- data/docs/Labels.md +5 -4
- data/docs/Manual.md +1 -1
- data/docs/Memories.md +70 -0
- data/docs/PersistentExpectations.md +31 -2
- data/docs/Pins.md +5 -7
- data/docs/PreventingCallStackOverflow.md +4 -6
- data/docs/QuickStartGuide.md +5 -5
- data/docs/RSpecIntegration.md +2 -2
- data/docs/RamWatcher.md +22 -11
- data/docs/Running.md +4 -6
- data/docs/Stubbing.md +4 -4
- data/docs/SupportedDevices.md +2 -11
- data/docs/SupportedMPLABXVersions.md +1 -0
- data/docs/SupportedOperatingSystems.md +3 -2
- data/docs/UnitTesting.md +1 -1
- data/docs/Variables.md +81 -25
- data/lib/rpicsim.rb +0 -12
- data/lib/rpicsim/call_stack_info.rb +43 -47
- data/lib/rpicsim/composite_memory.rb +53 -0
- data/lib/rpicsim/flaws.rb +34 -22
- data/lib/rpicsim/instruction.rb +204 -48
- data/lib/rpicsim/label.rb +4 -4
- data/lib/rpicsim/memory.rb +44 -23
- data/lib/rpicsim/memory_watcher.rb +14 -22
- data/lib/rpicsim/mplab.rb +38 -119
- data/lib/rpicsim/mplab/mplab_assembly.rb +23 -18
- data/lib/rpicsim/mplab/mplab_device_info.rb +9 -9
- data/lib/rpicsim/mplab/mplab_disassembler.rb +5 -6
- data/lib/rpicsim/mplab/mplab_instruction.rb +87 -16
- data/lib/rpicsim/mplab/mplab_loader.rb +106 -0
- data/lib/rpicsim/mplab/mplab_memory.rb +19 -6
- data/lib/rpicsim/mplab/mplab_nmmr_info.rb +4 -4
- data/lib/rpicsim/mplab/mplab_observer.rb +15 -10
- data/lib/rpicsim/mplab/mplab_pin.rb +3 -3
- data/lib/rpicsim/mplab/mplab_processor.rb +5 -5
- data/lib/rpicsim/mplab/mplab_program_file.rb +29 -17
- data/lib/rpicsim/mplab/mplab_register.rb +5 -5
- data/lib/rpicsim/mplab/mplab_sfr_info.rb +4 -4
- data/lib/rpicsim/mplab/mplab_simulator.rb +27 -30
- data/lib/rpicsim/pin.rb +6 -6
- data/lib/rpicsim/program_counter.rb +3 -3
- data/lib/rpicsim/program_file.rb +39 -81
- data/lib/rpicsim/rspec/be_predicate.rb +1 -1
- data/lib/rpicsim/rspec/helpers.rb +1 -1
- data/lib/rpicsim/rspec/persistent_expectations.rb +17 -2
- data/lib/rpicsim/rspec/sim_diagnostics.rb +5 -5
- data/lib/rpicsim/search.rb +1 -1
- data/lib/rpicsim/sim.rb +153 -228
- data/lib/rpicsim/stack_pointer.rb +41 -0
- data/lib/rpicsim/stack_trace.rb +1 -1
- data/lib/rpicsim/storage/memory_integer.rb +235 -0
- data/lib/rpicsim/{register.rb → storage/register.rb} +18 -18
- data/lib/rpicsim/variable.rb +25 -211
- data/lib/rpicsim/variable_set.rb +93 -0
- data/lib/rpicsim/version.rb +2 -2
- metadata +9 -4
- data/docs/SFRs.md +0 -71
@@ -0,0 +1,41 @@
|
|
1
|
+
module RPicSim
|
2
|
+
# Instances of this class represent the call stack pointer in a running
|
3
|
+
# simulation.
|
4
|
+
# A value of 0 means that the stack is empty, regardless of what device
|
5
|
+
# architecture you are simulating.
|
6
|
+
class StackPointer
|
7
|
+
# Initializes the StackPointer object.
|
8
|
+
# This be called when the call stack is empty, because this object uses
|
9
|
+
# the initial value of stkptr to deduce how it works.
|
10
|
+
# @param stkptr The STKPTR register of the simulation.
|
11
|
+
def initialize(stkptr)
|
12
|
+
@stkptr = stkptr
|
13
|
+
@stkptr_initial_value = @stkptr.value
|
14
|
+
end
|
15
|
+
|
16
|
+
def value
|
17
|
+
if @stkptr_initial_value > 0
|
18
|
+
raw_value = @stkptr.value
|
19
|
+
if raw_value == @stkptr_initial_value
|
20
|
+
0
|
21
|
+
else
|
22
|
+
raw_value + 1
|
23
|
+
end
|
24
|
+
else
|
25
|
+
@stkptr.value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def value=(value)
|
30
|
+
@stkptr.value = if @stkptr_initial_value > 0
|
31
|
+
if value == 0
|
32
|
+
@stkptr_initial_value
|
33
|
+
else
|
34
|
+
value - 1
|
35
|
+
end
|
36
|
+
else
|
37
|
+
value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/rpicsim/stack_trace.rb
CHANGED
@@ -0,0 +1,235 @@
|
|
1
|
+
module RPicSim::Storage
|
2
|
+
# This class and its subclasses represent integers stored in RAM.
|
3
|
+
class MemoryInteger
|
4
|
+
attr_reader :name, :address
|
5
|
+
attr_writer :memory
|
6
|
+
|
7
|
+
# Creates a new MemoryInteger object not bound to any memory yet.
|
8
|
+
# @param name [Symbol] The name of the variable.
|
9
|
+
# @param address [Integer] should be the address of the variable
|
10
|
+
def initialize(name, address)
|
11
|
+
@name = name
|
12
|
+
@address = address
|
13
|
+
end
|
14
|
+
|
15
|
+
# Creates a new Variable that is bound to the specified memory.
|
16
|
+
# @param memory [RPicSim::Memory]
|
17
|
+
def bind(memory)
|
18
|
+
bound_var = dup
|
19
|
+
bound_var.memory = memory
|
20
|
+
bound_var
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Range] The addresses of each byte that is part of this variable.
|
24
|
+
def addresses
|
25
|
+
address ... (address + size)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Reads the value of the variable from memory.
|
29
|
+
# @return [Integer]
|
30
|
+
def value
|
31
|
+
raise NoMethodError, 'value not implemented'
|
32
|
+
end
|
33
|
+
|
34
|
+
# Writes to the value to the variable's memory.
|
35
|
+
# @return [Integer]
|
36
|
+
def value=(val)
|
37
|
+
raise NoMethodError, 'value= not implemented'
|
38
|
+
end
|
39
|
+
|
40
|
+
def memory_value=(val)
|
41
|
+
self.value = val
|
42
|
+
end
|
43
|
+
|
44
|
+
def memory_value(val)
|
45
|
+
value
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
name.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
def inspect
|
53
|
+
'<%s %s 0x%x>' % [self.class, name, address]
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def check_value(value, allowed_values)
|
58
|
+
if !allowed_values.include?(value)
|
59
|
+
raise ArgumentError, "Invalid value #{value} written to #{name}."
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Represents an unsigned 8-bit variable.
|
65
|
+
class MemoryUInt8 < MemoryInteger
|
66
|
+
def size
|
67
|
+
1
|
68
|
+
end
|
69
|
+
|
70
|
+
def value
|
71
|
+
@memory.read_byte(@address)
|
72
|
+
end
|
73
|
+
|
74
|
+
def value=(val)
|
75
|
+
check_value val, 0..255
|
76
|
+
@memory.write_byte(@address, val)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
# Represents a signed 8-bit variable.
|
82
|
+
class MemoryInt8 < MemoryInteger
|
83
|
+
def size
|
84
|
+
1
|
85
|
+
end
|
86
|
+
|
87
|
+
def value
|
88
|
+
val = @memory.read_byte(@address)
|
89
|
+
val -= 0x100 if val >= 0x80
|
90
|
+
val
|
91
|
+
end
|
92
|
+
|
93
|
+
def value=(val)
|
94
|
+
check_value val, -0x80...0x80
|
95
|
+
@memory.write_byte(@address, val & 0xFF)
|
96
|
+
@memory.write_byte(@address + 1, (val >> 8) & 0xFF)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Represents an unsigned 16-bit variable.
|
101
|
+
class MemoryUInt16 < MemoryInteger
|
102
|
+
def size
|
103
|
+
2
|
104
|
+
end
|
105
|
+
|
106
|
+
def value
|
107
|
+
@memory.read_byte(@address) + 256 * @memory.read_byte(@address + 1)
|
108
|
+
end
|
109
|
+
|
110
|
+
def value=(val)
|
111
|
+
check_value val, 0...0x10000
|
112
|
+
@memory.write_byte(@address, val & 0xFF)
|
113
|
+
@memory.write_byte(@address + 1, (val >> 8) & 0xFF)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Represents a signed 16-bit variable.
|
118
|
+
class MemoryInt16 < MemoryInteger
|
119
|
+
def size
|
120
|
+
2
|
121
|
+
end
|
122
|
+
|
123
|
+
def value
|
124
|
+
val = @memory.read_byte(@address) + 256 * @memory.read_byte(@address + 1)
|
125
|
+
val -= 0x10000 if val >= 0x8000
|
126
|
+
val
|
127
|
+
end
|
128
|
+
|
129
|
+
def value=(val)
|
130
|
+
check_value val, -0x8000...0x8000
|
131
|
+
@memory.write_byte(@address, val & 0xFF)
|
132
|
+
@memory.write_byte(@address + 1, (val >> 8) & 0xFF)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Represents an unsigned 24-bit variable.
|
137
|
+
class MemoryUInt24 < MemoryInteger
|
138
|
+
def size
|
139
|
+
3
|
140
|
+
end
|
141
|
+
|
142
|
+
def value
|
143
|
+
@memory.read_byte(@address) + 0x100 * @memory.read_byte(@address + 1) +
|
144
|
+
0x10000 * @memory.read_byte(@address + 2)
|
145
|
+
end
|
146
|
+
|
147
|
+
def value=(val)
|
148
|
+
check_value val, 0...0x1000000
|
149
|
+
@memory.write_byte(@address, val & 0xFF)
|
150
|
+
@memory.write_byte(@address + 1, (val >> 8) & 0xFF)
|
151
|
+
@memory.write_byte(@address + 2, (val >> 16) & 0xFF)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Represents a signed 24-bit variable.
|
156
|
+
class MemoryInt24 < MemoryInteger
|
157
|
+
def size
|
158
|
+
3
|
159
|
+
end
|
160
|
+
|
161
|
+
def value
|
162
|
+
val = @memory.read_byte(@address) + 0x100 * @memory.read_byte(@address + 1) +
|
163
|
+
0x10000 * @memory.read_byte(@address + 2)
|
164
|
+
val -= 0x1000000 if val >= 0x800000
|
165
|
+
val
|
166
|
+
end
|
167
|
+
|
168
|
+
def value=(val)
|
169
|
+
check_value val, -0x800000..0x800000
|
170
|
+
@memory.write_byte(@address, val & 0xFF)
|
171
|
+
@memory.write_byte(@address + 1, (val >> 8) & 0xFF)
|
172
|
+
@memory.write_byte(@address + 2, (val >> 16) & 0xFF)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Represents an unsigned 32-bit variable.
|
177
|
+
class MemoryUInt32 < MemoryInteger
|
178
|
+
def size
|
179
|
+
4
|
180
|
+
end
|
181
|
+
|
182
|
+
def value
|
183
|
+
@memory.read_byte(@address) + 0x100 * @memory.read_byte(@address + 1) +
|
184
|
+
0x10000 * @memory.read_byte(@address + 2) +
|
185
|
+
0x1000000 * @memory.read_byte(@address + 3)
|
186
|
+
end
|
187
|
+
|
188
|
+
def value=(val)
|
189
|
+
check_value val, 0...0x100000000
|
190
|
+
@memory.write_byte(@address, val & 0xFF)
|
191
|
+
@memory.write_byte(@address + 1, (val >> 8) & 0xFF)
|
192
|
+
@memory.write_byte(@address + 2, (val >> 16) & 0xFF)
|
193
|
+
@memory.write_byte(@address + 3, (val >> 24) & 0xFF)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Represents a signed 32-bit variable.
|
198
|
+
class MemoryInt32 < MemoryInteger
|
199
|
+
def size
|
200
|
+
4
|
201
|
+
end
|
202
|
+
|
203
|
+
def value
|
204
|
+
val = @memory.read_byte(@address) + 0x100 * @memory.read_byte(@address + 1) +
|
205
|
+
0x10000 * @memory.read_byte(@address + 2) +
|
206
|
+
0x1000000 * @memory.read_byte(@address + 3) +
|
207
|
+
0x100000000 * @memory.read_byte(@address + 4)
|
208
|
+
val -= 0x100000000 if val >= 0x80000000
|
209
|
+
val
|
210
|
+
end
|
211
|
+
|
212
|
+
def value=(val)
|
213
|
+
check_value val, -0x80000000..0x80000000
|
214
|
+
@memory.write_byte(@address, val & 0xFF)
|
215
|
+
@memory.write_byte(@address + 1, (val >> 8) & 0xFF)
|
216
|
+
@memory.write_byte(@address + 2, (val >> 16) & 0xFF)
|
217
|
+
@memory.write_byte(@address + 3, (val >> 24) & 0xFF)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Represents a word-sized variable.
|
222
|
+
# The size of the word will depend on the memory the variable lives in.
|
223
|
+
class MemoryWord < MemoryInteger
|
224
|
+
attr_accessor :size
|
225
|
+
|
226
|
+
def value
|
227
|
+
@memory.read_word(@address)
|
228
|
+
end
|
229
|
+
|
230
|
+
def value=(val)
|
231
|
+
@memory.write_word(@address, val)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
@@ -1,16 +1,16 @@
|
|
1
|
-
module RPicSim
|
1
|
+
module RPicSim::Storage
|
2
2
|
class Register
|
3
3
|
attr_reader :name
|
4
|
-
|
4
|
+
|
5
5
|
# The size of the register in bytes.
|
6
6
|
attr_reader :size
|
7
|
-
|
7
|
+
|
8
8
|
# @param mplab_register [Mplab::MplabRegister]
|
9
9
|
# @param memory An optional parameter that enables memory_value.
|
10
10
|
def initialize(mplab_register, memory, width)
|
11
11
|
@mplab_register = mplab_register
|
12
12
|
@name = mplab_register.name.to_sym
|
13
|
-
|
13
|
+
|
14
14
|
@size = case width
|
15
15
|
when 8 then 1
|
16
16
|
when 16 then 2
|
@@ -18,14 +18,14 @@ module RPicSim
|
|
18
18
|
when 32 then 4
|
19
19
|
else raise "Unsupported register width: #{name} is #{width}-bit."
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
var_type = case size
|
23
|
-
when 1 then
|
24
|
-
when 2 then
|
25
|
-
when 3 then
|
26
|
-
when 4 then
|
23
|
+
when 1 then MemoryUInt8
|
24
|
+
when 2 then MemoryUInt16
|
25
|
+
when 3 then MemoryUInt24
|
26
|
+
when 4 then MemoryUInt32
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
@var = var_type.new(name, address).bind(memory)
|
30
30
|
end
|
31
31
|
|
@@ -34,13 +34,13 @@ module RPicSim
|
|
34
34
|
def value=(val)
|
35
35
|
@mplab_register.write val
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
# Reads the value of the register.
|
39
39
|
# @return [Integer]
|
40
40
|
def value
|
41
41
|
@mplab_register.read
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
# For some registers, like STATUS, you cannot read and write the full
|
45
45
|
# range of possible values using {#value=} because some bits are not
|
46
46
|
# writable by the CPU.
|
@@ -49,7 +49,7 @@ module RPicSim
|
|
49
49
|
def memory_value=(value)
|
50
50
|
@var.value = value
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
# Reads the value directly from the memory object backing the register.
|
54
54
|
def memory_value
|
55
55
|
@var.value
|
@@ -60,19 +60,19 @@ module RPicSim
|
|
60
60
|
def address
|
61
61
|
@mplab_register.address
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
# Gets the range of addresses occupied.
|
65
65
|
# @return [Range] A range of integers.
|
66
66
|
def addresses
|
67
67
|
address...(address + size)
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
def to_s
|
71
71
|
name.to_s
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
74
|
def inspect
|
75
|
-
|
75
|
+
'<%s %s 0x%x>' % [self.class, name, address]
|
76
76
|
end
|
77
77
|
end
|
78
|
-
end
|
78
|
+
end
|
data/lib/rpicsim/variable.rb
CHANGED
@@ -1,236 +1,50 @@
|
|
1
1
|
module RPicSim
|
2
|
-
# This class and its subclasses represent firmware-defined variables
|
3
|
-
# in RAM or flash.
|
4
|
-
#
|
5
|
-
# Instances of this class come in two varieties:
|
6
|
-
# - Unbound variables are just a name and an address.
|
7
|
-
# - Bound variables have a name and an address and they are attached to
|
8
|
-
# a memory object so you can actually read and write values from them.
|
9
2
|
class Variable
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
# Specifies the size of this class of variables in memory words.
|
15
|
-
# The units for this are usually bytes for RAM and more than a byte
|
16
|
-
# for flash. This should be called inside the definition of a subclass of
|
17
|
-
# {Variable}, not from anywhere else.
|
18
|
-
def size_is(size)
|
19
|
-
@size = size
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
extend ClassMethods
|
24
|
-
|
25
|
-
attr_reader :name, :address
|
26
|
-
attr_writer :memory
|
27
|
-
|
28
|
-
# Creates a new Variable object not bound to any memory yet.
|
29
|
-
# @param name [Symbol] The name of the variable.
|
30
|
-
# @param address [Integer] should be the address of the variable
|
31
|
-
def initialize(name, address)
|
32
|
-
@name = name
|
33
|
-
@address = address
|
34
|
-
end
|
35
|
-
|
36
|
-
# Creates a new Variable that is bound to the specified memory.
|
37
|
-
# @param memory [RPicSim::Memory]
|
38
|
-
def bind(memory)
|
39
|
-
bound_var = dup
|
40
|
-
bound_var.memory = memory
|
41
|
-
bound_var
|
42
|
-
end
|
43
|
-
|
44
|
-
# @return [Range] The addresses of each byte that is part of this variable.
|
45
|
-
def addresses
|
46
|
-
address ... (address + self.class.size)
|
3
|
+
# Creates a new Variable object.
|
4
|
+
# @param storage The internal storage for the variable.
|
5
|
+
def initialize(storage)
|
6
|
+
@storage = storage
|
47
7
|
end
|
48
8
|
|
49
|
-
# Reads the value of the variable
|
9
|
+
# Reads the value of the variable.
|
50
10
|
# @return [Integer]
|
51
11
|
def value
|
52
|
-
|
12
|
+
@storage.value
|
53
13
|
end
|
54
14
|
|
55
|
-
# Writes
|
15
|
+
# Writes the value to the variable.
|
56
16
|
# @return [Integer]
|
57
17
|
def value=(val)
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
def to_s
|
62
|
-
name.to_s
|
63
|
-
end
|
64
|
-
|
65
|
-
def inspect
|
66
|
-
"<%s %s 0x%x>" % [self.class, name, address]
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
def check_value(value, allowed_values)
|
71
|
-
if !allowed_values.include?(value)
|
72
|
-
raise ArgumentError, "Invalid value #{value} written to #{name}."
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# Represents an unsigned 8-bit variable.
|
78
|
-
class VariableU8 < Variable
|
79
|
-
size_is 1
|
80
|
-
|
81
|
-
def value
|
82
|
-
@memory.read_word(@address)
|
83
|
-
end
|
84
|
-
|
85
|
-
def value=(val)
|
86
|
-
check_value val, 0..255
|
87
|
-
@memory.write_word(@address, val)
|
88
|
-
end
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
# Represents a signed 8-bit variable.
|
93
|
-
class VariableS8 < Variable
|
94
|
-
size_is 1
|
95
|
-
|
96
|
-
def value
|
97
|
-
val = @memory.read_word(@address)
|
98
|
-
val -= 0x100 if val >= 0x80
|
99
|
-
val
|
100
|
-
end
|
101
|
-
|
102
|
-
def value=(val)
|
103
|
-
check_value val, -0x80...0x80
|
104
|
-
@memory.write_word(@address, val & 0xFF)
|
105
|
-
@memory.write_word(@address + 1, (val >> 8) & 0xFF)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# Represents an unsigned 16-bit variable.
|
110
|
-
class VariableU16 < Variable
|
111
|
-
size_is 2
|
112
|
-
|
113
|
-
def value
|
114
|
-
@memory.read_word(@address) + 256 * @memory.read_word(@address + 1)
|
115
|
-
end
|
116
|
-
|
117
|
-
def value=(val)
|
118
|
-
check_value val, 0...0x10000
|
119
|
-
@memory.write_word(@address, val & 0xFF)
|
120
|
-
@memory.write_word(@address + 1, (val >> 8) & 0xFF)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
# Represents a signed 16-bit variable.
|
125
|
-
class VariableS16 < Variable
|
126
|
-
size_is 2
|
127
|
-
|
128
|
-
def value
|
129
|
-
val = @memory.read_word(@address) + 256 * @memory.read_word(@address + 1)
|
130
|
-
val -= 0x10000 if val >= 0x8000
|
131
|
-
val
|
132
|
-
end
|
133
|
-
|
134
|
-
def value=(val)
|
135
|
-
check_value val, -0x8000...0x8000
|
136
|
-
@memory.write_word(@address, val & 0xFF)
|
137
|
-
@memory.write_word(@address + 1, (val >> 8) & 0xFF)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
# Represents an unsigned 24-bit variable.
|
142
|
-
class VariableU24 < Variable
|
143
|
-
size_is 3
|
144
|
-
|
145
|
-
def value
|
146
|
-
@memory.read_word(@address) + 0x100 * @memory.read_word(@address + 1) +
|
147
|
-
0x10000 * @memory.read_word(@address + 2)
|
148
|
-
end
|
149
|
-
|
150
|
-
def value=(val)
|
151
|
-
check_value val, 0...0x1000000
|
152
|
-
@memory.write_word(@address, val & 0xFF)
|
153
|
-
@memory.write_word(@address + 1, (val >> 8) & 0xFF)
|
154
|
-
@memory.write_word(@address + 2, (val >> 16) & 0xFF)
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
# Represents a signed 24-bit variable.
|
159
|
-
class VariableS24 < Variable
|
160
|
-
size_is 3
|
161
|
-
|
162
|
-
def value
|
163
|
-
val = @memory.read_word(@address) + 0x100 * @memory.read_word(@address + 1) +
|
164
|
-
0x10000 * @memory.read_word(@address + 2)
|
165
|
-
val -= 0x1000000 if val >= 0x800000
|
166
|
-
val
|
167
|
-
end
|
168
|
-
|
169
|
-
def value=(val)
|
170
|
-
check_value val, -0x800000..0x800000
|
171
|
-
@memory.write_word(@address, val & 0xFF)
|
172
|
-
@memory.write_word(@address + 1, (val >> 8) & 0xFF)
|
173
|
-
@memory.write_word(@address + 2, (val >> 16) & 0xFF)
|
18
|
+
@storage.value = val
|
174
19
|
end
|
175
|
-
end
|
176
|
-
|
177
|
-
# Represents an unsigned 32-bit variable.
|
178
|
-
class VariableU32 < Variable
|
179
|
-
size_is 4
|
180
20
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
21
|
+
# Writes the value to the variable in a lower-level way that
|
22
|
+
# overrides any read-only bits.
|
23
|
+
# For some types of variables, this is the same as {#value=}.
|
24
|
+
def memory_value=(val)
|
25
|
+
@storage.memory_value = val
|
185
26
|
end
|
186
27
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
@
|
191
|
-
@memory.write_word(@address + 2, (val >> 16) & 0xFF)
|
192
|
-
@memory.write_word(@address + 3, (val >> 24) & 0xFF)
|
28
|
+
# Reads the value directly from the memory object backing the register.
|
29
|
+
# For some types of variables, this is the same as {#value}.
|
30
|
+
def memory_value
|
31
|
+
@storage.memory_value
|
193
32
|
end
|
194
|
-
end
|
195
33
|
|
196
|
-
|
197
|
-
|
198
|
-
size_is 4
|
199
|
-
|
200
|
-
def value
|
201
|
-
val = @memory.read_word(@address) + 0x100 * @memory.read_word(@address + 1) +
|
202
|
-
0x10000 * @memory.read_word(@address + 2) +
|
203
|
-
0x1000000 * @memory.read_word(@address + 3) +
|
204
|
-
0x100000000 * @memory.read_word(@address + 4)
|
205
|
-
val -= 0x100000000 if val >= 0x80000000
|
206
|
-
val
|
34
|
+
def to_s
|
35
|
+
@storage.to_s
|
207
36
|
end
|
208
37
|
|
209
|
-
def
|
210
|
-
|
211
|
-
@memory.write_word(@address, val & 0xFF)
|
212
|
-
@memory.write_word(@address + 1, (val >> 8) & 0xFF)
|
213
|
-
@memory.write_word(@address + 2, (val >> 16) & 0xFF)
|
214
|
-
@memory.write_word(@address + 3, (val >> 24) & 0xFF)
|
38
|
+
def addresses
|
39
|
+
@storage.addresses
|
215
40
|
end
|
216
|
-
end
|
217
|
-
|
218
|
-
# Represents a word-sized variable.
|
219
|
-
# The size of the word will depend on the memory the variable lives in.
|
220
|
-
class VariableWord < Variable
|
221
|
-
size_is 1
|
222
|
-
|
223
|
-
attr_writer :max_value
|
224
41
|
|
225
|
-
def
|
226
|
-
@
|
42
|
+
def address
|
43
|
+
@storage.address
|
227
44
|
end
|
228
45
|
|
229
|
-
def
|
230
|
-
|
231
|
-
check_value val, 0..@max_value
|
232
|
-
end
|
233
|
-
@memory.write_word(@address, val)
|
46
|
+
def name
|
47
|
+
@storage.name
|
234
48
|
end
|
235
49
|
end
|
236
50
|
end
|