Mercurial > repos > blastem
comparison m68k_core_x86.c @ 682:7ed1dbb48f61
Merge
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 04 Jan 2015 23:35:55 -0800 |
parents | m68k_to_x86.c@666adeba5a61 m68k_to_x86.c@30ccf56842d6 |
children | 8cb61671777b |
comparison
equal
deleted
inserted
replaced
681:e26640daf1ae | 682:7ed1dbb48f61 |
---|---|
214 | 214 |
215 void dreg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg) | 215 void dreg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg) |
216 { | 216 { |
217 if (opts->dregs[reg] >= 0) { | 217 if (opts->dregs[reg] >= 0) { |
218 movsx_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_W, SZ_D); | 218 movsx_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_W, SZ_D); |
219 } else { | 219 } else { |
220 movsx_rdispr(&opts->gen.code, opts->gen.context_reg, dreg_offset(reg), native_reg, SZ_W, SZ_D); | 220 movsx_rdispr(&opts->gen.code, opts->gen.context_reg, dreg_offset(reg), native_reg, SZ_W, SZ_D); |
221 } | 221 } |
222 } | 222 } |
223 | 223 |
224 void native_to_areg(m68k_options *opts, uint8_t native_reg, uint8_t reg) | 224 void native_to_areg(m68k_options *opts, uint8_t native_reg, uint8_t reg) |
225 { | 225 { |
226 if (opts->aregs[reg] >= 0) { | 226 if (opts->aregs[reg] >= 0) { |
227 mov_rr(&opts->gen.code, native_reg, opts->aregs[reg], SZ_D); | 227 mov_rr(&opts->gen.code, native_reg, opts->aregs[reg], SZ_D); |
228 } else { | 228 } else { |
229 mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, areg_offset(reg), SZ_D); | 229 mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, areg_offset(reg), SZ_D); |
230 } | 230 } |
231 } | 231 } |
232 | 232 |
233 void native_to_dreg(m68k_options *opts, uint8_t native_reg, uint8_t reg) | 233 void native_to_dreg(m68k_options *opts, uint8_t native_reg, uint8_t reg) |
234 { | 234 { |
235 if (opts->dregs[reg] >= 0) { | 235 if (opts->dregs[reg] >= 0) { |
236 mov_rr(&opts->gen.code, native_reg, opts->dregs[reg], SZ_D); | 236 mov_rr(&opts->gen.code, native_reg, opts->dregs[reg], SZ_D); |
237 } else { | 237 } else { |
238 mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, dreg_offset(reg), SZ_D); | 238 mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, dreg_offset(reg), SZ_D); |
239 } | 239 } |
240 } | 240 } |
241 | 241 |
242 void ldi_areg(m68k_options *opts, int32_t value, uint8_t reg) | 242 void ldi_areg(m68k_options *opts, int32_t value, uint8_t reg) |
243 { | 243 { |
244 if (opts->aregs[reg] >= 0) { | 244 if (opts->aregs[reg] >= 0) { |
245 mov_ir(&opts->gen.code, value, opts->aregs[reg], SZ_D); | 245 mov_ir(&opts->gen.code, value, opts->aregs[reg], SZ_D); |
246 } else { | 246 } else { |
247 mov_irdisp(&opts->gen.code, value, opts->gen.context_reg, areg_offset(reg), SZ_D); | 247 mov_irdisp(&opts->gen.code, value, opts->gen.context_reg, areg_offset(reg), SZ_D); |
248 } | 248 } |
249 } | 249 } |
250 | 250 |
251 void ldi_native(m68k_options *opts, int32_t value, uint8_t reg) | 251 void ldi_native(m68k_options *opts, int32_t value, uint8_t reg) |
252 { | 252 { |
253 mov_ir(&opts->gen.code, value, reg, SZ_D); | 253 mov_ir(&opts->gen.code, value, reg, SZ_D); |
254 } | 254 } |
255 | 255 |
256 void addi_native(m68k_options *opts, int32_t value, uint8_t reg) | 256 void addi_native(m68k_options *opts, int32_t value, uint8_t reg) |
257 { | 257 { |
258 add_ir(&opts->gen.code, value, reg, SZ_D); | 258 add_ir(&opts->gen.code, value, reg, SZ_D); |
259 } | 259 } |
260 | 260 |
261 void subi_native(m68k_options *opts, int32_t value, uint8_t reg) | 261 void subi_native(m68k_options *opts, int32_t value, uint8_t reg) |
262 { | 262 { |
263 sub_ir(&opts->gen.code, value, reg, SZ_D); | 263 sub_ir(&opts->gen.code, value, reg, SZ_D); |
264 } | 264 } |
265 | 265 |
266 void push_native(m68k_options *opts, uint8_t reg) | 266 void push_native(m68k_options *opts, uint8_t reg) |
267 { | 267 { |
268 push_r(&opts->gen.code, reg); | 268 push_r(&opts->gen.code, reg); |
269 } | 269 } |
270 | 270 |
271 void pop_native(m68k_options *opts, uint8_t reg) | 271 void pop_native(m68k_options *opts, uint8_t reg) |
272 { | 272 { |
273 pop_r(&opts->gen.code, reg); | 273 pop_r(&opts->gen.code, reg); |
274 } | 274 } |
275 | 275 |
276 void sign_extend16_native(m68k_options *opts, uint8_t reg) | 276 void sign_extend16_native(m68k_options *opts, uint8_t reg) |
277 { | 277 { |
278 movsx_rr(&opts->gen.code, reg, reg, SZ_W, SZ_D); | 278 movsx_rr(&opts->gen.code, reg, reg, SZ_W, SZ_D); |
279 } | 279 } |
280 | 280 |
281 void addi_areg(m68k_options *opts, int32_t val, uint8_t reg) | 281 void addi_areg(m68k_options *opts, int32_t val, uint8_t reg) |
282 { | 282 { |
283 if (opts->aregs[reg] >= 0) { | 283 if (opts->aregs[reg] >= 0) { |
284 add_ir(&opts->gen.code, val, opts->aregs[reg], SZ_D); | 284 add_ir(&opts->gen.code, val, opts->aregs[reg], SZ_D); |
285 } else { | 285 } else { |
286 add_irdisp(&opts->gen.code, val, opts->gen.context_reg, areg_offset(reg), SZ_D); | 286 add_irdisp(&opts->gen.code, val, opts->gen.context_reg, areg_offset(reg), SZ_D); |
287 } | 287 } |
288 } | 288 } |
289 | 289 |
290 void subi_areg(m68k_options *opts, int32_t val, uint8_t reg) | 290 void subi_areg(m68k_options *opts, int32_t val, uint8_t reg) |
291 { | 291 { |
292 if (opts->aregs[reg] >= 0) { | 292 if (opts->aregs[reg] >= 0) { |
293 sub_ir(&opts->gen.code, val, opts->aregs[reg], SZ_D); | 293 sub_ir(&opts->gen.code, val, opts->aregs[reg], SZ_D); |
294 } else { | 294 } else { |
295 sub_irdisp(&opts->gen.code, val, opts->gen.context_reg, areg_offset(reg), SZ_D); | 295 sub_irdisp(&opts->gen.code, val, opts->gen.context_reg, areg_offset(reg), SZ_D); |
296 } | 296 } |
297 } | 297 } |
298 | 298 |
299 void add_areg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg) | 299 void add_areg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg) |
300 { | 300 { |
301 if (opts->aregs[reg] >= 0) { | 301 if (opts->aregs[reg] >= 0) { |
302 add_rr(&opts->gen.code, opts->aregs[reg], native_reg, SZ_D); | 302 add_rr(&opts->gen.code, opts->aregs[reg], native_reg, SZ_D); |
303 } else { | 303 } else { |
304 add_rdispr(&opts->gen.code, opts->gen.context_reg, areg_offset(reg), native_reg, SZ_D); | 304 add_rdispr(&opts->gen.code, opts->gen.context_reg, areg_offset(reg), native_reg, SZ_D); |
305 } | 305 } |
306 } | 306 } |
307 | 307 |
308 void add_dreg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg) | 308 void add_dreg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg) |
309 { | 309 { |
310 if (opts->dregs[reg] >= 0) { | 310 if (opts->dregs[reg] >= 0) { |
311 add_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_D); | 311 add_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_D); |
312 } else { | 312 } else { |
313 add_rdispr(&opts->gen.code, opts->gen.context_reg, dreg_offset(reg), native_reg, SZ_D); | 313 add_rdispr(&opts->gen.code, opts->gen.context_reg, dreg_offset(reg), native_reg, SZ_D); |
314 } | 314 } |
315 } | 315 } |
316 | 316 |
317 void calc_areg_displace(m68k_options *opts, m68k_op_info *op, uint8_t native_reg) | 317 void calc_areg_displace(m68k_options *opts, m68k_op_info *op, uint8_t native_reg) |
318 { | 318 { |
319 areg_to_native(opts, op->params.regs.pri, native_reg); | 319 areg_to_native(opts, op->params.regs.pri, native_reg); |
320 add_ir(&opts->gen.code, op->params.regs.displacement, native_reg, SZ_D); | 320 add_ir(&opts->gen.code, op->params.regs.displacement, native_reg, SZ_D); |
321 } | 321 } |
322 | 322 |
323 void calc_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg) | 323 void calc_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg) |
324 { | 324 { |
325 uint8_t sec_reg = (op->params.regs.sec >> 1) & 0x7; | 325 uint8_t sec_reg = (op->params.regs.sec >> 1) & 0x7; |
326 if (op->params.regs.sec & 1) { | 326 if (op->params.regs.sec & 1) { |
327 if (op->params.regs.sec & 0x10) { | 327 if (op->params.regs.sec & 0x10) { |
328 add_areg_native(opts, sec_reg, native_reg); | 328 add_areg_native(opts, sec_reg, native_reg); |
329 } else { | 329 } else { |
330 add_dreg_native(opts, sec_reg, native_reg); | 330 add_dreg_native(opts, sec_reg, native_reg); |
331 } | 331 } |
332 } else { | 332 } else { |
333 uint8_t other_reg = native_reg == opts->gen.scratch1 ? opts->gen.scratch2 : opts->gen.scratch1; | 333 uint8_t other_reg = native_reg == opts->gen.scratch1 ? opts->gen.scratch2 : opts->gen.scratch1; |
334 if (op->params.regs.sec & 0x10) { | 334 if (op->params.regs.sec & 0x10) { |
335 areg_to_native_sx(opts, sec_reg, other_reg); | 335 areg_to_native_sx(opts, sec_reg, other_reg); |
336 } else { | 336 } else { |
337 dreg_to_native_sx(opts, sec_reg, other_reg); | 337 dreg_to_native_sx(opts, sec_reg, other_reg); |
338 } | 338 } |
339 add_rr(&opts->gen.code, other_reg, native_reg, SZ_D); | 339 add_rr(&opts->gen.code, other_reg, native_reg, SZ_D); |
340 } | 340 } |
341 if (op->params.regs.displacement) { | 341 if (op->params.regs.displacement) { |
342 add_ir(&opts->gen.code, op->params.regs.displacement, native_reg, SZ_D); | 342 add_ir(&opts->gen.code, op->params.regs.displacement, native_reg, SZ_D); |
343 } | 343 } |
344 } | 344 } |
345 | 345 |
346 void calc_areg_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg) | 346 void calc_areg_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg) |
347 { | 347 { |
348 areg_to_native(opts, op->params.regs.pri, native_reg); | 348 areg_to_native(opts, op->params.regs.pri, native_reg); |
349 calc_index_disp8(opts, op, native_reg); | 349 calc_index_disp8(opts, op, native_reg); |
350 } | 350 } |
351 | 351 |
352 void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst) | 352 void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst) |
353 { | 353 { |
354 code_info *code = &opts->gen.code; | 354 code_info *code = &opts->gen.code; |
355 m68k_op_info *op = dst ? &inst->dst : &inst->src; | 355 m68k_op_info *op = dst ? &inst->dst : &inst->src; |
356 int8_t reg = native_reg(op, opts); | 356 int8_t reg = native_reg(op, opts); |
357 uint8_t sec_reg; | 357 uint8_t sec_reg; |
358 int32_t dec_amount,inc_amount; | 358 int32_t dec_amount, inc_amount; |
359 if (reg >= 0) { | 359 if (reg >= 0) { |
360 ea->mode = MODE_REG_DIRECT; | 360 ea->mode = MODE_REG_DIRECT; |
361 if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { | 361 if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { |
362 movsx_rr(code, reg, opts->gen.scratch1, SZ_W, SZ_D); | 362 movsx_rr(code, reg, opts->gen.scratch1, SZ_W, SZ_D); |
363 ea->base = opts->gen.scratch1; | 363 ea->base = opts->gen.scratch1; |
364 } else { | 364 } else { |
365 ea->base = reg; | 365 ea->base = reg; |
366 } | 366 } |
367 return; | 367 return; |
368 } | 368 } |
369 switch (op->addr_mode) | 369 switch (op->addr_mode) |
370 { | 370 { |
371 case MODE_REG: | 371 case MODE_REG: |
373 //We only get one memory parameter, so if the dst operand is a register in memory, | 373 //We only get one memory parameter, so if the dst operand is a register in memory, |
374 //we need to copy this to a temp register first if we're translating the src operand | 374 //we need to copy this to a temp register first if we're translating the src operand |
375 if (dst || native_reg(&(inst->dst), opts) >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) | 375 if (dst || native_reg(&(inst->dst), opts) >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) |
376 || inst->op == M68K_EXG) { | 376 || inst->op == M68K_EXG) { |
377 | 377 |
378 ea->mode = MODE_REG_DISPLACE8; | 378 ea->mode = MODE_REG_DISPLACE8; |
379 ea->base = opts->gen.context_reg; | 379 ea->base = opts->gen.context_reg; |
380 ea->disp = reg_offset(op); | 380 ea->disp = reg_offset(op); |
381 } else { | 381 } else { |
382 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { | 382 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { |
383 movsx_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, SZ_W, SZ_D); | 383 movsx_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, SZ_W, SZ_D); |
403 case MODE_AREG_POSTINC: | 403 case MODE_AREG_POSTINC: |
404 areg_to_native(opts, op->params.regs.pri, opts->gen.scratch1); | 404 areg_to_native(opts, op->params.regs.pri, opts->gen.scratch1); |
405 m68k_read_size(opts, inst->extra.size); | 405 m68k_read_size(opts, inst->extra.size); |
406 | 406 |
407 if (dst) { | 407 if (dst) { |
408 if (inst->src.addr_mode == MODE_AREG_PREDEC) { | 408 if (inst->src.addr_mode == MODE_AREG_PREDEC) { |
409 //restore src operand to opts->gen.scratch2 | 409 //restore src operand to opts->gen.scratch2 |
410 pop_r(code, opts->gen.scratch2); | 410 pop_r(code, opts->gen.scratch2); |
411 } else { | 411 } else { |
412 //save reg value in opts->gen.scratch2 so we can use it to save the result in memory later | 412 //save reg value in opts->gen.scratch2 so we can use it to save the result in memory later |
413 areg_to_native(opts, op->params.regs.pri, opts->gen.scratch2); | 413 areg_to_native(opts, op->params.regs.pri, opts->gen.scratch2); |
414 } | 414 } |
415 } | 415 } |
416 | 416 |
428 push_r(code, opts->gen.scratch1); | 428 push_r(code, opts->gen.scratch1); |
429 } | 429 } |
430 m68k_read_size(opts, inst->extra.size); | 430 m68k_read_size(opts, inst->extra.size); |
431 if (dst) { | 431 if (dst) { |
432 pop_r(code, opts->gen.scratch2); | 432 pop_r(code, opts->gen.scratch2); |
433 } | 433 } |
434 | 434 |
435 ea->mode = MODE_REG_DIRECT; | 435 ea->mode = MODE_REG_DIRECT; |
436 ea->base = opts->gen.scratch1; | 436 ea->base = opts->gen.scratch1; |
437 break; | 437 break; |
438 case MODE_AREG_INDEX_DISP8: | 438 case MODE_AREG_INDEX_DISP8: |
442 push_r(code, opts->gen.scratch1); | 442 push_r(code, opts->gen.scratch1); |
443 } | 443 } |
444 m68k_read_size(opts, inst->extra.size); | 444 m68k_read_size(opts, inst->extra.size); |
445 if (dst) { | 445 if (dst) { |
446 pop_r(code, opts->gen.scratch2); | 446 pop_r(code, opts->gen.scratch2); |
447 } | 447 } |
448 | 448 |
449 ea->mode = MODE_REG_DIRECT; | 449 ea->mode = MODE_REG_DIRECT; |
450 ea->base = opts->gen.scratch1; | 450 ea->base = opts->gen.scratch1; |
451 break; | 451 break; |
452 case MODE_PC_DISPLACE: | 452 case MODE_PC_DISPLACE: |
453 cycles(&opts->gen, BUS); | 453 cycles(&opts->gen, BUS); |
454 mov_ir(code, op->params.regs.displacement + inst->address+2, opts->gen.scratch1, SZ_D); | 454 mov_ir(code, op->params.regs.displacement + inst->address+2, opts->gen.scratch1, SZ_D); |
455 if (dst) { | 455 if (dst) { |
456 push_r(code, opts->gen.scratch1); | 456 push_r(code, opts->gen.scratch1); |
457 } | 457 } |
458 m68k_read_size(opts, inst->extra.size); | 458 m68k_read_size(opts, inst->extra.size); |
459 if (dst) { | 459 if (dst) { |
460 pop_r(code, opts->gen.scratch2); | 460 pop_r(code, opts->gen.scratch2); |
461 } | 461 } |
462 | 462 |
467 cycles(&opts->gen, 6); | 467 cycles(&opts->gen, 6); |
468 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); | 468 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D); |
469 calc_index_disp8(opts, op, opts->gen.scratch1); | 469 calc_index_disp8(opts, op, opts->gen.scratch1); |
470 if (dst) { | 470 if (dst) { |
471 push_r(code, opts->gen.scratch1); | 471 push_r(code, opts->gen.scratch1); |
472 } | 472 } |
473 m68k_read_size(opts, inst->extra.size); | 473 m68k_read_size(opts, inst->extra.size); |
474 if (dst) { | 474 if (dst) { |
475 pop_r(code, opts->gen.scratch2); | 475 pop_r(code, opts->gen.scratch2); |
476 } | 476 } |
477 | 477 |
478 ea->mode = MODE_REG_DIRECT; | 478 ea->mode = MODE_REG_DIRECT; |
479 ea->base = opts->gen.scratch1; | 479 ea->base = opts->gen.scratch1; |
480 break; | 480 break; |
481 case MODE_ABSOLUTE: | 481 case MODE_ABSOLUTE: |
482 case MODE_ABSOLUTE_SHORT: | 482 case MODE_ABSOLUTE_SHORT: |
483 cycles(&opts->gen, op->addr_mode == MODE_ABSOLUTE ? BUS*2 : BUS); | 483 cycles(&opts->gen, op->addr_mode == MODE_ABSOLUTE ? BUS*2 : BUS); |
484 mov_ir(code, op->params.immed, opts->gen.scratch1, SZ_D); | 484 mov_ir(code, op->params.immed, opts->gen.scratch1, SZ_D); |
485 if (dst) { | 485 if (dst) { |
486 push_r(code, opts->gen.scratch1); | 486 push_r(code, opts->gen.scratch1); |
487 } | 487 } |
488 m68k_read_size(opts, inst->extra.size); | 488 m68k_read_size(opts, inst->extra.size); |
489 if (dst) { | 489 if (dst) { |
490 pop_r(code, opts->gen.scratch2); | 490 pop_r(code, opts->gen.scratch2); |
491 } | 491 } |
492 | 492 |
658 case MODE_PC_INDEX_DISP8: | 658 case MODE_PC_INDEX_DISP8: |
659 cycles(&opts->gen, 6);//TODO: Check to make sure this is correct | 659 cycles(&opts->gen, 6);//TODO: Check to make sure this is correct |
660 mov_ir(code, inst->address, opts->gen.scratch2, SZ_D); | 660 mov_ir(code, inst->address, opts->gen.scratch2, SZ_D); |
661 if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { | 661 if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { |
662 push_r(code, opts->gen.scratch1); | 662 push_r(code, opts->gen.scratch1); |
663 } | 663 } |
664 calc_index_disp8(opts, &inst->dst, opts->gen.scratch2); | 664 calc_index_disp8(opts, &inst->dst, opts->gen.scratch2); |
665 if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { | 665 if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { |
666 pop_r(code, opts->gen.scratch1); | 666 pop_r(code, opts->gen.scratch1); |
667 } | 667 } |
668 if (src.mode == MODE_REG_DIRECT) { | 668 if (src.mode == MODE_REG_DIRECT) { |
700 } | 700 } |
701 | 701 |
702 if (inst->dst.addr_mode != MODE_AREG) { | 702 if (inst->dst.addr_mode != MODE_AREG) { |
703 cmp_ir(code, 0, flags_reg, inst->extra.size); | 703 cmp_ir(code, 0, flags_reg, inst->extra.size); |
704 update_flags(opts, N|Z|V0|C0); | 704 update_flags(opts, N|Z|V0|C0); |
705 } | 705 } |
706 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) { | 706 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) { |
707 m68k_write_size(opts, inst->extra.size); | 707 m68k_write_size(opts, inst->extra.size); |
708 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { | 708 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { |
709 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | 709 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); |
710 addi_areg(opts, inc_amount, inst->dst.params.regs.pri); | 710 addi_areg(opts, inc_amount, inst->dst.params.regs.pri); |
711 } | 711 } |
712 } | 712 } |
713 | 713 |
714 //add cycles for prefetch | 714 //add cycles for prefetch |
715 cycles(&opts->gen, BUS); | 715 cycles(&opts->gen, BUS); |
716 } | 716 } |
717 | 717 |
756 //M68K EXT only operates on registers so no need for a call to save result here | 756 //M68K EXT only operates on registers so no need for a call to save result here |
757 } | 757 } |
758 | 758 |
759 uint8_t m68k_eval_cond(m68k_options * opts, uint8_t cc) | 759 uint8_t m68k_eval_cond(m68k_options * opts, uint8_t cc) |
760 { | 760 { |
761 uint8_t cond = CC_NZ; | 761 uint8_t cond = CC_NZ; |
762 switch (cc) | 762 switch (cc) |
763 { | 763 { |
764 case COND_HIGH: | 764 case COND_HIGH: |
765 cond = CC_Z; | 765 cond = CC_Z; |
766 case COND_LOW_SAME: | 766 case COND_LOW_SAME: |
767 flag_to_reg(opts, FLAG_Z, opts->gen.scratch1); | 767 flag_to_reg(opts, FLAG_Z, opts->gen.scratch1); |
768 or_flag_to_reg(opts, FLAG_C, opts->gen.scratch1); | 768 or_flag_to_reg(opts, FLAG_C, opts->gen.scratch1); |
769 break; | 769 break; |
770 case COND_CARRY_CLR: | 770 case COND_CARRY_CLR: |
771 cond = CC_Z; | 771 cond = CC_Z; |
772 case COND_CARRY_SET: | 772 case COND_CARRY_SET: |
773 check_flag(opts, FLAG_C); | 773 check_flag(opts, FLAG_C); |
774 break; | 774 break; |
775 case COND_NOT_EQ: | 775 case COND_NOT_EQ: |
776 cond = CC_Z; | 776 cond = CC_Z; |
777 case COND_EQ: | 777 case COND_EQ: |
778 check_flag(opts, FLAG_Z); | 778 check_flag(opts, FLAG_Z); |
779 break; | 779 break; |
780 case COND_OVERF_CLR: | 780 case COND_OVERF_CLR: |
781 cond = CC_Z; | 781 cond = CC_Z; |
782 case COND_OVERF_SET: | 782 case COND_OVERF_SET: |
783 check_flag(opts, FLAG_V); | 783 check_flag(opts, FLAG_V); |
784 break; | 784 break; |
785 case COND_PLUS: | 785 case COND_PLUS: |
786 cond = CC_Z; | 786 cond = CC_Z; |
787 case COND_MINUS: | 787 case COND_MINUS: |
788 check_flag(opts, FLAG_N); | 788 check_flag(opts, FLAG_N); |
789 break; | 789 break; |
790 case COND_GREATER_EQ: | 790 case COND_GREATER_EQ: |
791 cond = CC_Z; | 791 cond = CC_Z; |
792 case COND_LESS: | 792 case COND_LESS: |
793 cmp_flags(opts, FLAG_N, FLAG_V); | 793 cmp_flags(opts, FLAG_N, FLAG_V); |
794 break; | 794 break; |
795 case COND_GREATER: | 795 case COND_GREATER: |
796 cond = CC_Z; | 796 cond = CC_Z; |
797 case COND_LESS_EQ: | 797 case COND_LESS_EQ: |
798 flag_to_reg(opts, FLAG_V, opts->gen.scratch1); | 798 flag_to_reg(opts, FLAG_V, opts->gen.scratch1); |
799 xor_flag_to_reg(opts, FLAG_N, opts->gen.scratch1); | 799 xor_flag_to_reg(opts, FLAG_N, opts->gen.scratch1); |
800 or_flag_to_reg(opts, FLAG_Z, opts->gen.scratch1); | 800 or_flag_to_reg(opts, FLAG_Z, opts->gen.scratch1); |
801 break; | 801 break; |
802 } | 802 } |
803 return cond; | 803 return cond; |
804 } | 804 } |
805 | 805 |
806 void translate_m68k_bcc(m68k_options * opts, m68kinst * inst) | 806 void translate_m68k_bcc(m68k_options * opts, m68kinst * inst) |
807 { | 807 { |
1208 case M68K_ROR: ror_irdisp(code, val, dst, disp, size); break; | 1208 case M68K_ROR: ror_irdisp(code, val, dst, disp, size); break; |
1209 case M68K_ROXL: rcl_irdisp(code, val, dst, disp, size); break; | 1209 case M68K_ROXL: rcl_irdisp(code, val, dst, disp, size); break; |
1210 case M68K_ROXR: rcr_irdisp(code, val, dst, disp, size); break; | 1210 case M68K_ROXR: rcr_irdisp(code, val, dst, disp, size); break; |
1211 case M68K_SUB: sub_irdisp(code, val, dst, disp, size); break; | 1211 case M68K_SUB: sub_irdisp(code, val, dst, disp, size); break; |
1212 case M68K_SUBX: sbb_irdisp(code, val, dst, disp, size); break; | 1212 case M68K_SUBX: sbb_irdisp(code, val, dst, disp, size); break; |
1213 } | 1213 } |
1214 } | 1214 } |
1215 | 1215 |
1216 void op_rr(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, uint8_t size) | 1216 void op_rr(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, uint8_t size) |
1217 { | 1217 { |
1218 switch (inst->op) | 1218 switch (inst->op) |
1219 { | 1219 { |
1228 case M68K_EOR: xor_rr(code, src, dst, size); break; | 1228 case M68K_EOR: xor_rr(code, src, dst, size); break; |
1229 case M68K_OR: or_rr(code, src, dst, size); break; | 1229 case M68K_OR: or_rr(code, src, dst, size); break; |
1230 case M68K_SUB: sub_rr(code, src, dst, size); break; | 1230 case M68K_SUB: sub_rr(code, src, dst, size); break; |
1231 case M68K_SUBX: sbb_rr(code, src, dst, size); break; | 1231 case M68K_SUBX: sbb_rr(code, src, dst, size); break; |
1232 } | 1232 } |
1233 } | 1233 } |
1234 | 1234 |
1235 void op_rrdisp(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, int32_t disp, uint8_t size) | 1235 void op_rrdisp(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, int32_t disp, uint8_t size) |
1236 { | 1236 { |
1237 switch (inst->op) | 1237 switch(inst->op) |
1238 { | 1238 { |
1239 case M68K_ADD: add_rrdisp(code, src, dst, disp, size); break; | 1239 case M68K_ADD: add_rrdisp(code, src, dst, disp, size); break; |
1240 case M68K_ADDX: adc_rrdisp(code, src, dst, disp, size); break; | 1240 case M68K_ADDX: adc_rrdisp(code, src, dst, disp, size); break; |
1241 case M68K_AND: and_rrdisp(code, src, dst, disp, size); break; | 1241 case M68K_AND: and_rrdisp(code, src, dst, disp, size); break; |
1242 case M68K_BTST: bt_rrdisp(code, src, dst, disp, size); break; | 1242 case M68K_BTST: bt_rrdisp(code, src, dst, disp, size); break; |
1246 case M68K_CMP: cmp_rrdisp(code, src, dst, disp, size); break; | 1246 case M68K_CMP: cmp_rrdisp(code, src, dst, disp, size); break; |
1247 case M68K_EOR: xor_rrdisp(code, src, dst, disp, size); break; | 1247 case M68K_EOR: xor_rrdisp(code, src, dst, disp, size); break; |
1248 case M68K_OR: or_rrdisp(code, src, dst, disp, size); break; | 1248 case M68K_OR: or_rrdisp(code, src, dst, disp, size); break; |
1249 case M68K_SUB: sub_rrdisp(code, src, dst, disp, size); break; | 1249 case M68K_SUB: sub_rrdisp(code, src, dst, disp, size); break; |
1250 case M68K_SUBX: sbb_rrdisp(code, src, dst, disp, size); break; | 1250 case M68K_SUBX: sbb_rrdisp(code, src, dst, disp, size); break; |
1251 } | 1251 } |
1252 } | 1252 } |
1253 | 1253 |
1254 void op_rdispr(code_info *code, m68kinst *inst, uint8_t src, int32_t disp, uint8_t dst, uint8_t size) | 1254 void op_rdispr(code_info *code, m68kinst *inst, uint8_t src, int32_t disp, uint8_t dst, uint8_t size) |
1255 { | 1255 { |
1256 switch (inst->op) | 1256 switch (inst->op) |
1257 { | 1257 { |
1261 case M68K_CMP: cmp_rdispr(code, src, disp, dst, size); break; | 1261 case M68K_CMP: cmp_rdispr(code, src, disp, dst, size); break; |
1262 case M68K_EOR: xor_rdispr(code, src, disp, dst, size); break; | 1262 case M68K_EOR: xor_rdispr(code, src, disp, dst, size); break; |
1263 case M68K_OR: or_rdispr(code, src, disp, dst, size); break; | 1263 case M68K_OR: or_rdispr(code, src, disp, dst, size); break; |
1264 case M68K_SUB: sub_rdispr(code, src, disp, dst, size); break; | 1264 case M68K_SUB: sub_rdispr(code, src, disp, dst, size); break; |
1265 case M68K_SUBX: sbb_rdispr(code, src, disp, dst, size); break; | 1265 case M68K_SUBX: sbb_rdispr(code, src, disp, dst, size); break; |
1266 } | 1266 } |
1267 } | 1267 } |
1268 | 1268 |
1269 void translate_m68k_arith(m68k_options *opts, m68kinst * inst, uint32_t flag_mask, host_ea *src_op, host_ea *dst_op) | 1269 void translate_m68k_arith(m68k_options *opts, m68kinst * inst, uint32_t flag_mask, host_ea *src_op, host_ea *dst_op) |
1270 { | 1270 { |
1271 code_info *code = &opts->gen.code; | 1271 code_info *code = &opts->gen.code; |
1272 cycles(&opts->gen, BUS); | 1272 cycles(&opts->gen, BUS); |
1273 if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) { | 1273 if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) { |
1274 flag_to_carry(opts, FLAG_X); | 1274 flag_to_carry(opts, FLAG_X); |
1275 } | 1275 } |
1276 uint8_t size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; | 1276 uint8_t size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; |
1277 if (src_op->mode == MODE_REG_DIRECT) { | 1277 if (src_op->mode == MODE_REG_DIRECT) { |
1278 if (dst_op->mode == MODE_REG_DIRECT) { | 1278 if (dst_op->mode == MODE_REG_DIRECT) { |
1279 op_rr(code, inst, src_op->base, dst_op->base, size); | 1279 op_rr(code, inst, src_op->base, dst_op->base, size); |
1280 } else { | 1280 } else { |
1281 op_rrdisp(code, inst, src_op->base, dst_op->base, dst_op->disp, size); | 1281 op_rrdisp(code, inst, src_op->base, dst_op->base, dst_op->disp, size); |
1282 } | 1282 } |
1283 } else if (src_op->mode == MODE_REG_DISPLACE8) { | 1283 } else if (src_op->mode == MODE_REG_DISPLACE8) { |
1284 op_rdispr(code, inst, src_op->base, src_op->disp, dst_op->base, size); | 1284 op_rdispr(code, inst, src_op->base, src_op->disp, dst_op->base, size); |
1285 } else { | 1285 } else { |
1286 if (dst_op->mode == MODE_REG_DIRECT) { | 1286 if (dst_op->mode == MODE_REG_DIRECT) { |
1287 op_ir(code, inst, src_op->disp, dst_op->base, size); | 1287 op_ir(code, inst, src_op->disp, dst_op->base, size); |
1288 } else { | 1288 } else { |
1289 op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, size); | 1289 op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, size); |
1290 } | 1290 } |
1291 } | 1291 } |
1292 if (inst->dst.addr_mode != MODE_AREG || inst->op == M68K_CMP) { | 1292 if (inst->dst.addr_mode != MODE_AREG || inst->op == M68K_CMP) { |
1293 update_flags(opts, flag_mask); | 1293 update_flags(opts, flag_mask); |
1294 if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) { | 1294 if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) { |
1295 check_alloc_code(code, 2*MAX_INST_LEN); | 1295 check_alloc_code(code, 2*MAX_INST_LEN); |
1296 code_ptr after_flag_set = code->cur + 1; | 1296 code_ptr after_flag_set = code->cur + 1; |
1297 jcc(code, CC_Z, code->cur + 2); | 1297 jcc(code, CC_Z, code->cur + 2); |
1298 set_flag(opts, 0, FLAG_Z); | 1298 set_flag(opts, 0, FLAG_Z); |
1299 *after_flag_set = code->cur - (after_flag_set+1); | 1299 *after_flag_set = code->cur - (after_flag_set+1); |
1300 } | 1300 } |
1301 } | 1301 } |
1302 if (inst->op != M68K_CMP) { | 1302 if (inst->op != M68K_CMP) { |
1303 m68k_save_result(inst, opts); | 1303 m68k_save_result(inst, opts); |
1304 } | 1304 } |
1305 } | 1305 } |
1306 | 1306 |
1313 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { | 1313 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { |
1314 push_r(code, opts->gen.scratch1); | 1314 push_r(code, opts->gen.scratch1); |
1315 translate_m68k_op(inst, &dst_op, opts, 1); | 1315 translate_m68k_op(inst, &dst_op, opts, 1); |
1316 pop_r(code, opts->gen.scratch2); | 1316 pop_r(code, opts->gen.scratch2); |
1317 src_op.base = opts->gen.scratch2; | 1317 src_op.base = opts->gen.scratch2; |
1318 } else { | 1318 } else { |
1319 translate_m68k_op(inst, &dst_op, opts, 1); | 1319 translate_m68k_op(inst, &dst_op, opts, 1); |
1320 if (inst->dst.addr_mode == MODE_AREG && size == OPSIZE_WORD) { | 1320 if (inst->dst.addr_mode == MODE_AREG && size == OPSIZE_WORD) { |
1321 size = OPSIZE_LONG; | 1321 size = OPSIZE_LONG; |
1322 } | 1322 } |
1323 } | 1323 } |
1324 translate_m68k_arith(opts, inst, N|Z|V|C, &src_op, &dst_op); | 1324 translate_m68k_arith(opts, inst, N|Z|V|C, &src_op, &dst_op); |
1325 } | 1325 } |
1326 | 1326 |
1327 void op_r(code_info *code, m68kinst *inst, uint8_t dst, uint8_t size) | 1327 void op_r(code_info *code, m68kinst *inst, uint8_t dst, uint8_t size) |
1358 { | 1358 { |
1359 code_info *code = &opts->gen.code; | 1359 code_info *code = &opts->gen.code; |
1360 cycles(&opts->gen, BUS); | 1360 cycles(&opts->gen, BUS); |
1361 if (dst_op->mode == MODE_REG_DIRECT) { | 1361 if (dst_op->mode == MODE_REG_DIRECT) { |
1362 op_r(code, inst, dst_op->base, inst->extra.size); | 1362 op_r(code, inst, dst_op->base, inst->extra.size); |
1363 } else { | 1363 } else { |
1364 op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size); | 1364 op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size); |
1365 } | 1365 } |
1366 update_flags(opts, flag_mask); | 1366 update_flags(opts, flag_mask); |
1367 m68k_save_result(inst, opts); | 1367 m68k_save_result(inst, opts); |
1368 } | 1368 } |
1369 | 1369 |
1370 void translate_m68k_invalid(m68k_options *opts, m68kinst *inst) | 1370 void translate_m68k_invalid(m68k_options *opts, m68kinst *inst) |
1371 { | 1371 { |
1372 code_info *code = &opts->gen.code; | 1372 code_info *code = &opts->gen.code; |
1373 if (inst->src.params.immed == 0x7100) { | 1373 if (inst->src.params.immed == 0x7100) { |
1389 } | 1389 } |
1390 } | 1390 } |
1391 if (dst_op->base != opts->gen.scratch1) { | 1391 if (dst_op->base != opts->gen.scratch1) { |
1392 if (dst_op->mode == MODE_REG_DIRECT) { | 1392 if (dst_op->mode == MODE_REG_DIRECT) { |
1393 mov_rr(code, dst_op->base, opts->gen.scratch1, SZ_B); | 1393 mov_rr(code, dst_op->base, opts->gen.scratch1, SZ_B); |
1394 } else { | 1394 } else { |
1395 mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, SZ_B); | 1395 mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, SZ_B); |
1396 } | 1396 } |
1397 } | 1397 } |
1398 uint8_t other_reg; | 1398 uint8_t other_reg; |
1399 //WARNING: This may need adjustment if register assignments change | 1399 //WARNING: This may need adjustment if register assignments change |
1400 if (opts->gen.scratch2 > RBX) { | 1400 if (opts->gen.scratch2 > RBX) { |
1401 other_reg = RAX; | 1401 other_reg = RAX; |
1402 xchg_rr(code, opts->gen.scratch2, RAX, SZ_D); | 1402 xchg_rr(code, opts->gen.scratch2, RAX, SZ_D); |
1403 } else { | 1403 } else { |
1404 other_reg = opts->gen.scratch2; | 1404 other_reg = opts->gen.scratch2; |
1405 } | 1405 } |
1406 mov_rr(code, opts->gen.scratch1, opts->gen.scratch1 + (AH-RAX), SZ_B); | 1406 mov_rr(code, opts->gen.scratch1, opts->gen.scratch1 + (AH-RAX), SZ_B); |
1407 mov_rr(code, other_reg, other_reg + (AH-RAX), SZ_B); | 1407 mov_rr(code, other_reg, other_reg + (AH-RAX), SZ_B); |
1408 and_ir(code, 0xF0, opts->gen.scratch1, SZ_B); | 1408 and_ir(code, 0xF0, opts->gen.scratch1, SZ_B); |
1411 and_ir(code, 0xF, other_reg + (AH-RAX), SZ_B); | 1411 and_ir(code, 0xF, other_reg + (AH-RAX), SZ_B); |
1412 //do op on low nibble | 1412 //do op on low nibble |
1413 flag_to_carry(opts, FLAG_X); | 1413 flag_to_carry(opts, FLAG_X); |
1414 if (inst->op == M68K_ABCD) { | 1414 if (inst->op == M68K_ABCD) { |
1415 adc_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B); | 1415 adc_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B); |
1416 } else { | 1416 } else { |
1417 sbb_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B); | 1417 sbb_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B); |
1418 } | 1418 } |
1419 cmp_ir(code, 0xA, opts->gen.scratch1 + (AH-RAX), SZ_B); | 1419 cmp_ir(code, 0xA, opts->gen.scratch1 + (AH-RAX), SZ_B); |
1420 code_ptr no_adjust = code->cur+1; | 1420 code_ptr no_adjust = code->cur+1; |
1421 //add correction factor if necessary | 1421 //add correction factor if necessary |
1422 jcc(code, CC_B, no_adjust); | 1422 jcc(code, CC_B, no_adjust); |
1423 if (inst->op == M68K_ABCD) { | 1423 if (inst->op == M68K_ABCD) { |
1424 add_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B); | 1424 add_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B); |
1425 } else { | 1425 } else { |
1426 sub_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B); | 1426 sub_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B); |
1427 } | 1427 } |
1428 *no_adjust = code->cur - (no_adjust+1); | 1428 *no_adjust = code->cur - (no_adjust+1); |
1429 //add low nibble result to one of the high nibble operands | 1429 //add low nibble result to one of the high nibble operands |
1430 add_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1, SZ_B); | 1430 add_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1, SZ_B); |
1431 if (inst->op == M68K_ABCD) { | 1431 if (inst->op == M68K_ABCD) { |
1432 add_rr(code, other_reg, opts->gen.scratch1, SZ_B); | 1432 add_rr(code, other_reg, opts->gen.scratch1, SZ_B); |
1433 } else { | 1433 } else { |
1434 sub_rr(code, other_reg, opts->gen.scratch1, SZ_B); | 1434 sub_rr(code, other_reg, opts->gen.scratch1, SZ_B); |
1435 } | 1435 } |
1436 if (opts->gen.scratch2 > RBX) { | 1436 if (opts->gen.scratch2 > RBX) { |
1437 mov_rr(code, opts->gen.scratch2, RAX, SZ_D); | 1437 mov_rr(code, opts->gen.scratch2, RAX, SZ_D); |
1438 } | 1438 } |
1439 set_flag(opts, 0, FLAG_C); | 1439 set_flag(opts, 0, FLAG_C); |
1440 set_flag(opts, 0, FLAG_V); | 1440 set_flag(opts, 0, FLAG_V); |
1441 code_ptr def_adjust = code->cur+1; | 1441 code_ptr def_adjust = code->cur+1; |
1442 jcc(code, CC_C, def_adjust); | 1442 jcc(code, CC_C, def_adjust); |
1443 cmp_ir(code, 0xA0, opts->gen.scratch1, SZ_B); | 1443 cmp_ir(code, 0xA0, opts->gen.scratch1, SZ_B); |
1447 set_flag(opts, 1, FLAG_C); | 1447 set_flag(opts, 1, FLAG_C); |
1448 if (inst->op == M68K_ABCD) { | 1448 if (inst->op == M68K_ABCD) { |
1449 add_ir(code, 0x60, opts->gen.scratch1, SZ_B); | 1449 add_ir(code, 0x60, opts->gen.scratch1, SZ_B); |
1450 } else { | 1450 } else { |
1451 sub_ir(code, 0x60, opts->gen.scratch1, SZ_B); | 1451 sub_ir(code, 0x60, opts->gen.scratch1, SZ_B); |
1452 } | 1452 } |
1453 //V flag is set based on the result of the addition of the | 1453 //V flag is set based on the result of the addition of the |
1454 //result and the correction factor | 1454 //result and the correction factor |
1455 set_flag_cond(opts, CC_O, FLAG_V); | 1455 set_flag_cond(opts, CC_O, FLAG_V); |
1456 *no_adjust = code->cur - (no_adjust+1); | 1456 *no_adjust = code->cur - (no_adjust+1); |
1457 flag_to_flag(opts, FLAG_C, FLAG_X); | 1457 flag_to_flag(opts, FLAG_C, FLAG_X); |
1464 if (dst_op->mode == MODE_REG_DIRECT) { | 1464 if (dst_op->mode == MODE_REG_DIRECT) { |
1465 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_B); | 1465 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_B); |
1466 } else { | 1466 } else { |
1467 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_B); | 1467 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_B); |
1468 } | 1468 } |
1469 } | 1469 } |
1470 m68k_save_result(inst, opts); | 1470 m68k_save_result(inst, opts); |
1471 } | 1471 } |
1472 | 1472 |
1473 void translate_m68k_sl(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 1473 void translate_m68k_sl(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
1474 { | 1474 { |
1475 translate_shift(opts, inst, src_op, dst_op, shl_ir, shl_irdisp, shl_clr, shl_clrdisp, shr_ir, shr_irdisp); | 1475 translate_shift(opts, inst, src_op, dst_op, shl_ir, shl_irdisp, shl_clr, shl_clrdisp, shr_ir, shr_irdisp); |
1476 } | 1476 } |
1477 | 1477 |
1478 void translate_m68k_asr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 1478 void translate_m68k_asr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
1479 { | 1479 { |
1480 translate_shift(opts, inst, src_op, dst_op, sar_ir, sar_irdisp, sar_clr, sar_clrdisp, NULL, NULL); | 1480 translate_shift(opts, inst, src_op, dst_op, sar_ir, sar_irdisp, sar_clr, sar_clrdisp, NULL, NULL); |
1481 } | 1481 } |
1482 | 1482 |
1483 void translate_m68k_lsr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 1483 void translate_m68k_lsr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
1484 { | 1484 { |
1485 translate_shift(opts, inst, src_op, dst_op, shr_ir, shr_irdisp, shr_clr, shr_clrdisp, shl_ir, shl_irdisp); | 1485 translate_shift(opts, inst, src_op, dst_op, shr_ir, shr_irdisp, shr_clr, shr_clrdisp, shl_ir, shl_irdisp); |
1486 } | 1486 } |
1487 | 1487 |
1488 void translate_m68k_bit(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 1488 void translate_m68k_bit(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
1489 { | 1489 { |
1490 code_info *code = &opts->gen.code; | 1490 code_info *code = &opts->gen.code; |
1491 cycles(&opts->gen, inst->extra.size == OPSIZE_BYTE ? 4 : ( | 1491 cycles(&opts->gen, inst->extra.size == OPSIZE_BYTE ? 4 : ( |
1492 inst->op == M68K_BTST ? 6 : (inst->op == M68K_BCLR ? 10 : 8)) | 1492 inst->op == M68K_BTST ? 6 : (inst->op == M68K_BCLR ? 10 : 8)) |
1493 ); | 1493 ); |
1494 if (src_op->mode == MODE_IMMED) { | 1494 if (src_op->mode == MODE_IMMED) { |
1495 if (inst->extra.size == OPSIZE_BYTE) { | 1495 if (inst->extra.size == OPSIZE_BYTE) { |
1496 src_op->disp &= 0x7; | 1496 src_op->disp &= 0x7; |
1497 } | 1497 } |
1498 if (dst_op->mode == MODE_REG_DIRECT) { | 1498 if (dst_op->mode == MODE_REG_DIRECT) { |
1499 op_ir(code, inst, src_op->disp, dst_op->base, inst->extra.size); | 1499 op_ir(code, inst, src_op->disp, dst_op->base, inst->extra.size); |
1500 } else { | 1500 } else { |
1501 op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); | 1501 op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); |
1502 } | 1502 } |
1503 } else { | 1503 } else { |
1504 if (src_op->mode == MODE_REG_DISPLACE8 || (inst->dst.addr_mode != MODE_REG && src_op->base != opts->gen.scratch1 && src_op->base != opts->gen.scratch2)) { | 1504 if (src_op->mode == MODE_REG_DISPLACE8 || (inst->dst.addr_mode != MODE_REG && src_op->base != opts->gen.scratch1 && src_op->base != opts->gen.scratch2)) { |
1505 if (dst_op->base == opts->gen.scratch1) { | 1505 if (dst_op->base == opts->gen.scratch1) { |
1506 push_r(code, opts->gen.scratch2); | 1506 push_r(code, opts->gen.scratch2); |
1507 if (src_op->mode == MODE_REG_DIRECT) { | 1507 if (src_op->mode == MODE_REG_DIRECT) { |
1508 mov_rr(code, src_op->base, opts->gen.scratch2, SZ_B); | 1508 mov_rr(code, src_op->base, opts->gen.scratch2, SZ_B); |
1515 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B); | 1515 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B); |
1516 } else { | 1516 } else { |
1517 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B); | 1517 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B); |
1518 } | 1518 } |
1519 src_op->base = opts->gen.scratch1; | 1519 src_op->base = opts->gen.scratch1; |
1520 } | 1520 } |
1521 } | 1521 } |
1522 uint8_t size = inst->extra.size; | 1522 uint8_t size = inst->extra.size; |
1523 if (dst_op->mode == MODE_REG_DISPLACE8) { | 1523 if (dst_op->mode == MODE_REG_DISPLACE8) { |
1524 if (src_op->base != opts->gen.scratch1 && src_op->base != opts->gen.scratch2) { | 1524 if (src_op->base != opts->gen.scratch1 && src_op->base != opts->gen.scratch2) { |
1525 if (src_op->mode == MODE_REG_DIRECT) { | 1525 if (src_op->mode == MODE_REG_DIRECT) { |
1526 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_D); | 1526 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_D); |
1527 } else { | 1527 } else { |
1528 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_D); | 1528 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_D); |
1529 src_op->mode = MODE_REG_DIRECT; | 1529 src_op->mode = MODE_REG_DIRECT; |
1530 } | 1530 } |
1531 src_op->base = opts->gen.scratch1; | 1531 src_op->base = opts->gen.scratch1; |
1532 } | 1532 } |
1533 //b### with register destination is modulo 32 | 1533 //b### with register destination is modulo 32 |
1534 //x86 with a memory destination isn't modulo anything | 1534 //x86 with a memory destination isn't modulo anything |
1535 //so use an and here to force the value to be modulo 32 | 1535 //so use an and here to force the value to be modulo 32 |
1536 and_ir(code, 31, opts->gen.scratch1, SZ_D); | 1536 and_ir(code, 31, opts->gen.scratch1, SZ_D); |
1537 } else if(inst->dst.addr_mode != MODE_REG) { | 1537 } else if(inst->dst.addr_mode != MODE_REG) { |
1538 //b### with memory destination is modulo 8 | 1538 //b### with memory destination is modulo 8 |
1539 //x86-64 doesn't support 8-bit bit operations | 1539 //x86-64 doesn't support 8-bit bit operations |
1540 //so we fake it by forcing the bit number to be modulo 8 | 1540 //so we fake it by forcing the bit number to be modulo 8 |
1541 and_ir(code, 7, src_op->base, SZ_D); | 1541 and_ir(code, 7, src_op->base, SZ_D); |
1542 size = SZ_D; | 1542 size = SZ_D; |
1543 } | 1543 } |
1544 if (dst_op->mode == MODE_REG_DIRECT) { | 1544 if (dst_op->mode == MODE_REG_DIRECT) { |
1545 op_rr(code, inst, src_op->base, dst_op->base, size); | 1545 op_rr(code, inst, src_op->base, dst_op->base, size); |
1546 } else { | 1546 } else { |
1547 op_rrdisp(code, inst, src_op->base, dst_op->base, dst_op->disp, size); | 1547 op_rrdisp(code, inst, src_op->base, dst_op->base, dst_op->disp, size); |
1548 } | 1548 } |
1549 if (src_op->base == opts->gen.scratch2) { | 1549 if (src_op->base == opts->gen.scratch2) { |
1550 pop_r(code, opts->gen.scratch2); | 1550 pop_r(code, opts->gen.scratch2); |
1551 } | 1551 } |
1552 } | 1552 } |
1553 //x86 sets the carry flag to the value of the bit tested | 1553 //x86 sets the carry flag to the value of the bit tested |
1554 //68K sets the zero flag to the complement of the bit tested | 1554 //68K sets the zero flag to the complement of the bit tested |
1555 set_flag_cond(opts, CC_NC, FLAG_Z); | 1555 set_flag_cond(opts, CC_NC, FLAG_Z); |
1556 if (inst->op != M68K_BTST) { | 1556 if (inst->op != M68K_BTST) { |
1557 m68k_save_result(inst, opts); | 1557 m68k_save_result(inst, opts); |
1558 } | 1558 } |
1559 } | 1559 } |
1560 | 1560 |
1561 void translate_m68k_chk(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 1561 void translate_m68k_chk(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
1562 { | 1562 { |
1563 code_info *code = &opts->gen.code; | 1563 code_info *code = &opts->gen.code; |
1564 cycles(&opts->gen, 6); | 1564 cycles(&opts->gen, 6); |
1565 if (dst_op->mode == MODE_REG_DIRECT) { | 1565 if (dst_op->mode == MODE_REG_DIRECT) { |
1566 cmp_ir(code, 0, dst_op->base, inst->extra.size); | 1566 cmp_ir(code, 0, dst_op->base, inst->extra.size); |
1567 } else { | 1567 } else { |
1568 cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size); | 1568 cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size); |
1569 } | 1569 } |
1570 uint32_t isize; | 1570 uint32_t isize; |
1571 switch(inst->src.addr_mode) | 1571 switch(inst->src.addr_mode) |
1572 { | 1572 { |
1573 case MODE_AREG_DISPLACE: | 1573 case MODE_AREG_DISPLACE: |
1574 case MODE_AREG_INDEX_DISP8: | 1574 case MODE_AREG_INDEX_DISP8: |
1575 case MODE_ABSOLUTE_SHORT: | 1575 case MODE_ABSOLUTE_SHORT: |
1576 case MODE_PC_INDEX_DISP8: | 1576 case MODE_PC_INDEX_DISP8: |
1577 case MODE_PC_DISPLACE: | 1577 case MODE_PC_DISPLACE: |
1578 case MODE_IMMEDIATE: | 1578 case MODE_IMMEDIATE: |
1579 isize = 4; | 1579 isize = 4; |
1580 break; | 1580 break; |
1581 case MODE_ABSOLUTE: | 1581 case MODE_ABSOLUTE: |
1582 isize = 6; | 1582 isize = 6; |
1583 break; | 1583 break; |
1584 default: | 1584 default: |
1585 isize = 2; | 1585 isize = 2; |
1586 } | 1586 } |
1587 //make sure we won't start a new chunk in the middle of these branches | 1587 //make sure we won't start a new chunk in the middle of these branches |
1588 check_alloc_code(code, MAX_INST_LEN * 11); | 1588 check_alloc_code(code, MAX_INST_LEN * 11); |
1589 code_ptr passed = code->cur + 1; | 1589 code_ptr passed = code->cur + 1; |
1590 jcc(code, CC_GE, code->cur + 2); | 1590 jcc(code, CC_GE, code->cur + 2); |
1591 set_flag(opts, 1, FLAG_N); | 1591 set_flag(opts, 1, FLAG_N); |
1596 if (dst_op->mode == MODE_REG_DIRECT) { | 1596 if (dst_op->mode == MODE_REG_DIRECT) { |
1597 if (src_op->mode == MODE_REG_DIRECT) { | 1597 if (src_op->mode == MODE_REG_DIRECT) { |
1598 cmp_rr(code, src_op->base, dst_op->base, inst->extra.size); | 1598 cmp_rr(code, src_op->base, dst_op->base, inst->extra.size); |
1599 } else if(src_op->mode == MODE_REG_DISPLACE8) { | 1599 } else if(src_op->mode == MODE_REG_DISPLACE8) { |
1600 cmp_rdispr(code, src_op->base, src_op->disp, dst_op->base, inst->extra.size); | 1600 cmp_rdispr(code, src_op->base, src_op->disp, dst_op->base, inst->extra.size); |
1601 } else { | 1601 } else { |
1602 cmp_ir(code, src_op->disp, dst_op->base, inst->extra.size); | 1602 cmp_ir(code, src_op->disp, dst_op->base, inst->extra.size); |
1603 } | 1603 } |
1604 } else if(dst_op->mode == MODE_REG_DISPLACE8) { | 1604 } else if(dst_op->mode == MODE_REG_DISPLACE8) { |
1605 if (src_op->mode == MODE_REG_DIRECT) { | 1605 if (src_op->mode == MODE_REG_DIRECT) { |
1606 cmp_rrdisp(code, src_op->base, dst_op->base, dst_op->disp, inst->extra.size); | 1606 cmp_rrdisp(code, src_op->base, dst_op->base, dst_op->disp, inst->extra.size); |
1607 } else { | 1607 } else { |
1608 cmp_irdisp(code, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); | 1608 cmp_irdisp(code, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); |
1609 } | 1609 } |
1610 } | 1610 } |
1611 passed = code->cur + 1; | 1611 passed = code->cur + 1; |
1612 jcc(code, CC_LE, code->cur + 2); | 1612 jcc(code, CC_LE, code->cur + 2); |
1613 set_flag(opts, 0, FLAG_N); | 1613 set_flag(opts, 0, FLAG_N); |
1614 mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D); | 1614 mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D); |
1615 mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D); | 1615 mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D); |
1616 jmp(code, opts->trap); | 1616 jmp(code, opts->trap); |
1617 *passed = code->cur - (passed+1); | 1617 *passed = code->cur - (passed+1); |
1618 cycles(&opts->gen, 4); | 1618 cycles(&opts->gen, 4); |
1619 } | 1619 } |
1620 | 1620 |
1621 void translate_m68k_div(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 1621 void translate_m68k_div(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
1622 { | 1622 { |
1623 code_info *code = &opts->gen.code; | 1623 code_info *code = &opts->gen.code; |
1624 check_alloc_code(code, MAX_NATIVE_SIZE); | 1624 check_alloc_code(code, MAX_NATIVE_SIZE); |
1625 //TODO: cycle exact division | 1625 //TODO: cycle exact division |
1626 cycles(&opts->gen, inst->op == M68K_DIVS ? 158 : 140); | 1626 cycles(&opts->gen, inst->op == M68K_DIVS ? 158 : 140); |
1627 set_flag(opts, 0, FLAG_C); | 1627 set_flag(opts, 0, FLAG_C); |
1628 push_r(code, RDX); | 1628 push_r(code, RDX); |
1629 push_r(code, RAX); | 1629 push_r(code, RAX); |
1630 if (dst_op->mode == MODE_REG_DIRECT) { | 1630 if (dst_op->mode == MODE_REG_DIRECT) { |
1631 mov_rr(code, dst_op->base, RAX, SZ_D); | 1631 mov_rr(code, dst_op->base, RAX, SZ_D); |
1632 } else { | 1632 } else { |
1633 mov_rdispr(code, dst_op->base, dst_op->disp, RAX, SZ_D); | 1633 mov_rdispr(code, dst_op->base, dst_op->disp, RAX, SZ_D); |
1634 } | 1634 } |
1635 if (src_op->mode == MODE_IMMED) { | 1635 if (src_op->mode == MODE_IMMED) { |
1636 mov_ir(code, (src_op->disp & 0x8000) && inst->op == M68K_DIVS ? src_op->disp | 0xFFFF0000 : src_op->disp, opts->gen.scratch2, SZ_D); | 1636 mov_ir(code, (src_op->disp & 0x8000) && inst->op == M68K_DIVS ? src_op->disp | 0xFFFF0000 : src_op->disp, opts->gen.scratch2, SZ_D); |
1637 } else if (src_op->mode == MODE_REG_DIRECT) { | 1637 } else if (src_op->mode == MODE_REG_DIRECT) { |
1638 if (inst->op == M68K_DIVS) { | 1638 if (inst->op == M68K_DIVS) { |
1639 movsx_rr(code, src_op->base, opts->gen.scratch2, SZ_W, SZ_D); | 1639 movsx_rr(code, src_op->base, opts->gen.scratch2, SZ_W, SZ_D); |
1640 } else { | 1640 } else { |
1641 movzx_rr(code, src_op->base, opts->gen.scratch2, SZ_W, SZ_D); | 1641 movzx_rr(code, src_op->base, opts->gen.scratch2, SZ_W, SZ_D); |
1642 } | 1642 } |
1643 } else if (src_op->mode == MODE_REG_DISPLACE8) { | 1643 } else if (src_op->mode == MODE_REG_DISPLACE8) { |
1644 if (inst->op == M68K_DIVS) { | 1644 if (inst->op == M68K_DIVS) { |
1645 movsx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_W, SZ_D); | 1645 movsx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_W, SZ_D); |
1646 } else { | 1646 } else { |
1647 movzx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_W, SZ_D); | 1647 movzx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_W, SZ_D); |
1648 } | 1648 } |
1649 } | 1649 } |
1650 uint32_t isize = 2; | 1650 uint32_t isize = 2; |
1651 switch(inst->src.addr_mode) | 1651 switch(inst->src.addr_mode) |
1652 { | 1652 { |
1653 case MODE_AREG_DISPLACE: | 1653 case MODE_AREG_DISPLACE: |
1654 case MODE_AREG_INDEX_DISP8: | 1654 case MODE_AREG_INDEX_DISP8: |
1669 pop_r(code, RDX); | 1669 pop_r(code, RDX); |
1670 mov_ir(code, VECTOR_INT_DIV_ZERO, opts->gen.scratch2, SZ_D); | 1670 mov_ir(code, VECTOR_INT_DIV_ZERO, opts->gen.scratch2, SZ_D); |
1671 mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D); | 1671 mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D); |
1672 jmp(code, opts->trap); | 1672 jmp(code, opts->trap); |
1673 *not_zero = code->cur - (not_zero+1); | 1673 *not_zero = code->cur - (not_zero+1); |
1674 if (inst->op == M68K_DIVS) { | 1674 if (inst->op == M68K_DIVS) { |
1675 cdq(code); | 1675 cdq(code); |
1676 } else { | 1676 } else { |
1677 xor_rr(code, RDX, RDX, SZ_D); | 1677 xor_rr(code, RDX, RDX, SZ_D); |
1678 } | 1678 } |
1679 if (inst->op == M68K_DIVS) { | 1679 if (inst->op == M68K_DIVS) { |
1680 idiv_r(code, opts->gen.scratch2, SZ_D); | 1680 idiv_r(code, opts->gen.scratch2, SZ_D); |
1681 } else { | 1681 } else { |
1682 div_r(code, opts->gen.scratch2, SZ_D); | 1682 div_r(code, opts->gen.scratch2, SZ_D); |
1683 } | 1683 } |
1684 code_ptr skip_sec_check, norm_off; | 1684 code_ptr skip_sec_check, norm_off; |
1685 if (inst->op == M68K_DIVS) { | 1685 if (inst->op == M68K_DIVS) { |
1686 cmp_ir(code, 0x8000, RAX, SZ_D); | 1686 cmp_ir(code, 0x8000, RAX, SZ_D); |
1687 skip_sec_check = code->cur + 1; | 1687 skip_sec_check = code->cur + 1; |
1688 jcc(code, CC_GE, code->cur + 2); | 1688 jcc(code, CC_GE, code->cur + 2); |
1689 cmp_ir(code, -0x8000, RAX, SZ_D); | 1689 cmp_ir(code, -0x8000, RAX, SZ_D); |
1690 norm_off = code->cur + 1; | 1690 norm_off = code->cur + 1; |
1691 jcc(code, CC_L, code->cur + 2); | 1691 jcc(code, CC_L, code->cur + 2); |
1692 } else { | 1692 } else { |
1693 cmp_ir(code, 0x10000, RAX, SZ_D); | 1693 cmp_ir(code, 0x10000, RAX, SZ_D); |
1694 norm_off = code->cur + 1; | 1694 norm_off = code->cur + 1; |
1695 jcc(code, CC_NC, code->cur + 2); | 1695 jcc(code, CC_NC, code->cur + 2); |
1696 } | 1696 } |
1697 if (dst_op->mode == MODE_REG_DIRECT) { | 1697 if (dst_op->mode == MODE_REG_DIRECT) { |
1698 mov_rr(code, RDX, dst_op->base, SZ_W); | 1698 mov_rr(code, RDX, dst_op->base, SZ_W); |
1699 shl_ir(code, 16, dst_op->base, SZ_D); | 1699 shl_ir(code, 16, dst_op->base, SZ_D); |
1700 mov_rr(code, RAX, dst_op->base, SZ_W); | 1700 mov_rr(code, RAX, dst_op->base, SZ_W); |
1701 } else { | 1701 } else { |
1702 mov_rrdisp(code, RDX, dst_op->base, dst_op->disp, SZ_W); | 1702 mov_rrdisp(code, RDX, dst_op->base, dst_op->disp, SZ_W); |
1703 shl_irdisp(code, 16, dst_op->base, dst_op->disp, SZ_D); | 1703 shl_irdisp(code, 16, dst_op->base, dst_op->disp, SZ_D); |
1704 mov_rrdisp(code, RAX, dst_op->base, dst_op->disp, SZ_W); | 1704 mov_rrdisp(code, RAX, dst_op->base, dst_op->disp, SZ_W); |
1705 } | 1705 } |
1706 cmp_ir(code, 0, RAX, SZ_W); | 1706 cmp_ir(code, 0, RAX, SZ_W); |
1707 pop_r(code, RAX); | 1707 pop_r(code, RAX); |
1708 pop_r(code, RDX); | 1708 pop_r(code, RDX); |
1709 update_flags(opts, V0|Z|N); | 1709 update_flags(opts, V0|Z|N); |
1710 code_ptr end_off = code->cur + 1; | 1710 code_ptr end_off = code->cur + 1; |
1711 jmp(code, code->cur + 2); | 1711 jmp(code, code->cur + 2); |
1712 *norm_off = code->cur - (norm_off + 1); | 1712 *norm_off = code->cur - (norm_off + 1); |
1713 if (inst->op == M68K_DIVS) { | 1713 if (inst->op == M68K_DIVS) { |
1714 *skip_sec_check = code->cur - (skip_sec_check+1); | 1714 *skip_sec_check = code->cur - (skip_sec_check+1); |
1715 } | 1715 } |
1716 pop_r(code, RAX); | 1716 pop_r(code, RAX); |
1717 pop_r(code, RDX); | 1717 pop_r(code, RDX); |
1718 set_flag(opts, 1, FLAG_V); | 1718 set_flag(opts, 1, FLAG_V); |
1719 *end_off = code->cur - (end_off + 1); | 1719 *end_off = code->cur - (end_off + 1); |
1720 } | 1720 } |
1721 | 1721 |
1722 void translate_m68k_exg(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 1722 void translate_m68k_exg(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
1723 { | 1723 { |
1724 code_info *code = &opts->gen.code; | 1724 code_info *code = &opts->gen.code; |
1725 cycles(&opts->gen, 6); | 1725 cycles(&opts->gen, 6); |
1726 if (dst_op->mode == MODE_REG_DIRECT) { | 1726 if (dst_op->mode == MODE_REG_DIRECT) { |
1727 mov_rr(code, dst_op->base, opts->gen.scratch2, SZ_D); | 1727 mov_rr(code, dst_op->base, opts->gen.scratch2, SZ_D); |
1728 if (src_op->mode == MODE_REG_DIRECT) { | 1728 if (src_op->mode == MODE_REG_DIRECT) { |
1729 mov_rr(code, src_op->base, dst_op->base, SZ_D); | 1729 mov_rr(code, src_op->base, dst_op->base, SZ_D); |
1730 mov_rr(code, opts->gen.scratch2, src_op->base, SZ_D); | 1730 mov_rr(code, opts->gen.scratch2, src_op->base, SZ_D); |
1731 } else { | 1731 } else { |
1732 mov_rdispr(code, src_op->base, src_op->disp, dst_op->base, SZ_D); | 1732 mov_rdispr(code, src_op->base, src_op->disp, dst_op->base, SZ_D); |
1733 mov_rrdisp(code, opts->gen.scratch2, src_op->base, src_op->disp, SZ_D); | 1733 mov_rrdisp(code, opts->gen.scratch2, src_op->base, src_op->disp, SZ_D); |
1734 } | 1734 } |
1735 } else { | 1735 } else { |
1736 mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_D); | 1736 mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_D); |
1737 if (src_op->mode == MODE_REG_DIRECT) { | 1737 if (src_op->mode == MODE_REG_DIRECT) { |
1738 mov_rrdisp(code, src_op->base, dst_op->base, dst_op->disp, SZ_D); | 1738 mov_rrdisp(code, src_op->base, dst_op->base, dst_op->disp, SZ_D); |
1739 mov_rr(code, opts->gen.scratch2, src_op->base, SZ_D); | 1739 mov_rr(code, opts->gen.scratch2, src_op->base, SZ_D); |
1740 } else { | 1740 } else { |
1741 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_D); | 1741 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_D); |
1742 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_D); | 1742 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_D); |
1743 mov_rrdisp(code, opts->gen.scratch2, src_op->base, src_op->disp, SZ_D); | 1743 mov_rrdisp(code, opts->gen.scratch2, src_op->base, src_op->disp, SZ_D); |
1744 } | 1744 } |
1745 } | 1745 } |
1746 } | 1746 } |
1747 | 1747 |
1748 void translate_m68k_mul(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 1748 void translate_m68k_mul(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
1749 { | 1749 { |
1750 code_info *code = &opts->gen.code; | 1750 code_info *code = &opts->gen.code; |
1751 cycles(&opts->gen, 70); //TODO: Calculate the actual value based on the value of the <ea> parameter | 1751 cycles(&opts->gen, 70); //TODO: Calculate the actual value based on the value of the <ea> parameter |
1752 if (src_op->mode == MODE_IMMED) { | 1752 if (src_op->mode == MODE_IMMED) { |
1753 mov_ir(code, inst->op == M68K_MULU ? (src_op->disp & 0xFFFF) : ((src_op->disp & 0x8000) ? src_op->disp | 0xFFFF0000 : src_op->disp), opts->gen.scratch1, SZ_D); | 1753 mov_ir(code, inst->op == M68K_MULU ? (src_op->disp & 0xFFFF) : ((src_op->disp & 0x8000) ? src_op->disp | 0xFFFF0000 : src_op->disp), opts->gen.scratch1, SZ_D); |
1754 } else if (src_op->mode == MODE_REG_DIRECT) { | 1754 } else if (src_op->mode == MODE_REG_DIRECT) { |
1755 if (inst->op == M68K_MULS) { | 1755 if (inst->op == M68K_MULS) { |
1756 movsx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D); | 1756 movsx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D); |
1757 } else { | 1757 } else { |
1758 movzx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D); | 1758 movzx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D); |
1759 } | 1759 } |
1760 } else { | 1760 } else { |
1761 if (inst->op == M68K_MULS) { | 1761 if (inst->op == M68K_MULS) { |
1762 movsx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D); | 1762 movsx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D); |
1763 } else { | 1763 } else { |
1764 movzx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D); | 1764 movzx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D); |
1765 } | 1765 } |
1766 } | 1766 } |
1767 uint8_t dst_reg; | 1767 uint8_t dst_reg; |
1768 if (dst_op->mode == MODE_REG_DIRECT) { | 1768 if (dst_op->mode == MODE_REG_DIRECT) { |
1769 dst_reg = dst_op->base; | 1769 dst_reg = dst_op->base; |
1770 if (inst->op == M68K_MULS) { | 1770 if (inst->op == M68K_MULS) { |
1771 movsx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D); | 1771 movsx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D); |
1772 } else { | 1772 } else { |
1773 movzx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D); | 1773 movzx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D); |
1774 } | 1774 } |
1775 } else { | 1775 } else { |
1776 dst_reg = opts->gen.scratch2; | 1776 dst_reg = opts->gen.scratch2; |
1777 if (inst->op == M68K_MULS) { | 1777 if (inst->op == M68K_MULS) { |
1778 movsx_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_W, SZ_D); | 1778 movsx_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_W, SZ_D); |
1779 } else { | 1779 } else { |
1780 movzx_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_W, SZ_D); | 1780 movzx_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_W, SZ_D); |
1781 } | 1781 } |
1782 } | 1782 } |
1783 imul_rr(code, opts->gen.scratch1, dst_reg, SZ_D); | 1783 imul_rr(code, opts->gen.scratch1, dst_reg, SZ_D); |
1784 if (dst_op->mode == MODE_REG_DISPLACE8) { | 1784 if (dst_op->mode == MODE_REG_DISPLACE8) { |
1785 mov_rrdisp(code, dst_reg, dst_op->base, dst_op->disp, SZ_D); | 1785 mov_rrdisp(code, dst_reg, dst_op->base, dst_op->disp, SZ_D); |
1786 } | 1786 } |
1787 cmp_ir(code, 0, dst_reg, SZ_D); | 1787 cmp_ir(code, 0, dst_reg, SZ_D); |
1788 update_flags(opts, N|Z|V0|C0); | 1788 update_flags(opts, N|Z|V0|C0); |
1789 } | 1789 } |
1790 | 1790 |
1791 void translate_m68k_negx(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 1791 void translate_m68k_negx(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
1792 { | 1792 { |
1793 code_info *code = &opts->gen.code; | 1793 code_info *code = &opts->gen.code; |
1794 cycles(&opts->gen, BUS); | 1794 cycles(&opts->gen, BUS); |
1804 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size); | 1804 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size); |
1805 flag_to_carry(opts, FLAG_X); | 1805 flag_to_carry(opts, FLAG_X); |
1806 sbb_rr(code, dst_op->base, opts->gen.scratch1, inst->extra.size); | 1806 sbb_rr(code, dst_op->base, opts->gen.scratch1, inst->extra.size); |
1807 mov_rr(code, opts->gen.scratch1, dst_op->base, inst->extra.size); | 1807 mov_rr(code, opts->gen.scratch1, dst_op->base, inst->extra.size); |
1808 } | 1808 } |
1809 } else { | 1809 } else { |
1810 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size); | 1810 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size); |
1811 flag_to_carry(opts, FLAG_X); | 1811 flag_to_carry(opts, FLAG_X); |
1812 sbb_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, inst->extra.size); | 1812 sbb_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, inst->extra.size); |
1813 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, inst->extra.size); | 1813 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, inst->extra.size); |
1814 } | 1814 } |
1815 set_flag_cond(opts, CC_C, FLAG_C); | 1815 set_flag_cond(opts, CC_C, FLAG_C); |
1816 code_ptr after_flag_set = code->cur + 1; | 1816 code_ptr after_flag_set = code->cur + 1; |
1817 jcc(code, CC_Z, code->cur + 2); | 1817 jcc(code, CC_Z, code->cur + 2); |
1818 set_flag(opts, 0, FLAG_Z); | 1818 set_flag(opts, 0, FLAG_Z); |
1819 *after_flag_set = code->cur - (after_flag_set+1); | 1819 *after_flag_set = code->cur - (after_flag_set+1); |
1820 set_flag_cond(opts, CC_S, FLAG_N); | 1820 set_flag_cond(opts, CC_S, FLAG_N); |
1821 set_flag_cond(opts, CC_O, FLAG_V); | 1821 set_flag_cond(opts, CC_O, FLAG_V); |
1822 if (opts->flag_regs[FLAG_C] >= 0) { | 1822 if (opts->flag_regs[FLAG_C] >= 0) { |
1823 flag_to_flag(opts, FLAG_C, FLAG_X); | 1823 flag_to_flag(opts, FLAG_C, FLAG_X); |
1824 } else { | 1824 } else { |
1825 set_flag_cond(opts, CC_C, FLAG_X); | 1825 set_flag_cond(opts, CC_C, FLAG_X); |
1826 } | 1826 } |
1827 m68k_save_result(inst, opts); | 1827 m68k_save_result(inst, opts); |
1828 } | 1828 } |
1829 | 1829 |
1830 void translate_m68k_rot(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 1830 void translate_m68k_rot(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
1831 { | 1831 { |
1832 code_info *code = &opts->gen.code; | 1832 code_info *code = &opts->gen.code; |
1833 int32_t init_flags = C|V0; | 1833 int32_t init_flags = C|V0; |
1834 if (inst->src.addr_mode == MODE_UNUSED) { | 1834 if (inst->src.addr_mode == MODE_UNUSED) { |
1835 cycles(&opts->gen, BUS); | 1835 cycles(&opts->gen, BUS); |
1836 //Memory rotate | 1836 //Memory rotate |
1837 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { | 1837 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { |
1838 flag_to_carry(opts, FLAG_X); | 1838 flag_to_carry(opts, FLAG_X); |
1839 init_flags |= X; | 1839 init_flags |= X; |
1840 } | 1840 } |
1841 op_ir(code, inst, 1, dst_op->base, inst->extra.size); | 1841 op_ir(code, inst, 1, dst_op->base, inst->extra.size); |
1842 update_flags(opts, init_flags); | 1842 update_flags(opts, init_flags); |
1843 cmp_ir(code, 0, dst_op->base, inst->extra.size); | 1843 cmp_ir(code, 0, dst_op->base, inst->extra.size); |
1844 update_flags(opts, Z|N); | 1844 update_flags(opts, Z|N); |
1845 m68k_save_result(inst, opts); | 1845 m68k_save_result(inst, opts); |
1846 } else { | 1846 } else { |
1847 if (src_op->mode == MODE_IMMED) { | 1847 if (src_op->mode == MODE_IMMED) { |
1848 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op->disp*2); | 1848 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op->disp*2); |
1849 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { | 1849 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { |
1850 flag_to_carry(opts, FLAG_X); | 1850 flag_to_carry(opts, FLAG_X); |
1851 init_flags |= X; | 1851 init_flags |= X; |
1852 } | 1852 } |
1853 if (dst_op->mode == MODE_REG_DIRECT) { | 1853 if (dst_op->mode == MODE_REG_DIRECT) { |
1854 op_ir(code, inst, src_op->disp, dst_op->base, inst->extra.size); | 1854 op_ir(code, inst, src_op->disp, dst_op->base, inst->extra.size); |
1855 } else { | 1855 } else { |
1856 op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); | 1856 op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); |
1857 } | 1857 } |
1858 update_flags(opts, init_flags); | 1858 update_flags(opts, init_flags); |
1859 } else { | 1859 } else { |
1860 if (src_op->mode == MODE_REG_DIRECT) { | 1860 if (src_op->mode == MODE_REG_DIRECT) { |
1861 if (src_op->base != opts->gen.scratch1) { | 1861 if (src_op->base != opts->gen.scratch1) { |
1862 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B); | 1862 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B); |
1863 } | 1863 } |
1864 } else { | 1864 } else { |
1865 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B); | 1865 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B); |
1866 } | 1866 } |
1867 and_ir(code, 63, opts->gen.scratch1, SZ_D); | 1867 and_ir(code, 63, opts->gen.scratch1, SZ_D); |
1868 code_ptr zero_off = code->cur + 1; | 1868 code_ptr zero_off = code->cur + 1; |
1869 jcc(code, CC_Z, code->cur + 2); | 1869 jcc(code, CC_Z, code->cur + 2); |
1870 //add 2 cycles for every bit shifted | 1870 //add 2 cycles for every bit shifted |
1871 mov_ir(code, 2 * opts->gen.clock_divider, opts->gen.scratch2, SZ_D); | 1871 mov_ir(code, 2 * opts->gen.clock_divider, opts->gen.scratch2, SZ_D); |
1875 code_ptr norm_off = code->cur + 1; | 1875 code_ptr norm_off = code->cur + 1; |
1876 jcc(code, CC_L, code->cur + 2); | 1876 jcc(code, CC_L, code->cur + 2); |
1877 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { | 1877 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { |
1878 flag_to_carry(opts, FLAG_X); | 1878 flag_to_carry(opts, FLAG_X); |
1879 init_flags |= X; | 1879 init_flags |= X; |
1880 } else { | 1880 } else { |
1881 sub_ir(code, 32, opts->gen.scratch1, SZ_B); | 1881 sub_ir(code, 32, opts->gen.scratch1, SZ_B); |
1882 } | 1882 } |
1883 if (dst_op->mode == MODE_REG_DIRECT) { | 1883 if (dst_op->mode == MODE_REG_DIRECT) { |
1884 op_ir(code, inst, 31, dst_op->base, inst->extra.size); | 1884 op_ir(code, inst, 31, dst_op->base, inst->extra.size); |
1885 op_ir(code, inst, 1, dst_op->base, inst->extra.size); | 1885 op_ir(code, inst, 1, dst_op->base, inst->extra.size); |
1886 } else { | 1886 } else { |
1887 op_irdisp(code, inst, 31, dst_op->base, dst_op->disp, inst->extra.size); | 1887 op_irdisp(code, inst, 31, dst_op->base, dst_op->disp, inst->extra.size); |
1888 op_irdisp(code, inst, 1, dst_op->base, dst_op->disp, inst->extra.size); | 1888 op_irdisp(code, inst, 1, dst_op->base, dst_op->disp, inst->extra.size); |
1889 } | 1889 } |
1890 | 1890 |
1891 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { | 1891 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { |
1892 set_flag_cond(opts, CC_C, FLAG_X); | 1892 set_flag_cond(opts, CC_C, FLAG_X); |
1893 sub_ir(code, 32, opts->gen.scratch1, SZ_B); | 1893 sub_ir(code, 32, opts->gen.scratch1, SZ_B); |
1894 *norm_off = code->cur - (norm_off+1); | 1894 *norm_off = code->cur - (norm_off+1); |
1895 flag_to_carry(opts, FLAG_X); | 1895 flag_to_carry(opts, FLAG_X); |
1896 } else { | 1896 } else { |
1897 *norm_off = code->cur - (norm_off+1); | 1897 *norm_off = code->cur - (norm_off+1); |
1898 } | 1898 } |
1899 if (dst_op->mode == MODE_REG_DIRECT) { | 1899 if (dst_op->mode == MODE_REG_DIRECT) { |
1900 op_r(code, inst, dst_op->base, inst->extra.size); | 1900 op_r(code, inst, dst_op->base, inst->extra.size); |
1901 } else { | 1901 } else { |
1902 op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size); | 1902 op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size); |
1903 } | 1903 } |
1904 update_flags(opts, init_flags); | 1904 update_flags(opts, init_flags); |
1905 code_ptr end_off = code->cur + 1; | 1905 code_ptr end_off = code->cur + 1; |
1906 jmp(code, code->cur + 2); | 1906 jmp(code, code->cur + 2); |
1907 *zero_off = code->cur - (zero_off+1); | 1907 *zero_off = code->cur - (zero_off+1); |
1908 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { | 1908 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { |
1909 //Carry flag is set to X flag when count is 0, this is different from ROR/ROL | 1909 //Carry flag is set to X flag when count is 0, this is different from ROR/ROL |
1910 flag_to_flag(opts, FLAG_X, FLAG_C); | 1910 flag_to_flag(opts, FLAG_X, FLAG_C); |
1911 } else { | 1911 } else { |
1912 set_flag(opts, 0, FLAG_C); | 1912 set_flag(opts, 0, FLAG_C); |
1913 } | 1913 } |
1914 *end_off = code->cur - (end_off+1); | 1914 *end_off = code->cur - (end_off+1); |
1915 } | 1915 } |
1916 if (dst_op->mode == MODE_REG_DIRECT) { | 1916 if (dst_op->mode == MODE_REG_DIRECT) { |
1917 cmp_ir(code, 0, dst_op->base, inst->extra.size); | 1917 cmp_ir(code, 0, dst_op->base, inst->extra.size); |
1918 } else { | 1918 } else { |
1919 cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size); | 1919 cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size); |
1920 } | 1920 } |
1921 update_flags(opts, Z|N); | 1921 update_flags(opts, Z|N); |
1922 } | 1922 } |
1923 } | 1923 } |
1924 | 1924 |
1925 void translate_m68k_illegal(m68k_options *opts, m68kinst *inst) | 1925 void translate_m68k_illegal(m68k_options *opts, m68kinst *inst) |
1926 { | 1926 { |
1927 code_info *code = &opts->gen.code; | 1927 code_info *code = &opts->gen.code; |
1928 call(code, opts->gen.save_context); | 1928 call(code, opts->gen.save_context); |
1929 call_args(code, (code_ptr)print_regs_exit, 1, opts->gen.context_reg); | 1929 call_args(code, (code_ptr)print_regs_exit, 1, opts->gen.context_reg); |
1930 } | 1930 } |
1931 | 1931 |
1932 #define BIT_SUPERVISOR 5 | 1932 #define BIT_SUPERVISOR 5 |
1933 | 1933 |
1934 void translate_m68k_andi_ori_ccr_sr(m68k_options *opts, m68kinst *inst) | 1934 void translate_m68k_andi_ori_ccr_sr(m68k_options *opts, m68kinst *inst) |
1935 { | 1935 { |
1941 for (int i = 0; i < 5; i++) | 1941 for (int i = 0; i < 5; i++) |
1942 { | 1942 { |
1943 if ((base_flag == X0) ^ (inst->src.params.immed & 1 << i) > 0) | 1943 if ((base_flag == X0) ^ (inst->src.params.immed & 1 << i) > 0) |
1944 { | 1944 { |
1945 flag_mask |= base_flag << ((4 - i) * 3); | 1945 flag_mask |= base_flag << ((4 - i) * 3); |
1946 } | 1946 } |
1947 } | 1947 } |
1948 update_flags(opts, flag_mask); | 1948 update_flags(opts, flag_mask); |
1949 if (inst->op == M68K_ANDI_SR || inst->op == M68K_ORI_SR) { | 1949 if (inst->op == M68K_ANDI_SR || inst->op == M68K_ORI_SR) { |
1950 if (inst->op == M68K_ANDI_SR) { | 1950 if (inst->op == M68K_ANDI_SR) { |
1951 and_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 1951 and_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
1952 } else { | 1952 } else { |
1953 or_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 1953 or_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
1954 } | 1954 } |
1955 if (inst->op == M68K_ANDI_SR && !(inst->src.params.immed & (1 << (BIT_SUPERVISOR + 8)))) { | 1955 if (inst->op == M68K_ANDI_SR && !(inst->src.params.immed & (1 << (BIT_SUPERVISOR + 8)))) { |
1956 //leave supervisor mode | 1956 //leave supervisor mode |
1957 swap_ssp_usp(opts); | 1957 swap_ssp_usp(opts); |
1958 } | 1958 } |
1959 if ((inst->op == M68K_ANDI_SR && (inst->src.params.immed & 0x700) != 0x700) | 1959 if ((inst->op == M68K_ANDI_SR && (inst->src.params.immed & 0x700) != 0x700) |
1960 || (inst->op == M68K_ORI_SR && inst->src.params.immed & 0x700)) { | 1960 || (inst->op == M68K_ORI_SR && inst->src.params.immed & 0x700)) { |
1961 call(code, opts->do_sync); | 1961 call(code, opts->do_sync); |
1962 } | 1962 } |
1963 } | 1963 } |
1964 } | 1964 } |
1965 | 1965 |
1966 void translate_m68k_eori_ccr_sr(m68k_options *opts, m68kinst *inst) | 1966 void translate_m68k_eori_ccr_sr(m68k_options *opts, m68kinst *inst) |
1967 { | 1967 { |
1968 code_info *code = &opts->gen.code; | 1968 code_info *code = &opts->gen.code; |
1969 cycles(&opts->gen, 20); | 1969 cycles(&opts->gen, 20); |
1970 //TODO: If ANDI to SR, trap if not in supervisor mode | 1970 //TODO: If ANDI to SR, trap if not in supervisor mode |
1971 if (inst->src.params.immed & 0x1) { | 1971 if (inst->src.params.immed & 0x1) { |
1972 xor_flag(opts, 1, FLAG_C); | 1972 xor_flag(opts, 1, FLAG_C); |
1973 } | 1973 } |
1974 if (inst->src.params.immed & 0x2) { | 1974 if (inst->src.params.immed & 0x2) { |
1975 xor_flag(opts, 1, FLAG_V); | 1975 xor_flag(opts, 1, FLAG_V); |
1976 } | 1976 } |
1977 if (inst->src.params.immed & 0x4) { | 1977 if (inst->src.params.immed & 0x4) { |
1978 xor_flag(opts, 1, FLAG_Z); | 1978 xor_flag(opts, 1, FLAG_Z); |
1979 } | 1979 } |
1980 if (inst->src.params.immed & 0x8) { | 1980 if (inst->src.params.immed & 0x8) { |
1981 xor_flag(opts, 1, FLAG_N); | 1981 xor_flag(opts, 1, FLAG_N); |
1982 } | 1982 } |
1983 if (inst->src.params.immed & 0x10) { | 1983 if (inst->src.params.immed & 0x10) { |
1984 xor_flag(opts, 1, FLAG_X); | 1984 xor_flag(opts, 1, FLAG_X); |
1985 } | 1985 } |
1986 if (inst->op == M68K_ORI_SR) { | 1986 if (inst->op == M68K_ORI_SR) { |
1987 xor_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 1987 xor_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
1988 if (inst->src.params.immed & 0x700) { | 1988 if (inst->src.params.immed & 0x700) { |
1989 call(code, opts->do_sync); | 1989 call(code, opts->do_sync); |
1990 } | 1990 } |
1991 } | 1991 } |
1992 } | 1992 } |
1993 | 1993 |
1994 void set_all_flags(m68k_options *opts, uint8_t flags) | 1994 void set_all_flags(m68k_options *opts, uint8_t flags) |
1995 { | 1995 { |
1996 uint32_t flag_mask = flags & 0x10 ? X1 : X0; | 1996 uint32_t flag_mask = flags & 0x10 ? X1 : X0; |
1997 flag_mask |= flags & 0x8 ? N1 : N0; | 1997 flag_mask |= flags & 0x8 ? N1 : N0; |
1998 flag_mask |= flags & 0x4 ? Z1 : Z0; | 1998 flag_mask |= flags & 0x4 ? Z1 : Z0; |
1999 flag_mask |= flags & 0x2 ? V1 : V0; | 1999 flag_mask |= flags & 0x2 ? V1 : V0; |
2000 flag_mask |= flags & 0x1 ? C1 : C0; | 2000 flag_mask |= flags & 0x1 ? C1 : C0; |
2001 update_flags(opts, flag_mask); | 2001 update_flags(opts, flag_mask); |
2002 } | 2002 } |
2003 | 2003 |
2004 void translate_m68k_move_ccr_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 2004 void translate_m68k_move_ccr_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
2005 { | 2005 { |
2006 code_info *code = &opts->gen.code; | 2006 code_info *code = &opts->gen.code; |
2007 //TODO: Privilege check for MOVE to SR | 2007 //TODO: Privilege check for MOVE to SR |
2010 if (inst->op == M68K_MOVE_SR) { | 2010 if (inst->op == M68K_MOVE_SR) { |
2011 mov_irdisp(code, (src_op->disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 2011 mov_irdisp(code, (src_op->disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
2012 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 2012 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
2013 //leave supervisor mode | 2013 //leave supervisor mode |
2014 swap_ssp_usp(opts); | 2014 swap_ssp_usp(opts); |
2015 } | 2015 } |
2016 call(code, opts->do_sync); | 2016 call(code, opts->do_sync); |
2017 } | 2017 } |
2018 cycles(&opts->gen, 12); | 2018 cycles(&opts->gen, 12); |
2019 } else { | 2019 } else { |
2020 if (src_op->base != opts->gen.scratch1) { | 2020 if (src_op->base != opts->gen.scratch1) { |
2021 if (src_op->mode == MODE_REG_DIRECT) { | 2021 if (src_op->mode == MODE_REG_DIRECT) { |
2022 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_W); | 2022 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_W); |
2023 } else { | 2023 } else { |
2024 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W); | 2024 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W); |
2025 } | 2025 } |
2026 } | 2026 } |
2027 call(code, inst->op == M68K_MOVE_SR ? opts->set_sr : opts->set_ccr); | 2027 call(code, inst->op == M68K_MOVE_SR ? opts->set_sr : opts->set_ccr); |
2028 cycles(&opts->gen, 12); | 2028 cycles(&opts->gen, 12); |
2029 } | 2029 } |
2030 } | 2030 } |
2031 | 2031 |
2032 void translate_m68k_stop(m68k_options *opts, m68kinst *inst) | 2032 void translate_m68k_stop(m68k_options *opts, m68kinst *inst) |
2033 { | 2033 { |
2034 //TODO: Trap if not in system mode | 2034 //TODO: Trap if not in system mode |
2035 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction | 2035 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction |
2036 //possibly even 12 since that's how long MOVE to SR takes | 2036 //possibly even 12 since that's how long MOVE to SR takes |
2037 //On further thought prefetch + the fact that this stops the CPU may make | 2037 //On further thought prefetch + the fact that this stops the CPU may make |
2038 //Motorola's accounting make sense here | 2038 //Motorola's accounting make sense here |
2039 code_info *code = &opts->gen.code; | 2039 code_info *code = &opts->gen.code; |
2040 cycles(&opts->gen, BUS*2); | 2040 cycles(&opts->gen, BUS*2); |
2041 set_all_flags(opts, inst->src.params.immed); | 2041 set_all_flags(opts, inst->src.params.immed); |
2042 mov_irdisp(code, (inst->src.params.immed >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 2042 mov_irdisp(code, (inst->src.params.immed >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
2043 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 2043 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
2044 //leave supervisor mode | 2044 //leave supervisor mode |
2045 swap_ssp_usp(opts); | 2045 swap_ssp_usp(opts); |
2046 } | 2046 } |
2047 code_ptr loop_top = code->cur; | 2047 code_ptr loop_top = code->cur; |
2048 call(code, opts->do_sync); | 2048 call(code, opts->do_sync); |
2049 cmp_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D); | 2049 cmp_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D); |
2050 code_ptr normal_cycle_up = code->cur + 1; | 2050 code_ptr normal_cycle_up = code->cur + 1; |
2051 jcc(code, CC_A, code->cur + 2); | 2051 jcc(code, CC_A, code->cur + 2); |
2055 *normal_cycle_up = code->cur - (normal_cycle_up + 1); | 2055 *normal_cycle_up = code->cur - (normal_cycle_up + 1); |
2056 mov_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D); | 2056 mov_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D); |
2057 *after_cycle_up = code->cur - (after_cycle_up+1); | 2057 *after_cycle_up = code->cur - (after_cycle_up+1); |
2058 cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D); | 2058 cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D); |
2059 jcc(code, CC_C, loop_top); | 2059 jcc(code, CC_C, loop_top); |
2060 } | 2060 } |
2061 | 2061 |
2062 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 2062 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
2063 { | 2063 { |
2064 code_info *code = &opts->gen.code; | 2064 code_info *code = &opts->gen.code; |
2065 //TODO: Trap if not in system mode | 2065 //TODO: Trap if not in system mode |
2066 call(code, opts->get_sr); | 2066 call(code, opts->get_sr); |
2067 if (dst_op->mode == MODE_REG_DIRECT) { | 2067 if (dst_op->mode == MODE_REG_DIRECT) { |
2068 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W); | 2068 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W); |
2069 } else { | 2069 } else { |
2070 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_W); | 2070 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_W); |
2071 } | 2071 } |
2072 m68k_save_result(inst, opts); | 2072 m68k_save_result(inst, opts); |
2073 } | 2073 } |
2074 | 2074 |
2075 void translate_m68k_reset(m68k_options *opts, m68kinst *inst) | 2075 void translate_m68k_reset(m68k_options *opts, m68kinst *inst) |
2076 { | 2076 { |
2112 void nop_fill_or_jmp_next(code_info *code, code_ptr old_end, code_ptr next_inst) | 2112 void nop_fill_or_jmp_next(code_info *code, code_ptr old_end, code_ptr next_inst) |
2113 { | 2113 { |
2114 if (next_inst == old_end && next_inst - code->cur < 2) { | 2114 if (next_inst == old_end && next_inst - code->cur < 2) { |
2115 while (code->cur < old_end) { | 2115 while (code->cur < old_end) { |
2116 *(code->cur++) = 0x90; //NOP | 2116 *(code->cur++) = 0x90; //NOP |
2117 } | 2117 } |
2118 } else { | 2118 } else { |
2119 jmp(code, next_inst); | 2119 jmp(code, next_inst); |
2120 } | 2120 } |
2121 } | 2121 } |
2122 | 2122 |
2123 m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context) | 2123 m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context) |
2139 call_args(code,(code_ptr)m68k_retranslate_inst, 2, options->gen.scratch2, options->gen.context_reg); | 2139 call_args(code,(code_ptr)m68k_retranslate_inst, 2, options->gen.scratch2, options->gen.context_reg); |
2140 pop_r(code, options->gen.context_reg); | 2140 pop_r(code, options->gen.context_reg); |
2141 mov_rr(code, RAX, options->gen.scratch1, SZ_PTR); | 2141 mov_rr(code, RAX, options->gen.scratch1, SZ_PTR); |
2142 call(code, options->gen.load_context); | 2142 call(code, options->gen.load_context); |
2143 jmp_r(code, options->gen.scratch1); | 2143 jmp_r(code, options->gen.scratch1); |
2144 } | 2144 } |
2145 jmp(&orig, options->retrans_stub); | 2145 jmp(&orig, options->retrans_stub); |
2146 } | 2146 } |
2147 return context; | 2147 return context; |
2148 } | 2148 } |
2149 | 2149 |