1370b324cSopenharmony_ci/* Bra.h -- Branch converters for executables 2370b324cSopenharmony_ci2023-04-02 : Igor Pavlov : Public domain */ 3370b324cSopenharmony_ci 4370b324cSopenharmony_ci#ifndef ZIP7_INC_BRA_H 5370b324cSopenharmony_ci#define ZIP7_INC_BRA_H 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#include "7zTypes.h" 8370b324cSopenharmony_ci 9370b324cSopenharmony_ciEXTERN_C_BEGIN 10370b324cSopenharmony_ci 11370b324cSopenharmony_ci#define Z7_BRANCH_CONV_DEC(name) z7_BranchConv_ ## name ## _Dec 12370b324cSopenharmony_ci#define Z7_BRANCH_CONV_ENC(name) z7_BranchConv_ ## name ## _Enc 13370b324cSopenharmony_ci#define Z7_BRANCH_CONV_ST_DEC(name) z7_BranchConvSt_ ## name ## _Dec 14370b324cSopenharmony_ci#define Z7_BRANCH_CONV_ST_ENC(name) z7_BranchConvSt_ ## name ## _Enc 15370b324cSopenharmony_ci 16370b324cSopenharmony_ci#define Z7_BRANCH_CONV_DECL(name) Byte * name(Byte *data, SizeT size, UInt32 pc) 17370b324cSopenharmony_ci#define Z7_BRANCH_CONV_ST_DECL(name) Byte * name(Byte *data, SizeT size, UInt32 pc, UInt32 *state) 18370b324cSopenharmony_ci 19370b324cSopenharmony_citypedef Z7_BRANCH_CONV_DECL( (*z7_Func_BranchConv)); 20370b324cSopenharmony_citypedef Z7_BRANCH_CONV_ST_DECL((*z7_Func_BranchConvSt)); 21370b324cSopenharmony_ci 22370b324cSopenharmony_ci#define Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL 0 23370b324cSopenharmony_ciZ7_BRANCH_CONV_ST_DECL(Z7_BRANCH_CONV_ST_DEC(X86)); 24370b324cSopenharmony_ciZ7_BRANCH_CONV_ST_DECL(Z7_BRANCH_CONV_ST_ENC(X86)); 25370b324cSopenharmony_ci 26370b324cSopenharmony_ci#define Z7_BRANCH_FUNCS_DECL(name) \ 27370b324cSopenharmony_ciZ7_BRANCH_CONV_DECL(Z7_BRANCH_CONV_DEC(name)); \ 28370b324cSopenharmony_ciZ7_BRANCH_CONV_DECL(Z7_BRANCH_CONV_ENC(name)); 29370b324cSopenharmony_ci 30370b324cSopenharmony_ciZ7_BRANCH_FUNCS_DECL(ARM64) 31370b324cSopenharmony_ciZ7_BRANCH_FUNCS_DECL(ARM) 32370b324cSopenharmony_ciZ7_BRANCH_FUNCS_DECL(ARMT) 33370b324cSopenharmony_ciZ7_BRANCH_FUNCS_DECL(PPC) 34370b324cSopenharmony_ciZ7_BRANCH_FUNCS_DECL(SPARC) 35370b324cSopenharmony_ciZ7_BRANCH_FUNCS_DECL(IA64) 36370b324cSopenharmony_ci 37370b324cSopenharmony_ci/* 38370b324cSopenharmony_ciThese functions convert data that contain CPU instructions. 39370b324cSopenharmony_ciEach such function converts relative addresses to absolute addresses in some 40370b324cSopenharmony_cibranch instructions: CALL (in all converters) and JUMP (X86 converter only). 41370b324cSopenharmony_ciSuch conversion allows to increase compression ratio, if we compress that data. 42370b324cSopenharmony_ci 43370b324cSopenharmony_ciThere are 2 types of converters: 44370b324cSopenharmony_ci Byte * Conv_RISC (Byte *data, SizeT size, UInt32 pc); 45370b324cSopenharmony_ci Byte * ConvSt_X86(Byte *data, SizeT size, UInt32 pc, UInt32 *state); 46370b324cSopenharmony_ciEach Converter supports 2 versions: one for encoding 47370b324cSopenharmony_ciand one for decoding (_Enc/_Dec postfixes in function name). 48370b324cSopenharmony_ci 49370b324cSopenharmony_ciIn params: 50370b324cSopenharmony_ci data : data buffer 51370b324cSopenharmony_ci size : size of data 52370b324cSopenharmony_ci pc : current virtual Program Counter (Instruction Pinter) value 53370b324cSopenharmony_ciIn/Out param: 54370b324cSopenharmony_ci state : pointer to state variable (for X86 converter only) 55370b324cSopenharmony_ci 56370b324cSopenharmony_ciReturn: 57370b324cSopenharmony_ci The pointer to position in (data) buffer after last byte that was processed. 58370b324cSopenharmony_ci If the caller calls converter again, it must call it starting with that position. 59370b324cSopenharmony_ci But the caller is allowed to move data in buffer. so pointer to 60370b324cSopenharmony_ci current processed position also will be changed for next call. 61370b324cSopenharmony_ci Also the caller must increase internal (pc) value for next call. 62370b324cSopenharmony_ci 63370b324cSopenharmony_ciEach converter has some characteristics: Endian, Alignment, LookAhead. 64370b324cSopenharmony_ci Type Endian Alignment LookAhead 65370b324cSopenharmony_ci 66370b324cSopenharmony_ci X86 little 1 4 67370b324cSopenharmony_ci ARMT little 2 2 68370b324cSopenharmony_ci ARM little 4 0 69370b324cSopenharmony_ci ARM64 little 4 0 70370b324cSopenharmony_ci PPC big 4 0 71370b324cSopenharmony_ci SPARC big 4 0 72370b324cSopenharmony_ci IA64 little 16 0 73370b324cSopenharmony_ci 74370b324cSopenharmony_ci (data) must be aligned for (Alignment). 75370b324cSopenharmony_ci processed size can be calculated as: 76370b324cSopenharmony_ci SizeT processed = Conv(data, size, pc) - data; 77370b324cSopenharmony_ci if (processed == 0) 78370b324cSopenharmony_ci it means that converter needs more data for processing. 79370b324cSopenharmony_ci If (size < Alignment + LookAhead) 80370b324cSopenharmony_ci then (processed == 0) is allowed. 81370b324cSopenharmony_ci 82370b324cSopenharmony_ciExample code for conversion in loop: 83370b324cSopenharmony_ci UInt32 pc = 0; 84370b324cSopenharmony_ci size = 0; 85370b324cSopenharmony_ci for (;;) 86370b324cSopenharmony_ci { 87370b324cSopenharmony_ci size += Load_more_input_data(data + size); 88370b324cSopenharmony_ci SizeT processed = Conv(data, size, pc) - data; 89370b324cSopenharmony_ci if (processed == 0 && no_more_input_data_after_size) 90370b324cSopenharmony_ci break; // we stop convert loop 91370b324cSopenharmony_ci data += processed; 92370b324cSopenharmony_ci size -= processed; 93370b324cSopenharmony_ci pc += processed; 94370b324cSopenharmony_ci } 95370b324cSopenharmony_ci*/ 96370b324cSopenharmony_ci 97370b324cSopenharmony_ciEXTERN_C_END 98370b324cSopenharmony_ci 99370b324cSopenharmony_ci#endif 100