]>
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; |
199b2450 | 29 | GDB_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 | /****************************************/ | |
ac91d2ca ILT |
41 | |
42 | struct tabent { | |
43 | char *name; | |
44 | char numops; | |
45 | }; | |
46 | ||
dd3b648e RP |
47 | static int /* returns instruction length: 4 or 8 */ |
48 | mem( memaddr, word1, word2, noprint ) | |
49 | unsigned long memaddr; | |
50 | unsigned long word1, word2; | |
51 | int noprint; /* If TRUE, return instruction length, but | |
52 | don't output any text. */ | |
53 | { | |
54 | int i, j; | |
55 | int len; | |
56 | int mode; | |
57 | int offset; | |
b52373a2 | 58 | const char *reg1, *reg2, *reg3; |
dd3b648e RP |
59 | |
60 | /* This lookup table is too sparse to make it worth typing in, but not | |
61 | * so large as to make a sparse array necessary. We allocate the | |
62 | * table at runtime, initialize all entries to empty, and copy the | |
63 | * real ones in from an initialization table. | |
64 | * | |
65 | * NOTE: In this table, the meaning of 'numops' is: | |
66 | * 1: single operand | |
67 | * 2: 2 operands, load instruction | |
68 | * -2: 2 operands, store instruction | |
69 | */ | |
70 | static struct tabent *mem_tab = NULL; | |
8a96d79b | 71 | /* Opcodes of 0x8X, 9X, aX, bX, and cX must be in the table. */ |
dd3b648e | 72 | #define MEM_MIN 0x80 |
8a96d79b JG |
73 | #define MEM_MAX 0xcf |
74 | #define MEM_SIZ ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent)) | |
75 | ||
76 | static struct { int opcode; char *name; char numops; } mem_init[] = { | |
dd3b648e RP |
77 | 0x80, "ldob", 2, |
78 | 0x82, "stob", -2, | |
79 | 0x84, "bx", 1, | |
80 | 0x85, "balx", 2, | |
81 | 0x86, "callx", 1, | |
82 | 0x88, "ldos", 2, | |
83 | 0x8a, "stos", -2, | |
84 | 0x8c, "lda", 2, | |
85 | 0x90, "ld", 2, | |
86 | 0x92, "st", -2, | |
87 | 0x98, "ldl", 2, | |
88 | 0x9a, "stl", -2, | |
89 | 0xa0, "ldt", 2, | |
90 | 0xa2, "stt", -2, | |
91 | 0xb0, "ldq", 2, | |
92 | 0xb2, "stq", -2, | |
93 | 0xc0, "ldib", 2, | |
94 | 0xc2, "stib", -2, | |
95 | 0xc8, "ldis", 2, | |
96 | 0xca, "stis", -2, | |
dd3b648e RP |
97 | 0, NULL, 0 |
98 | }; | |
99 | ||
100 | if ( mem_tab == NULL ){ | |
101 | mem_tab = (struct tabent *) xmalloc( MEM_SIZ ); | |
4ed97c9a | 102 | memset( mem_tab, '\0', MEM_SIZ ); |
dd3b648e RP |
103 | for ( i = 0; mem_init[i].opcode != 0; i++ ){ |
104 | j = mem_init[i].opcode - MEM_MIN; | |
105 | mem_tab[j].name = mem_init[i].name; | |
106 | mem_tab[j].numops = mem_init[i].numops; | |
107 | } | |
108 | } | |
109 | ||
110 | i = ((word1 >> 24) & 0xff) - MEM_MIN; | |
111 | mode = (word1 >> 10) & 0xf; | |
112 | ||
113 | if ( (mem_tab[i].name != NULL) /* Valid instruction */ | |
114 | && ((mode == 5) || (mode >=12)) ){ /* With 32-bit displacement */ | |
115 | len = 8; | |
116 | } else { | |
117 | len = 4; | |
118 | } | |
119 | ||
120 | if ( noprint ){ | |
121 | return len; | |
122 | } | |
720b3aed | 123 | abort (); |
dd3b648e RP |
124 | } |
125 | ||
720b3aed JK |
126 | /* Read the i960 instruction at 'memaddr' and return the address of |
127 | the next instruction after that, or 0 if 'memaddr' is not the | |
128 | address of a valid instruction. The first word of the instruction | |
129 | is stored at 'pword1', and the second word, if any, is stored at | |
130 | 'pword2'. */ | |
dd3b648e | 131 | |
720b3aed JK |
132 | CORE_ADDR |
133 | next_insn (memaddr, pword1, pword2) | |
134 | unsigned long *pword1, *pword2; | |
135 | CORE_ADDR memaddr; | |
dd3b648e | 136 | { |
720b3aed | 137 | int len; |
34df79fc | 138 | char buf[8]; |
dd3b648e | 139 | |
720b3aed JK |
140 | /* Read the two (potential) words of the instruction at once, |
141 | to eliminate the overhead of two calls to read_memory (). | |
34df79fc JK |
142 | FIXME: Loses if the first one is readable but the second is not |
143 | (e.g. last word of the segment). */ | |
dd3b648e | 144 | |
34df79fc JK |
145 | read_memory (memaddr, buf, 8); |
146 | *pword1 = extract_unsigned_integer (buf, 4); | |
147 | *pword2 = extract_unsigned_integer (buf + 4, 4); | |
dd3b648e | 148 | |
720b3aed | 149 | /* Divide instruction set into classes based on high 4 bits of opcode*/ |
dd3b648e | 150 | |
720b3aed JK |
151 | switch ((*pword1 >> 28) & 0xf) |
152 | { | |
153 | case 0x0: | |
154 | case 0x1: /* ctrl */ | |
dd3b648e | 155 | |
720b3aed JK |
156 | case 0x2: |
157 | case 0x3: /* cobr */ | |
dd3b648e | 158 | |
720b3aed JK |
159 | case 0x5: |
160 | case 0x6: | |
161 | case 0x7: /* reg */ | |
162 | len = 4; | |
163 | break; | |
dd3b648e | 164 | |
720b3aed JK |
165 | case 0x8: |
166 | case 0x9: | |
167 | case 0xa: | |
168 | case 0xb: | |
169 | case 0xc: | |
170 | len = mem (memaddr, *pword1, *pword2, 1); | |
171 | break; | |
dd3b648e | 172 | |
720b3aed JK |
173 | default: /* invalid instruction */ |
174 | len = 0; | |
175 | break; | |
176 | } | |
dd3b648e | 177 | |
720b3aed JK |
178 | if (len) |
179 | return memaddr + len; | |
180 | else | |
181 | return 0; | |
dd3b648e | 182 | } |