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);