// SPDX-FileCopyrightText: 2014 Fedor Sakharov <fedor.sakharov@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#ifndef COFF_SPECS_H
#define COFF_SPECS_H

#include <rz_types_base.h>

#define COFF_FILE_MACHINE_UNKNOWN   0x0
#define COFF_FILE_MACHINE_AM33      0x1d3
#define COFF_FILE_MACHINE_AMD64     0x8664
#define COFF_FILE_MACHINE_ARM       0x1c0
#define COFF_FILE_MACHINE_ARMNT     0x1c4
#define COFF_FILE_MACHINE_ARM64     0xaa64
#define COFF_FILE_MACHINE_EBC       0xebc
#define COFF_FILE_MACHINE_I386      0x14c
#define COFF_FILE_MACHINE_IA64      0x200
#define COFF_FILE_MACHINE_M32R      0x9041
#define COFF_FILE_MACHINE_MIPS16    0x266
#define COFF_FILE_MACHINE_MIPSFPU   0x366
#define COFF_FILE_MACHINE_MIPSFPU16 0x466
#define COFF_FILE_MACHINE_AMD29KBE  0x7a01
#define COFF_FILE_MACHINE_AMD29KLE  0x17a
#define COFF_FILE_MACHINE_POWERPC   0x1f0
#define COFF_FILE_MACHINE_POWERPCFP 0x1f1
#define COFF_FILE_MACHINE_R4000     0x166
#define COFF_FILE_MACHINE_SH3       0x1a2
#define COFF_FILE_MACHINE_SH3DSP    0x1a3
#define COFF_FILE_MACHINE_SH4       0x1a6
#define COFF_FILE_MACHINE_SH5       0x1a8
#define COFF_FILE_MACHINE_THUMB     0x1c2
#define COFF_FILE_MACHINE_WCEMIPSV2 0x169
#define COFF_FILE_MACHINE_H8300     0x0083

#define COFF_FILE_TI_COFF               0xc1
#define COFF_FILE_MACHINE_TMS470        0x0097
#define COFF_FILE_MACHINE_TMS320C54     0x0098
#define COFF_FILE_MACHINE_TMS320C60     0x0099
#define COFF_FILE_MACHINE_TMS320C55     0x009C
#define COFF_FILE_MACHINE_TMS320C28     0x009D
#define COFF_FILE_MACHINE_MSP430        0x00A0
#define COFF_FILE_MACHINE_TMS320C55PLUS 0x00A1

#define COFF_FLAGS_TI_F_RELFLG 0x0001
#define COFF_FLAGS_TI_F_EXEC   0x0002
#define COFF_FLAGS_TI_F_LNNO   0x0004
#define COFF_FLAGS_TI_F_LSYMS  0x0008
#define COFF_FLAGS_TI_F_BIG    0x0200
#define COFF_FLAGS_TI_F_LITTLE 0x0100

