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