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