#define COFF_SCN_TYPE_NO_PAD     0x00000008
#define COFF_SCN_CNT_CODE        0x00000020
#define COFF_SCN_CNT_INIT_DATA   0x00000040
#define COFF_SCN_CNT_UNIN_DATA   0x00000080 // The section contains uninitialized data.
#define COFF_SCN_LNK_OTHER       0x00000100
#define COFF_SCN_LNK_INFO        0x00000200
#define COFF_SCN_LNK_REMOVE      0x00000800
#define COFF_SCN_LNK_COMDAT      0x00001000
#define COFF_SCN_GPREL           0x00008000
#define COFF_SCN_MEM_PURGEABLE   0x00010000
#define COFF_SCN_MEM_16BIT       0x00020000
#define COFF_SCN_MEM_LOCKED      0x00040000
#define COFF_SCN_MEM_PRELOAD     0x00080000
#define COFF_SCN_ALIGN_1BYTES    0x00100000
#define COFF_SCN_ALIGN_2BYTES    0x00200000
#define COFF_SCN_ALIGN_4BYTES    0x00300000
#define COFF_SCN_ALIGN_8BYTES    0x00400000
#define COFF_SCN_ALIGN_16BYTES   0x00500000
#define COFF_SCN_ALIGN_32BYTES   0x00600000
#define COFF_SCN_ALIGN_64BYTES   0x00700000
#define COFF_SCN_ALIGN_128BYTES  0x00800000
#define COFF_SCN_ALIGN_256BYTES  0x00900000
#define COFF_SCN_ALIGN_512BYTES  0x00A00000
#define COFF_SCN_ALIGN_1024BYTES 0x00B00000
#define COFF_SCN_ALIGN_2048BYTES 0x00C00000
#define COFF_SCN_ALIGN_4096BYTES 0x00D00000
#define COFF_SCN_ALIGN_8192BYTES 0x00E00000
#define COFF_SCN_LNK_NRELOC_OVFL 0x01000000
#define COFF_SCN_MEM_DISCARDABLE 0x02000000
#define COFF_SCN_MEM_NOT_CACHED  0x04000000
#define COFF_SCN_MEM_NOT_PAGED   0x08000000
#define COFF_SCN_MEM_SHARED      0x10000000
#define COFF_SCN_MEM_EXECUTE     0x20000000
#define COFF_SCN_MEM_READ        0x40000000
#define COFF_SCN_MEM_WRITE       0x80000000

#define COFF_SCN_ALIGN_MASK 0x00F00000

#define COFF_SYM_SCNUM_UNDEF 0
#define COFF_SYM_SCNUM_ABS   0xffff
#define COFF_SYM_SCNUM_DEBUG 0xfffe

#define COFF_SYM_TYPE_NULL   0
#define COFF_SYM_TYPE_VOID   1
#define COFF_SYM_TYPE_CHAR   2
#define COFF_SYM_TYPE_SHORT  3
#define COFF_SYM_TYPE_INT    4
#define COFF_SYM_TYPE_LONG   5
#define COFF_SYM_TYPE_FLOAT  6
#define COFF_SYM_TYPE_DOUBLE 7
#define COFF_SYM_TYPE_STRUCT 8
#define COFF_SYM_TYPE_UNION  9
#define COFF_SYM_TYPE_ENUM   10
#define COFF_SYM_TYPE_MOE    11
#define COFF_SYM_TYPE_BYTE   12
#define COFF_SYM_TYPE_WORD   13
#define COFF_SYM_TYPE_UINT   14
#define COFF_SYM_TYPE_DWORD  15

#define COFF_SYM_DTYPE_NULL     0
#define COFF_SYM_DTYPE_POINTER  1
#define COFF_SYM_DTYPE_FUNCTION 2
#define COFF_SYM_DTYPE_ARRAY    3

#define COFF_SYM_CLASS_END_OF_FUNCTION  0xFF
#define COFF_SYM_CLASS_NULL             0
#define COFF_SYM_CLASS_AUTOMATIC        1
#define COFF_SYM_CLASS_EXTERNAL         2
#define COFF_SYM_CLASS_STATIC           3
#define COFF_SYM_CLASS_REGISTER         4
#define COFF_SYM_CLASS_EXTERNAL_DEF     5
#define COFF_SYM_CLASS_LABEL            6
#define COFF_SYM_CLASS_UNDEFINED_LABEL  7
#define COFF_SYM_CLASS_MEMBER_OF_STRUCT 8
#define COFF_SYM_CLASS_ARGUMENT         9
#define COFF_SYM_CLASS_STRUCT_TAG       10
#define COFF_SYM_CLASS_MEMBER_OF_UNION  11
#define COFF_SYM_CLASS_UNION_TAG        12
#define COFF_SYM_CLASS_TYPE_DEFINITION  13
#define COFF_SYM_CLASS_UNDEFINED_STATIC 14
#define COFF_SYM_CLASS_ENUM_TAG         15
#define COFF_SYM_CLASS_MEMBER_OF_ENUM   16
#define COFF_SYM_CLASS_REGISTER_PARAM   17
#define COFF_SYM_CLASS_BIT_FIELD        18
#define COFF_SYM_CLASS_BLOCK            100
#define COFF_SYM_CLASS_FUNCTION         101
#define COFF_SYM_CLASS_END_OF_STRUCT    102
#define COFF_SYM_CLASS_FILE             103
#define COFF_SYM_CLASS_SECTION          104
#define COFF_SYM_CLASS_WEAK_EXTERNAL    105
#define COFF_SYM_CLASS_CLR_TOKEN        107

