15 #include <linux/kernel.h>
16 #include <linux/string.h>
17 #include <asm/byteorder.h>
23 #define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE
24 #define tile_decoded_instruction tilegx_decoded_instruction
25 #define tile_mnemonic tilegx_mnemonic
26 #define parse_insn_tile parse_insn_tilegx
27 #define TILE_OPC_IRET TILEGX_OPC_IRET
28 #define TILE_OPC_ADDI TILEGX_OPC_ADDI
29 #define TILE_OPC_ADDLI TILEGX_OPC_ADDLI
30 #define TILE_OPC_INFO TILEGX_OPC_INFO
31 #define TILE_OPC_INFOL TILEGX_OPC_INFOL
32 #define TILE_OPC_JRP TILEGX_OPC_JRP
33 #define TILE_OPC_MOVE TILEGX_OPC_MOVE
34 #define OPCODE_STORE TILEGX_OPC_ST
37 #define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE
38 #define tile_decoded_instruction tilepro_decoded_instruction
39 #define tile_mnemonic tilepro_mnemonic
40 #define parse_insn_tile parse_insn_tilepro
41 #define TILE_OPC_IRET TILEPRO_OPC_IRET
42 #define TILE_OPC_ADDI TILEPRO_OPC_ADDI
43 #define TILE_OPC_ADDLI TILEPRO_OPC_ADDLI
44 #define TILE_OPC_INFO TILEPRO_OPC_INFO
45 #define TILE_OPC_INFOL TILEPRO_OPC_INFOL
46 #define TILE_OPC_JRP TILEPRO_OPC_JRP
47 #define TILE_OPC_MOVE TILEPRO_OPC_MOVE
48 #define OPCODE_STORE TILEPRO_OPC_SW
68 const int *operand_values,
69 int num_operands_to_match)
78 if (insn->opcode->mnemonic != mnemonic)
82 for (j = 0; j < num_operands_to_match; j++) {
83 if (operand_values[j] != insn->operand_values[j]) {
122 *adjust = insn->operand_values[2];
137 for (i = 0; i < bundle->
num_insns; i++) {
143 operands[num_ops++] = insn->operand_values[0];
153 static bool bt_has_jrp(
const struct BacktraceBundle *bundle,
int *target_reg)
160 *target_reg = insn->operand_values[0];
168 for (i = 0; i < bundle->
num_insns; i++) {
172 if (insn->opcode->implicitly_written_register == reg)
175 for (j = 0; j < insn->opcode->num_operands; j++)
176 if (insn->operands[j]->is_dest_reg &&
177 insn->operand_values[j] == reg)
185 static inline bool bt_modifies_sp(
const struct BacktraceBundle *bundle)
187 return bt_modifies_reg(bundle,
TREG_SP);
191 static inline bool bt_modifies_lr(
const struct BacktraceBundle *bundle)
193 return bt_modifies_reg(bundle,
TREG_LR);
197 static inline bool bt_has_move_r52_sp(
const struct BacktraceBundle *bundle)
199 static const int vals[2] = { 52,
TREG_SP };
204 static inline bool bt_has_sw_sp_lr(
const struct BacktraceBundle *bundle)
212 static inline void bt_update_moveli(
const struct BacktraceBundle *bundle,
216 for (i = 0; i < bundle->
num_insns; i++) {
221 int reg = insn->operand_values[0];
222 moveli_args[
reg] = insn->operand_values[1];
231 static bool bt_has_add_sp(
const struct BacktraceBundle *bundle,
int *adjust,
239 int reg = insn->operand_values[2];
240 if (moveli_args[reg]) {
241 *adjust = moveli_args[
reg];
253 const unsigned long start_pc,
255 void *read_memory_func_extra)
260 bool sp_determined =
false;
263 bool lr_modified =
false;
266 bool sp_moved_to_r52 =
false;
269 bool seen_terminating_bundle =
false;
275 int num_bundles_prefetched = 0;
302 int one_ago, jrp_reg;
305 if (next_bundle >= num_bundles_prefetched) {
313 unsigned int bytes_to_prefetch = 4096 - (pc & 4095);
314 if (bytes_to_prefetch >
sizeof prefetched_bundles)
315 bytes_to_prefetch =
sizeof prefetched_bundles;
317 if (!read_memory_func(prefetched_bundles, pc,
319 read_memory_func_extra)) {
320 if (pc == start_pc) {
336 num_bundles_prefetched =
348 num_info_ops = bt_get_info_ops(&bundle, info_operands);
353 for (one_ago = (pc != start_pc) ? 1 : 0;
354 one_ago >= 0; one_ago--) {
356 for (i = 0; i < num_info_ops; i++) {
357 int info_operand = info_operands[
i];
372 info_operand &= ~ONE_BUNDLE_AGO_FLAG;
382 switch (info_operand) {
395 const unsigned int val = info_operand
397 const unsigned int sp_offset =
399 if (sp_offset < 32768) {
421 if (seen_terminating_bundle) {
428 if (bundle.
bits == 0) {
439 if (!sp_determined) {
441 if (bt_has_addi_sp(&bundle, &adjust)
443 || bt_has_add_sp(&bundle, &adjust, moveli_args)
457 sp_determined =
true;
459 if (bt_has_move_r52_sp(&bundle)) {
465 sp_moved_to_r52 =
true;
468 if (bt_modifies_sp(&bundle)) {
469 if (sp_moved_to_r52) {
489 sp_determined =
true;
495 bt_update_moveli(&bundle, moveli_args);
499 if (bt_has_iret(&bundle)) {
501 seen_terminating_bundle =
true;
510 has_jrp = bt_has_jrp(&bundle, &jrp_reg);
512 seen_terminating_bundle =
true;
516 if (jrp_reg ==
TREG_LR && !lr_modified) {
525 }
else if (bt_has_sw_sp_lr(&bundle)) {
528 }
else if (bt_modifies_lr(&bundle)) {
549 void *read_memory_func_extra,
550 unsigned long pc,
unsigned long lr,
551 unsigned long sp,
unsigned long r52)
554 unsigned long fp, initial_frame_caller_pc;
557 find_caller_pc_and_caller_sp(&location, pc,
558 read_memory_func, read_memory_func_extra);
587 initial_frame_caller_pc = -1;
600 initial_frame_caller_pc =
lr;
627 return ((
unsigned long)reg == reg);
635 unsigned long next_fp, next_pc;
638 if (state->
fp == -1) {
649 next_fp = next_frame[1];
650 if (!valid_addr_reg(next_frame[1]) ||
669 next_pc = next_frame[0];
670 if (!valid_addr_reg(next_frame[0]) || next_pc == 0 ||
679 state->
sp = state->
fp;