Issue 070426.2: Support bundled instructions

Author: Cary Coutant
Champion:
Date submitted: 2007-04-26
Date revised:
Date closed:
Type: Extension
Status: Accepted
DWARF Version: 4
Background

On many VLIW architectures (e.g., Itanium, ARM), several independent
operations may be encoded into a single instruction. Even though the
individual operations often cannot be individually addressed, they can
often be executed individually, making it desirable to provide line
number information at the operation level rather than the instruction
level. This proposal describes a way to include that extra information
within a DWARF line number table.

In existing implementations, the compiler and debugger are left to
agree on an ad hoc convention for how to represent the individual
operations inside the instruction. On Itanium, for example, an
instruction (called a "bundle") is 16 bytes and contains 5 template
bits plus three 41-bit operations (called "slots"). On HP-UX, the
compiler uses the bundle address plus 0, 4, and 8 to represent the
three individual slots, respectively; on Linux, the compiler instead
uses the bundle address plus 0, 1, and 2. In the line number program
on HP-UX, the compiler sets minimum_instruction_length to 4,
permitting it to use increments of 1, 1, 2, 1, 1, 2, .... On Linux,
however, minimum_instruction_length is set to 1, and uses increments
of 1, 1, 14, 1, 1, 14, .... In both cases -- especially so on Linux --
the precious space of special opcodes in the line table program is
being used inefficiently. The ideal solution would be to set
minimum_instruction_length to 16/3, so the compiler could just use
uniform increments of 1 between all operations.

Proposal

The proposed changes to the DWARF specification are detailed below,
keyed to the section numbering for the December 20, 2005 version of
the DWARF-3 document.

I've used single quotation marks for terms that would normally be set
in a computer typeface.


6.2.2  State Machine Registers

Add the following new register:

  op_index   An unsigned integer representing the index of an operation
             within a VLIW instruction. The index of the first operation
             in an instruction is 0. For non-VLIW architectures, this
             register will always be 0.

             The 'address' and 'op_index' registers, taken together,
             form an "operation pointer" that can reference any
             individual operation within the instruction stream.

Just below the list of registers, add an initial value for op_index:

  At the beginning of each sequence within a line number program, the
state of the registers is:

  address        0
  op_index       0
  file           1
  ...


6.2.4  The Line Number Program Header

Modify the description of 'minimum_instruction_length' and add a new
item immediately following for 'maximum_operations_per_instruction':

  4. mimimum_instruction_length (ubyte)

     The size in bytes of the smallest target machine instruction. Line
     number program opcodes that alter the address and op_index registers
     use this and 'maximum_operations_per_instruction' in their
     calculations.

  5. maximum_operations_per_instruction (ubyte)

     The maximum number of individual operations that may be encoded in an
     instruction. Line number program opcodes that alter the address and
     op_index registers use this and 'maximum_operations_per_instruction'
     in their calculations.

     For non-VLIW architectures, this field should be set to 1.

     (Present only if the 'version' field is greater than or equal to 4.)


6.2.5.1  Special Opcodes

Modify the description of the effect of 'minimum_instruction_length':

  2. Modify the "operation pointer" by incrementing the 'address' and
     'op_index' registers. The arithmetic is described below.

  ...

  All of the special opcodes do those same six things; they differ from
  one another only in what values they add to the 'line', 'address', and
  'op_index' registers.

(Note that the original wording for step 2 above implied that the
'address' register was always advanced by a non-negative number. That
was incorrect even for DWARF-2.)

Further down in the section:

  A special opcode value is chosen based on the amount that needs to be
  added to the 'line' register and the "operation pointer" (represented
  by the 'address' and 'op_index' registers). ... The "operation advance"
  represents the desired number of operations to skip when advancing the
  "operation pointer", based on the assumption that each instruction
  contains exactly the number of operations given by the value of
  'maximum_operations_per_instruction'. An "operation advance" equal to
  'maximum_operations_per_instruction' will advance the 'address'
  register by 'minimum_instruction_length' bytes, and will leave the
  'op_index' register unchanged. The special opcode is then calculated
  using the following formula:

    opcode = (desired line increment - line_base) +
               (line_range * operation advance) + opcode_base

  ...

  To decode a special opcode, subtract the 'opcode_base' from the opcode
  itself to give the adjusted opcode. The "operation advance" is
  determined by dividing the adjusted opcode by 'line_range'. The new
  values of the 'address' and 'op_index' registers are calculated by
  the following formulas:

    new address = address + minimum_instruction_length *
                             ((op_index + operation advance) div
                              maximum_operations_per_instruction)

    new op_index = ((op_index + operation advance) rem
                    maximum_operations_per_instruction)

  For these calculations, the 'div' and 'rem' operators are defined such
  that:

    a.  (a div b) is an integer;
    b.  a = (a div b) * b + (a rem b); and
    c.  0 <= (a rem b) < b.

(We could add an explanatory note to the effect that when
'maximum_operations_per_instruction' is 1, these calculations are
equivalent to the line table version 3 specifications.)

In the example given, change "address advance" to "operation advance".


6.2.5.2  Standard Opcodes

Modify the description of DW_LNS_advance_pc:

  2. DW_LNS_advance_pc

     The DW_LNS_advance_pc opcode takes a single unsigned LEB128 operand
     and advances the "operation pointer" by modifying the 'address' and
     'op_index' registers of the state machine according to the formulas
     given in the preceding section.

Modify the description of DW_LNS_const_add_pc and DW_LNS_fixed_advance_pc:

  8. DW_LNS_const_add_pc

     The DW_LNS_const_add_pc opcode takes no operands. It advances the
     "operation pointer" by the increment corresponding to that of special
     opcode 255, according to the formulas given in Section 6.2.5.1.

    ...

  9. DW_LNS_fixed_advance_pc

     The DW_LNS_fixed_advance_pc opcode takes a single uhalf (unencoded)
     operand, adds it to the 'address' register of the state machine, and
     sets the 'op_index' register to 0. This is the only standard opcode
     ...


6.2.5.3  Extended Opcodes

Modify the description of DW_LNE_set_address:

  2. DW_LNE_set_address

     The DW_LNE_set_address opcode takes a single relocatable address as
     an operand. The size of the operand is the size appropriate to hold
     an address on the target machine. It sets the 'address' register to
     the value given by the relocatable address, and sets the 'op_index'
     register to 0.


7.21  Line Number Information

Change the version number to 4:

  The version number in the line number program header is 4 for DWARF
  Version 4.


Appendix F - Version Numbers

Specify the version number for the .debug_line section to be 4 for
DWARF Version 4.

-----------------
see also proposal 070519.1