Search
lxdream.org :: lxdream/src/sh4/sh4core.in :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4core.in
changeset 948:545c85cc56f1
prev946:d41ee7994db7
next951:63483914846f
author nkeynes
date Wed Jan 07 04:39:04 2009 +0000 (11 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Introduce sh4_finalize_instruction to clean-up on instruction exits
Remove the sh4_flush_icache special cases, now works through the
general case.
file annotate diff log raw
1.1 --- a/src/sh4/sh4core.in Tue Jan 06 01:58:08 2009 +0000
1.2 +++ b/src/sh4/sh4core.in Wed Jan 07 04:39:04 2009 +0000
1.3 @@ -102,9 +102,6 @@
1.4
1.5 /********************** SH4 emulation core ****************************/
1.6
1.7 -#define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
1.8 -#define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }while(0)
1.9 -
1.10 #if(SH4_CALLTRACE == 1)
1.11 #define MAX_CALLSTACK 32
1.12 static struct call_stack {
1.13 @@ -187,10 +184,6 @@
1.14 #define MEM_WRITE_LONG( addr, val ) ADDRSPACE[(addr)>>12]->write_long(addr, val)
1.15 #define MEM_PREFETCH( addr ) ADDRSPACE[(addr)>>12]->prefetch(addr)
1.16 #endif
1.17 -
1.18 -
1.19 -
1.20 -
1.21
1.22 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
1.23
1.24 @@ -223,6 +216,131 @@
1.25 MEM_WRITE_LONG(addr, *((uint32_t *)&FR((reg))) ); \
1.26 }
1.27
1.28 +#define UNDEF(ir)
1.29 +#define UNIMP(ir)
1.30 +
1.31 +/**
1.32 + * Perform instruction-completion following core exit of a partially completed
1.33 + * instruction. NOTE: This is only allowed on memory writes, operation is not
1.34 + * guaranteed in any other case.
1.35 + */
1.36 +void sh4_finalize_instruction( void )
1.37 +{
1.38 + unsigned short ir;
1.39 + uint32_t tmp;
1.40 +
1.41 + assert( IS_IN_ICACHE(sh4r.pc) );
1.42 + ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
1.43 +
1.44 + /**
1.45 + * Note - we can't take an exit on a control transfer instruction itself,
1.46 + * which means the exit must have happened in the delay slot. So for these
1.47 + * cases, finalize the delay slot instruction, and re-execute the control transfer.
1.48 + *
1.49 + * For delay slots which modify the argument used in the branch instruction,
1.50 + * we pretty much just assume that that can't have already happened in an exit case.
1.51 + */
1.52 +
1.53 +%%
1.54 +BRA disp {:
1.55 + sh4r.pc += 2;
1.56 + sh4_finalize_instruction();
1.57 + sh4r.pc += disp;
1.58 + sh4r.slice_cycle += sh4_cpu_period;
1.59 +:}
1.60 +BRAF Rn {:
1.61 + sh4r.pc += 2;
1.62 + tmp = sh4r.r[Rn];
1.63 + sh4_finalize_instruction();
1.64 + sh4r.pc += tmp;
1.65 + sh4r.slice_cycle += sh4_cpu_period;
1.66 +:}
1.67 +BSR disp {:
1.68 + /* Note: PR is already set */
1.69 + sh4r.pc += 2;
1.70 + sh4_finalize_instruction();
1.71 + sh4r.pc += disp;
1.72 + sh4r.slice_cycle += sh4_cpu_period;
1.73 +:}
1.74 +BSRF Rn {:
1.75 + /* Note: PR is already set */
1.76 + sh4r.pc += 2;
1.77 + tmp = sh4r.r[Rn];
1.78 + sh4_finalize_instruction();
1.79 + sh4r.pc += tmp;
1.80 + sh4r.slice_cycle += sh4_cpu_period;
1.81 +:}
1.82 +BF/S disp {:
1.83 + sh4r.pc += 2;
1.84 + sh4_finalize_instruction();
1.85 + if( !sh4r.t ) {
1.86 + sh4r.pc += disp;
1.87 + }
1.88 + sh4r.slice_cycle += sh4_cpu_period;
1.89 +:}
1.90 +BT/S disp {:
1.91 + sh4r.pc += 2;
1.92 + sh4_finalize_instruction();
1.93 + if( sh4r.t ) {
1.94 + sh4r.pc += disp;
1.95 + }
1.96 + sh4r.slice_cycle += sh4_cpu_period;
1.97 +:}
1.98 +JMP @Rn {:
1.99 + sh4r.pc += 2;
1.100 + tmp = sh4r.r[Rn];
1.101 + sh4_finalize_instruction();
1.102 + sh4r.pc = tmp;
1.103 + sh4r.new_pc = tmp + 2;
1.104 + sh4r.slice_cycle += 2*sh4_cpu_period;
1.105 + return;
1.106 +:}
1.107 +JSR @Rn {:
1.108 + /* Note: PR is already set */
1.109 + sh4r.pc += 2;
1.110 + tmp = sh4r.r[Rn];
1.111 + sh4_finalize_instruction();
1.112 + sh4r.pc = tmp;
1.113 + sh4r.new_pc = tmp + 2;
1.114 + sh4r.slice_cycle += 2*sh4_cpu_period;
1.115 + return;
1.116 +:}
1.117 +RTS {:
1.118 + sh4r.pc += 2;
1.119 + sh4_finalize_instruction();
1.120 + sh4r.pc = sh4r.pr;
1.121 + sh4r.new_pc = sh4r.pr + 2;
1.122 + sh4r.slice_cycle += 2*sh4_cpu_period;
1.123 + return;
1.124 +:}
1.125 +RTE {:
1.126 + /* SR is already set */
1.127 + sh4r.pc += 2;
1.128 + sh4_finalize_instruction();
1.129 + sh4r.pc = sh4r.spc;
1.130 + sh4r.new_pc = sh4r.pr + 2;
1.131 + sh4r.slice_cycle += 2*sh4_cpu_period;
1.132 + return;
1.133 +:}
1.134 +MOV.B Rm, @-Rn {: sh4r.r[Rn]--; :}
1.135 +MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; :}
1.136 +MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; :}
1.137 +MOV.B @Rm+, Rn {: sh4r.r[Rm] ++; :}
1.138 +MOV.W @Rm+, Rn {: sh4r.r[Rm] += 2; :}
1.139 +MOV.L @Rm+, Rn {: sh4r.r[Rm] += 4; :}
1.140 +%%
1.141 + sh4r.pc += 2;
1.142 + sh4r.new_pc = sh4r.pc+2;
1.143 + sh4r.slice_cycle += sh4_cpu_period;
1.144 +}
1.145 +
1.146 +#undef UNDEF(ir)
1.147 +#undef UNIMP(ir)
1.148 +
1.149 +#define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
1.150 +#define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }while(0)
1.151 +
1.152 +
1.153 gboolean sh4_execute_instruction( void )
1.154 {
1.155 uint32_t pc;
1.156 @@ -265,6 +383,14 @@
1.157 }
1.158 assert( IS_IN_ICACHE(pc) );
1.159 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
1.160 +
1.161 + /* FIXME: This is a bit of a hack, but the PC of the delay slot should not
1.162 + * be visible until after the instruction has executed (for exception
1.163 + * correctness)
1.164 + */
1.165 + if( sh4r.in_delay_slot ) {
1.166 + sh4r.pc -= 2;
1.167 + }
1.168 %%
1.169 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
1.170 AND #imm, R0 {: R0 &= imm; :}
.