xref: /src/contrib/opencsd/decoder/source/i_dec/trc_i_decode.cpp (revision 46e6e290975f19ea62d03f90ac3e523af4dae557)
1a6157d81SRuslan Bukin /*
2a6157d81SRuslan Bukin  * \file       trc_i_decode.cpp
3a6157d81SRuslan Bukin  * \brief      OpenCSD :
4a6157d81SRuslan Bukin  *
5a6157d81SRuslan Bukin  * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
6a6157d81SRuslan Bukin  */
7a6157d81SRuslan Bukin 
8a6157d81SRuslan Bukin /*
9a6157d81SRuslan Bukin  * Redistribution and use in source and binary forms, with or without modification,
10a6157d81SRuslan Bukin  * are permitted provided that the following conditions are met:
11a6157d81SRuslan Bukin  *
12a6157d81SRuslan Bukin  * 1. Redistributions of source code must retain the above copyright notice,
13a6157d81SRuslan Bukin  * this list of conditions and the following disclaimer.
14a6157d81SRuslan Bukin  *
15a6157d81SRuslan Bukin  * 2. Redistributions in binary form must reproduce the above copyright notice,
16a6157d81SRuslan Bukin  * this list of conditions and the following disclaimer in the documentation
17a6157d81SRuslan Bukin  * and/or other materials provided with the distribution.
18a6157d81SRuslan Bukin  *
19a6157d81SRuslan Bukin  * 3. Neither the name of the copyright holder nor the names of its contributors
20a6157d81SRuslan Bukin  * may be used to endorse or promote products derived from this software without
21a6157d81SRuslan Bukin  * specific prior written permission.
22a6157d81SRuslan Bukin  *
23a6157d81SRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24a6157d81SRuslan Bukin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25a6157d81SRuslan Bukin  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26a6157d81SRuslan Bukin  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27a6157d81SRuslan Bukin  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28a6157d81SRuslan Bukin  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29a6157d81SRuslan Bukin  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30a6157d81SRuslan Bukin  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31a6157d81SRuslan Bukin  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32a6157d81SRuslan Bukin  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33a6157d81SRuslan Bukin  */
34a6157d81SRuslan Bukin 
35a6157d81SRuslan Bukin #include "opencsd/ocsd_if_types.h"
36a6157d81SRuslan Bukin #include "i_dec/trc_i_decode.h"
37a6157d81SRuslan Bukin #include "i_dec/trc_idec_arminst.h"
38a6157d81SRuslan Bukin 
DecodeInstruction(ocsd_instr_info * instr_info)39a6157d81SRuslan Bukin ocsd_err_t TrcIDecode::DecodeInstruction(ocsd_instr_info *instr_info)
40a6157d81SRuslan Bukin {
41a6157d81SRuslan Bukin     ocsd_err_t err = OCSD_OK;
42d7aa8d0aSAndrew Turner     struct decode_info info;
43d7aa8d0aSAndrew Turner 
44d7aa8d0aSAndrew Turner     info.instr_sub_type = OCSD_S_INSTR_NONE;
45974000f1SRuslan Bukin     info.arch_version = instr_info->pe_type.arch;
46cf98ba14SRuslan Bukin 
47a6157d81SRuslan Bukin     switch(instr_info->isa)
48a6157d81SRuslan Bukin     {
49a6157d81SRuslan Bukin     case ocsd_isa_arm:
50d7aa8d0aSAndrew Turner         err = DecodeA32(instr_info, &info);
51a6157d81SRuslan Bukin         break;
52a6157d81SRuslan Bukin 
53a6157d81SRuslan Bukin     case ocsd_isa_thumb2:
54d7aa8d0aSAndrew Turner         err = DecodeT32(instr_info, &info);
55a6157d81SRuslan Bukin         break;
56a6157d81SRuslan Bukin 
57a6157d81SRuslan Bukin     case ocsd_isa_aarch64:
58d7aa8d0aSAndrew Turner         err = DecodeA64(instr_info, &info);
59a6157d81SRuslan Bukin         break;
60a6157d81SRuslan Bukin 
61a6157d81SRuslan Bukin     case ocsd_isa_tee:
62a6157d81SRuslan Bukin     case ocsd_isa_jazelle:
63a6157d81SRuslan Bukin     default:
64a6157d81SRuslan Bukin         // unsupported ISA
65a6157d81SRuslan Bukin         err = OCSD_ERR_UNSUPPORTED_ISA;
66a6157d81SRuslan Bukin         break;
67a6157d81SRuslan Bukin     }
68d7aa8d0aSAndrew Turner     instr_info->sub_type = info.instr_sub_type;
69a6157d81SRuslan Bukin     return err;
70a6157d81SRuslan Bukin }
71a6157d81SRuslan Bukin 
DecodeA32(ocsd_instr_info * instr_info,struct decode_info * info)72d7aa8d0aSAndrew Turner ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info, struct decode_info *info)
73a6157d81SRuslan Bukin {
74a6157d81SRuslan Bukin     uint32_t branchAddr = 0;
75a6157d81SRuslan Bukin     arm_barrier_t barrier;
76a6157d81SRuslan Bukin 
77a6157d81SRuslan Bukin     instr_info->instr_size = 4; // instruction size A32
78a6157d81SRuslan Bukin     instr_info->type =  OCSD_INSTR_OTHER;  // default type
79a6157d81SRuslan Bukin     instr_info->next_isa = instr_info->isa; // assume same ISA
80a6157d81SRuslan Bukin     instr_info->is_link = 0;
81a6157d81SRuslan Bukin 
82d7aa8d0aSAndrew Turner     if(inst_ARM_is_indirect_branch(instr_info->opcode, info))
83a6157d81SRuslan Bukin     {
84a6157d81SRuslan Bukin         instr_info->type = OCSD_INSTR_BR_INDIRECT;
85d7aa8d0aSAndrew Turner         instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode, info);
86a6157d81SRuslan Bukin     }
87a6157d81SRuslan Bukin     else if(inst_ARM_is_direct_branch(instr_info->opcode))
88a6157d81SRuslan Bukin     {
89a6157d81SRuslan Bukin         inst_ARM_branch_destination((uint32_t)instr_info->instr_addr,instr_info->opcode,&branchAddr);
90a6157d81SRuslan Bukin         instr_info->type = OCSD_INSTR_BR;
91a6157d81SRuslan Bukin         if (branchAddr & 0x1)
92a6157d81SRuslan Bukin         {
93a6157d81SRuslan Bukin             instr_info->next_isa = ocsd_isa_thumb2;
94a6157d81SRuslan Bukin             branchAddr &= ~0x1;
95a6157d81SRuslan Bukin         }
96a6157d81SRuslan Bukin         instr_info->branch_addr = (ocsd_vaddr_t)branchAddr;
97d7aa8d0aSAndrew Turner         instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode, info);
98a6157d81SRuslan Bukin     }
99a6157d81SRuslan Bukin     else if((barrier = inst_ARM_barrier(instr_info->opcode)) != ARM_BARRIER_NONE)
100a6157d81SRuslan Bukin     {
101a6157d81SRuslan Bukin         switch(barrier)
102a6157d81SRuslan Bukin         {
103a6157d81SRuslan Bukin         case ARM_BARRIER_ISB:
104a6157d81SRuslan Bukin             instr_info->type = OCSD_INSTR_ISB;
105a6157d81SRuslan Bukin             break;
106a6157d81SRuslan Bukin 
107a6157d81SRuslan Bukin         case ARM_BARRIER_DSB:
108a6157d81SRuslan Bukin         case ARM_BARRIER_DMB:
109a6157d81SRuslan Bukin             if(instr_info->dsb_dmb_waypoints)
110a6157d81SRuslan Bukin                 instr_info->type = OCSD_INSTR_DSB_DMB;
111a6157d81SRuslan Bukin             break;
112a6157d81SRuslan Bukin         }
113a6157d81SRuslan Bukin     }
114cf98ba14SRuslan Bukin     else if (instr_info->wfi_wfe_branch)
115cf98ba14SRuslan Bukin     {
116cf98ba14SRuslan Bukin         if (inst_ARM_wfiwfe(instr_info->opcode))
117cf98ba14SRuslan Bukin         {
118cf98ba14SRuslan Bukin             instr_info->type = OCSD_INSTR_WFI_WFE;
119cf98ba14SRuslan Bukin         }
120cf98ba14SRuslan Bukin     }
121a6157d81SRuslan Bukin     instr_info->is_conditional = inst_ARM_is_conditional(instr_info->opcode);
122a6157d81SRuslan Bukin 
123a6157d81SRuslan Bukin     return OCSD_OK;
124a6157d81SRuslan Bukin }
125a6157d81SRuslan Bukin 
DecodeA64(ocsd_instr_info * instr_info,struct decode_info * info)126d7aa8d0aSAndrew Turner ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info, struct decode_info *info)
127a6157d81SRuslan Bukin {
128a6157d81SRuslan Bukin     uint64_t branchAddr = 0;
129a6157d81SRuslan Bukin     arm_barrier_t barrier;
130a6157d81SRuslan Bukin 
131a6157d81SRuslan Bukin     instr_info->instr_size =  4; // default address update
132a6157d81SRuslan Bukin     instr_info->type =  OCSD_INSTR_OTHER;  // default type
133a6157d81SRuslan Bukin     instr_info->next_isa = instr_info->isa; // assume same ISA
134a6157d81SRuslan Bukin     instr_info->is_link = 0;
135a6157d81SRuslan Bukin 
136d7aa8d0aSAndrew Turner     if(inst_A64_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link, info))
137a6157d81SRuslan Bukin     {
138a6157d81SRuslan Bukin         instr_info->type = OCSD_INSTR_BR_INDIRECT;
139a6157d81SRuslan Bukin     }
140d7aa8d0aSAndrew Turner     else if(inst_A64_is_direct_branch_link(instr_info->opcode, &instr_info->is_link, info))
141a6157d81SRuslan Bukin     {
142a6157d81SRuslan Bukin         inst_A64_branch_destination(instr_info->instr_addr,instr_info->opcode,&branchAddr);
143a6157d81SRuslan Bukin         instr_info->type = OCSD_INSTR_BR;
144a6157d81SRuslan Bukin         instr_info->branch_addr = (ocsd_vaddr_t)branchAddr;
145a6157d81SRuslan Bukin     }
146a6157d81SRuslan Bukin     else if((barrier = inst_A64_barrier(instr_info->opcode)) != ARM_BARRIER_NONE)
147a6157d81SRuslan Bukin     {
148a6157d81SRuslan Bukin         switch(barrier)
149a6157d81SRuslan Bukin         {
150a6157d81SRuslan Bukin         case ARM_BARRIER_ISB:
151a6157d81SRuslan Bukin             instr_info->type = OCSD_INSTR_ISB;
152a6157d81SRuslan Bukin             break;
153a6157d81SRuslan Bukin 
154a6157d81SRuslan Bukin         case ARM_BARRIER_DSB:
155a6157d81SRuslan Bukin         case ARM_BARRIER_DMB:
156a6157d81SRuslan Bukin             if(instr_info->dsb_dmb_waypoints)
157a6157d81SRuslan Bukin                 instr_info->type = OCSD_INSTR_DSB_DMB;
158a6157d81SRuslan Bukin             break;
159a6157d81SRuslan Bukin         }
160a6157d81SRuslan Bukin     }
161974000f1SRuslan Bukin     else if (instr_info->wfi_wfe_branch &&
162974000f1SRuslan Bukin              inst_A64_wfiwfe(instr_info->opcode, info))
163cf98ba14SRuslan Bukin     {
164cf98ba14SRuslan Bukin         instr_info->type = OCSD_INSTR_WFI_WFE;
165cf98ba14SRuslan Bukin     }
166974000f1SRuslan Bukin     else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_AA64))
167974000f1SRuslan Bukin     {
168974000f1SRuslan Bukin         if (inst_A64_Tstart(instr_info->opcode))
169974000f1SRuslan Bukin             instr_info->type = OCSD_INSTR_TSTART;
170cf98ba14SRuslan Bukin     }
171a6157d81SRuslan Bukin 
172a6157d81SRuslan Bukin     instr_info->is_conditional = inst_A64_is_conditional(instr_info->opcode);
173a6157d81SRuslan Bukin 
174a6157d81SRuslan Bukin     return OCSD_OK;
175a6157d81SRuslan Bukin }
176a6157d81SRuslan Bukin 
DecodeT32(ocsd_instr_info * instr_info,struct decode_info * info)177d7aa8d0aSAndrew Turner ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info, struct decode_info *info)
178a6157d81SRuslan Bukin {
179a6157d81SRuslan Bukin     uint32_t branchAddr = 0;
180a6157d81SRuslan Bukin     arm_barrier_t barrier;
181a6157d81SRuslan Bukin 
182a6157d81SRuslan Bukin     // need to align the 32 bit opcode as 2 16 bit, with LS 16 as in top 16 bit of
183a6157d81SRuslan Bukin     // 32 bit word - T2 routines assume 16 bit in top 16 bit of 32 bit opcode.
184a6157d81SRuslan Bukin     uint32_t op_temp = (instr_info->opcode >> 16) & 0xFFFF;
185a6157d81SRuslan Bukin     op_temp |= ((instr_info->opcode & 0xFFFF) << 16);
186a6157d81SRuslan Bukin     instr_info->opcode = op_temp;
187a6157d81SRuslan Bukin 
188a6157d81SRuslan Bukin 
189a6157d81SRuslan Bukin     instr_info->instr_size = is_wide_thumb((uint16_t)(instr_info->opcode >> 16)) ? 4 : 2;
190a6157d81SRuslan Bukin     instr_info->type =  OCSD_INSTR_OTHER;  // default type
191a6157d81SRuslan Bukin     instr_info->next_isa = instr_info->isa; // assume same ISA
192a6157d81SRuslan Bukin     instr_info->is_link = 0;
193cf98ba14SRuslan Bukin     instr_info->is_conditional = 0;
194a6157d81SRuslan Bukin 
195cf98ba14SRuslan Bukin 
196d7aa8d0aSAndrew Turner     if(inst_Thumb_is_direct_branch_link(instr_info->opcode,&instr_info->is_link, &instr_info->is_conditional, info))
197a6157d81SRuslan Bukin     {
198a6157d81SRuslan Bukin         inst_Thumb_branch_destination((uint32_t)instr_info->instr_addr,instr_info->opcode,&branchAddr);
199a6157d81SRuslan Bukin         instr_info->type = OCSD_INSTR_BR;
200a6157d81SRuslan Bukin         instr_info->branch_addr = (ocsd_vaddr_t)(branchAddr & ~0x1);
201a6157d81SRuslan Bukin         if((branchAddr & 0x1) == 0)
202a6157d81SRuslan Bukin             instr_info->next_isa = ocsd_isa_arm;
203cf98ba14SRuslan Bukin     }
204d7aa8d0aSAndrew Turner     else if (inst_Thumb_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link, info))
205cf98ba14SRuslan Bukin     {
206cf98ba14SRuslan Bukin         instr_info->type = OCSD_INSTR_BR_INDIRECT;
207a6157d81SRuslan Bukin     }
208a6157d81SRuslan Bukin     else if((barrier = inst_Thumb_barrier(instr_info->opcode)) != ARM_BARRIER_NONE)
209a6157d81SRuslan Bukin     {
210a6157d81SRuslan Bukin         switch(barrier)
211a6157d81SRuslan Bukin         {
212a6157d81SRuslan Bukin         case ARM_BARRIER_ISB:
213a6157d81SRuslan Bukin             instr_info->type = OCSD_INSTR_ISB;
214a6157d81SRuslan Bukin             break;
215a6157d81SRuslan Bukin 
216a6157d81SRuslan Bukin         case ARM_BARRIER_DSB:
217a6157d81SRuslan Bukin         case ARM_BARRIER_DMB:
218a6157d81SRuslan Bukin             if(instr_info->dsb_dmb_waypoints)
219a6157d81SRuslan Bukin                 instr_info->type = OCSD_INSTR_DSB_DMB;
220a6157d81SRuslan Bukin             break;
221a6157d81SRuslan Bukin         }
222a6157d81SRuslan Bukin     }
223cf98ba14SRuslan Bukin     else if (instr_info->wfi_wfe_branch)
224cf98ba14SRuslan Bukin     {
225cf98ba14SRuslan Bukin         if (inst_Thumb_wfiwfe(instr_info->opcode))
226cf98ba14SRuslan Bukin         {
227cf98ba14SRuslan Bukin             instr_info->type = OCSD_INSTR_WFI_WFE;
228cf98ba14SRuslan Bukin         }
229cf98ba14SRuslan Bukin     }
230a6157d81SRuslan Bukin     instr_info->is_conditional = inst_Thumb_is_conditional(instr_info->opcode);
231a6157d81SRuslan Bukin     instr_info->thumb_it_conditions = inst_Thumb_is_IT(instr_info->opcode);
232a6157d81SRuslan Bukin 
233a6157d81SRuslan Bukin     return OCSD_OK;
234a6157d81SRuslan Bukin }
235a6157d81SRuslan Bukin 
236a6157d81SRuslan Bukin /* End of File trc_i_decode.cpp */
237