| 1 | /* Bra.h -- Branch converters for executables |
| 2 | 2024-01-20 : Igor Pavlov : Public domain */ |
| 3 | |
| 4 | #ifndef ZIP7_INC_BRA_H |
| 5 | #define ZIP7_INC_BRA_H |
| 6 | |
| 7 | #include "7zTypes.h" |
| 8 | |
| 9 | EXTERN_C_BEGIN |
| 10 | |
| 11 | /* #define PPC BAD_PPC_11 // for debug */ |
| 12 | |
| 13 | #define Z7_BRANCH_CONV_DEC_2(name) z7_ ## name ## _Dec |
| 14 | #define Z7_BRANCH_CONV_ENC_2(name) z7_ ## name ## _Enc |
| 15 | #define Z7_BRANCH_CONV_DEC(name) Z7_BRANCH_CONV_DEC_2(BranchConv_ ## name) |
| 16 | #define Z7_BRANCH_CONV_ENC(name) Z7_BRANCH_CONV_ENC_2(BranchConv_ ## name) |
| 17 | #define Z7_BRANCH_CONV_ST_DEC(name) z7_BranchConvSt_ ## name ## _Dec |
| 18 | #define Z7_BRANCH_CONV_ST_ENC(name) z7_BranchConvSt_ ## name ## _Enc |
| 19 | |
| 20 | #define Z7_BRANCH_CONV_DECL(name) Byte * name(Byte *data, SizeT size, UInt32 pc) |
| 21 | #define Z7_BRANCH_CONV_ST_DECL(name) Byte * name(Byte *data, SizeT size, UInt32 pc, UInt32 *state) |
| 22 | |
| 23 | typedef Z7_BRANCH_CONV_DECL( (*z7_Func_BranchConv)); |
| 24 | typedef Z7_BRANCH_CONV_ST_DECL((*z7_Func_BranchConvSt)); |
| 25 | |
| 26 | #define Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL 0 |
| 27 | Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_DEC(X86)); |
| 28 | Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_ENC(X86)); |
| 29 | |
| 30 | #define Z7_BRANCH_FUNCS_DECL(name) \ |
| 31 | Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_DEC_2(name)); \ |
| 32 | Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_ENC_2(name)); |
| 33 | |
| 34 | Z7_BRANCH_FUNCS_DECL (BranchConv_ARM64) |
| 35 | Z7_BRANCH_FUNCS_DECL (BranchConv_ARM) |
| 36 | Z7_BRANCH_FUNCS_DECL (BranchConv_ARMT) |
| 37 | Z7_BRANCH_FUNCS_DECL (BranchConv_PPC) |
| 38 | Z7_BRANCH_FUNCS_DECL (BranchConv_SPARC) |
| 39 | Z7_BRANCH_FUNCS_DECL (BranchConv_IA64) |
| 40 | Z7_BRANCH_FUNCS_DECL (BranchConv_RISCV) |
| 41 | |
| 42 | /* |
| 43 | These functions convert data that contain CPU instructions. |
| 44 | Each such function converts relative addresses to absolute addresses in some |
| 45 | branch instructions: CALL (in all converters) and JUMP (X86 converter only). |
| 46 | Such conversion allows to increase compression ratio, if we compress that data. |
| 47 | |
| 48 | There are 2 types of converters: |
| 49 | Byte * Conv_RISC (Byte *data, SizeT size, UInt32 pc); |
| 50 | Byte * ConvSt_X86(Byte *data, SizeT size, UInt32 pc, UInt32 *state); |
| 51 | Each Converter supports 2 versions: one for encoding |
| 52 | and one for decoding (_Enc/_Dec postfixes in function name). |
| 53 | |
| 54 | In params: |
| 55 | data : data buffer |
| 56 | size : size of data |
| 57 | pc : current virtual Program Counter (Instruction Pointer) value |
| 58 | In/Out param: |
| 59 | state : pointer to state variable (for X86 converter only) |
| 60 | |
| 61 | Return: |
| 62 | The pointer to position in (data) buffer after last byte that was processed. |
| 63 | If the caller calls converter again, it must call it starting with that position. |
| 64 | But the caller is allowed to move data in buffer. So pointer to |
| 65 | current processed position also will be changed for next call. |
| 66 | Also the caller must increase internal (pc) value for next call. |
| 67 | |
| 68 | Each converter has some characteristics: Endian, Alignment, LookAhead. |
| 69 | Type Endian Alignment LookAhead |
| 70 | |
| 71 | X86 little 1 4 |
| 72 | ARMT little 2 2 |
| 73 | RISCV little 2 6 |
| 74 | ARM little 4 0 |
| 75 | ARM64 little 4 0 |
| 76 | PPC big 4 0 |
| 77 | SPARC big 4 0 |
| 78 | IA64 little 16 0 |
| 79 | |
| 80 | (data) must be aligned for (Alignment). |
| 81 | processed size can be calculated as: |
| 82 | SizeT processed = Conv(data, size, pc) - data; |
| 83 | if (processed == 0) |
| 84 | it means that converter needs more data for processing. |
| 85 | If (size < Alignment + LookAhead) |
| 86 | then (processed == 0) is allowed. |
| 87 | |
| 88 | Example code for conversion in loop: |
| 89 | UInt32 pc = 0; |
| 90 | size = 0; |
| 91 | for (;;) |
| 92 | { |
| 93 | size += Load_more_input_data(data + size); |
| 94 | SizeT processed = Conv(data, size, pc) - data; |
| 95 | if (processed == 0 && no_more_input_data_after_size) |
| 96 | break; // we stop convert loop |
| 97 | data += processed; |
| 98 | size -= processed; |
| 99 | pc += processed; |
| 100 | } |
| 101 | */ |
| 102 | |
| 103 | EXTERN_C_END |
| 104 | |
| 105 | #endif |