1a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras/*
2a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * This file is part of ltrace.
3a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras *
4a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * Copyright (C) 2013 Imagination Technologies Ltd.
5a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras *
6a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * This program is free software; you can redistribute it and/or
7a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * modify it under the terms of the GNU General Public License
8a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * version 2 as published by the Free Software Foundation.
9a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras *
10a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * This program is distributed in the hope that it will be useful, but
11a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * WITHOUT ANY WARRANTY; without even the implied warranty of
12a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * General Public License for more details.
14a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras *
15a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * You should have received a copy of the GNU General Public License
16a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * along with this program; if not, write to the Free Software
17a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * 02110-1301 USA
19a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras */
20a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
21a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include "config.h"
22a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
23a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <sys/types.h>
24a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <sys/wait.h>
25a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <signal.h>
26a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <sys/ptrace.h>
27a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <linux/uio.h>
28a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <asm/ptrace.h>
29a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <assert.h>
30a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
31a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include "proc.h"
32a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include "common.h"
33a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
34a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#define METAG_INSN_SIZE	4
35a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#define N_UNITS 2
36a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#define REG_SIZE 4
37a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
38a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras/* unit codes  */
39a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasenum metag_unitnum {
40a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_CT,       /* 0x0 */
41a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_D0,
42a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_D1,
43a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_A0,
44a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_A1,       /* 0x4 */
45a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_PC,
46a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_RA,
47a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_TR,
48a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_TT,       /* 0x8 */
49a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_FX,
50a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_MAX,
51a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras};
52a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
53a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras/**
54a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras    \param proc The process that had an event.
55a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
56a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras    Called by \c next_event() right after the return from wait.
57a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras */
58a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasvoid
59a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasget_arch_dep(struct process *proc)
60a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{
61a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
62a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras}
63a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
64a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras/**
65a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras    \param proc Process that had event.
66a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras    \param status From \c\ waitpid().
67a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras    \param sysnum 0-based syscall number.
68a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras    \return 1 if syscall, 2 if sysret, 0 otherwise.
69a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
70a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras    Called by \c next_event() after the call to get_arch_dep().
71a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
72a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras */
73a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasint
74a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrassyscall_p(struct process *proc, int status, int *sysnum)
75a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{
76a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	if (WIFSTOPPED(status)
77a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	    && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
78a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		struct user_gp_regs regs;
79a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		struct iovec iov;
80a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
81a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Get GP registers.  */
82a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		iov.iov_base = &regs;
83a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		iov.iov_len = sizeof(regs);
84a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (ptrace(PTRACE_GETREGSET, proc->pid, NT_PRSTATUS,
85a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			   (long)&iov))
86a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			return -1;
87a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
88a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Fetch the SWITCH instruction.  */
89a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		unsigned int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, regs.pc,
90a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras					   0);
91a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		*sysnum = regs.dx[0][1];
92a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
93a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (insn != 0xaf440001) {
94a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			/* Check if we're returning from the system call.  */
95a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			insn = ptrace(PTRACE_PEEKTEXT, proc->pid, regs.pc - 4,
96a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras				      0);
97a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			if (insn == 0xaf440001)
98a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras				return 2;
99a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
100a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			return 0;
101a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		}
102a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
103a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (*sysnum >= 0)
104a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			return 1;
105a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	}
106a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	return 0;
107a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras}
108a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
109a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras/* 2-bit base unit (BU) mapping.  */
110a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasstatic enum metag_unitnum metag_bu_map[4] = {
111a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_A1,
112a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_D0,
113a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_D1,
114a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	METAG_UNIT_A0,
115a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras};
116a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
117a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasstatic int
118a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasget_regval_from_unit(enum metag_unitnum unit, unsigned int reg,
119a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		     struct user_gp_regs *regs)
120a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{
121a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	/*
122a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	 * Check if reg has a sane value.
123a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	 * We do have N_UNITS, each one having X registers
124a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	 * and each register is REG_SIZE bytes.
125a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	 */
126a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	if ((unit == METAG_UNIT_A0) || (unit == METAG_UNIT_A1)) {
127a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (reg >= ((sizeof(regs->ax)/N_UNITS/REG_SIZE)))
128a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			goto bad_reg;
129a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	} else if ((unit == METAG_UNIT_D0) || (unit == METAG_UNIT_D1)) {
130a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (reg >= ((sizeof(regs->dx)/N_UNITS/REG_SIZE)))
131a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			goto bad_reg;
132a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	}
133a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
134a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	switch(unit) {
135a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	case METAG_UNIT_A1:
136a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		return regs->ax[reg][1];
137a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	case METAG_UNIT_D0:
138a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		return regs->dx[reg][0];
139a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	case METAG_UNIT_D1:
140a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		return regs->dx[reg][1];
141a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	case METAG_UNIT_A0:
142a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		return regs->ax[reg][0];
143a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	/* We really shouldn't be here.  */
144a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	default:
145a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		assert(unit != unit);
146a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		abort();
147a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	}
148a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	return 0;
149a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
150a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasbad_reg:
151a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	fprintf(stderr,
152a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		"Reading from register %d of unit %d is not implemented.",
153a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		reg, unit);
154a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	return 0;
155a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
156a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras}
157a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
158a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasstatic int
159a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasmetag_next_pcs(struct process *proc, uint32_t pc, uint32_t *newpc)
160a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{
161a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	uint32_t inst;
162a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	int nr = 0, imm, reg_val;
163a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	unsigned int unit = 0, reg;
164a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	struct user_gp_regs regs;
165a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	struct iovec iov;
166a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
167a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	inst = ptrace(PTRACE_PEEKTEXT, proc->pid, pc, 0);
168a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
169a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	if (inst == 0xa0fffffe) { /* NOP (Special branch instruction) */
170a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		newpc[nr++] = pc + 4;
171a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	} else if ((inst & 0xff000000) == 0xa0000000) {
172a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Matching 0xA 0x0 for opcode for B #S19 or B<cc> #S19.
173a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 *
174a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * Potential Targets:
175a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * - pc + #S19 * METAG_INSN_SIZE if R=1 or <CC> true
176a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * - pc + 4  */
177a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		imm = ((inst << 8) >> 13) * METAG_INSN_SIZE;
178a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		newpc[nr++] = pc + imm;
179a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		newpc[nr++] = pc + 4;
180a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	} else if ((inst & 0xff000000) == 0xac000000) {
181a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Matching 0xA 0xC for opcode.
182a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * JUMP BBx.r,#X16 or CALL BBx.r,#X16
183a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 *
184a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * pc = reg + #x16 (aligned)  */
185a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		imm = (inst >> 3) & 0xffff;
186a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		reg = (inst >> 19) & 0x1f;
187a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		unit = metag_bu_map[inst & 0x3];
188a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		iov.iov_base = &regs;
189a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		iov.iov_len = sizeof(regs);
190a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (ptrace(PTRACE_GETREGSET, proc->pid,
191a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			   NT_PRSTATUS, (long)&iov))
192a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			goto ptrace_fail;
193a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
194a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		reg_val = get_regval_from_unit(unit, reg, &regs);
195a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		newpc[nr++] = (reg_val + imm) & -METAG_INSN_SIZE;
196a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	} else if ((inst & 0xff000000) == 0xab000000) {
197a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Matching 0xA 0xB for opcode.
198a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 *
199a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * CALLR BBx.r,#S19  */
200a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		imm = ((inst << 8) >> 13) * METAG_INSN_SIZE;
201a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		newpc[nr++] = pc + imm;
202a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	} else if ((inst & 0xff0001e0) == 0xa30000a0) {
203a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/*
204a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * Matching 0xA 0x3 for opcode and then
205a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * Ud (bit 8-5) = 0x5 = METAG_UNIT_PC
206a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 *
207a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * Potential MOV PC,.. or SWAP<cc> PC,.. or SWAP<cc> ..,PC
208a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 */
209a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
210a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		iov.iov_base = &regs;
211a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		iov.iov_len = sizeof(regs);
212a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (ptrace(PTRACE_GETREGSET, proc->pid,
213a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			   NT_PRSTATUS, (long)&iov))
214a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			goto ptrace_fail;
215a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
216a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/*
217a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * Maybe PC is the source register for a SWAP?
218a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * bit9 = 1 and bit13-10(Us) == METAG_UNIT_PC
219a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 */
220a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (((inst >> 9 ) & 0x1) &&
221a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		    (((inst >> 10) & 0xf) == METAG_UNIT_PC)) {
222a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			/* PC will get its value from the
223a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			 * destination register.  */
224a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			reg = (inst >> 14) & 0x1f;
225a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			unit = (inst >> 5) & 0xf;
226a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		} else { /* PC is the destination register.
227a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			  * Find the source register.  */
228a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			reg = (inst >> 19) & 0x1f;
229a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			unit = (inst >> 10) & 0xf;
230a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		}
231a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
232a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		switch(unit) {
233a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		case METAG_UNIT_D0:
234a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		case METAG_UNIT_D1:
235a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		case METAG_UNIT_A0:
236a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		case METAG_UNIT_A1:
237a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			reg_val = get_regval_from_unit(unit, reg, &regs);
238a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			break;
239a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		case METAG_UNIT_PC:
240a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			reg_val = regs.pc;
241a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			break;
242a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		default:
243a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			goto unhandled;
244a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		}
245a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		newpc[nr++] = reg_val;
246a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* In case it is a conditional instruction.  */
247a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		newpc[nr++] = pc + 4;
248a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	} else if ((inst & 0xff00001f) == 0xc600000a){
249a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Matching 0xC 0x{4,6} for opcode
250a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * and UD == 0x5 == METAG_UNIT_PC
251a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 *
252a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * GETD PC, [A0.r + #S6] or
253a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		 * GETD PC, [A0.r + A0.r]  */
254a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		unit = metag_bu_map[(inst >> 5) & 0x3];
255a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		iov.iov_base = &regs;
256a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		iov.iov_len = sizeof(regs);
257a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		reg = (inst >> 14) & 0x1f;
258a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		imm = (inst << 18) >> 5; /* sign-extend it */
259a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (ptrace(PTRACE_GETREGSET, proc->pid,
260a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			   NT_PRSTATUS, (long)&iov))
261a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			goto ptrace_fail;
262a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		reg_val = get_regval_from_unit(unit, reg, &regs) + imm;
263a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* See where reg_val actually points to.  */
264a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		newpc[nr++] = ptrace(PTRACE_PEEKTEXT, proc->pid, reg_val, 0);
265a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	} else if (((inst & 0xfe0001e0) == 0x840000a0) || /* ADDcc R, A, R */
266a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		   ((inst & 0xfe00003f) == 0x8600002a) || /* ADD R, A, #X8 */
267a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		   ((inst & 0xfe0001e0) == 0x8c0000a0) || /* SUBcc R, A, R */
268a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		   ((inst & 0xfe00003f) == 0x8e00002a) || /* SUB R, A, #X8 */
269a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		   ((inst & 0xf40001e0) == 0x040000a0) || /* ADDcc R, D, D */
270a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		   ((inst & 0xfe00003f) == 0x0600002a) || /* ADD R, D, #X8 */
271a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		   ((inst & 0xf40001e0) == 0x140000a0) || /* SUBcc R, D, D */
272a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		   ((inst & 0xf600003f) == 0x1600002a)) { /* SUB R, D, #X8 */
273a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
274a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* bits4-1(Ud) == METAG_UNIT_PC */
275a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
276a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		int src1, src2, pc_src1 = 0, pc_src2 = 0, is_aunit = 0;
277a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		int umask = 0, optype = 0;
278a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
279a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Look for O2R bit */
280a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if ((((inst >> 24) & 0x6) == 0x4) && (inst & 0x1))
281a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			goto unhandled;
282a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
283a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		iov.iov_base = &regs;
284a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		iov.iov_len = sizeof(regs);
285a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (ptrace(PTRACE_GETREGSET, proc->pid,
286a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			   NT_PRSTATUS, (long)&iov))
287a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			goto ptrace_fail;
288a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
289a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Figure out unit for source registers based on the opcode.  */
290a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		switch((inst >> 28) & 0xf) {
291a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		case 0: /* ADD<cc> Rx.r, Dx.r, De.r|#X8 */
292a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		case 1: /* SUB<cc> Rx.r, Dx.r, De.r|#X8 */
293a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			unit = METAG_UNIT_D0 + ((inst >> 24) & 0x1);
294a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			is_aunit = 0;
295a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			umask = 0x1f;
296a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			optype = (inst >> 28) & 0x1;
297a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			break;
298a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		case 8:
299a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			unit = METAG_UNIT_A0 + ((inst >> 24) & 0x1);
300a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			is_aunit = 1;
301a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			umask = 0xf;
302a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			optype = (inst >> 27) & 0x1;
303a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			break;
304a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		}
305a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
306a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Get pc bits (if any).  */
307a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (is_aunit) {
308a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			pc_src1 = (inst >> 18) & 0x1;
309a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			pc_src2 = (inst >> 13) & 0x1;
310a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		}
311a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
312a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Determine ADD|SUB format. Immediate or register ?  */
313a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if ((inst >> 25) & 0x1) { /* ADD|SUB cc PC, X, #imm8 */
314a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			src2 = (inst >> 6) & 0xff; /* so we can share code.  */
315a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			reg = (inst >> 14) & umask;
316a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			if (pc_src1)	/* This can only be true for AU ops.  */
317a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras				src1 = regs.pc;
318a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			else		/* This covers both AU an DU ops.  */
319a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras				src1 = get_regval_from_unit(unit, reg, &regs);
320a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		} else { /* ADD|SUB cc PC, X, X */
321a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			if (pc_src1)
322a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras				src1 = regs.pc;
323a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			else
324a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras				src1 = get_regval_from_unit(unit, (inst >> 14)
325a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras							    & umask, &regs);
326a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			if (pc_src2)
327a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras				src2 = regs.pc;
328a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			else
329a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras				src2 = get_regval_from_unit(unit, (inst >> 9)
330a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras							    & umask, &regs);
331a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		}
332a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
333a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Construct the new PC.  */
334a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (optype)
335a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			/* SUB */
336a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			newpc[nr++] = src1 - src2;
337a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		else 	/* ADD */
338a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			newpc[nr++] = src1 + src2;
339a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		/* Conditional instruction so PC may not change.  */
340a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		newpc[nr++] = pc + 4;
341a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	} else {
342a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		newpc[nr++] = pc + 4;
343a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	}
344a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
345a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	if (nr <= 0 || nr > 2)
346a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		goto fail;
347a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	if (nr == 2 && newpc[1] == 0)
348a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		goto fail;
349a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
350a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	return nr;
351a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
352a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasptrace_fail:
353a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	fprintf(stderr, "Failed to read the registers pid=%d @ pc=0x%08x\n",
354a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		proc->pid, pc);
355a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	return 0;
356a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasunhandled:
357a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	fprintf(stderr, "Unhandled instruction: pc=0x%08x, inst=0x%08x\n",
358a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		pc, inst);
359a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	return 0;
360a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasfail:
361a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	fprintf(stderr, "nr=%d pc=0x%08x\n", nr, pc);
362a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	fprintf(stderr, "newpc=0x%08x 0x%08x\n", newpc[0], newpc[1]);
363a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	return 0;
364a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
365a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras}
366a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
367a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasenum sw_singlestep_status
368a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasarch_sw_singlestep(struct process *proc, struct breakpoint *bp,
369a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		   int (*add_cb)(arch_addr_t, struct sw_singlestep_data *),
370a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		   struct sw_singlestep_data *add_cb_data)
371a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{
372a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	arch_addr_t pc = get_instruction_pointer(proc);
373a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	uint32_t newpcs[2];
374a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	int nr;
375a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
376a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	nr = metag_next_pcs(proc, (uint32_t)pc, newpcs);
377a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
378a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	while (nr-- > 0) {
379a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		arch_addr_t baddr = (arch_addr_t) newpcs[nr];
380a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (dict_find(proc->leader->breakpoints, &baddr) != NULL) {
381a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			fprintf(stderr, "skip %p %p\n", baddr, add_cb_data);
382a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			continue;
383a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		}
384a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
385a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (add_cb(baddr, add_cb_data) < 0)
386a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			return SWS_FAIL;
387a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	}
388a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
389a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	ptrace(PTRACE_SYSCALL, proc->pid, 0, 0);
390a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	return SWS_OK;
391a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras}
392a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
393a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandraslong
394a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasgimme_arg(enum tof type, struct process *proc, int arg_num,
395a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	  struct arg_type_info *info)
396a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{
397a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	long ret;
398a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	struct user_gp_regs regs;
399a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	struct iovec iov;
400a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
401a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	/* get GP registers */
402a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	iov.iov_base = &regs;
403a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	iov.iov_len = sizeof(regs);
404a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	if (ptrace(PTRACE_GETREGSET, proc->pid, NT_PRSTATUS, (long)&iov))
405a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		return 0;
406a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
407a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	debug(2, "type %d arg %d arg",type, arg_num);
408a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL) {
409a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		if (arg_num < 6) {
410a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			/* Args go backwards starting from D1Ar1 (D1.3) */
411a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			ret = ((unsigned long *)&regs.dx[3][1])[-arg_num];
412a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			debug(2,"ret = %#lx",ret);
413a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			return ret;
414a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		} else {
415a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras			return 0;
416a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		}
417a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	}
418a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	if (arg_num >= 0) {
419a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		fprintf(stderr,"args on return?");
420a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	}
421a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	if (type == LT_TOF_FUNCTIONR || type == LT_TOF_SYSCALLR) {
422a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras		return regs.dx[0][0]; /* D0Re0 (D0.0) */
423a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	}
424a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
425a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	fprintf(stderr, "gimme_arg called with wrong arguments\n");
426a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras
427a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras	return 0;
428a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras}
429