1 // Inferno libmach/6.c
2 // http://code.google.com/p/inferno-os/source/browse/utils/libmach/6.c
3 //
4 // 	Copyright © 1994-1999 Lucent Technologies Inc.
5 // 	Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
6 // 	Portions Copyright © 1997-1999 Vita Nuova Limited.
7 // 	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
8 // 	Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
9 //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 // THE SOFTWARE.
28 
29 /*
30  * amd64 definition
31  */
32 #include <u.h>
33 #include <libc.h>
34 #include <bio.h>
35 #include <mach.h>
36 #include "uregamd64.h"
37 
38 	char	*i386excep(Map*, Regs*);
39 	int	i386foll(Map*, Regs*, u64int, u64int*);
40 	int	i386hexinst(Map*, u64int, char*, int);
41 	int	i386das(Map*, u64int, char, char*, int);
42 	int	i386instlen(Map*, u64int);
43 	int	i386unwind(Map*, Regs*, u64int*, Symbol*);
44 
45 #define	REGOFF(x)	offsetof(struct Ureg, x)
46 
47 #define	REGSIZE		sizeof(struct Ureg)
48 #define FP_CTLS(x)	(REGSIZE+2*(x))
49 #define FP_CTL(x)	(REGSIZE+4*(x))
50 #define FP_REG(x)	(FP_CTL(8)+16*(x))
51 #define XM_REG(x)	(FP_CTL(8)+8*16+16*(x))
52 
53 #define	FPREGSIZE	512	/* TO DO? currently only 0x1A0 used */
54 
55 static Regdesc amd64reglist[] = {
56 	{"AX",		REGOFF(ax),	RINT, 'Y'},
57 	{"BX",		REGOFF(bx),	RINT, 'Y'},
58 	{"CX",		REGOFF(cx),	RINT, 'Y'},
59 	{"DX",		REGOFF(dx),	RINT, 'Y'},
60 	{"SI",		REGOFF(si),	RINT, 'Y'},
61 	{"DI",		REGOFF(di),	RINT, 'Y'},
62 	{"BP",		REGOFF(bp),	RINT, 'Y'},
63 	{"R8",		REGOFF(r8),	RINT, 'Y'},
64 	{"R9",		REGOFF(r9),	RINT, 'Y'},
65 	{"R10",		REGOFF(r10),	RINT, 'Y'},
66 	{"R11",		REGOFF(r11),	RINT, 'Y'},
67 	{"R12",		REGOFF(r12),	RINT, 'Y'},
68 	{"R13",		REGOFF(r13),	RINT, 'Y'},
69 	{"R14",		REGOFF(r14),	RINT, 'Y'},
70 	{"R15",		REGOFF(r15),	RINT, 'Y'},
71 	{"DS",		REGOFF(ds),	RINT, 'x'},
72 	{"ES",		REGOFF(es),	RINT, 'x'},
73 	{"FS",		REGOFF(fs),	RINT, 'x'},
74 	{"GS",		REGOFF(gs),	RINT, 'x'},
75 	{"TYPE",	REGOFF(type), 	RINT, 'Y'},
76 	{"TRAP",	REGOFF(type), 	RINT, 'Y'},	/* alias for acid */
77 	{"ERROR",	REGOFF(error),	RINT, 'Y'},
78 	{"IP",		REGOFF(ip),	RINT, 'Y'},
79 	{"PC",		REGOFF(ip),	RINT, 'Y'},	/* alias for acid */
80 	{"CS",		REGOFF(cs),	RINT, 'Y'},
81 	{"FLAGS",	REGOFF(flags),	RINT, 'Y'},
82 	{"SP",		REGOFF(sp),	RINT, 'Y'},
83 	{"SS",		REGOFF(ss),	RINT, 'Y'},
84 
85 	{"FCW",		FP_CTLS(0),	RFLT, 'x'},
86 	{"FSW",		FP_CTLS(1),	RFLT, 'x'},
87 	{"FTW",		FP_CTLS(2),	RFLT, 'b'},
88 	{"FOP",		FP_CTLS(3),	RFLT, 'x'},
89 	{"RIP",		FP_CTL(2),	RFLT, 'Y'},
90 	{"RDP",		FP_CTL(4),	RFLT, 'Y'},
91 	{"MXCSR",	FP_CTL(6),	RFLT, 'X'},
92 	{"MXCSRMASK",	FP_CTL(7),	RFLT, 'X'},
93 	{"M0",		FP_REG(0),	RFLT, 'F'},	/* assumes double */
94 	{"M1",		FP_REG(1),	RFLT, 'F'},
95 	{"M2",		FP_REG(2),	RFLT, 'F'},
96 	{"M3",		FP_REG(3),	RFLT, 'F'},
97 	{"M4",		FP_REG(4),	RFLT, 'F'},
98 	{"M5",		FP_REG(5),	RFLT, 'F'},
99 	{"M6",		FP_REG(6),	RFLT, 'F'},
100 	{"M7",		FP_REG(7),	RFLT, 'F'},
101 	{"X0",		XM_REG(0),	RFLT, 'F'},	/* assumes double */
102 	{"X1",		XM_REG(1),	RFLT, 'F'},
103 	{"X2",		XM_REG(2),	RFLT, 'F'},
104 	{"X3",		XM_REG(3),	RFLT, 'F'},
105 	{"X4",		XM_REG(4),	RFLT, 'F'},
106 	{"X5",		XM_REG(5),	RFLT, 'F'},
107 	{"X6",		XM_REG(6),	RFLT, 'F'},
108 	{"X7",		XM_REG(7),	RFLT, 'F'},
109 	{"X8",		XM_REG(8),	RFLT, 'F'},
110 	{"X9",		XM_REG(9),	RFLT, 'F'},
111 	{"X10",		XM_REG(10),	RFLT, 'F'},
112 	{"X11",		XM_REG(11),	RFLT, 'F'},
113 	{"X12",		XM_REG(12),	RFLT, 'F'},
114 	{"X13",		XM_REG(13),	RFLT, 'F'},
115 	{"X14",		XM_REG(14),	RFLT, 'F'},
116 	{"X15",		XM_REG(15),	RFLT, 'F'},
117 	{"X16",		XM_REG(16),	RFLT, 'F'},
118 /*
119 	{"F0",		FP_REG(7),	RFLT, '3'},
120 	{"F1",		FP_REG(6),	RFLT, '3'},
121 	{"F2",		FP_REG(5),	RFLT, '3'},
122 	{"F3",		FP_REG(4),	RFLT, '3'},
123 	{"F4",		FP_REG(3),	RFLT, '3'},
124 	{"F5",		FP_REG(2),	RFLT, '3'},
125 	{"F6",		FP_REG(1),	RFLT, '3'},
126 	{"F7",		FP_REG(0),	RFLT, '3'},
127 */
128 	{  0 }
129 };
130 
131 static char *amd64windregs[] = {
132 	"PC",
133 	"SP",
134 	"BP",
135 	"AX",
136 	"CX",
137 	"DX",
138 	"BX",
139 	"SI",
140 	"DI",
141 	"R8",
142 	"R9",
143 	"R10",
144 	"R11",
145 	"R12",
146 	"R13",
147 	"R14",
148 	"R15",
149 	0,
150 };
151 
152 
153 Mach machamd64=
154 {
155 	"amd64",
156 	MAMD64,			/* machine type */
157 	amd64reglist,		/* register list */
158 	REGSIZE,		/* size of registers in bytes */
159 	FPREGSIZE,		/* size of fp registers in bytes */
160 	"PC",			/* name of PC */
161 	"SP",			/* name of SP */
162 	"BP",			/* name of FP */
163 	0,			/* link register */
164 	"setSB",		/* static base register name (bogus anyways) */
165 	0,			/* static base register value */
166 	0x1000,			/* page size */
167 	0xFFFFFFFF80110000ULL,	/* kernel base */
168 	0xFFFF800000000000ULL,	/* kernel text mask */
169 	1,			/* quantization of pc */
170 	8,			/* szaddr */
171 	4,			/* szreg */
172 	4,			/* szfloat */
173 	8,			/* szdouble */
174 
175 	amd64windregs,	/* locations unwound in stack trace */
176 	17,
177 
178 	{0xCC, 0, 0, 0},	/* break point: INT 3 */
179 	1,			/* break point size */
180 
181 	i386foll,		/* following addresses */
182 	i386excep,		/* print exception */
183 	i386unwind,		/* stack unwind */
184 
185 	leswap2,			/* convert short to local byte order */
186 	leswap4,			/* convert long to local byte order */
187 	leswap8,			/* convert vlong to local byte order */
188 	leieeeftoa32,		/* single precision float pointer */
189 	leieeeftoa64,		/* double precision float pointer */
190 	leieeeftoa80,		/* long double precision floating point */
191 
192 	i386das,		/* dissembler */
193 	i386das,		/* plan9-format disassembler */
194 	0,			/* commercial disassembler */
195 	i386hexinst,		/* print instruction */
196 	i386instlen,		/* instruction size calculation */
197 };
198