1//===-- DNBRegisterInfo.cpp -------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//  Created by Greg Clayton on 8/3/07.
10//
11//===----------------------------------------------------------------------===//
12
13#include "DNBRegisterInfo.h"
14#include "DNBLog.h"
15#include <cstring>
16
17DNBRegisterValueClass::DNBRegisterValueClass(const DNBRegisterInfo *regInfo) {
18  Clear();
19  if (regInfo)
20    info = *regInfo;
21}
22
23void DNBRegisterValueClass::Clear() {
24  memset(&info, 0, sizeof(DNBRegisterInfo));
25  memset(&value, 0, sizeof(value));
26}
27
28bool DNBRegisterValueClass::IsValid() const {
29  return info.name != NULL && info.type != InvalidRegType && info.size > 0 &&
30         info.size <= sizeof(value);
31}
32
33#define PRINT_COMMA_SEPARATOR                                                  \
34  do {                                                                         \
35    if (pos < end) {                                                           \
36      if (i > 0) {                                                             \
37        strlcpy(pos, ", ", end - pos);                                         \
38        pos += 2;                                                              \
39      }                                                                        \
40    }                                                                          \
41  } while (0)
42
43void DNBRegisterValueClass::Dump(const char *pre, const char *post) const {
44  if (info.name != NULL) {
45    char str[1024];
46    char *pos;
47    char *end = str + sizeof(str);
48    if (info.format == Hex) {
49      switch (info.size) {
50      case 0:
51        snprintf(str, sizeof(str), "%s",
52                 "error: invalid register size of zero.");
53        break;
54      case 1:
55        snprintf(str, sizeof(str), "0x%2.2x", value.uint8);
56        break;
57      case 2:
58        snprintf(str, sizeof(str), "0x%4.4x", value.uint16);
59        break;
60      case 4:
61        snprintf(str, sizeof(str), "0x%8.8x", value.uint32);
62        break;
63      case 8:
64        snprintf(str, sizeof(str), "0x%16.16llx", value.uint64);
65        break;
66      case 16:
67        snprintf(str, sizeof(str), "0x%16.16llx%16.16llx", value.v_uint64[0],
68                 value.v_uint64[1]);
69        break;
70      default:
71        strlcpy(str, "0x", 3);
72        pos = str + 2;
73        for (uint32_t i = 0; i < info.size; ++i) {
74          if (pos < end)
75            pos +=
76                snprintf(pos, end - pos, "%2.2x", (uint32_t)value.v_uint8[i]);
77        }
78        break;
79      }
80    } else {
81      switch (info.type) {
82      case Uint:
83        switch (info.size) {
84        case 1:
85          snprintf(str, sizeof(str), "%u", value.uint8);
86          break;
87        case 2:
88          snprintf(str, sizeof(str), "%u", value.uint16);
89          break;
90        case 4:
91          snprintf(str, sizeof(str), "%u", value.uint32);
92          break;
93        case 8:
94          snprintf(str, sizeof(str), "%llu", value.uint64);
95          break;
96        default:
97          snprintf(str, sizeof(str), "error: unsupported uint byte size %d.",
98                   info.size);
99          break;
100        }
101        break;
102
103      case Sint:
104        switch (info.size) {
105        case 1:
106          snprintf(str, sizeof(str), "%d", value.sint8);
107          break;
108        case 2:
109          snprintf(str, sizeof(str), "%d", value.sint16);
110          break;
111        case 4:
112          snprintf(str, sizeof(str), "%d", value.sint32);
113          break;
114        case 8:
115          snprintf(str, sizeof(str), "%lld", value.sint64);
116          break;
117        default:
118          snprintf(str, sizeof(str), "error: unsupported sint byte size %d.",
119                   info.size);
120          break;
121        }
122        break;
123
124      case IEEE754:
125        switch (info.size) {
126        case 4:
127          snprintf(str, sizeof(str), "%f", value.float32);
128          break;
129        case 8:
130          snprintf(str, sizeof(str), "%g", value.float64);
131          break;
132        default:
133          snprintf(str, sizeof(str), "error: unsupported float byte size %d.",
134                   info.size);
135          break;
136        }
137        break;
138
139      case Vector:
140        if (info.size > 0) {
141          switch (info.format) {
142          case VectorOfSInt8:
143            snprintf(str, sizeof(str), "%s", "sint8   { ");
144            pos = str + strlen(str);
145            for (uint32_t i = 0; i < info.size; ++i) {
146              PRINT_COMMA_SEPARATOR;
147              if (pos < end)
148                pos +=
149                    snprintf(pos, end - pos, "%d", (int32_t)value.v_sint8[i]);
150            }
151            strlcat(str, " }", sizeof(str));
152            break;
153
154          default:
155            DNBLogError(
156                "unsupported vector format %d, defaulting to hex bytes.",
157                info.format);
158            [[clang::fallthrough]];
159          case VectorOfUInt8:
160            snprintf(str, sizeof(str), "%s", "uint8   { ");
161            pos = str + strlen(str);
162            for (uint32_t i = 0; i < info.size; ++i) {
163              PRINT_COMMA_SEPARATOR;
164              if (pos < end)
165                pos +=
166                    snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint8[i]);
167            }
168            break;
169
170          case VectorOfSInt16:
171            snprintf(str, sizeof(str), "%s", "sint16  { ");
172            pos = str + strlen(str);
173            for (uint32_t i = 0; i < info.size / 2; ++i) {
174              PRINT_COMMA_SEPARATOR;
175              if (pos < end)
176                pos +=
177                    snprintf(pos, end - pos, "%d", (int32_t)value.v_sint16[i]);
178            }
179            break;
180
181          case VectorOfUInt16:
182            snprintf(str, sizeof(str), "%s", "uint16  { ");
183            pos = str + strlen(str);
184            for (uint32_t i = 0; i < info.size / 2; ++i) {
185              PRINT_COMMA_SEPARATOR;
186              if (pos < end)
187                pos +=
188                    snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint16[i]);
189            }
190            break;
191
192          case VectorOfSInt32:
193            snprintf(str, sizeof(str), "%s", "sint32  { ");
194            pos = str + strlen(str);
195            for (uint32_t i = 0; i < info.size / 4; ++i) {
196              PRINT_COMMA_SEPARATOR;
197              if (pos < end)
198                pos +=
199                    snprintf(pos, end - pos, "%d", (int32_t)value.v_sint32[i]);
200            }
201            break;
202
203          case VectorOfUInt32:
204            snprintf(str, sizeof(str), "%s", "uint32  { ");
205            pos = str + strlen(str);
206            for (uint32_t i = 0; i < info.size / 4; ++i) {
207              PRINT_COMMA_SEPARATOR;
208              if (pos < end)
209                pos +=
210                    snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint32[i]);
211            }
212            break;
213
214          case VectorOfFloat32:
215            snprintf(str, sizeof(str), "%s", "float32 { ");
216            pos = str + strlen(str);
217            for (uint32_t i = 0; i < info.size / 4; ++i) {
218              PRINT_COMMA_SEPARATOR;
219              if (pos < end)
220                pos += snprintf(pos, end - pos, "%f", value.v_float32[i]);
221            }
222            break;
223
224          case VectorOfUInt128:
225            snprintf(str, sizeof(str), "%s", "uint128 { ");
226            pos = str + strlen(str);
227            for (uint32_t i = 0; i < info.size / 16; ++i) {
228              PRINT_COMMA_SEPARATOR;
229              if (pos < end)
230                pos += snprintf(pos, end - pos, "0x%16.16llx%16.16llx",
231                                value.v_uint64[i], value.v_uint64[i + 1]);
232            }
233            break;
234          }
235          strlcat(str, " }", sizeof(str));
236        } else {
237          snprintf(str, sizeof(str), "error: unsupported vector size %d.",
238                   info.size);
239        }
240        break;
241
242      default:
243        snprintf(str, sizeof(str), "error: unsupported register type %d.",
244                 info.type);
245        break;
246      }
247    }
248
249    DNBLog("%s%4s = %s%s", pre ? pre : "", info.name, str, post ? post : "");
250  }
251}
252