Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Save link information in *AL(L) instructions unconditionally
All "Jump and link" and "Branch and link" like instructions save the PC in the
target register unconditionally and not only when the branch/jump is taken.
The specification is not clear whether the store is actually made before or
after the delay slot and therefore the behavior of the dynarecs ("link" before
delay slot) is used.

Reported-by: Nebuleon <nebuleon.fumika@gmail.com>
  • Loading branch information
ecsv committed Jan 28, 2014
1 parent 94d7677 commit cb891a0
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 15 deletions.
10 changes: 5 additions & 5 deletions src/r4300/pure_interp.c
Expand Up @@ -55,6 +55,11 @@ static void prefetch(void);
const unsigned int jump_target = (destination); \
long long int *link_register = (link); \
if (cop1 && check_cop1_unusable()) return; \
if (link_register != &reg[0]) \
{ \
*link_register=interp_PC.addr + 8; \
sign_extended(*link_register); \
} \
if (!likely || take_jump) \
{ \
interp_PC.addr += 4; \
Expand All @@ -65,11 +70,6 @@ static void prefetch(void);
delay_slot=0; \
if (take_jump && !skip_jump) \
{ \
if (link_register != &reg[0]) \
{ \
*link_register=interp_PC.addr; \
sign_extended(*link_register); \
} \
interp_PC.addr = jump_target; \
} \
} \
Expand Down
20 changes: 10 additions & 10 deletions src/r4300/r4300.c
Expand Up @@ -88,6 +88,11 @@ int rounding_mode = 0x33F, trunc_mode = 0xF3F, round_mode = 0x33F,
const unsigned int jump_target = (destination); \
long long int *link_register = (link); \
if (cop1 && check_cop1_unusable()) return; \
if (link_register != &reg[0]) \
{ \
*link_register=PC->addr + 8; \
sign_extended(*link_register); \
} \
if (!likely || take_jump) \
{ \
PC++; \
Expand All @@ -98,11 +103,6 @@ int rounding_mode = 0x33F, trunc_mode = 0xF3F, round_mode = 0x33F,
delay_slot=0; \
if (take_jump && !skip_jump) \
{ \
if (link_register != &reg[0]) \
{ \
*link_register=PC->addr; \
sign_extended(*link_register); \
} \
PC=actual->block+((jump_target-actual->start)>>2); \
} \
} \
Expand All @@ -120,6 +120,11 @@ int rounding_mode = 0x33F, trunc_mode = 0xF3F, round_mode = 0x33F,
const unsigned int jump_target = (destination); \
long long int *link_register = (link); \
if (cop1 && check_cop1_unusable()) return; \
if (link_register != &reg[0]) \
{ \
*link_register=PC->addr + 8; \
sign_extended(*link_register); \
} \
if (!likely || take_jump) \
{ \
PC++; \
Expand All @@ -130,11 +135,6 @@ int rounding_mode = 0x33F, trunc_mode = 0xF3F, round_mode = 0x33F,
delay_slot=0; \
if (take_jump && !skip_jump) \
{ \
if (link_register != &reg[0]) \
{ \
*link_register=PC->addr; \
sign_extended(*link_register); \
} \
jump_to(jump_target); \
} \
} \
Expand Down

0 comments on commit cb891a0

Please sign in to comment.