If you have an issue with any of our projects. feel free to register.

Commit d070dffd authored by Christopher Snowhill's avatar Christopher Snowhill

Updated lazyusf2 with fixes from Josh W for cases where some USF rips would...

Updated lazyusf2 with fixes from Josh W for cases where some USF rips would cause the internal counter variable to take a full 32 bit loop before producing more audio, having all the appearances of temporarily locking up
parent 97fee7e4
......@@ -53,12 +53,15 @@ static uint32_t get_remaining_dma_length(struct ai_controller* ai)
if (next_ai_event == 0)
return 0;
if ((int)(ai->r4300->state->g_cp0_regs[CP0_COUNT_REG] - next_ai_event) >= 0)
return 0;
remaining_dma_duration = next_ai_event - ai->r4300->state->g_cp0_regs[CP0_COUNT_REG];
if (remaining_dma_duration >= 0x80000000)
return 0;
return (uint32_t)((uint64_t)remaining_dma_duration * ai->fifo[0].length / ai->fifo[0].duration);
return (uint32_t)((uint64_t)remaining_dma_duration * ai->fifo[0].length / ai->fifo[0].duration) & ~7;
}
static unsigned int get_dma_duration(struct ai_controller* ai)
......
......@@ -422,6 +422,8 @@ static int savestates_load_pj64(usf_state_t * state, unsigned char * ptr, unsign
load_eventqueue_infos(state, buffer);
state->cycle_count = state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count;
// FPCR
state->FCR0 = GETDATA(curr, int);
curr += 30 * 4; // FCR1...FCR30 not supported
......
......@@ -76,7 +76,7 @@
update_count(state); \
} \
state->last_addr = state->PC->addr; \
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state); \
if (state->cycle_count >=0) gen_interupt(state); \
} \
static void osal_fastcall name##_OUT(usf_state_t * state) \
{ \
......@@ -108,21 +108,21 @@
update_count(state); \
} \
state->last_addr = state->PC->addr; \
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state); \
if (state->cycle_count >=0) gen_interupt(state); \
} \
static void osal_fastcall name##_IDLE(usf_state_t * state) \
{ \
const int take_jump = (condition); \
int skip; \
if (cop1 && check_cop1_unusable(state)) return; \
if (take_jump) \
{ \
update_count(state); \
skip = state->next_interupt - state->g_cp0_regs[CP0_COUNT_REG]; \
if (skip > 3) state->g_cp0_regs[CP0_COUNT_REG] += (skip & 0xFFFFFFFC); \
else name(state); \
if (state->cycle_count < 0) \
{ \
state->g_cp0_regs[CP0_COUNT_REG] -= state->cycle_count; \
state->cycle_count = 0; \
} \
} \
else name(state); \
name(state); \
}
#define CHECK_MEMORY() \
......
......@@ -56,7 +56,9 @@ void update_count(usf_state_t * state)
if (r4300emu != CORE_DYNAREC)
{
#endif
state->g_cp0_regs[CP0_COUNT_REG] += ((state->PC->addr - state->last_addr) >> 2) * state->count_per_op;
uint32_t count = ((state->PC->addr - state->last_addr) >> 2) * state->count_per_op;
state->g_cp0_regs[CP0_COUNT_REG] += count;
state->cycle_count += count;
state->last_addr = state->PC->addr;
#ifdef NEW_DYNAREC
}
......
......@@ -111,6 +111,7 @@ void TLB_refill_exception(usf_state_t * state, unsigned int address, int w)
{
state->skip_jump = state->PC->addr;
state->next_interupt = 0;
state->cycle_count = 0;
}
}
}
......@@ -147,6 +148,7 @@ void osal_fastcall exception_general(usf_state_t * state)
{
state->skip_jump = state->PC->addr;
state->next_interupt = 0;
state->cycle_count = 0;
}
}
}
......
......@@ -71,7 +71,7 @@ DECLARE_INSTRUCTION(MTC0)
case CP0_COUNT_REG:
update_count(state);
state->interupt_unsafe_state = 1;
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state);
if (state->cycle_count >= 0) gen_interupt(state);
state->interupt_unsafe_state = 0;
translate_event_queue(state, (unsigned int) rrt & 0xFFFFFFFF);
state->g_cp0_regs[CP0_COUNT_REG] = (unsigned int) rrt & 0xFFFFFFFF;
......@@ -82,7 +82,14 @@ DECLARE_INSTRUCTION(MTC0)
case CP0_COMPARE_REG:
update_count(state);
remove_event(state, COMPARE_INT);
add_interupt_event_count(state, COMPARE_INT, (unsigned int)rrt);
/* Add count_per_op to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */
state->g_cp0_regs[CP0_COUNT_REG] += state->count_per_op;
state->cycle_count += state->count_per_op;
add_interupt_event_count(state, COMPARE_INT, rrt);
state->g_cp0_regs[CP0_COUNT_REG] -= state->count_per_op;
/* Update next interrupt in case first event is COMPARE_INT */
state->cycle_count = state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count;
state->g_cp0_regs[CP0_COMPARE_REG] = (unsigned int) rrt;
state->g_cp0_regs[CP0_CAUSE_REG] &= 0xFFFF7FFF; //Timer interupt is clear
break;
......@@ -97,7 +104,7 @@ DECLARE_INSTRUCTION(MTC0)
ADD_TO_PC(1);
check_interupt(state);
state->interupt_unsafe_state = 1;
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state);
if (state->cycle_count >= 0) gen_interupt(state);
state->interupt_unsafe_state = 0;
ADD_TO_PC(-1);
break;
......
......@@ -404,5 +404,7 @@ DECLARE_INSTRUCTION(DSRA32)
DECLARE_INSTRUCTION(BREAK)
{
state->g_cp0_regs[CP0_COUNT_REG] = state->next_interupt;
state->cycle_count = 0;
ADD_TO_PC(1);
}
......@@ -246,5 +246,5 @@ DECLARE_INSTRUCTION(ERET)
state->llbit = 0;
check_interupt(state);
state->last_addr = PCADDR;
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state);
if (state->cycle_count >= 0) gen_interupt(state);
}
......@@ -131,30 +131,12 @@ static void clear_queue(usf_state_t * state)
static int before_event(usf_state_t * state, unsigned int evt1, unsigned int evt2, int type2)
{
if(evt1 - state->g_cp0_regs[CP0_COUNT_REG] < 0x80000000)
{
if(evt2 - state->g_cp0_regs[CP0_COUNT_REG] < 0x80000000)
{
if((evt1 - state->g_cp0_regs[CP0_COUNT_REG]) < (evt2 - state->g_cp0_regs[CP0_COUNT_REG])) return 1;
else return 0;
}
else
{
if((state->g_cp0_regs[CP0_COUNT_REG] - evt2) < 0x10000000)
{
switch(type2)
{
case SPECIAL_INT:
if(state->SPECIAL_done) return 1;
else return 0;
break;
default:
return 0;
}
}
else return 1;
}
}
int count = state->g_cp0_regs[CP0_COUNT_REG];
if (state->cycle_count > 0)
count -= state->cycle_count;
if ((evt1 - count) < (evt2 - count)) return 1;
else return 0;
}
......@@ -167,19 +149,9 @@ void add_interupt_event_count(usf_state_t * state, int type, unsigned int count)
{
struct node* event;
struct node* e;
int special;
special = (type == SPECIAL_INT);
if(state->g_cp0_regs[CP0_COUNT_REG] > 0x80000000) state->SPECIAL_done = 0;
if (get_event(state, type)) {
DebugMessage(state, M64MSG_WARNING, "two events of type 0x%x in interrupt queue", type);
/* FIXME: hack-fix for freezing in Perfect Dark
* http://code.google.com/p/mupen64plus/issues/detail?id=553
* https://github.com/mupen64plus-ae/mupen64plus-ae/commit/802d8f81d46705d64694d7a34010dc5f35787c7d
*/
return;
}
event = alloc_node(&state->q.pool);
......@@ -197,18 +169,20 @@ void add_interupt_event_count(usf_state_t * state, int type, unsigned int count)
state->q.first = event;
event->next = NULL;
state->next_interupt = state->q.first->data.count;
state->cycle_count = state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count;
}
else if (before_event(state, count, state->q.first->data.count, state->q.first->data.type) && !special)
else if (before_event(state, count, state->q.first->data.count, state->q.first->data.type))
{
event->next = state->q.first;
state->q.first = event;
state->next_interupt = state->q.first->data.count;
state->cycle_count = state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count;
}
else
{
for(e = state->q.first;
e->next != NULL &&
(!before_event(state, count, e->next->data.count, e->next->data.type) || special);
(!before_event(state, count, e->next->data.count, e->next->data.type));
e = e->next);
if (e->next == NULL)
......@@ -218,8 +192,7 @@ void add_interupt_event_count(usf_state_t * state, int type, unsigned int count)
}
else
{
if (!special)
for(; e->next != NULL && e->next->data.count == count; e = e->next);
for(; e->next != NULL && e->next->data.count == count; e = e->next);
event->next = e->next;
e->next = event;
......@@ -235,11 +208,13 @@ static void remove_interupt_event(usf_state_t * state)
state->q.first = e->next;
free_node(&state->q.pool, e);
state->next_interupt = (state->q.first != NULL
&& (state->q.first->data.count > state->g_cp0_regs[CP0_COUNT_REG]
|| (state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count) < 0x80000000))
state->next_interupt = (state->q.first != NULL)
? state->q.first->data.count
: 0;
state->cycle_count = (state->q.first != NULL)
? (state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count)
: 0;
}
unsigned int get_event(usf_state_t * state, int type)
......@@ -303,8 +278,18 @@ void translate_event_queue(usf_state_t * state, unsigned int base)
{
e->data.count = (e->data.count - state->g_cp0_regs[CP0_COUNT_REG]) + base;
}
state->g_cp0_regs[CP0_COUNT_REG] = base;
add_interupt_event_count(state, SPECIAL_INT, ((state->g_cp0_regs[CP0_COUNT_REG] & UINT32_C(0x80000000)) ^ UINT32_C(0x80000000)));
/* Add count_per_op to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */
state->g_cp0_regs[CP0_COUNT_REG] += state->count_per_op;
state->cycle_count += state->count_per_op;
add_interupt_event_count(state, COMPARE_INT, state->g_cp0_regs[CP0_COMPARE_REG]);
add_interupt_event_count(state, SPECIAL_INT, 0);
state->g_cp0_regs[CP0_COUNT_REG] -= state->count_per_op;
/* Update next interrupt in case first event is COMPARE_INT */
state->cycle_count = state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count;
}
int save_eventqueue_infos(usf_state_t * state, char *buf)
......@@ -336,6 +321,8 @@ void load_eventqueue_infos(usf_state_t * state, char *buf)
add_interupt_event_count(state, type, count);
len += 8;
}
remove_event(state, SPECIAL_INT);
add_interupt_event_count(state, SPECIAL_INT, ((state->g_cp0_regs[CP0_COUNT_REG] & UINT32_C(0x80000000)) ^ UINT32_C(0x80000000)));
}
void init_interupt(usf_state_t * state)
......@@ -346,7 +333,8 @@ void init_interupt(usf_state_t * state)
clear_queue(state);
add_interupt_event_count(state, VI_INT, state->g_vi.next_vi);
add_interupt_event_count(state, SPECIAL_INT, 0);
add_interupt_event_count(state, SPECIAL_INT, 0x80000000);
add_interupt_event_count(state, COMPARE_INT, 0);
}
void check_interupt(usf_state_t * state)
......@@ -388,6 +376,7 @@ void check_interupt(usf_state_t * state)
event->data.count = state->next_interupt = state->g_cp0_regs[CP0_COUNT_REG];
event->data.type = CHECK_INT;
state->cycle_count = 0;
if (state->q.first == NULL)
{
......@@ -434,21 +423,21 @@ void raise_maskable_interrupt(usf_state_t * state, uint32_t cause)
static void special_int_handler(usf_state_t * state)
{
if (state->g_cp0_regs[CP0_COUNT_REG] > 0x10000000)
return;
state->SPECIAL_done = 1;
remove_interupt_event(state);
add_interupt_event_count(state, SPECIAL_INT, 0);
add_interupt_event_count(state, SPECIAL_INT, ((state->g_cp0_regs[CP0_COUNT_REG] & UINT32_C(0x80000000)) ^ UINT32_C(0x80000000)));
}
static void compare_int_handler(usf_state_t * state)
{
remove_interupt_event(state);
state->g_cp0_regs[CP0_COUNT_REG]+=state->count_per_op;
state->cycle_count += state->count_per_op;
add_interupt_event_count(state, COMPARE_INT, state->g_cp0_regs[CP0_COMPARE_REG]);
state->g_cp0_regs[CP0_COUNT_REG]-=state->count_per_op;
/* Update next interrupt in case first event is COMPARE_INT */
state->cycle_count = state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count;
if (state->enablecompare)
raise_maskable_interrupt(state, 0x8000);
}
......@@ -526,11 +515,14 @@ void osal_fastcall gen_interupt(usf_state_t * state)
unsigned int dest = state->skip_jump;
state->skip_jump = 0;
state->next_interupt = (state->q.first->data.count > state->g_cp0_regs[CP0_COUNT_REG]
|| (state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count) < 0x80000000)
state->next_interupt = (state->q.first != NULL)
? state->q.first->data.count
: 0;
state->cycle_count = (state->q.first != NULL)
? (state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count)
: 0;
state->last_addr = dest;
generic_jump_to(state, dest);
return;
......
......@@ -105,7 +105,7 @@ int write_mi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
check_interupt(r4300->state);
update_count(r4300->state);
if (r4300->state->next_interupt <= r4300->state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(r4300->state);
if (r4300->state->cycle_count >= 0) gen_interupt(r4300->state);
break;
}
......
......@@ -76,7 +76,7 @@ static void InterpretOpcode(usf_state_t * state);
update_count(state); \
} \
state->last_addr = state->interp_PC.addr; \
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state); \
if (state->cycle_count >= 0) gen_interupt(state); \
} \
static void name##_IDLE(usf_state_t * state, uint32_t op) \
{ \
......@@ -86,11 +86,13 @@ static void InterpretOpcode(usf_state_t * state);
if (take_jump) \
{ \
update_count(state); \
skip = state->next_interupt - state->g_cp0_regs[CP0_COUNT_REG]; \
if (skip > 3) state->g_cp0_regs[CP0_COUNT_REG] += (skip & 0xFFFFFFFC); \
else name(state, op); \
if(state->cycle_count < 0) \
{ \
state->g_cp0_regs[CP0_COUNT_REG] -= state->cycle_count; \
state->cycle_count = 0; \
} \
} \
else name(state, op); \
name(state, op); \
}
#define CHECK_MEMORY()
......
......@@ -133,6 +133,8 @@ void r4300_reset_hard(usf_state_t * state)
state->g_cp0_regs[CP0_EPC_REG] = 0xFFFFFFFF;
state->g_cp0_regs[CP0_BADVADDR_REG] = 0xFFFFFFFF;
state->g_cp0_regs[CP0_ERROREPC_REG] = 0xFFFFFFFF;
state->cycle_count = 0;
state->rounding_mode = 0x33F;
}
......
......@@ -177,6 +177,12 @@ static osal_inline void test_reg32_imm32(usf_state_t * state, int reg32, unsigne
put32(state, imm32);
}
static osal_inline void test_reg32_reg32(usf_state_t * state, int reg1, int reg2)
{
put8(state, 0x85);
put8(state, ((reg2 << 3) | reg1 | 0xC0));
}
static osal_inline void test_m32_imm32(usf_state_t * state, unsigned int *m32, unsigned int imm32)
{
put8(state, 0xF7);
......@@ -192,6 +198,13 @@ static osal_inline void add_m32_reg32(usf_state_t * state, unsigned int *m32, in
put32(state, (unsigned int)(m32));
}
static osal_inline void sub_m32_reg32(usf_state_t * state, unsigned int *m32, int reg32)
{
put8(state, 0x29);
put8(state, (reg32 << 3) | 5);
put32(state, (unsigned int)(m32));
}
static osal_inline void sub_reg32_m32(usf_state_t * state, int reg32, unsigned int *m32)
{
put8(state, 0x2B);
......@@ -290,6 +303,18 @@ static osal_inline void jp_rj(usf_state_t * state, unsigned char saut)
put8(state, saut);
}
static osal_inline void jns_rj(usf_state_t * state, unsigned char saut)
{
put8(state, 0x79);
put8(state, saut);
}
static osal_inline void js_rj(usf_state_t * state, unsigned char saut)
{
put8(state, 0x78);
put8(state, saut);
}
static osal_inline void je_near_rj(usf_state_t * state, unsigned int saut)
{
put8(state, 0x0F);
......
......@@ -44,14 +44,15 @@ static void genupdate_count(usf_state_t * state, unsigned int addr)
mov_reg32_m32(state, EDX, &state->count_per_op);
mul_reg32(state, EDX);
add_m32_reg32(state, (unsigned int*)(&state->g_cp0_regs[CP0_COUNT_REG]), EAX);
add_m32_reg32(state, (unsigned int*)(&state->cycle_count), EAX);
}
static void gencheck_interupt(usf_state_t * state, unsigned int instr_structure)
{
free_register(state, EBX);
mov_eax_memoffs32(state, &state->next_interupt);
cmp_reg32_m32(state, EAX, &state->g_cp0_regs[CP0_COUNT_REG]);
ja_rj(state, 19);
mov_eax_memoffs32(state, &state->cycle_count);
test_reg32_reg32(state, EAX, EAX);
js_rj(state, 19);
mov_m32_imm32(state, (unsigned int*)(&state->PC), instr_structure); // 10
mov_reg32_imm32(state, EBX, (unsigned int)gen_interupt); // 5
mov_reg32_reg32(state, RP0, ESI); // 2
......@@ -61,9 +62,9 @@ static void gencheck_interupt(usf_state_t * state, unsigned int instr_structure)
static void gencheck_interupt_out(usf_state_t * state, unsigned int addr)
{
free_register(state, EBX);
mov_eax_memoffs32(state, &state->next_interupt);
cmp_reg32_m32(state, EAX, &state->g_cp0_regs[CP0_COUNT_REG]);
ja_rj(state, 29);
mov_eax_memoffs32(state, &state->cycle_count);
test_reg32_reg32(state, EAX, EAX);
js_rj(state, 29);
mov_m32_imm32(state, (unsigned int*)(&state->fake_instr.addr), addr); // 10
mov_m32_imm32(state, (unsigned int*)(&state->PC), (unsigned int)(&state->fake_instr)); // 10
mov_reg32_imm32(state, EBX, (unsigned int)gen_interupt); // 5
......@@ -359,9 +360,9 @@ void genfin_block(usf_state_t * state)
void gencheck_interupt_reg(usf_state_t * state) // addr is in EAX
{
free_register(state, ECX);
mov_reg32_m32(state, EBX, &state->next_interupt);
cmp_reg32_m32(state, EBX, &state->g_cp0_regs[CP0_COUNT_REG]);
ja_rj(state, 24);
mov_reg32_m32(state, EBX, &state->cycle_count);
test_reg32_reg32(state, EBX, EBX);
js_rj(state, 24);
mov_memoffs32_eax(state, (unsigned int*)(&state->fake_instr.addr)); // 5
mov_m32_imm32(state, (unsigned int*)(&state->PC), (unsigned int)(&state->fake_instr)); // 10
mov_reg32_imm32(state, EBX, (unsigned int)gen_interupt); // 5
......@@ -427,6 +428,7 @@ void genj_out(usf_state_t * state)
void genj_idle(usf_state_t * state)
{
#ifdef INTERPRET_J_IDLE
gencallinterp(state, (unsigned int)state->current_instruction_table.J_IDLE, 1);
#else
......@@ -436,14 +438,13 @@ void genj_idle(usf_state_t * state)
gencallinterp(state, (unsigned int)state->current_instruction_table.J_IDLE, 1);
return;
}
mov_eax_memoffs32(state, (unsigned int *)(&state->cycle_count));
test_reg32_reg32(state, EAX, EAX);
js_rj(state, 16);
mov_eax_memoffs32(state, (unsigned int *)(&state->next_interupt));
sub_reg32_m32(state, EAX, (unsigned int *)(&state->g_cp0_regs[CP0_COUNT_REG]));
cmp_reg32_imm8(state, EAX, 3);
jbe_rj(state, 11);
and_eax_imm32(state, 0xFFFFFFFC); // 5
add_m32_reg32(state, (unsigned int *)(&state->g_cp0_regs[CP0_COUNT_REG]), EAX); // 6
sub_m32_reg32(state, (unsigned int *)(&state->g_cp0_regs[CP0_COUNT_REG]), EAX); // 6
mov_m32_imm32(state, (unsigned int *)(&state->cycle_count), 0); //10
genj(state);
#endif
......@@ -527,13 +528,12 @@ void genjal_idle(usf_state_t * state)
return;
}
mov_eax_memoffs32(state, (unsigned int *)(&state->next_interupt));
sub_reg32_m32(state, EAX, (unsigned int *)(&state->g_cp0_regs[CP0_COUNT_REG]));
cmp_reg32_imm8(state, EAX, 3);
jbe_rj(state, 11);
mov_eax_memoffs32(state, (unsigned int *)(&state->cycle_count));
test_reg32_reg32(state, EAX, EAX);
jns_rj(state, 16);
and_eax_imm32(state, 0xFFFFFFFC);
add_m32_reg32(state, (unsigned int *)(&state->g_cp0_regs[CP0_COUNT_REG]), EAX);
sub_m32_reg32(state, (unsigned int *)(&state->g_cp0_regs[CP0_COUNT_REG]), EAX); // 6
mov_m32_imm32(state, (unsigned int *)(&state->cycle_count), 0); //10
genjal(state);
#endif
......@@ -629,14 +629,12 @@ void gentest_idle(usf_state_t * state)
jump_start_rel32(state);
mov_reg32_m32(state, reg, (unsigned int *)(&state->next_interupt));
sub_reg32_m32(state, reg, (unsigned int *)(&state->g_cp0_regs[CP0_COUNT_REG]));
cmp_reg32_imm8(state, reg, 3);
jbe_rj(state, 12);
//sub_reg32_imm32(state, reg, 2); // 6
and_reg32_imm32(state, reg, 0xFFFFFFFC); // 6
add_m32_reg32(state, (unsigned int *)(&state->g_cp0_regs[CP0_COUNT_REG]), reg); // 6
mov_reg32_m32(state, reg, (unsigned int *)(&state->cycle_count));
test_reg32_reg32(state, reg, reg);
jns_rj(state, 16);
sub_m32_reg32(state, (unsigned int *)(&state->g_cp0_regs[CP0_COUNT_REG]), reg); // 6
mov_m32_imm32(state, (unsigned int *)(&state->cycle_count), 0); //10
jump_end_rel32(state);
}
......
......@@ -347,6 +347,12 @@ static inline void test_m32rel_imm32(usf_state_t * state, unsigned int *m32, uns
put32(state, imm32);
}
static osal_inline void test_reg32_reg32(usf_state_t * state, unsigned int reg1, unsigned int reg2)
{
put8(state, 0x85);
put8(state, 0xC0 | (reg2 << 3) | reg1);
}
static inline void add_m32rel_xreg32(usf_state_t * state, unsigned int *m32, int xreg32)
{
int offset = rel_r15_offset(state, m32, "add_m32rel_xreg32");
......@@ -357,6 +363,16 @@ static inline void add_m32rel_xreg32(usf_state_t * state, unsigned int *m32, int
put32(state, offset);
}
static osal_inline void sub_m32rel_xreg32(usf_state_t * state, unsigned int *m32, int xreg32)
{
int offset = rel_r15_offset(state, m32, "sub_m32rel_xreg32");
put8(state, 0x41 | ((xreg32 & 8) >> 1));
put8(state, 0x29);
put8(state, 0x87 | ((xreg32 & 7) << 3));
put32(state, offset);
}
static inline void sub_xreg32_m32rel(usf_state_t * state, int xreg32, unsigned int *m32)
{
int offset = rel_r15_offset(state, m32, "sub_xreg32_m32rel");
......@@ -436,6 +452,18 @@ static inline void jp_rj(usf_state_t * state, unsigned char saut)
put8(state, saut);
}
static osal_inline void jns_rj(usf_state_t * state, unsigned char saut)
{
put8(state, 0x79);
put8(state, saut);
}
static osal_inline void js_rj(usf_state_t * state, unsigned char saut)
{
put8(state, 0x78);
put8(state, saut);
}
static inline void je_near_rj(usf_state_t * state, unsigned int saut)