1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28: #include "sysdep.h"
29: #include <stdio.h>
30: #include "ansidecl.h"
31: #include "dis-asm.h"
32: #include "bfd.h"
33: #include "symcat.h"
34: #include "frv-desc.h"
35: #include "frv-opc.h"
36: #include "opintl.h"
37: #include "safe-ctype.h"
38:
39: #undef min
40: #define min(a,b) ((a) < (b) ? (a) : (b))
41: #undef max
42: #define max(a,b) ((a) > (b) ? (a) : (b))
43:
44:
45: #define FLD(f) (fields->f)
46:
47: static const char * insert_normal
48: (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
49: unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR);
50: static const char * insert_insn_normal
51: (CGEN_CPU_DESC, const CGEN_INSN *,
52: CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
53: static int extract_normal
54: (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
55: unsigned int, unsigned int, unsigned int, unsigned int,
56: unsigned int, unsigned int, bfd_vma, long *);
57: static int extract_insn_normal
58: (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
59: CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
60: #if CGEN_INT_INSN_P
61: static void put_insn_int_value
62: (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
63: #endif
64: #if ! CGEN_INT_INSN_P
65: static CGEN_INLINE void insert_1
66: (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
67: static CGEN_INLINE int fill_cache
68: (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, bfd_vma);
69: static CGEN_INLINE long extract_1
70: (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
71: #endif
72: ^L
73:
74:
75: #if ! CGEN_INT_INSN_P
76:
77:
78:
79: static CGEN_INLINE void
80: insert_1 (CGEN_CPU_DESC cd,
81: unsigned long value,
82: int start,
83: int length,
84: int word_length,
85: unsigned char *bufp)
86: {
87: unsigned long x,mask;
88: int shift;
89:
90: x = cgen_get_insn_value (cd, bufp, word_length);
91:
92:
93: mask = (((1L << (length - 1)) - 1) << 1) | 1;
94: if (CGEN_INSN_LSB0_P)
95: shift = (start + 1) - length;
96: else
97: shift = (word_length - (start + length));
98: x = (x & ~(mask << shift)) | ((value & mask) << shift);
99:
100: cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
101: }
102:
103: #endif
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121: static const char *
122: insert_normal (CGEN_CPU_DESC cd,
123: long value,
124: unsigned int attrs,
125: unsigned int word_offset,
126: unsigned int start,
127: unsigned int length,
128: unsigned int word_length,
129: unsigned int total_length,
130: CGEN_INSN_BYTES_PTR buffer)
131: {
132: static char errbuf[100];
133:
134: unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
135:
136:
137: if (length == 0)
138: return NULL;
139:
140: if (word_length > 32)
141: abort ();
142:
143:
144:
145: if (cd->min_insn_bitsize < cd->base_insn_bitsize)
146: {
147: if (word_offset == 0
148: && word_length > total_length)
149: word_length = total_length;
150: }
151:
152:
153: if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
154: {
155: long minval = - (1L << (length - 1));
156: unsigned long maxval = mask;
157:
158: if ((value > 0 && (unsigned long) value > maxval)
159: || value < minval)
160: {
161:
162: sprintf (errbuf,
163: _("operand out of range (%ld not between %ld and %lu)"),
164: value, minval, maxval);
165: return errbuf;
166: }
167: }
168: else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
169: {
170: unsigned long maxval = mask;
171: unsigned long val = (unsigned long) value;
172:
173:
174:
175:
176:
177: if (sizeof (unsigned long) > 4 && ((value >> 32) == -1))
178: val &= 0xFFFFFFFF;
179:
180: if (val > maxval)
181: {
182:
183: sprintf (errbuf,
184: _("operand out of range (0x%lx not between 0 and 0x%lx)"),
185: val, maxval);
186: return errbuf;
187: }
188: }
189: else
190: {
191: if (! cgen_signed_overflow_ok_p (cd))
192: {
193: long minval = - (1L << (length - 1));
194: long maxval = (1L << (length - 1)) - 1;
195:
196: if (value < minval || value > maxval)
197: {
198: sprintf
199:
200: (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
201: value, minval, maxval);
202: return errbuf;
203: }
204: }
205: }
206:
207: #if CGEN_INT_INSN_P
208:
209: {
210: int shift;
211:
212: if (CGEN_INSN_LSB0_P)
213: shift = (word_offset + start + 1) - length;
214: else
215: shift = total_length - (word_offset + start + length);
216: *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
217: }
218:
219: #else
220:
221: {
222: unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
223:
224: insert_1 (cd, value, start, length, word_length, bufp);
225: }
226:
227: #endif
228:
229: return NULL;
230: }
231:
232:
233:
234:
235:
236:
237:
238:
239: static const char *
240: insert_insn_normal (CGEN_CPU_DESC cd,
241: const CGEN_INSN * insn,
242: CGEN_FIELDS * fields,
243: CGEN_INSN_BYTES_PTR buffer,
244: bfd_vma pc)
245: {
246: const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
247: unsigned long value;
248: const CGEN_SYNTAX_CHAR_TYPE * syn;
249:
250: CGEN_INIT_INSERT (cd);
251: value = CGEN_INSN_BASE_VALUE (insn);
252:
253:
254:
255:
256: #if CGEN_INT_INSN_P
257:
258: put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
259: CGEN_FIELDS_BITSIZE (fields), value);
260:
261: #else
262:
263: cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
264: (unsigned) CGEN_FIELDS_BITSIZE (fields)),
265: value);
266:
267: #endif
268:
269:
270:
271:
272:
273:
274: for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
275: {
276: const char *errmsg;
277:
278: if (CGEN_SYNTAX_CHAR_P (* syn))
279: continue;
280:
281: errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
282: fields, buffer, pc);
283: if (errmsg)
284: return errmsg;
285: }
286:
287: return NULL;
288: }
289:
290: #if CGEN_INT_INSN_P
291:
292:
293:
294: static void
295: put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
296: CGEN_INSN_BYTES_PTR buf,
297: int length,
298: int insn_length,
299: CGEN_INSN_INT value)
300: {
301:
302:
303: if (length > insn_length)
304: *buf = value;
305: else
306: {
307: int shift = insn_length - length;
308:
309: CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
310:
311: *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
312: }
313: }
314: #endif
315: ^L
316:
317:
318: #if ! CGEN_INT_INSN_P
319:
320:
321:
322:
323:
324:
325:
326: static CGEN_INLINE int
327: fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
328: CGEN_EXTRACT_INFO *ex_info,
329: int offset,
330: int bytes,
331: bfd_vma pc)
332: {
333:
334:
335: unsigned int mask;
336: disassemble_info *info = (disassemble_info *) ex_info->dis_info;
337:
338:
339: mask = (1 << bytes) - 1;
340: if (((ex_info->valid >> offset) & mask) == mask)
341: return 1;
342:
343:
344: for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
345: if (! (mask & ex_info->valid))
346: break;
347:
348: if (bytes)
349: {
350: int status;
351:
352: pc += offset;
353: status = (*info->read_memory_func)
354: (pc, ex_info->insn_bytes + offset, bytes, info);
355:
356: if (status != 0)
357: {
358: (*info->memory_error_func) (status, pc, info);
359: return 0;
360: }
361:
362: ex_info->valid |= ((1 << bytes) - 1) << offset;
363: }
364:
365: return 1;
366: }
367:
368:
369:
370: static CGEN_INLINE long
371: extract_1 (CGEN_CPU_DESC cd,
372: CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
373: int start,
374: int length,
375: int word_length,
376: unsigned char *bufp,
377: bfd_vma pc ATTRIBUTE_UNUSED)
378: {
379: unsigned long x;
380: int shift;
381:
382: x = cgen_get_insn_value (cd, bufp, word_length);
383:
384: if (CGEN_INSN_LSB0_P)
385: shift = (start + 1) - length;
386: else
387: shift = (word_length - (start + length));
388: return x >> shift;
389: }
390:
391: #endif
392:
393:
394:
395:
396:
397:
398:
399:
400:
401:
402:
403:
404:
405:
406:
407:
408:
409:
410:
411:
412:
413: static int
414: extract_normal (CGEN_CPU_DESC cd,
415: #if ! CGEN_INT_INSN_P
416: CGEN_EXTRACT_INFO *ex_info,
417: #else
418: CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
419: #endif
420: CGEN_INSN_INT insn_value,
421: unsigned int attrs,
422: unsigned int word_offset,
423: unsigned int start,
424: unsigned int length,
425: unsigned int word_length,
426: unsigned int total_length,
427: #if ! CGEN_INT_INSN_P
428: bfd_vma pc,
429: #else
430: bfd_vma pc ATTRIBUTE_UNUSED,
431: #endif
432: long *valuep)
433: {
434: long value, mask;
435:
436:
437:
438: if (length == 0)
439: {
440: *valuep = 0;
441: return 1;
442: }
443:
444: if (word_length > 32)
445: abort ();
446:
447:
448:
449: if (cd->min_insn_bitsize < cd->base_insn_bitsize)
450: {
451: if (word_offset + word_length > total_length)
452: word_length = total_length - word_offset;
453: }
454:
455:
456:
457: if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
458: {
459: if (CGEN_INSN_LSB0_P)
460: value = insn_value >> ((word_offset + start + 1) - length);
461: else
462: value = insn_value >> (total_length - ( word_offset + start + length));
463: }
464:
465: #if ! CGEN_INT_INSN_P
466:
467: else
468: {
469: unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
470:
471: if (word_length > 32)
472: abort ();
473:
474: if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
475: return 0;
476:
477: value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
478: }
479:
480: #endif
481:
482:
483: mask = (((1L << (length - 1)) - 1) << 1) | 1;
484:
485: value &= mask;
486:
487: if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
488: && (value & (1L << (length - 1))))
489: value |= ~mask;
490:
491: *valuep = value;
492:
493: return 1;
494: }
495:
496:
497:
498:
499:
500:
501:
502:
503:
504:
505: static int
506: extract_insn_normal (CGEN_CPU_DESC cd,
507: const CGEN_INSN *insn,
508: CGEN_EXTRACT_INFO *ex_info,
509: CGEN_INSN_INT insn_value,
510: CGEN_FIELDS *fields,
511: bfd_vma pc)
512: {
513: const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
514: const CGEN_SYNTAX_CHAR_TYPE *syn;
515:
516: CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
517:
518: CGEN_INIT_EXTRACT (cd);
519:
520: for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
521: {
522: int length;
523:
524: if (CGEN_SYNTAX_CHAR_P (*syn))
525: continue;
526:
527: length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
528: ex_info, insn_value, fields, pc);
529: if (length <= 0)
530: return length;
531: }
532:
533:
534: return CGEN_INSN_BITSIZE (insn);
535: }
536: ^L
537:
538:
539: const char * frv_cgen_insert_operand
540: (CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
541:
542:
543:
544:
545:
546:
547:
548:
549:
550:
551:
552:
553:
554:
555:
556: const char *
557: frv_cgen_insert_operand (CGEN_CPU_DESC cd,
558: int opindex,
559: CGEN_FIELDS * fields,
560: CGEN_INSN_BYTES_PTR buffer,
561: bfd_vma pc ATTRIBUTE_UNUSED)
562: {
563: const char * errmsg = NULL;
564: unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
565:
566: switch (opindex)
567: {
568: case FRV_OPERAND_A0 :
569: errmsg = insert_normal (cd, fields->f_A, 0, 0, 17, 1, 32, total_length, buffer);
570: break;
571: case FRV_OPERAND_A1 :
572: errmsg = insert_normal (cd, fields->f_A, 0, 0, 17, 1, 32, total_length, buffer);
573: break;
574: case FRV_OPERAND_ACC40SI :
575: errmsg = insert_normal (c