1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <setjmp.h>
22: #include "as.h"
23: #include "symcat.h"
24: #include "cgen-desc.h"
25: #include "subsegs.h"
26: #include "cgen.h"
27: #include "dwarf2dbg.h"
28:
29: #include "symbols.h"
30: #include "struc-symbol.h"
31:
32: #ifdef OBJ_COMPLEX_RELC
33: static expressionS * make_right_shifted_expr
34: (expressionS *, const int, const int);
35:
36: static unsigned long gas_cgen_encode_addend
37: (const unsigned long, const unsigned long, const unsigned long, \
38: const unsigned long, const unsigned long, const unsigned long, \
39: const unsigned long);
40:
41: static char * weak_operand_overflow_check
42: (const expressionS *, const CGEN_OPERAND *);
43:
44: static void queue_fixup_recursively
45: (const int, const int, expressionS *, \
46: const CGEN_MAYBE_MULTI_IFLD *, const int, const int);
47:
48: static int rightshift = 0;
49: #endif
50: static void queue_fixup (int, int, expressionS *);
51:
52:
53:
54: CGEN_CPU_DESC gas_cgen_cpu_desc;
55:
56:
57:
58:
59:
60: void
61: cgen_asm_record_register (name, number)
62: char *name;
63: int number;
64: {
65:
66:
67: symbol_table_insert (symbol_create (name, reg_section,
68: number, &zero_address_frag));
69: }
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82: struct fixup
83: {
84: int opindex;
85: int opinfo;
86: expressionS exp;
87: struct cgen_maybe_multi_ifield * field;
88: int msb_field_p;
89: };
90:
91: static struct fixup fixups[GAS_CGEN_MAX_FIXUPS];
92: static int num_fixups;
93:
94:
95:
96:
97: void
98: gas_cgen_init_parse ()
99: {
100: num_fixups = 0;
101: }
102:
103:
104:
105: static void
106: queue_fixup (opindex, opinfo, expP)
107: int opindex;
108: int opinfo;
109: expressionS * expP;
110: {
111:
112: if (num_fixups >= GAS_CGEN_MAX_FIXUPS)
113: as_fatal (_("too many fixups"));
114: fixups[num_fixups].exp = *expP;
115: fixups[num_fixups].opindex = opindex;
116: fixups[num_fixups].opinfo = opinfo;
117: ++ num_fixups;
118: }
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154: struct saved_fixups
155: {
156: struct fixup fixup_chain[GAS_CGEN_MAX_FIXUPS];
157: int num_fixups_in_chain;
158: };
159:
160: static struct saved_fixups stored_fixups[MAX_SAVED_FIXUP_CHAINS];
161:
162: void
163: gas_cgen_initialize_saved_fixups_array ()
164: {
165: int i = 0;
166:
167: while (i < MAX_SAVED_FIXUP_CHAINS)
168: stored_fixups[i++].num_fixups_in_chain = 0;
169: }
170:
171: void
172: gas_cgen_save_fixups (i)
173: int i;
174: {
175: if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
176: {
177: as_fatal ("index into stored_fixups[] out of bounds");
178: return;
179: }
180:
181: stored_fixups[i].num_fixups_in_chain = num_fixups;
182: memcpy (stored_fixups[i].fixup_chain, fixups,
183: sizeof (fixups[0]) * num_fixups);
184: num_fixups = 0;
185: }
186:
187: void
188: gas_cgen_restore_fixups (i)
189: int i;
190: {
191: if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
192: {
193: as_fatal ("index into stored_fixups[] out of bounds");
194: return;
195: }
196:
197: num_fixups = stored_fixups[i].num_fixups_in_chain;
198: memcpy (fixups, stored_fixups[i].fixup_chain,
199: (sizeof (stored_fixups[i].fixup_chain[0])) * num_fixups);
200: stored_fixups[i].num_fixups_in_chain = 0;
201: }
202:
203: void
204: gas_cgen_swap_fixups (i)
205: int i;
206: {
207: if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
208: {
209: as_fatal ("index into stored_fixups[] out of bounds");
210: return;
211: }
212:
213: if (num_fixups == 0)
214: gas_cgen_restore_fixups (i);
215:
216: else if (stored_fixups[i].num_fixups_in_chain == 0)
217: gas_cgen_save_fixups (i);
218:
219: else
220: {
221: int tmp;
222: struct fixup tmp_fixup;
223:
224: tmp = stored_fixups[i].num_fixups_in_chain;
225: stored_fixups[i].num_fixups_in_chain = num_fixups;
226: num_fixups = tmp;
227:
228: for (tmp = GAS_CGEN_MAX_FIXUPS; tmp--;)
229: {
230: tmp_fixup = stored_fixups[i].fixup_chain [tmp];
231: stored_fixups[i].fixup_chain[tmp] = fixups [tmp];
232: fixups [tmp] = tmp_fixup;
233: }
234: }
235: }
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250: fixS *
251: gas_cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
252: fragS * frag;
253: int where;
254: const CGEN_INSN * insn;
255: int length;
256: const CGEN_OPERAND * operand;
257: int opinfo;
258: symbolS * symbol;
259: offsetT offset;
260: {
261: fixS *fixP;
262:
263:
264:
265: fixP = fix_new (frag, where, length / 8, symbol, offset,
266: CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
267: (bfd_reloc_code_real_type)
268: ((int) BFD_RELOC_UNUSED
269: + (int) operand->type));
270: fixP->fx_cgen.insn = insn;
271: fixP->fx_cgen.opinfo = opinfo;
272: fixP->fx_cgen.field = NULL;
273: fixP->fx_cgen.msb_field_p = 0;
274:
275: return fixP;
276: }
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291: fixS *
292: gas_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
293: fragS * frag;
294: int where;
295: const CGEN_INSN * insn;
296: int length;
297: const CGEN_OPERAND * operand;
298: int opinfo;
299: expressionS * exp;
300: {
301: fixS *fixP;
302:
303:
304:
305: fixP = fix_new_exp (frag, where, length / 8, exp,
306: CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
307: (bfd_reloc_code_real_type)
308: ((int) BFD_RELOC_UNUSED
309: + (int) operand->type));
310: fixP->fx_cgen.insn = insn;
311: fixP->fx_cgen.opinfo = opinfo;
312: fixP->fx_cgen.field = NULL;
313: fixP->fx_cgen.msb_field_p = 0;
314:
315: return fixP;
316: }
317:
318: #ifdef OBJ_COMPLEX_RELC
319: static symbolS *
320: expr_build_binary (operatorT op, symbolS * s1, symbolS * s2)
321: {
322: expressionS e;
323:
324: e.X_op = op;
325: e.X_add_symbol = s1;
326: e.X_op_symbol = s2;
327: e.X_add_number = 0;
328: return make_expr_symbol (& e);
329: }
330: #endif
331:
332:
333: static jmp_buf expr_jmp_buf;
334: static int expr_jmp_buf_p;
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347: const char *
348: gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
349:
350: #ifdef OBJ_COMPLEX_RELC
351: CGEN_CPU_DESC cd;
352: #else
353: CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
354: #endif
355: enum cgen_parse_operand_type want;
356: const char **strP;
357: int opindex;
358: int opinfo;
359: enum cgen_parse_operand_result *resultP;
360: bfd_vma *valueP;
361: {
362: #ifdef __STDC__
363:
364: char * volatile hold;
365: enum cgen_parse_operand_result * volatile resultP_1;
366: volatile int opinfo_1;
367: #else
368: static char *hold;
369: static enum cgen_parse_operand_result *resultP_1;
370: int opinfo_1;
371: #endif
372: const char *errmsg;
373: expressionS exp;
374:
375: #ifdef OBJ_COMPLEX_RELC
376: volatile int signed_p = 0;
377: symbolS * stmp = NULL;
378: bfd_reloc_code_real_type reloc_type;
379: const CGEN_OPERAND * operand;
380: fixS dummy_fixup;
381: #endif
382: if (want == CGEN_PARSE_OPERAND_INIT)
383: {
384: gas_cgen_init_parse ();
385: return NULL;
386: }
387:
388: resultP_1 = resultP;
389: hold = input_line_pointer;
390: input_line_pointer = (char *) *strP;
391: opinfo_1 = opinfo;
392:
393:
394:
395: if (setjmp (expr_jmp_buf) != 0)
396: {
397: expr_jmp_buf_p = 0;
398: input_line_pointer = (char *) hold;
399: *resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
400: return _("illegal operand");
401: }
402:
403: expr_jmp_buf_p = 1;
404: expression (&exp);
405: expr_jmp_buf_p = 0;
406: errmsg = NULL;
407:
408: *strP = input_line_pointer;
409: input_line_pointer = hold;
410:
411: #ifdef TC_CGEN_PARSE_FIX_EXP
412: opinfo_1 = TC_CGEN_PARSE_FIX_EXP (opinfo_1, & exp);
413: #endif
414:
415:
416:
417: switch (exp.X_op)
418: {
419: case O_illegal:
420: errmsg = _("illegal operand");
421: *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
422: break;
423: case O_absent:
424: errmsg = _("missing operand");
425: *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
426: break;
427: case O_constant:
428: if (want == CGEN_PARSE_OPERAND_SYMBOLIC)
429: goto de_fault;
430: *valueP = exp.X_add_number;
431: *resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
432: break;
433: case O_register:
434: *valueP = exp.X_add_number;
435: *resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
436: break;
437: de_fault:
438: default:
439: #ifdef OBJ_COMPLEX_RELC
440:
441:
442: operand = cgen_operand_lookup_by_num (cd, opindex);
443: errmsg = weak_operand_overflow_check (& exp, operand);
444:
445: if (! errmsg)
446: {
447:
448: memset (& dummy_fixup, 0, sizeof (fixS));
449:
450: reloc_type = md_cgen_lookup_reloc (0, operand, & dummy_fixup);
451:
452: if (exp.X_op == O_symbol
453: && reloc_type == BFD_RELOC_RELC
454: && exp.X_add_symbol->sy_value.X_op == O_constant
455: && exp.X_add_symbol->bsym->section != expr_section
456: && exp.X_add_symbol->bsym->section != absolute_section
457: && exp.X_add_symbol->bsym->section != undefined_section)
458: {
459:
460:
461:
462:
463:
464:
465: stmp = symbol_create (FAKE_LABEL_NAME, expr_section, 0,
466: & zero_address_frag);
467: symbol_set_value_expression (stmp, & exp);
468: }
469: else
470: stmp = make_expr_symbol (& exp);
471:
472:
473:
474: if (reloc_type == BFD_RELOC_RELC
475: && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR))
476: stmp = expr_build_binary (O_subtract, stmp, expr_build_dot ());
477:
478:
479:
480:
481:
482: if (operand && (operand->hw_type == HW_H_SINT))
483: signed_p = 1;
484:
485: if (stmp->bsym && (stmp->bsym->section == expr_section))
486: {
487: if (signed_p)
488: stmp->bsym->flags |= BSF_SRELC;
489: else
490: stmp->bsym->flags |= BSF_RELC;
491: }
492:
493:
494: exp.X_op = O_symbol;
495: exp.X_op_symbol = 0;
496: exp.X_add_symbol = stmp;
497: exp.X_add_number = 0;
498:
499:
500: rightshift = operand->length;
501: queue_fixup_recursively (opindex, opinfo_1, & exp,
502: (reloc_type == BFD_RELOC_RELC) ?
503: & (operand->index_fields) : 0,
504: signed_p, -1);
505: }
506: * resultP = errmsg
507: ? CGEN_PARSE_OPERAND_RESULT_ERROR
508: : CGEN_PARSE_OPERAND_RESULT_QUEUED;
509: *valueP = 0;
510: #else
511: queue_fixup (opindex, opinfo_1, &exp);
512: *valueP = 0;
513: *resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
514: #endif
515: break;
516: }
517:
518: return errmsg;
519: }
520:
521:
522:
523:
524:
525:
526: void
527: gas_cgen_md_operand (expressionP)
528: expressionS *expressionP ATTRIBUTE_UNUSED;
529: {
530:
531: if (expr_jmp_buf_p)
532: longjmp (expr_jmp_buf, 1);
533: }
534:
535:
536:
537:
538:
539:
540:
541:
542: void
543: gas_cgen_finish_insn (insn, buf, length, relax_p, result)
544: const CGEN_INSN *insn;
545: CGEN_INSN_BYTES_PTR buf;
546: unsigned int length;
547: int relax_p;
548: finished_insnS *result;
549: {
550: int i;
551: int relax_operand;
552: char *f;
553: unsigned int byte_len = length / 8;
554:
555:
556:
557:
558:
559:
560:
561:
562:
563:
564:
565:
566:
567: if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
568:
569: abort ();
570:
571:
572:
573: relax_operand = -1;
574: if (relax_p && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE))
575: {
576:
577:
578:
579: for (i = 0; i < num_fixups; ++i)
580: {
581: if (CGEN_OPERAND_ATTR_VALUE (cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex),
582: CGEN_OPERAND_RELAX))
583: {
584: relax_operand = i;
585: break;
586: }
587: }
588: }
589:
590: if (relax_operand != -1)
591: {
592: int max_len;
593: fragS *old_frag;
594: expressionS *exp;
595: symbolS *sym;
596: offsetT off;
597:
598: #ifdef TC_CGEN_MAX_RELAX
599: max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
600: #else
601: max_len = CGEN_MAX_INSN_SIZE;
602: #endif
603:
604:
605: frag_grow (max_len);
606:
607:
608: f = frag_more (byte_len);
609:
610:
611: old_frag = frag_now;
612:
613: exp = &fixups[relax_operand].exp