📄 tc-tic54x.c
字号:
/* .version cpu-version cpu-version may be one of the following: 541 542 543 545 545LP 546LP 548 549 This is for compatibility only. It currently has no affect on assembly. */static int cpu_needs_set = 1;static voidtic54x_version (x) int x ATTRIBUTE_UNUSED;{ enum cpu_version version = VNONE; enum cpu_version old_version = cpu; int c; char *ver; ILLEGAL_WITHIN_STRUCT (); SKIP_WHITESPACE (); ver = input_line_pointer; while (!is_end_of_line[(int) *input_line_pointer]) ++input_line_pointer; c = *input_line_pointer; *input_line_pointer = 0; version = lookup_version (ver); if (cpu != VNONE && cpu != version) as_warn (_("CPU version has already been set")); if (version == VNONE) { as_bad (_("Unrecognized version '%s'"), ver); ignore_rest_of_line (); return; } else if (assembly_begun && version != old_version) { as_bad (_("Changing of CPU version on the fly not supported")); ignore_rest_of_line (); return; } set_cpu (version); *input_line_pointer = c; demand_empty_rest_of_line ();}/* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble. */static voidtic54x_float_cons (int type){ if (current_stag != 0) tic54x_struct_field ('f');#ifdef md_flush_pending_output md_flush_pending_output ();#endif /* Align to long word boundary (4 octets) unless it's ".xfloat". */ if (type != 'x') { frag_align (2, 0, 2); /* If there's a label, assign it to the first allocated word. */ if (line_label != NULL) { symbol_set_frag (line_label, frag_now); S_SET_VALUE (line_label, frag_now_fix ()); } } float_cons ('f');}/* The argument is capitalized if it should be zero-terminated 's' is normal string with upper 8-bits zero-filled, 'p' is packed. Code copied from read.c, and slightly modified so that strings are packed and encoded into the correct octets. */static voidtic54x_stringer (type) int type;{ register unsigned int c; char *start; int append_zero = type == 'S' || type == 'P'; int packed = type == 'p' || type == 'P'; int last_char = -1; /* Packed strings need two bytes at a time to encode. */ if (current_stag != NULL) { tic54x_struct_field ('*'); return; }#ifdef md_flush_pending_output md_flush_pending_output ();#endif c = ','; /* Do loop. */ while (c == ',') { SKIP_WHITESPACE (); switch (*input_line_pointer) { default: { unsigned short value = get_absolute_expression (); FRAG_APPEND_1_CHAR ( value & 0xFF); FRAG_APPEND_1_CHAR ((value >> 8) & 0xFF); break; } case '\"': ++input_line_pointer; /* -> 1st char of string. */ start = input_line_pointer; while (is_a_char (c = next_char_of_string ())) { if (!packed) { FRAG_APPEND_1_CHAR (c); FRAG_APPEND_1_CHAR (0); } else { /* Packed strings are filled MS octet first. */ if (last_char == -1) last_char = c; else { FRAG_APPEND_1_CHAR (c); FRAG_APPEND_1_CHAR (last_char); last_char = -1; } } } if (append_zero) { if (packed && last_char != -1) { FRAG_APPEND_1_CHAR (0); FRAG_APPEND_1_CHAR (last_char); last_char = -1; } else { FRAG_APPEND_1_CHAR (0); FRAG_APPEND_1_CHAR (0); } } know (input_line_pointer[-1] == '\"'); break; } SKIP_WHITESPACE (); c = *input_line_pointer; if (!is_end_of_line[c]) ++input_line_pointer; } /* Finish up any leftover packed string. */ if (packed && last_char != -1) { FRAG_APPEND_1_CHAR (0); FRAG_APPEND_1_CHAR (last_char); } demand_empty_rest_of_line ();}static voidtic54x_p2align (arg) int arg ATTRIBUTE_UNUSED;{ as_bad (_("p2align not supported on this target"));}static voidtic54x_align_words (arg) int arg;{ /* Only ".align" with no argument is allowed within .struct/.union. */ int count = arg; if (!is_end_of_line[(int) *input_line_pointer]) { if (arg == 2) as_warn (_("Argument to .even ignored")); else count = get_absolute_expression (); } if (current_stag != NULL && arg == 128) { if (current_stag->current_bitfield_offset != 0) { current_stag->current_bitfield_offset = 0; ++abs_section_offset; } demand_empty_rest_of_line (); return; } ILLEGAL_WITHIN_STRUCT (); s_align_bytes (count << 1);}/* Initialize multiple-bit fields withing a single word of memory. */static voidtic54x_field (ignore) int ignore ATTRIBUTE_UNUSED;{ expressionS exp; int size = 16; char *p; valueT value; symbolS *label = line_label; if (current_stag != NULL) { tic54x_struct_field ('.'); return; } input_line_pointer = parse_expression (input_line_pointer, &exp); if (*input_line_pointer == ',') { ++input_line_pointer; size = get_absolute_expression (); if (size < 1 || size > 32) { as_bad (_("Invalid field size, must be from 1 to 32")); ignore_rest_of_line (); return; } } /* Truncate values to the field width. */ if (exp.X_op != O_constant) { /* If the expression value is relocatable, the field size *must* be 16. */ if (size != 16) { as_bad (_("field size must be 16 when value is relocatable")); ignore_rest_of_line (); return; } frag_now->tc_frag_data = 0; emit_expr (&exp, 2); } else { unsigned long fmask = (size == 32) ? 0xFFFFFFFF : (1ul << size) - 1; value = exp.X_add_number; exp.X_add_number &= fmask; if (value != (valueT) exp.X_add_number) as_warn (_("field value truncated")); value = exp.X_add_number; /* Bits are stored MS first. */ while (size >= 16) { frag_now->tc_frag_data = 0; p = frag_more (2); md_number_to_chars (p, (value >> (size - 16)) & 0xFFFF, 2); size -= 16; } if (size > 0) { int bit_offset = frag_bit_offset (frag_now, now_seg); fragS *alloc_frag = bit_offset_frag (frag_now, now_seg); if (bit_offset == -1) { struct bit_info *bi = xmalloc (sizeof (struct bit_info)); /* We don't know the previous offset at this time, so store the info we need and figure it out later. */ expressionS size_exp; size_exp.X_op = O_constant; size_exp.X_add_number = size; bi->seg = now_seg; bi->type = TYPE_FIELD; bi->value = value; p = frag_var (rs_machine_dependent, 4, 1, (relax_substateT) 0, make_expr_symbol (&size_exp), (offsetT) 0, (char *) bi); goto getout; } else if (bit_offset == 0 || bit_offset + size > 16) { /* Align a new field. */ p = frag_more (2); frag_now->tc_frag_data = 0; alloc_frag = frag_now; } else { /* Put the new value entirely within the existing one. */ p = alloc_frag == frag_now ? frag_now->fr_literal + frag_now_fix_octets () - 2 : alloc_frag->fr_literal; if (label != NULL) { symbol_set_frag (label, alloc_frag); if (alloc_frag == frag_now) S_SET_VALUE (label, frag_now_fix () - 1); label = NULL; } } value <<= 16 - alloc_frag->tc_frag_data - size; /* OR in existing value. */ if (alloc_frag->tc_frag_data) value |= ((unsigned short) p[1] << 8) | p[0]; md_number_to_chars (p, value, 2); alloc_frag->tc_frag_data += size; if (alloc_frag->tc_frag_data == 16) alloc_frag->tc_frag_data = 0; } } getout: demand_empty_rest_of_line ();}/* Ideally, we want to check SEC_LOAD and SEC_HAS_CONTENTS, but those aren't available yet. seg_info ()->bss is the next best thing. */static inttic54x_initialized_section (seg) segT seg;{ return !seg_info (seg)->bss;}/* .clink ["section name"] Marks the section as conditionally linked (link only if contents are referenced elsewhere. Without a name, refers to the current initialized section. Name is required for uninitialized sections. */static voidtic54x_clink (ignored) int ignored ATTRIBUTE_UNUSED;{ segT seg = now_seg; ILLEGAL_WITHIN_STRUCT (); if (*input_line_pointer == '\"') { char *section_name = ++input_line_pointer; char *name; while (is_a_char (next_char_of_string ())) ; know (input_line_pointer[-1] == '\"'); input_line_pointer[-1] = 0; name = xmalloc (input_line_pointer - section_name + 1); strcpy (name, section_name); seg = bfd_get_section_by_name (stdoutput, name); if (seg == NULL) { as_bad (_("Unrecognized section '%s'"), section_name); ignore_rest_of_line (); return; } } else { if (!tic54x_initialized_section (seg)) { as_bad (_("Current section is unitialized, " "section name required for .clink")); ignore_rest_of_line (); return; } } seg->flags |= SEC_CLINK; demand_empty_rest_of_line ();}/* Change the default include directory to be the current source file's directory, instead of the current working directory. If DOT is non-zero, set to "." instead. */static voidtic54x_set_default_include (dot) int dot;{ char *dir = "."; char *tmp = NULL; if (!dot) { char *curfile; unsigned lineno; as_where (&curfile, &lineno); dir = strcpy (xmalloc (strlen (curfile) + 1), curfile); tmp = strrchr (dir, '/'); } if (tmp != NULL) { int len; *tmp = '\0'; len = strlen (dir); if (include_dir_count == 0) { include_dirs = (char **) xmalloc (sizeof (*include_dirs)); include_dir_count = 1; } include_dirs[0] = dir; if (len > include_dir_maxlen) include_dir_maxlen = len; } else if (include_dirs != NULL) include_dirs[0] = ".";}/* .include "filename" | filename .copy "filename" | filename FIXME 'include' file should be omitted from any output listing, 'copy' should be included in any output listing FIXME -- prevent any included files from changing listing (compat only) FIXME -- need to include source file directory in search path; what's a good way to do this? Entering/exiting included/copied file clears all local labels. */static voidtic54x_include (ignored) int ignored ATTRIBUTE_UNUSED;{ char newblock[] = " .newblock\n"; char *filename; char *input; int len, c = -1; ILLEGAL_WITHIN_STRUCT (); SKIP_WHITESPACE (); if (*input_line_pointer == '"') { filename = demand_copy_C_string (&len); demand_empty_rest_of_line (); } else { filename = input_line_pointer; while (!is_end_of_line[(int) *input_line_pointer]) ++input_line_pointer; c = *input_line_pointer; *input_line_pointer = '\0'; filename = strcpy (xmalloc (strlen (filename) + 1), filename); *input_line_pointer = c; demand_empty_rest_of_line (); } /* Insert a partial line with the filename (for the sake of s_include) and a .newblock. The included file will be inserted before the newblock, so that the newblock is executed after the included file is processed. */ input = xmalloc (sizeof (newblock) + strlen (filename) + 4); sprintf (input, "\"%s\"\n%s", filename, newblock); input_scrub_insert_line (input); tic54x_clear_local_labels (0); tic54x_set_default_include (0); s_include (0);}static voidtic54x_message (type) int type;{ char *msg; char c; int len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -