Skip to content
Snippets Groups Projects
  • Jose E. Marchesi's avatar
    e9bffec9
    opcodes: discriminate endianness and insn-endianness in CGEN ports · e9bffec9
    Jose E. Marchesi authored
    The CGEN support code in opcodes accesses instruction contents using a
    couple of functions defined in cgen-opc.c: cgen_get_insn_value and
    cgen_put_insn_value.  These functions use the "instruction endianness"
    in the CPU description to order the read/written bytes.
    
    The process of writing an instruction to the object file is:
    
      a) cgen_put_insn_value        ;; Writes out the opcodes.
      b) ARCH_cgen_insert_operand
           insert_normal
             insert_1
               cgen_put_insn_value  ;; Writes out the bytes of the
                                    ;; operand.
    
    Likewise, the process of reading an instruction from the object file
    is:
    
      a) cgen_get_insn_value        ;; Reads the opcodes.
      b) ARCH_cgen_extract_operand
           extract_normal
             extract_1
               cgen_get_insn_value  ;; Reads in the bytes of the
                                    ;; operand.
    
    As can be seen above, cgen_{get,put}_insn_value are used to both
    process the instruction opcodes (the constant fields conforming the
    base instruction) and also the values of the instruction operands,
    such as immediates.
    
    This is problematic for architectures in which the endianness of
    instructions is different to the endianness of data.  An example is
    BPF, where instructions are always encoded big-endian but the data may
    be either big or little.
    
    This patch changes the cgen_{get,put}_insn_value functions in order to
    get an extra argument with the endianness to use, and adapts the
    existin callers to these functions in order to provide cd->endian or
    cd->insn_endian, whatever appropriate.  Callers like extract_1 and
    insert_1 pass cd->endian (since they are reading/writing operand
    values) while callers reading/writing the base instruction pass
    cd->insn_endian instead.
    
    A few little adjustments have been needed in some existing CGEN based
    ports:
    * The BPF assembler uses cgen_put_insn_value.  It has been adapted to
      pass the new endian argument.
    * The mep port has code in mep.opc that uses cgen_{get,put}_insn_value.
      It has been adapted to pass the new endianargument.  Ditto for a
      call in the assembler.
    
    Tested with --enable-targets=all.
    Regested in all supported targets.
    No regressions.
    
    include/ChangeLog:
    
    2020-06-04  Jose E. Marchesi  <jose.marchesi@oracle.com>
    
    	* opcode/cgen.h: Get an `endian' argument in both
    	cgen_get_insn_value and cgen_put_insn_value.
    
    opcodes/ChangeLog:
    
    2020-06-04  Jose E. Marchesi  <jose.marchesi@oracle.com>
    
    	* cgen-opc.c (cgen_get_insn_value): Get an `endian' argument.
    	(cgen_put_insn_value): Likewise.
    	(cgen_lookup_insn): Pass endianness to cgen_{get,put}_insn_value.
    	* cgen-dis.in (print_insn): Likewise.
    	* cgen-ibld.in (insert_1): Likewise.
    	(insert_1): Likewise.
    	(insert_insn_normal): Likewise.
    	(extract_1): Likewise.
    	* bpf-dis.c: Regenerate.
    	* bpf-ibld.c: Likewise.
    	* bpf-ibld.c: Likewise.
    	* cgen-dis.in: Likewise.
    	* cgen-ibld.in: Likewise.
    	* cgen-opc.c: Likewise.
    	* epiphany-dis.c: Likewise.
    	* epiphany-ibld.c: Likewise.
    	* fr30-dis.c: Likewise.
    	* fr30-ibld.c: Likewise.
    	* frv-dis.c: Likewise.
    	* frv-ibld.c: Likewise.
    	* ip2k-dis.c: Likewise.
    	* ip2k-ibld.c: Likewise.
    	* iq2000-dis.c: Likewise.
    	* iq2000-ibld.c: Likewise.
    	* lm32-dis.c: Likewise.
    	* lm32-ibld.c: Likewise.
    	* m32c-dis.c: Likewise.
    	* m32c-ibld.c: Likewise.
    	* m32r-dis.c: Likewise.
    	* m32r-ibld.c: Likewise.
    	* mep-dis.c: Likewise.
    	* mep-ibld.c: Likewise.
    	* mt-dis.c: Likewise.
    	* mt-ibld.c: Likewise.
    	* or1k-dis.c: Likewise.
    	* or1k-ibld.c: Likewise.
    	* xc16x-dis.c: Likewise.
    	* xc16x-ibld.c: Likewise.
    	* xstormy16-dis.c: Likewise.
    	* xstormy16-ibld.c: Likewise.
    
    gas/ChangeLog:
    
    2020-06-04  Jose E. Marchesi  <jose.marchesi@oracle.com>
    
    	* cgen.c (gas_cgen_finish_insn): Pass the endianness to
    	cgen_put_insn_value.
    	(gas_cgen_md_apply_fix): Likewise.
    	(gas_cgen_md_apply_fix): Likewise.
    	* config/tc-bpf.c (md_apply_fix): Pass data endianness to
    	cgen_put_insn_value.
    	* config/tc-mep.c (mep_check_ivc2_scheduling): Pass endianness to
    	cgen_put_insn_value.
    
    cpu/ChangeLog:
    
    2020-06-02  Jose E. Marchesi  <jose.marchesi@oracle.com>
    
    	* mep.opc (print_slot_insn): Pass the insn endianness to
    	cgen_get_insn_value.
    e9bffec9
    History
    opcodes: discriminate endianness and insn-endianness in CGEN ports
    Jose E. Marchesi authored
    The CGEN support code in opcodes accesses instruction contents using a
    couple of functions defined in cgen-opc.c: cgen_get_insn_value and
    cgen_put_insn_value.  These functions use the "instruction endianness"
    in the CPU description to order the read/written bytes.
    
    The process of writing an instruction to the object file is:
    
      a) cgen_put_insn_value        ;; Writes out the opcodes.
      b) ARCH_cgen_insert_operand
           insert_normal
             insert_1
               cgen_put_insn_value  ;; Writes out the bytes of the
                                    ;; operand.
    
    Likewise, the process of reading an instruction from the object file
    is:
    
      a) cgen_get_insn_value        ;; Reads the opcodes.
      b) ARCH_cgen_extract_operand
           extract_normal
             extract_1
               cgen_get_insn_value  ;; Reads in the bytes of the
                                    ;; operand.
    
    As can be seen above, cgen_{get,put}_insn_value are used to both
    process the instruction opcodes (the constant fields conforming the
    base instruction) and also the values of the instruction operands,
    such as immediates.
    
    This is problematic for architectures in which the endianness of
    instructions is different to the endianness of data.  An example is
    BPF, where instructions are always encoded big-endian but the data may
    be either big or little.
    
    This patch changes the cgen_{get,put}_insn_value functions in order to
    get an extra argument with the endianness to use, and adapts the
    existin callers to these functions in order to provide cd->endian or
    cd->insn_endian, whatever appropriate.  Callers like extract_1 and
    insert_1 pass cd->endian (since they are reading/writing operand
    values) while callers reading/writing the base instruction pass
    cd->insn_endian instead.
    
    A few little adjustments have been needed in some existing CGEN based
    ports:
    * The BPF assembler uses cgen_put_insn_value.  It has been adapted to
      pass the new endian argument.
    * The mep port has code in mep.opc that uses cgen_{get,put}_insn_value.
      It has been adapted to pass the new endianargument.  Ditto for a
      call in the assembler.
    
    Tested with --enable-targets=all.
    Regested in all supported targets.
    No regressions.
    
    include/ChangeLog:
    
    2020-06-04  Jose E. Marchesi  <jose.marchesi@oracle.com>
    
    	* opcode/cgen.h: Get an `endian' argument in both
    	cgen_get_insn_value and cgen_put_insn_value.
    
    opcodes/ChangeLog:
    
    2020-06-04  Jose E. Marchesi  <jose.marchesi@oracle.com>
    
    	* cgen-opc.c (cgen_get_insn_value): Get an `endian' argument.
    	(cgen_put_insn_value): Likewise.
    	(cgen_lookup_insn): Pass endianness to cgen_{get,put}_insn_value.
    	* cgen-dis.in (print_insn): Likewise.
    	* cgen-ibld.in (insert_1): Likewise.
    	(insert_1): Likewise.
    	(insert_insn_normal): Likewise.
    	(extract_1): Likewise.
    	* bpf-dis.c: Regenerate.
    	* bpf-ibld.c: Likewise.
    	* bpf-ibld.c: Likewise.
    	* cgen-dis.in: Likewise.
    	* cgen-ibld.in: Likewise.
    	* cgen-opc.c: Likewise.
    	* epiphany-dis.c: Likewise.
    	* epiphany-ibld.c: Likewise.
    	* fr30-dis.c: Likewise.
    	* fr30-ibld.c: Likewise.
    	* frv-dis.c: Likewise.
    	* frv-ibld.c: Likewise.
    	* ip2k-dis.c: Likewise.
    	* ip2k-ibld.c: Likewise.
    	* iq2000-dis.c: Likewise.
    	* iq2000-ibld.c: Likewise.
    	* lm32-dis.c: Likewise.
    	* lm32-ibld.c: Likewise.
    	* m32c-dis.c: Likewise.
    	* m32c-ibld.c: Likewise.
    	* m32r-dis.c: Likewise.
    	* m32r-ibld.c: Likewise.
    	* mep-dis.c: Likewise.
    	* mep-ibld.c: Likewise.
    	* mt-dis.c: Likewise.
    	* mt-ibld.c: Likewise.
    	* or1k-dis.c: Likewise.
    	* or1k-ibld.c: Likewise.
    	* xc16x-dis.c: Likewise.
    	* xc16x-ibld.c: Likewise.
    	* xstormy16-dis.c: Likewise.
    	* xstormy16-ibld.c: Likewise.
    
    gas/ChangeLog:
    
    2020-06-04  Jose E. Marchesi  <jose.marchesi@oracle.com>
    
    	* cgen.c (gas_cgen_finish_insn): Pass the endianness to
    	cgen_put_insn_value.
    	(gas_cgen_md_apply_fix): Likewise.
    	(gas_cgen_md_apply_fix): Likewise.
    	* config/tc-bpf.c (md_apply_fix): Pass data endianness to
    	cgen_put_insn_value.
    	* config/tc-mep.c (mep_check_ivc2_scheduling): Pass endianness to
    	cgen_put_insn_value.
    
    cpu/ChangeLog:
    
    2020-06-02  Jose E. Marchesi  <jose.marchesi@oracle.com>
    
    	* mep.opc (print_slot_insn): Pass the insn endianness to
    	cgen_get_insn_value.