[INTEL NAVIGATION HEADER]

IC960 R3.5 New Feature (-Gds) Simplifies Assignment of Global Data to Memory

(#3292)IC960 R3.5 New Feature (-Gds) Simplifies Assignment of Global Data to Memory [INTEL NAVIGATION HEADER]

IC960 R3.5 New Feature (-Gds) Simplifies Assignment of Global Data to Memory

The R3.5 version of ic960 provides a new option, -G{dc|ds}, which permits the user to select whether common symbol definitions (dc) should be emitted for uninitialized externs or whether these common symbol definitions should be suppressed (ds). If unspecified, the default is -Gdc.

The -Gds feature provides the user with the ability to easily assign global data (uninitialized externs) to specific memory addresses at link time. This feature did not exist in the R3.0 version of ic960 and a workaround for that version is discussed in the March 1991 issue of ;Comments.

First, we'll define some terms for use in this article. An "uninitialized extern" is a type of symbol whose definition appears outside of a function block, i.e., not enclosed within curly braces, which has no initialization value(s) and which has not necessarily been declared as "extern".

In the example below, the variable "xyz" is an uninitialized extern symbol; in this case a defining instance of a global variable. It is global because it appears outside of curly braces; it is a defining instance because the keyword "extern" is absent; and it has no initial value, hence it is uninitialized.

int xyz;
void foo(void) {
        xyz++;
}

Remember that there is a difference between a definition of a symbol and a reference to a symbol. The reference to an external symbol in a prototype is preceded by the keyword "extern", while the definition of an external symbol is not.

A "common symbol definition" is one method that the compiler can use to allocate storage for a defining instance of an uninitialized extern symbol, where the symbol, after a final link, ultimately occupies the same addresses in memory as all other identical defining instances of the same symbol. FORTRAN programmers will recognize this as being similar to a FORTRAN common block.

In an application where a module defines an uninitialized extern, by default the compiler will emit a common symbol definition by placing the symbol in a temporary section named ".comm". This is easily demonstrated by the following example. Given the one-line source file, foo.c:

When compiled with "ic960 -S", the following assembler mnemonics are emitted, which are subsequently assembled:

At link time, the linker will resolve all references to the array _exampl between modules. If defining instances of the array appear in more than one input module, they are all assigned to the same memory addresses. If all defining instances in all linker input modules appeared in the temporary ".comm" section, at final link the linker will assign the array to the output ".bss" section, which by definition is uninitialized in the COFF output module. This is the case that we'll discuss further in this article.

However, as an aside, the following linking possibilities also exist:

  1. If one (and ONLY ONE) of the linker input modules contained an INITIALIZED defining instance for the array _exampl, the linker will ultimately assign the array to the output ".data" section.

  2. If more than one linker input module contains an INITIALIZED defining instance, the linker will report a REMARK that there are multiple definitions. Such a case is a user error and the resulting output file is unusable.

  3. If one (and ONLY ONE) of the linker input modules contains an UNINITIALIZED defining instance for the array _example, and this instance appears in the ".bss" section of this same input module rather than the temporary ".comm" section, the linker will still assign the array to the output ".bss" section by default, but with an explicit starting address and outside of the collection of ".comm" sections at the end of the output ".bss" section. However, the user does have control over this assignment via thelinker directive file.
The use of common symbol definitions presents a limitation at link time when the user has:

The linker will ignore any attempt by the user to explicitly specify the memory address assignment for the array _exampl when the input module(s) have been compiled without the -Gds option, since the compiler has emitted common symbol definitions for uninitialized externs. The linker does not permit the user to control the address assignments for incoming ".comm" sections.

The iC960 R3.5 feature -Gds tells the compiler to place the uninitialized extern(s) in the ".bss" section in the object module(s) subsequently output by the assembler. The linker will permit the user to control the address assignments for incoming ".bss" sections. The same source file, foo.c, when compiled with "ic960 -S -Gds":

When linked, using the following linker directive file, the linker will permit the assignment of the array _exampl to the section named "foosec".

 MEMORY
 {
 one: o=0x10000000,l=0x200000
 two: o=0x10200000,l=0x1cffff
 }
 SECTIONS
 {
 GROUP : {
 .text : { }
 .data : { }
 .bss : { }
 } > one
 foosec : { foo.o(.bss)
 } > two
 }
 
It should be noted that compiling with "ic960 -Gds" presents a limitation of its own; of the modules compiled with -Gds, there can now only be ONE defining instance of the uninitialized extern in the entire application. All other appearances of the extern in other modules compiled with -Gds must be references only, i.e, they all must be preceded by the keyword "extern". For example:

Otherwise, the linker won't properly resolve all references to the single range of memory addresses specified in the linker directive file.

In summary, using the iC960 R3.5 -Gds switch will allow the user complete control over the assignment of global data to memory, via the linker directive file, whereas omitting the -Gds switch from the compiler's invocation will cause all uninitialized externs to end up in the default .bss section.

Free Web Hosting

Legal Stuff © 1997 Intel Corporation



Legal Stuff © 1997 Intel Corporation