]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/z8k-dis.c
* configure.in: Add ncr* configuration.
[thirdparty/binutils-gdb.git] / opcodes / z8k-dis.c
1 #include <stdio.h>
2 #define DEFINE_TABLE
3 #include "z8k-opc.h"
4
5 static void fetch_data();
6 static void fetch_instr();
7 static unsigned long get_val();
8 static int is_segmented();
9 static int lookup_instr();
10 static void output_instr();
11 static void unpack_instr();
12 static void unparse_instr();
13
14 typedef struct {
15 unsigned char instr_buf[24];
16 unsigned long bytes_fetched;
17 unsigned long tabl_index;
18 char instr_asmsrc[80];
19 unsigned long arg_reg[0x0f];
20 unsigned long immediate;
21 unsigned long displacement;
22 unsigned long address;
23 unsigned long cond_code;
24 unsigned long ctrl_code;
25 unsigned long flags;
26 unsigned long interrupts;
27 } instr_data_s;
28
29
30 static char *codes[16] =
31 {
32 "f",
33 "lt",
34 "le",
35 "ule",
36 "ov/pe",
37 "mi",
38 "eq",
39 "c/ult",
40 "t",
41 "ge",
42 "gt",
43 "ugt",
44 "nov/po",
45 "pl",
46 "ne",
47 "nc/uge"
48 };
49
50
51 int print_insn_z8k(addr, in_buf, stream)
52 unsigned long addr;
53 unsigned char *in_buf;
54 FILE *stream;
55 {
56 instr_data_s instr_data;
57
58 fetch_instr( &in_buf, &instr_data );
59 if ( lookup_instr( &instr_data ))
60 {
61 fetch_data( &in_buf, &instr_data );
62 unpack_instr( &instr_data );
63 unparse_instr( &instr_data );
64 output_instr( &instr_data, addr, stream );
65 return instr_data.bytes_fetched;
66 }
67 else {
68 fprintf(stream,".word %02x%02x", in_buf[0], in_buf[1]);
69 return 2;
70 }
71
72 }
73
74
75 static void fetch_data( in_buf, instr_data )
76 unsigned char **in_buf;
77 instr_data_s *instr_data;
78 {
79 int bytes_2fetch;
80
81 bytes_2fetch = z8k_table[instr_data->tabl_index].length -
82 instr_data->bytes_fetched;
83 while( bytes_2fetch-- )
84 instr_data->instr_buf[instr_data->bytes_fetched++] = *(*in_buf)++;
85 }
86
87 static void fetch_instr( in_buf, instr_data )
88 unsigned char **in_buf;
89 instr_data_s *instr_data;
90 {
91 unsigned int loop = 2;
92
93 instr_data->bytes_fetched = 0;
94 while( loop-- )
95 instr_data->instr_buf[instr_data->bytes_fetched++] = *(*in_buf)++;
96
97 }
98
99 static unsigned long get_val( instr_buf, start_nibl, nibls_long )
100 unsigned char (*instr_buf)[];
101 unsigned int start_nibl, nibls_long;
102 {
103 unsigned long ret_val;
104 unsigned char byte_val, nibl_val;
105 unsigned int nibl_index, nibl_lim;
106 unsigned int byte_index;
107 unsigned int which_nibl;
108
109 ret_val = 0;
110 nibl_lim = start_nibl + nibls_long;
111 for( nibl_index = start_nibl; nibl_index < nibl_lim; nibl_index++ )
112 {
113 byte_index = nibl_index / 2;
114 which_nibl = nibl_index % 2;
115 switch( which_nibl )
116 {
117 case 0:
118 byte_val = (*instr_buf)[byte_index];
119 nibl_val = (byte_val >> 4) & 0x0f;
120 break;
121 case 1:
122 nibl_val = byte_val & 0x0f;
123 break;
124 }
125 ret_val = (ret_val << 4) | nibl_val;
126 }
127
128 return ret_val;
129
130 }
131
132 static int is_segmented()
133 {
134 return 1;
135 }
136
137 static
138 int lookup_instr( instr_data )
139 instr_data_s *instr_data;
140 {
141
142 int nibl_index, tabl_index;
143 int tablent_found, nibl_matched;
144 unsigned short instr_nibl;
145 unsigned short tabl_datum, datum_class, datum_value;
146
147 nibl_matched = 0;
148 tabl_index = 0;
149 while( ! nibl_matched && z8k_table[tabl_index].name)
150 {
151 nibl_matched = 1;
152 for( nibl_index = 0; nibl_index < 4 && nibl_matched; nibl_index++ )
153 {
154 instr_nibl = get_val( instr_data->instr_buf, nibl_index, 1 );
155
156 tabl_datum = z8k_table[tabl_index].byte_info[nibl_index];
157 datum_class = tabl_datum & CLASS_MASK;
158 datum_value = ~CLASS_MASK & tabl_datum;
159
160 switch( datum_class )
161 {
162 case CLASS_BIT:
163 if( datum_value != instr_nibl ) nibl_matched = 0;
164 break;
165 case CLASS_00II:
166 if( ! ((~instr_nibl) & 0x4) ) nibl_matched = 0;
167 break;
168 case CLASS_01II:
169 if( ! (instr_nibl & 0x4) ) nibl_matched = 0;
170 break;
171 case CLASS_0CCC:
172 if( ! ((~instr_nibl) & 0x8) ) nibl_matched = 0;
173 break;
174 case CLASS_1CCC:
175 if( ! (instr_nibl & 0x8) ) nibl_matched = 0;
176 break;
177 case CLASS_0DISP7:
178 if( ! ((~instr_nibl) & 0x8) ) nibl_matched = 0;
179 nibl_index += 1;
180 break;
181 case CLASS_1DISP7:
182 if( ! (instr_nibl & 0x8) ) nibl_matched = 0;
183 nibl_index += 1;
184 break;
185 case CLASS_REGN0:
186 if( instr_nibl == 0 ) nibl_matched = 0;
187 break;
188 default:
189 break;
190 }
191 }
192 tabl_index++;
193 }
194
195
196 instr_data->tabl_index = tabl_index;
197
198 return nibl_matched;
199
200 }
201
202 static void output_instr( instr_data, addr, stream )
203 instr_data_s *instr_data;
204 unsigned long addr;
205 FILE *stream;
206 {
207 int loop, loop_limit;
208 unsigned long word_val;
209 char tmp_str[20];
210 char out_str[100];
211
212 strcpy( out_str, "" );
213
214 loop_limit = z8k_table[instr_data->tabl_index].length / 2;
215 for( loop = 0; loop < loop_limit; loop++ )
216 {
217 word_val = get_val( instr_data->instr_buf, loop * 4, 4 );
218 sprintf( tmp_str, "%04x ", word_val );
219 strcat( out_str, tmp_str );
220 }
221
222 while( loop++ < 5 )
223 {
224 strcat( out_str, " " );
225 }
226
227 strcat( out_str, instr_data->instr_asmsrc );
228
229 fprintf( stream, "%s", out_str );
230 }
231
232 static void unpack_instr( instr_data )
233 instr_data_s *instr_data;
234 {
235 int nibl_index, word_index;
236 int nibl_count, loop;
237 unsigned short instr_nibl, instr_byte, instr_word, instr_long;
238 unsigned short tabl_datum, datum_class, datum_value;
239
240 nibl_count = 0;
241 loop = 0;
242 while( z8k_table[instr_data->tabl_index].byte_info[loop] != 0 )
243 {
244 word_index = (int) nibl_count / 4;
245 nibl_index = (int) nibl_count % 4;
246
247 switch( nibl_index )
248 {
249 case 0:
250 instr_nibl = get_val( instr_data->instr_buf, nibl_count, 1 );
251 instr_byte = get_val( instr_data->instr_buf, nibl_count, 2 );
252 instr_word = get_val( instr_data->instr_buf, nibl_count, 4 );
253 instr_long = get_val( instr_data->instr_buf, nibl_count, 8 );
254 break;
255 case 1:
256 instr_nibl = get_val( instr_data->instr_buf, nibl_count, 1 );
257 break;
258 case 2:
259 instr_nibl = get_val( instr_data->instr_buf, nibl_count, 1 );
260 instr_byte = get_val( instr_data->instr_buf, nibl_count, 2 );
261 break;
262 case 3:
263 instr_nibl = get_val( instr_data->instr_buf, nibl_count, 1 );
264 break;
265 default:
266 break;
267 }
268
269 tabl_datum = z8k_table[instr_data->tabl_index].byte_info[loop];
270 datum_class = tabl_datum & CLASS_MASK;
271 datum_value = tabl_datum & ~CLASS_MASK;
272
273 switch( datum_class )
274 {
275 case CLASS_X:
276 instr_data->address = instr_nibl;
277 break;
278 case CLASS_BA:
279 instr_data->displacement = instr_nibl;
280 break;
281 case CLASS_BX:
282 instr_data->arg_reg[datum_value] = instr_nibl;
283 break;
284 case CLASS_DISP:
285 switch( datum_value )
286 {
287 case ARG_DISP16:
288 instr_data->displacement = instr_word;
289 nibl_count += 3;
290 break;
291 case ARG_DISP12:
292 instr_data->displacement = instr_word & 0x0fff;
293 nibl_count += 2;
294 break;
295 default:
296 break;
297 }
298 break;
299 case CLASS_IMM:
300 switch( datum_value )
301 {
302 case ARG_IMM4:
303 instr_data->immediate = instr_nibl;
304 break;
305 case ARG_IMM8:
306 instr_data->immediate = instr_byte;
307 nibl_count += 1;
308 break;
309 case ARG_IMM16:
310 instr_data->immediate = instr_word;
311 nibl_count += 3;
312 break;
313 case ARG_IMM32:
314 instr_data->immediate = instr_long;
315 nibl_count += 7;
316 break;
317 case ARG_IMMN:
318 instr_data->immediate = instr_nibl -1;
319 break;
320 /* ????? */
321 /* missing ARG_IMMNMINUS1 */
322 case ARG_IMM_1:
323 instr_data->immediate = 1;
324 break;
325 case ARG_IMM_2:
326 instr_data->immediate = 2;
327 break;
328 case ARG_NIM16:
329 instr_data->immediate = (- instr_word);
330 nibl_count += 3;
331 break;
332 case ARG_IMM2:
333 instr_data->immediate = instr_nibl & 0x3;
334 break;
335 default:
336 break;
337 }
338 break;
339 case CLASS_CC:
340 instr_data->cond_code = instr_nibl;
341 break;
342 case CLASS_CTRL:
343 instr_data->ctrl_code = instr_nibl;
344 break;
345 case CLASS_DA:
346 case CLASS_ADDRESS:
347 if( is_segmented() )
348 {
349 if( instr_nibl & 0x8 )
350 {
351 instr_data->address = ((instr_word & 0x7f00) << 8) +
352 (instr_long & 0xffff);
353 nibl_count += 7;
354 }
355 else
356 {
357 instr_data->address = ((instr_word & 0x7f00) << 8) +
358 (instr_word & 0x00ff);
359 nibl_count += 3;
360 }
361 }
362 else
363 {
364 instr_data->address = instr_word;
365 nibl_count += 3;
366 }
367 break;
368 case CLASS_0CCC:
369 instr_data->cond_code = instr_nibl & 0x7;
370 break;
371 case CLASS_1CCC:
372 instr_data->cond_code = instr_nibl & 0x7;
373 break;
374 case CLASS_0DISP7:
375 instr_data->displacement = instr_byte & 0x7f;
376 nibl_count += 1;
377 break;
378 case CLASS_1DISP7:
379 instr_data->displacement = instr_byte & 0x7f;
380 nibl_count += 1;
381 break;
382 case CLASS_01II:
383 instr_data->interrupts = instr_nibl & 0x3;
384 break;
385 case CLASS_00II:
386 instr_data->interrupts = instr_nibl & 0x3;
387 break;
388 case CLASS_BIT:
389 /* do nothing */
390 break;
391 case CLASS_IR:
392 instr_data->arg_reg[datum_value] = instr_nibl;
393 break;
394 case CLASS_FLAGS:
395 instr_data->flags = instr_nibl;
396 break;
397 case CLASS_REG:
398 instr_data->arg_reg[datum_value] = instr_nibl;
399 break;
400 case CLASS_REG_BYTE:
401 instr_data->arg_reg[datum_value] = instr_nibl;
402 break;
403 case CLASS_REG_WORD:
404 instr_data->arg_reg[datum_value] = instr_nibl;
405 break;
406 case CLASS_REG_QUAD:
407 instr_data->arg_reg[datum_value] = instr_nibl;
408 break;
409 case CLASS_REG_LONG:
410 instr_data->arg_reg[datum_value] = instr_nibl;
411 break;
412 case CLASS_REGN0:
413 instr_data->arg_reg[datum_value] = instr_nibl;
414 break;
415 default:
416 break;
417 }
418
419 loop += 1;
420 nibl_count += 1;
421 }
422 }
423
424 static void unparse_instr( instr_data )
425 instr_data_s *instr_data;
426 {
427 unsigned short tabl_datum, datum_class, datum_value;
428 int loop, loop_limit;
429 char out_str[80], tmp_str[25];
430
431 sprintf( out_str, "\t%-10s", z8k_table[instr_data->tabl_index].name );
432
433 loop_limit = z8k_table[instr_data->tabl_index].noperands;
434 for( loop = 0; loop < loop_limit; loop++ )
435 {
436 if( loop )
437 strcat( out_str, "," );
438
439 tabl_datum = z8k_table[instr_data->tabl_index].arg_info[loop];
440 datum_class = tabl_datum & CLASS_MASK;
441 datum_value = tabl_datum & ~CLASS_MASK;
442
443 switch( datum_class )
444 {
445 case CLASS_X:
446 sprintf( tmp_str, "0x%0x(R%d)", instr_data->address,
447 instr_data->arg_reg[datum_value] );
448 strcat( out_str, tmp_str );
449 break;
450 case CLASS_BA:
451 sprintf( tmp_str, "r%d(#%x)", instr_data->arg_reg[datum_value],
452 instr_data->displacement);
453 strcat( out_str, tmp_str );
454 break;
455 case CLASS_BX:
456 sprintf( tmp_str, "r%d(R%d)", instr_data->arg_reg[datum_value],
457 instr_data->arg_reg[ARG_RX] );
458 strcat( out_str, tmp_str );
459 break;
460 case CLASS_DISP:
461 sprintf( tmp_str, "#0x%0x", instr_data->displacement );
462 strcat( out_str, tmp_str );
463 break;
464 case CLASS_IMM:
465 sprintf( tmp_str, "#0x%0x", instr_data->immediate );
466 strcat( out_str, tmp_str );
467 break;
468 case CLASS_CC:
469 sprintf( tmp_str, "%s", codes[instr_data->cond_code] );
470 strcat( out_str, tmp_str );
471 break;
472 case CLASS_CTRL:
473 sprintf( tmp_str, "0x%0x", instr_data->ctrl_code );
474 strcat( out_str, tmp_str );
475 break;
476 case CLASS_DA:
477 case CLASS_ADDRESS:
478 sprintf( tmp_str, "#0x%0x", instr_data->address );
479 strcat( out_str, tmp_str );
480 break;
481 case CLASS_IR:
482 sprintf( tmp_str, "@R%d", instr_data->arg_reg[datum_value] );
483 strcat( out_str, tmp_str );
484 break;
485 case CLASS_FLAGS:
486 sprintf( tmp_str, "0x%0x", instr_data->flags );
487 strcat( out_str, tmp_str );
488 break;
489 case CLASS_REG_BYTE:
490 if( instr_data->arg_reg[datum_value] >= 0x8 )
491 {
492 sprintf( tmp_str, "rl%d",
493 instr_data->arg_reg[datum_value] - 0x8 );
494 }
495 else
496 {
497 sprintf( tmp_str, "rh%d", instr_data->arg_reg[datum_value] );
498 }
499 strcat( out_str, tmp_str );
500 break;
501 case CLASS_REG_WORD:
502 sprintf( tmp_str, "r%d", instr_data->arg_reg[datum_value] );
503 strcat( out_str, tmp_str );
504 break;
505 case CLASS_REG_QUAD:
506 sprintf( tmp_str, "rq%d", instr_data->arg_reg[datum_value] );
507 strcat( out_str, tmp_str );
508 break;
509 case CLASS_REG_LONG:
510 sprintf( tmp_str, "rr%d", instr_data->arg_reg[datum_value] );
511 strcat( out_str, tmp_str );
512 break;
513 default:
514 break;
515 }
516 }
517
518 strcpy( instr_data->instr_asmsrc, out_str );
519 }