Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | # -*- perl -*- |
2 | ||
3 | package Midas::MMU::TTEFormat; | |
4 | use strict; | |
5 | ||
6 | use TRELoad 'BitFieldTie'; | |
7 | use Tie::IxHash; | |
8 | ||
9 | require Exporter; | |
10 | ||
11 | our @ISA = qw(Exporter); | |
12 | our @EXPORT = qw( | |
13 | get_tte_field_hash | |
14 | get_union_tte_field_hash | |
15 | tte_hash_to_tsb_data | |
16 | tte_hash_to_tsb_tag | |
17 | parse_tsb_data | |
18 | is_good_format_for_mmu | |
19 | ||
20 | %TSB_TAG_FORMAT | |
21 | %TSB_DATA_FORMAT | |
22 | ); | |
23 | ||
24 | our %TSB_TAG_FORMAT; | |
25 | our %TSB_DATA_FORMAT; | |
26 | ||
27 | # BEGIN block, because these need to be defined when other modules | |
28 | # call get_union_tte_field hash inside a 'use fields' clause. | |
29 | BEGIN { | |
30 | ||
31 | our %TSB_TAG_FORMAT = | |
32 | ( | |
33 | ultra2 => | |
34 | { | |
35 | tagtarget => | |
36 | { | |
37 | G => { hi=>63, lo=>63 }, | |
38 | CONTEXT => { hi=>60, lo=>48 }, | |
39 | VA => { hi=>41, lo=> 0, src=>'63:22' }, | |
40 | }, | |
41 | tagaccess => | |
42 | { | |
43 | VA => { hi=>63, lo=>13, src=>'63:13' }, | |
44 | CONTEXT => { hi=>12, lo=> 0 }, | |
45 | }, | |
46 | }, | |
47 | ||
48 | niagara => | |
49 | { | |
50 | tagtarget => | |
51 | { | |
52 | CONTEXT => { hi=>60, lo=>48 }, | |
53 | VA => { hi=>41, lo=> 0, src=>'63:22' }, | |
54 | }, | |
55 | tagaccess => | |
56 | { | |
57 | VA => { hi=>63, lo=>13, src=>'63:13' }, | |
58 | CONTEXT => { hi=>12, lo=> 0 }, | |
59 | }, | |
60 | }, | |
61 | ||
62 | niagara2 => | |
63 | { | |
64 | tagtarget => | |
65 | { | |
66 | CONTEXT => { hi=>60, lo=>48 }, | |
67 | VA => { hi=>41, lo=> 0, src=>'63:22' }, | |
68 | }, | |
69 | tagaccess => | |
70 | { | |
71 | VA => { hi=>63, lo=>13, src=>'63:13' }, | |
72 | CONTEXT => { hi=>12, lo=> 0 }, | |
73 | }, | |
74 | }, | |
75 | rock => | |
76 | { | |
77 | tagtarget => | |
78 | { | |
79 | CONTEXT => { hi=>60, lo=>48 }, | |
80 | VA => { hi=>41, lo=> 0, src=>'63:22' }, | |
81 | }, | |
82 | tagaccess => | |
83 | { | |
84 | VA => { hi=>63, lo=>13, src=>'63:13' }, | |
85 | CONTEXT => { hi=>12, lo=> 0 }, | |
86 | }, | |
87 | }, | |
88 | ||
89 | ||
90 | ); | |
91 | ||
92 | tie my %tsb_data_ultra2_sun4u, 'Tie::IxHash'; | |
93 | tie my %tsb_data_niagara_sun4u, 'Tie::IxHash'; | |
94 | tie my %tsb_data_niagara_sun4v, 'Tie::IxHash'; | |
95 | tie my %tsb_data_niagara2_sun4u, 'Tie::IxHash'; | |
96 | tie my %tsb_data_niagara2_sun4v, 'Tie::IxHash'; | |
97 | tie my %tsb_data_rock_sun4v, 'Tie::IxHash'; | |
98 | ||
99 | %tsb_data_ultra2_sun4u = | |
100 | ( | |
101 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1" }, | |
102 | SIZE => { hi=>62, lo=>61, descr => "Encoded page size"}, | |
103 | NFO => { hi=>60, lo=>60, descr => "Non-Faulting Only" }, | |
104 | IE => { hi=>59, lo=>59, descr => "Invert Endianness" }, | |
105 | SOFT2=> { hi=>58, lo=>50, descr => "Software usable"}, | |
106 | DIAG => { hi=>49, lo=>41, descr => "Diagnostic"}, | |
107 | PA => { hi=>40, lo=>13, src=>'40:13', descr => "Physical Address"}, | |
108 | SOFT => { hi=>12, lo=> 7, descr => "Software usable" }, | |
109 | L => { hi=> 6, lo=> 6, descr => "Lock"}, | |
110 | CP => { hi=> 5, lo=> 5, | |
111 | descr => "Cacheable in phys. indexed cache"}, | |
112 | CV => { hi=> 4, lo=> 4, | |
113 | descr => "Cacheable in virt. indexed cache"}, | |
114 | E => { hi=> 3, lo=> 3, descr => "Side-effect"}, | |
115 | P => { hi=> 2, lo=> 2, descr => "Priviliged"}, | |
116 | W => { hi=> 1, lo=> 1, descr => "Writeable"}, | |
117 | G => { hi=> 0, lo=> 0, descr => "Global" }, | |
118 | ); | |
119 | ||
120 | %tsb_data_niagara_sun4u = | |
121 | ( | |
122 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1"}, | |
123 | SZL => { hi=>62, lo=>61, name=>'SIZE', src=>'1:0', | |
124 | descr => "Low bits of encoded page size" }, | |
125 | NFO => { hi=>60, lo=>60, descr => "Non-Faulting Only"}, | |
126 | IE => { hi=>59, lo=>59, descr => "Invert Endianness"}, | |
127 | SOFT2=> { hi=>58, lo=>49, descr => "Software usable"}, | |
128 | SZH => { hi=>48, lo=>48, name=>'SIZE', src=>'2', | |
129 | descr => "High bit of encoded page size" }, | |
130 | DIAG => { hi=>47, lo=>40, descr => "Diagnostic"}, | |
131 | PA => { hi=>39, lo=>13, src=>'39:13', descr => "Physical Address"}, | |
132 | SOFT => { hi=>12, lo=> 8, descr => "Software usable"}, | |
133 | RSVD0=> { hi=> 7, lo=> 7, descr => "Reserved"}, | |
134 | L => { hi=> 6, lo=> 6, descr => "Lock" }, | |
135 | CP => { hi=> 5, lo=> 5, | |
136 | descr => "Cacheable in phys. indexed cache"}, | |
137 | CV => { hi=> 4, lo=> 4, | |
138 | descr => "Cacheable in virt. indexed cache"}, | |
139 | E => { hi=> 3, lo=> 3, descr => "Side-effect"}, | |
140 | P => { hi=> 2, lo=> 2, descr => "Priviliged" }, | |
141 | W => { hi=> 1, lo=> 1, descr => "Writeable" }, | |
142 | RSVD1=> { hi=> 0, lo=> 0, aliases=>['G'], descr => "Reserved" }, | |
143 | ); | |
144 | ||
145 | %tsb_data_niagara_sun4v = | |
146 | ( | |
147 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1"}, | |
148 | NFO => { hi=>62, lo=>62, descr => "Non-Faulting Only" }, | |
149 | L => { hi=>61, lo=>61, descr => "Lock" }, | |
150 | SOFT => { hi=>60, lo=>40, descr => "Software usable"}, | |
151 | PA => { hi=>39, lo=>13, src=>'39:13', descr => "Physical Address"}, | |
152 | IE => { hi=>12, lo=>12, descr => "Invert Endianness"}, | |
153 | E => { hi=>11, lo=>11, descr => "Side-effect"}, | |
154 | CP => { hi=>10, lo=>10, | |
155 | descr => "Cacheable in phys. indexed cache"}, | |
156 | CV => { hi=> 9, lo=> 9, | |
157 | descr => "Cacheable in virt. indexed cache"}, | |
158 | P => { hi=> 8, lo=> 8, descr => "Priviliged" }, | |
159 | RSVD0=> { hi=> 7, lo=> 7, descr => "Reserved" }, | |
160 | W => { hi=> 6, lo=> 6, descr => "Writeable" }, | |
161 | SW1 => { hi=> 5, lo=> 5, descr => "Software usable" }, | |
162 | SW0 => { hi=> 4, lo=> 4, descr => "Software usable" }, | |
163 | RSVD1=> { hi=> 3, lo=> 3, descr => "Reserved" }, | |
164 | SIZE => { hi=> 2, lo=> 0, descr => "Encoded page size" }, | |
165 | ); | |
166 | ||
167 | %tsb_data_niagara2_sun4u = | |
168 | ( | |
169 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1"}, | |
170 | SZL => { hi=>62, lo=>61, name=>'SIZE', src=>'1:0', | |
171 | descr => "Low bits of encoded page size" }, | |
172 | NFO => { hi=>60, lo=>60, descr => "Non-Faulting Only"}, | |
173 | IE => { hi=>59, lo=>59, descr => "Invert Endianness"}, | |
174 | SOFT2=> { hi=>58, lo=>49, descr => "Software usable"}, | |
175 | SZH => { hi=>48, lo=>48, name=>'SIZE', src=>'2', | |
176 | descr => "High bit of encoded page size" }, | |
177 | DIAG => { hi=>47, lo=>40, descr => "Diagnostic" }, | |
178 | PA => { hi=>39, lo=>13, src=>'39:13', descr => "Physical Address"}, | |
179 | SOFT => { hi=>12, lo=> 8, descr => "Software usable"}, | |
180 | EP => { hi=> 7, lo=> 7, aliases=>['X'], | |
181 | descr => "Executable (also TTE_X)"}, | |
182 | L => { hi=> 6, lo=> 6, descr => "Lock" }, | |
183 | CP => { hi=> 5, lo=> 5, | |
184 | descr => "Cacheable in phys. indexed cache"}, | |
185 | CV => { hi=> 4, lo=> 4, | |
186 | descr => "Cacheable in virt. indexed cache"}, | |
187 | E => { hi=> 3, lo=> 3, descr => "Side-effect"}, | |
188 | P => { hi=> 2, lo=> 2, descr => "Priviliged" }, | |
189 | W => { hi=> 1, lo=> 1, descr => "Writeable" }, | |
190 | RSVD1=> { hi=> 0, lo=> 0, aliases=>['G'], descr => "Reserved" }, | |
191 | ); | |
192 | ||
193 | %tsb_data_niagara2_sun4v = | |
194 | ( | |
195 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1"}, | |
196 | NFO => { hi=>62, lo=>62, descr => "Non-Faulting Only" }, | |
197 | L => { hi=>61, lo=>61, descr => "Lock"}, | |
198 | SOFT => { hi=>60, lo=>40, descr => "Software usable"}, | |
199 | PA => { hi=>39, lo=>13, src=>'39:13', descr => "Physical Address"}, | |
200 | IE => { hi=>12, lo=>12, descr => "Invert Endianness"}, | |
201 | E => { hi=>11, lo=>11, descr => "Side-effect"}, | |
202 | CP => { hi=>10, lo=>10, | |
203 | descr => "Cacheable in phys. indexed cache"}, | |
204 | CV => { hi=> 9, lo=> 9, | |
205 | descr => "Cacheable in virt. indexed cache"}, | |
206 | P => { hi=> 8, lo=> 8, descr => "Priviliged"}, | |
207 | EP => { hi=> 7, lo=> 7, aliases=>['X'], | |
208 | descr => "Executable (also TTE_X)"}, | |
209 | W => { hi=> 6, lo=> 6, descr => "Writeable" }, | |
210 | SW1 => { hi=> 5, lo=> 5, descr => "Software usable"}, | |
211 | SW0 => { hi=> 4, lo=> 4, descr => "Software usable"}, | |
212 | RSVD1=> { hi=> 3, lo=> 3, descr => "Reserved" }, | |
213 | SIZE => { hi=> 2, lo=> 0, descr => "Encoded page size"}, | |
214 | ); | |
215 | ||
216 | %tsb_data_rock_sun4v = | |
217 | ( | |
218 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1"}, | |
219 | NFO => { hi=>62, lo=>62, descr => "Non-Faulting Only" }, | |
220 | SW1 => { hi=>61, lo=>47, descr => "Software usable"}, | |
221 | PA => { hi=>46, lo=>13, src=>'46:13', descr => "Physical Address"}, | |
222 | IE => { hi=>12, lo=>12, descr => "Invert Endianness" }, | |
223 | E => { hi=>11, lo=>11, descr => "Side-effect"}, | |
224 | CP => { hi=>10, lo=>10, | |
225 | descr => "Cacheable in phys. indexed cache"}, | |
226 | CV => { hi=> 9, lo=> 9, | |
227 | descr => "Cacheable in virt. indexed cache"}, | |
228 | P => { hi=> 8, lo=> 8, descr => "Priviliged" }, | |
229 | X => { hi=> 7, lo=> 7, aliases=>['EP'], | |
230 | descr => "Executable (also TTE_EP)" }, | |
231 | W => { hi=> 6, lo=> 6, descr => "Writeable" }, | |
232 | R => { hi=> 5, lo=> 5, descr => "Readable" }, | |
233 | SW0 => { hi=> 4, lo=> 4, descr => "Software usable"}, | |
234 | RSVD0=> { hi=> 3, lo=> 3, descr => "Reserved"}, | |
235 | SIZE => { hi=> 2, lo=> 0, descr => "Encoded page size" }, | |
236 | ); | |
237 | ||
238 | our %TSB_DATA_FORMAT = | |
239 | ( | |
240 | ||
241 | ultra2 => { | |
242 | sun4u => \%tsb_data_ultra2_sun4u, | |
243 | }, | |
244 | niagara => { | |
245 | sun4u => \%tsb_data_niagara_sun4u, | |
246 | sun4v => \%tsb_data_niagara_sun4v, | |
247 | }, | |
248 | ||
249 | niagara2 => { | |
250 | sun4u => \%tsb_data_niagara2_sun4u, | |
251 | sun4v => \%tsb_data_niagara2_sun4v, | |
252 | }, | |
253 | ||
254 | ||
255 | rock => { | |
256 | sun4v => \%tsb_data_rock_sun4v, | |
257 | }, | |
258 | ||
259 | ); | |
260 | } | |
261 | ||
262 | ############################################################################## | |
263 | ||
264 | sub get_tte_field_hash { | |
265 | my $mmu_type = shift; | |
266 | my $ttefmt = shift; | |
267 | my $tsbtagfmt = shift; | |
268 | ||
269 | my %fields; | |
270 | foreach my $field (keys %{$TSB_DATA_FORMAT{$mmu_type}{$ttefmt}}) { | |
271 | my $descr = $TSB_DATA_FORMAT{$mmu_type}{$ttefmt}{$field}; | |
272 | my $size = $descr->{hi} - $descr->{lo} + 1; | |
273 | my $name = (exists $descr->{name}) ? $descr->{name} : $field; | |
274 | ||
275 | my @names = ($name); | |
276 | push @names, @{ $descr->{aliases} } if exists $descr->{aliases}; | |
277 | ||
278 | foreach my $n (@names) { | |
279 | my $tte_n = lc('tte_' . $n); | |
280 | ||
281 | $fields{$tte_n} = 0 unless exists $fields{$tte_n}; | |
282 | $fields{$tte_n} += $size; | |
283 | } | |
284 | } | |
285 | ||
286 | foreach my $field (keys %{$TSB_TAG_FORMAT{$mmu_type}{$tsbtagfmt}}) { | |
287 | my $descr = $TSB_TAG_FORMAT{$mmu_type}{$tsbtagfmt}{$field}; | |
288 | my $size = $descr->{hi} - $descr->{lo} + 1; | |
289 | my $name = (exists $descr->{name}) ? $descr->{name} : $field; | |
290 | ||
291 | my @names = ($name); | |
292 | push @names, @{ $descr->{aliases} } if exists $descr->{aliases}; | |
293 | ||
294 | foreach my $n (@names) { | |
295 | my $tte_n = lc('tte_' . $n); | |
296 | ||
297 | $fields{$tte_n} = 0 unless exists $fields{$tte_n}; | |
298 | if($tte_n eq 'tte_g') { | |
299 | $fields{$tte_n} = $size; | |
300 | } else { | |
301 | $fields{$tte_n} += $size; | |
302 | } | |
303 | } | |
304 | } | |
305 | ||
306 | delete $fields{tte_va} if exists $fields{tte_va}; | |
307 | delete $fields{tte_ra} if exists $fields{tte_ra}; | |
308 | delete $fields{tte_pa} if exists $fields{tte_pa}; | |
309 | ||
310 | ||
311 | return \%fields; | |
312 | } | |
313 | ||
314 | ############################################################################## | |
315 | ||
316 | sub get_union_tte_field_hash { | |
317 | my $mmu_type = shift; | |
318 | ||
319 | my %fields; | |
320 | foreach my $ttefmt (keys %{ $TSB_DATA_FORMAT{$mmu_type} }) { | |
321 | foreach my $tsbtagfmt (keys %{ $TSB_TAG_FORMAT{$mmu_type} } ) { | |
322 | my $fieldHash = get_tte_field_hash($mmu_type, $ttefmt, $tsbtagfmt); | |
323 | foreach my $field (keys %$fieldHash) { | |
324 | $fields{$field} = 0 unless defined $fields{$field}; | |
325 | $fields{$field} = ($fields{$field} > $fieldHash->{$field}) ? | |
326 | $fields{$field} : $fieldHash->{$field}; | |
327 | } | |
328 | } | |
329 | } | |
330 | ||
331 | return \%fields; | |
332 | } | |
333 | ||
334 | ############################################################################## | |
335 | ||
336 | sub tte_hash_to_tsb_data { | |
337 | my $mmutype = shift; | |
338 | my $ttefmt = shift; | |
339 | my $ttehash = shift; | |
340 | my $addr = shift; | |
341 | ||
342 | $addr = '0' unless defined $addr; | |
343 | ||
344 | my $pa = BitFieldTie->new(64, $addr); | |
345 | my $data = BitFieldTie->new(64, 0); | |
346 | my $size = (exists $ttehash->{tte_size}) ? | |
347 | BitFieldTie->new(64, $ttehash->{tte_size}) : undef; | |
348 | ||
349 | tie my %data, 'BitFieldTie', $data; | |
350 | tie my %pa, 'BitFieldTie', $pa; | |
351 | tie my %size, 'BitFieldTie', $size; | |
352 | ||
353 | foreach my $field (keys %{ $TSB_DATA_FORMAT{$mmutype}{$ttefmt} }) { | |
354 | my $descr = $TSB_DATA_FORMAT{$mmutype}{$ttefmt}{$field}; | |
355 | my $name = (exists $descr->{name}) ? $descr->{name} : $field; | |
356 | ||
357 | my @names = ($name); | |
358 | push @names, @{ $descr->{aliases} } if exists $descr->{aliases}; | |
359 | ||
360 | my $def_value = (defined $descr->{default}) ? $descr->{default} : 0; | |
361 | my $value; | |
362 | my $set_already = 0; | |
363 | if($name eq 'PA' or $name eq 'SIZE') { | |
364 | my $bits = (exists $descr->{src}) ? $descr->{src} : '31:0'; | |
365 | if($name eq 'PA') { | |
366 | if($bits =~ /^(\d+):(\d+)$/) { | |
367 | my ($hi, $lo) = ($1, $2); | |
368 | my $dist = $hi - $lo + 1; | |
369 | if($dist > 32) { | |
370 | my $mid_hi = $hi-31; | |
371 | my $mid_lo = $mid_hi-1; | |
372 | ||
373 | my $descr_mid_hi = $descr->{hi} - 31; | |
374 | my $descr_mid_lo = $descr_mid_hi - 1; | |
375 | ||
376 | $data{"$descr->{hi}:$descr_mid_hi"} = | |
377 | $pa{"${hi}:$mid_hi"}; | |
378 | ||
379 | $data{"${descr_mid_lo}:$descr->{lo}"} = | |
380 | $pa{"${mid_lo}:$lo"}; | |
381 | ||
382 | $set_already = 1; | |
383 | } else { | |
384 | $value = $pa{$bits}; | |
385 | } | |
386 | } else { | |
387 | $value = $pa{$bits}; | |
388 | } | |
389 | } elsif($name eq 'SIZE') { | |
390 | $value = $size{$bits}; | |
391 | } | |
392 | } else { | |
393 | my $found = 0; | |
394 | foreach my $n (@names) { | |
395 | my $tte_n = lc('tte_' . $n); | |
396 | if(exists $ttehash->{$tte_n}) { | |
397 | $value ||= $ttehash->{$tte_n}; | |
398 | $found = 1; | |
399 | } | |
400 | } | |
401 | $value = $def_value unless $found; | |
402 | } | |
403 | ||
404 | $data{"$descr->{hi}" . ':' . "$descr->{lo}"} = $value | |
405 | unless $set_already; | |
406 | ||
407 | } | |
408 | return $data->stringify(); | |
409 | } | |
410 | ||
411 | ############################################################################## | |
412 | ||
413 | sub tte_hash_to_tsb_tag { | |
414 | my $mmutype = shift; | |
415 | my $tsbtagfmt = shift; | |
416 | my $ttehash = shift; | |
417 | my $addr = shift; | |
418 | my $force_ctx_zero = shift; | |
419 | ||
420 | $addr = '0' unless defined $addr; | |
421 | $force_ctx_zero = 0 unless defined $force_ctx_zero; | |
422 | ||
423 | my $va = BitFieldTie->new(64, $addr); | |
424 | my $tag = BitFieldTie->new(64, 0); | |
425 | ||
426 | tie my %tag, 'BitFieldTie', $tag; | |
427 | tie my %va, 'BitFieldTie', $va; | |
428 | ||
429 | foreach my $field (keys %{ $TSB_TAG_FORMAT{$mmutype}{$tsbtagfmt} }) { | |
430 | my $descr = $TSB_TAG_FORMAT{$mmutype}{$tsbtagfmt}{$field}; | |
431 | my $name = (exists $descr->{name}) ? $descr->{name} : $field; | |
432 | ||
433 | my @names = ($name); | |
434 | push @names, @{ $descr->{aliases} } if exists $descr->{aliases}; | |
435 | ||
436 | my $value = (defined $descr->{default}) ? $descr->{default} : 0; | |
437 | if( $name eq 'VA') { | |
438 | my $bits = (exists $descr->{src}) ? $descr->{src} : '31:0'; | |
439 | ||
440 | my $hi = $descr->{hi}; | |
441 | my $lo = $descr->{lo}; | |
442 | my $dist = ($hi-$lo+1); | |
443 | if($dist >= 32) { | |
444 | my $cut = $hi-31; | |
445 | if($bits =~ /(\d+)\:(\d+)/) { | |
446 | my ($bitsHi, $bitsLo) = ($1, $2); | |
447 | my $bitsCut = $bitsHi-31; | |
448 | $tag{"${hi}:${cut}"} = $va{"${bitsHi}:${bitsCut}"}; | |
449 | $cut--; $bitsCut--; | |
450 | $tag{"${cut}:${lo}"} = $va{"${bitsCut}:${bitsLo}"}; | |
451 | } | |
452 | } else { | |
453 | $tag{"${hi}:${lo}"} = $va{$bits}; | |
454 | } | |
455 | ||
456 | ||
457 | } else { | |
458 | foreach my $n (@names) { | |
459 | my $tte_n = lc('tte_' . $n); | |
460 | if(exists $ttehash->{$tte_n}) { | |
461 | $value ||= $ttehash->{$tte_n}; | |
462 | } | |
463 | if($tte_n eq 'tte_context' and $force_ctx_zero) { | |
464 | $value = 0; | |
465 | } | |
466 | } | |
467 | ||
468 | $tag{"$descr->{hi}" . ':' . "$descr->{lo}"} = $value; | |
469 | } | |
470 | ||
471 | ||
472 | } | |
473 | return $tag->stringify(); | |
474 | } | |
475 | ||
476 | ############################################################################## | |
477 | ||
478 | sub parse_tsb_data { | |
479 | my $mmutype = shift; | |
480 | my $ttefmt = shift; | |
481 | my $tte_data = shift; | |
482 | ||
483 | tie my %parsed, 'Tie::IxHash'; | |
484 | ||
485 | my $data = BitFieldTie->new(64, $tte_data); | |
486 | tie my %data, 'BitFieldTie', $data; | |
487 | ||
488 | my $types = $TSB_DATA_FORMAT{$mmutype}{$ttefmt}; | |
489 | foreach my $field (sort { $types->{$b}{hi} <=> $types->{$a}{hi}} | |
490 | keys %$types) | |
491 | { | |
492 | my $descr = $types->{$field}; | |
493 | my $value = $data{"$descr->{hi}" . ':' . "$descr->{lo}"}; | |
494 | my $name = (exists $descr->{name}) ? $descr->{name} : $field; | |
495 | ||
496 | $parsed{$name} = 0 unless defined $parsed{$name}; | |
497 | if(exists $descr->{src}) { | |
498 | my $v = BitFieldTie->new(64, 0); | |
499 | tie my %v, 'BitFieldTie', $v; | |
500 | $v{$descr->{src}} = $value; | |
501 | $value = $v->extract(31,0); | |
502 | } | |
503 | $parsed{$name} |= $value; | |
504 | ||
505 | } | |
506 | ||
507 | return \%parsed; | |
508 | } | |
509 | ||
510 | ############################################################################## | |
511 | ||
512 | sub is_good_format_for_mmu { | |
513 | my $mmutype = shift; | |
514 | my $ttefmt = shift; | |
515 | return 1 if exists $TSB_DATA_FORMAT{$mmutype}{$ttefmt}; | |
516 | return; | |
517 | } | |
518 | ||
519 | ############################################################################## | |
520 | 1; |