1 /*
2  * BCJ filter for Itanium (IA-64) instructions
3  *
4  * Authors: Lasse Collin <lasse.collin@tukaani.org>
5  *          Igor Pavlov <http://7-zip.org/>
6  *
7  * This file has been put into the public domain.
8  * You can do whatever you want with this file.
9  */
10 
11 package org.tukaani.xz.simple;
12 
13 public final class IA64 implements SimpleFilter {
14     private static final int[] BRANCH_TABLE = {
15             0, 0, 0, 0, 0, 0, 0, 0,
16             0, 0, 0, 0, 0, 0, 0, 0,
17             4, 4, 6, 6, 0, 0, 7, 7,
18             4, 4, 0, 0, 4, 4, 0, 0 };
19 
20     private final boolean isEncoder;
21     private int pos;
22 
IA64(boolean isEncoder, int startPos)23     public IA64(boolean isEncoder, int startPos) {
24         this.isEncoder = isEncoder;
25         pos = startPos;
26     }
27 
code(byte[] buf, int off, int len)28     public int code(byte[] buf, int off, int len) {
29         int end = off + len - 16;
30         int i;
31 
32         for (i = off; i <= end; i += 16) {
33             int instrTemplate = buf[i] & 0x1F;
34             int mask = BRANCH_TABLE[instrTemplate];
35 
36             for (int slot = 0, bitPos = 5; slot < 3; ++slot, bitPos += 41) {
37                 if (((mask >>> slot) & 1) == 0)
38                     continue;
39 
40                 int bytePos = bitPos >>> 3;
41                 int bitRes = bitPos & 7;
42 
43                 long instr = 0;
44                 for (int j = 0; j < 6; ++j)
45                     instr |= (buf[i + bytePos + j] & 0xFFL) << (8 * j);
46 
47                 long instrNorm = instr >>> bitRes;
48 
49                 if (((instrNorm >>> 37) & 0x0F) != 0x05
50                         || ((instrNorm >>> 9) & 0x07) != 0x00)
51                     continue;
52 
53                 int src = (int)((instrNorm >>> 13) & 0x0FFFFF);
54                 src |= ((int)(instrNorm >>> 36) & 1) << 20;
55                 src <<= 4;
56 
57                 int dest;
58                 if (isEncoder)
59                     dest = src + (pos + i - off);
60                 else
61                     dest = src - (pos + i - off);
62 
63                 dest >>>= 4;
64 
65                 instrNorm &= ~(0x8FFFFFL << 13);
66                 instrNorm |= (dest & 0x0FFFFFL) << 13;
67                 instrNorm |= (dest & 0x100000L) << (36 - 20);
68 
69                 instr &= (1 << bitRes) - 1;
70                 instr |= instrNorm << bitRes;
71 
72                 for (int j = 0; j < 6; ++j)
73                     buf[i + bytePos + j] = (byte)(instr >>> (8 * j));
74             }
75         }
76 
77         i -= off;
78         pos += i;
79         return i;
80     }
81 }
82