// 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   0x0000
#define COFF_FILE_MACHINE_ALPHA     0x0184
#define COFF_FILE_MACHINE_ALPHA64   0x0284
#define COFF_FILE_MACHINE_AM33      0x01d3 // Matsushita AM33
#define COFF_FILE_MACHINE_AMD64     0x8664
#define COFF_FILE_MACHINE_ARM       0x01c0
#define COFF_FILE_MACHINE_THUMB     0x01c2
#define COFF_FILE_MACHINE_ARMNT     0x01c4
#define COFF_FILE_MACHINE_ARM64     0xaa64
#define COFF_FILE_MACHINE_EBC       0x0ebc
#define COFF_FILE_MACHINE_I386      0x014c
#define COFF_FILE_MACHINE_I386_PTX  0x0154
#define COFF_FILE_MACHINE_I386_AIX  0x0175
#define COFF_FILE_MACHINE_IA64      0x0200 // Intel Itanium
#define COFF_FILE_MACHINE_M32R      0x9041 // Mitsubishi M32R
#define COFF_FILE_MACHINE_MIPS16    0x0266
#define COFF_FILE_MACHINE_MIPSFPU   0x0366
#define COFF_FILE_MACHINE_MIPSFPU16 0x0466
#define COFF_FILE_MACHINE_AMD29KBE  0x017a
#define COFF_FILE_MACHINE_AMD29KLE  0x017b
#define COFF_FILE_MACHINE_POWERPC   0x01f0
#define COFF_FILE_MACHINE_POWERPCFP 0x01f1
#define COFF_FILE_MACHINE_SH3       0x01a2
#define COFF_FILE_MACHINE_SH3DSP    0x01a3
#define COFF_FILE_MACHINE_SH4       0x01a6
#define COFF_FILE_MACHINE_SH5       0x01a8
#define COFF_FILE_MACHINE_WCEMIPSV2 0x0169
#define COFF_FILE_MACHINE_H8300     0x0083 // Renesas H8/300 (formerly Hitachi H8/300)
#define COFF_FILE_MACHINE_H8500     0x8500 // Renesas H8/500 (formerly Hitachi H8/500)
#define COFF_FILE_MACHINE_M68K      0x0268
#define COFF_FILE_MACHINE_68KAUX    0x0150 // Motorola 68k Apple A/UX
#define COFF_FILE_MACHINE_PIC30     0x1236 // PIC-30 (dsPIC30F)
#define COFF_FILE_MACHINE_I960RO    0x0160 // i960 read-only text segments
#define COFF_FILE_MACHINE_I960RW    0x0161 // i960 read-write text segments
#define COFF_FILE_MACHINE_R3000     0x0162 // MIPS R3000
#define COFF_FILE_MACHINE_R4000     0x0166 // MIPS R4000
#define COFF_FILE_MACHINE_R10000    0x0168 // MIPS R10000
#define COFF_FILE_MACHINE_RISCV32   0x5032
#define COFF_FILE_MACHINE_RISCV64   0x5064
#define COFF_FILE_MACHINE_RISCV128  0x5128
#define COFF_FILE_MACHINE_TI_1      0x00c1
#define COFF_FILE_MACHINE_TI_2      0x00c2
#define COFF_FILE_MACHINE_MIL1750   0x00db

#define COFF_FILE_TARGET_TI_TMS320C3x4x      0x0093
#define COFF_FILE_TARGET_TI_TMS470           0x0097
#define COFF_FILE_TARGET_TI_TMS320C5400      0x0098
#define COFF_FILE_TARGET_TI_TMS320C6000      0x0099
#define COFF_FILE_TARGET_TI_TMS320C5500      0x009c
#define COFF_FILE_TARGET_TI_TMS320C2800      0x009d
#define COFF_FILE_TARGET_TI_MSP430           0x00a0
#define COFF_FILE_TARGET_TI_TMS320C5500_PLUS 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

typedef 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 */
} CoffHdr;

typedef 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 */
} CoffOptHdr;

typedef 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 */
} CoffScnHdr;

typedef 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 */
} CoffSym;

#define COFF_SYMBOL_SIZE 18

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 */
