1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 
6 int
locfmt(Fmt * fmt)7 locfmt(Fmt *fmt)
8 {
9 	Loc l;
10 
11 	l = va_arg(fmt->args, Loc);
12 	switch(l.type){
13 	default:
14 		return fmtprint(fmt, "<loc%d>", l.type);
15 	case LCONST:
16 		return fmtprint(fmt, "0x%lux", l.addr);
17 	case LADDR:
18 		return fmtprint(fmt, "*0x%lux", l.addr);
19 	case LOFFSET:
20 		return fmtprint(fmt, "%ld(%s)", l.offset, l.reg);
21 	case LREG:
22 		return fmtprint(fmt, "%s", l.reg);
23 	}
24 }
25 
26 int
loccmp(Loc * a,Loc * b)27 loccmp(Loc *a, Loc *b)
28 {
29 	int i;
30 
31 	if(a->type < b->type)
32 		return -1;
33 	if(a->type > b->type)
34 		return 1;
35 	switch(a->type){
36 	default:
37 		return 0;
38 	case LADDR:
39 		if(a->addr < b->addr)
40 			return -1;
41 		if(a->addr > b->addr)
42 			return 1;
43 		return 0;
44 	case LOFFSET:
45 		i = strcmp(a->reg, b->reg);
46 		if(i != 0)
47 			return i;
48 		if(a->offset < b->offset)
49 			return -1;
50 		if(a->offset > b->offset)
51 			return 1;
52 		return 0;
53 	case LREG:
54 		return strcmp(a->reg, b->reg);
55 	}
56 }
57 
58 int
lget1(Map * map,Regs * regs,Loc loc,uchar * a,uint n)59 lget1(Map *map, Regs *regs, Loc loc, uchar *a, uint n)
60 {
61 	if(locsimplify(map, regs, loc, &loc) < 0)
62 		return -1;
63 	if(loc.type == LADDR)
64 		return get1(map, loc.addr, a, n);
65 	/* could do more here - i'm lazy */
66 	werrstr("bad location for lget1");
67 	return -1;
68 }
69 
70 int
lget2(Map * map,Regs * regs,Loc loc,u16int * u)71 lget2(Map *map, Regs *regs, Loc loc, u16int *u)
72 {
73 	u64int ul;
74 
75 	if(locsimplify(map, regs, loc, &loc) < 0)
76 		return -1;
77 	if(loc.type == LADDR)
78 		return get2(map, loc.addr, u);
79 	if(loc.type == LCONST){
80 		*u = loc.addr;
81 		return 0;
82 	}
83 	if(loc.type == LREG){
84 		if(rget(regs, loc.reg, &ul) < 0)
85 			return -1;
86 		*u = ul;
87 		return 0;
88 	}
89 	werrstr("bad location for lget2");
90 	return -1;
91 }
92 
93 int
lget4(Map * map,Regs * regs,Loc loc,u32int * u)94 lget4(Map *map, Regs *regs, Loc loc, u32int *u)
95 {
96 	u64int ul;
97 
98 	if(locsimplify(map, regs, loc, &loc) < 0)
99 		return -1;
100 	if(loc.type == LADDR)
101 		return get4(map, loc.addr, u);
102 	if(loc.type == LCONST){
103 		*u = loc.addr;
104 		return 0;
105 	}
106 	if(loc.type == LREG){
107 		if(rget(regs, loc.reg, &ul) < 0)
108 			return -1;
109 		*u = ul;
110 		return 0;
111 	}
112 	werrstr("bad location for lget4");
113 	return -1;
114 }
115 
116 int
lgeta(Map * map,Regs * regs,Loc loc,u64int * u)117 lgeta(Map *map, Regs *regs, Loc loc, u64int *u)
118 {
119 	u32int v;
120 
121 	if(machcpu == &machamd64)
122 		return lget8(map, regs, loc, u);
123 	if(lget4(map, regs, loc, &v) < 0)
124 		return -1;
125 	*u = v;
126 	return 4;
127 }
128 
129 int
lget8(Map * map,Regs * regs,Loc loc,u64int * u)130 lget8(Map *map, Regs *regs, Loc loc, u64int *u)
131 {
132 	u64int ul;
133 
134 	if(locsimplify(map, regs, loc, &loc) < 0)
135 		return -1;
136 	if(loc.type == LADDR)
137 		return get8(map, loc.addr, u);
138 	if(loc.type == LCONST){
139 		*u = loc.addr;
140 		return 0;
141 	}
142 	if(loc.type == LREG){
143 		if(rget(regs, loc.reg, &ul) < 0)
144 			return -1;
145 		*u = ul;
146 		return 0;
147 	}
148 	werrstr("bad location for lget8");
149 	return -1;
150 }
151 
152 int
lput1(Map * map,Regs * regs,Loc loc,uchar * a,uint n)153 lput1(Map *map, Regs *regs, Loc loc, uchar *a, uint n)
154 {
155 	if(locsimplify(map, regs, loc, &loc) < 0)
156 		return -1;
157 	if(loc.type == LADDR)
158 		return put1(map, loc.addr, a, n);
159 	/* could do more here - i'm lazy */
160 	werrstr("bad location for lput1");
161 	return -1;
162 }
163 
164 int
lput2(Map * map,Regs * regs,Loc loc,u16int u)165 lput2(Map *map, Regs *regs, Loc loc, u16int u)
166 {
167 	if(locsimplify(map, regs, loc, &loc) < 0)
168 		return -1;
169 	if(loc.type == LADDR)
170 		return put2(map, loc.addr, u);
171 	if(loc.type == LREG)
172 		return rput(regs, loc.reg, u);
173 	werrstr("bad location for lput2");
174 	return -1;
175 }
176 
177 int
lput4(Map * map,Regs * regs,Loc loc,u32int u)178 lput4(Map *map, Regs *regs, Loc loc, u32int u)
179 {
180 	if(locsimplify(map, regs, loc, &loc) < 0)
181 		return -1;
182 	if(loc.type == LADDR)
183 		return put4(map, loc.addr, u);
184 	if(loc.type == LREG)
185 		return rput(regs, loc.reg, u);
186 	werrstr("bad location for lput4");
187 	return -1;
188 }
189 
190 int
lput8(Map * map,Regs * regs,Loc loc,u64int u)191 lput8(Map *map, Regs *regs, Loc loc, u64int u)
192 {
193 	if(locsimplify(map, regs, loc, &loc) < 0)
194 		return -1;
195 	if(loc.type == LADDR)
196 		return put8(map, loc.addr, u);
197 	if(loc.type == LREG)
198 		return rput(regs, loc.reg, u);
199 	werrstr("bad location for lput8");
200 	return -1;
201 }
202 
203 static Loc zl;
204 
205 Loc
locaddr(u64int addr)206 locaddr(u64int addr)
207 {
208 	Loc l;
209 
210 	l = zl;
211 	l.type = LADDR;
212 	l.addr = addr;
213 	return l;
214 }
215 
216 Loc
locindir(char * reg,long offset)217 locindir(char *reg, long offset)
218 {
219 	Loc l;
220 
221 	l = zl;
222 	l.type = LOFFSET;
223 	l.reg = reg;
224 	l.offset = offset;
225 	l.addr = 0;	/* SHUT UP GCC 4.0 */
226 	return l;
227 }
228 
229 Loc
locconst(u64int con)230 locconst(u64int con)
231 {
232 	Loc l;
233 
234 	l = zl;
235 	l.type = LCONST;
236 	l.addr = con;
237 	return l;
238 }
239 
240 Loc
locnone(void)241 locnone(void)
242 {
243 	Loc l;
244 
245 	l = zl;
246 	l.type = LNONE;
247 	return l;
248 }
249 
250 Loc
locreg(char * reg)251 locreg(char *reg)
252 {
253 	Loc l;
254 
255 	l = zl;
256 	l.type = LREG;
257 	l.reg = reg;
258 	return l;
259 }
260 
261 int
locsimplify(Map * map,Regs * regs,Loc loc,Loc * newloc)262 locsimplify(Map *map, Regs *regs, Loc loc, Loc *newloc)
263 {
264 	u64int u;
265 
266 	if(loc.type == LOFFSET){
267 		if(rget(regs, loc.reg, &u) < 0)
268 			return -1;
269 		*newloc = locaddr(u + loc.offset);
270 	}else
271 		*newloc = loc;
272 	return 0;
273 }
274