From 82489ea062091d79ce205dd59150f15b06d453eb Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Thu, 2 Jun 1994 16:35:41 +0000 Subject: [PATCH] 68060 support --- gas/config/tc-m68k.c | 448 +++++++++++++++++++++++++------------------ gas/configure.in | 2 +- 2 files changed, 264 insertions(+), 186 deletions(-) diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index 0e9ddbe3c76..75f1736c0d2 100644 --- a/gas/config/tc-m68k.c +++ b/gas/config/tc-m68k.c @@ -74,6 +74,12 @@ const int md_reloc_size = 8; /* Size of relocation record */ references. */ int flag_want_pic; +#ifdef REGISTER_PREFIX_OPTIONAL +int flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL; +#else +int flag_reg_prefix_optional; +#endif + /* Its an arbitrary name: This means I don't approve of it */ /* See flames below */ static struct obstack robyn; @@ -187,13 +193,25 @@ struct m68k_exp short e_siz; /* 0== default 1==short/byte 2==word 3==long */ }; -/* DATA and ADDR have to be contiguous, so that reg-DATA gives 0-7==data reg, - 8-15==addr reg for operands that take both types */ +/* DATA and ADDR have to be contiguous, so that reg-DATA gives + 0-7==data reg, 8-15==addr reg for operands that take both types. + + We don't use forms like "ADDR0 = ADDR" here because this file is + likely to be used on an Apollo, and the broken Apollo compiler + gives an `undefined variable' error if we do that, according to + troy@cbme.unsw.edu.au. */ + +#define DATA DATA0 +#define ADDR ADDR0 +#define SP ADDR7 +#define FPREG FP0 +#define COPNUM COP0 +#define BAD BAD0 +#define BAC BAC0 enum _register { - DATA = 1, /* 1- 8 == data registers 0-7 */ - DATA0 = DATA, + DATA0 = 1, /* 1- 8 == data registers 0-7 */ DATA1, DATA2, DATA3, @@ -202,8 +220,7 @@ enum _register DATA6, DATA7, - ADDR, - ADDR0 = ADDR, + ADDR0, ADDR1, ADDR2, ADDR3, @@ -212,13 +229,10 @@ enum _register ADDR6, ADDR7, - /* Note that COPNUM==processor #1 -- COPNUM+7==#8, which stores as 000 */ + /* Note that COP0==processor #1 -- COP0+7==#8, which stores as 000 */ /* I think. . . */ - SP = ADDR7, - - FPREG, /* Eight FP registers */ - FP0 = FPREG, + FP0, /* Eight FP registers */ FP1, FP2, FP3, @@ -226,8 +240,8 @@ enum _register FP5, FP6, FP7, - COPNUM = (FPREG + 8), /* Co-processor #1-#8 */ - COP0 = COPNUM, + + COP0, /* Co-processor #1-#8 */ COP1, COP2, COP3, @@ -235,12 +249,13 @@ enum _register COP5, COP6, COP7, + PC, /* Program counter */ ZPC, /* Hack for Program space, but 0 addressing */ SR, /* Status Reg */ CCR, /* Condition code Reg */ - /* These have to be in order for the movec instruction to work. */ + /* These have to be grouped together for the movec instruction to work. */ USP, /* User Stack Pointer */ ISP, /* Interrupt stack pointer */ SFC, @@ -257,6 +272,9 @@ enum _register TC, SRP, URP, + BUSCR, /* 68060 added these */ + PCR, +#define last_movec_reg PCR /* end of movec ordering constraints */ FPI, @@ -269,8 +287,7 @@ enum _register VAL, SCC, AC, - BAD, - BAD0 = BAD, + BAD0, BAD1, BAD2, BAD3, @@ -278,8 +295,7 @@ enum _register BAD5, BAD6, BAD7, - BAC, - BAC0 = BAC, + BAC0, BAC1, BAC2, BAC3, @@ -300,6 +316,28 @@ enum _register TT1, }; +static const enum _register m68000_control_regs[] = { 0 }; +static const enum _register m68010_control_regs[] = { + SFC, DFC, USP, VBR, + 0 +}; +static const enum _register m68020_control_regs[] = { + SFC, DFC, USP, VBR, CACR, CAAR, MSP, ISP, + 0 +}; +static const enum _register m68040_control_regs[] = { + SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1, + USP, VBR, MSP, ISP, MMUSR, URP, SRP, + 0 +}; +static const enum _register m68060_control_regs[] = { + SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1, BUSCR, + USP, VBR, URP, SRP, PCR, + 0 +}; + +static const enum _register *control_regs; + /* Internal form of an operand. */ struct m68k_op { @@ -597,15 +635,19 @@ m68k_reg_parse (ccp) char *p; symbolS *symbolP; -#ifdef REGISTER_PREFIX - if (*start != REGISTER_PREFIX) - return FAIL; - p = start + 1; -#else - p = start; - if (*p == OPTIONAL_REGISTER_PREFIX) - p++, start++; -#endif + if (flag_reg_prefix_optional) + { + if (*start == REGISTER_PREFIX) + start++; + p = start; + } + else + { + if (*start != REGISTER_PREFIX) + return FAIL; + p = start + 1; + } + if (!isalpha (*p) || !is_name_beginner (*p)) return FAIL; @@ -846,7 +888,7 @@ m68k_ip_op (str, opP) ; --strend; - if (*str == '#') + if (*str == '#' || *str == '&') { str++; opP->con1 = add_exp (str, strend); @@ -1002,9 +1044,8 @@ m68k_ip_op (str, opP) { /* "(EXPR,..." , a displacement */ char *stmp; - char *index (); - if ((stmp = index (str, ',')) != NULL) + if ((stmp = strchr (str, ',')) != NULL) { opP->con1 = add_exp (str, stmp - 1); str = stmp; @@ -1097,8 +1138,7 @@ m68k_ip_op (str, opP) { /* "EXP2" or "EXP2(REG..." */ char *stmp; - char *index (); - if ((stmp = index (str, '(')) != NULL) + if ((stmp = strchr (str, '(')) != NULL) { char *ostr = str; @@ -1397,10 +1437,47 @@ m68k_ip_op (str, opP) #if defined (M68KCOFF) && !defined (BFD_ASSEMBLER) +#ifdef NO_PCREL_RELOCS + +int +make_pcrel_absolute(fixP, add_number) + fixS *fixP; + long *add_number; +{ + register unsigned char *opcode = fixP->fx_frag->fr_opcode; + + /* rewrite the PC relative instructions to absolute address ones. + * these are rumoured to be faster, and the apollo linker refuses + * to deal with the PC relative relocations. + */ + if (opcode[0] == 0x60 && opcode[1] == 0xff) /* BRA -> JMP */ + { + opcode[0] = 0x4e; + opcode[1] = 0xf9; + } + else if (opcode[0] == 0x61 && opcode[1] == 0xff) /* BSR -> JSR */ + { + opcode[0] = 0x4e; + opcode[1] = 0xb9; + } + else + as_fatal ("Unknown PC relative instruction"); + *add_number -= 4; + return 0; +} + +#endif /* NO_PCREL_RELOCS */ + short tc_coff_fix2rtype (fixP) fixS *fixP; { +#ifdef NO_PCREL_RELOCS + know (fixP->fx_pcrel == 0); + return (fixP->fx_size == 1 ? R_RELBYTE + : fixP->fx_size == 2 ? R_DIR16 + : R_DIR32); +#else return (fixP->fx_pcrel ? (fixP->fx_size == 1 ? R_PCRBYTE : fixP->fx_size == 2 ? R_PCRWORD : @@ -1408,8 +1485,7 @@ tc_coff_fix2rtype (fixP) (fixP->fx_size == 1 ? R_RELBYTE : fixP->fx_size == 2 ? R_RELWORD : R_RELLONG)); - - +#endif } #endif @@ -1823,27 +1899,17 @@ m68k_ip (instring) case 'J': if (opP->mode != MSCR || opP->reg < USP - || opP->reg > URP - || cpu_of_arch (current_architecture) < m68010 /* before 68010 had none */ - || (cpu_of_arch (current_architecture) < m68020 - && opP->reg != SFC - && opP->reg != DFC - && opP->reg != USP - && opP->reg != VBR) /* 68010's had only these */ - || (cpu_of_arch (current_architecture) < m68040 - && opP->reg != SFC - && opP->reg != DFC - && opP->reg != USP - && opP->reg != VBR - && opP->reg != CACR - && opP->reg != CAAR - && opP->reg != MSP - && opP->reg != ISP) /* 680[23]0's have only these */ - || (cpu_of_arch (current_architecture) == m68040 /* 68040 has all but this */ - && opP->reg == CAAR)) + || opP->reg > last_movec_reg) + losing++; + else { - losing++; - } /* doesn't cut it */ + enum _register *rp; + for (rp = control_regs; *rp; rp++) + if (*rp == opP->reg) + break; + if (*rp == 0) + losing++; + } break; case 'k': @@ -2042,7 +2108,7 @@ m68k_ip (instring) switch (ok_arch) { case mfloat: - strcpy (cp, "fpu (68040 or 68881/68882)"); + strcpy (cp, "fpu (68040, 68060 or 68881/68882)"); break; case mmmu: strcpy (cp, "mmu (68030 or 68851)"); @@ -2071,6 +2137,7 @@ m68k_ip (instring) { m68020, "68020" }, { m68030, "68030" }, { m68040, "68040" }, + { m68060, "68060" }, { cpu32, "cpu32" }, { m68881, "68881" }, { m68851, "68851" } @@ -2195,7 +2262,7 @@ m68k_ip (instring) /* Can other cases happen here? */ if (op (opP->con1) != O_constant) abort (); - + val = (valueT) offs (opP->con1); gencnt = 0; do @@ -2267,6 +2334,7 @@ m68k_ip (instring) if (opP->reg == PC) { addword (0x0170); + opP->con1->e_exp.X_add_number += 6; add_fix ('l', opP->con1, 1); addword (0), addword (0); break; @@ -2292,6 +2360,7 @@ m68k_ip (instring) { if (opP->reg == PC) { + opP->con1->e_exp.X_add_number += 2; add_fix ('w', opP->con1, 1); } else @@ -3376,24 +3445,25 @@ insert_reg (regname, regnum) { char buf[100]; int i; -symbolS *s; #ifdef REGISTER_PREFIX - buf[0] = REGISTER_PREFIX; - strcpy (buf + 1, regname); - regname = buf; + if (!flag_reg_prefix_optional) + { + buf[0] = REGISTER_PREFIX; + strcpy (buf + 1, regname); + regname = buf; + } #endif - symbol_table_insert (s = symbol_new (regname, reg_section, regnum, &zero_address_frag)); - -verify_symbol_chain_2 (s); + symbol_table_insert (symbol_new (regname, reg_section, regnum, + &zero_address_frag)); for (i = 0; regname[i]; i++) buf[i] = islower (regname[i]) ? toupper (regname[i]) : regname[i]; buf[i] = '\0'; - symbol_table_insert (s = symbol_new (buf, reg_section, regnum, &zero_address_frag)); -verify_symbol_chain_2 (s); + symbol_table_insert (symbol_new (buf, reg_section, regnum, + &zero_address_frag)); } struct init_entry @@ -3538,83 +3608,6 @@ md_assemble (str) int m, n = 0; char *to_beg_P; int shorts_this_frag; - static int done_first_time; - - if (!done_first_time) - { - done_first_time = 1; - - if (cpu_of_arch (current_architecture) == 0) - { - int cpu_type; - - if (strcmp (TARGET_CPU, "m68000") == 0 - || strcmp (TARGET_CPU, "m68302") == 0) - cpu_type = m68000; - else if (strcmp (TARGET_CPU, "m68010") == 0) - cpu_type = m68010; - else if (strcmp (TARGET_CPU, "m68020") == 0 - || strcmp (TARGET_CPU, "m68k") == 0) - cpu_type = m68020; - else if (strcmp (TARGET_CPU, "m68030") == 0) - cpu_type = m68030; - else if (strcmp (TARGET_CPU, "m68040") == 0) - cpu_type = m68040; - else if (strcmp (TARGET_CPU, "cpu32") == 0 - || strcmp (TARGET_CPU, "m68331") == 0 - || strcmp (TARGET_CPU, "m68332") == 0 - || strcmp (TARGET_CPU, "m68333") == 0 - || strcmp (TARGET_CPU, "m68340") == 0) - cpu_type = cpu32; - else - cpu_type = m68020; - - current_architecture |= cpu_type; - } -#if 0 /* Could be doing emulation. */ - if (current_architecture & m68881) - { - if (current_architecture & m68000) - as_bad ("incompatible processors 68000 and 68881/2 specified"); - if (current_architecture & m68010) - as_bad ("incompatible processors 68010 and 68881/2 specified"); - if (current_architecture & m68040) - as_bad ("incompatible processors 68040 and 68881/2 specified"); - } -#endif - /* What other incompatibilities could we check for? */ - - /* Toss in some default assumptions about coprocessors. */ - if (!no_68881 - && (cpu_of_arch (current_architecture) - /* Can CPU32 have a 68881 coprocessor?? */ - & (m68020 | m68030 | cpu32))) - { - current_architecture |= m68881; - } - if (!no_68851 - && (cpu_of_arch (current_architecture) & m68020up) != 0 - && cpu_of_arch (current_architecture) != m68040) - { - current_architecture |= m68851; - } - if (no_68881 && (current_architecture & m68881)) - as_bad ("options for 68881 and no-68881 both given"); - if (no_68851 && (current_architecture & m68851)) - as_bad ("options for 68851 and no-68851 both given"); - -#ifdef OBJ_AOUT - /* Work out the magic number. This isn't very general. */ - if (current_architecture & m68000) - m68k_aout_machtype = 0; - else if (current_architecture & m68010) - m68k_aout_machtype = 1; - else if (current_architecture & m68020) - m68k_aout_machtype = 2; - else - m68k_aout_machtype = 2; -#endif - } memset ((char *) (&the_ins), '\0', sizeof (the_ins)); m68k_ip (str); @@ -3791,8 +3784,7 @@ md_begin () register unsigned int i; register char c; - if ((op_hash = hash_new ()) == NULL) - as_fatal ("Virtual memory exhausted"); + op_hash = hash_new (); obstack_begin (&robyn, 4000); for (i = 0; i < numopcodes; i++) @@ -3822,7 +3814,6 @@ md_begin () while (slak); retval = hash_insert (op_hash, ins->name, (char *) hack); - /* Didn't his mommy tell him about null pointers? */ if (retval) as_bad ("Internal Error: Can't hash %s: %s", ins->name, retval); } @@ -3848,9 +3839,6 @@ md_begin () #ifdef REGISTER_PREFIX alt_notend_table[REGISTER_PREFIX] = 1; #endif -#ifdef OPTIONAL_REGISTER_PREFIX - alt_notend_table[OPTIONAL_REGISTER_PREFIX] = 1; -#endif #ifndef MIT_SYNTAX_ONLY /* Insert pseudo ops, these have to go into the opcode table since @@ -3873,20 +3861,119 @@ md_begin () init_regtable (); } +void +m68k_init_after_args () +{ + if (cpu_of_arch (current_architecture) == 0) + { + int cpu_type; + + if (strcmp (TARGET_CPU, "m68000") == 0 + || strcmp (TARGET_CPU, "m68302") == 0) + cpu_type = m68000; + else if (strcmp (TARGET_CPU, "m68010") == 0) + cpu_type = m68010; + else if (strcmp (TARGET_CPU, "m68020") == 0 + || strcmp (TARGET_CPU, "m68k") == 0) + cpu_type = m68020; + else if (strcmp (TARGET_CPU, "m68030") == 0) + cpu_type = m68030; + else if (strcmp (TARGET_CPU, "m68040") == 0) + cpu_type = m68040; + else if (strcmp (TARGET_CPU, "m68060") == 0) + cpu_type = m68060; + else if (strcmp (TARGET_CPU, "cpu32") == 0 + || strcmp (TARGET_CPU, "m68331") == 0 + || strcmp (TARGET_CPU, "m68332") == 0 + || strcmp (TARGET_CPU, "m68333") == 0 + || strcmp (TARGET_CPU, "m68340") == 0) + cpu_type = cpu32; + else + cpu_type = m68020; + + current_architecture |= cpu_type; + } +#if 0 /* Could be doing emulation. */ + if (current_architecture & m68881) + { + if (current_architecture & m68000) + as_bad ("incompatible processors 68000 and 68881/2 specified"); + if (current_architecture & m68010) + as_bad ("incompatible processors 68010 and 68881/2 specified"); + if (current_architecture & m68040) + as_bad ("incompatible processors 68040 and 68881/2 specified"); + } +#endif + if (current_architecture & m68851) + { + if (current_architecture & m68040) + { + as_warn ("68040 and 68851 specified; mmu instructions may assemble incorrectly"); + } + } + /* What other incompatibilities could we check for? */ + + /* Toss in some default assumptions about coprocessors. */ + if (!no_68881 + && (cpu_of_arch (current_architecture) + /* Can CPU32 have a 68881 coprocessor?? */ + & (m68020 | m68030 | cpu32))) + { + current_architecture |= m68881; + } + if (!no_68851 + && (cpu_of_arch (current_architecture) & m68020up) != 0 + && (cpu_of_arch (current_architecture) & m68040up) == 0) + { + current_architecture |= m68851; + } + if (no_68881 && (current_architecture & m68881)) + as_bad ("options for 68881 and no-68881 both given"); + if (no_68851 && (current_architecture & m68851)) + as_bad ("options for 68851 and no-68851 both given"); + +#ifdef OBJ_AOUT + /* Work out the magic number. This isn't very general. */ + if (current_architecture & m68000) + m68k_aout_machtype = 0; + else if (current_architecture & m68010) + m68k_aout_machtype = 1; + else if (current_architecture & m68020) + m68k_aout_machtype = 2; + else + m68k_aout_machtype = 2; +#endif + + /* Note which set of "movec" control registers is available. */ + switch (cpu_of_arch (current_architecture)) + { + case m68000: + control_regs = m68000_control_regs; + break; + case m68010: + control_regs = m68010_control_regs; + break; + case m68020: + case m68030: + control_regs = m68020_control_regs; + break; + case m68040: + control_regs = m68040_control_regs; + break; + case m68060: + control_regs = m68060_control_regs; + break; + default: + abort (); + } +} + #if 0 #define notend(s) ((*s == ',' || *s == '}' || *s == '{' \ || (*s == ':' && strchr("aAdD#", s[1]))) \ ? 0 : 1) #endif -/* This funciton is called once, before the assembler exits. It is - supposed to do any final cleanup for this part of the assembler. - */ -void -md_end () -{ -} - /* Equal to MAX_PRECISION in atof-ieee.c */ #define MAX_LITTLENUMS 6 @@ -3949,37 +4036,13 @@ md_atof (type, litP, sizeP) return 0; } -/* Turn an integer of n bytes (in val) into a stream of bytes appropriate - for use in the a.out file, and stores them in the array pointed to by buf. - This knows about the endian-ness of the target machine and does - THE RIGHT THING, whatever it is. Possible values for n are 1 (byte) - 2 (short) and 4 (long) Floating numbers are put out as a series of - LITTLENUMS (shorts, here at least) - */ void md_number_to_chars (buf, val, n) char *buf; valueT val; int n; { - switch (n) - { - case 1: - *buf++ = val; - break; - case 2: - *buf++ = (val >> 8); - *buf++ = val; - break; - case 4: - *buf++ = (val >> 24); - *buf++ = (val >> 16); - *buf++ = (val >> 8); - *buf++ = val; - break; - default: - as_fatal ("failed sanity check."); - } + number_to_chars_bigendian (buf, val, n); } static void @@ -4526,8 +4589,7 @@ tc_aout_fix_to_chars (where, fixP, segment_address_in_file) * Out: GNU LD relocation length code: 0, 1, or 2. */ - static CONST unsigned char nbytes_r_length[] = - {42, 0, 1, 42, 2}; + static CONST unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2}; long r_symbolnum; know (fixP->fx_addsy != NULL); @@ -4545,8 +4607,6 @@ tc_aout_fix_to_chars (where, fixP, segment_address_in_file) where[6] = r_symbolnum & 0x0ff; where[7] = (((fixP->fx_pcrel << 7) & 0x80) | ((nbytes_r_length[fixP->fx_size] << 5) & 0x60) | (((!S_IS_DEFINED (fixP->fx_addsy)) << 4) & 0x10)); - - return; } #endif @@ -4896,6 +4956,20 @@ s_proc (ignore) #define MAYBE_FLOAT_TOO /* m68881 */ 0 /* this is handled later */ #endif +int +m68k_parse_long_option (opt) + char *opt; +{ + /* Skip over double-dash. */ + opt += 2; + if (!strcmp (opt, "register-prefix-optional")) + { + flag_reg_prefix_optional = 1; + return 1; + } + return 0; +} + int md_parse_option (argP, cntP, vecP) char **argP; @@ -4945,6 +5019,10 @@ md_parse_option (argP, cntP, vecP) { current_architecture |= m68040 | MAYBE_FLOAT_TOO; } + else if (!strcmp (*argP, "68060")) + { + current_architecture |= m68060 | MAYBE_FLOAT_TOO; + } #ifndef NO_68881 else if (!strcmp (*argP, "68881")) { diff --git a/gas/configure.in b/gas/configure.in index 9671b07a6c0..5428394e011 100644 --- a/gas/configure.in +++ b/gas/configure.in @@ -109,7 +109,7 @@ case ${target_cpu} in # but this is what the support files are named... hppa*) cpu_type=hppa ;; i486) cpu_type=i386 ;; - m680[01234]0) cpu_type=m68k ;; + m680[012346]0) cpu_type=m68k ;; m68008) cpu_type=m68k ;; m683??) cpu_type=m68k ;; m8*) cpu_type=m88k ;; -- 2.30.2