Home | History | Annotate | Line # | Download | only in simple
      1 // SPDX-License-Identifier: 0BSD
      2 
      3 ///////////////////////////////////////////////////////////////////////////////
      4 //
      5 /// \file       powerpc.c
      6 /// \brief      Filter for PowerPC (big endian) binaries
      7 ///
      8 //  Authors:    Igor Pavlov
      9 //              Lasse Collin
     10 //
     11 ///////////////////////////////////////////////////////////////////////////////
     12 
     13 #include "simple_private.h"
     14 
     15 
     16 static size_t
     17 powerpc_code(void *simple lzma_attribute((__unused__)),
     18 		uint32_t now_pos, bool is_encoder,
     19 		uint8_t *buffer, size_t size)
     20 {
     21 	size &= ~(size_t)3;
     22 
     23 	size_t i;
     24 	for (i = 0; i < size; i += 4) {
     25 		// PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link)
     26 		if ((buffer[i] >> 2) == 0x12
     27 				&& ((buffer[i + 3] & 3) == 1)) {
     28 
     29 			const uint32_t src
     30 				= (((uint32_t)(buffer[i + 0]) & 3) << 24)
     31 				| ((uint32_t)(buffer[i + 1]) << 16)
     32 				| ((uint32_t)(buffer[i + 2]) << 8)
     33 				| ((uint32_t)(buffer[i + 3]) & ~UINT32_C(3));
     34 
     35 			uint32_t dest;
     36 			if (is_encoder)
     37 				dest = now_pos + (uint32_t)(i) + src;
     38 			else
     39 				dest = src - (now_pos + (uint32_t)(i));
     40 
     41 			buffer[i + 0] = 0x48 | ((dest >> 24) &  0x03);
     42 			buffer[i + 1] = (dest >> 16);
     43 			buffer[i + 2] = (dest >> 8);
     44 			buffer[i + 3] &= 0x03;
     45 			buffer[i + 3] |= dest;
     46 		}
     47 	}
     48 
     49 	return i;
     50 }
     51 
     52 
     53 static lzma_ret
     54 powerpc_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
     55 		const lzma_filter_info *filters, bool is_encoder)
     56 {
     57 	return lzma_simple_coder_init(next, allocator, filters,
     58 			&powerpc_code, 0, 4, 4, is_encoder);
     59 }
     60 
     61 
     62 #ifdef HAVE_ENCODER_POWERPC
     63 extern lzma_ret
     64 lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
     65 		const lzma_allocator *allocator,
     66 		const lzma_filter_info *filters)
     67 {
     68 	return powerpc_coder_init(next, allocator, filters, true);
     69 }
     70 #endif
     71 
     72 
     73 #ifdef HAVE_DECODER_POWERPC
     74 extern lzma_ret
     75 lzma_simple_powerpc_decoder_init(lzma_next_coder *next,
     76 		const lzma_allocator *allocator,
     77 		const lzma_filter_info *filters)
     78 {
     79 	return powerpc_coder_init(next, allocator, filters, false);
     80 }
     81 #endif
     82