- long opcode = inst >> 26;
- long r1 = (inst >> 21) & 0x1f;
- long r2 = (inst >> 16) & 0x1f;
- long bdisp = (inst&(1<<15)) ? inst | (-1 << 16) : inst&0xffff;
- long jdisp = (inst&(1<<25)) ? inst | (-1 << 26) : inst&0xffff;
- long disp = 0;
+ return (unsigned int)(*os_context_register_addr(context, offset));
+}
+
+static inline unsigned int
+os_context_pc(os_context_t *context)
+{
+ return (unsigned int)(*os_context_pc_addr(context));
+}
+
+static inline unsigned int
+os_context_insn(os_context_t *context)
+{
+ if (os_context_bd_cause(context))
+ return *(unsigned int *)(os_context_pc(context) + INSN_LEN);
+ else
+ return *(unsigned int *)(os_context_pc(context));
+}
+
+boolean
+arch_insn_with_bdelay_p(unsigned int insn)
+{
+ switch (insn >> 26) {
+ case 0x0:
+ switch (insn & 0x3f) {
+ /* register jumps */
+ case 0x08:
+ case 0x09:
+ return 1;
+ }
+ break;
+ /* branches and immediate jumps */
+ case 0x1:
+ switch ((insn >> 16) & 0x1f) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ return 1;
+ }
+ break;
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ return 1;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ switch ((insn >> 21) & 0x1f) {
+ /* CP0/CP1/CP2 branches */
+ case 0x08:
+ return 1;
+ }
+ break;
+ /* branch likely (MIPS II) */
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ return 1;
+ }
+ return 0;
+}
+
+/* Find the next instruction in the control flow. For a instruction
+ with branch delay slot, this is the branch/jump target if the branch
+ is taken, and PC + 8 if it is not taken. For other instructions it
+ is PC + 4. */
+static unsigned int
+next_insn_addr(os_context_t *context, unsigned int inst)
+{
+ unsigned int opcode = inst >> 26;
+ unsigned int r1 = (inst >> 21) & 0x1f;
+ unsigned int r2 = (inst >> 16) & 0x1f;
+ unsigned int r3 = (inst >> 11) & 0x1f;
+ unsigned int disp = ((inst&(1<<15)) ? inst | (-1 << 16) : inst&0x7fff) << 2;
+ unsigned int jtgt = (os_context_pc(context) & ~0x0fffffff) | (inst&0x3ffffff) << 2;
+ unsigned int tgt = os_context_pc(context);