📄 mmix.c
字号:
} if (string < string_end) { fprintf (stream, "#%x", *string & 255); string++; if (string < string_end) fprintf (stream, ","); } }}/* ASM_OUTPUT_SOURCE_LINE. */voidmmix_asm_output_source_line (stream, lineno) FILE * stream; int lineno;{ fprintf (stream, "# %d ", lineno); OUTPUT_QUOTED_STRING (stream, main_input_filename); fprintf (stream, "\n");}/* Target hook for assembling integer objects. Use mmix_print_operand for WYDE and TETRA. Use mmix_output_octa to output 8-byte CONST_DOUBLEs. */static boolmmix_assemble_integer (x, size, aligned_p) rtx x; unsigned int size; int aligned_p;{ if (aligned_p) switch (size) { /* We handle a limited number of types of operands in here. But that's ok, because we can punt to generic functions. We then pretend that aligned data isn't needed, so the usual .<pseudo> syntax is used (which works for aligned data too). We actually *must* do that, since we say we don't have simple aligned pseudos, causing this function to be called. We just try and keep as much compatibility as possible with mmixal syntax for normal cases (i.e. without GNU extensions and C only). */ case 1: if (GET_CODE (x) != CONST_INT) { aligned_p = 0; break; } fputs ("\tBYTE\t", asm_out_file); mmix_print_operand (asm_out_file, x, 'B'); fputc ('\n', asm_out_file); return true; case 2: if (GET_CODE (x) != CONST_INT) { aligned_p = 0; break; } fputs ("\tWYDE\t", asm_out_file); mmix_print_operand (asm_out_file, x, 'W'); fputc ('\n', asm_out_file); return true; case 4: if (GET_CODE (x) != CONST_INT) { aligned_p = 0; break; } fputs ("\tTETRA\t", asm_out_file); mmix_print_operand (asm_out_file, x, 'L'); fputc ('\n', asm_out_file); return true; case 8: if (GET_CODE (x) == CONST_DOUBLE) /* We don't get here anymore for CONST_DOUBLE, because DImode isn't expressed as CONST_DOUBLE, and DFmode is handled elsewhere. */ abort (); assemble_integer_with_op ("\tOCTA\t", x); return true; } return default_assemble_integer (x, size, aligned_p);}/* ASM_OUTPUT_ASCII. */voidmmix_asm_output_ascii (stream, string, length) FILE *stream; const char *string; int length;{ while (length > 0) { int chunk_size = length > 60 ? 60 : length; fprintf (stream, "\tBYTE "); mmix_output_quoted_string (stream, string, chunk_size); string += chunk_size; length -= chunk_size; fprintf (stream, "\n"); }}/* ASM_OUTPUT_ALIGNED_COMMON. */voidmmix_asm_output_aligned_common (stream, name, size, align) FILE *stream; const char *name; int size; int align;{ /* This is mostly the elfos.h one. There doesn't seem to be a way to express this in a mmixal-compatible way. */ fprintf (stream, "\t.comm\t"); assemble_name (stream, name); fprintf (stream, ",%u,%u ! mmixal-incompatible COMMON\n", size, align / BITS_PER_UNIT);}/* ASM_OUTPUT_ALIGNED_LOCAL. */voidmmix_asm_output_aligned_local (stream, name, size, align) FILE * stream; const char * name; int size; int align;{ data_section (); ASM_OUTPUT_ALIGN (stream, exact_log2 (align/BITS_PER_UNIT)); assemble_name (stream, name); fprintf (stream, "\tLOC @+%d\n", size);}/* ASM_OUTPUT_LABEL. */voidmmix_asm_output_label (stream, name) FILE *stream; const char * name;{ assemble_name (stream, name); fprintf (stream, "\tIS @\n");}/* ASM_DECLARE_REGISTER_GLOBAL. */voidmmix_asm_declare_register_global (stream, decl, regno, name) FILE *stream ATTRIBUTE_UNUSED; tree decl ATTRIBUTE_UNUSED; int regno ATTRIBUTE_UNUSED; const char *name ATTRIBUTE_UNUSED;{ /* Nothing to do here, but there *will* be, therefore the framework is here. */}/* ASM_WEAKEN_LABEL. */voidmmix_asm_weaken_label (stream, name) FILE * stream ATTRIBUTE_UNUSED; const char * name ATTRIBUTE_UNUSED;{ fprintf (stream, "\t.weak "); assemble_name (stream, name); fprintf (stream, " ! mmixal-incompatible\n");}/* MAKE_DECL_ONE_ONLY. */voidmmix_make_decl_one_only (decl) tree decl;{ DECL_WEAK (decl) = 1;}/* ASM_OUTPUT_LABELREF. Strip GCC's '*' and our own '@'. No order is assumed. */voidmmix_asm_output_labelref (stream, name) FILE *stream; const char *name;{ int is_extern = 1; for (; (*name == '@' || *name == '*'); name++) if (*name == '@') is_extern = 0; asm_fprintf (stream, "%s%U%s", is_extern && TARGET_TOPLEVEL_SYMBOLS ? ":" : "", name);}/* ASM_OUTPUT_INTERNAL_LABEL. */voidmmix_asm_output_internal_label (stream, name, num) FILE * stream; const char * name; int num;{ fprintf (stream, "%s:%d\tIS @\n", name, num);}/* ASM_OUTPUT_DEF. */voidmmix_asm_output_def (stream, name, value) FILE * stream; const char * name; const char * value;{ assemble_name (stream, name); fprintf (stream, "\tIS "); assemble_name (stream, value); fputc ('\n', stream);}/* PRINT_OPERAND. */voidmmix_print_operand (stream, x, code) FILE * stream; rtx x; int code;{ /* When we add support for different codes later, we can, when needed, drop through to the main handler with a modified operand. */ rtx modified_x = x; int regno = x != NULL_RTX && REG_P (x) ? REGNO (x) : 0; switch (code) { /* Unrelated codes are in alphabetic order. */ case '+': /* For conditional branches, output "P" for a probable branch. */ if (TARGET_BRANCH_PREDICT) { x = find_reg_note (current_output_insn, REG_BR_PROB, 0); if (x && INTVAL (XEXP (x, 0)) > REG_BR_PROB_BASE / 2) putc ('P', stream); } return; case '.': /* For the %d in POP %d,0. */ fprintf (stream, "%d", MMIX_POP_ARGUMENT ()); return; case 'B': if (GET_CODE (x) != CONST_INT) fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x); fprintf (stream, "%d", (int) (INTVAL (x) & 0xff)); return; case 'H': /* Highpart. Must be general register, and not the last one, as that one cannot be part of a consecutive register pair. */ if (regno > MMIX_LAST_GENERAL_REGISTER - 1) internal_error ("MMIX Internal: Bad register: %d", regno); /* This is big-endian, so the high-part is the first one. */ fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]); return; case 'L': /* Lowpart. Must be CONST_INT or general register, and not the last one, as that one cannot be part of a consecutive register pair. */ if (GET_CODE (x) == CONST_INT) { fprintf (stream, "#%lx", (unsigned long) (INTVAL (x) & ((unsigned int) 0x7fffffff * 2 + 1))); return; } if (GET_CODE (x) == SYMBOL_REF) { output_addr_const (stream, x); return; } if (regno > MMIX_LAST_GENERAL_REGISTER - 1) internal_error ("MMIX Internal: Bad register: %d", regno); /* This is big-endian, so the low-part is + 1. */ fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno) + 1]); return; /* Can't use 'a' because that's a generic modifier for address output. */ case 'A': mmix_output_shiftvalue_op_from_str (stream, "ANDN", ~(unsigned HOST_WIDEST_INT) mmix_intval (x)); return; case 'i': mmix_output_shiftvalue_op_from_str (stream, "INC", (unsigned HOST_WIDEST_INT) mmix_intval (x)); return; case 'o': mmix_output_shiftvalue_op_from_str (stream, "OR", (unsigned HOST_WIDEST_INT) mmix_intval (x)); return; case 's': mmix_output_shiftvalue_op_from_str (stream, "SET", (unsigned HOST_WIDEST_INT) mmix_intval (x)); return; case 'd': case 'D': mmix_output_condition (stream, x, (code == 'D')); return; case 'e': /* Output an extra "e" to make fcmpe, fune. */ if (TARGET_FCMP_EPSILON) fprintf (stream, "e"); return; case 'm': /* Output the number minus 1. */ if (GET_CODE (x) != CONST_INT) { fatal_insn ("MMIX Internal: Bad value for 'm', not a CONST_INT", x); } fprintf (stream, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) (mmix_intval (x) - 1)); return; case 'p': /* Store the number of registers we want to save. This was setup by the prologue. The actual operand contains the number of registers to pass, but we don't use it currently. Anyway, we need to output the number of saved registers here. */ fprintf (stream, "%d", cfun->machine->highest_saved_stack_register + 1); return; case 'r': /* Store the register to output a constant to. */ if (! REG_P (x)) fatal_insn ("MMIX Internal: Expected a register, not this", x); mmix_output_destination_register = MMIX_OUTPUT_REGNO (regno); return; case 'I': /* Output the constant. Note that we use this for floats as well. */ if (GET_CODE (x) != CONST_INT && (GET_CODE (x) != CONST_DOUBLE || (GET_MODE (x) != VOIDmode && GET_MODE (x) != DFmode && GET_MODE (x) != SFmode))) fatal_insn ("MMIX Internal: Expected a constant, not this", x); mmix_output_register_setting (stream, mmix_output_destination_register, mmix_intval (x), 0); return; case 'U': /* An U for unsigned, if TARGET_ZERO_EXTEND. Ignore the operand. */ if (TARGET_ZERO_EXTEND) putc ('U', stream); return; case 'v': mmix_output_shifted_value (stream, (HOST_WIDEST_INT) mmix_intval (x)); return; case 'V': mmix_output_shifted_value (stream, (HOST_WIDEST_INT) ~mmix_intval (x)); return; case 'W': if (GET_CODE (x) != CONST_INT) fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x); fprintf (stream, "#%x", (int) (INTVAL (x) & 0xffff)); return; case 0: /* Nothing to do. */ break; default: /* Presumably there's a missing case above if we get here. */ internal_error ("MMIX Internal: Missing `%c' case in mmix_print_operand", code); } switch (GET_CODE (modified_x)) { case REG: regno = REGNO (modified_x); if (regno >= FIRST_PSEUDO_REGISTER) internal_error ("MMIX Internal: Bad register: %d", regno); fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]); return; case MEM: output_address (XEXP (modified_x, 0)); return; case CONST_INT: /* For -2147483648, mmixal complains that the constant does not fit in 4 bytes, so let's output it as hex. Take care to handle hosts where HOST_WIDE_INT is longer than an int. Print small constants +-255 using decimal. */ if (INTVAL (modified_x) > -256 && INTVAL (modified_x) < 256) fprintf (stream, "%d", (int) (INTVAL (modified_x))); else fprintf (stream, "#%x", (int) (INTVAL (modified_x)) & (unsigned int) ~0); return; case CONST_DOUBLE: /* Do somewhat as CONST_INT. */ mmix_output_octa (stream, mmix_intval (modified_x), 0); return; case CONST: output_addr_const (stream, modified_x); return; default: /* No need to test for all strange things. Let output_addr_const do it for us. */ if (CONSTANT_P (modified_x) /* Strangely enough, this is not included in CONSTANT_P. FIXME: Ask/check about sanity here. */ || GET_CODE (modified_x) == CODE_LABEL) { output_addr_const (stream, modified_x); return; } /* We need the original here. */ fatal_insn ("MMIX Internal: Cannot decode this operand", x); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -