2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2013, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
9 #include "ValueLocation.h"
12 // #pragma mark - ValuePieceLocation
16 ValuePieceLocation::Normalize(bool bigEndian
)
18 uint64 excessMSBs
= bitOffset
/ 8;
19 uint64 excessLSBs
= size
- (bitOffset
+ bitSize
+ 7) / 8;
21 if (excessMSBs
> 0 || excessLSBs
> 0) {
23 case VALUE_PIECE_LOCATION_MEMORY
:
25 address
+= excessMSBs
;
27 address
+= excessLSBs
;
28 bitOffset
-= excessMSBs
* 8;
29 size
-= excessMSBs
+ excessLSBs
;
31 case VALUE_PIECE_LOCATION_UNKNOWN
:
32 bitOffset
-= excessMSBs
* 8;
33 size
-= excessMSBs
+ excessLSBs
;
35 case VALUE_PIECE_LOCATION_REGISTER
:
45 // #pragma mark - ValueLocation
48 ValueLocation::ValueLocation()
56 ValueLocation::ValueLocation(bool bigEndian
)
58 fBigEndian(bigEndian
),
64 ValueLocation::ValueLocation(bool bigEndian
, const ValuePieceLocation
& piece
)
72 ValueLocation::ValueLocation(const ValueLocation
& other
)
74 fPieces(other
.fPieces
),
75 fBigEndian(other
.fBigEndian
)
81 ValueLocation::SetToByteOffset(const ValueLocation
& other
, uint64 byteOffset
,
86 fBigEndian
= other
.fBigEndian
;
87 ValuePieceLocation piece
= other
.PieceAt(0);
88 piece
.SetToMemory(piece
.address
+ byteOffset
);
89 piece
.SetSize(byteSize
);
91 return AddPiece(piece
);
96 ValueLocation::SetTo(const ValueLocation
& other
, uint64 bitOffset
,
101 fBigEndian
= other
.fBigEndian
;
103 // compute the total bit size
104 int32 count
= other
.CountPieces();
105 uint64 totalBitSize
= 0;
106 for (int32 i
= 0; i
< count
; i
++) {
107 const ValuePieceLocation
&piece
= other
.PieceAt(i
);
108 totalBitSize
+= piece
.bitSize
;
111 // adjust requested bit offset/size to something reasonable, if necessary
112 if (bitOffset
+ bitSize
> totalBitSize
) {
113 if (bitOffset
>= totalBitSize
)
115 bitSize
= totalBitSize
- bitOffset
;
119 // Big endian: Skip the superfluous most significant bits, copy the
120 // pieces we need (cutting the first and the last one as needed) and
121 // ignore the remaining pieces.
123 // skip pieces for the most significant bits we don't need anymore
124 uint64 bitsToSkip
= bitOffset
;
126 ValuePieceLocation piece
;
127 for (i
= 0; i
< count
; i
++) {
128 const ValuePieceLocation
& tempPiece
= other
.PieceAt(i
);
129 if (tempPiece
.bitSize
> bitsToSkip
) {
130 if (!piece
.Copy(tempPiece
))
134 bitsToSkip
-= tempPiece
.bitSize
;
137 // handle partial piece
138 if (bitsToSkip
> 0) {
139 piece
.bitOffset
+= bitsToSkip
;
140 piece
.bitSize
-= bitsToSkip
;
141 piece
.Normalize(fBigEndian
);
144 // handle remaining pieces
145 while (bitSize
> 0) {
146 if (piece
.bitSize
> bitSize
) {
147 // the piece is bigger than the remaining size -- cut it
148 piece
.bitSize
= bitSize
;
149 piece
.Normalize(fBigEndian
);
152 bitSize
-= piece
.bitSize
;
154 if (!AddPiece(piece
))
160 if (!piece
.Copy(other
.PieceAt(i
)))
164 // Little endian: Skip the superfluous least significant bits, copy the
165 // pieces we need (cutting the first and the last one as needed) and
166 // ignore the remaining pieces.
168 // skip pieces for the least significant bits we don't need anymore
169 uint64 bitsToSkip
= totalBitSize
- bitOffset
- bitSize
;
171 ValuePieceLocation piece
;
172 for (i
= 0; i
< count
; i
++) {
173 const ValuePieceLocation
& tempPiece
= other
.PieceAt(i
);
174 if (tempPiece
.bitSize
> bitsToSkip
) {
175 if (!piece
.Copy(tempPiece
))
179 bitsToSkip
-= piece
.bitSize
;
182 // handle partial piece
183 if (bitsToSkip
> 0) {
184 piece
.bitSize
-= bitsToSkip
;
185 piece
.Normalize(fBigEndian
);
188 // handle remaining pieces
189 while (bitSize
> 0) {
190 if (piece
.bitSize
> bitSize
) {
191 // the piece is bigger than the remaining size -- cut it
192 piece
.bitOffset
+= piece
.bitSize
- bitSize
;
193 piece
.bitSize
= bitSize
;
194 piece
.Normalize(fBigEndian
);
197 bitSize
-= piece
.bitSize
;
199 if (!AddPiece(piece
))
205 if (!piece
.Copy(other
.PieceAt(i
)))
215 ValueLocation::Clear()
223 ValueLocation::AddPiece(const ValuePieceLocation
& piece
)
225 // Just add, don't normalize. This allows for using the class with different
226 // semantics (e.g. in the DWARF code).
228 fPieces
.push_back(piece
);
233 if (fPieces
.size() == 1)
234 fWritable
= piece
.writable
;
236 fWritable
= fWritable
&& piece
.writable
;
243 ValueLocation::CountPieces() const
245 return fPieces
.size();
250 ValueLocation::PieceAt(int32 index
) const
252 if (index
< 0 || index
>= (int32
)fPieces
.size())
253 return ValuePieceLocation();
255 return fPieces
[index
];
260 ValueLocation::SetPieceAt(int32 index
, const ValuePieceLocation
& piece
)
262 if (index
< 0 || index
>= (int32
)fPieces
.size())
265 return fPieces
[index
].Copy(piece
);
270 ValueLocation::operator=(const ValueLocation
& other
)
272 fPieces
= other
.fPieces
;
273 fBigEndian
= other
.fBigEndian
;
279 ValueLocation::Dump() const
281 int32 count
= fPieces
.size();
282 printf("ValueLocation: %s endian, %" B_PRId32
" pieces:\n",
283 fBigEndian
? "big" : "little", count
);
285 for (int32 i
= 0; i
< count
; i
++) {
286 const ValuePieceLocation
& piece
= fPieces
[i
];
287 switch (piece
.type
) {
288 case VALUE_PIECE_LOCATION_INVALID
:
289 printf(" invalid\n");
291 case VALUE_PIECE_LOCATION_UNKNOWN
:
294 case VALUE_PIECE_LOCATION_MEMORY
:
295 printf(" address %#" B_PRIx64
, piece
.address
);
297 case VALUE_PIECE_LOCATION_REGISTER
:
298 printf(" register %" B_PRIu32
, piece
.reg
);
300 case VALUE_PIECE_LOCATION_IMPLICIT
:
301 printf(" implicit value: ");
302 for (uint32 j
= 0; j
< piece
.size
; j
++)
303 printf("%x ", ((char *)piece
.value
)[j
]);
307 printf(" size: %" B_PRIu64
" (%" B_PRIu64
" bits), offset: %" B_PRIu64
308 " bits\n", piece
.size
, piece
.bitSize
, piece
.bitOffset
);