📄 tc-tic54x.c
字号:
{ /* The blocking flag may be missing. */ ++input_line_pointer; if (*input_line_pointer != ',') block = get_absolute_expression (); else block = 0; if (*input_line_pointer == ',') { ++input_line_pointer; align = get_absolute_expression (); } else align = 0; } else block = align = 0; subseg_set (bss_section, 0); symbolP = symbol_find_or_make (name); if (S_GET_SEGMENT (symbolP) == bss_section) symbolP->sy_frag->fr_symbol = (symbolS *) NULL; symbol_set_frag (symbolP, frag_now); p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) (words << 1), (char *) 0); *p = 0; /* Fill char. */ S_SET_SEGMENT (symbolP, bss_section); /* The symbol may already have been created with a preceding ".globl" directive -- be careful not to step on storage class in that case. Otherwise, set it to static. */ if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) S_SET_STORAGE_CLASS (symbolP, C_STAT); if (align) { /* s_align eats end of line; restore it */ s_align_bytes (4); --input_line_pointer; } if (block) bss_section->flags |= SEC_BLOCK; subseg_set (current_seg, current_subseg); /* Restore current seg. */ demand_empty_rest_of_line ();}static voidstag_add_field_symbols (stag, path, base_offset, rootsym, root_stag_name) struct stag *stag; const char *path; bfd_vma base_offset; symbolS *rootsym; const char *root_stag_name;{ char prefix[strlen (path) + 2]; struct stag_field *field = stag->field; /* Construct a symbol for every field contained within this structure including fields within structure fields. */ strcpy (prefix, path); if (*path) strcat (prefix, "."); while (field != NULL) { int len = strlen (prefix) + strlen (field->name) + 2; char *name = xmalloc (len); strcpy (name, prefix); strcat (name, field->name); if (rootsym == NULL) { symbolS *sym; sym = symbol_new (name, absolute_section, (field->stag ? field->offset : (valueT) (base_offset + field->offset)), &zero_address_frag); SF_SET_LOCAL (sym); symbol_table_insert (sym); } else { char *replacement = xmalloc (strlen (name) + strlen (stag->name) + 2); strcpy (replacement, S_GET_NAME (rootsym)); strcat (replacement, "+"); strcat (replacement, root_stag_name); strcat (replacement, name + strlen (S_GET_NAME (rootsym))); hash_insert (subsym_hash[0], name, replacement); } /* Recurse if the field is a structure. Note the field offset is relative to the outermost struct. */ if (field->stag != NULL) stag_add_field_symbols (field->stag, name, field->offset, rootsym, root_stag_name); field = field->next; }}/* Keep track of stag fields so that when structures are nested we can add the complete dereferencing symbols to the symbol table. */static voidstag_add_field (parent, name, offset, stag) struct stag *parent; const char *name; bfd_vma offset; struct stag *stag;{ struct stag_field *sfield = xmalloc (sizeof (struct stag_field)); memset (sfield, 0, sizeof (*sfield)); sfield->name = strcpy (xmalloc (strlen (name) + 1), name); sfield->offset = offset; sfield->bitfield_offset = parent->current_bitfield_offset; sfield->stag = stag; if (parent->field == NULL) parent->field = sfield; else { struct stag_field *sf = parent->field; while (sf->next != NULL) sf = sf->next; sf->next = sfield; } /* Only create a symbol for this field if the parent has no name. */ if (!strncmp (".fake", parent->name, 5)) { symbolS *sym = symbol_new (name, absolute_section, (valueT) offset, &zero_address_frag); SF_SET_LOCAL (sym); symbol_table_insert (sym); }}/* [STAG] .struct [OFFSET] Start defining structure offsets (symbols in absolute section). */static voidtic54x_struct (int arg){ int start_offset = 0; int is_union = arg; if (!current_stag) { /* Starting a new struct, switch to absolute section. */ stag_saved_seg = now_seg; stag_saved_subseg = now_subseg; subseg_set (absolute_section, 0); } /* Align the current pointer. */ else if (current_stag->current_bitfield_offset != 0) { ++abs_section_offset; current_stag->current_bitfield_offset = 0; } /* Offset expression is only meaningful for global .structs. */ if (!is_union) { /* Offset is ignored in inner structs. */ SKIP_WHITESPACE (); if (!is_end_of_line[(int) *input_line_pointer]) start_offset = get_absolute_expression (); else start_offset = 0; } if (current_stag) { /* Nesting, link to outer one. */ current_stag->inner = (struct stag *) xmalloc (sizeof (struct stag)); memset (current_stag->inner, 0, sizeof (struct stag)); current_stag->inner->outer = current_stag; current_stag = current_stag->inner; if (start_offset) as_warn (_("Offset on nested structures is ignored")); start_offset = abs_section_offset; } else { current_stag = (struct stag *) xmalloc (sizeof (struct stag)); memset (current_stag, 0, sizeof (struct stag)); abs_section_offset = start_offset; } current_stag->is_union = is_union; if (line_label == NULL) { static int struct_count = 0; char fake[] = ".fake_stagNNNNNNN"; sprintf (fake, ".fake_stag%d", struct_count++); current_stag->sym = symbol_new (fake, absolute_section, (valueT) abs_section_offset, &zero_address_frag); } else { char label[strlen (S_GET_NAME (line_label)) + 1]; strcpy (label, S_GET_NAME (line_label)); current_stag->sym = symbol_new (label, absolute_section, (valueT) abs_section_offset, &zero_address_frag); } current_stag->name = S_GET_NAME (current_stag->sym); SF_SET_LOCAL (current_stag->sym); /* Nested .structs don't go into the symbol table. */ if (current_stag->outer == NULL) symbol_table_insert (current_stag->sym); line_label = NULL;}/* [LABEL] .endstruct finish defining structure offsets; optional LABEL's value will be the size of the structure. */static voidtic54x_endstruct (int is_union){ int size; const char *path = !strncmp (current_stag->name, ".fake", 5) ? "" : current_stag->name; if (!current_stag || current_stag->is_union != is_union) { as_bad (_(".end%s without preceding .%s"), is_union ? "union" : "struct", is_union ? "union" : "struct"); ignore_rest_of_line (); return; } /* Align end of structures. */ if (current_stag->current_bitfield_offset) { ++abs_section_offset; current_stag->current_bitfield_offset = 0; } if (current_stag->is_union) size = current_stag->size; else size = abs_section_offset - S_GET_VALUE (current_stag->sym); if (line_label != NULL) { S_SET_VALUE (line_label, size); symbol_table_insert (line_label); line_label = NULL; } /* Union size has already been calculated. */ if (!current_stag->is_union) current_stag->size = size; /* Nested .structs don't get put in the stag table. */ if (current_stag->outer == NULL) { hash_insert (stag_hash, current_stag->name, current_stag); stag_add_field_symbols (current_stag, path, S_GET_VALUE (current_stag->sym), NULL, NULL); } current_stag = current_stag->outer; /* If this is a nested .struct/.union, add it as a field to the enclosing one. otherwise, restore the section we were in. */ if (current_stag != NULL) { stag_add_field (current_stag, current_stag->inner->name, S_GET_VALUE (current_stag->inner->sym), current_stag->inner); } else subseg_set (stag_saved_seg, stag_saved_subseg);}/* [LABEL] .tag STAG Reference a structure within a structure, as a sized field with an optional label. If used outside of a .struct/.endstruct, overlays the given structure format on the existing allocated space. */static voidtic54x_tag (ignore) int ignore ATTRIBUTE_UNUSED;{ char *name = input_line_pointer; int c = get_symbol_end (); struct stag *stag = (struct stag *) hash_find (stag_hash, name); if (!stag) { if (*name) as_bad (_("Unrecognized struct/union tag '%s'"), name); else as_bad (_(".tag requires a structure tag")); ignore_rest_of_line (); return; } if (line_label == NULL) { as_bad (_("Label required for .tag")); ignore_rest_of_line (); return; } else { char label[strlen (S_GET_NAME (line_label)) + 1]; strcpy (label, S_GET_NAME (line_label)); if (current_stag != NULL) stag_add_field (current_stag, label, abs_section_offset - S_GET_VALUE (current_stag->sym), stag); else { symbolS *sym = symbol_find (label); if (!sym) { as_bad (_(".tag target '%s' undefined"), label); ignore_rest_of_line (); return; } stag_add_field_symbols (stag, S_GET_NAME (sym), S_GET_VALUE (stag->sym), sym, stag->name); } } /* Bump by the struct size, but only if we're within a .struct section. */ if (current_stag != NULL && !current_stag->is_union) abs_section_offset += stag->size; *input_line_pointer = c; demand_empty_rest_of_line (); line_label = NULL;}/* Handle all .byte, .char, .double, .field, .float, .half, .int, .long, .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword, and .word. */static voidtic54x_struct_field (int type){ int size; int count = 1; int new_bitfield_offset = 0; int field_align = current_stag->current_bitfield_offset != 0; int longword_align = 0; SKIP_WHITESPACE (); if (!is_end_of_line[(int) *input_line_pointer]) count = get_absolute_expression (); switch (type) { case 'b': case 'B': case 'c': case 'C': case 'h': case 'H': case 'i': case 'I': case 's': case 'S': case 'w': case 'W': case '*': /* String. */ size = 1; break; case 'f': case 'l': case 'L': longword_align = 1; size = 2; break; case '.': /* Bitfield. */ size = 0; if (count < 1 || count > 32) { as_bad (_(".field count '%d' out of range (1 <= X <= 32)"), count); ignore_rest_of_line (); return; } if (current_stag->current_bitfield_offset + count > 16) { /* Set the appropriate size and new field offset. */ if (count == 32) { size = 2; count = 1; } else if (count > 16) { size = 1; count = 1; new_bitfield_offset = count - 16; } else { new_bitfield_offset = count; } } else { field_align = 0; new_bitfield_offset = current_stag->current_bitfield_offset + count; } break; default: as_bad (_("Unrecognized field type '%c'"), type); ignore_rest_of_line (); return; } if (field_align) { /* Align to the actual starting position of the field. */ current_stag->current_bitfield_offset = 0; ++abs_section_offset; } /* Align to longword boundary. */ if (longword_align && (abs_section_offset & 0x1)) ++abs_section_offset; if (line_label == NULL) { static int fieldno = 0; char fake[] = ".fake_fieldNNNNN"; sprintf (fake, ".fake_field%d", fieldno++); stag_add_field (current_stag, fake, abs_section_offset - S_GET_VALUE (current_stag->sym), NULL); } else { char label[strlen (S_GET_NAME (line_label) + 1)]; strcpy (label, S_GET_NAME (line_label)); stag_add_field (current_stag, label, abs_section_offset - S_GET_VALUE (current_stag->sym), NULL); } if (current_stag->is_union) { /* Note we treat the element as if it were an array of COUNT. */ if (current_stag->size < (unsigned) size * count) current_stag->size = size * count; } else { abs_section_offset += (unsigned) size * count; current_stag->current_bitfield_offset = new_bitfield_offset; } line_label = NULL;}/* Handle .byte, .word. .int, .long and all variants. */int emitting_long = 0;static voidtic54x_cons (int type){ register unsigned int c; int octets; /* If we're within a .struct construct, don't actually allocate space. */ if (current_stag != NULL) { tic54x_struct_field (type); return; }#ifdef md_flush_pending_output md_flush_pending_output ();#endif generate_lineno_debug (); /* Align long words to long word boundaries (4 octets). */ if (type == 'l' || type == 'L') { frag_align (2, 0, 2); /* If there's a label, assign it to the first allocated word. */ if (line_label != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -