diff -r -u binutils-2.9.4.0.7.hjlu/gas/config/tc-i370.c binutils-2.9.4.0.7/gas/config/tc-i370.c --- binutils-2.9.4.0.7.hjlu/gas/config/tc-i370.c Sun Jun 6 19:29:50 1999 +++ binutils-2.9.4.0.7/gas/config/tc-i370.c Tue Jul 13 23:55:43 1999 @@ -105,7 +105,7 @@ static void i370_ltorg PARAMS ((int)); static void i370_using PARAMS ((int)); static void i370_drop PARAMS ((int)); -static void i370_make_relative PARAMS ((expressionS *exp)); +static void i370_make_relative PARAMS ((expressionS *exp, expressionS *baseaddr)); #ifdef OBJ_ELF static bfd_reloc_code_real_type i370_elf_suffix PARAMS ((char **, expressionS *)); @@ -385,11 +385,34 @@ I370_OPCODE_32 or I370_OPCODE_64. */ static int i370_size = I370_OPCODE_32; -/* The base register to use for opcode with optional operands */ -static int i370_using_regno = -1; +/* The base register to use for opcode with optional operands. + * We define two of these: "text" and "other". Normally, "text" + * would get used in the .text section for branches, while "other" + * gets used in the .data section for address constants. + * + * The idea of a second base register in a different section + * is foreign to the usual HLASM-style semantics; however, it + * allows us to provide support for dynamically loaded libraries, + * by allowing us to place address constants in a section other + * than the text section. The "other" section need not be the + * .data section, it can be any section that isn't the .text section. + * + * Note that HLASM defines a multiple, concurrent .using semantic + * that we do not: in calculating offsets, it uses either the most + * recent .using directive, or the one with the smallest displacement. + * This allows HLASM to support a quasi-block-scope-like behaviour. + * Handy for people writing assembly by hand ... but not supported + * by us. + */ +static int i370_using_text_regno = -1; +static int i370_using_other_regno = -1; /* The base address for address literals */ -static expressionS i370_using_baseaddr; +static expressionS i370_using_text_baseaddr; +static expressionS i370_using_other_baseaddr; + +/* the "other" section, used only for syntax error detection */ +static segT i370_other_section = undefined_section; /* Opcode hash table. */ static struct hash_control *i370_hash; @@ -1030,23 +1053,23 @@ i370_dsect (xxx) int xxx; { - as_tsktsk ("dsect not supported"); -} - -static void -i370_csect (xxx) - int xxx; -{ char *save_line = input_line_pointer; - static char section[] = ".text\n"; + static char section[] = ".data\n"; - /* Just pretend this is .section .text */ + /* Just pretend this is .section .data */ input_line_pointer = section; obj_elf_section (xxx); input_line_pointer = save_line; } +static void +i370_csect (xxx) + int xxx; +{ + as_tsktsk ("csect not supported"); +} + /* DC Define Const is only partially supported. * For samplecode on what to do, look at i370_elf_cons() above. @@ -1442,7 +1465,17 @@ else if (1 == sz) exx->X_add_symbol = byte_poolP; exx->X_add_number = offset_in_pool; exx->X_op_symbol = NULL; - i370_make_relative (exx); + + /* If the user has set up a base reg in another section, + * use that; otherwise use the text section. */ + if (0 < i370_using_other_regno) + { + i370_make_relative (exx, &i370_using_other_baseaddr); + } + else + { + i370_make_relative (exx, &i370_using_text_baseaddr); + } } /* The symbol setup for the literal pool is done in two steps. First, @@ -1556,7 +1589,15 @@ expression (exx); /* OK, now we have to subtract the "using" location */ - i370_make_relative (exx); + /* normally branches appear in the text section only... */ + if (text_section == now_seg || 0 > i370_using_other_regno) + { + i370_make_relative (exx, &i370_using_text_baseaddr); + } + else + { + i370_make_relative (exx, &i370_using_other_baseaddr); + } /* put the * back */ if (dot) *dot = '*'; @@ -1718,6 +1759,18 @@ int biggest_align = 0; char pool_name[20]; + if (now_seg != text_section && + i370_other_section == undefined_section) + { + as_bad (".ltorg without prior .using in section %s", + now_seg->name); + } + if (now_seg != text_section && + i370_other_section != now_seg ) + { + as_bad (".ltorg in section %s paired to .using in section %s", + now_seg->name, i370_other_section->name); + } if ((NULL == longlong_poolP) && (NULL == word_poolP) && (NULL == short_poolP) && @@ -1730,11 +1783,12 @@ /* find largest literal .. 2 4 or 8 */ lit_count = 0; - while (lit_count < next_literal_pool_place) { - if (biggest_literal_size < literals[lit_count].size) - biggest_literal_size = literals[lit_count].size; - lit_count ++; - } + while (lit_count < next_literal_pool_place) + { + if (biggest_literal_size < literals[lit_count].size) + biggest_literal_size = literals[lit_count].size; + lit_count ++; + } if (2 == biggest_literal_size) biggest_align = 1; else if (4 == biggest_literal_size) biggest_align = 2; else if (8 == biggest_literal_size) biggest_align = 3; @@ -1816,7 +1870,7 @@ i370_using (ignore) int ignore; { - expressionS ex; + expressionS ex, baseaddr; int iregno; char *star; @@ -1827,11 +1881,11 @@ /* the first arg to using will usually be ".", but it can * be a more complex exprsssion too ... */ - expression (&i370_using_baseaddr); + expression (&baseaddr); if (star) *star = '*'; - if ((O_constant != i370_using_baseaddr.X_op) && - (O_symbol != i370_using_baseaddr.X_op) && - (O_uminus != i370_using_baseaddr.X_op)) + if ((O_constant != baseaddr.X_op) && + (O_symbol != baseaddr.X_op) && + (O_uminus != baseaddr.X_op)) { as_bad (".using: base address expression illegal or too complex"); } @@ -1843,19 +1897,17 @@ demand_empty_rest_of_line (); iregno = ex.X_add_number; - /* if we were strict, we could check that the current - * using was -1 and if not, flag it as a warning ... */ - if (-1 != i370_using_regno) { - // In fact, there can be multiple usings outstanding; - // the most recent or the one with the least offset is - // the one that gets used. We don't support this ... - // but don't print the error mesg, the common - // usage doesn't mess things up but does print this msg. - // as_tsktsk (".using %d without dropping %d first", - // iregno, i370_using_regno); - } - - i370_using_regno = iregno; + if (text_section == now_seg) + { + i370_using_text_baseaddr = baseaddr; + i370_using_text_regno = iregno; + } + else + { + i370_using_other_baseaddr = baseaddr; + i370_using_other_regno = iregno; + i370_other_section = now_seg; + } } static void @@ -1869,37 +1921,62 @@ demand_empty_rest_of_line (); iregno = ex.X_add_number; - if (iregno != i370_using_regno) { - as_bad ("droping register %d does not match using register %d", - iregno, i370_using_regno); - } - i370_using_regno = -1; - i370_using_baseaddr.X_op = O_absent; + if (text_section == now_seg) + { + if (iregno != i370_using_text_regno) + { + as_bad ("droping register %d in section %s does not match using register %d", + iregno, now_seg->name, i370_using_text_regno); + } + i370_using_text_regno = -1; + i370_using_text_baseaddr.X_op = O_absent; + } + else + { + if (iregno != i370_using_other_regno) + { + as_bad ("droping register %d in section %s does not match using register %d", + iregno, now_seg->name, i370_using_other_regno); + } + if (i370_other_section != now_seg) + { + as_bad ("droping register %d in section %s previously used in section %s", + iregno, now_seg->name, i370_other_section->name); + } + i370_using_other_regno = -1; + i370_using_other_baseaddr.X_op = O_absent; + i370_other_section = undefined_section; + } } +/* Make the first argument an address-relative expression + * by subtracting the second argument. + */ static void -i370_make_relative (expressionS *exx) +i370_make_relative (expressionS *exx, expressionS *baseaddr) { - if (O_constant == i370_using_baseaddr.X_op) - { - exx->X_op = O_symbol; - exx->X_add_number -= i370_using_baseaddr.X_add_number; - } else - if (O_symbol == i370_using_baseaddr.X_op) - { - exx->X_op = O_subtract; - exx->X_op_symbol = i370_using_baseaddr.X_add_symbol; - exx->X_add_number -= i370_using_baseaddr.X_add_number; - } else - if (O_uminus == i370_using_baseaddr.X_op) - { - exx->X_op = O_add; - exx->X_op_symbol = i370_using_baseaddr.X_add_symbol; - exx->X_add_number += i370_using_baseaddr.X_add_number; - } else - { - as_bad ("Missing or bad .using directive"); - } + + if (O_constant == baseaddr->X_op) + { + exx->X_op = O_symbol; + exx->X_add_number -= baseaddr->X_add_number; + } + else if (O_symbol == baseaddr->X_op) + { + exx->X_op = O_subtract; + exx->X_op_symbol = baseaddr->X_add_symbol; + exx->X_add_number -= baseaddr->X_add_number; + } + else if (O_uminus == baseaddr->X_op) + { + exx->X_op = O_add; + exx->X_op_symbol = baseaddr->X_add_symbol; + exx->X_add_number += baseaddr->X_add_number; + } + else + { + as_bad ("Missing or bad .using directive"); + } } /* We need to keep a list of fixups. We can't simply generate them as @@ -1927,6 +2004,7 @@ const unsigned char *opindex_ptr; int have_optional_index, have_optional_basereg, have_optional_reg; int skip_optional_index, skip_optional_basereg, skip_optional_reg; + int use_text=0, use_other=0; int off_by_one; int need_paren = 0; struct i370_fixup fixups[MAX_INSN_FIXUPS]; @@ -2074,10 +2152,34 @@ if (skip_optional_basereg && ((operand->flags & I370_OPERAND_BASE) != 0)) { - if (0 > i370_using_regno) { - as_bad ("not using any base register"); - } - insn = i370_insert_operand (insn, operand, i370_using_regno, + int basereg = -1; + if (use_text) + { + if (text_section == now_seg || 0 > i370_using_other_regno) + { + basereg = i370_using_text_regno; + } + else + { + basereg = i370_using_other_regno; + } + } + else if (use_other) + { + if (0 > i370_using_other_regno) + { + basereg = i370_using_text_regno; + } + else + { + basereg = i370_using_other_regno; + } + } + if (0 > basereg) + { + as_bad ("not using any base register"); + } + insn = i370_insert_operand (insn, operand, basereg, (char *) NULL, 0); continue; } @@ -2113,8 +2215,10 @@ } /* check for a address constant expression */ - else if (i370_addr_cons (&ex)) {} - else if (i370_addr_offset (&ex)) {} + /* We will put PSW-relative addresses in the text section, + * and adress literals in the .data (or other) section. */ + else if (i370_addr_cons (&ex)) { use_other=1; } + else if (i370_addr_offset (&ex)) { use_text=1; } else expression (&ex); str = input_line_pointer; diff -r -u binutils-2.9.4.0.7.hjlu/gas/doc/c-i370.texi binutils-2.9.4.0.7/gas/doc/c-i370.texi --- binutils-2.9.4.0.7.hjlu/gas/doc/c-i370.texi Sat Jun 5 20:50:54 1999 +++ binutils-2.9.4.0.7/gas/doc/c-i370.texi Tue Jul 13 23:57:03 1999 @@ -25,16 +25,18 @@ @node ESA/390 Notes @section Notes -As a back end for @sc{gnu} @sc{cc} @code{@value{AS}} has been tested -but should still be considered experimental. It will not work with -HLASM-style assembly because it supports only a small subset of the -HLASM directives. Note that that only ELF-style binary file formats are -supported; none of the usual MVS/VM/OE/USS object file formats are -supported. - -The ESA/390 @code{@value{AS}} port generates only a 31-bit relocation; -many more are available in the ELF object file format but are not -supported, and may fail silently. +The ESA/390 @code{@value{AS}} port is currently intended to be a back-end +for the @sc{gnu} @sc{cc} compiler. It is not HLASM compatible, although +it does support a subset of some of the HLASM directives. The only +supported binary file format is ELF; none of the usual MVS/VM/OE/USS +object file formats, such as ESD or XSD, are supported. + +When used with the @sc{gnu} @sc{cc} compiler, the ESA/390 @code{@value{AS}} +will produce correct, fully relocated, functional binaries, and has been +used to compile and execute large projects. However, many aspects should +still be considered experimental; these include shared library support, +dynamically loadable objects, and any relocation other than the 31-bit +relocation. @node ESA/390 Options @section Options @@ -49,7 +51,7 @@ are @emph{not} supported for the most part, with the exception of those described herein. -A leading dot in front of directives is optional, and teh case of +A leading dot in front of directives is optional, and the case of directives is ignored; thus for example, .using and USING have the same effect. @@ -121,7 +123,9 @@ A small subset of the usual DC directive is supported. @item .drop @var{regno} -Stop using @var{regno} as the base register. +Stop using @var{regno} as the base register. The @var{regno} must +have been previously declared with a @code{.using} directive in the +same section as the current section. @item .ebcdic @var{string} Emit the EBCDIC equivalent of the indicated string. The emitted string @@ -134,11 +138,60 @@ @item .ltorg Dump the literal pool accumulated so far; begin a new literal pool. +The literal pool will be written in the current section; in order to +generate correct assembly, a @code{.using} must have been previously +specified in the same section. @item .using @var{expr},@var{regno} Use @var{regno} as the base register for all subsequent RX, RS, and SS form instructions. The @var{expr} will be evaluated to obtain the base address; usually, @var{expr} will merely be @samp{*}. + +This assembler allows two @code{.using} directives to be simultaneously +outstanding, one in the @code{.text} section, and one in another section +(typically, the @code{.data} section). This feature allows +dynamically loaded objects to be implemented in a relatively +straightforward way. A @code{.using} directive must always be specified +in the @code{.text} section; this will specify the base register that +will be used for branches in the @code{.text} section. A second +@code{.using} may be specified in another section; this will specify +the base register that is used for non-label address literals. +When a second @code{.using} is specified, then the subsequent +@code{.ltorg} must be put in the same section; otherwise an error will +result. + +Thus, for example, the following code uses @code{r3} to address branch +targets and @code{r4} to address the literal pool, which has been written +to the @code{.data} section. The is, the constants @code{=A(some_routine)}, +@code{=H'42'} and @code{=E'3.1416'} will all appear in the @code{.data} +section. + +@example +.data + .using LITPOOL,r4 +.text + BASR r3,0 + .using *,r3 + B START + .long LITPOOL +START: + L r4,4(,r3) + L r15,=A(some_routine) + LTR r15,r15 + BNE LABEL + AH r0,=H'42' +LABEL: + ME r6,=E'3.1416' +.data +LITPOOL: + .ltorg +@end example + + +Note that this dual-@code{.using} directive semantics extends +and is not compatible with HLASM semantics. Note that this assembler +directive does not support the full range of HLASM semantics. + @end table @node ESA/390 Opcodes