Mercurial > repos > blastem
comparison m68k_core_x86.c @ 1363:df6af7187b36
Fix to M68K interrupt latency for most instructions. Still needs some work for RAW_IMPL instructions besides move
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 19 May 2017 20:27:35 -0700 |
parents | 87bbc4bec958 |
children | eaca4443e831 |
comparison
equal
deleted
inserted
replaced
1362:83bdd358f3a7 | 1363:df6af7187b36 |
---|---|
348 { | 348 { |
349 areg_to_native(opts, op->params.regs.pri, native_reg); | 349 areg_to_native(opts, op->params.regs.pri, native_reg); |
350 calc_index_disp8(opts, op, native_reg); | 350 calc_index_disp8(opts, op, native_reg); |
351 } | 351 } |
352 | 352 |
353 void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst) | 353 void m68k_check_cycles_int_latch(m68k_options *opts) |
354 { | |
355 code_info *code = &opts->gen.code; | |
356 uint8_t cc; | |
357 if (opts->gen.limit < 0) { | |
358 cmp_ir(code, 1, opts->gen.cycles, SZ_D); | |
359 cc = CC_NS; | |
360 } else { | |
361 cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D); | |
362 cc = CC_A; | |
363 } | |
364 code_ptr jmp_off = code->cur+1; | |
365 jcc(code, cc, jmp_off+1); | |
366 call(code, opts->handle_int_latch); | |
367 *jmp_off = code->cur - (jmp_off+1); | |
368 } | |
369 | |
370 uint8_t translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst) | |
354 { | 371 { |
355 code_info *code = &opts->gen.code; | 372 code_info *code = &opts->gen.code; |
356 m68k_op_info *op = dst ? &inst->dst : &inst->src; | 373 m68k_op_info *op = dst ? &inst->dst : &inst->src; |
357 int8_t reg = native_reg(op, opts); | 374 int8_t reg = native_reg(op, opts); |
358 uint8_t sec_reg; | 375 uint8_t sec_reg; |
376 uint8_t ret = 1; | |
359 int32_t dec_amount, inc_amount; | 377 int32_t dec_amount, inc_amount; |
360 if (reg >= 0) { | 378 if (reg >= 0) { |
361 ea->mode = MODE_REG_DIRECT; | 379 ea->mode = MODE_REG_DIRECT; |
362 if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { | 380 if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { |
363 movsx_rr(code, reg, opts->gen.scratch1, SZ_W, SZ_D); | 381 movsx_rr(code, reg, opts->gen.scratch1, SZ_W, SZ_D); |
364 ea->base = opts->gen.scratch1; | 382 ea->base = opts->gen.scratch1; |
365 } else { | 383 } else { |
366 ea->base = reg; | 384 ea->base = reg; |
367 } | 385 } |
368 return; | 386 return 0; |
369 } | 387 } |
370 switch (op->addr_mode) | 388 switch (op->addr_mode) |
371 { | 389 { |
372 case MODE_REG: | 390 case MODE_REG: |
373 case MODE_AREG: | 391 case MODE_AREG: |
386 mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, inst->extra.size); | 404 mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, inst->extra.size); |
387 } | 405 } |
388 ea->mode = MODE_REG_DIRECT; | 406 ea->mode = MODE_REG_DIRECT; |
389 ea->base = opts->gen.scratch1; | 407 ea->base = opts->gen.scratch1; |
390 //we're explicitly handling the areg dest here, so we exit immediately | 408 //we're explicitly handling the areg dest here, so we exit immediately |
391 return; | 409 return 0; |
392 } | 410 } |
411 ret = 0; | |
393 break; | 412 break; |
394 case MODE_AREG_PREDEC: | 413 case MODE_AREG_PREDEC: |
395 if (dst && inst->src.addr_mode == MODE_AREG_PREDEC) { | 414 if (dst && inst->src.addr_mode == MODE_AREG_PREDEC) { |
396 push_r(code, opts->gen.scratch1); | 415 push_r(code, opts->gen.scratch1); |
397 } | 416 } |
503 ea->disp = op->params.immed; | 522 ea->disp = op->params.immed; |
504 //sign extend value when the destination is an address register | 523 //sign extend value when the destination is an address register |
505 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && ea->disp & 0x8000) { | 524 if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && ea->disp & 0x8000) { |
506 ea->disp |= 0xFFFF0000; | 525 ea->disp |= 0xFFFF0000; |
507 } | 526 } |
508 return; | 527 return inst->variant != VAR_QUICK; |
509 default: | 528 default: |
510 m68k_disasm(inst, disasm_buf); | 529 m68k_disasm(inst, disasm_buf); |
511 fatal_error("%X: %s\naddress mode %d not implemented (%s)\n", inst->address, disasm_buf, op->addr_mode, dst ? "dst" : "src"); | 530 fatal_error("%X: %s\naddress mode %d not implemented (%s)\n", inst->address, disasm_buf, op->addr_mode, dst ? "dst" : "src"); |
512 } | 531 } |
513 if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { | 532 if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { |
517 movsx_rdispr(code, ea->base, ea->disp, opts->gen.scratch1, SZ_W, SZ_D); | 536 movsx_rdispr(code, ea->base, ea->disp, opts->gen.scratch1, SZ_W, SZ_D); |
518 ea->mode = MODE_REG_DIRECT; | 537 ea->mode = MODE_REG_DIRECT; |
519 } | 538 } |
520 ea->base = opts->gen.scratch1; | 539 ea->base = opts->gen.scratch1; |
521 } | 540 } |
541 return ret; | |
522 } | 542 } |
523 | 543 |
524 void check_user_mode_swap_ssp_usp(m68k_options *opts) | 544 void check_user_mode_swap_ssp_usp(m68k_options *opts) |
525 { | 545 { |
526 code_info * code = &opts->gen.code; | 546 code_info * code = &opts->gen.code; |
538 int8_t reg, flags_reg, sec_reg; | 558 int8_t reg, flags_reg, sec_reg; |
539 uint8_t dir = 0; | 559 uint8_t dir = 0; |
540 int32_t offset; | 560 int32_t offset; |
541 int32_t inc_amount, dec_amount; | 561 int32_t inc_amount, dec_amount; |
542 host_ea src; | 562 host_ea src; |
543 translate_m68k_op(inst, &src, opts, 0); | 563 if (translate_m68k_op(inst, &src, opts, 0)) { |
564 m68k_check_cycles_int_latch(opts); | |
565 } | |
544 reg = native_reg(&(inst->dst), opts); | 566 reg = native_reg(&(inst->dst), opts); |
545 | 567 |
546 if (inst->dst.addr_mode != MODE_AREG) { | 568 if (inst->dst.addr_mode != MODE_AREG) { |
547 if (src.mode == MODE_REG_DIRECT) { | 569 if (src.mode == MODE_REG_DIRECT) { |
548 flags_reg = src.base; | 570 flags_reg = src.base; |
3083 //discard function return address | 3105 //discard function return address |
3084 pop_r(code, opts->gen.scratch2); | 3106 pop_r(code, opts->gen.scratch2); |
3085 add_ir(code, 16-sizeof(void *), RSP, SZ_PTR); | 3107 add_ir(code, 16-sizeof(void *), RSP, SZ_PTR); |
3086 jmp_r(code, opts->gen.scratch1); | 3108 jmp_r(code, opts->gen.scratch1); |
3087 code->stack_off = tmp_stack_off; | 3109 code->stack_off = tmp_stack_off; |
3110 | |
3111 opts->handle_int_latch = code->cur; | |
3112 cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D); | |
3113 code_ptr do_latch = code->cur + 1; | |
3114 jcc(code, CC_NC, do_latch); | |
3115 retn(code); | |
3116 *do_latch = code->cur - (do_latch + 1); | |
3117 cmp_irdisp(code, INT_PENDING_NONE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); | |
3118 do_latch = code->cur + 1; | |
3119 jcc(code, CC_Z, do_latch); | |
3120 retn(code); | |
3121 *do_latch = code->cur - (do_latch + 1); | |
3122 //store current interrupt number so it doesn't change before we start processing the vector | |
3123 push_r(code, opts->gen.scratch1); | |
3124 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B); | |
3125 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); | |
3126 pop_r(code, opts->gen.scratch1); | |
3127 retn(code); | |
3088 | 3128 |
3089 opts->trap = code->cur; | 3129 opts->trap = code->cur; |
3090 push_r(code, opts->gen.scratch2); | 3130 push_r(code, opts->gen.scratch2); |
3091 //swap USP and SSP if not already in supervisor mode | 3131 //swap USP and SSP if not already in supervisor mode |
3092 check_user_mode_swap_ssp_usp(opts); | 3132 check_user_mode_swap_ssp_usp(opts); |