1/*	$NetBSD: stackframe.h,v 1.4 2016/07/31 19:33:18 dholland Exp $	*/
2
3/*
4 * Contributed to the NetBSD foundation by Cherry G. Mathew
5 */
6
7#define UNW_VER(x)           ((x) >> 48)
8#define UNW_FLAG_MASK        0x0000ffff00000000L
9#define UNW_FLAG_OSMASK      0x0000f00000000000L
10#define UNW_FLAG_EHANDLER(x) ((x) & 0x0000000100000000L)
11#define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000L)
12#define UNW_LENGTH(x)        ((x) & 0x00000000ffffffffL)
13
14/* Unwind table entry. */
15struct uwtable_ent {
16	uint64_t start;
17	uint64_t end;
18	char *infoptr;
19};
20
21
22enum regrecord_type{
23	/* Register contents live ( and therefore untouched ). */
24	UNSAVED,
25	/* .offset field is the saved content. */
26	IMMED,
27	/* Register saved in one of the Branch Registers. */
28	BRREL,
29	/*
30	 * Register saved in one of the Stacked GRs
31	 * regstate.offset contains GR number (usually >= 32)
32	 */
33	GRREL,
34	/*
35	 * Register saved on the memory stack frame.
36	 * regstate.offset is in words; ie; location == (sp + 4 * spoff).
37	 */
38	SPREL,
39	/*
40	 * Register saved on the memory stack frame but offseted via psp
41	 * regstate.offset is in words; ie,
42	 * location == (psp + 16 ���� 4 * pspoff)
43	 */
44	PSPREL
45};
46
47
48struct regstate {
49	enum regrecord_type where;
50	uint64_t when;
51
52#define INVALID -1UL	/* Indicates uninitialised offset value. */
53	uint64_t offset;
54};
55
56
57/* A staterecord contains the net state of
58 * sequentially parsing unwind descriptors.
59 * The entry state of the current prologue region
60 * is the exit state of the previous region.
61 * We record info about registers we care about
62 * ie; just enough to re-construct an unwind frame,
63 * and ignore the rest.
64 * Initial state is where = UNSAVED for all .where fields.
65 */
66
67struct staterecord {
68	struct regstate bsp;
69   	struct regstate psp;
70 	struct regstate rp;
71 	struct regstate pfs;
72};
73
74/* The unwind frame is a simpler version of the trap frame
75 * and contains a subset of preserved registers, which are
76 * useful in unwinding an ia64 stack frame.
77 * Keep this in sync with the staterecord. See: stackframe.c:updateregs()
78 */
79
80struct unwind_frame {
81	uint64_t		bsp;	/* Base of the RSE. */
82				    /* !!! XXX: Stack Frame discontinuities */
83	uint64_t		psp;	/* Mem stack (variable size) base. */
84	uint64_t		rp;	/* Return Pointer */
85	uint64_t		pfs;	/* Previous Frame size info */
86
87	/* Don't mirror anything below this line with struct staterecord */
88	uint64_t		sp;
89};
90
91
92void buildrecordchain(uint64_t, struct recordchain *);
93void initrecord(struct staterecord *);
94void modifyrecord(struct staterecord *, struct recordchain *, uint64_t);
95void pushrecord(struct staterecord *);
96void poprecord(struct staterecord *, int);
97void dump_staterecord(struct staterecord *);
98void clonerecordstack(u_int);
99void switchrecordstack(u_int);
100
101struct uwtable_ent *get_unwind_table_entry(uint64_t);
102void patchunwindframe(struct unwind_frame *, uint64_t, uint64_t);
103void updateregs(struct unwind_frame *uwf, struct staterecord *, uint64_t);
104struct uwtable_ent * get_unwind_table_entry(uint64_t ip);
105
106struct staterecord *buildrecordstack(struct recordchain *, uint64_t);
107void dump_recordchain(struct recordchain *);
108
109/* Convenience macros to decompose CFM & ar.pfs. */
110#define	IA64_CFM_SOF(x)		((x) & 0x7f)
111#define	IA64_CFM_SOL(x)		(((x) >> 7) & 0x7f)
112#define	IA64_CFM_SOR(x)		(((x) >> 14) & 0x0f)
113#define	IA64_CFM_RRB_GR(x)	(((x) >> 18) & 0x7f)
114#define	IA64_CFM_RRB_FR(x)	(((x) >> 25) & 0x7f)
115#define	IA64_CFM_RRB_PR(x)	(((x) >> 32) & 0x3f)
116
117#define IA64_RNATINDEX(x)	(((x) & 0x1f8) >> 3)
118
119/* Obeys Table 6:2 RSE Operation Instructions and State Modification */
120
121/* These functions adjust for RSE rnat saves to bsp in the forward and
122 * reverse directions respectively.
123 */
124#define ia64_rnat_adjust ia64_bsp_adjust_call
125
126static __inline uint64_t
127ia64_bsp_adjust_call(uint64_t bsp, int sol)
128{
129	bsp += ((sol + (IA64_RNATINDEX(bsp) + sol) / 63) << 3);
130	return bsp;
131}
132
133static __inline uint64_t
134ia64_bsp_adjust_ret(uint64_t bsp, int sol)
135{
136	bsp -= ((sol + (62 - IA64_RNATINDEX(bsp) + sol) / 63) << 3);
137	return bsp;
138}
139
140static __inline uint64_t
141ia64_getrse_gr(uint64_t bsp, uint64_t gr)
142{
143	bsp = ia64_bsp_adjust_call(bsp, gr);
144	return *(uint64_t *) bsp;
145}
146