Print this page
patch fix-lint
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libdisasm/common/dis_sparc_fmt.c
+++ new/usr/src/lib/libdisasm/common/dis_sparc_fmt.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Copyright 2009 Jason King. All rights reserved.
29 29 * Use is subject to license terms.
30 30 * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
31 31 */
32 32
33 33
34 34 #include <sys/byteorder.h>
35 35 #include <stdarg.h>
36 36
37 37 #if !defined(DIS_STANDALONE)
38 38 #include <stdio.h>
39 39 #endif /* DIS_STANDALONE */
40 40
41 41 #include "libdisasm.h"
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
42 42 #include "libdisasm_impl.h"
43 43 #include "dis_sparc.h"
44 44 #include "dis_sparc_fmt.h"
45 45
46 46 extern char *strncpy(char *, const char *, size_t);
47 47 extern size_t strlen(const char *);
48 48 extern int strcmp(const char *, const char *);
49 49 extern int strncmp(const char *, const char *, size_t);
50 50 extern size_t strlcat(char *, const char *, size_t);
51 51 extern size_t strlcpy(char *, const char *, size_t);
52 -extern int snprintf(char *, size_t, const char *, ...);
53 -extern int vsnprintf(char *, size_t, const char *, va_list);
54 52
55 53 /*
56 54 * This file has the functions that do all the dirty work of outputting the
57 55 * disassembled instruction
58 56 *
59 57 * All the non-static functions follow the format_fcn (in dis_sparc.h):
60 58 * Input:
61 59 * disassembler handle/context
62 60 * instruction to disassemble
63 61 * instruction definition pointer (inst_t *)
64 62 * index in the table of the instruction
65 63 * Return:
66 64 * 0 Success
67 65 * !0 Invalid instruction
68 66 *
69 67 * Generally, instructions found in the same table use the same output format
70 68 * or have a few minor differences (which are described in the 'flags' field
71 69 * of the instruction definition. In some cases, certain instructions differ
72 70 * radically enough from those in the same table, that their own format
73 71 * function is used.
74 72 *
75 73 * Typically each table has a unique format function defined in this file. In
76 74 * some cases (such as branches) a common one for all the tables is used.
77 75 *
78 76 * When adding support for new instructions, it is largely a judgement call
79 77 * as to when a new format function is defined.
80 78 */
81 79
82 80 /* The various instruction formats of a sparc instruction */
83 81
84 82 #if defined(_BIT_FIELDS_HTOL)
85 83 typedef struct format1 {
86 84 uint32_t op:2;
87 85 uint32_t disp30:30;
88 86 } format1_t;
89 87 #elif defined(_BIT_FIELDS_LTOH)
90 88 typedef struct format1 {
91 89 uint32_t disp30:30;
92 90 uint32_t op:2;
93 91 } format1_t;
94 92 #else
95 93 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
96 94 #endif
97 95
98 96 #if defined(_BIT_FIELDS_HTOL)
99 97 typedef struct format2 {
100 98 uint32_t op:2;
101 99 uint32_t rd:5;
102 100 uint32_t op2:3;
103 101 uint32_t imm22:22;
104 102 } format2_t;
105 103 #elif defined(_BIT_FIELDS_LTOH)
106 104 typedef struct format2 {
107 105 uint32_t imm22:22;
108 106 uint32_t op2:3;
109 107 uint32_t rd:5;
110 108 uint32_t op:2;
111 109 } format2_t;
112 110 #else
113 111 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
114 112 #endif
115 113
116 114 #if defined(_BIT_FIELDS_HTOL)
117 115 typedef struct format2a {
118 116 uint32_t op:2;
119 117 uint32_t a:1;
120 118 uint32_t cond:4;
121 119 uint32_t op2:3;
122 120 uint32_t disp22:22;
123 121 } format2a_t;
124 122 #elif defined(_BIT_FIELDS_LTOH)
125 123 typedef struct format2a {
126 124 uint32_t disp22:22;
127 125 uint32_t op2:3;
128 126 uint32_t cond:4;
129 127 uint32_t a:1;
130 128 uint32_t op:2;
131 129 } format2a_t;
132 130 #else
133 131 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
134 132 #endif
135 133
136 134 #if defined(_BIT_FIELDS_HTOL)
137 135 typedef struct format2b {
138 136 uint32_t op:2;
139 137 uint32_t a:1;
140 138 uint32_t cond:4;
141 139 uint32_t op2:3;
142 140 uint32_t cc:2;
143 141 uint32_t p:1;
144 142 uint32_t disp19:19;
145 143 } format2b_t;
146 144 #elif defined(_BIT_FIELDS_LTOH)
147 145 typedef struct format2b {
148 146 uint32_t disp19:19;
149 147 uint32_t p:1;
150 148 uint32_t cc:2;
151 149 uint32_t op2:3;
152 150 uint32_t cond:4;
153 151 uint32_t a:1;
154 152 uint32_t op:2;
155 153 } format2b_t;
156 154 #else
157 155 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
158 156 #endif
159 157
160 158 #if defined(_BIT_FIELDS_HTOL)
161 159 typedef struct format2c {
162 160 uint32_t op:2;
163 161 uint32_t a:1;
164 162 uint32_t cond:4;
165 163 uint32_t op2:3;
166 164 uint32_t d16hi:2;
167 165 uint32_t p:1;
168 166 uint32_t rs1:5;
169 167 uint32_t d16lo:14;
170 168 } format2c_t;
171 169 #elif defined(_BIT_FIELDS_LTOH)
172 170 typedef struct format2c {
173 171 uint32_t d16lo:14;
174 172 uint32_t rs1:5;
175 173 uint32_t p:1;
176 174 uint32_t d16hi:2;
177 175 uint32_t op2:3;
178 176 uint32_t cond:4;
179 177 uint32_t a:1;
180 178 uint32_t op:2;
181 179 } format2c_t;
182 180 #else
183 181 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
184 182 #endif
185 183
186 184 #if defined(_BIT_FIELDS_HTOL)
187 185 typedef struct format3 {
188 186 uint32_t op:2;
189 187 uint32_t rd:5;
190 188 uint32_t op3:6;
191 189 uint32_t rs1:5;
192 190 uint32_t i:1;
193 191 uint32_t asi:8;
194 192 uint32_t rs2:5;
195 193 } format3_t;
196 194 #elif defined(_BIT_FIELDS_LTOH)
197 195 typedef struct format3 {
198 196 uint32_t rs2:5;
199 197 uint32_t asi:8;
200 198 uint32_t i:1;
201 199 uint32_t rs1:5;
202 200 uint32_t op3:6;
203 201 uint32_t rd:5;
204 202 uint32_t op:2;
205 203 } format3_t;
206 204 #else
207 205 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
208 206 #endif
209 207
210 208 #if defined(_BIT_FIELDS_HTOL)
211 209 typedef struct format3a {
212 210 uint32_t op:2;
213 211 uint32_t rd:5;
214 212 uint32_t op3:6;
215 213 uint32_t rs1:5;
216 214 uint32_t i:1;
217 215 uint32_t simm13:13;
218 216 } format3a_t;
219 217 #elif defined(_BIT_FIELDS_LTOH)
220 218 typedef struct format3a {
221 219 uint32_t simm13:13;
222 220 uint32_t i:1;
223 221 uint32_t rs1:5;
224 222 uint32_t op3:6;
225 223 uint32_t rd:5;
226 224 uint32_t op:2;
227 225 } format3a_t;
228 226 #else
229 227 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
230 228 #endif
231 229
232 230 #if defined(_BIT_FIELDS_HTOL)
233 231 typedef struct format3b {
234 232 uint32_t op:2;
235 233 uint32_t rd:5;
236 234 uint32_t op3:6;
237 235 uint32_t rs1:5;
238 236 uint32_t i:1;
239 237 uint32_t x:1;
240 238 uint32_t undef:6;
241 239 uint32_t shcnt:6;
242 240 } format3b_t;
243 241 #elif defined(_BIT_FIELDS_LTOH)
244 242 typedef struct format3b {
245 243 uint32_t shcnt:6;
246 244 uint32_t undef:6;
247 245 uint32_t x:1;
248 246 uint32_t i:1;
249 247 uint32_t rs1:5;
250 248 uint32_t op3:6;
251 249 uint32_t rd:5;
252 250 uint32_t op:2;
253 251 } format3b_t;
254 252 #else
255 253 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
256 254 #endif
257 255
258 256 #if defined(_BIT_FIELDS_HTOL)
259 257 typedef struct format3c {
260 258 uint32_t op:2;
261 259 uint32_t rd:5;
262 260 uint32_t op3:6;
263 261 uint32_t cc2:1;
264 262 uint32_t cond:4;
265 263 uint32_t i:1;
266 264 uint32_t cc:2;
267 265 uint32_t simm11:11;
268 266 } format3c_t;
269 267 #elif defined(_BIT_FIELDS_LTOH)
270 268 typedef struct format3c {
271 269 uint32_t simm11:11;
272 270 uint32_t cc:2;
273 271 uint32_t i:1;
274 272 uint32_t cond:4;
275 273 uint32_t cc2:1;
276 274 uint32_t op3:6;
277 275 uint32_t rd:5;
278 276 uint32_t op:2;
279 277 } format3c_t;
280 278 #else
281 279 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
282 280 #endif
283 281
284 282 #if defined(_BIT_FIELDS_HTOL)
285 283 typedef struct format3d {
286 284 uint32_t op:2;
287 285 uint32_t rd:5;
288 286 uint32_t op3:6;
289 287 uint32_t rs1:5;
290 288 uint32_t i:1;
291 289 uint32_t rcond:3;
292 290 uint32_t simm10:10;
293 291 } format3d_t;
294 292 #elif defined(_BIT_FIELDS_LTOH)
295 293 typedef struct format3d {
296 294 uint32_t simm10:10;
297 295 uint32_t rcond:3;
298 296 uint32_t i:1;
299 297 uint32_t rs1:5;
300 298 uint32_t op3:6;
301 299 uint32_t rd:5;
302 300 uint32_t op:2;
303 301 } format3d_t;
304 302 #else
305 303 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
306 304 #endif
307 305
308 306 #if defined(_BIT_FIELDS_HTOL)
309 307 typedef struct formatcp {
310 308 uint32_t op:2;
311 309 uint32_t rd:5;
312 310 uint32_t op3:6;
313 311 uint32_t rs1:5;
314 312 uint32_t opc:9;
315 313 uint32_t rs2:5;
316 314 } formatcp_t;
317 315 #elif defined(_BIT_FIELDS_LTOH)
318 316 typedef struct formatcp {
319 317 uint32_t rs2:5;
320 318 uint32_t opc:9;
321 319 uint32_t rs1:5;
322 320 uint32_t op3:6;
323 321 uint32_t rd:5;
324 322 uint32_t op:2;
325 323 } formatcp_t;
326 324 #else
327 325 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
328 326 #endif
329 327
330 328 #if defined(_BIT_FIELDS_HTOL)
331 329 typedef struct formattcc {
332 330 uint32_t op:2;
333 331 uint32_t undef:1;
334 332 uint32_t cond:4;
335 333 uint32_t op3:6;
336 334 uint32_t rs1:5;
337 335 uint32_t i:1;
338 336 uint32_t cc:2;
339 337 uint32_t undef2:3;
340 338 uint32_t immtrap:8;
341 339 } formattcc_t;
342 340 #elif defined(_BIT_FIELDS_LTOH)
343 341 typedef struct formattcc {
344 342 uint32_t immtrap:8;
345 343 uint32_t undef2:3;
346 344 uint32_t cc:2;
347 345 uint32_t i:1;
348 346 uint32_t rs1:5;
349 347 uint32_t op3:6;
350 348 uint32_t cond:4;
351 349 uint32_t undef:1;
352 350 uint32_t op:2;
353 351 } formattcc_t;
354 352 #else
355 353 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
356 354 #endif
357 355
358 356 #if defined(_BIT_FIELDS_HTOL)
359 357 typedef struct formattcc2 {
360 358 uint32_t op:2;
361 359 uint32_t undef:1;
362 360 uint32_t cond:4;
363 361 uint32_t op3:6;
364 362 uint32_t rs1:5;
365 363 uint32_t i:1;
366 364 uint32_t cc:2;
367 365 uint32_t undef2:6;
368 366 uint32_t rs2:5;
369 367 } formattcc2_t;
370 368 #elif defined(_BIT_FIELDS_LTOH)
371 369 typedef struct formattcc2 {
372 370 uint32_t rs2:5;
373 371 uint32_t undef2:6;
374 372 uint32_t cc:2;
375 373 uint32_t i:1;
376 374 uint32_t rs1:5;
377 375 uint32_t op3:6;
378 376 uint32_t cond:4;
379 377 uint32_t undef:1;
380 378 uint32_t op:2;
381 379 } formattcc2_t;
382 380 #else
383 381 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
384 382 #endif
385 383
386 384 #if defined(_BIT_FIELDS_HTOL)
387 385 typedef struct formatmbr {
388 386 uint32_t op:2;
389 387 uint32_t rd:5;
390 388 uint32_t op3:6;
391 389 uint32_t rs1:5;
392 390 uint32_t i:1;
393 391 uint32_t undef:6;
394 392 uint32_t cmask:3;
395 393 uint32_t mmask:4;
396 394 } formatmbr_t;
397 395 #elif defined(_BIT_FIELDS_LTOH)
398 396 typedef struct formatmbr {
399 397 uint32_t mmask:4;
400 398 uint32_t cmask:3;
401 399 uint32_t undef:6;
402 400 uint32_t i:1;
403 401 uint32_t rs1:5;
404 402 uint32_t op3:6;
405 403 uint32_t rd:5;
406 404 uint32_t op:2;
407 405 } formatmbr_t;
408 406 #else
409 407 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
410 408 #endif
411 409
412 410 #if defined(_BIT_FIELDS_HTOL)
413 411 typedef struct formatfcmp {
414 412 uint32_t op:2;
415 413 uint32_t undef:3;
416 414 uint32_t cc:2;
417 415 uint32_t op3:6;
418 416 uint32_t rs1:5;
419 417 uint32_t opf:9;
420 418 uint32_t rs2:5;
421 419 } formatfcmp_t;
422 420 #elif defined(_BIT_FIELDS_LTOH)
423 421 typedef struct formatfcmp {
424 422 uint32_t rs2:5;
425 423 uint32_t opf:9;
426 424 uint32_t rs1:5;
427 425 uint32_t op3:6;
428 426 uint32_t cc:2;
429 427 uint32_t undef:3;
430 428 uint32_t op:2;
431 429 } formatfcmp_t;
432 430 #else
433 431 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
434 432 #endif
435 433
436 434 #if defined(_BIT_FIELDS_HTOL)
437 435 typedef struct formatfmov {
438 436 uint32_t op:2;
439 437 uint32_t rd:5;
440 438 uint32_t op3:6;
441 439 uint32_t undef:1;
442 440 uint32_t cond:4;
443 441 uint32_t cc:3;
444 442 uint32_t opf:6;
445 443 uint32_t rs2:5;
446 444 } formatfmov_t;
447 445 #elif defined(_BIT_FIELDS_LTOH)
448 446 typedef struct formatfmov {
449 447 uint32_t rs2:5;
450 448 uint32_t opf:6;
451 449 uint32_t cc:3;
452 450 uint32_t cond:4;
453 451 uint32_t undef:1;
454 452 uint32_t op3:6;
455 453 uint32_t rd:5;
456 454 uint32_t op:2;
457 455 } formatfmov_t;
458 456 #else
459 457 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
460 458 #endif
461 459
462 460 #if defined(_BIT_FIELDS_HTOL)
463 461 typedef struct formatfused {
464 462 uint32_t op:2;
465 463 uint32_t rd:5;
466 464 uint32_t op3:6;
467 465 uint32_t rs1:5;
468 466 uint32_t rs3:5;
469 467 uint32_t op5:4;
470 468 uint32_t rs2:5;
471 469 } formatfused_t;
472 470 #elif defined(_BIT_FIELDS_LTOH)
473 471 typedef struct formatfused {
474 472 uint32_t rs2:5;
475 473 uint32_t op5:4;
476 474 uint32_t rs3:5;
477 475 uint32_t rs1:5;
478 476 uint32_t op3:6;
479 477 uint32_t rd:5;
480 478 uint32_t op:2;
481 479 } formatfused_t;
482 480 #else
483 481 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
484 482 #endif
485 483
486 484 typedef union ifmt {
487 485 uint32_t i;
488 486 format1_t f1;
489 487 format2_t f2;
490 488 format2a_t f2a;
491 489 format2b_t f2b;
492 490 format2c_t f2c;
493 491 format3_t f3;
494 492 format3a_t f3a;
495 493 format3b_t f3b;
496 494 format3c_t f3c;
497 495 format3d_t f3d;
498 496 formatcp_t fcp;
499 497 formattcc_t ftcc;
500 498 formattcc2_t ftcc2;
501 499 formatfcmp_t fcmp;
502 500 formatmbr_t fmb;
503 501 formatfmov_t fmv;
504 502 formatfused_t fused;
505 503 } ifmt_t;
506 504
507 505 /* integer register names */
508 506 static const char *reg_names[32] = {
509 507 "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
510 508 "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
511 509 "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
512 510 "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7"
513 511 };
514 512
515 513 /* floating point register names */
516 514 static const char *freg_names[32] = {
517 515 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
518 516 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
519 517 "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
520 518 "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31"
521 519 };
522 520
523 521 /* double precision register names */
524 522 static const char *fdreg_names[32] = {
525 523 "%d0", "%d32", "%d2", "%d34", "%d4", "%d36", "%d6", "%d38",
526 524 "%d8", "%d40", "%d10", "%d42", "%d12", "%d44", "%d14", "%d46",
527 525 "%d16", "%d48", "%d18", "%d50", "%d20", "%d52", "%d22", "%d54",
528 526 "%d24", "%d56", "%d26", "%d58", "%d28", "%d60", "%d30", "%d62"
529 527 };
530 528
531 529 static const char *compat_fdreg_names[32] = {
532 530 "%f0", "%f32", "%f2", "%f34", "%f4", "%f36", "%f6", "%f38",
533 531 "%f8", "%f40", "%f10", "%f42", "%f12", "%f44", "%f14", "%f46",
534 532 "%f16", "%f48", "%f18", "%f50", "%f20", "%f52", "%f22", "%f54",
535 533 "%f24", "%f56", "%f26", "%f58", "%f28", "%f60", "%f30", "%f62"
536 534 };
537 535
538 536
539 537 static const char *fqreg_names[32] = {
540 538 "%q0", "%q32", "%f2", "%f3", "%f4", "%q4", "%q36", "%f6",
541 539 "%f7", "%q8", "%q40", "%f10", "%f11", "%q12", "%q44", "%f14",
542 540 "%f15", "%q16", "%q48", "%f18", "%f19", "%q20", "%q52", "%f22",
543 541 "%f23", "%q24", "%q56", "%f26", "%f27", "%q28", "%q60", "%f30",
544 542 };
545 543
546 544
547 545 /* coprocessor register names -- sparcv8 only */
548 546 static const char *cpreg_names[32] = {
549 547 "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7",
550 548 "%c8", "%c9", "%c10", "%c11", "%c12", "%c13", "%c14", "%c15",
551 549 "%c16", "%c17", "%c18", "%c19", "%c20", "%c21", "%c22", "%c23",
552 550 "%c24", "%c25", "%c26", "%c27", "%c28", "%c29", "%c30", "%c31",
553 551 };
554 552
555 553 /* floating point condition code names */
556 554 static const char *fcc_names[4] = {
557 555 "%fcc0", "%fcc1", "%fcc2", "%fcc3"
558 556 };
559 557
560 558 /* condition code names */
561 559 static const char *icc_names[4] = {
562 560 "%icc", NULL, "%xcc", NULL
563 561 };
564 562
565 563 /* bitmask values for membar */
566 564 static const char *membar_mmask[4] = {
567 565 "#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore"
568 566 };
569 567
570 568 static const char *membar_cmask[3] = {
571 569 "#Lookaside", "#MemIssue", "#Sync"
572 570 };
573 571
574 572 /* v8 ancillary state register names */
575 573 static const char *asr_names[32] = {
576 574 "%y", "%asr1", "%asr2", "%asr3",
577 575 "%asr4", "%asr5", "%asr6", "%asr7",
578 576 "%asr8", "%asr9", "%asr10", "%asr11",
579 577 "%asr12", "%asr13", "%asr14", "%asr15",
580 578 NULL, NULL, NULL, NULL,
581 579 NULL, NULL, NULL, NULL,
582 580 NULL, NULL, NULL, NULL,
583 581 NULL, NULL, NULL, NULL
584 582 };
585 583 static const uint32_t asr_rdmask = 0x0000ffffL;
586 584 static const uint32_t asr_wrmask = 0x0000ffffL;
587 585
588 586 static const char *v9_asr_names[32] = {
589 587 "%y", NULL, "%ccr", "%asi",
590 588 "%tick", "%pc", "%fprs", NULL,
591 589 NULL, NULL, NULL, NULL,
592 590 NULL, NULL, NULL, NULL,
593 591 "%pcr", "%pic", "%dcr", "%gsr",
594 592 "%softint_set", "%softint_clr", "%softint", "%tick_cmpr",
595 593 "%stick", "%stick_cmpr", NULL, NULL,
596 594 NULL, NULL, NULL, NULL
597 595 };
598 596 /*
599 597 * on v9, only certain registers are valid for read or writing
600 598 * these are bitmasks corresponding to which registers are valid in which
601 599 * case. Any access to %dcr is illegal.
602 600 */
603 601 static const uint32_t v9_asr_rdmask = 0x03cb007d;
604 602 static const uint32_t v9_asr_wrmask = 0x03fb004d;
605 603
606 604 /* privledged register names on v9 */
607 605 /* TODO: compat - NULL to %priv_nn */
608 606 static const char *v9_privreg_names[32] = {
609 607 "%tpc", "%tnpc", "%tstate", "%tt",
610 608 "%tick", "%tba", "%pstate", "%tl",
611 609 "%pil", "%cwp", "%cansave", "%canrestore",
612 610 "%cleanwin", "%otherwin", "%wstate", "%fq",
613 611 "%gl", NULL, NULL, NULL,
614 612 NULL, NULL, NULL, NULL,
615 613 NULL, NULL, NULL, NULL,
616 614 NULL, NULL, NULL, "%ver"
617 615 };
618 616
619 617 /* hyper privileged register names on v9 */
620 618 static const char *v9_hprivreg_names[32] = {
621 619 "%hpstate", "%htstate", NULL, "%hintp",
622 620 NULL, "%htba", "%hver", NULL,
623 621 NULL, NULL, NULL, NULL,
624 622 NULL, NULL, NULL, NULL,
625 623 NULL, NULL, NULL, NULL,
626 624 NULL, NULL, NULL, NULL,
627 625 NULL, NULL, NULL, NULL,
628 626 NULL, NULL, NULL, "%hstick_cmpr"
629 627 };
630 628
631 629 static const uint32_t v9_pr_rdmask = 0x80017fff;
632 630 static const uint32_t v9_pr_wrmask = 0x00017fff;
633 631 static const uint32_t v9_hpr_rdmask = 0x8000006b;
634 632 static const uint32_t v9_hpr_wrmask = 0x8000006b;
635 633
636 634 static const char *prefetch_str[32] = {
637 635 "#n_reads", "#one_read",
638 636 "#n_writes", "#one_write",
639 637 "#page", NULL, NULL, NULL,
640 638 NULL, NULL, NULL, NULL,
641 639 NULL, NULL, NULL, NULL,
642 640 NULL, "#unified", NULL, NULL,
643 641 "#n_reads_strong", "#one_read_strong",
644 642 "#n_writes_strong", "#one_write_strong",
645 643 NULL, NULL, NULL, NULL,
646 644 NULL, NULL, NULL, NULL
647 645 };
648 646
649 647 static void prt_field(const char *, uint32_t, int);
650 648
651 649 static const char *get_regname(dis_handle_t *, int, uint32_t);
652 650 static int32_t sign_extend(int32_t, int32_t);
653 651
654 652 static void prt_name(dis_handle_t *, const char *, int);
655 653
656 654 #define IMM_SIGNED 0x01 /* Is immediate value signed */
657 655 #define IMM_ADDR 0x02 /* Is immediate value part of an address */
658 656 static void prt_imm(dis_handle_t *, uint32_t, int);
659 657
660 658 static void prt_asi(dis_handle_t *, uint32_t);
661 659 static const char *get_asi_name(uint8_t);
662 660 static void prt_address(dis_handle_t *, uint32_t, int);
663 661 static void prt_aluargs(dis_handle_t *, uint32_t, uint32_t);
664 662 static void bprintf(dis_handle_t *, const char *, ...);
665 663
666 664 /*
667 665 * print out val (which is 'bitlen' bits long) in binary
668 666 */
669 667 #if defined(DIS_STANDALONE)
670 668 /* ARGSUSED */
671 669 void
672 670 prt_binary(uint32_t val, int bitlen)
673 671 {
674 672
675 673 }
676 674
677 675 #else
678 676
679 677 void
680 678 prt_binary(uint32_t val, int bitlen)
681 679 {
682 680 int i;
683 681
684 682 for (i = bitlen - 1; i >= 0; --i) {
685 683 (void) fprintf(stderr, ((val & (1L << i)) != 0) ? "1" : "0");
686 684
687 685 if (i % 4 == 0 && i != 0)
688 686 (void) fprintf(stderr, " ");
689 687 }
690 688 }
691 689 #endif /* DIS_STANDALONE */
692 690
693 691
694 692 /*
695 693 * print out a call instruction
696 694 * format: call address <name>
697 695 */
698 696 /* ARGSUSED1 */
699 697 int
700 698 fmt_call(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
701 699 {
702 700 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
703 701 ifmt_t *f = (ifmt_t *)&instr;
704 702
705 703 int32_t disp;
706 704 size_t curlen;
707 705
708 706 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
709 707
710 708 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
711 709 prt_field("op", f->f1.op, 2);
712 710 prt_field("disp30", f->f1.disp30, 30);
713 711 }
714 712
715 713 disp = sign_extend(f->f1.disp30, 30) * 4;
716 714
717 715 prt_name(dhp, inp->in_data.in_def.in_name, 1);
718 716
719 717 bprintf(dhp, (octal != 0) ? "%s0%-11lo" : "%s0x%-10lx",
720 718 (disp < 0) ? "-" : "+",
721 719 (disp < 0) ? (-disp) : disp);
722 720
723 721 (void) strlcat(dhx->dhx_buf, " <", dhx->dhx_buflen);
724 722
725 723 curlen = strlen(dhx->dhx_buf);
726 724 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
727 725 dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen - 1, NULL,
728 726 NULL);
729 727 (void) strlcat(dhx->dhx_buf, ">", dhx->dhx_buflen);
730 728
731 729
732 730 return (0);
733 731 }
734 732
735 733 int
736 734 fmt_sethi(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
737 735 {
738 736 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
739 737 ifmt_t *f = (ifmt_t *)&instr;
740 738
741 739 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
742 740 prt_field("op", f->f2.op, 2);
743 741 prt_field("op2", f->f2.op2, 3);
744 742 prt_field("rd", f->f2.rd, 5);
745 743 prt_field("imm22", f->f2.imm22, 22);
746 744 }
747 745
748 746 if (idx == 0) {
749 747 /* unimp / illtrap */
750 748 prt_name(dhp, inp->in_data.in_def.in_name, 1);
751 749 prt_imm(dhp, f->f2.imm22, 0);
752 750 return (0);
753 751 }
754 752
755 753 if (f->f2.imm22 == 0 && f->f2.rd == 0) {
756 754 prt_name(dhp, "nop", 0);
757 755 return (0);
758 756 }
759 757
760 758 /* ?? Should we return -1 if rd == 0 && disp != 0 */
761 759
762 760 prt_name(dhp, inp->in_data.in_def.in_name, 1);
763 761
764 762 bprintf(dhp,
765 763 ((dhp->dh_flags & DIS_OCTAL) != 0) ?
766 764 "%%hi(0%lo), %s" : "%%hi(0x%lx), %s",
767 765 f->f2.imm22 << 10,
768 766 reg_names[f->f2.rd]);
769 767
770 768 return (0);
771 769 }
772 770
773 771 /* ARGSUSED3 */
774 772 int
775 773 fmt_branch(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
776 774 {
777 775 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
778 776 const char *name = inp->in_data.in_def.in_name;
779 777 const char *r = NULL;
780 778 const char *annul = "";
781 779 const char *pred = "";
782 780
783 781 char buf[15];
784 782
785 783 ifmt_t *f = (ifmt_t *)&instr;
786 784
787 785 size_t curlen;
788 786 int32_t disp;
789 787 uint32_t flags = inp->in_data.in_def.in_flags;
790 788 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
791 789
792 790 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
793 791 prt_field("op", f->f2.op, 2);
794 792 prt_field("op2", f->f2.op2, 3);
795 793
796 794 switch (FLG_DISP_VAL(flags)) {
797 795 case DISP22:
798 796 prt_field("cond", f->f2a.cond, 4);
799 797 prt_field("a", f->f2a.a, 1);
800 798 prt_field("disp22", f->f2a.disp22, 22);
801 799 break;
802 800
803 801 case DISP19:
804 802 prt_field("cond", f->f2a.cond, 4);
805 803 prt_field("a", f->f2a.a, 1);
806 804 prt_field("p", f->f2b.p, 1);
807 805 prt_field("cc", f->f2b.cc, 2);
808 806 prt_field("disp19", f->f2b.disp19, 19);
809 807 break;
810 808
811 809 case DISP16:
812 810 prt_field("bit 28", ((instr & (1L << 28)) >> 28), 1);
813 811 prt_field("rcond", f->f2c.cond, 3);
814 812 prt_field("p", f->f2c.p, 1);
815 813 prt_field("rs1", f->f2c.rs1, 5);
816 814 prt_field("d16hi", f->f2c.d16hi, 2);
817 815 prt_field("d16lo", f->f2c.d16lo, 14);
818 816 break;
819 817 }
820 818 }
821 819
822 820 if (f->f2b.op2 == 0x01 && idx == 0x00 && f->f2b.p == 1 &&
823 821 f->f2b.cc == 0x02 && ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) != 0)) {
824 822 name = "iprefetch";
825 823 flags = FLG_RS1(REG_NONE)|FLG_DISP(DISP19);
826 824 }
827 825
828 826
829 827 switch (FLG_DISP_VAL(flags)) {
830 828 case DISP22:
831 829 disp = sign_extend(f->f2a.disp22, 22);
832 830 break;
833 831
834 832 case DISP19:
835 833 disp = sign_extend(f->f2b.disp19, 19);
836 834 break;
837 835
838 836 case DISP16:
839 837 disp = sign_extend((f->f2c.d16hi << 14)|f->f2c.d16lo, 16);
840 838 break;
841 839
842 840 }
843 841
844 842 disp *= 4;
845 843
846 844 if ((FLG_RS1_VAL(flags) == REG_ICC) || (FLG_RS1_VAL(flags) == REG_FCC))
847 845 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2b.cc);
848 846 else
849 847 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2c.rs1);
850 848
851 849 if (r == NULL)
852 850 return (-1);
853 851
854 852 if (f->f2a.a == 1)
855 853 annul = ",a";
↓ open down ↓ |
792 lines elided |
↑ open up ↑ |
856 854
857 855 if ((flags & FLG_PRED) != 0) {
858 856 if (f->f2b.p == 0) {
859 857 pred = ",pn";
860 858 } else {
861 859 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0)
862 860 pred = ",pt";
863 861 }
864 862 }
865 863
866 - (void) snprintf(buf, sizeof (buf), "%s%s%s", name, annul, pred);
864 + (void) dis_snprintf(buf, sizeof (buf), "%s%s%s", name, annul, pred);
867 865 prt_name(dhp, buf, 1);
868 866
869 867
870 868 switch (FLG_DISP_VAL(flags)) {
871 869 case DISP22:
872 870 bprintf(dhp,
873 871 (octal != 0) ? "%s0%-11lo <" : "%s0x%-10lx <",
874 872 (disp < 0) ? "-" : "+",
875 873 (disp < 0) ? (-disp) : disp);
876 874 break;
877 875
878 876 case DISP19:
879 877 bprintf(dhp,
880 878 (octal != 0) ? "%s, %s0%-5lo <" :
881 879 "%s, %s0x%-04lx <", r,
882 880 (disp < 0) ? "-" : "+",
883 881 (disp < 0) ? (-disp) : disp);
884 882 break;
885 883
886 884 case DISP16:
887 885 bprintf(dhp,
888 886 (octal != 0) ? "%s, %s0%-6lo <" : "%s, %s0x%-5lx <",
889 887 r,
890 888 (disp < 0) ? "-" : "+",
891 889 (disp < 0) ? (-disp) : disp);
892 890 break;
893 891 }
894 892
895 893 curlen = strlen(dhx->dhx_buf);
896 894 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
897 895 dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen - 1, NULL, NULL);
898 896
899 897 (void) strlcat(dhx->dhx_buf, ">", dhx->dhx_buflen);
900 898
901 899 return (0);
902 900 }
903 901
904 902
905 903
906 904 /*
907 905 * print out the compare and swap instructions (casa/casxa)
908 906 * format: casa/casxa [%rs1] imm_asi, %rs2, %rd
909 907 * casa/casxa [%rs1] %asi, %rs2, %rd
910 908 *
911 909 * If DIS_DEBUG_SYN_ALL is set, synthetic instructions are emitted
912 910 * when an immediate ASI value is given as follows:
913 911 *
914 912 * casa [%rs1]#ASI_P, %rs2, %rd -> cas [%rs1], %rs2, %rd
915 913 * casa [%rs1]#ASI_P_L, %rs2, %rd -> casl [%rs1], %rs2, %rd
916 914 * casxa [%rs1]#ASI_P, %rs2, %rd -> casx [%rs1], %rs2, %rd
917 915 * casxa [%rs1]#ASI_P_L, %rs2, %rd -> casxl [%rs1], %rs2, %rd
918 916 */
919 917 static int
920 918 fmt_cas(dis_handle_t *dhp, uint32_t instr, const char *name)
921 919 {
922 920 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
923 921 ifmt_t *f = (ifmt_t *)&instr;
924 922 const char *asistr = NULL;
925 923 int noasi = 0;
926 924
927 925 asistr = get_asi_name(f->f3.asi);
928 926
929 927 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) != 0) {
930 928 if (f->f3.op3 == 0x3c && f->f3.i == 0) {
931 929 if (f->f3.asi == 0x80) {
932 930 noasi = 1;
933 931 name = "cas";
934 932 }
935 933
936 934 if (f->f3.asi == 0x88) {
937 935 noasi = 1;
938 936 name = "casl";
939 937 }
940 938 }
941 939
942 940 if (f->f3.op3 == 0x3e && f->f3.i == 0) {
943 941 if (f->f3.asi == 0x80) {
944 942 noasi = 1;
945 943 name = "casx";
946 944 }
947 945
948 946 if (f->f3.asi == 0x88) {
949 947 noasi = 1;
950 948 name = "casxl";
951 949 }
952 950 }
953 951 }
954 952
955 953 prt_name(dhp, name, 1);
956 954
957 955 bprintf(dhp, "[%s]", reg_names[f->f3.rs1]);
958 956
959 957 if (noasi == 0) {
960 958 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
961 959 prt_asi(dhp, instr);
962 960 }
963 961
964 962 bprintf(dhp, ", %s, %s", reg_names[f->f3.rs2], reg_names[f->f3.rd]);
965 963
966 964 if (noasi == 0 && asistr != NULL)
967 965 bprintf(dhp, "\t<%s>", asistr);
968 966
969 967 return (0);
970 968 }
971 969
972 970 /*
973 971 * format a load/store instruction
974 972 * format: ldXX [%rs1 + %rs2], %rd load, i==0
975 973 * ldXX [%rs1 +/- nn], %rd load, i==1
976 974 * ldXX [%rs1 + %rs2] #XX, %rd load w/ imm_asi, i==0
977 975 * ldXX [%rs1 +/- nn] %asi, %rd load from asi[%asi], i==1
978 976 *
979 977 * stXX %rd, [%rs1 + %rs2] store, i==0
980 978 * stXX %rd, [%rs1 +/- nn] store, i==1
981 979 * stXX %rd, [%rs1 + %rs1] #XX store to imm_asi, i==0
982 980 * stXX %rd, [%rs1 +/-nn] %asi store to asi[%asi], i==1
983 981 *
984 982 * The register sets used for %rd are set in the instructions flags field
985 983 * The asi variants are used if FLG_ASI is set in the instructions flags field
986 984 *
987 985 * If DIS_DEBUG_SYNTH_ALL or DIS_DEBUG_COMPAT are set,
988 986 * When %rs1, %rs2 or nn are 0, they are not printed, i.e.
989 987 * [ %rs1 + 0x0 ], %rd -> [%rs1], %rd for example
990 988 *
991 989 * The following synthetic instructions are also implemented:
992 990 *
993 991 * stb %g0, [addr] -> clrb [addr] DIS_DEBUG_SYNTH_ALL
994 992 * sth %g0, [addr] -> crlh [addr] DIS_DEBUG_SYNTH_ALL
995 993 * stw %g0, [addr] -> clr [addr] DIS_DEBUG_SYNTH_ALL|DIS_DEBUG_COMPAT
996 994 * stx %g0, [addr] -> clrx [addr] DIS_DEBUG_SYNTH_ALL
997 995 *
998 996 * If DIS_DEBUG_COMPAT is set, the following substitutions also take place
999 997 * lduw -> ld
1000 998 * ldtw -> ld
1001 999 * stuw -> st
1002 1000 * sttw -> st
1003 1001 */
1004 1002 int
1005 1003 fmt_ls(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1006 1004 {
1007 1005 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1008 1006 ifmt_t *f = (ifmt_t *)&instr;
1009 1007 const char *regstr = NULL;
1010 1008 const char *asistr = NULL;
1011 1009
1012 1010 const char *iname = inp->in_data.in_def.in_name;
1013 1011 uint32_t flags = inp->in_data.in_def.in_flags;
1014 1012
1015 1013 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1016 1014 prt_field("op", f->f3.op, 2);
1017 1015 prt_field("op3", f->f3.op3, 6);
1018 1016 prt_field("rs1", f->f3.rs1, 5);
1019 1017 prt_field("i", f->f3.i, 1);
1020 1018 if (f->f3.i != 0) {
1021 1019 prt_field("simm13", f->f3a.simm13, 13);
1022 1020 } else {
1023 1021 if ((flags & FLG_ASI) != 0)
1024 1022 prt_field("imm_asi", f->f3.asi, 8);
1025 1023 prt_field("rs2", f->f3.rs2, 5);
1026 1024 }
1027 1025 prt_field("rd", f->f3.rd, 5);
1028 1026 }
1029 1027
1030 1028 if (idx == 0x2d || idx == 0x3d) {
1031 1029 /* prefetch / prefetcha */
1032 1030
1033 1031 prt_name(dhp, iname, 1);
1034 1032
1035 1033 prt_address(dhp, instr, 0);
1036 1034
1037 1035 if (idx == 0x3d) {
1038 1036 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1039 1037 prt_asi(dhp, instr);
1040 1038 }
1041 1039
1042 1040 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1043 1041
1044 1042 /* fcn field is the same as rd */
1045 1043 if (prefetch_str[f->f3.rd] != NULL)
1046 1044 (void) strlcat(dhx->dhx_buf, prefetch_str[f->f3.rd],
1047 1045 dhx->dhx_buflen);
1048 1046 else
1049 1047 prt_imm(dhp, f->f3.rd, 0);
1050 1048
1051 1049 if (idx == 0x3d && f->f3.i == 0) {
1052 1050 asistr = get_asi_name(f->f3.asi);
1053 1051 if (asistr != NULL)
1054 1052 bprintf(dhp, "\t<%s>", asistr);
1055 1053 }
1056 1054
1057 1055 return (0);
1058 1056 }
1059 1057
1060 1058 /* casa / casxa */
1061 1059 if (idx == 0x3c || idx == 0x3e)
1062 1060 return (fmt_cas(dhp, instr, iname));
1063 1061
1064 1062 /* synthetic instructions & special cases */
1065 1063 switch (idx) {
1066 1064 case 0x00:
1067 1065 /* ld */
1068 1066 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1069 1067 iname = "lduw";
1070 1068 break;
1071 1069
1072 1070 case 0x03:
1073 1071 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1074 1072 iname = "ldtw";
1075 1073 break;
1076 1074
1077 1075 case 0x04:
1078 1076 /* stw */
1079 1077 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1080 1078 iname = "stuw";
1081 1079
1082 1080 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1083 1081 == 0)
1084 1082 break;
1085 1083
1086 1084 if (f->f3.rd == 0) {
1087 1085 iname = "clr";
1088 1086 flags = FLG_RD(REG_NONE);
1089 1087 }
1090 1088 break;
1091 1089
1092 1090 case 0x05:
1093 1091 /* stb */
1094 1092 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1095 1093 == 0)
1096 1094 break;
1097 1095
1098 1096 if (f->f3.rd == 0) {
1099 1097 iname = "clrb";
1100 1098 flags = FLG_RD(REG_NONE);
1101 1099 }
1102 1100 break;
1103 1101
1104 1102 case 0x06:
1105 1103 /* sth */
1106 1104 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1107 1105 == 0)
1108 1106 break;
1109 1107
1110 1108 if (f->f3.rd == 0) {
1111 1109 iname = "clrh";
1112 1110 flags = FLG_RD(REG_NONE);
1113 1111 }
1114 1112 break;
1115 1113
1116 1114 case 0x07:
1117 1115 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
1118 1116 iname = "sttw";
1119 1117 break;
1120 1118
1121 1119 case 0x0e:
1122 1120 /* stx */
1123 1121
1124 1122 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1125 1123 == 0)
1126 1124 break;
1127 1125
1128 1126 if (f->f3.rd == 0) {
1129 1127 iname = "clrx";
1130 1128 flags = FLG_RD(REG_NONE);
1131 1129 }
1132 1130 break;
1133 1131
1134 1132 case 0x13:
1135 1133 /* ldtwa */
1136 1134 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) &&
1137 1135 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
1138 1136 iname = "ldtwa";
1139 1137 break;
1140 1138
1141 1139 case 0x17:
1142 1140 /* sttwa */
1143 1141 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) &&
1144 1142 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
1145 1143 iname = "sttwa";
1146 1144 break;
1147 1145
1148 1146 case 0x21:
1149 1147 case 0x25:
1150 1148 /*
1151 1149 * on sparcv8 it merely says that rd != 1 should generate an
1152 1150 * exception, on v9, it is illegal
1153 1151 */
1154 1152 if ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0)
1155 1153 break;
1156 1154
1157 1155 iname = (idx == 0x21) ? "ldx" : "stx";
1158 1156
1159 1157 if (f->f3.rd > 1)
1160 1158 return (-1);
1161 1159
1162 1160 break;
1163 1161
1164 1162 case 0x31:
1165 1163 /* stda */
1166 1164 switch (f->f3.asi) {
1167 1165 case 0xc0:
1168 1166 case 0xc1:
1169 1167 case 0xc8:
1170 1168 case 0xc9:
1171 1169 case 0xc2:
1172 1170 case 0xc3:
1173 1171 case 0xca:
1174 1172 case 0xcb:
1175 1173 case 0xc4:
1176 1174 case 0xc5:
1177 1175 case 0xcc:
1178 1176 case 0xcd:
1179 1177 /*
1180 1178 * store partial floating point, only valid w/
1181 1179 * vis
1182 1180 *
1183 1181 * Somewhat confusingly, it uses the same op
1184 1182 * code as 'stda' -- store double to alternate
1185 1183 * space. It is distinguised by specific
1186 1184 * imm_asi values (as seen above), and
1187 1185 * has a slightly different output syntax
1188 1186 */
1189 1187
1190 1188 if ((dhp->dh_flags & DIS_SPARC_V9_SGI) == 0)
1191 1189 break;
1192 1190 if (f->f3.i != 0)
1193 1191 break;
1194 1192 prt_name(dhp, iname, 1);
1195 1193 bprintf(dhp, "%s, %s, [%s] ",
1196 1194 get_regname(dhp, REG_FPD, f->f3.rd),
1197 1195 get_regname(dhp, REG_FPD, f->f3.rs2),
1198 1196 get_regname(dhp, REG_FPD, f->f3.rs1));
1199 1197 prt_asi(dhp, instr);
1200 1198 asistr = get_asi_name(f->f3.asi);
1201 1199 if (asistr != NULL)
1202 1200 bprintf(dhp, "\t<%s>", asistr);
1203 1201
1204 1202 return (0);
1205 1203
1206 1204 default:
1207 1205 break;
1208 1206 }
1209 1207
1210 1208 }
1211 1209
1212 1210 regstr = get_regname(dhp, FLG_RD_VAL(flags), f->f3.rd);
1213 1211
1214 1212 if (f->f3.i == 0)
1215 1213 asistr = get_asi_name(f->f3.asi);
1216 1214
1217 1215 prt_name(dhp, iname, 1);
1218 1216
1219 1217 if ((flags & FLG_STORE) != 0) {
1220 1218 if (regstr[0] != '\0') {
1221 1219 (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1222 1220 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1223 1221 }
1224 1222
1225 1223 prt_address(dhp, instr, 0);
1226 1224 if ((flags & FLG_ASI) != 0) {
1227 1225 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1228 1226 prt_asi(dhp, instr);
1229 1227 }
1230 1228 } else {
1231 1229 prt_address(dhp, instr, 0);
1232 1230 if ((flags & FLG_ASI) != 0) {
1233 1231 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1234 1232 prt_asi(dhp, instr);
1235 1233 }
1236 1234
1237 1235 if (regstr[0] != '\0') {
1238 1236 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1239 1237 (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1240 1238 }
1241 1239 }
1242 1240
1243 1241 if ((flags & FLG_ASI) != 0 && asistr != NULL)
1244 1242 bprintf(dhp, "\t<%s>", asistr);
1245 1243
1246 1244 return (0);
1247 1245 }
1248 1246
1249 1247 static int
1250 1248 fmt_cpop(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1251 1249 {
1252 1250 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1253 1251 ifmt_t *f = (ifmt_t *)&instr;
1254 1252 int flags = FLG_P1(REG_CP)|FLG_P2(REG_CP)|FLG_NOIMM|FLG_P3(REG_CP);
1255 1253
1256 1254 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1257 1255 prt_field("op", f->fcp.op, 2);
1258 1256 prt_field("op3", f->fcp.op3, 6);
1259 1257 prt_field("opc", f->fcp.opc, 9);
1260 1258 prt_field("rs1", f->fcp.rs1, 5);
1261 1259 prt_field("rs2", f->fcp.rs2, 5);
1262 1260 prt_field("rd", f->fcp.rd, 5);
1263 1261 }
1264 1262
1265 1263 prt_name(dhp, inp->in_data.in_def.in_name, 1);
1266 1264 prt_imm(dhp, f->fcp.opc, 0);
1267 1265
1268 1266 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1269 1267 (void) prt_aluargs(dhp, instr, flags);
1270 1268
1271 1269 return (0);
1272 1270 }
1273 1271
1274 1272 static int
1275 1273 dis_fmt_rdwr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1276 1274 {
1277 1275 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1278 1276 const char *psr_str = "%psr";
1279 1277 const char *wim_str = "%wim";
1280 1278 const char *tbr_str = "%tbr";
1281 1279
1282 1280 const char *name = inp->in_data.in_def.in_name;
1283 1281 const char *regstr = NULL;
1284 1282
1285 1283 ifmt_t *f = (ifmt_t *)&instr;
1286 1284
1287 1285 int rd = (idx < 0x30);
1288 1286 int v9 = (dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI));
1289 1287 int ridx = f->f3.rs1;
1290 1288 int i, first;
1291 1289 int pr_rs1 = 1;
1292 1290 int pr_rs2 = 1;
1293 1291
1294 1292 int use_mask = 1;
1295 1293 uint32_t mask;
1296 1294
1297 1295 if (rd == 0)
1298 1296 ridx = f->f3.rd;
1299 1297
1300 1298 switch (idx) {
1301 1299 case 0x28:
1302 1300 /* rd */
1303 1301
1304 1302 /* stbar */
1305 1303 if ((f->f3.rd == 0) && (f->f3.rs1 == 15) && (f->f3.i == 0)) {
1306 1304 prt_name(dhp, "stbar", 0);
1307 1305 return (0);
1308 1306 }
1309 1307
1310 1308 /* membar */
1311 1309 if ((v9 != 0) && (f->f3.rd == 0) && (f->f3.rs1 == 15) &&
1312 1310 (f->f3.i == 1) && ((f->i & (1L << 12)) == 0)) {
1313 1311
1314 1312 prt_name(dhp, "membar",
1315 1313 ((f->fmb.cmask != 0) || (f->fmb.mmask != 0)));
1316 1314
1317 1315 first = 0;
1318 1316
1319 1317 for (i = 0; i < 4; ++i) {
1320 1318 if ((f->fmb.cmask & (1L << i)) != 0) {
1321 1319 bprintf(dhp, "%s%s",
1322 1320 (first != 0) ? "|" : "",
1323 1321 membar_cmask[i]);
1324 1322 first = 1;
1325 1323 }
1326 1324 }
1327 1325
1328 1326 for (i = 0; i < 5; ++i) {
1329 1327 if ((f->fmb.mmask & (1L << i)) != 0) {
1330 1328 bprintf(dhp, "%s%s",
1331 1329 (first != 0) ? "|" : "",
1332 1330 membar_mmask[i]);
1333 1331 first = 1;
1334 1332 }
1335 1333 }
1336 1334
1337 1335 return (0);
1338 1336 }
1339 1337
1340 1338 if (v9 != 0) {
1341 1339 regstr = v9_asr_names[ridx];
1342 1340 mask = v9_asr_rdmask;
1343 1341 } else {
1344 1342 regstr = asr_names[ridx];
1345 1343 mask = asr_rdmask;
1346 1344 }
1347 1345 break;
1348 1346
1349 1347 case 0x29:
1350 1348 if (v9 != 0) {
1351 1349 regstr = v9_hprivreg_names[ridx];
1352 1350 mask = v9_hpr_rdmask;
1353 1351 } else {
1354 1352 regstr = psr_str;
1355 1353 use_mask = 0;
1356 1354 }
1357 1355 break;
1358 1356
1359 1357 case 0x2a:
1360 1358 if (v9 != 0) {
1361 1359 regstr = v9_privreg_names[ridx];
1362 1360 mask = v9_pr_rdmask;
1363 1361 } else {
1364 1362 regstr = wim_str;
1365 1363 use_mask = 0;
1366 1364 }
1367 1365 break;
1368 1366
1369 1367 case 0x2b:
1370 1368 if (v9 != 0) {
1371 1369 /* flushw */
1372 1370 prt_name(dhp, name, 0);
1373 1371 return (0);
1374 1372 }
1375 1373
1376 1374 regstr = tbr_str;
1377 1375 use_mask = 0;
1378 1376 break;
1379 1377
1380 1378 case 0x30:
1381 1379 if (v9 != 0) {
1382 1380 regstr = v9_asr_names[ridx];
1383 1381 mask = v9_asr_wrmask;
1384 1382 } else {
1385 1383 regstr = asr_names[ridx];
1386 1384 mask = asr_wrmask;
1387 1385 }
1388 1386
1389 1387 /*
1390 1388 * sir is shoehorned in here, per Ultrasparc 2007
1391 1389 * hyperprivileged edition, section 7.88, all of
1392 1390 * these must be true to distinguish from WRasr
1393 1391 */
1394 1392 if (v9 != 0 && f->f3.rd == 15 && f->f3.rs1 == 0 &&
1395 1393 f->f3.i == 1) {
1396 1394 prt_name(dhp, "sir", 1);
1397 1395 prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
1398 1396 IMM_SIGNED);
1399 1397 return (0);
1400 1398 }
1401 1399
1402 1400 /* synth: mov */
1403 1401 if ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1404 1402 == 0)
1405 1403 break;
1406 1404
1407 1405 if (v9 == 0) {
1408 1406 if (f->f3.rs1 == 0) {
1409 1407 name = "mov";
1410 1408 pr_rs1 = 0;
1411 1409 }
1412 1410
1413 1411 if ((f->f3.i == 0 && f->f3.rs2 == 0) ||
1414 1412 (f->f3.i == 1 && f->f3a.simm13 == 0)) {
1415 1413 name = "mov";
1416 1414 pr_rs2 = 0;
1417 1415 }
1418 1416 }
1419 1417
1420 1418 if (pr_rs1 == 0)
1421 1419 pr_rs2 = 1;
1422 1420
1423 1421 break;
1424 1422
1425 1423 case 0x31:
1426 1424 /*
1427 1425 * NOTE: due to the presence of an overlay entry for another
1428 1426 * table, this case only happens when doing v8 instructions
1429 1427 * only
1430 1428 */
1431 1429 regstr = psr_str;
1432 1430 use_mask = 0;
1433 1431 break;
1434 1432
1435 1433 case 0x32:
1436 1434 if (v9 != 0) {
1437 1435 regstr = v9_privreg_names[ridx];
1438 1436 mask = v9_pr_wrmask;
1439 1437 } else {
1440 1438 regstr = wim_str;
1441 1439 use_mask = 0;
1442 1440 }
1443 1441 break;
1444 1442
1445 1443 case 0x33:
1446 1444 if (v9 != 0) {
1447 1445 regstr = v9_hprivreg_names[ridx];
1448 1446 mask = v9_hpr_wrmask;
1449 1447 } else {
1450 1448 regstr = tbr_str;
1451 1449 use_mask = 0;
1452 1450 }
1453 1451 break;
1454 1452 }
1455 1453
1456 1454 if (regstr == NULL)
1457 1455 return (-1);
1458 1456
1459 1457 if (use_mask != 0 && ((1L << ridx) & mask) == 0)
1460 1458 return (-1);
1461 1459
1462 1460 prt_name(dhp, name, 1);
1463 1461
1464 1462 if (rd != 0) {
1465 1463 bprintf(dhp, "%s, %s", regstr, reg_names[f->f3.rd]);
1466 1464 } else {
1467 1465 if (pr_rs1 == 1)
1468 1466 bprintf(dhp, "%s, ", reg_names[f->f3.rs1]);
1469 1467
1470 1468 if (pr_rs2 != 0) {
1471 1469 if (f->f3.i == 1)
1472 1470 prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
1473 1471 IMM_SIGNED);
1474 1472 else
1475 1473 (void) strlcat(dhx->dhx_buf,
1476 1474 reg_names[f->f3.rs2], dhx->dhx_buflen);
1477 1475 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1478 1476 }
1479 1477
1480 1478 (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1481 1479 }
1482 1480
1483 1481 return (0);
1484 1482 }
1485 1483
1486 1484 /* ARGSUSED3 */
1487 1485 int
1488 1486 fmt_trap(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1489 1487 {
1490 1488 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1491 1489 ifmt_t *f = (ifmt_t *)&instr;
1492 1490
1493 1491 int v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
1494 1492 int p_rs1, p_t;
1495 1493
1496 1494 if (f->ftcc.undef != 0)
1497 1495 return (-1);
1498 1496
1499 1497 if (icc_names[f->ftcc.cc] == NULL)
1500 1498 return (-1);
1501 1499
1502 1500 if (f->ftcc.i == 1 && f->ftcc.undef2 != 0)
1503 1501 return (-1);
1504 1502
1505 1503 if (f->ftcc2.i == 0 && f->ftcc2.undef2 != 0)
1506 1504 return (-1);
1507 1505
1508 1506 p_rs1 = ((f->ftcc.rs1 != 0) ||
1509 1507 ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0));
1510 1508
1511 1509 if (f->ftcc.i == 0) {
1512 1510 p_t = (f->f3.rs2 != 0 || p_rs1 == 0);
1513 1511
1514 1512 bprintf(dhp, "%-9s %s%s%s%s%s", inp->in_data.in_def.in_name,
1515 1513 (v9 != 0) ? icc_names[f->ftcc2.cc] : "",
1516 1514 (v9 != 0) ? ", " : "",
1517 1515 (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "",
1518 1516 (p_rs1 != 0) ? " + " : "",
1519 1517 (p_t != 0) ? reg_names[f->f3.rs2] : "");
1520 1518 } else {
1521 1519 bprintf(dhp, "%-9s %s%s%s%s0x%x", inp->in_data.in_def.in_name,
1522 1520 (v9 != 0) ? icc_names[f->ftcc2.cc] : "",
1523 1521 (v9 != 0) ? ", " : "",
1524 1522 (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "",
1525 1523 (p_rs1 != 0) ? " + " : "",
1526 1524 f->ftcc.immtrap);
1527 1525 }
1528 1526 return (0);
1529 1527 }
1530 1528
1531 1529 static int
1532 1530 prt_shift(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1533 1531 {
1534 1532 char name[5];
1535 1533 uint32_t cnt;
1536 1534
1537 1535 ifmt_t *f = (ifmt_t *)&instr;
1538 1536 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
1539 1537
1540 1538 name[0] = '\0';
1541 1539 (void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name));
1542 1540
1543 1541 if (f->f3b.i == 1)
1544 1542 cnt = f->f3.rs2;
1545 1543
1546 1544 if (f->f3b.x == 1 && ((dhp->dh_flags & DIS_SPARC_V8) == 0)) {
1547 1545 cnt = f->f3b.shcnt;
1548 1546 (void) strlcat(name, "x", sizeof (name));
1549 1547 }
1550 1548
1551 1549 prt_name(dhp, name, 1);
1552 1550
1553 1551 if (f->f3b.i == 1)
1554 1552 bprintf(dhp, (octal != 0) ? "%s, 0%lo, %s" : "%s, 0x%lx, %s",
1555 1553 reg_names[f->f3.rs1], cnt, reg_names[f->f3.rd]);
1556 1554 else
1557 1555 bprintf(dhp, "%s, %s, %s", reg_names[f->f3.rs1],
1558 1556 reg_names[f->f3.rs2], reg_names[f->f3.rd]);
1559 1557
1560 1558 return (0);
1561 1559 }
1562 1560
1563 1561 /* ARGSUSED3 */
1564 1562 static int
1565 1563 prt_jmpl(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1566 1564 {
1567 1565 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1568 1566 const char *name = inp->in_data.in_def.in_name;
1569 1567 ifmt_t *f = (ifmt_t *)&instr;
1570 1568
1571 1569 if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0))
1572 1570 name = "call";
1573 1571
1574 1572 if (f->f3.rd == 0) {
1575 1573 if (f->f3.i == 1 && f->f3a.simm13 == 8) {
1576 1574 if (f->f3.rs1 == 15) {
1577 1575 prt_name(dhp, "retl", 0);
1578 1576 return (0);
1579 1577 }
1580 1578
1581 1579 if (f->f3.rs1 == 31) {
1582 1580 prt_name(dhp, "ret", 0);
1583 1581 return (0);
1584 1582 }
1585 1583 }
1586 1584
1587 1585 name = "jmp";
1588 1586 }
1589 1587
1590 1588 prt_name(dhp, name, 1);
1591 1589 prt_address(dhp, instr, 1);
1592 1590
1593 1591 if (f->f3.rd == 0)
1594 1592 return (0);
1595 1593
1596 1594 if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0))
1597 1595 return (0);
1598 1596
1599 1597 bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1600 1598
1601 1599 return (0);
1602 1600 }
1603 1601
1604 1602 int
1605 1603 fmt_alu(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1606 1604 {
1607 1605 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1608 1606 ifmt_t *f = (ifmt_t *)&instr;
1609 1607
1610 1608 const char *name = inp->in_data.in_def.in_name;
1611 1609 int flags = inp->in_data.in_def.in_flags;
1612 1610 int arg = 0;
1613 1611
1614 1612 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1615 1613 prt_field("op", f->f3.op, 2);
1616 1614 prt_field("op3", f->f3.op3, 6);
1617 1615 prt_field("rs1", f->f3.rs1, 5);
1618 1616
1619 1617 switch (idx) {
1620 1618 /* TODO: more formats */
1621 1619
1622 1620 default:
1623 1621 if (f->f3.i == 0)
1624 1622 prt_field("rs2", f->f3.rs2, 5);
1625 1623 else
1626 1624 prt_field("simm13", f->f3a.simm13, 13);
1627 1625
1628 1626 prt_field("rd", f->f3.rd, 5);
1629 1627 }
1630 1628
1631 1629 }
1632 1630
1633 1631 switch (idx) {
1634 1632 case 0x00:
1635 1633 /* add */
1636 1634
1637 1635 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1638 1636 break;
1639 1637
1640 1638 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1641 1639 f->f3a.simm13 == 1) {
1642 1640 name = "inc";
1643 1641 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1644 1642 break;
1645 1643 }
1646 1644
1647 1645 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1648 1646 f->f3a.simm13 != 1) {
1649 1647 name = "inc";
1650 1648 flags = FLG_P1(REG_NONE);
1651 1649 break;
1652 1650 }
1653 1651 break;
1654 1652
1655 1653 case 0x02:
1656 1654 /* or */
1657 1655
1658 1656 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1659 1657 == 0)
1660 1658 break;
1661 1659
1662 1660 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) != 0) {
1663 1661 if (f->f3.rs1 == f->f3.rd) {
1664 1662 name = "bset";
1665 1663 flags = FLG_P1(REG_NONE);
1666 1664 break;
1667 1665 }
1668 1666 }
1669 1667
1670 1668 if (((f->f3.i == 0 && f->f3.rs2 == 0) ||
1671 1669 (f->f3.i == 1 && f->f3a.simm13 == 0)) &&
1672 1670 (f->f3.rs1 == 0)) {
1673 1671 name = "clr";
1674 1672 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1675 1673 break;
1676 1674 }
1677 1675
1678 1676 if (f->f3.rs1 == 0) {
1679 1677 name = "mov";
1680 1678 flags = FLG_P1(REG_NONE);
1681 1679 break;
1682 1680 }
1683 1681 break;
1684 1682
1685 1683 case 0x04:
1686 1684 /* sub */
1687 1685
1688 1686 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1689 1687 == 0)
1690 1688 break;
1691 1689
1692 1690 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 == f->f3.rd) {
1693 1691 name = "neg";
1694 1692 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE);
1695 1693 break;
1696 1694 }
1697 1695
1698 1696 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 != f->f3.rd) {
1699 1697 name = "neg";
1700 1698 flags = FLG_P1(REG_NONE);
1701 1699 break;
1702 1700 }
1703 1701
1704 1702 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1705 1703 break;
1706 1704
1707 1705 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1708 1706 f->f3a.simm13 == 1) {
1709 1707 name = "dec";
1710 1708 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1711 1709 break;
1712 1710 }
1713 1711
1714 1712 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1715 1713 f->f3a.simm13 != 1) {
1716 1714 name = "dec";
1717 1715 flags = FLG_P1(REG_NONE);
1718 1716 break;
1719 1717 }
1720 1718 break;
1721 1719
1722 1720 case 0x07:
1723 1721 /* xnor */
1724 1722
1725 1723 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1726 1724 == 0)
1727 1725 break;
1728 1726
1729 1727 /*
1730 1728 * xnor -> not when you have:
1731 1729 * xnor %rs1, 0x0 or %g0, %rd
1732 1730 */
1733 1731 if ((f->f3.i == 0 && f->f3.rs2 != 0) ||
1734 1732 (f->f3.i == 1 && f->f3a.simm13 != 0))
1735 1733 break;
1736 1734
1737 1735 name = "not";
1738 1736
1739 1737 if (f->f3.rs1 == f->f3.rd)
1740 1738 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM|
1741 1739 FLG_P3(REG_INT);
1742 1740 else
1743 1741 flags = FLG_P1(REG_INT)|FLG_P2(REG_NONE)|FLG_NOIMM|
1744 1742 FLG_P3(REG_INT);
1745 1743
1746 1744 break;
1747 1745
1748 1746 case 0x10:
1749 1747 /* addcc */
1750 1748
1751 1749 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1752 1750 break;
1753 1751
1754 1752 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1755 1753 f->f3a.simm13 == 1) {
1756 1754 name = "inccc";
1757 1755 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1758 1756 break;
1759 1757 }
1760 1758
1761 1759 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1762 1760 f->f3a.simm13 != 1) {
1763 1761 name = "inccc";
1764 1762 flags = FLG_P1(REG_NONE);
1765 1763 break;
1766 1764 }
1767 1765 break;
1768 1766
1769 1767 case 0x11:
1770 1768 /* andcc */
1771 1769
1772 1770 if (f->f3.rd != 0)
1773 1771 break;
1774 1772
1775 1773 if ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1776 1774 == 0)
1777 1775 break;
1778 1776
1779 1777 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0) &&
1780 1778 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0))
1781 1779 break;
1782 1780
1783 1781 name = "btst";
1784 1782 flags = FLG_P1(REG_NONE);
1785 1783 f->f3.rd = f->f3.rs1;
1786 1784 break;
1787 1785
1788 1786 case 0x12:
1789 1787 /* orcc */
1790 1788
1791 1789 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1792 1790 == 0)
1793 1791 break;
1794 1792
1795 1793 if (f->f3.rs1 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1796 1794 name = "tst";
1797 1795 flags = FLG_P1(REG_NONE)|FLG_P3(REG_NONE);
1798 1796 break;
1799 1797 }
1800 1798
1801 1799 if (f->f3.rs2 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1802 1800 name = "tst";
1803 1801 flags = FLG_P2(REG_NONE)|FLG_P3(REG_NONE);
1804 1802 break;
1805 1803 }
1806 1804
1807 1805 break;
1808 1806
1809 1807 case 0x14:
1810 1808 /* subcc */
1811 1809
1812 1810 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1813 1811 == 0)
1814 1812 break;
1815 1813
1816 1814 if (f->f3.rd == 0) {
1817 1815 name = "cmp";
1818 1816 flags = FLG_P3(REG_NONE);
1819 1817 break;
1820 1818 }
1821 1819
1822 1820 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0)
1823 1821 break;
1824 1822
1825 1823 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1826 1824 f->f3a.simm13 == 1) {
1827 1825 name = "deccc";
1828 1826 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1829 1827 break;
1830 1828 }
1831 1829
1832 1830 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1833 1831 f->f3a.simm13 != 1) {
1834 1832 name = "deccc";
1835 1833 flags = FLG_P1(REG_NONE);
1836 1834 break;
1837 1835 }
1838 1836
1839 1837 break;
1840 1838
1841 1839 case 0x25:
1842 1840 case 0x26:
1843 1841 case 0x27:
1844 1842 return (prt_shift(dhp, instr, inp));
1845 1843
1846 1844 case 0x28:
1847 1845 case 0x29:
1848 1846 case 0x2a:
1849 1847 case 0x2b:
1850 1848 case 0x30:
1851 1849 case 0x31:
1852 1850 case 0x32:
1853 1851 case 0x33:
1854 1852 return (dis_fmt_rdwr(dhp, instr, inp, idx));
1855 1853
1856 1854 case 0x36:
1857 1855 case 0x37:
1858 1856 /* NOTE: overlayed on v9 */
1859 1857 if ((dhp->dh_flags & DIS_SPARC_V8) != 0)
1860 1858 return (fmt_cpop(dhp, instr, inp));
1861 1859 break;
1862 1860
1863 1861 case 0x38:
1864 1862 /* jmpl */
1865 1863 return (prt_jmpl(dhp, instr, inp, idx));
1866 1864
1867 1865 case 0x39:
1868 1866 /* rett / return */
1869 1867 prt_name(dhp, name, 1);
1870 1868 prt_address(dhp, instr, 1);
1871 1869 return (0);
1872 1870
1873 1871 case 0x3b:
1874 1872 /* flush */
1875 1873 prt_name(dhp, name, 1);
1876 1874 prt_address(dhp, instr, 0);
1877 1875 return (0);
1878 1876
1879 1877 case 0x3c:
1880 1878 case 0x3d:
1881 1879 /* save / restore */
1882 1880 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1883 1881 == 0)
1884 1882 break;
1885 1883
1886 1884 if (f->f3.rs1 != 0 || f->f3.rs2 != 0 || f->f3.rd != 0)
1887 1885 break;
1888 1886
1889 1887 if (f->f3.i != 0 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0))
1890 1888 break;
1891 1889
1892 1890 prt_name(dhp, name, 0);
1893 1891 return (0);
1894 1892 }
1895 1893
1896 1894 if (FLG_P1_VAL(flags) != REG_NONE || FLG_P2_VAL(flags) != REG_NONE ||
1897 1895 FLG_P3_VAL(flags) != REG_NONE)
1898 1896 arg = 1;
1899 1897
1900 1898 prt_name(dhp, name, (arg != 0));
1901 1899 prt_aluargs(dhp, instr, flags);
1902 1900
1903 1901 return (0);
1904 1902 }
1905 1903
1906 1904 /* ARGSUSED1 */
1907 1905 int
1908 1906 fmt_regwin(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1909 1907 {
1910 1908 prt_name(dhp, inp->in_data.in_def.in_name, 0);
1911 1909 return (0);
1912 1910 }
1913 1911
1914 1912 /* ARGSUSED1 */
1915 1913 int
1916 1914 fmt_trap_ret(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1917 1915 {
1918 1916 ifmt_t *f = (ifmt_t *)&instr;
1919 1917 prt_name(dhp, inp->in_data.in_def.in_name, 1);
1920 1918
1921 1919 if (f->f3.rd == 0xf) {
1922 1920 /* jpriv */
1923 1921 prt_address(dhp, instr, 1);
1924 1922 }
1925 1923
1926 1924 return (0);
1927 1925 }
1928 1926
1929 1927 /* ARGSUSED3 */
1930 1928 int
1931 1929 fmt_movcc(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1932 1930 {
1933 1931 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1934 1932 ifmt_t *f = (ifmt_t *)&instr;
1935 1933 const char **regs = NULL;
1936 1934
1937 1935 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1938 1936 prt_field("op", f->f3c.op, 2);
1939 1937 prt_field("op3", f->f3c.op3, 6);
1940 1938 prt_field("cond", f->f3c.cond, 4);
1941 1939 prt_field("cc2", f->f3c.cc2, 1);
1942 1940 prt_field("cc", f->f3c.cc, 2);
1943 1941 prt_field("i", f->f3c.i, 1);
1944 1942
1945 1943 if (f->f3c.i == 0)
1946 1944 prt_field("rs2", f->f3.rs2, 5);
1947 1945 else
1948 1946 prt_field("simm11", f->f3c.simm11, 11);
1949 1947
1950 1948 prt_field("rd", f->f3.rd, 5);
1951 1949 }
1952 1950
1953 1951 if (f->f3c.cc2 == 0) {
1954 1952 regs = fcc_names;
1955 1953 } else {
1956 1954 regs = icc_names;
1957 1955 if (regs[f->f3c.cc] == NULL)
1958 1956 return (-1);
1959 1957 }
1960 1958
1961 1959 prt_name(dhp, inp->in_data.in_def.in_name, 1);
1962 1960
1963 1961 bprintf(dhp, "%s, ", regs[f->f3c.cc]);
1964 1962
1965 1963 if (f->f3c.i == 1)
1966 1964 prt_imm(dhp, sign_extend(f->f3c.simm11, 11), IMM_SIGNED);
1967 1965 else
1968 1966 (void) strlcat(dhx->dhx_buf, reg_names[f->f3.rs2],
1969 1967 dhx->dhx_buflen);
1970 1968
1971 1969 bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1972 1970
1973 1971 return (0);
1974 1972 }
1975 1973
1976 1974 /* ARGSUSED3 */
1977 1975 int
1978 1976 fmt_movr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1979 1977 {
1980 1978 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1981 1979 ifmt_t *f = (ifmt_t *)&instr;
1982 1980
1983 1981 prt_name(dhp, inp->in_data.in_def.in_name, 1);
1984 1982
1985 1983 bprintf(dhp, "%s, ", reg_names[f->f3d.rs1]);
1986 1984
1987 1985 if (f->f3d.i == 1)
1988 1986 prt_imm(dhp, sign_extend(f->f3d.simm10, 10), IMM_SIGNED);
1989 1987 else
1990 1988 (void) strlcat(dhx->dhx_buf, reg_names[f->f3.rs2],
1991 1989 dhx->dhx_buflen);
1992 1990
1993 1991 bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1994 1992
1995 1993 return (0);
1996 1994 }
1997 1995
1998 1996 /* ARGSUSED3 */
1999 1997 int
2000 1998 fmt_fpop1(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2001 1999 {
2002 2000 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2003 2001 ifmt_t *f = (ifmt_t *)&instr;
2004 2002 int flags = inp->in_data.in_def.in_flags;
2005 2003
2006 2004 flags |= FLG_NOIMM;
2007 2005
2008 2006 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2009 2007 prt_field("op", f->f3.op, 2);
2010 2008 prt_field("op3", f->f3.op3, 6);
2011 2009 prt_field("opf", f->fcmp.opf, 9);
2012 2010 prt_field("rs1", f->f3.rs1, 5);
2013 2011 prt_field("rs2", f->f3.rs2, 5);
2014 2012 prt_field("rd", f->f3.rd, 5);
2015 2013 }
2016 2014
2017 2015 prt_name(dhp, inp->in_data.in_def.in_name, 1);
2018 2016 prt_aluargs(dhp, instr, flags);
2019 2017
2020 2018 return (0);
2021 2019 }
2022 2020
2023 2021 int
2024 2022 fmt_fpop2(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2025 2023 {
2026 2024 static const char *condstr_icc[16] = {
2027 2025 "n", "e", "le", "l", "leu", "lu", "neg", "vs",
2028 2026 "a", "nz", "g", "ge", "gu", "geu", "pos", "vc"
2029 2027 };
2030 2028
2031 2029 static const char *condstr_fcc[16] = {
2032 2030 "n", "nz", "lg", "ul", "l", "ug", "g", "u",
2033 2031 "a", "e", "ue", "ge", "uge", "le", "ule", "o"
2034 2032 };
2035 2033
2036 2034 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2037 2035 ifmt_t *f = (ifmt_t *)&instr;
2038 2036 const char *ccstr = "";
2039 2037 char name[15];
2040 2038
2041 2039 int flags = inp->in_data.in_def.in_flags;
2042 2040 int is_cmp = (idx == 0x51 || idx == 0x52 || idx == 0x53 ||
2043 2041 idx == 0x55 || idx == 0x56 || idx == 0x57);
2044 2042 int is_fmov = (idx & 0x3f);
2045 2043 int is_v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
2046 2044 int is_compat = ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0);
2047 2045
2048 2046 int p_cc = 0;
2049 2047
2050 2048 is_fmov = (is_fmov == 0x1 || is_fmov == 0x2 || is_fmov == 0x3);
2051 2049
2052 2050 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2053 2051 prt_field("op", f->f3.op, 2);
2054 2052 prt_field("op3", f->f3.op3, 6);
2055 2053 prt_field("opf", f->fcmp.opf, 9);
2056 2054
2057 2055 switch (idx & 0x3f) {
2058 2056 case 0x51:
2059 2057 case 0x52:
2060 2058 case 0x53:
2061 2059 case 0x55:
2062 2060 case 0x56:
2063 2061 case 0x57:
2064 2062 prt_field("cc", f->fcmp.cc, 2);
2065 2063 prt_field("rs1", f->f3.rs1, 5);
2066 2064 prt_field("rs2", f->f3.rs2, 5);
2067 2065 break;
2068 2066
2069 2067 case 0x01:
2070 2068 case 0x02:
2071 2069 case 0x03:
2072 2070 prt_field("opf_low", f->fmv.opf, 6);
2073 2071 prt_field("cond", f->fmv.cond, 4);
2074 2072 prt_field("opf_cc", f->fmv.cc, 3);
2075 2073 prt_field("rs2", f->fmv.rs2, 5);
2076 2074 break;
2077 2075
2078 2076 default:
2079 2077 prt_field("rs1", f->f3.rs1, 5);
2080 2078 prt_field("rs2", f->f3.rs2, 5);
2081 2079 prt_field("rd", f->f3.rd, 5);
2082 2080 }
2083 2081 }
2084 2082
2085 2083 name[0] = '\0';
2086 2084 (void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name));
2087 2085
2088 2086 if (is_fmov != 0) {
2089 2087 (void) strlcat(name,
2090 2088 (f->fmv.cc < 4) ? condstr_fcc[f->fmv.cond]
2091 2089 : condstr_icc[f->fmv.cond],
2092 2090 sizeof (name));
2093 2091 }
2094 2092
2095 2093 prt_name(dhp, name, 1);
2096 2094
2097 2095 if (is_cmp != 0)
2098 2096 ccstr = fcc_names[f->fcmp.cc];
2099 2097
2100 2098 if (is_fmov != 0)
2101 2099 ccstr = (f->fmv.cc < 4) ? fcc_names[f->fmv.cc & 0x3]
2102 2100 : icc_names[f->fmv.cc & 0x3];
2103 2101
2104 2102 if (ccstr == NULL)
2105 2103 return (-1);
2106 2104
2107 2105 p_cc = (is_compat == 0 || is_v9 != 0 ||
2108 2106 (is_cmp != 0 && f->fcmp.cc != 0) ||
2109 2107 (is_fmov != 0 && f->fmv.cc != 0));
2110 2108
2111 2109 if (p_cc != 0)
2112 2110 bprintf(dhp, "%s, ", ccstr);
2113 2111
2114 2112 prt_aluargs(dhp, instr, flags);
2115 2113
2116 2114 return (0);
2117 2115 }
2118 2116
2119 2117 int
2120 2118 fmt_vis(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2121 2119 {
2122 2120 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2123 2121 ifmt_t *f = (ifmt_t *)&instr;
2124 2122 int flags = inp->in_data.in_def.in_flags;
2125 2123
2126 2124 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2127 2125 prt_field("op", f->f3.op, 2);
2128 2126 prt_field("op3", f->f3.op3, 6);
2129 2127 prt_field("opf", f->fcmp.opf, 9);
2130 2128
2131 2129 if (idx == 0x081) {
2132 2130 prt_field("mode", instr & 02L, 2);
2133 2131 } else {
2134 2132 prt_field("rs1", f->f3.rs1, 5);
2135 2133 prt_field("rs2", f->f3.rs2, 5);
2136 2134 prt_field("rd", f->f3.rd, 5);
2137 2135 }
2138 2136 }
2139 2137
2140 2138 prt_name(dhp, inp->in_data.in_def.in_name, 1);
2141 2139
2142 2140 if (idx == 0x081) {
2143 2141 /* siam */
2144 2142 bprintf(dhp, "%d", instr & 0x7L);
2145 2143 return (0);
2146 2144 }
2147 2145
2148 2146 prt_aluargs(dhp, instr, flags);
2149 2147
2150 2148 return (0);
2151 2149 }
2152 2150
2153 2151 /* ARGSUSED3 */
2154 2152 int
2155 2153 fmt_fused(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2156 2154 {
2157 2155 ifmt_t *f = (ifmt_t *)&instr;
2158 2156 int flags = inp->in_data.in_def.in_flags;
2159 2157
2160 2158 prt_name(dhp, inp->in_data.in_def.in_name, 1);
2161 2159 bprintf(dhp, "%s, %s, %s, %s",
2162 2160 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs1),
2163 2161 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs2),
2164 2162 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs3),
2165 2163 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rd));
2166 2164
2167 2165 return (0);
2168 2166 }
2169 2167 /*
2170 2168 * put name into the output buffer
2171 2169 * if add_space !=0, append a space after it
2172 2170 */
2173 2171 static void
2174 2172 prt_name(dis_handle_t *dhp, const char *name, int add_space)
2175 2173 {
2176 2174 bprintf(dhp, (add_space == 0) ? "%s" : "%-9s ", name);
2177 2175 }
2178 2176
2179 2177 /*
2180 2178 * For debugging, print out a field of the instruction
2181 2179 * field is the name of the field
2182 2180 * val is the value of the field
2183 2181 * len is the length of the field (in bits)
2184 2182 */
2185 2183 #if defined(DIS_STANDALONE)
2186 2184 /* ARGSUSED */
2187 2185 static void
2188 2186 prt_field(const char *field, uint32_t val, int len)
2189 2187 {
2190 2188
2191 2189 }
2192 2190
2193 2191 #else
2194 2192 static void
2195 2193 prt_field(const char *field, uint32_t val, int len)
2196 2194 {
2197 2195 (void) fprintf(stderr, "DISASM: %8s = 0x%-8x (", field, val);
2198 2196 prt_binary(val, len);
2199 2197 (void) fprintf(stderr, ")\n");
2200 2198 }
2201 2199 #endif /* DIS_STANDALONE */
2202 2200
2203 2201 /*
2204 2202 * sign extend a val (that is 'bits' bits in length) to a 32-bit signed
2205 2203 * integer
2206 2204 */
2207 2205 static int32_t
2208 2206 sign_extend(int32_t val, int32_t bits)
2209 2207 {
2210 2208 if ((val & (1L << (bits - 1))) == 0)
2211 2209 return (val);
2212 2210
2213 2211 return ((-1L << bits) | val);
2214 2212 }
2215 2213
2216 2214 /*
2217 2215 * print out an immediate (i.e. constant) value
2218 2216 * val is the value
2219 2217 * format indicates if it is:
2220 2218 * 0 Unsigned
2221 2219 * IMM_SIGNED A signed value (prepend +/- to the value)
2222 2220 * IMM_ADDR Part of an address expression (prepend +/- but with a space
2223 2221 * between the sign and the value for things like [%i1 + 0x55]
2224 2222 */
2225 2223 static void
2226 2224 prt_imm(dis_handle_t *dhp, uint32_t val, int format)
2227 2225 {
2228 2226 const char *fmtstr = NULL;
2229 2227 int32_t sv = (int32_t)val;
2230 2228 int octal = dhp->dh_flags & DIS_OCTAL;
2231 2229
2232 2230 switch (format) {
2233 2231 case IMM_ADDR:
2234 2232 if (sv < 0) {
2235 2233 sv = -sv;
2236 2234 fmtstr = (octal != 0) ? "- 0%lo" : "- 0x%lx";
2237 2235 } else {
2238 2236 fmtstr = (octal != 0) ? "+ 0%lo" : "+ 0x%lx";
2239 2237 }
2240 2238 break;
2241 2239
2242 2240 case IMM_SIGNED:
2243 2241 if (sv < 0) {
2244 2242 sv = -sv;
2245 2243 fmtstr = (octal != 0) ? "-0%lo" : "-0x%lx";
2246 2244 break;
2247 2245 }
2248 2246 /* fall through */
2249 2247
2250 2248 default:
2251 2249 fmtstr = (octal != 0) ? "0%lo" : "0x%lx";
2252 2250 }
2253 2251
2254 2252 bprintf(dhp, fmtstr, sv);
2255 2253 }
2256 2254
2257 2255 /*
2258 2256 * return the symbolic name of a register
2259 2257 * regset is one of the REG_* values indicating which type of register it is
2260 2258 * such as integer, floating point, etc.
2261 2259 * idx is the numeric value of the register
2262 2260 *
2263 2261 * If regset is REG_NONE, an empty, but non-NULL string is returned
2264 2262 * NULL may be returned if the index indicates an invalid register value
2265 2263 * such as with the %icc/%xcc sets
2266 2264 */
2267 2265 static const char *
2268 2266 get_regname(dis_handle_t *dhp, int regset, uint32_t idx)
2269 2267 {
2270 2268 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2271 2269 const char *regname = NULL;
2272 2270
2273 2271 switch (regset) {
2274 2272 case REG_INT:
2275 2273 regname = reg_names[idx];
2276 2274 break;
2277 2275
2278 2276 case REG_FP:
2279 2277 regname = freg_names[idx];
2280 2278 break;
2281 2279
2282 2280 case REG_FPD:
2283 2281 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) ||
2284 2282 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
2285 2283 regname = fdreg_names[idx];
2286 2284 else
2287 2285 regname = compat_fdreg_names[idx];
2288 2286
2289 2287 break;
2290 2288
2291 2289 case REG_FPQ:
2292 2290 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
2293 2291 regname = fqreg_names[idx];
2294 2292 else
2295 2293 regname = freg_names[idx];
2296 2294
2297 2295 break;
2298 2296
2299 2297 case REG_CP:
2300 2298 regname = cpreg_names[idx];
2301 2299 break;
2302 2300
2303 2301 case REG_ICC:
2304 2302 regname = icc_names[idx];
2305 2303 break;
2306 2304
2307 2305 case REG_FCC:
2308 2306 regname = fcc_names[idx];
2309 2307 break;
2310 2308
2311 2309 case REG_FSR:
2312 2310 regname = "%fsr";
2313 2311 break;
2314 2312
2315 2313 case REG_CSR:
2316 2314 regname = "%csr";
2317 2315 break;
2318 2316
2319 2317 case REG_CQ:
2320 2318 regname = "%cq";
2321 2319 break;
2322 2320
2323 2321 case REG_NONE:
2324 2322 regname = "";
2325 2323 break;
2326 2324 }
2327 2325
2328 2326 return (regname);
2329 2327 }
2330 2328
2331 2329 /*
2332 2330 * output the asi value from the instruction
2333 2331 *
2334 2332 * TODO: investigate if this should perhaps have a mask -- are undefined ASI
2335 2333 * values for an instruction still disassembled??
2336 2334 */
2337 2335 static void
2338 2336 prt_asi(dis_handle_t *dhp, uint32_t instr)
2339 2337 {
2340 2338 ifmt_t *f = (ifmt_t *)&instr;
2341 2339 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
2342 2340
2343 2341 if (f->f3.i != 0)
2344 2342 bprintf(dhp, "%%asi");
2345 2343 else
2346 2344 bprintf(dhp, (octal != 0) ? "0%03o" : "0x%02x", f->f3.asi);
2347 2345
2348 2346 }
2349 2347
2350 2348 /*
2351 2349 * put an address expression into the output buffer
2352 2350 *
2353 2351 * instr is the instruction to use
2354 2352 * if nobrackets != 0, [] are not added around the instruction
2355 2353 *
2356 2354 * Currently this option is set when printing out the address portion
2357 2355 * of a jmpl instruction, but otherwise 0 for load/stores
2358 2356 *
2359 2357 * If no debug flags are set, the full expression is output, even when
2360 2358 * %g0 or 0x0 appears in the address
2361 2359 *
2362 2360 * If DIS_DEBUG_SYN_ALL or DIS_DEBUG_COMPAT are set, when %g0 or 0x0
2363 2361 * appear in the address, they are not output. If the wierd (and probably
2364 2362 * shouldn't happen) address of [%g0 + %g0] or [%g0 + 0x0] is encountered,
2365 2363 * [%g0] is output
2366 2364 */
2367 2365 static void
2368 2366 prt_address(dis_handle_t *dhp, uint32_t instr, int nobrackets)
2369 2367 {
2370 2368 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2371 2369 ifmt_t *f = (ifmt_t *)&instr;
2372 2370 int32_t simm13;
2373 2371 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
2374 2372 int p1 = ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0);
2375 2373 int p2 = ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0);
2376 2374
2377 2375 if (f->f3a.i == 0) {
2378 2376 p1 |= ((f->f3a.rs1 != 0) || f->f3.rs2 == 0);
2379 2377 p2 |= (f->f3.rs2 != 0);
2380 2378
2381 2379 bprintf(dhp, "%s%s%s%s%s",
2382 2380 (nobrackets == 0) ? "[" : "",
2383 2381 (p1 != 0) ? reg_names[f->f3a.rs1] : "",
2384 2382 (p1 != 0 && p2 != 0) ? " + " : "",
2385 2383 (p2 != 0) ? reg_names[f->f3.rs2] : "",
2386 2384 (nobrackets == 0) ? "]" : "");
2387 2385 } else {
2388 2386 const char *sign;
2389 2387
2390 2388 simm13 = sign_extend(f->f3a.simm13, 13);
2391 2389 sign = (simm13 < 0) ? "-" : "+";
2392 2390
2393 2391 p1 |= (f->f3a.rs1 != 0);
2394 2392 p2 |= (p1 == 0 || simm13 != 0);
2395 2393
2396 2394 if (p1 == 0 && simm13 == 0)
2397 2395 p2 = 1;
2398 2396
2399 2397 if (p1 == 0 && simm13 >= 0)
2400 2398 sign = "";
2401 2399
2402 2400 if (p2 != 0)
2403 2401 bprintf(dhp,
2404 2402 (octal != 0) ? "%s%s%s%s%s0%lo%s" :
2405 2403 "%s%s%s%s%s0x%lx%s",
2406 2404 (nobrackets == 0) ? "[" : "",
2407 2405 (p1 != 0) ? reg_names[f->f3a.rs1] : "",
2408 2406 (p1 != 0) ? " " : "",
2409 2407 sign,
2410 2408 (p1 != 0) ? " " : "",
2411 2409 (simm13 < 0) ? -(simm13) : simm13,
2412 2410 (nobrackets == 0) ? "]" : "");
2413 2411 else
2414 2412 bprintf(dhp, "%s%s%s",
2415 2413 (nobrackets == 0) ? "[" : "",
2416 2414 reg_names[f->f3a.rs1],
2417 2415 (nobrackets == 0) ? "]" : "");
2418 2416 }
2419 2417 }
2420 2418
2421 2419 /*
2422 2420 * print out the arguments to an alu operation (add, sub, etc.)
2423 2421 * conatined in 'instr'
2424 2422 *
2425 2423 * alu instructions have the following format:
2426 2424 * %rs1, %rs2, %rd (i == 0)
2427 2425 * %rs1, 0xnnn, %rd (i == 1)
2428 2426 * ^ ^ ^
2429 2427 * | | |
2430 2428 * p1 p2 p3
2431 2429 *
2432 2430 * flags indicates the register set to use for each position (p1, p2, p3)
2433 2431 * as well as if immediate values (i == 1) are allowed
2434 2432 *
2435 2433 * if flags indicates a specific position has REG_NONE set as it's register
2436 2434 * set, it is omitted from the output. This is primarly used for certain
2437 2435 * floating point operations
2438 2436 */
2439 2437 static void
2440 2438 prt_aluargs(dis_handle_t *dhp, uint32_t instr, uint32_t flags)
2441 2439 {
2442 2440 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2443 2441 ifmt_t *f = (ifmt_t *)&instr;
2444 2442 const char *r1, *r2, *r3;
2445 2443 int p1, p2, p3;
2446 2444 unsigned int opf = 0;
2447 2445
2448 2446 r1 = get_regname(dhp, FLG_P1_VAL(flags), f->f3.rs1);
2449 2447 r2 = get_regname(dhp, FLG_P2_VAL(flags), f->f3.rs2);
2450 2448 r3 = get_regname(dhp, FLG_P3_VAL(flags), f->f3.rd);
2451 2449
2452 2450 p1 = (FLG_P1_VAL(flags) != REG_NONE);
2453 2451 p2 = (((flags & FLG_NOIMM) == 0) || (FLG_P2_VAL(flags) != REG_NONE));
2454 2452 p3 = (FLG_RD_VAL(flags) != REG_NONE);
2455 2453
2456 2454 if (r1 == NULL || r1[0] == '\0')
2457 2455 p1 = 0;
2458 2456
2459 2457 if (f->f3a.i == 0 && (r2 == NULL || r2[0] == '\0'))
2460 2458 p2 = 0;
2461 2459
2462 2460 if (r3 == NULL || r3[0] == '\0')
2463 2461 p3 = 0;
2464 2462
2465 2463 if ((f->fcmp.op == 2) && (f->fcmp.op3 == 0x36) && (f->fcmp.cc != 0))
2466 2464 opf = f->fcmp.opf;
2467 2465
2468 2466 if ((opf == 0x151) || (opf == 0x152)) {
2469 2467 (void) strlcat(dhx->dhx_buf, r3, dhx->dhx_buflen);
2470 2468 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
2471 2469 p3 = 0;
2472 2470 }
2473 2471
2474 2472 if (p1 != 0) {
2475 2473 (void) strlcat(dhx->dhx_buf, r1, dhx->dhx_buflen);
2476 2474 if (p2 != 0 || p3 != 0)
2477 2475 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
2478 2476 }
2479 2477
2480 2478 if (p2 != 0) {
2481 2479 if (f->f3.i == 0 || ((flags & FLG_NOIMM) != 0))
2482 2480 (void) strlcat(dhx->dhx_buf, r2, dhx->dhx_buflen);
2483 2481 else
2484 2482 prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
2485 2483 IMM_SIGNED);
2486 2484
2487 2485 if (p3 != 0)
2488 2486 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
2489 2487 }
2490 2488
2491 2489 if (p3 != 0)
2492 2490 (void) strlcat(dhx->dhx_buf, r3, dhx->dhx_buflen);
2493 2491 }
2494 2492
2495 2493 static const char *
2496 2494 get_asi_name(uint8_t asi)
2497 2495 {
2498 2496 switch (asi) {
2499 2497 case 0x04:
2500 2498 return ("ASI_N");
2501 2499
2502 2500 case 0x0c:
2503 2501 return ("ASI_NL");
2504 2502
2505 2503 case 0x10:
2506 2504 return ("ASI_AIUP");
2507 2505
2508 2506 case 0x11:
2509 2507 return ("ASI_AIUS");
2510 2508
2511 2509 case 0x14:
2512 2510 return ("ASI_REAL");
2513 2511
2514 2512 case 0x15:
2515 2513 return ("ASI_REAL_IO");
2516 2514
2517 2515 case 0x16:
2518 2516 return ("ASI_BLK_AIUP");
2519 2517
2520 2518 case 0x17:
2521 2519 return ("ASI_BLK_AIUS");
2522 2520
2523 2521 case 0x18:
2524 2522 return ("ASI_AIUPL");
2525 2523
2526 2524 case 0x19:
2527 2525 return ("ASI_AIUSL");
2528 2526
2529 2527 case 0x1c:
2530 2528 return ("ASI_REAL_L");
2531 2529
2532 2530 case 0x1d:
2533 2531 return ("ASI_REAL_IO_L");
2534 2532
2535 2533 case 0x1e:
2536 2534 return ("ASI_BLK_AIUPL");
2537 2535
2538 2536 case 0x1f:
2539 2537 return ("ASI_BLK_AIUS_L");
2540 2538
2541 2539 case 0x20:
2542 2540 return ("ASI_SCRATCHPAD");
2543 2541
2544 2542 case 0x21:
2545 2543 return ("ASI_MMU_CONTEXTID");
2546 2544
2547 2545 case 0x22:
2548 2546 return ("ASI_TWINX_AIUP");
2549 2547
2550 2548 case 0x23:
2551 2549 return ("ASI_TWINX_AIUS");
2552 2550
2553 2551 case 0x25:
2554 2552 return ("ASI_QUEUE");
2555 2553
2556 2554 case 0x26:
2557 2555 return ("ASI_TWINX_R");
2558 2556
2559 2557 case 0x27:
2560 2558 return ("ASI_TWINX_N");
2561 2559
2562 2560 case 0x2a:
2563 2561 return ("ASI_LDTX_AIUPL");
2564 2562
2565 2563 case 0x2b:
2566 2564 return ("ASI_TWINX_AIUS_L");
2567 2565
2568 2566 case 0x2e:
2569 2567 return ("ASI_TWINX_REAL_L");
2570 2568
2571 2569 case 0x2f:
2572 2570 return ("ASI_TWINX_NL");
2573 2571
2574 2572 case 0x30:
2575 2573 return ("ASI_AIPP");
2576 2574
2577 2575 case 0x31:
2578 2576 return ("ASI_AIPS");
2579 2577
2580 2578 case 0x36:
2581 2579 return ("ASI_AIPN");
2582 2580
2583 2581 case 0x38:
2584 2582 return ("ASI_AIPP_L");
2585 2583
2586 2584 case 0x39:
2587 2585 return ("ASI_AIPS_L");
2588 2586
2589 2587 case 0x3e:
2590 2588 return ("ASI_AIPN_L");
2591 2589
2592 2590 case 0x41:
2593 2591 return ("ASI_CMT_SHARED");
2594 2592
2595 2593 case 0x4f:
2596 2594 return ("ASI_HYP_SCRATCHPAD");
2597 2595
2598 2596 case 0x50:
2599 2597 return ("ASI_IMMU");
2600 2598
2601 2599 case 0x52:
2602 2600 return ("ASI_MMU_REAL");
2603 2601
2604 2602 case 0x54:
2605 2603 return ("ASI_MMU");
2606 2604
2607 2605 case 0x55:
2608 2606 return ("ASI_ITLB_DATA_ACCESS_REG");
2609 2607
2610 2608 case 0x56:
2611 2609 return ("ASI_ITLB_TAG_READ_REG");
2612 2610
2613 2611 case 0x57:
2614 2612 return ("ASI_IMMU_DEMAP");
2615 2613
2616 2614 case 0x58:
2617 2615 return ("ASI_DMMU / ASI_UMMU");
2618 2616
2619 2617 case 0x5c:
2620 2618 return ("ASI_DTLB_DATA_IN_REG");
2621 2619
2622 2620 case 0x5d:
2623 2621 return ("ASI_DTLB_DATA_ACCESS_REG");
2624 2622
2625 2623 case 0x5e:
2626 2624 return ("ASI_DTLB_TAG_READ_REG");
2627 2625
2628 2626 case 0x5f:
2629 2627 return ("ASI_DMMU_DEMAP");
2630 2628
2631 2629 case 0x63:
2632 2630 return ("ASI_CMT_PER_STRAND / ASI_CMT_PER_CORE");
2633 2631
2634 2632 case 0x80:
2635 2633 return ("ASI_P");
2636 2634
2637 2635 case 0x81:
2638 2636 return ("ASI_S");
2639 2637
2640 2638 case 0x82:
2641 2639 return ("ASI_PNF");
2642 2640
2643 2641 case 0x83:
2644 2642 return ("ASI_SNF");
2645 2643
2646 2644 case 0x88:
2647 2645 return ("ASI_PL");
2648 2646
2649 2647 case 0x89:
2650 2648 return ("ASI_SL");
2651 2649
2652 2650 case 0x8a:
2653 2651 return ("ASI_PNFL");
2654 2652
2655 2653 case 0x8b:
2656 2654 return ("ASI_SNFL");
2657 2655
2658 2656 case 0xc0:
2659 2657 return ("ASI_PST8_P");
2660 2658
2661 2659 case 0xc1:
2662 2660 return ("ASI_PST8_S");
2663 2661
2664 2662 case 0xc2:
2665 2663 return ("ASI_PST16_P");
2666 2664
2667 2665 case 0xc3:
2668 2666 return ("ASI_PST16_S");
2669 2667
2670 2668 case 0xc4:
2671 2669 return ("ASI_PST32_P");
2672 2670
2673 2671 case 0xc5:
2674 2672 return ("ASI_PST32_S");
2675 2673
2676 2674 case 0xc8:
2677 2675 return ("ASI_PST8_PL");
2678 2676
2679 2677 case 0xc9:
2680 2678 return ("ASI_PST8_SL");
2681 2679
2682 2680 case 0xca:
2683 2681 return ("ASI_PST16_PL");
2684 2682
2685 2683 case 0xcb:
2686 2684 return ("ASI_PST16_SL");
2687 2685
2688 2686 case 0xcc:
2689 2687 return ("ASI_PST32_PL");
2690 2688
2691 2689 case 0xcd:
2692 2690 return ("ASI_PST32_SL");
2693 2691
2694 2692 case 0xd0:
2695 2693 return ("ASI_FL8_P");
2696 2694
2697 2695 case 0xd1:
2698 2696 return ("ASI_FL8_S");
2699 2697
2700 2698 case 0xd2:
2701 2699 return ("ASI_FL16_P");
2702 2700
2703 2701 case 0xd3:
2704 2702 return ("ASI_FL16_S");
2705 2703
2706 2704 case 0xd8:
2707 2705 return ("ASI_FL8_PL");
2708 2706
2709 2707 case 0xd9:
2710 2708 return ("ASI_FL8_SL");
2711 2709
2712 2710 case 0xda:
2713 2711 return ("ASI_FL16_PL");
2714 2712
2715 2713 case 0xdb:
2716 2714 return ("ASI_FL16_SL");
2717 2715
2718 2716 case 0xe0:
2719 2717 return ("ASI_BLK_COMMIT_P");
2720 2718
2721 2719 case 0xe1:
2722 2720 return ("ASI_BLK_SOMMIT_S");
2723 2721
2724 2722 case 0xe2:
2725 2723 return ("ASI_TWINX_P");
2726 2724
2727 2725 case 0xe3:
2728 2726 return ("ASI_TWINX_S");
2729 2727
2730 2728 case 0xea:
2731 2729 return ("ASI_TWINX_PL");
2732 2730
2733 2731 case 0xeb:
2734 2732 return ("ASI_TWINX_SL");
2735 2733
2736 2734 case 0xf0:
2737 2735 return ("ASI_BLK_P");
2738 2736
2739 2737 case 0xf1:
2740 2738 return ("ASI_BLK_S");
2741 2739
2742 2740 case 0xf8:
2743 2741 return ("ASI_BLK_PL");
2744 2742
2745 2743 case 0xf9:
2746 2744 return ("ASI_BLK_SL");
2747 2745
2748 2746 default:
2749 2747 return (NULL);
2750 2748 }
2751 2749 }
2752 2750
2753 2751 /*
2754 2752 * just a handy function that takes care of managing the buffer length
2755 2753 * w/ printf
2756 2754 */
2757 2755
2758 2756 /*
2759 2757 * PRINTF LIKE 1
2760 2758 */
↓ open down ↓ |
1884 lines elided |
↑ open up ↑ |
2761 2759 static void
2762 2760 bprintf(dis_handle_t *dhp, const char *fmt, ...)
2763 2761 {
2764 2762 dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2765 2763 size_t curlen;
2766 2764 va_list ap;
2767 2765
2768 2766 curlen = strlen(dhx->dhx_buf);
2769 2767
2770 2768 va_start(ap, fmt);
2771 - (void) vsnprintf(dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen, fmt,
2772 - ap);
2769 + (void) dis_vsnprintf(dhx->dhx_buf + curlen, dhx->dhx_buflen -
2770 + curlen, fmt, ap);
2773 2771 va_end(ap);
2774 2772 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX