ld64 with ppc
[darwin-xtools.git] / cctools / otool / sparc_disasm.c
blob0a1e2972fde714c2959d02febc806cc358b403e5
1 /*
2 * Copyright © 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * @APPLE_LICENSE_HEADER_END@
31 #include <stdio.h>
32 #include <string.h>
33 #include <mach-o/loader.h>
34 #include <mach-o/nlist.h>
35 #include <mach-o/reloc.h>
36 #include <mach-o/sparc/reloc.h>
37 #include "stuff/bytesex.h"
38 #include "stuff/symbol.h"
39 #include "otool.h"
40 #include "dyld_bind_info.h"
41 #include "ofile_print.h"
42 #include "../as/sparc-opcode.h"
44 #define DEBUG
47 /* Sign-extend a value which is N bits long. */
48 #define SEX(value, bits) \
49 ((((int)(value)) << ((8 * sizeof (int)) - bits)) \
50 >> ((8 * sizeof (int)) - bits) )
52 static char *reg_names[] =
53 { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
54 "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
55 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
56 "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
57 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
58 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
59 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
60 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
61 "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr"
64 #define freg_names (&reg_names[4 * 8])
66 union sparc_insn
68 uint32_t code;
69 struct
71 #ifdef __BIG_ENDIAN__
72 unsigned int anop:2;
73 unsigned int anrd:5;
74 unsigned int op3:6;
75 unsigned int anrs1:5;
76 unsigned int i:1;
77 unsigned int anasi:8;
78 unsigned int anrs2:5;
79 #endif
80 #ifdef __LITTLE_ENDIAN__
81 unsigned int anrs2:5;
82 unsigned int anasi:8;
83 unsigned int i:1;
84 unsigned int anrs1:5;
85 unsigned int op3:6;
86 unsigned int anrd:5;
87 unsigned int anop:2;
88 #endif
89 } ldst;
90 struct
92 #ifdef __BIG_ENDIAN__
93 unsigned int anop:2;
94 unsigned int anrd:5;
95 unsigned int op3:6;
96 unsigned int anrs1:5;
97 unsigned int i:1;
98 unsigned int IMM13:13;
99 #endif
100 #ifdef __LITTLE_ENDIAN__
101 unsigned int IMM13:13;
102 unsigned int i:1;
103 unsigned int anrs1:5;
104 unsigned int op3:6;
105 unsigned int anrd:5;
106 unsigned int anop:2;
107 #endif
108 } IMM13;
109 struct
111 #ifdef __BIG_ENDIAN__
112 unsigned int anop:2;
113 unsigned int a:1;
114 unsigned int cond:4;
115 unsigned int op2:3;
116 unsigned int DISP22:22;
117 #endif
118 #ifdef __LITTLE_ENDIAN__
119 unsigned int DISP22:22;
120 unsigned int op2:3;
121 unsigned int cond:4;
122 unsigned int a:1;
123 unsigned int anop:2;
124 #endif
125 } branch;
126 struct
128 #ifdef __BIG_ENDIAN__
129 unsigned int anop:2;
130 unsigned int adisp30:30;
131 #endif
132 #ifdef __LITTLE_ENDIAN__
133 unsigned int adisp30:30;
134 unsigned int anop:2;
135 #endif
136 } call;
139 #define op ldst.anop
140 #define rd ldst.anrd
141 #define rs1 ldst.anrs1
142 #define asi ldst.anasi
143 #define rs2 ldst.anrs2
144 #define shcnt rs2
145 #define imm13 IMM13.IMM13
146 #define disp22 branch.DISP22
147 #define imm22 disp22
148 #define disp30 call.adisp30
150 #define SYM_PRINT(a,b,c) print_symbolic((a),(b),(c),relocs, nrelocs, symbols, \
151 nsymbols, sorted_symbols, \
152 nsorted_symbols, strings, \
153 strings_size, verbose)
155 static int opcodes_sorted = 0;
156 extern void qsort();
157 static int compare_opcodes ();
159 #ifdef NOT_USED
160 /* Nonzero if INSN is the opcode for a delayed branch. */
161 static int
162 is_delayed_branch (insn)
163 union sparc_insn insn;
165 unsigned int i;
167 for (i = 0; i < NUMOPCODES; ++i) {
168 struct sparc_opcode *opcode = &sparc_opcodes[i];
170 if ((opcode->match & insn.code) == opcode->match
171 && (opcode->lose & insn.code) == 0)
172 return (opcode->flags & F_DELAYED);
174 return 0;
177 /* find_lo_value attempts to look ahead in the code and find the %lo
178 value corresponding to the current %hi and return its value.
179 The %lo may have been optimized away by the assembler and we don't
180 know how many intermediate instructions there will be between the hi/lo
181 combination. To limit the search, we only look a maximum of 5 insn
182 ahead */
184 #define MAX_LO_LOOKAHEAD 5
187 find_lo_value(
188 char *section,
189 uint32_t addr,
190 union sparc_insn insn)
192 int index, next_insn;
194 index = 0;
195 while (++index < MAX_LO_LOOKAHEAD) {
196 memcpy(&next_insn, section + 4*index, sizeof (unsigned int));
199 #endif /* NOT_USED */
201 void
202 print_address_func(unsigned int addr)
204 printf("0x%x", addr);
207 /* print a label symbol. Modified from print_label in ofile_print.c
208 * Prints the label it found and returns TRUE or prints nothing
209 * and return FALSE
212 enum bool
213 label_symbol(
214 uint32_t addr,
215 enum bool colon_and_newline,
216 struct symbol *sorted_symbols,
217 uint32_t nsorted_symbols)
219 int32_t high, low, mid;
221 low = 0;
222 high = nsorted_symbols - 1;
223 mid = (high - low) / 2;
224 while(high >= low){
225 if(sorted_symbols[mid].n_value == addr){
226 printf("%s", sorted_symbols[mid].name);
227 if(colon_and_newline == TRUE)
228 printf(":\n");
229 return TRUE;
231 if(sorted_symbols[mid].n_value > addr){
232 high = mid - 1;
233 mid = (high + low) / 2;
235 else{
236 low = mid + 1;
237 mid = (high + low) / 2;
240 return FALSE;
243 /* print symbol name for an address and reloc entry.
244 print either symbol found or print the value of the address but print
245 something
247 static void
248 print_symbolic(
249 char operand,
250 uint32_t value,
251 unsigned int pc,
252 struct relocation_info *relocs,
253 uint32_t nrelocs,
254 struct nlist *symbols,
255 uint32_t nsymbols,
256 struct symbol *sorted_symbols,
257 uint32_t nsorted_symbols,
258 char *strings,
259 uint32_t strings_size,
260 enum bool verbose)
262 struct relocation_info *rp, *rp_pair;
263 uint32_t i, r_address, r_symbolnum, r_type, r_extern,
264 r_value, r_scattered, pair_r_type, pair_r_value;
265 int32_t reloc_found, offset;
266 uint32_t other_half;
267 const char *name, *add, *sub;
268 struct scattered_relocation_info *srp;
270 r_symbolnum = 0;
271 r_type = 0;
272 r_extern = 0;
273 r_value = 0;
274 r_scattered = 0;
275 other_half = 0;
276 reloc_found = 0;
277 pair_r_value = 0;
279 /* if verbose output is not requested, don't even attempt lookup */
281 if (!verbose) {
282 printf("0x%x", (unsigned int) value);
283 return;
286 /* Check all reloc entries */
287 if (nrelocs) {
288 for (i=0, rp = relocs; i<nrelocs; i++, rp++) {
289 if (rp->r_address & R_SCATTERED) {
290 srp = (struct scattered_relocation_info *) rp;
291 r_scattered = 1;
292 r_address = srp->r_address;
293 r_extern = 0;
294 r_type = srp->r_type;
295 r_value = srp->r_value;
296 } else {
297 r_scattered = 0;
298 r_address = rp->r_address;
299 r_symbolnum = rp->r_symbolnum;
300 r_extern = rp->r_extern;
301 r_type = rp->r_type;
303 if (r_type == SPARC_RELOC_PAIR) {
304 fprintf(stderr, "Stray SPARC_RELOC_PAIR entry ");
305 continue;
307 if(r_address == pc){
308 if(r_type == SPARC_RELOC_HI22 ||
309 r_type == SPARC_RELOC_LO10 ||
310 r_type == SPARC_RELOC_HI22_SECTDIFF ||
311 r_type == SPARC_RELOC_LO10_SECTDIFF ||
312 r_type == SPARC_RELOC_SECTDIFF){
313 if(i+1 < nrelocs){
314 rp_pair = rp+1;
315 if(rp_pair->r_address & R_SCATTERED){
316 srp = (struct scattered_relocation_info *) rp_pair;
317 other_half = srp->r_address;
318 pair_r_type = srp->r_type;
319 pair_r_value = srp->r_value;
320 } else {
321 other_half = rp_pair->r_address;
322 pair_r_type = rp_pair->r_type;
324 if(pair_r_type != SPARC_RELOC_PAIR){
325 fprintf(stderr, "No SPARC_RELOC_PAIR relocation "
326 "entry after entry %u\n", i);
327 continue;
331 reloc_found = 1;
332 break;
335 if (r_type == SPARC_RELOC_HI22 ||
336 r_type == SPARC_RELOC_LO10 ||
337 r_type == SPARC_RELOC_SECTDIFF ||
338 r_type == SPARC_RELOC_HI22_SECTDIFF ||
339 r_type == SPARC_RELOC_LO10_SECTDIFF)
341 if (i+1 < nrelocs) {
342 rp_pair = (rp + 1);
343 if (rp_pair->r_address & R_SCATTERED) {
344 srp = (struct scattered_relocation_info *) rp_pair;
345 pair_r_type = srp->r_type;
346 } else {
347 pair_r_type = rp_pair->r_type;
349 if (pair_r_type == SPARC_RELOC_PAIR) {
350 i++;
351 rp++;
352 } else {
353 fprintf(stderr,
354 "no SPARC_RELOC_PAIR relocation entry after %u\n", i);
361 /* Now get the reloc information if we located one */
363 if (reloc_found && (r_extern == 1)) {
364 if ((uint32_t)symbols[r_symbolnum].n_un.n_strx >= strings_size)
365 name = "bad string offset";
366 else
367 name = strings + symbols[r_symbolnum].n_un.n_strx;
369 switch (r_type) {
370 case SPARC_RELOC_HI22:
371 value += other_half;
372 printf("%%hi(%s", name);
373 if (value)
374 printf("+0x%x)", (unsigned int) value);
375 else
376 printf(")");
377 break;
378 case SPARC_RELOC_LO10:
379 value |= other_half << 10;
380 printf("%%lo(%s", name);
381 if (value)
382 printf("+0x%x)", (unsigned int) value);
383 else
384 printf(")");
385 break;
386 case SPARC_RELOC_WDISP30:
387 printf("%s", name);
388 if (value)
389 printf("+0x%x", (unsigned int) value);
390 break;
391 case SPARC_RELOC_WDISP22:
392 printf("%s", name);
393 if (value)
394 printf("+0x%x", (unsigned int) value);
395 break;
396 default:
397 printf("%s", name);
399 return;
402 offset = 0;
403 if(reloc_found){
404 if(r_type == SPARC_RELOC_HI22 ||
405 r_type == SPARC_RELOC_HI22_SECTDIFF)
406 value |= other_half;
407 else if(r_type == SPARC_RELOC_LO10 ||
408 r_type == SPARC_RELOC_LO10_SECTDIFF)
409 value |= other_half << 10;
410 if(r_scattered &&
411 (r_type != SPARC_RELOC_HI22_SECTDIFF &&
412 r_type != SPARC_RELOC_LO10_SECTDIFF)){
413 offset = value - r_value;
414 value = r_value;
418 if (reloc_found &&
419 (r_type == SPARC_RELOC_HI22_SECTDIFF ||
420 r_type == SPARC_RELOC_LO10_SECTDIFF)) {
421 if (r_type == SPARC_RELOC_HI22_SECTDIFF)
422 printf("%%hi(");
423 else
424 printf("%%lo(");
425 add = guess_symbol (r_value, sorted_symbols,
426 nsorted_symbols, verbose);
427 sub = guess_symbol (pair_r_value, sorted_symbols,
428 nsorted_symbols, verbose);
429 if (add)
430 printf("%s", add);
431 else
432 printf("0x%x", (unsigned int) r_value);
434 if (sub)
435 printf("-%s", sub);
436 else
437 printf("-0x%x", (unsigned int) pair_r_value);
439 if (offset)
440 printf("+0x%x)", (unsigned int) offset);
441 else
442 printf(")");
443 return;
446 /* no reloc entry, so it's either a symbol or a label */
448 if (operand == 'l' || operand == 'L') {
450 The pc has already been added in the 'l' and 'L' cases by the caller.
451 if ((name = guess_symbol(pc + value, sorted_symbols,
452 nsorted_symbols, verbose)) != NULL)
454 if ((name = guess_symbol(value, sorted_symbols,
455 nsorted_symbols, verbose)) != NULL)
456 printf("%s", name);
457 else
458 printf("0x%x", (unsigned int) value);
459 } else {
460 /* possible symbol reference */
461 name = guess_symbol(value, sorted_symbols, nsorted_symbols, TRUE);
463 switch (r_type) {
464 case SPARC_RELOC_HI22:
466 /* to print the correct value, we really should look ahead for
467 %lo portion of the immediate value and reconstruct it instead
468 of simply printing the already truncated %hi value only */
469 if (name)
470 printf("%%hi(%s)", name);
471 else
472 printf("%%hi(0x%x)", (unsigned int) value);
473 break;
474 case SPARC_RELOC_LO10:
476 /* same here. Look at the last remembered %hi value and add it in */
477 if (name)
478 printf("%%lo(%s)", name);
479 else
480 printf("%%lo(0x%x)", (unsigned int) value);
481 break;
482 default:
483 if (name)
484 printf("%s", name);
485 else
486 printf("0x%x", (unsigned int) value);
491 uint32_t
492 sparc_disassemble(
493 char *sect,
494 uint32_t left,
495 uint32_t addr,
496 uint32_t sect_addr,
497 enum byte_sex object_byte_sex,
498 struct relocation_info *relocs,
499 uint32_t nrelocs,
500 struct nlist *symbols,
501 uint32_t nsymbols,
502 struct symbol *sorted_symbols,
503 uint32_t nsorted_symbols,
504 char *strings,
505 uint32_t strings_size,
506 uint32_t *indirect_symbols,
507 uint32_t nindirect_symbols,
508 struct load_command *load_commands,
509 uint32_t ncmds,
510 uint32_t sizeofcmds,
511 enum bool verbose)
513 enum byte_sex host_byte_sex;
514 enum bool swapped;
515 int i;
516 uint32_t sect_offset;
517 union sparc_insn insn;
518 struct sparc_opcode *opcode;
519 int imm_added_to_rs1 = 0; /* adding or or'ing imm13 into rs1? */
520 int found_plus = 0; /* Found plus sign in args? */
521 int is_annulled = 0; /* We have an annulled branch? */
522 const char *s;
523 static union sparc_insn sethi_insn;
524 const char *indirect_symbol_name;
527 opcode = NULL;
528 if (!opcodes_sorted) {
529 qsort ((char *) sparc_opcodes, NUMOPCODES,
530 sizeof (sparc_opcodes[0]), compare_opcodes);
531 opcodes_sorted = 1;
534 sect_offset = addr - sect_addr;
535 host_byte_sex = get_host_byte_sex();
536 swapped = host_byte_sex != object_byte_sex;
538 if (left < sizeof(uint32_t)) {
539 if(left != 0) {
540 memcpy(&insn, sect, left);
541 if(swapped)
542 insn.code = SWAP_INT(insn.code);
543 printf(".long\t0x%08x\n", (unsigned int)insn.code);
545 printf("(end of section)\n");
546 return(left);
549 memcpy(&insn, sect, sizeof(uint32_t));
550 if (swapped)
551 insn.code = SWAP_INT(insn.code);
553 /* search through the opcode table */
554 for (i=0; i<NUMOPCODES; ++i) {
555 opcode = &sparc_opcodes[i];
556 if ((opcode->match & insn.code) == opcode->match
557 && (opcode->lose & insn.code) == 0) {
558 /* Can't do simple format if source and dest are different. */
559 /* This also takes care of the synthetic 'neg' instruction */
560 if ((insn.rs1 != insn.rd
561 && strchr (opcode->args, 'r') != 0) ||
562 (insn.rs2 != insn.rd &&
563 strchr (opcode->args, 'u'))) {
564 continue;
566 else {
567 break;
572 if (i >= NUMOPCODES) {
573 printf(".long 0x%08x\n", (unsigned int)insn.code);
574 return(4);
577 printf("%s", opcode->name);
579 /* Do we have an `add' or `or' instruction where rs1 is the same
580 as rsd, and which has the i bit set? */
581 /* Check for st instruction as well, as it's commonly used with %lo */
582 if ((opcode->match == 0x80102000 || /* or */
583 opcode->match == 0x80002000 || /* add */
584 opcode->match == 0xd0202000 ) /* st */
585 /* && insn.rs1 == insn.rd */)
586 imm_added_to_rs1 = 1;
588 if (opcode->args[0] != ',')
589 printf("\t");
590 for (s = opcode->args; *s != '\0'; ++s) {
591 while (*s == ',') {
592 printf(",");
593 ++s;
594 switch (*s) {
595 case 'a':
596 printf("a\t");
597 is_annulled = 1;
598 ++s;
599 continue;
600 default:
601 break;
602 } /* switch on arg */
603 } /* while there are comma started args */
605 switch (*s) {
606 case '+':
607 found_plus = 1;
608 /* fall through */
609 default:
610 printf("%c", *s);
611 break;
612 case '#':
613 printf("0");
614 break;
616 #define reg(n) printf("%%%s", reg_names[n])
617 case '1':
618 case 'r':
619 reg (insn.rs1);
620 break;
622 case '2':
623 reg (insn.rs2);
624 break;
626 case 'u':
627 reg (insn.rs2);
628 break;
630 case 'd':
631 reg (insn.rd);
632 break;
633 #undef reg
635 #define freg(n) printf("%%%s", freg_names[n])
636 #define fregx(n) printf("%%%s", reg_names[((n) & ~1) | (((n) & 1) << 5)])
637 case 'e':
638 freg (insn.rs1);
639 break;
640 case 'v': /* double/even */
641 case 'V': /* quad/multiple of 4 */
642 fregx (insn.rs1);
643 break;
645 case 'f':
646 freg (insn.rs2);
647 break;
648 case 'B': /* double/even */
649 case 'R': /* quad/multiple of 4 */
650 fregx (insn.rs2);
651 break;
653 case 'g':
654 freg (insn.rd);
655 break;
656 case 'H': /* double/even */
657 case 'J': /* quad/multiple of 4 */
658 fregx (insn.rd);
659 break;
660 #undef freg
661 #undef fregx
663 #define creg(n) printf("%%c%u", (unsigned int) (n))
664 case 'b':
665 creg (insn.rs1);
666 break;
668 case 'c':
669 creg (insn.rs2);
670 break;
672 case 'D':
673 creg (insn.rd);
674 break;
675 #undef creg
676 case 'h':
677 sethi_insn.code = insn.code; /* for later use */
678 SYM_PRINT(*s ,((int) insn.imm22<<10), sect_offset);
679 break;
680 case 'i':
682 /* We cannot trust the compiler to sign-extend
683 when extracting the bitfield, hence the shifts. */
684 int imm = SEX (insn.imm13, 13);
686 /* Check to see whether we have a 1+i, and take
687 note of that fact.
689 Note: because of the way we sort the table,
690 we will be matching 1+i rather than i+1,
691 so it is OK to assume that i is after +,
692 not before it. */
693 if (found_plus)
694 imm_added_to_rs1 = 1;
696 printf("0x%x", imm);
698 break;
699 case 'M':
700 printf("%%asr%d", insn.rs1);
701 break;
702 case 'm':
703 printf("%%asr%d", insn.rd);
704 break;
705 case 'L':
706 SYM_PRINT(*s,addr + ((insn.disp30 & 0x3fffffff) << 2), sect_offset);
707 if(verbose){
708 indirect_symbol_name = guess_indirect_symbol(
709 addr + ((insn.disp30 & 0x3fffffff) << 2),
710 ncmds, sizeofcmds, load_commands, object_byte_sex, indirect_symbols,
711 nindirect_symbols, symbols, NULL, nsymbols, strings, strings_size);
712 if(indirect_symbol_name != NULL)
713 printf("\t; symbol stub for: %s", indirect_symbol_name);
715 break;
716 case 'n':
717 printf("%#x", (SEX (insn.disp22, 22)));
718 break;
719 case 'l':
720 SYM_PRINT(*s,addr + (SEX(insn.disp22, 22) << 2), sect_offset);
721 break;
722 case 'A':
723 printf("(%d)", (int) insn.asi);
724 break;
725 case 'C':
726 printf("%%csr");
727 break;
728 case 'F':
729 printf("%%fsr");
730 break;
731 case 'p':
732 printf("%%psr");
733 break;
734 case 'q':
735 printf("%%fq");
736 break;
737 case 'Q':
738 printf("%%cq");
739 break;
740 case 't':
741 printf("%%tbr");
742 break;
743 case 'w':
744 printf("%%wim");
745 break;
746 case 'y':
747 printf("%%y");
748 break;
752 /* If we are adding or or'ing something to rs1, then
753 check to see whether the previous instruction was
754 a sethi to the same register as in the sethi.
755 If so, attempt to print the result of the add or
756 or (in this context add and or do the same thing)
757 and its symbolic value. */
758 if (imm_added_to_rs1) {
759 union sparc_insn prev_insn;
761 /* Check if there is a pending sethi instruction. If so, check if
762 the insn uses the same r1 register - that's a good indication
763 this is the %lo we're waiting for. The prolem is that the
764 instruction containg the %lo may have been optimized away by
765 the assembler. There is also no telling how many intermediate
766 instructions the compiler (or human) has put between the
767 sethi and %lo. */
769 if (sethi_insn.code) /* got a pending one */
770 if (insn.rs1 == sethi_insn.rs1) { /* getting closer */
771 /* SYM_PRINT(*s ,((int) insn.imm13), sect_offset); */
772 sethi_insn.code = 0;
776 if ((sect_addr - addr) >= 8) // space before us this?
777 memcpy(&prev_insn, sect - 4, sizeof(uint32_t));
778 else
779 prev_insn.code = 0;
781 /* If it is a delayed branch, we need to look at the
782 instruction before the delayed branch. This handles
783 sequences such as
785 sethi %o1, %hi(_foo), %o1
786 call _printf
787 or %o1, %lo(_foo), %o1
790 if (prev_insn.code /* && is_delayed_branch (prev_insn) */)
791 memcpy(&prev_insn, sect - 8, sizeof(uint32_t));
792 else
793 prev_insn.code = 0;
795 /* Is it sethi to the same register? */
796 if ((prev_insn.code & 0xc1c00000) == 0x01000000
797 && prev_insn.rd == insn.rs1) {
798 printf("\t! ");
799 print_address_func(
800 (0xFFFFFFFF & (int) prev_insn.imm22 << 10)
801 | SEX (insn.imm13, 13));
804 printf("\n");
805 return (4);
808 /* Compare opcodes A and B. */
810 static int
811 compare_opcodes (a, b)
812 char *a, *b;
814 struct sparc_opcode *op0 = (struct sparc_opcode *) a;
815 struct sparc_opcode *op1 = (struct sparc_opcode *) b;
816 uint32_t match0 = op0->match, match1 = op1->match;
817 uint32_t lose0 = op0->lose, lose1 = op1->lose;
818 register unsigned int i;
820 /* If a bit is set in both match and lose, there is something
821 wrong with the opcode table. */
822 if (match0 & lose0)
824 fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8x, %#.8x\n",
825 op0->name, match0, lose0);
826 op0->lose &= ~op0->match;
827 lose0 = op0->lose;
830 if (match1 & lose1)
832 fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8x, %#.8x\n",
833 op1->name, match1, lose1);
834 op1->lose &= ~op1->match;
835 lose1 = op1->lose;
838 /* Because the bits that are variable in one opcode are constant in
839 another, it is important to order the opcodes in the right order. */
840 for (i = 0; i < 32; ++i)
842 uint32_t x = 1 << i;
843 int x0 = (match0 & x) != 0;
844 int x1 = (match1 & x) != 0;
846 if (x0 != x1)
847 return x1 - x0;
850 for (i = 0; i < 32; ++i)
852 uint32_t x = 1 << i;
853 int x0 = (lose0 & x) != 0;
854 int x1 = (lose1 & x) != 0;
856 if (x0 != x1)
857 return x1 - x0;
860 /* They are functionally equal. So as long as the opcode table is
861 valid, we can put whichever one first we want, on aesthetic grounds. */
863 /* Our first aesthetic ground is that aliases defer to real insns. */
865 int alias_diff = (op0->flags & F_ALIAS) - (op1->flags & F_ALIAS);
866 if (alias_diff != 0)
867 /* Put the one that isn't an alias first. */
868 return alias_diff;
871 /* Except for aliases, two "identical" instructions had
872 better have the same opcode. This is a sanity check on the table. */
873 i = strcmp (op0->name, op1->name);
874 if (i){
875 if (op0->flags & F_ALIAS) /* If they're both aliases, be arbitrary. */
876 return i;
877 else
878 fprintf (stderr,
879 "Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n",
880 op0->name, op1->name);
883 /* Fewer arguments are preferred. */
885 int length_diff = strlen (op0->args) - strlen (op1->args);
886 if (length_diff != 0)
887 /* Put the one with fewer arguments first. */
888 return length_diff;
891 /* Put 1+i before i+1. */
893 char *p0 = (char *) strchr(op0->args, '+');
894 char *p1 = (char *) strchr(op1->args, '+');
896 if (p0 && p1)
898 /* There is a plus in both operands. Note that a plus
899 sign cannot be the first character in args,
900 so the following [-1]'s are valid. */
901 if (p0[-1] == 'i' && p1[1] == 'i')
902 /* op0 is i+1 and op1 is 1+i, so op1 goes first. */
903 return 1;
904 if (p0[1] == 'i' && p1[-1] == 'i')
905 /* op0 is 1+i and op1 is i+1, so op0 goes first. */
906 return -1;
910 /* They are, as far as we can tell, identical.
911 Since qsort may have rearranged the table partially, there is
912 no way to tell which one was first in the opcode table as
913 written, so just say there are equal. */
914 return 0;