|
@@ -215,3 +215,35 @@ static const struct unwind_idx *unwind_find_idx(unsigned long addr)
|
|
|
}
|
|
|
|
|
|
static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl)
|
|
|
+{
|
|
|
+ unsigned long ret;
|
|
|
+
|
|
|
+ if (ctrl->entries <= 0) {
|
|
|
+ pr_warning("unwind: Corrupt unwind table\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = (*ctrl->insn >> (ctrl->byte * 8)) & 0xff;
|
|
|
+
|
|
|
+ if (ctrl->byte == 0) {
|
|
|
+ ctrl->insn++;
|
|
|
+ ctrl->entries--;
|
|
|
+ ctrl->byte = 3;
|
|
|
+ } else
|
|
|
+ ctrl->byte--;
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Execute the current unwind instruction.
|
|
|
+ */
|
|
|
+static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
|
|
|
+{
|
|
|
+ unsigned long insn = unwind_get_byte(ctrl);
|
|
|
+
|
|
|
+ pr_debug("%s: insn = %08lx\n", __func__, insn);
|
|
|
+
|
|
|
+ if ((insn & 0xc0) == 0x00)
|
|
|
+ ctrl->vrs[SP] += ((insn & 0x3f) << 2) + 4;
|
|
|
+ else if ((insn & 0xc0) == 0x40)
|