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