Commit | Line | Data |
---|---|---|
609756e2 | 1 | /* i80960 instruction disassembler for GDB. |
609f87d4 | 2 | Copyright 1990, 1991, 1992 Free Software Foundation, Inc. |
609756e2 JG |
3 | |
4 | This file is part of GDB. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
dd3b648e | 19 | |
dd3b648e | 20 | #include "defs.h" |
720b3aed | 21 | #include "dis-asm.h" |
dd3b648e | 22 | |
720b3aed JK |
23 | /* Print the instruction at address MEMADDR in debugged memory, |
24 | on STREAM. Returns length of the instruction, in bytes. */ | |
dd3b648e | 25 | |
dd3b648e | 26 | int |
720b3aed | 27 | print_insn (memaddr, stream) |
dd3b648e | 28 | CORE_ADDR memaddr; |
720b3aed | 29 | FILE *stream; |
dd3b648e | 30 | { |
720b3aed | 31 | disassemble_info info; |
dd3b648e | 32 | |
720b3aed | 33 | GDB_INIT_DISASSEMBLE_INFO(info, stream); |
dd3b648e | 34 | |
720b3aed | 35 | return print_insn_i960 (memaddr, &info); |
dd3b648e RP |
36 | } |
37 | ||
38 | /****************************************/ | |
39 | /* MEM format */ | |
40 | /****************************************/ | |
41 | static int /* returns instruction length: 4 or 8 */ | |
42 | mem( memaddr, word1, word2, noprint ) | |
43 | unsigned long memaddr; | |
44 | unsigned long word1, word2; | |
45 | int noprint; /* If TRUE, return instruction length, but | |
46 | don't output any text. */ | |
47 | { | |
48 | int i, j; | |
49 | int len; | |
50 | int mode; | |
51 | int offset; | |
b52373a2 | 52 | const char *reg1, *reg2, *reg3; |
dd3b648e RP |
53 | |
54 | /* This lookup table is too sparse to make it worth typing in, but not | |
55 | * so large as to make a sparse array necessary. We allocate the | |
56 | * table at runtime, initialize all entries to empty, and copy the | |
57 | * real ones in from an initialization table. | |
58 | * | |
59 | * NOTE: In this table, the meaning of 'numops' is: | |
60 | * 1: single operand | |
61 | * 2: 2 operands, load instruction | |
62 | * -2: 2 operands, store instruction | |
63 | */ | |
64 | static struct tabent *mem_tab = NULL; | |
8a96d79b | 65 | /* Opcodes of 0x8X, 9X, aX, bX, and cX must be in the table. */ |
dd3b648e | 66 | #define MEM_MIN 0x80 |
8a96d79b JG |
67 | #define MEM_MAX 0xcf |
68 | #define MEM_SIZ ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent)) | |
69 | ||
70 | static struct { int opcode; char *name; char numops; } mem_init[] = { | |
dd3b648e RP |
71 | 0x80, "ldob", 2, |
72 | 0x82, "stob", -2, | |
73 | 0x84, "bx", 1, | |
74 | 0x85, "balx", 2, | |
75 | 0x86, "callx", 1, | |
76 | 0x88, "ldos", 2, | |
77 | 0x8a, "stos", -2, | |
78 | 0x8c, "lda", 2, | |
79 | 0x90, "ld", 2, | |
80 | 0x92, "st", -2, | |
81 | 0x98, "ldl", 2, | |
82 | 0x9a, "stl", -2, | |
83 | 0xa0, "ldt", 2, | |
84 | 0xa2, "stt", -2, | |
85 | 0xb0, "ldq", 2, | |
86 | 0xb2, "stq", -2, | |
87 | 0xc0, "ldib", 2, | |
88 | 0xc2, "stib", -2, | |
89 | 0xc8, "ldis", 2, | |
90 | 0xca, "stis", -2, | |
dd3b648e RP |
91 | 0, NULL, 0 |
92 | }; | |
93 | ||
94 | if ( mem_tab == NULL ){ | |
95 | mem_tab = (struct tabent *) xmalloc( MEM_SIZ ); | |
96 | bzero( mem_tab, MEM_SIZ ); | |
97 | for ( i = 0; mem_init[i].opcode != 0; i++ ){ | |
98 | j = mem_init[i].opcode - MEM_MIN; | |
99 | mem_tab[j].name = mem_init[i].name; | |
100 | mem_tab[j].numops = mem_init[i].numops; | |
101 | } | |
102 | } | |
103 | ||
104 | i = ((word1 >> 24) & 0xff) - MEM_MIN; | |
105 | mode = (word1 >> 10) & 0xf; | |
106 | ||
107 | if ( (mem_tab[i].name != NULL) /* Valid instruction */ | |
108 | && ((mode == 5) || (mode >=12)) ){ /* With 32-bit displacement */ | |
109 | len = 8; | |
110 | } else { | |
111 | len = 4; | |
112 | } | |
113 | ||
114 | if ( noprint ){ | |
115 | return len; | |
116 | } | |
720b3aed | 117 | abort (); |
dd3b648e RP |
118 | } |
119 | ||
720b3aed JK |
120 | /* Read the i960 instruction at 'memaddr' and return the address of |
121 | the next instruction after that, or 0 if 'memaddr' is not the | |
122 | address of a valid instruction. The first word of the instruction | |
123 | is stored at 'pword1', and the second word, if any, is stored at | |
124 | 'pword2'. */ | |
dd3b648e | 125 | |
720b3aed JK |
126 | CORE_ADDR |
127 | next_insn (memaddr, pword1, pword2) | |
128 | unsigned long *pword1, *pword2; | |
129 | CORE_ADDR memaddr; | |
dd3b648e | 130 | { |
720b3aed JK |
131 | int len; |
132 | unsigned long buf[2]; | |
dd3b648e | 133 | |
720b3aed JK |
134 | /* Read the two (potential) words of the instruction at once, |
135 | to eliminate the overhead of two calls to read_memory (). | |
136 | TODO: read more instructions at once and cache them. */ | |
dd3b648e | 137 | |
720b3aed JK |
138 | read_memory (memaddr, buf, sizeof (buf)); |
139 | *pword1 = buf[0]; | |
140 | SWAP_TARGET_AND_HOST (pword1, sizeof (long)); | |
141 | *pword2 = buf[1]; | |
142 | SWAP_TARGET_AND_HOST (pword2, sizeof (long)); | |
dd3b648e | 143 | |
720b3aed | 144 | /* Divide instruction set into classes based on high 4 bits of opcode*/ |
dd3b648e | 145 | |
720b3aed JK |
146 | switch ((*pword1 >> 28) & 0xf) |
147 | { | |
148 | case 0x0: | |
149 | case 0x1: /* ctrl */ | |
dd3b648e | 150 | |
720b3aed JK |
151 | case 0x2: |
152 | case 0x3: /* cobr */ | |
dd3b648e | 153 | |
720b3aed JK |
154 | case 0x5: |
155 | case 0x6: | |
156 | case 0x7: /* reg */ | |
157 | len = 4; | |
158 | break; | |
dd3b648e | 159 | |
720b3aed JK |
160 | case 0x8: |
161 | case 0x9: | |
162 | case 0xa: | |
163 | case 0xb: | |
164 | case 0xc: | |
165 | len = mem (memaddr, *pword1, *pword2, 1); | |
166 | break; | |
dd3b648e | 167 | |
720b3aed JK |
168 | default: /* invalid instruction */ |
169 | len = 0; | |
170 | break; | |
171 | } | |
dd3b648e | 172 | |
720b3aed JK |
173 | if (len) |
174 | return memaddr + len; | |
175 | else | |
176 | return 0; | |
dd3b648e | 177 | } |