#define COFF_REL_I386_ABS     0
#define COFF_REL_I386_DIR16   1
#define COFF_REL_I386_REL16   2
#define COFF_REL_I386_DIR32   6
#define COFF_REL_I386_DIR32NB 7
#define COFF_REL_I386_REL32   20

#define COFF_REL_AMD64_ABS       0
#define COFF_REL_AMD64_ADDR64    1
#define COFF_REL_AMD64_ADDR32    2
#define COFF_REL_AMD64_ADDR32_NB 3
#define COFF_REL_AMD64_REL32     4
#define COFF_REL_AMD64_REL32_1   5
#define COFF_REL_AMD64_REL32_2   6
#define COFF_REL_AMD64_REL32_3   7
#define COFF_REL_AMD64_REL32_4   8
#define COFF_REL_AMD64_REL32_5   9

#define COFF_REL_ARM_BRANCH24T 20
#define COFF_REL_ARM_BLX23T    21

#define COFF_REL_ARM64_ABSOLUTE 0
#define COFF_REL_ARM64_ADDR32   1
#define COFF_REL_ARM64_ADDR32NB 2
#define COFF_REL_ARM64_BRANCH26 3

RZ_PACKED(
	struct coff_hdr {
		ut16 f_magic; /* Magic number */
		ut16 f_nscns; /* Number of Sections */
		ut32 f_timdat; /* Time & date stamp */
		ut32 f_symptr; /* File pointer to Symbol Table */
		ut32 f_nsyms; /* Number of Symbols */
		ut16 f_opthdr; /* sizeof(Optional Header) */
		ut16 f_flags; /* Flags */
	}); // __attribute__ ((packed));

RZ_PACKED(
	struct coff_opt_hdr {
		ut16 magic; /* Magic Number                    */
		ut16 vstamp; /* Version stamp                   */
		ut32 tsize; /* Text size in bytes              */
		ut32 dsize; /* Initialised data size           */
		ut32 bsize; /* Uninitialised data size         */
		ut32 entry; /* Entry point                     */
		ut32 text_start; /* Base of Text used for this file */
		ut32 data_start; /* Base of Data used for this file */
	});

RZ_PACKED(
	struct coff_scn_hdr {
		char s_name[8]; /* Section Name */
		ut32 s_paddr; /* Physical Address */
		ut32 s_vaddr; /* Virtual Address */
		ut32 s_size; /* Section Size in Bytes */
		ut32 s_scnptr; /* File offset to the Section data */
		ut32 s_relptr; /* File offset to the Relocation table for this Section */
		ut32 s_lnnoptr; /* File offset to the Line Number table for this Section */
		ut16 s_nreloc; /* Number of Relocation table entries */
		ut16 s_nlnno; /* Number of Line Number table entries */
		ut32 s_flags; /* Flags for this section */
	});

RZ_PACKED(
	struct coff_symbol {
		char n_name[8]; /* Symbol Name */
		ut32 n_value; /* Value of Symbol */
		ut16 n_scnum; /* Section Number */
		ut16 n_type; /* Symbol Type */
		ut8 n_sclass; /* Storage Class */
		ut8 n_numaux; /* Auxiliary Count */
	});

struct coff_reloc {
	ut32 rz_vaddr; /* Reference Address */
	ut32 rz_symndx; /* Symbol index */
	ut16 rz_type; /* Type of relocation */
};

#define COFF_SYM_GET_DTYPE(type) (((type) >> 4) & 3)
#endif /* COFF_SPECS_H */
