xref: /freebsd/contrib/xz/src/liblzma/simple/ia64.c (revision 128836d304d93f2d00eb14069c27089ab46c38d4)
13b35e7eeSXin LI // SPDX-License-Identifier: 0BSD
23b35e7eeSXin LI 
381ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
481ad8388SMartin Matuska //
581ad8388SMartin Matuska /// \file       ia64.c
681ad8388SMartin Matuska /// \brief      Filter for IA64 (Itanium) binaries
781ad8388SMartin Matuska ///
881ad8388SMartin Matuska //  Authors:    Igor Pavlov
981ad8388SMartin Matuska //              Lasse Collin
1081ad8388SMartin Matuska //
1181ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
1281ad8388SMartin Matuska 
1381ad8388SMartin Matuska #include "simple_private.h"
1481ad8388SMartin Matuska 
1581ad8388SMartin Matuska 
1681ad8388SMartin Matuska static size_t
ia64_code(void * simple lzma_attribute ((__unused__)),uint32_t now_pos,bool is_encoder,uint8_t * buffer,size_t size)171456f0f9SXin LI ia64_code(void *simple lzma_attribute((__unused__)),
1881ad8388SMartin Matuska 		uint32_t now_pos, bool is_encoder,
1981ad8388SMartin Matuska 		uint8_t *buffer, size_t size)
2081ad8388SMartin Matuska {
2181ad8388SMartin Matuska 	static const uint32_t BRANCH_TABLE[32] = {
2281ad8388SMartin Matuska 		0, 0, 0, 0, 0, 0, 0, 0,
2381ad8388SMartin Matuska 		0, 0, 0, 0, 0, 0, 0, 0,
2481ad8388SMartin Matuska 		4, 4, 6, 6, 0, 0, 7, 7,
2581ad8388SMartin Matuska 		4, 4, 0, 0, 4, 4, 0, 0
2681ad8388SMartin Matuska 	};
2781ad8388SMartin Matuska 
28*128836d3SXin LI 	size &= ~(size_t)15;
29*128836d3SXin LI 
3081ad8388SMartin Matuska 	size_t i;
31*128836d3SXin LI 	for (i = 0; i < size; i += 16) {
3281ad8388SMartin Matuska 		const uint32_t instr_template = buffer[i] & 0x1F;
3381ad8388SMartin Matuska 		const uint32_t mask = BRANCH_TABLE[instr_template];
3481ad8388SMartin Matuska 		uint32_t bit_pos = 5;
3581ad8388SMartin Matuska 
3681ad8388SMartin Matuska 		for (size_t slot = 0; slot < 3; ++slot, bit_pos += 41) {
3781ad8388SMartin Matuska 			if (((mask >> slot) & 1) == 0)
3881ad8388SMartin Matuska 				continue;
3981ad8388SMartin Matuska 
4081ad8388SMartin Matuska 			const size_t byte_pos = (bit_pos >> 3);
4181ad8388SMartin Matuska 			const uint32_t bit_res = bit_pos & 0x7;
4281ad8388SMartin Matuska 			uint64_t instruction = 0;
4381ad8388SMartin Matuska 
4481ad8388SMartin Matuska 			for (size_t j = 0; j < 6; ++j)
4581ad8388SMartin Matuska 				instruction += (uint64_t)(
4681ad8388SMartin Matuska 						buffer[i + j + byte_pos])
4781ad8388SMartin Matuska 						<< (8 * j);
4881ad8388SMartin Matuska 
4981ad8388SMartin Matuska 			uint64_t inst_norm = instruction >> bit_res;
5081ad8388SMartin Matuska 
5181ad8388SMartin Matuska 			if (((inst_norm >> 37) & 0xF) == 0x5
5281ad8388SMartin Matuska 					&& ((inst_norm >> 9) & 0x7) == 0
5381ad8388SMartin Matuska 					/* &&  (inst_norm & 0x3F)== 0 */
5481ad8388SMartin Matuska 					) {
5581ad8388SMartin Matuska 				uint32_t src = (uint32_t)(
5681ad8388SMartin Matuska 						(inst_norm >> 13) & 0xFFFFF);
5781ad8388SMartin Matuska 				src |= ((inst_norm >> 36) & 1) << 20;
5881ad8388SMartin Matuska 
5981ad8388SMartin Matuska 				src <<= 4;
6081ad8388SMartin Matuska 
6181ad8388SMartin Matuska 				uint32_t dest;
6281ad8388SMartin Matuska 				if (is_encoder)
6381ad8388SMartin Matuska 					dest = now_pos + (uint32_t)(i) + src;
6481ad8388SMartin Matuska 				else
6581ad8388SMartin Matuska 					dest = src - (now_pos + (uint32_t)(i));
6681ad8388SMartin Matuska 
6781ad8388SMartin Matuska 				dest >>= 4;
6881ad8388SMartin Matuska 
6981ad8388SMartin Matuska 				inst_norm &= ~((uint64_t)(0x8FFFFF) << 13);
7081ad8388SMartin Matuska 				inst_norm |= (uint64_t)(dest & 0xFFFFF) << 13;
7181ad8388SMartin Matuska 				inst_norm |= (uint64_t)(dest & 0x100000)
7281ad8388SMartin Matuska 						<< (36 - 20);
7381ad8388SMartin Matuska 
74a8675d92SXin LI 				instruction &= (1U << bit_res) - 1;
7581ad8388SMartin Matuska 				instruction |= (inst_norm << bit_res);
7681ad8388SMartin Matuska 
7781ad8388SMartin Matuska 				for (size_t j = 0; j < 6; j++)
7881ad8388SMartin Matuska 					buffer[i + j + byte_pos] = (uint8_t)(
7981ad8388SMartin Matuska 							instruction
8081ad8388SMartin Matuska 							>> (8 * j));
8181ad8388SMartin Matuska 			}
8281ad8388SMartin Matuska 		}
8381ad8388SMartin Matuska 	}
8481ad8388SMartin Matuska 
8581ad8388SMartin Matuska 	return i;
8681ad8388SMartin Matuska }
8781ad8388SMartin Matuska 
8881ad8388SMartin Matuska 
8981ad8388SMartin Matuska static lzma_ret
ia64_coder_init(lzma_next_coder * next,const lzma_allocator * allocator,const lzma_filter_info * filters,bool is_encoder)9053200025SRui Paulo ia64_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
9181ad8388SMartin Matuska 		const lzma_filter_info *filters, bool is_encoder)
9281ad8388SMartin Matuska {
9381ad8388SMartin Matuska 	return lzma_simple_coder_init(next, allocator, filters,
9481ad8388SMartin Matuska 			&ia64_code, 0, 16, 16, is_encoder);
9581ad8388SMartin Matuska }
9681ad8388SMartin Matuska 
9781ad8388SMartin Matuska 
9873ed8e77SXin LI #ifdef HAVE_ENCODER_IA64
9981ad8388SMartin Matuska extern lzma_ret
lzma_simple_ia64_encoder_init(lzma_next_coder * next,const lzma_allocator * allocator,const lzma_filter_info * filters)10081ad8388SMartin Matuska lzma_simple_ia64_encoder_init(lzma_next_coder *next,
10153200025SRui Paulo 		const lzma_allocator *allocator,
10253200025SRui Paulo 		const lzma_filter_info *filters)
10381ad8388SMartin Matuska {
10481ad8388SMartin Matuska 	return ia64_coder_init(next, allocator, filters, true);
10581ad8388SMartin Matuska }
10673ed8e77SXin LI #endif
10781ad8388SMartin Matuska 
10881ad8388SMartin Matuska 
10973ed8e77SXin LI #ifdef HAVE_DECODER_IA64
11081ad8388SMartin Matuska extern lzma_ret
lzma_simple_ia64_decoder_init(lzma_next_coder * next,const lzma_allocator * allocator,const lzma_filter_info * filters)11181ad8388SMartin Matuska lzma_simple_ia64_decoder_init(lzma_next_coder *next,
11253200025SRui Paulo 		const lzma_allocator *allocator,
11353200025SRui Paulo 		const lzma_filter_info *filters)
11481ad8388SMartin Matuska {
11581ad8388SMartin Matuska 	return ia64_coder_init(next, allocator, filters, false);
11681ad8388SMartin Matuska }
11773ed8e77SXin LI #endif
118