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