Revision e6dbd3b3 target-m68k/translate.c
b/target-m68k/translate.c | ||
---|---|---|
42 | 42 |
|
43 | 43 |
/* internal defines */ |
44 | 44 |
typedef struct DisasContext { |
45 |
CPUM68KState *env; |
|
45 | 46 |
target_ulong pc; |
46 | 47 |
int is_jmp; |
47 | 48 |
int cc_op; |
... | ... | |
198 | 199 |
} |
199 | 200 |
} |
200 | 201 |
|
202 |
/* Read a 32-bit immediate constant. */ |
|
203 |
static inline uint32_t read_im32(DisasContext *s) |
|
204 |
{ |
|
205 |
uint32_t im; |
|
206 |
im = ((uint32_t)lduw_code(s->pc)) << 16; |
|
207 |
s->pc += 2; |
|
208 |
im |= lduw_code(s->pc); |
|
209 |
s->pc += 2; |
|
210 |
return im; |
|
211 |
} |
|
212 |
|
|
213 |
/* Calculate and address index. */ |
|
214 |
static int gen_addr_index(uint16_t ext, int tmp) |
|
215 |
{ |
|
216 |
int add; |
|
217 |
int scale; |
|
218 |
|
|
219 |
add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12); |
|
220 |
if ((ext & 0x800) == 0) { |
|
221 |
gen_op_ext16s32(tmp, add); |
|
222 |
add = tmp; |
|
223 |
} |
|
224 |
scale = (ext >> 9) & 3; |
|
225 |
if (scale != 0) { |
|
226 |
gen_op_shl32(tmp, add, gen_im32(scale)); |
|
227 |
add = tmp; |
|
228 |
} |
|
229 |
return add; |
|
230 |
} |
|
231 |
|
|
201 | 232 |
/* Handle a base + index + displacement effective addresss. A base of |
202 | 233 |
-1 means pc-relative. */ |
203 | 234 |
static int gen_lea_indexed(DisasContext *s, int opsize, int base) |
204 | 235 |
{ |
205 |
int scale; |
|
206 | 236 |
uint32_t offset; |
207 | 237 |
uint16_t ext; |
208 | 238 |
int add; |
209 | 239 |
int tmp; |
240 |
uint32_t bd, od; |
|
210 | 241 |
|
211 | 242 |
offset = s->pc; |
212 | 243 |
ext = lduw_code(s->pc); |
213 | 244 |
s->pc += 2; |
214 |
tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0); |
|
215 |
/* ??? Check W/L bit. */ |
|
216 |
scale = (ext >> 9) & 3; |
|
217 |
if (scale == 0) { |
|
218 |
add = tmp; |
|
219 |
} else { |
|
220 |
add = gen_new_qreg(QMODE_I32); |
|
221 |
gen_op_shl32(add, tmp, gen_im32(scale)); |
|
222 |
} |
|
223 |
tmp = gen_new_qreg(QMODE_I32); |
|
224 |
if (base != -1) { |
|
225 |
gen_op_add32(tmp, base, gen_im32((int8_t)ext)); |
|
226 |
gen_op_add32(tmp, tmp, add); |
|
245 |
|
|
246 |
if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX)) |
|
247 |
return -1; |
|
248 |
|
|
249 |
if (ext & 0x100) { |
|
250 |
/* full extension word format */ |
|
251 |
if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL)) |
|
252 |
return -1; |
|
253 |
|
|
254 |
if ((ext & 0x30) > 0x10) { |
|
255 |
/* base displacement */ |
|
256 |
if ((ext & 0x30) == 0x20) { |
|
257 |
bd = (int16_t)lduw_code(s->pc); |
|
258 |
s->pc += 2; |
|
259 |
} else { |
|
260 |
bd = read_im32(s); |
|
261 |
} |
|
262 |
} else { |
|
263 |
bd = 0; |
|
264 |
} |
|
265 |
tmp = gen_new_qreg(QMODE_I32); |
|
266 |
if ((ext & 0x44) == 0) { |
|
267 |
/* pre-index */ |
|
268 |
add = gen_addr_index(ext, tmp); |
|
269 |
} else { |
|
270 |
add = QREG_NULL; |
|
271 |
} |
|
272 |
if ((ext & 0x80) == 0) { |
|
273 |
/* base not suppressed */ |
|
274 |
if (base == -1) { |
|
275 |
base = gen_im32(offset + bd); |
|
276 |
bd = 0; |
|
277 |
} |
|
278 |
if (add) { |
|
279 |
gen_op_add32(tmp, add, base); |
|
280 |
add = tmp; |
|
281 |
} else { |
|
282 |
add = base; |
|
283 |
} |
|
284 |
} |
|
285 |
if (add) { |
|
286 |
if (bd != 0) { |
|
287 |
gen_op_add32(tmp, add, gen_im32(bd)); |
|
288 |
add = tmp; |
|
289 |
} |
|
290 |
} else { |
|
291 |
add = gen_im32(bd); |
|
292 |
} |
|
293 |
if ((ext & 3) != 0) { |
|
294 |
/* memory indirect */ |
|
295 |
base = gen_load(s, OS_LONG, add, 0); |
|
296 |
if ((ext & 0x44) == 4) { |
|
297 |
add = gen_addr_index(ext, tmp); |
|
298 |
gen_op_add32(tmp, add, base); |
|
299 |
add = tmp; |
|
300 |
} else { |
|
301 |
add = base; |
|
302 |
} |
|
303 |
if ((ext & 3) > 1) { |
|
304 |
/* outer displacement */ |
|
305 |
if ((ext & 3) == 2) { |
|
306 |
od = (int16_t)lduw_code(s->pc); |
|
307 |
s->pc += 2; |
|
308 |
} else { |
|
309 |
od = read_im32(s); |
|
310 |
} |
|
311 |
} else { |
|
312 |
od = 0; |
|
313 |
} |
|
314 |
if (od != 0) { |
|
315 |
gen_op_add32(add, tmp, gen_im32(od)); |
|
316 |
add = tmp; |
|
317 |
} |
|
318 |
} |
|
227 | 319 |
} else { |
228 |
gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext)); |
|
320 |
/* brief extension word format */ |
|
321 |
tmp = gen_new_qreg(QMODE_I32); |
|
322 |
add = gen_addr_index(ext, tmp); |
|
323 |
if (base != -1) { |
|
324 |
gen_op_add32(tmp, add, base); |
|
325 |
if ((int8_t)ext) |
|
326 |
gen_op_add32(tmp, tmp, gen_im32((int8_t)ext)); |
|
327 |
} else { |
|
328 |
gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext)); |
|
329 |
} |
|
330 |
add = tmp; |
|
229 | 331 |
} |
230 |
return tmp; |
|
231 |
} |
|
232 |
|
|
233 |
/* Read a 32-bit immediate constant. */ |
|
234 |
static inline uint32_t read_im32(DisasContext *s) |
|
235 |
{ |
|
236 |
uint32_t im; |
|
237 |
im = ((uint32_t)lduw_code(s->pc)) << 16; |
|
238 |
s->pc += 2; |
|
239 |
im |= lduw_code(s->pc); |
|
240 |
s->pc += 2; |
|
241 |
return im; |
|
332 |
return add; |
|
242 | 333 |
} |
243 | 334 |
|
244 |
|
|
245 | 335 |
/* Update the CPU env CC_OP state. */ |
246 | 336 |
static inline void gen_flush_cc_op(DisasContext *s) |
247 | 337 |
{ |
... | ... | |
2721 | 2811 |
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
2722 | 2812 |
gen_opparam_ptr = gen_opparam_buf; |
2723 | 2813 |
|
2814 |
dc->env = env; |
|
2724 | 2815 |
dc->is_jmp = DISAS_NEXT; |
2725 | 2816 |
dc->pc = pc_start; |
2726 | 2817 |
dc->cc_op = CC_OP_DYNAMIC; |
Also available in: Unified diff