*/
/* This should eventually end up in machdep/, but for now, x86 is the
-only target, and it's easier this way... */
+ only target, and it's easier this way... */
#include "flags_x86.h"
/*************************************************************************
-* Some basic information about the the target CPU *
-*************************************************************************/
+ * Some basic information about the the target CPU *
+ *************************************************************************/
#define R1 RR1
#define R2 RR2
#endif
#if defined(CPU_x86_64)
-uae_s8 always_used[] = { 4, 12, -1 };
+#ifdef UAE
+/* Register R12 (and ESP) cannot be used with simple [r/m + disp32] addressing,
+ * since r/m bits 100 implies SIB byte. Simplest fix is to not use these
+ * registers. Also note that these registers are listed in the freescratch
+ * function as well. */
+uae_s8 always_used[] = { ESP_INDEX, R12_INDEX, -1 };
+#else
+uae_s8 always_used[] = { ESP_INDEX, -1 };
+#endif
uae_s8 can_byte[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1};
uae_s8 can_word[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1};
#else
-uae_s8 always_used[] = { 4, -1 };
+uae_s8 always_used[] = { ESP_INDEX, -1 };
uae_s8 can_byte[]={0,1,2,3,-1};
uae_s8 can_word[]={0,1,2,3,5,6,7,-1};
#endif
+static bool have_lahf_lm = true; // target has LAHF supported in long mode ?
#if USE_OPTIMIZED_CALLS
/* Make sure interpretive core does not use cpuopti */
#endif
}
-static inline void x86_64_rex(bool w, uae_u32 *r, uae_u32 *x, uae_u32 *b)
+static inline void x86_64_rex(bool /* w */, uae_u32 * /* r */, uae_u32 * /* x */, uae_u32 *b)
{
#ifdef CPU_x86_64
int rex_byte = 0x40;
if (rex_byte != 0x40) {
emit_byte(rex_byte);
}
+#else
+ UNUSED(b);
#endif
}
const bool optimize_shift_once = true;
/*************************************************************************
-* Actual encoding of the instructions on the target CPU *
-*************************************************************************/
+ * Actual encoding of the instructions on the target CPU *
+ *************************************************************************/
static inline int isaccum(int r)
{
// gb-- used for making an fpcr value in compemu_fpp.cpp
LOWFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s))
{
- emit_byte(0x0b);
- emit_byte(0x05+8*d);
- emit_long(s);
+ emit_byte(0x0b);
+ emit_byte(0x05+8*d);
+ emit_long(s);
}
LENDFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s))
LOWFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s))
{
- abort(); /* %^$&%^$%#^ x86! */
- emit_byte(0x0f);
- emit_byte(0xaf);
- emit_byte(0xc0+8*d+s);
+ jit_abort("unsupported MUL"); /* %^$&%^$%#^ x86! */
+ emit_byte(0x0f);
+ emit_byte(0xaf);
+ emit_byte(0xc0+8*d+s);
}
LENDFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s))
emit_byte(baser+8*index+0x40*fi);
if (isebp)
emit_byte(0x00);
- }
+}
LENDFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor))
LOWFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor))
int fi;
switch(factor) {
- case 1: fi=0; break;
- case 2: fi=1; break;
- case 4: fi=2; break;
- case 8: fi=3; break;
- default: abort();
+ case 1: fi=0; break;
+ case 2: fi=1; break;
+ case 4: fi=2; break;
+ case 8: fi=3; break;
+ default: abort();
}
emit_byte(0x89);
int fi;
switch(factor) {
- case 1: fi=0; break;
- case 2: fi=1; break;
- case 4: fi=2; break;
- case 8: fi=3; break;
- default: abort();
+ case 1: fi=0; break;
+ case 2: fi=1; break;
+ case 4: fi=2; break;
+ case 8: fi=3; break;
+ default: abort();
}
emit_byte(0x66);
int fi;
switch(factor) {
- case 1: fi=0; break;
- case 2: fi=1; break;
- case 4: fi=2; break;
- case 8: fi=3; break;
- default: abort();
+ case 1: fi=0; break;
+ case 2: fi=1; break;
+ case 4: fi=2; break;
+ case 8: fi=3; break;
+ default: abort();
}
emit_byte(0x88);
emit_byte(0x84+8*s);
emit_byte(baser+8*index+0x40*fi);
emit_long(base);
- }
+}
LENDFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s))
LOWFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor))
int fi;
switch(factor) {
- case 1: fi=0; break;
- case 2: fi=1; break;
- case 4: fi=2; break;
- case 8: fi=3; break;
- default: abort();
+ case 1: fi=0; break;
+ case 2: fi=1; break;
+ case 4: fi=2; break;
+ case 8: fi=3; break;
+ default: abort();
}
emit_byte(0x8b);
int fi;
switch(factor) {
- case 1: fi=0; break;
- case 2: fi=1; break;
- case 4: fi=2; break;
- case 8: fi=3; break;
- default: abort();
+ case 1: fi=0; break;
+ case 2: fi=1; break;
+ case 4: fi=2; break;
+ case 8: fi=3; break;
+ default: abort();
}
emit_byte(0x66);
int fi;
switch(factor) {
- case 1: fi=0; break;
- case 2: fi=1; break;
- case 4: fi=2; break;
- case 8: fi=3; break;
- default: abort();
+ case 1: fi=0; break;
+ case 2: fi=1; break;
+ case 4: fi=2; break;
+ case 8: fi=3; break;
+ default: abort();
}
emit_byte(0x8a);
{
int fi;
switch(factor) {
- case 1: fi=0; break;
- case 2: fi=1; break;
- case 4: fi=2; break;
- case 8: fi=3; break;
- default:
- fprintf(stderr,"Bad factor %d in mov_l_rm_indexed!\n",factor);
- abort();
+ case 1: fi=0; break;
+ case 2: fi=1; break;
+ case 4: fi=2; break;
+ case 8: fi=3; break;
+ default:
+ jit_abort("Bad factor %d in mov_l_rm_indexed!",factor);
}
emit_byte(0x8b);
emit_byte(0x04+8*d);
{
int fi;
switch(factor) {
- case 1: fi=0; break;
- case 2: fi=1; break;
- case 4: fi=2; break;
- case 8: fi=3; break;
- default:
- fprintf(stderr,"Bad factor %d in mov_l_rm_indexed!\n",factor);
- abort();
+ case 1: fi=0; break;
+ case 2: fi=1; break;
+ case 4: fi=2; break;
+ case 8: fi=3; break;
+ default:
+ jit_abort("Bad factor %d in mov_l_rm_indexed!",factor);
}
if (have_cmov) {
emit_byte(0x0f);
int fi;
switch(factor) {
- case 1: fi=0; break;
- case 2: fi=1; break;
- case 4: fi=2; break;
- case 8: fi=3; break;
- default: abort();
+ case 1: fi=0; break;
+ case 2: fi=1; break;
+ case 4: fi=2; break;
+ case 8: fi=3; break;
+ default: abort();
}
if (optimize_imm8 && isbyte(offset)) {
int fi;
switch(factor) {
- case 1: fi=0; break;
- case 2: fi=1; break;
- case 4: fi=2; break;
- case 8: fi=3; break;
- default: abort();
+ case 1: fi=0; break;
+ case 2: fi=1; break;
+ case 4: fi=2; break;
+ case 8: fi=3; break;
+ default: abort();
}
emit_byte(0x8d);
LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i))
{
- emit_byte(0x81);
- emit_byte(0xf0+d);
- emit_long(i);
+ emit_byte(0x81);
+ emit_byte(0xf0+d);
+ emit_long(i);
}
LENDFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i))
else {
emit_byte(0x81);
emit_byte(0xc8+d);
- }
- emit_long(i);
+ }
+ emit_long(i);
}
}
LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i))
LOWFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s))
{
- emit_byte(0x80);
- emit_byte(0x3d);
- emit_long(d);
- emit_byte(s);
+ emit_byte(0x80);
+ emit_byte(0x3d);
+ emit_long(d);
+ emit_byte(s);
}
LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s))
LOWFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor))
{
- int fi;
-
- switch(factor) {
- case 1: fi=0; break;
- case 2: fi=1; break;
- case 4: fi=2; break;
- case 8: fi=3; break;
- default: abort();
- }
- emit_byte(0x39);
- emit_byte(0x04+8*d);
- emit_byte(5+8*index+0x40*fi);
- emit_long(offset);
+ int fi;
+
+ switch(factor) {
+ case 1: fi=0; break;
+ case 2: fi=1; break;
+ case 4: fi=2; break;
+ case 8: fi=3; break;
+ default: abort();
+ }
+ emit_byte(0x39);
+ emit_byte(0x04+8*d);
+ emit_byte(5+8*index+0x40*fi);
+ emit_long(offset);
}
LENDFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor))
static inline void raw_call_r(R4 r)
{
#if USE_NEW_RTASM
- CALLsr(r);
+ CALLsr(r);
#else
emit_byte(0xff);
emit_byte(0xd0+r);
emit_byte(0xc3);
}
-static inline void raw_nop(void)
+static inline void raw_emit_nop(void)
{
emit_byte(0x90);
}
for (i = 0; i < remains; i++) {
emit_block(prefixes, len);
- raw_nop();
+ raw_emit_nop();
}
for (; i < nnops; i++) {
emit_block(prefixes, len - 1);
- raw_nop();
+ raw_emit_nop();
}
#else
/* Source: GNU Binutils 2.12.90.0.15 */
Note: Don't try to assemble the instructions in the comments.
0L and 0w are not legal. */
static const uae_u8 f32_1[] =
- {0x90}; /* nop */
+ {0x90}; /* nop */
static const uae_u8 f32_2[] =
- {0x89,0xf6}; /* movl %esi,%esi */
+ {0x89,0xf6}; /* movl %esi,%esi */
static const uae_u8 f32_3[] =
- {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */
+ {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */
static const uae_u8 f32_4[] =
- {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */
+ {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */
static const uae_u8 f32_5[] =
- {0x90, /* nop */
- 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */
+ {0x90, /* nop */
+ 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */
static const uae_u8 f32_6[] =
- {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */
+ {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */
static const uae_u8 f32_7[] =
- {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */
+ {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */
static const uae_u8 f32_8[] =
- {0x90, /* nop */
- 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */
+ {0x90, /* nop */
+ 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */
static const uae_u8 f32_9[] =
- {0x89,0xf6, /* movl %esi,%esi */
- 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
+ {0x89,0xf6, /* movl %esi,%esi */
+ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
static const uae_u8 f32_10[] =
- {0x8d,0x76,0x00, /* leal 0(%esi),%esi */
- 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
+ {0x8d,0x76,0x00, /* leal 0(%esi),%esi */
+ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
static const uae_u8 f32_11[] =
- {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */
- 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
+ {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */
+ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
static const uae_u8 f32_12[] =
- {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */
- 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */
+ {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */
+ 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */
static const uae_u8 f32_13[] =
- {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */
- 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
+ {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */
+ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
static const uae_u8 f32_14[] =
- {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */
- 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
+ {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */
+ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
static const uae_u8 f32_15[] =
- {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */
- 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
+ {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */
+ 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
static const uae_u8 f32_16[] =
- {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */
- 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
+ {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */
+ 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
static const uae_u8 *const f32_patt[] = {
- f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8,
- f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15
+ f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8,
+ f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15
};
int nloops = nbytes / 16;
/*************************************************************************
-* Flag handling, to and fro UAE flag register *
-*************************************************************************/
+ * Flag handling, to and fro UAE flag register *
+ *************************************************************************/
static inline void raw_flags_evicted(int r)
{
#define FLAG_NREG3_FLAGREG 0 /* Set to -1 if any register will do */
static __inline__ void raw_flags_set_zero_FLAGREG(int s, int tmp)
{
- raw_mov_l_rr(tmp,s);
- raw_lahf(s); /* flags into ah */
- raw_and_l_ri(s,0xffffbfff);
- raw_and_l_ri(tmp,0x00004000);
- raw_xor_l_ri(tmp,0x00004000);
- raw_or_l(s,tmp);
- raw_sahf(s);
+ raw_mov_l_rr(tmp,s);
+ raw_lahf(s); /* flags into ah */
+ raw_and_l_ri(s,0xffffbfff);
+ raw_and_l_ri(tmp,0x00004000);
+ raw_xor_l_ri(tmp,0x00004000);
+ raw_or_l(s,tmp);
+ raw_sahf(s);
}
static inline void raw_flags_init_FLAGREG(void) { }
#define FLAG_NREG3_FLAGSTK -1 /* Set to -1 if any register will do */
static inline void raw_flags_set_zero_FLAGSTK(int s, int tmp)
{
- raw_mov_l_rr(tmp,s);
- raw_pushfl();
- raw_pop_l_r(s);
- raw_and_l_ri(s,0xffffffbf);
- raw_and_l_ri(tmp,0x00000040);
- raw_xor_l_ri(tmp,0x00000040);
- raw_or_l(s,tmp);
- raw_push_l_r(s);
- raw_popfl();
+ raw_mov_l_rr(tmp,s);
+ raw_pushfl();
+ raw_pop_l_r(s);
+ raw_and_l_ri(s,0xffffffbf);
+ raw_and_l_ri(tmp,0x00000040);
+ raw_xor_l_ri(tmp,0x00000040);
+ raw_or_l(s,tmp);
+ raw_push_l_r(s);
+ raw_popfl();
}
static inline void raw_flags_init_FLAGSTK(void) { }
{
if (have_lahf_lm) {
// NOTE: the interpreter uses the normal EFLAGS layout
- // pushf/popf CF(0) ZF( 6) SF( 7) OF(11)
- // sahf/lahf CF(8) ZF(14) SF(15) OF( 0)
+ // pushf/popf CF(0) ZF( 6) SF( 7) OF(11)
+ // sahf/lahf CF(8) ZF(14) SF(15) OF( 0)
assert(r == 0);
- raw_setcc(r,0); /* V flag in AL */
+ raw_setcc(r,0); /* V flag in AL */
raw_lea_l_r_scaled(0,0,8); /* move it to its EFLAGS location */
raw_mov_b_mr(((uintptr)live.state[FLAGTMP].mem)+1,0);
raw_lahf(0); /* most flags in AH */
#define raw_flags_set_zero FLAG_GLUE(raw_flags_set_zero)
/* Apparently, there are enough instructions between flag store and
-flag reload to avoid the partial memory stall */
+ flag reload to avoid the partial memory stall */
static inline void raw_load_flagreg(uae_u32 target, uae_u32 r)
{
#if 1
#include "exception_handler.cpp"
#endif
+#ifdef UAE
static
+#endif
void compiler_status() {
jit_log("compiled code starts at %p, current at %p (size 0x%x)", compiled_code, current_compile_p, (unsigned int)(current_compile_p - compiled_code));
}
/*************************************************************************
-* Checking for CPU features *
-*************************************************************************/
+ * Checking for CPU features *
+ *************************************************************************/
struct cpuinfo_x86 {
uae_u8 x86; // CPU family
uae_u8 x86_model;
uae_u8 x86_mask;
bool x86_has_xmm2;
- int cpuid_level; // Maximum supported CPUID level, -1=no CPUID
+ int cpuid_level; // Maximum supported CPUID level, -1=no CPUID
char x86_vendor_id[16];
uintptr x86_clflush_size;
};
enum {
X86_VENDOR_INTEL = 0,
X86_VENDOR_CYRIX = 1,
- X86_VENDOR_AMD = 2,
- X86_VENDOR_UMC = 3,
+ X86_VENDOR_AMD = 2,
+ X86_VENDOR_UMC = 3,
X86_VENDOR_NEXGEN = 4,
- X86_VENDOR_CENTAUR = 5,
- X86_VENDOR_RISE = 6,
+ X86_VENDOR_CENTAUR = 5,
+ X86_VENDOR_RISE = 6,
X86_VENDOR_TRANSMETA = 7,
- X86_VENDOR_NSC = 8,
- X86_VENDOR_UNKNOWN = 0xff
+ X86_VENDOR_NSC = 8,
+ X86_VENDOR_UNKNOWN = 0xff
};
enum {
- X86_PROCESSOR_I386, /* 80386 */
- X86_PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */
+ X86_PROCESSOR_I386, /* 80386 */
+ X86_PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */
X86_PROCESSOR_PENTIUM,
X86_PROCESSOR_PENTIUMPRO,
X86_PROCESSOR_K6,
X86_PROCESSOR_max
};
+#if defined(UAE) || (defined(DEBUG) && DEBUG)
static const char * x86_processor_string_table[X86_PROCESSOR_max] = {
"80386",
"80486",
"Pentium4",
"x86-64"
};
+#endif
static struct ptt {
const int align_loop;
{ 16, 7, 16, 7, 16 }
};
-static void
- x86_get_cpu_vendor(struct cpuinfo_x86 *c)
+static void x86_get_cpu_vendor(struct cpuinfo_x86 *c)
{
char *v = c->x86_vendor_id;
c->x86_vendor = X86_VENDOR_NEXGEN;
else if (!strcmp(v, "RiseRiseRise"))
c->x86_vendor = X86_VENDOR_RISE;
- else if (!strcmp(v, "GenuineTMx86") ||
- !strcmp(v, "TransmetaCPU"))
+ else if (!strcmp(v, "GenuineTMx86") || !strcmp(v, "TransmetaCPU"))
c->x86_vendor = X86_VENDOR_TRANSMETA;
else
c->x86_vendor = X86_VENDOR_UNKNOWN;
*ebx = cpuinfo[1];
*ecx = cpuinfo[2];
*edx = cpuinfo[3];
- }
+}
#endif
static void
cpuid_count(op, 0, eax, ebx, ecx, edx);
}
-static void
-raw_init_cpu(void)
+static void raw_init_cpu(void)
{
struct cpuinfo_x86 *c = &cpuinfo;
uae_u32 dummy;
jit_log(" Mask : %d", c->x86_mask);
jit_log(" Vendor : %s [%d]", c->x86_vendor_id, c->x86_vendor);
if (c->x86_brand_id)
+ {
jit_log(" BrandID : %02x", c->x86_brand_id);
+ }
}
/* Have CMOV support? */
have_rat_stall = true; //(c->x86_vendor == X86_VENDOR_INTEL);
#if 0
/* It appears that partial register writes are a bad idea even on
- AMD K7 cores, even though they are not supposed to have the
- dreaded rat stall. Why? Anyway, that's why we lie about it ;-) */
+ AMD K7 cores, even though they are not supposed to have the
+ dreaded rat stall. Why? Anyway, that's why we lie about it ;-) */
if (c->x86_processor == X86_PROCESSOR_ATHLON)
have_rat_stall = true;
#endif
align_jumps = x86_alignments[c->x86_processor].align_jump;
}
- jit_log("Max CPUID level=%d Processor is %s [%s]",
+ jit_log("<JIT compiler> : Max CPUID level=%d Processor is %s [%s]",
c->cpuid_level, c->x86_vendor_id,
x86_processor_string_table[c->x86_processor]);
raw_flags_init();
}
-#if 0
+#ifndef UAE
static void __attribute_noinline__ prevent_redzone_use(void) {}
static bool target_check_bsf(void)
if (ZF != tmp || SF != g_SF || OF != g_OF || CF != g_CF)
mismatch = true;
}
- }}}}
+ }
+ }
+ }
+ }
if (mismatch)
{
- jit_log("Target CPU defines all flags on BSF instruction");
+ jit_log("<JIT compiler> : Target CPU defines all flags on BSF instruction");
}
return !mismatch;
}
#endif
/*************************************************************************
-* FPU stuff *
-*************************************************************************/
+ * FPU stuff *
+ *************************************************************************/
static inline void raw_fp_init(void)
{
#if 0
/* using FINIT instead of popping all the entries.
- Seems to have side effects --- there is display corruption in
- Quake when this is used */
+ Seems to have side effects --- there is display corruption in
+ Quake when this is used */
if (live.tos>1) {
emit_byte(0x9b);
emit_byte(0xdb);
static inline void make_tos2(int r, int r2)
{
- int q;
+ int q;
- make_tos(r2); /* Put the reg that's supposed to end up in position2
- on top */
+ make_tos(r2); /* Put the reg that's supposed to end up in position2 on top */
- if (live.spos[r]<0) { /* Register not yet on stack */
- make_tos(r); /* This will extend the stack */
- return;
- }
- /* Register is on stack */
- emit_byte(0xd9);
- emit_byte(0xc9); /* Move r2 into position 2 */
+ if (live.spos[r]<0) { /* Register not yet on stack */
+ make_tos(r); /* This will extend the stack */
+ return;
+ }
+ /* Register is on stack */
+ emit_byte(0xd9);
+ emit_byte(0xc9); /* Move r2 into position 2 */
- q=live.onstack[live.tos-1];
- live.onstack[live.tos]=q;
- live.spos[q]=live.tos;
- live.onstack[live.tos-1]=r2;
- live.spos[r2]=live.tos-1;
+ q=live.onstack[live.tos-1];
+ live.onstack[live.tos]=q;
+ live.spos[q]=live.tos;
+ live.onstack[live.tos-1]=r2;
+ live.spos[r2]=live.tos-1;
- make_tos(r); /* And r into 1 */
+ make_tos(r); /* And r into 1 */
}
static inline int stackpos(int r)
return;
}
emit_byte(0xdd);
- emit_byte(0xd8+(live.tos+1)-live.spos[r]); /* store top of stack in reg,
- and pop it*/
+ emit_byte(0xd8+(live.tos+1)-live.spos[r]); /* store top of stack in reg, and pop it*/
}
/* FP helper functions */
#define DEFINE_OP(NAME, GEN) \
static inline void raw_##NAME(uint32 m) \
{ \
- GEN(m, X86_NOREG, X86_NOREG, 1); \
+ GEN(m, X86_NOREG, X86_NOREG, 1); \
}
DEFINE_OP(fstl, FSTLm);
DEFINE_OP(fstpl, FSTPLm);
#define DEFINE_OP(NAME, OP1, OP2) \
static inline void raw_##NAME(uint32 m) \
{ \
- emit_byte(OP1); \
- emit_byte(OP2); \
- emit_long(m); \
+ emit_byte(OP1); \
+ emit_byte(OP2); \
+ emit_long(m); \
}
DEFINE_OP(fstl, 0xdd, 0x15);
DEFINE_OP(fstpl, 0xdd, 0x1d);
{
int rs;
- /* Stupid x87 can't write a long double to mem without popping the
- stack! */
+ /* Stupid x87 can't write a long double to mem without popping the stack! */
usereg(r);
rs=stackpos(r);
- emit_byte(0xd9); /* Get a copy to the top of stack */
+ emit_byte(0xd9); /* Get a copy to the top of stack */
emit_byte(0xc0+rs);
raw_fstpt(m); /* store and pop it */
emit_byte(0xc0+ds); /* duplicate source */
emit_byte(0xd9);
emit_byte(0xfa); /* take square root */
- tos_make(d); /* store to destination */
+ tos_make(d); /* store to destination */
}
else {
make_tos(d);
emit_byte(0xd9);
- emit_byte(0xfa); /* take square root */
+ emit_byte(0xfa); /* take square root */
}
}
LENDFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s))
emit_byte(0xc0+ds); /* duplicate source */
emit_byte(0xd9);
emit_byte(0xe1); /* take fabs */
- tos_make(d); /* store to destination */
+ tos_make(d); /* store to destination */
}
else {
make_tos(d);
emit_byte(0xc0+ds); /* duplicate source */
emit_byte(0xd9);
emit_byte(0xfc); /* take frndint */
- tos_make(d); /* store to destination */
+ tos_make(d); /* store to destination */
}
else {
make_tos(d);
emit_byte(0xd9);
emit_byte(0xc0+ds); /* duplicate source */
emit_byte(0xd9);
- emit_byte(0xff); /* take cos */
- tos_make(d); /* store to destination */
+ emit_byte(0xff); /* take cos */
+ tos_make(d); /* store to destination */
}
else {
make_tos(d);
emit_byte(0xd9);
- emit_byte(0xff); /* take cos */
+ emit_byte(0xff); /* take cos */
}
}
LENDFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s))
int ds;
if (d!=s) {
+ usereg(s);
ds=stackpos(s);
emit_byte(0xd9);
emit_byte(0xc0+ds); /* fld x */
emit_byte(0xd9);
- emit_byte(0xfe); /* fsin sin(x) */
- tos_make(d); /* store to destination */
+ emit_byte(0xfe); /* fsin sin(x) */
+ tos_make(d); /* store to destination */
}
else {
make_tos(d);
{
int ds;
+ usereg(s);
ds=stackpos(s);
emit_byte(0xd9);
emit_byte(0xc0+ds); /* fld x */
ds=stackpos(s);
if (ds!=1) {
- printf("Failed horribly in raw_frem_rr! ds is %d\n",ds);
- abort();
+ jit_abort("Failed horribly in raw_frem_rr! ds is %d",ds);
}
emit_byte(0xd9);
emit_byte(0xf8); /* take rem from dest by source */
ds=stackpos(s);
if (ds!=1) {
- printf("Failed horribly in raw_frem1_rr! ds is %d\n",ds);
- abort();
+ jit_abort("Failed horribly in raw_frem1_rr! ds is %d",ds);
}
emit_byte(0xd9);
emit_byte(0xf5); /* take rem1 from dest by source */
#ifndef COMPEMU_H
#define COMPEMU_H
+#include "sysconfig.h"
#include "newcpu.h"
#ifdef UAE
struct blockinfo_t;
struct cpu_history {
- uae_u16* location;
- uae_u8 specmem;
+ uae_u16* location;
+#ifdef UAE
+ uae_u8 specmem;
+#endif
};
union cacheline {
for jump targets */
#define INDIVIDUAL_INST 0
+#ifdef WINUAE_ARANYM
+#define FLAG_X 0x0010
+#define FLAG_N 0x0008
+#define FLAG_Z 0x0004
+#define FLAG_V 0x0002
+#define FLAG_C 0x0001
+#else
#define FLAG_C 0x0010
#define FLAG_V 0x0008
#define FLAG_Z 0x0004
#define FLAG_N 0x0002
#define FLAG_X 0x0001
+#endif
#define FLAG_CZNV (FLAG_C | FLAG_Z | FLAG_N | FLAG_V)
+#define FLAG_ALL (FLAG_C | FLAG_Z | FLAG_N | FLAG_V | FLAG_X)
#define FLAG_ZNV (FLAG_Z | FLAG_N | FLAG_V)
#define KILLTHERAT 1 /* Set to 1 to avoid some partial_rat_stalls */
/* Functions exposed to newcpu, or to what was moved from newcpu.c to
* compemu_support.c */
+#ifdef WINUAE_ARANYM
+extern void compiler_init(void);
+extern void compiler_exit(void);
+extern bool compiler_use_jit(void);
+#endif
extern void init_comp(void);
extern void flush(int save_regs);
extern void small_flush(int save_regs);
extern int get_cache_state(void);
extern uae_u32 get_jitted_size(void);
#ifdef JIT
+#ifdef WINUAE_ARANYM
+extern void (*flush_icache)(int n);
+#else
extern void flush_icache(int n);
extern void flush_icache_hard(int n);
#endif
+#endif
extern void alloc_cache(void);
extern int check_for_cache_miss(void);
cpuop_func* direct_pen;
cpuop_func* direct_pcc;
+#ifdef UAE
uae_u8* nexthandler;
+#endif
uae_u8* pc_p;
uae_u32 c1;
#else
+#ifdef WINUAE_ARANYM
+#define jit_log(format, ...) D(bug(format, ##__VA_ARGS__))
+#define jit_log2(format, ...) D2(bug(format, ##__VA_ARGS__))
+void jit_abort(const char *format,...) __attribute__((format(printf, 1, 2))) __attribute__((__noreturn__));
+#else
#define jit_abort(...) abort()
#define jit_log panicbug
#define jit_log2(...)
-
#endif
+#endif /* UAE */
+
#ifdef CPU_64_BIT
-static inline uae_u32 check_uae_p32(uae_u64 address, const char *file, int line)
+static inline uae_u32 check_uae_p32(uintptr address, const char *file, int line)
{
if (address > (uintptr_t) 0xffffffff) {
jit_abort("JIT: 64-bit pointer (0x%llx) at %s:%d (fatal)",
- address, file, line);
+ (unsigned long long)address, file, line);
}
return (uae_u32) address;
}
-#define uae_p32(x) (check_uae_p32((uae_u64)(x), __FILE__, __LINE__))
+#define uae_p32(x) (check_uae_p32((uintptr)(x), __FILE__, __LINE__))
#else
#define uae_p32(x) ((uae_u32)(x))
#endif
*
*/
+static int f_rmw(int r)
+{
+ int n;
+
+ f_make_exclusive(r,0);
+ if (f_isinreg(r)) {
+ n=live.fate[r].realreg;
+ }
+ else
+ n=f_alloc_reg(r,0);
+ live.fate[r].status=DIRTY;
+ live.fat[n].locked++;
+ live.fat[n].touched=touchcnt++;
+ return n;
+}
+
+static void fflags_into_flags_internal(uae_u32 tmp)
+{
+ int r;
+
+ clobber_flags();
+ r=f_readreg(FP_RESULT);
+ if (FFLAG_NREG_CLOBBER_CONDITION) {
+ int tmp2=tmp;
+ tmp=writereg_specific(tmp,4,FFLAG_NREG);
+ raw_fflags_into_flags(r);
+ unlock2(tmp);
+ forget_about(tmp2);
+ }
+ else
+ raw_fflags_into_flags(r);
+ f_unlock(r);
+ live_flags();
+}
+
+
/********************************************************************
* CPU functions exposed to gencomp. Both CREATE and EMIT time *
********************************************************************/
}
MENDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc))
-#ifdef UAE
-/* FIXME: UAE version looks correct */
MIDFUNC(2,bsf_l_rr,(W4 d, RR4 s))
-#else
-MIDFUNC(2,bsf_l_rr,(W4 d, W4 s))
-#endif
{
CLOBBER_BSF;
- s=readreg(s,4);
- d=writereg(d,4);
- raw_bsf_l_rr(d,s);
+ s = readreg(s, 4);
+ d = writereg(d, 4);
+ raw_bsf_l_rr(d, s);
unlock2(s);
unlock2(d);
}
-#ifdef UAE
-/* FIXME: UAE version looks correct */
MENDFUNC(2,bsf_l_rr,(W4 d, RR4 s))
-#else
-MENDFUNC(2,bsf_l_rr,(W4 d, W4 s))
-#endif
/* Set the Z flag depending on the value in s. Note that the
value has to be 0 or -1 (or, more precisely, for non-zero
values, bit 14 must be set)! */
MIDFUNC(2,simulate_bsf,(W4 tmp, RW4 s))
{
- CLOBBER_BSF;
- s=rmw_specific(s,4,4,FLAG_NREG3);
- tmp=writereg(tmp,4);
- raw_flags_set_zero(s, tmp);
- unlock2(tmp);
- unlock2(s);
+ CLOBBER_BSF;
+ s=rmw_specific(s,4,4,FLAG_NREG3);
+ tmp=writereg(tmp,4);
+ raw_flags_set_zero(s, tmp);
+ unlock2(tmp);
+ unlock2(s);
}
MENDFUNC(2,simulate_bsf,(W4 tmp, RW4 s))
MIDFUNC(2,mul_32_32,(RW4 d, RR4 s))
{
- CLOBBER_MUL;
- s=readreg(s,4);
- d=rmw(d,4,4);
- raw_mul_32_32(d,s);
- unlock2(s);
- unlock2(d);
+ CLOBBER_MUL;
+ s=readreg(s,4);
+ d=rmw(d,4,4);
+ raw_mul_32_32(d,s);
+ unlock2(s);
+ unlock2(d);
}
MENDFUNC(2,mul_32_32,(RW4 d, RR4 s))
#if SIZEOF_VOID_P == 8
MIDFUNC(2,sign_extend_32_rr,(W4 d, RR2 s))
{
- int isrmw;
+ int isrmw;
- if (isconst(s)) {
+ if (isconst(s)) {
set_const(d,(uae_s32)live.state[s].val);
return;
- }
+ }
- CLOBBER_SE32;
- isrmw=(s==d);
- if (!isrmw) {
- s=readreg(s,4);
- d=writereg(d,4);
- }
- else { /* If we try to lock this twice, with different sizes, we
- are int trouble! */
- s=d=rmw(s,4,4);
- }
- raw_sign_extend_32_rr(d,s);
- if (!isrmw) {
- unlock2(d);
- unlock2(s);
- }
- else {
- unlock2(s);
- }
+ CLOBBER_SE32;
+ isrmw=(s==d);
+ if (!isrmw) {
+ s=readreg(s,4);
+ d=writereg(d,4);
+ }
+ else { /* If we try to lock this twice, with different sizes, we
+ are int trouble! */
+ s=d=rmw(s,4,4);
+ }
+ raw_sign_extend_32_rr(d,s);
+ if (!isrmw) {
+ unlock2(d);
+ unlock2(s);
+ }
+ else {
+ unlock2(s);
+ }
}
MENDFUNC(2,sign_extend_32_rr,(W4 d, RR2 s))
#endif
d=writereg(d,4);
}
else { /* If we try to lock this twice, with different sizes, we
- are int trouble! */
+ are int trouble! */
s=d=rmw(s,4,2);
}
raw_sign_extend_16_rr(d,s);
d=writereg(d,4);
}
else { /* If we try to lock this twice, with different sizes, we
- are int trouble! */
+ are int trouble! */
s=d=rmw(s,4,1);
}
d=writereg(d,4);
}
else { /* If we try to lock this twice, with different sizes, we
- are int trouble! */
+ are int trouble! */
s=d=rmw(s,4,2);
}
raw_zero_extend_16_rr(d,s);
d=writereg(d,4);
}
else { /* If we try to lock this twice, with different sizes, we
- are int trouble! */
+ are int trouble! */
s=d=rmw(s,4,1);
}
MIDFUNC(5,mov_l_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR4 s))
{
- int basereg=baser;
- int indexreg=index;
+ int basereg=baser;
+ int indexreg=index;
- CLOBBER_MOV;
- s=readreg(s,4);
- baser=readreg_offset(baser,4);
- index=readreg_offset(index,4);
+ CLOBBER_MOV;
+ s=readreg(s,4);
+ baser=readreg_offset(baser,4);
+ index=readreg_offset(index,4);
- base+=get_offset(basereg);
- base+=factor*get_offset(indexreg);
+ base+=get_offset(basereg);
+ base+=factor*get_offset(indexreg);
- raw_mov_l_bmrr_indexed(base,baser,index,factor,s);
- unlock2(s);
- unlock2(baser);
- unlock2(index);
+ raw_mov_l_bmrr_indexed(base,baser,index,factor,s);
+ unlock2(s);
+ unlock2(baser);
+ unlock2(index);
}
MENDFUNC(5,mov_l_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR4 s))
MIDFUNC(5,mov_w_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR2 s))
{
- int basereg=baser;
- int indexreg=index;
+ int basereg=baser;
+ int indexreg=index;
- CLOBBER_MOV;
- s=readreg(s,2);
- baser=readreg_offset(baser,4);
- index=readreg_offset(index,4);
+ CLOBBER_MOV;
+ s=readreg(s,2);
+ baser=readreg_offset(baser,4);
+ index=readreg_offset(index,4);
- base+=get_offset(basereg);
- base+=factor*get_offset(indexreg);
+ base+=get_offset(basereg);
+ base+=factor*get_offset(indexreg);
- raw_mov_w_bmrr_indexed(base,baser,index,factor,s);
- unlock2(s);
- unlock2(baser);
- unlock2(index);
+ raw_mov_w_bmrr_indexed(base,baser,index,factor,s);
+ unlock2(s);
+ unlock2(baser);
+ unlock2(index);
}
MENDFUNC(5,mov_w_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR2 s))
MIDFUNC(5,mov_b_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR1 s))
{
- int basereg=baser;
- int indexreg=index;
+ int basereg=baser;
+ int indexreg=index;
- CLOBBER_MOV;
- s=readreg(s,1);
- baser=readreg_offset(baser,4);
- index=readreg_offset(index,4);
+ CLOBBER_MOV;
+ s=readreg(s,1);
+ baser=readreg_offset(baser,4);
+ index=readreg_offset(index,4);
- base+=get_offset(basereg);
- base+=factor*get_offset(indexreg);
+ base+=get_offset(basereg);
+ base+=factor*get_offset(indexreg);
- raw_mov_b_bmrr_indexed(base,baser,index,factor,s);
- unlock2(s);
- unlock2(baser);
- unlock2(index);
+ raw_mov_b_bmrr_indexed(base,baser,index,factor,s);
+ unlock2(s);
+ unlock2(baser);
+ unlock2(index);
}
MENDFUNC(5,mov_b_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR1 s))
/* Read a long from base+baser+factor*index */
MIDFUNC(5,mov_l_brrm_indexed,(W4 d, IMM base, RR4 baser, RR4 index, IMM factor))
{
- int basereg=baser;
- int indexreg=index;
+ int basereg=baser;
+ int indexreg=index;
- CLOBBER_MOV;
- baser=readreg_offset(baser,4);
- index=readreg_offset(index,4);
- base+=get_offset(basereg);
- base+=factor*get_offset(indexreg);
- d=writereg(d,4);
- raw_mov_l_brrm_indexed(d,base,baser,index,factor);
- unlock2(d);
- unlock2(baser);
- unlock2(index);
+ CLOBBER_MOV;
+ baser=readreg_offset(baser,4);
+ index=readreg_offset(index,4);
+ base+=get_offset(basereg);
+ base+=factor*get_offset(indexreg);
+ d=writereg(d,4);
+ raw_mov_l_brrm_indexed(d,base,baser,index,factor);
+ unlock2(d);
+ unlock2(baser);
+ unlock2(index);
}
MENDFUNC(5,mov_l_brrm_indexed,(W4 d, IMM base, RR4 baser, RR4 index, IMM factor))
MIDFUNC(5,mov_w_brrm_indexed,(W2 d, IMM base, RR4 baser, RR4 index, IMM factor))
{
- int basereg=baser;
- int indexreg=index;
-
- CLOBBER_MOV;
- remove_offset(d,-1);
- baser=readreg_offset(baser,4);
- index=readreg_offset(index,4);
- base+=get_offset(basereg);
- base+=factor*get_offset(indexreg);
- d=writereg(d,2);
- raw_mov_w_brrm_indexed(d,base,baser,index,factor);
- unlock2(d);
- unlock2(baser);
- unlock2(index);
+ int basereg=baser;
+ int indexreg=index;
+
+ CLOBBER_MOV;
+ remove_offset(d,-1);
+ baser=readreg_offset(baser,4);
+ index=readreg_offset(index,4);
+ base+=get_offset(basereg);
+ base+=factor*get_offset(indexreg);
+ d=writereg(d,2);
+ raw_mov_w_brrm_indexed(d,base,baser,index,factor);
+ unlock2(d);
+ unlock2(baser);
+ unlock2(index);
}
MENDFUNC(5,mov_w_brrm_indexed,(W2 d, IMM base, RR4 baser, RR4 index, IMM factor))
MIDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, RR4 baser, RR4 index, IMM factor))
{
- int basereg=baser;
- int indexreg=index;
-
- CLOBBER_MOV;
- remove_offset(d,-1);
- baser=readreg_offset(baser,4);
- index=readreg_offset(index,4);
- base+=get_offset(basereg);
- base+=factor*get_offset(indexreg);
- d=writereg(d,1);
- raw_mov_b_brrm_indexed(d,base,baser,index,factor);
- unlock2(d);
- unlock2(baser);
- unlock2(index);
+ int basereg=baser;
+ int indexreg=index;
+
+ CLOBBER_MOV;
+ remove_offset(d,-1);
+ baser=readreg_offset(baser,4);
+ index=readreg_offset(index,4);
+ base+=get_offset(basereg);
+ base+=factor*get_offset(indexreg);
+ d=writereg(d,1);
+ raw_mov_b_brrm_indexed(d,base,baser,index,factor);
+ unlock2(d);
+ unlock2(baser);
+ unlock2(index);
}
MENDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, RR4 baser, RR4 index, IMM factor))
MIDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor))
{
- CLOBBER_LEA;
- s=readreg(s,4);
- index=readreg(index,4);
- d=writereg(d,4);
+ CLOBBER_LEA;
+ s=readreg(s,4);
+ index=readreg(index,4);
+ d=writereg(d,4);
- raw_lea_l_rr_indexed(d,s,index,factor);
- unlock2(d);
- unlock2(index);
- unlock2(s);
+ raw_lea_l_rr_indexed(d,s,index,factor);
+ unlock2(d);
+ unlock2(index);
+ unlock2(s);
}
MENDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor))
{
if (isconst(r)) {
uae_u32 oldv=live.state[r].val;
- live.state[r].val=((oldv>>8)&0xff) | ((oldv<<8)&0xff00) |
- (oldv&0xffff0000);
+ live.state[r].val=((oldv>>8)&0xff) | ((oldv<<8)&0xff00) | (oldv&0xffff0000);
return;
}
MIDFUNC(2,and_l_ri,(RW4 d, IMM i))
{
- if (isconst (d) && ! needflags) {
+ if (isconst(d) && !needflags) {
live.state[d].val &= i;
return;
}
// gb-- used for making an fpcr value in compemu_fpp.cpp
MIDFUNC(2,or_l_rm,(RW4 d, IMM s))
{
- CLOBBER_OR;
- d=rmw(d,4,4);
+ CLOBBER_OR;
+ d=rmw(d,4,4);
- raw_or_l_rm(d,s);
- unlock2(d);
+ raw_or_l_rm(d,s);
+ unlock2(d);
}
MENDFUNC(2,or_l_rm,(RW4 d, IMM s))
in1=readreg_specific(in1,isize,REG_PAR1);
r=readreg(r,4);
prepare_for_call_1(); /* This should ensure that there won't be
- any need for swapping nregs in prepare_for_call_2
- */
+ any need for swapping nregs in prepare_for_call_2
+ */
#if USE_NORMAL_CALLING_CONVENTION
raw_push_l_r(in1);
#endif
in2=readreg_specific(in2,isize2,REG_PAR2);
r=readreg(r,4);
prepare_for_call_1(); /* This should ensure that there won't be
- any need for swapping nregs in prepare_for_call_2
- */
+ any need for swapping nregs in prepare_for_call_2
+ */
#if USE_NORMAL_CALLING_CONVENTION
raw_push_l_r(in2);
raw_push_l_r(in1);
MIDFUNC(0,nop,(void))
{
- raw_nop();
+ raw_emit_nop();
}
MENDFUNC(0,nop,(void))
}
MENDFUNC(2,fmovi_rm,(FW r, MEMR m))
+MIDFUNC(2,fmovi_mr,(MEMW m, FR r))
+{
+ r=f_readreg(r);
+ raw_fmovi_mr(m,r);
+ f_unlock(r);
+}
+MENDFUNC(2,fmovi_mr,(MEMW m, FR r))
+
MIDFUNC(3,fmovi_mrb,(MEMW m, FR r, double *bounds))
{
r=f_readreg(r);
static inline void emit_jmp_target(uae_u32 a) {
emit_long(a-((uintptr)target+4));
}
-
DECLARE_MIDFUNC(fmov_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmov_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmovi_rm(FW r, MEMR m));
+DECLARE_MIDFUNC(fmovi_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmovi_mrb(MEMW m, FR r, double *bounds));
DECLARE_MIDFUNC(fmovs_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmovs_mr(MEMW m, FR r));
STATIC_INLINE uae_u16 swap16(uae_u16 x)
{
+#ifdef _MSC_VER
+ return _byteswap_ushort(x);
+#else
return ((x&0xff00)>>8)|((x&0x00ff)<<8);
+#endif
}
STATIC_INLINE uae_u32 swap32(uae_u32 x)
{
+#ifdef _MSC_VER
+ return _byteswap_ulong(x);
+#else
return ((x&0xff00)<<8)|((x&0x00ff)<<24)|((x&0xff0000)>>8)|((x&0xff000000)>>24);
+#endif
}
STATIC_INLINE int isbyte(uae_s32 x)
#include "memory.h"
#include "custom.h"
#else
-#include "sysdeps.h"
#include "cpu_emulation.h"
#include "main.h"
#include "vm_alloc.h"
#define DEBUG 0
#include "debug.h"
+#define NATMEM_OFFSET MEMBaseDiff
+#define canbang 1
+#define op_illg op_illg_1
+
+#ifdef WINUAE_ARANYM
+void jit_abort(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ ndebug::pdbvprintf(format, args);
+ va_end(args);
+ abort();
+}
+#endif
+
#if DEBUG
#define PROFILE_COMPILE_TIME 1
#define PROFILE_UNTRANSLATED_INSNS 1
static bool avoid_fpu = true; // Flag: compile FPU instructions ?
#endif
static bool have_cmov = false; // target has CMOV instructions ?
-static bool have_lahf_lm = true; // target has LAHF supported in long mode ?
static bool have_rat_stall = true; // target has partial register stalls ?
const bool tune_alignment = true; // Tune code alignments for running CPU ?
const bool tune_nop_fillers = true; // Tune no-op fillers for architecture
return (prop[opcode].cflow == fl_const_jump);
}
+#if 0
static inline bool may_trap(uae_u32 opcode)
{
return (prop[opcode].cflow & fl_trap);
}
+#endif
#endif
static int branch_cc;
static int redo_current_block;
-int segvcount=0;
-int soft_flush_count=0;
-int hard_flush_count=0;
-int checksum_count=0;
static uae_u8* current_compile_p=NULL;
static uae_u8* max_compile_start;
static uae_u8* compiled_code=NULL;
* UPDATE: We now use those entries to store the start of the linked
* lists that we maintain for each hash result.
*/
-static
-cacheline cache_tags[TAGSIZE];
-int letit=0;
-static
-blockinfo* hold_bi[MAX_HOLD_BI];
-static
-blockinfo* active;
-static
-blockinfo* dormant;
+static cacheline cache_tags[TAGSIZE];
+static int cache_enabled=0;
+static blockinfo* hold_bi[MAX_HOLD_BI];
+static blockinfo* active;
+static blockinfo* dormant;
#ifdef NOFLAGS_SUPPORT
/* 68040 */
extern const struct cputbl op_smalltbl_5_nf[];
#endif
-static
-bigstate live;
-static
-smallstate empty_ss;
-static
-smallstate default_ss;
+#ifdef WINUAE_ARANYM
+static void flush_icache_hard(int n);
+static void flush_icache_lazy(int n);
+static void flush_icache_none(int n);
+void (*flush_icache)(int n) = flush_icache_none;
+#endif
+
+static bigstate live;
+static smallstate empty_ss;
+static smallstate default_ss;
static int optlev;
static int writereg(int r, int size);
* side effects they would have on the flags are not important. This
* variable indicates whether we need the side effects or not
*/
-uae_u32 needflags=0;
+static uae_u32 needflags=0;
/* Flag handling is complicated.
*
return NULL;
}
+#ifdef WINUAE_ARANYM
+/*******************************************************************
+ * Disassembler support *
+ *******************************************************************/
+
+#define TARGET_M68K 0
+#define TARGET_POWERPC 1
+#define TARGET_X86 2
+#define TARGET_X86_64 3
+#define TARGET_ARM 4
+#if defined(CPU_i386)
+#define TARGET_NATIVE TARGET_X86
+#endif
+#if defined(CPU_powerpc)
+#define TARGET_NATIVE TARGET_POWERPC
+#endif
+#if defined(CPU_x86_64)
+#define TARGET_NATIVE TARGET_X86_64
+#endif
+#if defined(CPU_arm)
+#define TARGET_NATIVE TARGET_ARM
+#endif
+#include "disasm-glue.h"
+
+#ifdef JIT_DEBUG
+static void disasm_block(int disasm_target, const uint8 *start, size_t length)
+{
+ UNUSED(start);
+ UNUSED(length);
+ switch (disasm_target)
+ {
+ case TARGET_M68K:
+#if defined(HAVE_DISASM_M68K)
+ {
+ char buf[256];
+
+ disasm_info.memory_vma = ((memptr)((uintptr_t)(start) - MEMBaseDiff));
+ while (length > 0)
+ {
+ int isize = m68k_disasm_to_buf(&disasm_info, buf);
+ bug("%s", buf);
+ if (isize < 0)
+ break;
+ if ((uintptr)isize > length)
+ break;
+ length -= isize;
+ }
+ }
+#endif
+ break;
+ case TARGET_X86:
+ case TARGET_X86_64:
+#if defined(HAVE_DISASM_X86)
+ {
+ const uint8 *end = start + length;
+ char buf[256];
+
+ while (start < end)
+ {
+ start = x86_disasm(start, buf);
+ bug("%s", buf);
+ }
+ }
+#endif
+ break;
+ case TARGET_ARM:
+#if defined(HAVE_DISASM_ARM)
+ {
+ const uint8 *end = start + length;
+ char buf[256];
+
+ while (start < end)
+ {
+ start = arm_disasm(start, buf);
+ bug("%s", buf);
+ }
+ }
+#endif
+ break;
+ }
+}
+
+static inline void disasm_native_block(const uint8 *start, size_t length)
+{
+ disasm_block(TARGET_NATIVE, start, length);
+}
+
+static inline void disasm_m68k_block(const uint8 *start, size_t length)
+{
+ disasm_block(TARGET_M68K, start, length);
+}
+#endif
+#endif
+
/*******************************************************************
* All sorts of list related functions for all of the lists *
bi->next->prev_p=bi->prev_p;
}
+#if 0
static inline void remove_from_lists(blockinfo* bi)
{
remove_from_list(bi);
remove_from_cl_list(bi);
}
+#endif
static inline void add_to_cl_list(blockinfo* bi)
{
bi->status = BI_NEED_RECOMP;
}
+#if USE_MATCH
static inline void mark_callers_recompile(blockinfo * bi)
{
dependency *x = bi->deplist;
- while (x) {
+ while (x) {
dependency *next = x->next; /* This disappears when we mark for
* recompilation and thus remove the
* blocks from the lists */
x = next;
}
}
+#endif
static inline blockinfo* get_blockinfo_addr_new(void* addr, int /* setstate */)
{
return data;
}
- void release(T * const chunk) {
+ void release(T * const ) {
// Deallocated on invalidation
}
};
*target++=x;
}
-static inline void emit_word(uae_u16 x)
-{
- *((uae_u16*)target)=x;
- target+=2;
-}
-
-static inline void emit_long(uae_u32 x)
-{
- *((uae_u32*)target)=x;
- target+=4;
-}
-
static inline void skip_n_bytes(int n) {
target += n;
}
static inline void skip_byte()
{
- target++;
+ skip_n_bytes(1);
}
static inline void skip_word()
{
- target += 2;
+ skip_n_bytes(2);
}
static inline void skip_long()
{
- target += 4;
+ skip_n_bytes(4);
}
static inline void skip_quad()
{
- target += 8;
+ skip_n_bytes(8);
+}
+
+static inline void emit_word(uae_u16 x)
+{
+ *((uae_u16*)target)=x;
+ skip_word();
+}
+
+static inline void emit_long(uae_u32 x)
+{
+ *((uae_u32*)target)=x;
+ skip_long();
}
-static __inline__ void emit_quad(uae_u64 x)
+static inline void emit_quad(uae_u64 x)
{
*((uae_u64*) target) = x;
- target += 8;
+ skip_quad();
}
static inline void emit_block(const uae_u8 *block, uae_u32 blocklen)
static inline uae_u32 reverse32(uae_u32 v)
{
-#if 0
+#ifdef WINUAE_ARANYM
// gb-- We have specialized byteswapping functions, just use them
return do_byteswap_32(v);
+#elif _MSC_VER
+ return _byteswap_ulong(v);
#else
return ((v>>24)&0xff) | ((v>>8)&0xff00) | ((v<<8)&0xff0000) | ((v<<24)&0xff000000);
#endif
uae_u16 wmask;
};
+#if 0
static inline void ru_set(uae_u16 *mask, int reg)
{
#if USE_OPTIMIZED_CALLS
return ru_get(&ru->wmask, reg);
}
-#if 0
static void ru_fill_ea(regusage *ru, int reg, amodes mode,
wordsizes size, int write_mode)
{
#define L_NEEDED -2
#define L_UNNEEDED -3
+#if USE_MATCH
static inline void big_to_small_state(bigstate * /* b */, smallstate * s)
{
int i;
* callers */
return 0;
}
+#endif
static inline void log_startblock(void)
{
int i;
for (i = 0; i < VREGS; i++) {
- vstate[i]=L_UNKNOWN;
- vwritten[i] = 0;
+ vstate[i] = L_UNKNOWN;
+ vwritten[i] = 0;
}
- for (i=0;i<N_REGS;i++)
- nstate[i]=L_UNKNOWN;
+ for (i = 0; i < N_REGS; i++)
+ nstate[i] = L_UNKNOWN;
}
/* Using an n-reg for a temp variable */
static inline void log_isused(int n)
{
- if (nstate[n]==L_UNKNOWN)
- nstate[n]=L_UNAVAIL;
+ if (nstate[n] == L_UNKNOWN)
+ nstate[n] = L_UNAVAIL;
}
static inline void log_visused(int r)
compemu_raw_mov_l_rm(n, (uintptr) live.state[r].mem);
}
+#if 0
static inline void check_load_reg(int n, int r)
{
compemu_raw_mov_l_rm(n, (uintptr) live.state[r].mem);
}
+#endif
static inline void log_vwrite(int r)
{
static inline void log_isreg(int n, int r)
{
if (nstate[n] == L_UNKNOWN && r < 16 && !vwritten[r] && USE_MATCH)
- nstate[n]=r;
+ nstate[n] = r;
else {
do_load_reg(n, r);
if (nstate[n] == L_UNKNOWN)
nstate[n] = L_UNAVAIL;
}
- if (vstate[r]==L_UNKNOWN)
- vstate[r]=L_NEEDED;
+ if (vstate[r] == L_UNKNOWN)
+ vstate[r] = L_NEEDED;
}
static inline void log_clobberreg(int r)
{
- if (vstate[r]==L_UNKNOWN)
- vstate[r]=L_UNNEEDED;
+ if (vstate[r] == L_UNKNOWN)
+ vstate[r] = L_UNNEEDED;
}
/* This ends all possibility of clever register allocation */
static inline void log_flush(void)
{
int i;
-
- for (i=0;i<VREGS;i++)
- if (vstate[i]==L_UNKNOWN)
- vstate[i]=L_NEEDED;
- for (i=0;i<N_REGS;i++)
- if (nstate[i]==L_UNKNOWN)
- nstate[i]=L_UNAVAIL;
+
+ for (i = 0; i < VREGS; i++)
+ if (vstate[i] == L_UNKNOWN)
+ vstate[i] = L_NEEDED;
+ for (i = 0; i < N_REGS; i++)
+ if (nstate[i] == L_UNKNOWN)
+ nstate[i] = L_UNAVAIL;
}
static inline void log_dump(void)
return;
jit_log("----------------------");
- for (i=0;i<N_REGS;i++) {
- switch(nstate[i]) {
+ for (i = 0; i < N_REGS; i++) {
+ switch (nstate[i]) {
case L_UNKNOWN:
- jit_log("Nat %d : UNKNOWN",i);
+ jit_log("Nat %d : UNKNOWN", i);
break;
case L_UNAVAIL:
- jit_log("Nat %d : UNAVAIL",i);
+ jit_log("Nat %d : UNAVAIL", i);
break;
default:
- jit_log("Nat %d : %d",i,nstate[i]);
+ jit_log("Nat %d : %d", i, nstate[i]);
break;
}
}
- for (i=0;i<VREGS;i++) {
+ for (i = 0; i < VREGS; i++) {
if (vstate[i] == L_UNNEEDED) {
- jit_log("Virt %d: UNNEEDED",i);
+ jit_log("Virt %d: UNNEEDED", i);
}
}
}
static inline void set_status(int r, int status)
{
- if (status==ISCONST)
+ if (status == ISCONST)
log_clobberreg(r);
live.state[r].status=status;
}
compemu_raw_lea_l_brr(r,r,val);
}
-static void tomem(int r)
+static void tomem(int r)
{
int rr=live.state[r].realreg;
if (isinreg(r)) {
if (live.state[r].val && live.nat[rr].nholds==1
&& !live.nat[rr].locked) {
- jit_log2("RemovingA offset %x from reg %d (%d) at %p", live.state[r].val,r,rr,target);
- adjust_nreg(rr,live.state[r].val);
- live.state[r].val=0;
- live.state[r].dirtysize=4;
- set_status(r,DIRTY);
+ jit_log2("RemovingA offset %x from reg %d (%d) at %p", live.state[r].val,r,rr,target);
+ adjust_nreg(rr,live.state[r].val);
+ live.state[r].val=0;
+ live.state[r].dirtysize=4;
+ set_status(r,DIRTY);
}
}
tomem(r);
}
-static void evict(int r)
+static void evict(int r)
{
int rr;
Dif (live.nat[rr].locked &&
live.nat[rr].nholds==1) {
- jit_abort("register %d in nreg %d is locked!",r,live.state[r].realreg);
+ jit_abort("register %d in nreg %d is locked!",r,live.state[r].realreg);
}
live.nat[rr].nholds--;
if (live.nat[rr].nholds!=live.state[r].realind) { /* Was not last */
int topreg=live.nat[rr].holds[live.nat[rr].nholds];
int thisind=live.state[r].realind;
-
+
live.nat[rr].holds[thisind]=topreg;
live.state[topreg].realind=thisind;
}
return live.state[r].val;
}
-static int alloc_reg_hinted(int r, int size, int willclobber, int hint)
+static int alloc_reg_hinted(int r, int size, int willclobber, int hint)
{
int bestreg;
uae_s32 when;
if ((size==1 && live.nat[i].canbyte) ||
(size==2 && live.nat[i].canword) ||
(size==4)) {
- bestreg=i;
- when=badness;
- if (live.nat[i].nholds==0 && hint<0)
- break;
- if (i==hint)
- break;
+ bestreg=i;
+ when=badness;
+ if (live.nat[i].nholds==0 && hint<0)
+ break;
+ if (i==hint)
+ break;
}
}
}
if (isinreg(r)) {
int rr=live.state[r].realreg;
/* This will happen if we read a partially dirty register at a
- bigger size */
+ bigger size */
Dif (willclobber || live.state[r].validsize>=size)
jit_abort("willclobber || live.state[r].validsize>=size");
Dif (live.nat[rr].nholds!=1)
if (size == 4) {
log_clobberreg(r);
log_isused(bestreg);
- }
+ }
else {
log_visused(r);
log_isused(bestreg);
}
/*
-static int alloc_reg(int r, int size, int willclobber)
+static int alloc_reg(int r, int size, int willclobber)
{
return alloc_reg_hinted(r,size,willclobber,-1);
}
live.nat[r].locked--;
}
-static void setlock(int r)
+static void setlock(int r)
{
live.nat[r].locked++;
}
/* Get a new register, that we will clobber completely */
if (oldstate.status==DIRTY) {
/* If dirtysize is <4, we need a register that can handle the
- eventual smaller memory store! Thanks to Quake68k for exposing
- this detail ;-) */
+ eventual smaller memory store! Thanks to Quake68k for exposing
+ this detail ;-) */
nr=alloc_reg_hinted(r,oldstate.dirtysize,1,spec);
}
else {
static inline void flush_reg_count(void)
{
#ifdef RECORD_REGISTER_USAGE
- for (int r = 0; r < 16; r++)
- if (reg_count_local[r])
- ADDQim(reg_count_local[r], ((uintptr)reg_count) + (8 * r), X86_NOREG, X86_NOREG, 1);
+ for (int r = 0; r < 16; r++)
+ if (reg_count_local[r])
+ ADDQim(reg_count_local[r], ((uintptr)reg_count) + (8 * r), X86_NOREG, X86_NOREG, 1);
#endif
}
static inline void record_register(int r)
{
#ifdef RECORD_REGISTER_USAGE
- if (r < 16)
- reg_count_local[r]++;
+ if (r < 16)
+ reg_count_local[r]++;
#else
UNUSED(r);
#endif
evict(r);
}
/* either the value was in memory to start with, or it was evicted and
- is in memory now */
+ is in memory now */
if (answer<0) {
answer=alloc_reg_hinted(r,spec>=0?4:size,0,spec);
}
evict(r);
}
/* either the value was in memory to start with, or it was evicted and
- is in memory now */
+ is in memory now */
if (answer<0) {
answer=alloc_reg_hinted(r,size,1,spec);
}
if (isinreg(r) && live.state[r].validsize>=rsize) {
n=live.state[r].realreg;
Dif (live.nat[n].nholds!=1)
- jit_abort("live.nat[n].nholds!=1", n);
+ jit_abort("live.nat[%d].nholds!=1", n);
switch(rsize) {
case 1:
evict(r);
}
/* either the value was in memory to start with, or it was evicted and
- is in memory now */
+ is in memory now */
if (answer<0) {
answer=alloc_reg_hinted(r,spec>=0?4:rsize,0,spec);
}
* FPU register status handling. EMIT TIME! *
********************************************************************/
-static void f_tomem(int r)
+static void f_tomem(int r)
{
if (live.fate[r].status==DIRTY) {
if (use_long_double) {
}
}
-static void f_tomem_drop(int r)
+static void f_tomem_drop(int r)
{
if (live.fate[r].status==DIRTY) {
if (use_long_double) {
Dif (live.fat[rr].locked &&
live.fat[rr].nholds==1) {
- jit_abort("FPU register %d in nreg %d is locked!",r,live.fate[r].realreg);
+ jit_abort("FPU register %d in nreg %d is locked!",r,live.fate[r].realreg);
}
live.fat[rr].nholds--;
-static int f_alloc_reg(int r, int willclobber)
+static int f_alloc_reg(int r, int willclobber)
{
int bestreg;
uae_s32 when;
}
}
Dif (bestreg==-1)
- abort();
+ jit_abort("bestreg==-1");
if (live.fat[bestreg].nholds>0) {
f_free_nreg(bestreg);
return bestreg;
}
-static void f_unlock(int r)
+static void f_unlock(int r)
{
Dif (!live.fat[r].locked)
- jit_abort (_T("unlock %d"), r);
+ jit_abort ("unlock %d", r);
live.fat[r].locked--;
}
-static void f_setlock(int r)
+static void f_setlock(int r)
{
live.fat[r].locked++;
}
answer=n;
}
/* either the value was in memory to start with, or it was evicted and
- is in memory now */
+ is in memory now */
if (answer<0)
answer=f_alloc_reg(r,0);
return answer;
}
-static int f_rmw(int r)
-{
- int n;
-
- f_make_exclusive(r,0);
- if (f_isinreg(r)) {
- n=live.fate[r].realreg;
- }
- else
- n=f_alloc_reg(r,0);
- live.fate[r].status=DIRTY;
- live.fat[n].locked++;
- live.fat[n].touched=touchcnt++;
- return n;
-}
-
-static void fflags_into_flags_internal(uae_u32 tmp)
-{
- int r;
-
- clobber_flags();
- r=f_readreg(FP_RESULT);
- if (FFLAG_NREG_CLOBBER_CONDITION) {
- int tmp2=tmp;
- tmp=writereg_specific(tmp,4,FFLAG_NREG);
- raw_fflags_into_flags(r);
- unlock2(tmp);
- forget_about(tmp2);
- }
- else
- raw_fflags_into_flags(r);
- f_unlock(r);
- live_flags();
-}
-
-
#if defined(CPU_arm)
#include "compemu_midfunc_arm.cpp"
void set_zero(int r, int tmp)
{
- if (setzflg_uses_bsf)
- bsf_l_rr(r,r);
- else
- simulate_bsf(tmp,r);
+ if (setzflg_uses_bsf)
+ bsf_l_rr(r,r);
+ else
+ simulate_bsf(tmp,r);
}
int kill_rodent(int r)
return KILLTHERAT &&
have_rat_stall &&
(live.state[r].status==INMEM ||
- live.state[r].status==CLEAN ||
- live.state[r].status==ISCONST ||
- live.state[r].dirtysize==4);
+ live.state[r].status==CLEAN ||
+ live.state[r].status==ISCONST ||
+ live.state[r].dirtysize==4);
}
uae_u32 get_const(int r)
{
- Dif (!isconst(r)) {
- jit_abort("Register %d should be constant, but isn't",r);
+ Dif (!isconst(r)) {
+ jit_abort("Register %d should be constant, but isn't",r);
}
return live.state[r].val;
}
#else
#ifdef JIT_DEBUG
// JIT debug mode ?
- JITDebug = bx_options.startup.debugger;
+ JITDebug = bx_options.jit.jitdebug;
#endif
jit_log("<JIT compiler> : enable runtime disassemblers : %s", JITDebug ? "yes" : "no");
cache_size = bx_options.jit.jitcachesize;
jit_log("<JIT compiler> : requested translation cache size : %d KB", cache_size);
- // Initialize target CPU (check for features, e.g. CMOV, rat stalls)
- raw_init_cpu();
setzflg_uses_bsf = target_check_bsf();
jit_log("<JIT compiler> : target processor has CMOV instructions : %s", have_cmov ? "yes" : "no");
jit_log("<JIT compiler> : target processor can suffer from partial register stalls : %s", have_rat_stall ? "yes" : "no");
#else
#if DEBUG
#if defined(USE_DATA_BUFFER)
- printf("data_wasted = %d bytes\n", data_wasted);
+ jit_log("data_wasted = %d bytes", data_wasted);
#endif
#endif
+
// Deallocate translation cache
if (compiled_code) {
vm_release(compiled_code, cache_size * 1024);
int reg_count_ids[16];
uint64 tot_reg_count = 0;
for (int i = 0; i < 16; i++) {
- reg_count_ids[i] = i;
- tot_reg_count += reg_count[i];
+ reg_count_ids[i] = i;
+ tot_reg_count += reg_count[i];
}
qsort(reg_count_ids, 16, sizeof(int), reg_count_compare);
uint64 cum_reg_count = 0;
for (int i = 0; i < 16; i++) {
- int r = reg_count_ids[i];
- cum_reg_count += reg_count[r];
- jit_log("%c%d : %16ld %2.1f%% [%2.1f]", r < 8 ? 'D' : 'A', r % 8,
+ int r = reg_count_ids[i];
+ cum_reg_count += reg_count[r];
+ jit_log("%c%d : %16ld %2.1f%% [%2.1f]", r < 8 ? 'D' : 'A', r % 8,
reg_count[r],
100.0*double(reg_count[r])/double(tot_reg_count),
100.0*double(cum_reg_count)/double(tot_reg_count));
for (i=0;i<VREGS;i++) {
if (i<16) { /* First 16 registers map to 68k registers */
-#ifdef UAE
live.state[i].mem=®s.regs[i];
-#else
- live.state[i].mem=((uae_u32*)®s)+i;
-#endif
live.state[i].needflush=NF_TOMEM;
set_status(i,INMEM);
}
for (i=0;i<VFREGS;i++) {
if (live.fate[i].needflush==NF_SCRATCH ||
live.fate[i].status==CLEAN) {
- f_disassociate(i);
+ f_disassociate(i);
}
}
for (i=0;i<VREGS;i++) {
break;
case CLEAN:
case DIRTY:
- remove_offset(i,-1); tomem(i); break;
+ remove_offset(i,-1);
+ tomem(i);
+ break;
case ISCONST:
if (i!=PC_P)
writeback_const(i);
for (i=0;i<VFREGS;i++) {
if (live.fate[i].needflush==NF_TOMEM &&
live.fate[i].status==DIRTY) {
- f_evict(i);
+ f_evict(i);
}
}
raw_fp_cleanup_drop();
for (i=0;i<VFREGS;i++) {
if (live.fate[i].needflush==NF_SCRATCH ||
live.fate[i].status==CLEAN) {
- f_disassociate(i);
+ f_disassociate(i);
}
}
for (i=0;i<VREGS;i++) {
break;
case CLEAN:
case DIRTY:
- remove_offset(i,-1); tomem(i); break;
+ remove_offset(i,-1);
+ tomem(i);
+ break;
case ISCONST:
if (i!=PC_P)
writeback_const(i);
for (i=0;i<VFREGS;i++) {
if (live.fate[i].needflush==NF_TOMEM &&
live.fate[i].status==DIRTY) {
- f_evict(i);
+ f_evict(i);
}
}
raw_fp_cleanup_drop();
{
int i;
for (i=0;i<N_REGS;i++)
- if (live.nat[i].locked && i!=4 && i!= 12) {
+#if defined(CPU_arm)
+ if (live.nat[i].locked && i != REG_WORK1 && i != REG_WORK2)
+#else
+ if (live.nat[i].locked && i != ESP_INDEX
+#if defined(UAE) && defined(CPU_x86_64)
+ && i != R12_INDEX
+#endif
+ )
+#endif
+ {
jit_log("Warning! %d is locked",i);
- }
+ }
for (i=0;i<VREGS;i++)
if (live.state[i].needflush==NF_SCRATCH) {
forget_about(i);
}
- for (i=0;i<VFREGS;i++)
- if (live.fate[i].needflush==NF_SCRATCH) {
- f_forget_about(i);
- }
+ for (i=0;i<VFREGS;i++)
+ if (live.fate[i].needflush==NF_SCRATCH) {
+ f_forget_about(i);
+ }
}
/********************************************************************
else {
/* Fill with NOPs --- makes debugging with gdb easier */
while ((uintptr)target&(a-1))
- *target++=0x90; // Attention x86 specific code
+ emit_byte(0x90); // Attention x86 specific code
}
}
tomem(i);
}
}
- for (i=0;i<VFREGS;i++)
- if (f_isinreg(i))
- f_evict(i);
- raw_fp_cleanup_drop();
+ for (i=0;i<VFREGS;i++)
+ if (f_isinreg(i))
+ f_evict(i);
+ raw_fp_cleanup_drop();
}
/* Make sure all registers that will get clobbered by a call are
static void prepare_for_call_1(void)
{
flush_all(); /* If there are registers that don't get clobbered,
- * we should be a bit more selective here */
+ * we should be a bit more selective here */
}
/* We will call a C routine in a moment. That will clobber all registers,
f_free_nreg(i);
live.flags_in_flags=TRASH; /* Note: We assume we already rescued the
- flags at the very start of the call_r
- functions! */
+ flags at the very start of the call_r
+ functions! */
}
/********************************************************************
}
/* Note: get_handler may fail in 64 Bit environments, if direct_handler_to_use is
- * outside 32 bit
+ * outside 32 bit
*/
static uintptr get_handler(uintptr addr)
{
}
/* This version assumes that it is writing *real* memory, and *will* fail
-* if that assumption is wrong! No branches, no second chances, just
-* straight go-for-it attitude */
+ * if that assumption is wrong! No branches, no second chances, just
+ * straight go-for-it attitude */
static void writemem_real(int address, int source, int size, int tmp, int clobber)
{
f=source;
switch(size) {
- case 1: mov_b_bRr(address,source,MEMBaseDiff); break;
- case 2: mov_w_rr(f,source); mid_bswap_16(f); mov_w_bRr(address,f,MEMBaseDiff); break;
- case 4: mov_l_rr(f,source); mid_bswap_32(f); mov_l_bRr(address,f,MEMBaseDiff); break;
+ case 1: mov_b_bRr(address,source,MEMBaseDiff); break;
+ case 2: mov_w_rr(f,source); mid_bswap_16(f); mov_w_bRr(address,f,MEMBaseDiff); break;
+ case 4: mov_l_rr(f,source); mid_bswap_32(f); mov_l_bRr(address,f,MEMBaseDiff); break;
}
forget_about(tmp);
forget_about(f);
}
#endif
+#ifdef UAE
mov_l_rr(f,address);
shrl_l_ri(f,16); /* The index into the baseaddr table */
mov_l_rm_indexed(f,uae_p32(baseaddr),f,SIZEOF_VOID_P); /* FIXME: is SIZEOF_VOID_P correct? */
case 4: mid_bswap_32(source); mov_l_mrr_indexed(address,f,1,source);
mid_bswap_32(source); break;
}
+#endif
}
+#ifdef UAE
static inline void writemem(int address, int source, int offset, int size, int tmp)
{
int f=tmp;
call_r_02(f,address,source,4,size);
forget_about(tmp);
}
+#endif
void writebyte(int address, int source, int tmp)
{
+#ifdef UAE
if ((special_mem & S_WRITE) || distrust_byte())
writemem_special(address, source, 5 * SIZEOF_VOID_P, 1, tmp);
else
+#endif
writemem_real(address,source,1,tmp,0);
}
static inline void writeword_general(int address, int source, int tmp,
int clobber)
{
+#ifdef UAE
if ((special_mem & S_WRITE) || distrust_word())
writemem_special(address, source, 4 * SIZEOF_VOID_P, 2, tmp);
else
+#endif
writemem_real(address,source,2,tmp,clobber);
}
static inline void writelong_general(int address, int source, int tmp,
int clobber)
{
+#ifdef UAE
if ((special_mem & S_WRITE) || distrust_long())
writemem_special(address, source, 3 * SIZEOF_VOID_P, 4, tmp);
else
+#endif
writemem_real(address,source,4,tmp,clobber);
}
/* This version assumes that it is reading *real* memory, and *will* fail
-* if that assumption is wrong! No branches, no second chances, just
-* straight go-for-it attitude */
+ * if that assumption is wrong! No branches, no second chances, just
+ * straight go-for-it attitude */
static void readmem_real(int address, int dest, int size, int tmp)
{
#ifdef NATMEM_OFFSET
if (canbang) { /* Woohoo! go directly at the memory! */
switch(size) {
- case 1: mov_b_brR(dest,address,MEMBaseDiff); break;
- case 2: mov_w_brR(dest,address,MEMBaseDiff); mid_bswap_16(dest); break;
- case 4: mov_l_brR(dest,address,MEMBaseDiff); mid_bswap_32(dest); break;
+ case 1: mov_b_brR(dest,address,MEMBaseDiff); break;
+ case 2: mov_w_brR(dest,address,MEMBaseDiff); mid_bswap_16(dest); break;
+ case 4: mov_l_brR(dest,address,MEMBaseDiff); mid_bswap_32(dest); break;
}
forget_about(tmp);
(void) f;
}
#endif
+#ifdef UAE
mov_l_rr(f,address);
shrl_l_ri(f,16); /* The index into the baseaddr table */
mov_l_rm_indexed(f,uae_p32(baseaddr),f,SIZEOF_VOID_P); /* FIXME: is SIZEOF_VOID_P correct? */
case 4: mov_l_rrm_indexed(dest,address,f,1); mid_bswap_32(dest); break;
}
forget_about(tmp);
+#endif
}
+#ifdef UAE
static inline void readmem(int address, int dest, int offset, int size, int tmp)
{
int f=tmp;
call_r_11(dest,f,address,size,4);
forget_about(tmp);
}
+#endif
void readbyte(int address, int dest, int tmp)
{
+#ifdef UAE
if ((special_mem & S_READ) || distrust_byte())
readmem_special(address, dest, 2 * SIZEOF_VOID_P, 1, tmp);
else
+#endif
readmem_real(address,dest,1,tmp);
}
void readword(int address, int dest, int tmp)
{
+#ifdef UAE
if ((special_mem & S_READ) || distrust_word())
readmem_special(address, dest, 1 * SIZEOF_VOID_P, 2, tmp);
else
+#endif
readmem_real(address,dest,2,tmp);
}
void readlong(int address, int dest, int tmp)
{
+#ifdef UAE
if ((special_mem & S_READ) || distrust_long())
readmem_special(address, dest, 0 * SIZEOF_VOID_P, 4, tmp);
else
+#endif
readmem_real(address,dest,4,tmp);
}
void get_n_addr(int address, int dest, int tmp)
{
+#ifdef UAE
if (special_mem || distrust_addr()) {
/* This one might appear a bit odd... */
readmem(address, dest, 6 * SIZEOF_VOID_P, 4, tmp);
return;
}
+#endif
// a is the register containing the virtual address
// after the offset had been fetched
return;
}
#endif
+
+#ifdef UAE
mov_l_rr(f,address);
mov_l_rr(dest,address); // gb-- nop if dest==address
shrl_l_ri(f,16);
mov_l_rm_indexed(f,uae_p32(baseaddr),f,SIZEOF_VOID_P); /* FIXME: is SIZEOF_VOID_P correct? */
add_l(dest,f);
forget_about(tmp);
+#endif
}
void get_n_addr_jmp(int address, int dest, int tmp)
{
-#if 0
+#ifdef WINUAE_ARANYM
/* For this, we need to get the same address as the rest of UAE
would --- otherwise we end up translating everything twice */
get_n_addr(address,dest,tmp);
void set_cache_state(int enabled)
{
- if (enabled!=letit)
- flush_icache_hard(3);
- letit=enabled;
+ if (enabled!=cache_enabled)
+ flush_icache_hard(77);
+ cache_enabled=enabled;
}
int get_cache_state(void)
{
- return letit;
+ return cache_enabled;
}
uae_u32 get_jitted_size(void)
return 0;
}
-const int CODE_ALLOC_MAX_ATTEMPTS = 10;
-const int CODE_ALLOC_BOUNDARIES = 128 * 1024; // 128 KB
-
static uint8 *do_alloc_code(uint32 size, int depth)
{
-#if defined(__linux__) && 0
- /*
- This is a really awful hack that is known to work on Linux at
- least.
-
- The trick here is to make sure the allocated cache is nearby
- code segment, and more precisely in the positive half of a
- 32-bit address space. i.e. addr < 0x80000000. Actually, it
- turned out that a 32-bit binary run on AMD64 yields a cache
- allocated around 0xa0000000, thus causing some troubles when
- translating addresses from m68k to x86.
- */
- static uint8 * code_base = NULL;
- if (code_base == NULL) {
- uintptr page_size = getpagesize();
- uintptr boundaries = CODE_ALLOC_BOUNDARIES;
- if (boundaries < page_size)
- boundaries = page_size;
- code_base = (uint8 *)sbrk(0);
- for (int attempts = 0; attempts < CODE_ALLOC_MAX_ATTEMPTS; attempts++) {
- if (vm_acquire_fixed(code_base, size) == 0) {
- uint8 *code = code_base;
- code_base += size;
- return code;
- }
- code_base += boundaries;
- }
- return NULL;
- }
-
- if (vm_acquire_fixed(code_base, size) == 0) {
- uint8 *code = code_base;
- code_base += size;
- return code;
- }
-
- if (depth >= CODE_ALLOC_MAX_ATTEMPTS)
- return NULL;
-
- return do_alloc_code(size, depth + 1);
-#else
UNUSED(depth);
uint8 *code = (uint8 *)vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_32BIT);
return code == VM_MAP_FAILED ? NULL : code;
-#endif
}
static inline uint8 *alloc_code(uint32 size)
void alloc_cache(void)
{
if (compiled_code) {
- flush_icache_hard(3);
+ flush_icache_hard(6);
vm_release(compiled_code, cache_size * 1024);
compiled_code = 0;
}
vm_protect(compiled_code, cache_size * 1024, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE);
if (compiled_code) {
- jit_log("Actual translation cache size : %d KB at %p-%p", cache_size, compiled_code, compiled_code + cache_size*1024);
+ jit_log("<JIT compiler> : actual translation cache size : %d KB at %p-%p", cache_size, compiled_code, compiled_code + cache_size*1024);
#ifdef USE_DATA_BUFFER
max_compile_start = compiled_code + cache_size*1024 - BYTES_PER_INST - DATA_BUFFER_SIZE;
#else
max_compile_start = compiled_code + cache_size*1024 - BYTES_PER_INST;
#endif
- current_compile_p=compiled_code;
+ current_compile_p = compiled_code;
current_cache_size = 0;
#if defined(USE_DATA_BUFFER)
reset_data_buffer();
static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2)
{
- uae_u32 k1=0;
- uae_u32 k2=0;
+ uae_u32 k1 = 0;
+ uae_u32 k2 = 0;
#if USE_CHECKSUM_INFO
checksum_info *csi = bi->csi;
uae_s32 len = csi->length;
uintptr tmp = (uintptr)csi->start_p;
#else
- uae_s32 len=bi->len;
+ uae_s32 len = bi->len;
uintptr tmp = (uintptr)bi->min_pcp;
#endif
uae_u32* pos;
- len+=(tmp&3);
+ len += (tmp & 3);
tmp &= ~((uintptr)3);
- pos=(uae_u32*)tmp;
+ pos = (uae_u32 *)tmp;
if (len >= 0 && len <= MAX_CHECKSUM_LEN) {
- while (len>0) {
- k1+=*pos;
- k2^=*pos;
+ while (len > 0) {
+ k1 += *pos;
+ k2 ^= *pos;
pos++;
- len-=4;
+ len -= 4;
}
}
static void recompile_block(void)
{
/* An existing block's countdown code has expired. We need to make
- sure that execute_normal doesn't refuse to recompile due to a
- perceived cache miss... */
+ sure that execute_normal doesn't refuse to recompile due to a
+ perceived cache miss... */
blockinfo* bi=get_blockinfo_addr(regs.pc_p);
Dif (!bi)
static void cache_miss(void)
{
blockinfo* bi=get_blockinfo_addr(regs.pc_p);
+#if COMP_DEBUG
uae_u32 cl=cacheline(regs.pc_p);
blockinfo* bi2=get_blockinfo(cl);
+#endif
if (!bi) {
execute_normal(); /* Compile this block now */
{
uae_u32 c1,c2;
bool isgood;
-
+
if (bi->status!=BI_NEED_CHECK)
return 1; /* This block is in a checked state */
- checksum_count++;
-
if (bi->c1 || bi->c2)
calc_checksum(bi,&c1,&c2);
else {
if (isgood) {
/* This block is still OK. So we reactivate. Of course, that
- means we have to move it into the needs-to-be-flushed list */
+ means we have to move it into the needs-to-be-flushed list */
bi->handler_to_use=bi->handler;
set_dhtu(bi,bi->direct_handler);
bi->status=BI_CHECKING;
}
else {
/* This block actually changed. We need to invalidate it,
- and set it up to be recompiled */
+ and set it up to be recompiled */
jit_log2("discard %p/%p (%x %x/%x %x)",bi,bi->pc_p, c1,c2,bi->c1,bi->c2);
invalidate_block(bi);
raise_in_cl_list(bi);
for (i=0;i<2 && isgood;i++) {
if (bi->dep[i].jmp_off) {
- isgood=block_check_checksum(bi->dep[i].target);
+ isgood=block_check_checksum(bi->dep[i].target);
}
}
return isgood;
uae_u32 cl=cacheline(regs.pc_p);
blockinfo* bi2=get_blockinfo(cl);
- /* These are not the droids you are looking for... */
+ /* These are not the droids you are looking for... */
if (!bi) {
/* Whoever is the primary target is in a dormant state, but
- calling it was accidental, and we should just compile this
- new block */
+ calling it was accidental, and we should just compile this
+ new block */
execute_normal();
return;
}
{
int i,r;
-#ifdef UAE
if (popallspace == NULL) {
-#endif
if ((popallspace = alloc_code(POPALLSPACE_SIZE)) == NULL) {
-#ifdef UAE
jit_log("WARNING: Could not allocate popallspace!");
- if (currprefs.cachesize > 0) {
+#ifdef UAE
+ if (currprefs.cachesize > 0)
#endif
+ {
jit_abort("Could not allocate popallspace!");
-#ifdef UAE
}
+#ifdef UAE
/* This is not fatal if JIT is not used. If JIT is
* turned on, it will crash, but it would have crashed
* anyway. */
return;
+#endif
}
}
-#endif
vm_protect(popallspace, POPALLSPACE_SIZE, VM_PAGE_READ | VM_PAGE_WRITE);
int stack_space = STACK_OFFSET;
r=REG_PC_TMP;
compemu_raw_mov_l_rm(r, uae_p32(®s.pc_p));
compemu_raw_and_l_ri(r,TAGMASK);
- compemu_raw_jmp_m_indexed(uae_p32(cache_tags), r, SIZEOF_VOID_P);
+ compemu_raw_jmp_m_indexed(uae_p32(cache_tags), r, sizeof(void *));
/* now the exit points */
align_target(align_jumps);
//bi->env=empty_ss;
}
+#ifdef UAE
void compemu_reset(void)
{
set_cache_state(0);
}
+#endif
#ifdef UAE
#else
}
if (*p == 0 || *p == ',') {
- jit_log("blacklist opcodes : %04x-%04x", opcode1, opcode2);
+ jit_log("<JIT compiler> : blacklist opcodes : %04x-%04x", opcode1, opcode2);
for (int opcode = opcode1; opcode <= opcode2; opcode++)
reset_compop(cft_map(opcode));
const struct comptbl* tbl=op_smalltbl_0_comp_ff;
const struct comptbl* nftbl=op_smalltbl_0_comp_nf;
int count;
+#ifdef WINUAE_ARANYM
+ unsigned int cpu_level = 4; // 68040
+ const struct cputbl *nfctbl = op_smalltbl_0_nf;
+#else
#ifdef NOFLAGS_SUPPORT
struct comptbl *nfctbl = (currprefs.cpu_level >= 5 ? op_smalltbl_0_nf
: currprefs.cpu_level == 4 ? op_smalltbl_1_nf
: ! currprefs.cpu_compatible ? op_smalltbl_4_nf
: op_smalltbl_5_nf);
#endif
+#endif
+ // Initialize target CPU (check for features, e.g. CMOV, rat stalls)
raw_init_cpu();
#ifdef NATMEM_OFFSET
#ifdef JIT_EXCEPTION_HANDLER
install_exception_handler();
#endif
-#else
- signal(SIGSEGV, (sighandler_t)segfault_vec);
- D(bug("<JIT compiler> : NATMEM OFFSET handler installed"));
#endif
#endif
- jit_log("Building compiler function tables");
+ jit_log("<JIT compiler> : building compiler function tables");
for (opcode = 0; opcode < 65536; opcode++) {
reset_compop(opcode);
#ifdef NOFLAGS_SUPPORT
nfcpufunctbl[opcode] = op_illg;
#endif
- prop[opcode].use_flags = 0x1f;
- prop[opcode].set_flags = 0x1f;
+ prop[opcode].use_flags = FLAG_ALL;
+ prop[opcode].set_flags = FLAG_ALL;
+#ifdef UAE
prop[opcode].is_jump=1;
+#else
+ prop[opcode].cflow = fl_trap; // ILLEGAL instructions do trap
+#endif
}
for (i = 0; tbl[i].opcode < 65536; i++) {
+#ifdef UAE
int isjmp = (tbl[i].specific & COMP_OPCODE_ISJUMP);
int isaddx = (tbl[i].specific & COMP_OPCODE_ISADDX);
int iscjmp = (tbl[i].specific & COMP_OPCODE_ISCJUMP);
prop[cft_map(tbl[i].opcode)].is_jump = isjmp;
prop[cft_map(tbl[i].opcode)].is_const_jump = iscjmp;
prop[cft_map(tbl[i].opcode)].is_addx = isaddx;
+#else
+ int cflow = table68k[tbl[i].opcode].cflow;
+ if (follow_const_jumps && (tbl[i].specific & COMP_OPCODE_ISCJUMP))
+ cflow = fl_const_jump;
+ else
+ cflow &= ~fl_const_jump;
+ prop[cft_map(tbl[i].opcode)].cflow = cflow;
+#endif
bool uses_fpu = (tbl[i].specific & COMP_OPCODE_USES_FPU) != 0;
if (uses_fpu && avoid_fpu)
}
for (i = 0; nftbl[i].opcode < 65536; i++) {
- nfcompfunctbl[cft_map(nftbl[i].opcode)] = nftbl[i].handler;
+ bool uses_fpu = (tbl[i].specific & COMP_OPCODE_USES_FPU) != 0;
+ if (uses_fpu && avoid_fpu)
+ nfcompfunctbl[cft_map(nftbl[i].opcode)] = NULL;
+ else
+ nfcompfunctbl[cft_map(nftbl[i].opcode)] = nftbl[i].handler;
#ifdef NOFLAGS_SUPPORT
nfcpufunctbl[cft_map(nftbl[i].opcode)] = nfctbl[i].handler;
#endif
#ifdef NOFLAGS_SUPPORT
cpuop_func *nfcf;
#endif
- int isjmp,isaddx,iscjmp;
+ int isaddx;
+#ifdef UAE
+ int isjmp,iscjmp;
+#else
+ int cflow;
+#endif
+#ifdef UAE
int cpu_level = (currprefs.cpu_model - 68000) / 10;
if (cpu_level > 4)
cpu_level--;
+#endif
if ((instrmnem)table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level)
continue;
#ifdef NOFLAGS_SUPPORT
nfcf = nfcpufunctbl[cft_map(table68k[opcode].handler)];
#endif
+ isaddx = prop[cft_map(table68k[opcode].handler)].is_addx;
+ prop[cft_map(opcode)].is_addx = isaddx;
+#ifdef UAE
isjmp = prop[cft_map(table68k[opcode].handler)].is_jump;
iscjmp = prop[cft_map(table68k[opcode].handler)].is_const_jump;
- isaddx = prop[cft_map(table68k[opcode].handler)].is_addx;
prop[cft_map(opcode)].is_jump = isjmp;
prop[cft_map(opcode)].is_const_jump = iscjmp;
- prop[cft_map(opcode)].is_addx = isaddx;
+#else
+ cflow = prop[cft_map(table68k[opcode].handler)].cflow;
+ prop[cft_map(opcode)].cflow = cflow;
+#endif
compfunctbl[cft_map(opcode)] = f;
nfcompfunctbl[cft_map(opcode)] = nff;
#ifdef NOFLAGS_SUPPORT
prop[cft_map(opcode)].use_flags = table68k[opcode].flaglive;
/* Unconditional jumps don't evaluate condition codes, so they
* don't actually use any flags themselves */
+#ifdef UAE
if (prop[cft_map(opcode)].is_const_jump)
+#else
+ if (prop[cft_map(opcode)].cflow & fl_const_jump)
+#endif
prop[cft_map(opcode)].use_flags = 0;
}
#ifdef NOFLAGS_SUPPORT
/* Merge in blacklist */
if (!merge_blacklist())
- jit_log("blacklist merge failure!");
-
+ {
+ jit_log("<JIT compiler> : blacklist merge failure!");
+ }
+
count=0;
for (opcode = 0; opcode < 65536; opcode++) {
if (compfunctbl[cft_map(opcode)])
count++;
}
- jit_log("Supposedly %d compileable opcodes!",count);
+ jit_log("<JIT compiler> : supposedly %d compileable opcodes!",count);
/* Initialise state */
create_popalls();
cache_tags[i].handler=(cpuop_func*)popall_execute_normal;
cache_tags[i+1].bi=NULL;
}
+#ifdef UAE
compemu_reset();
+#endif
#if 0
for (i=0;i<N_REGS;i++) {
{
blockinfo* bi, *dbi;
- hard_flush_count++;
-#if 0
- write_log (_T("JIT: Flush Icache_hard(%d/%x/%p), %u instruction bytes\n"),
- n,regs.pc,regs.pc_p,current_compile_p-compiled_code);
+#ifndef UAE
+ jit_log("JIT: Flush Icache_hard(%d/%x/%p), %u KB",
+ n,regs.pc,regs.pc_p,current_cache_size/1024);
#endif
+ UNUSED(n);
bi=active;
while(bi) {
cache_tags[cacheline(bi->pc_p)].handler=(cpuop_func*)popall_execute_normal;
reset_lists();
if (!compiled_code)
return;
+
+#if defined(USE_DATA_BUFFER)
+ reset_data_buffer();
+#endif
+
current_compile_p=compiled_code;
+#ifdef UAE
set_special(0); /* To get out of compiled code */
+#else
+ SPCFLAGS_SET( SPCFLAG_JIT_EXEC_RETURN ); /* To get out of compiled code */
+#endif
}
we simply mark everything as "needs to be checked".
*/
+#ifdef WINUAE_ARANYM
+static inline void flush_icache_lazy(int)
+#else
void flush_icache(int n)
+#endif
{
blockinfo* bi;
blockinfo* bi2;
+#ifdef UAE
if (currprefs.comp_hardflush) {
flush_icache_hard(n);
return;
}
- soft_flush_count++;
+#endif
if (!active)
return;
int failure;
-#define TARGET_M68K 0
-#define TARGET_POWERPC 1
-#define TARGET_X86 2
-#define TARGET_X86_64 3
-#define TARGET_ARM 4
-#if defined(CPU_i386)
-#define TARGET_NATIVE TARGET_X86
-#endif
-#if defined(CPU_powerpc)
-#define TARGET_NATIVE TARGET_POWERPC
-#endif
-#if defined(CPU_x86_64)
-#define TARGET_NATIVE TARGET_X86_64
-#endif
-#if defined(CPU_arm)
-#define TARGET_NATIVE TARGET_ARM
-#endif
-
-#ifdef UAE
-static
-#endif
-void disasm_block(int /* target */, uint8 * /* start */, size_t /* length */)
-{
- if (!JITDebug)
- return;
-}
-
-static inline void disasm_native_block(uint8 *start, size_t length)
-{
- disasm_block(TARGET_NATIVE, start, length);
-}
-
-static inline void disasm_m68k_block(uint8 *start, size_t length)
-{
- disasm_block(TARGET_M68K, start, length);
-}
-
#ifdef UAE
static inline unsigned int get_opcode_cft_map(unsigned int f)
{
if (!JITDebug)
return;
- bug("### Host addresses");
- bug("MEM_BASE : %x", MEMBaseDiff);
- bug("PC_P : %p", ®s.pc_p);
- bug("SPCFLAGS : %p", ®s.spcflags);
- bug("D0-D7 : %p-%p", ®s.regs[0], ®s.regs[7]);
- bug("A0-A7 : %p-%p", ®s.regs[8], ®s.regs[15]);
- bug("");
+ jit_log("### Host addresses");
+ jit_log("MEM_BASE : %lx", (unsigned long)MEMBaseDiff);
+ jit_log("PC_P : %p", ®s.pc_p);
+ jit_log("SPCFLAGS : %p", ®s.spcflags);
+ jit_log("D0-D7 : %p-%p", ®s.regs[0], ®s.regs[7]);
+ jit_log("A0-A7 : %p-%p", ®s.regs[8], ®s.regs[15]);
+ jit_log(" ");
- bug("### M68k processor state");
+ jit_log("### M68k processor state");
+#ifdef UAE
+ m68k_dumpstate(NULL);
+#else
m68k_dumpstate(stderr, 0);
- bug("");
+#endif
+ jit_log(" ");
- bug("### Block in Atari address space");
- bug("M68K block : %p",
+ jit_log("### Block in Atari address space");
+ jit_log("M68K block : %p",
(void *)(uintptr)last_regs_pc_p);
if (last_regs_pc_p != 0) {
- bug("Native block : %p (%d bytes)",
+ jit_log("Native block : %p (%d bytes)",
(void *)last_compiled_block_addr,
get_blockinfo_addr(last_regs_pc_p)->direct_handler_size);
}
- bug("");
+ jit_log(" ");
}
#endif
#ifdef UAE
void compile_block(cpu_history *pc_hist, int blocklen, int totcycles)
{
- if (letit && compiled_code && currprefs.cpu_model >= 68020) {
+ if (cache_enabled && compiled_code && currprefs.cpu_model >= 68020) {
#else
static void compile_block(cpu_history* pc_hist, int blocklen)
{
- if (letit && compiled_code) {
+ if (cache_enabled && compiled_code) {
#endif
#ifdef PROFILE_COMPILE_TIME
compile_count++;
redo_current_block=0;
if (current_compile_p >= MAX_COMPILE_PTR)
- flush_icache_hard(3);
+ flush_icache_hard(7);
alloc_blockinfos();
if (bi->status!=BI_INVALID) {
Dif (bi!=bi2) {
/* I don't think it can happen anymore. Shouldn't, in
- any case. So let's make sure... */
+ any case. So let's make sure... */
jit_abort("WOOOWOO count=%d, ol=%d %p %p", bi->count,bi->optlevel,bi->handler_to_use, cache_tags[cl].handler);
}
bi->csi = NULL;
#endif
- liveflags[blocklen]=0x1f; /* All flags needed afterwards */
+ liveflags[blocklen]=FLAG_ALL; /* All flags needed afterwards */
i=blocklen;
while (i--) {
uae_u16* currpcp=pc_hist[i].location;
#endif
#ifdef UAE
- if (currprefs.compnf) {
+ if (!currprefs.compnf) {
+ liveflags[i]=FLAG_ALL;
+ }
+ else
#endif
- liveflags[i]=((liveflags[i+1]&
- (~prop[op].set_flags))|
- prop[op].use_flags);
+ {
+ liveflags[i] = ((liveflags[i+1] & (~prop[op].set_flags))|prop[op].use_flags);
if (prop[op].is_addx && (liveflags[i+1]&FLAG_Z)==0)
liveflags[i]&= ~FLAG_Z;
-#ifdef UAE
}
- else {
- liveflags[i]=0x1f;
- }
-#endif
}
#if USE_CHECKSUM_INFO
compemu_raw_mov_l_mi((uintptr)&last_compiled_block_addr,current_block_start_target);
}
#endif
-
- for (i=0;i<blocklen &&
- get_target_noopt() < MAX_COMPILE_PTR;i++) {
- cpuop_func **cputbl;
- compop_func **comptbl;
- uae_u32 opcode=DO_GET_OPCODE(pc_hist[i].location);
- needed_flags=(liveflags[i+1] & prop[opcode].set_flags);
+
+ for (i=0;i<blocklen && get_target_noopt() < MAX_COMPILE_PTR;i++) {
+ cpuop_func **cputbl;
+ compop_func **comptbl;
+ uae_u32 opcode=DO_GET_OPCODE(pc_hist[i].location);
+ needed_flags=(liveflags[i+1] & prop[opcode].set_flags);
#ifdef UAE
- special_mem=pc_hist[i].specmem;
- if (!needed_flags && currprefs.compnf) {
+ special_mem=pc_hist[i].specmem;
+ if (!needed_flags && currprefs.compnf)
#else
- if (!needed_flags) {
+ if (!needed_flags)
#endif
+ {
#ifdef NOFLAGS_SUPPORT
- cputbl=nfcpufunctbl;
+ cputbl=nfcpufunctbl;
#else
- cputbl=cpufunctbl;
+ cputbl=cpufunctbl;
#endif
- comptbl=nfcompfunctbl;
- }
- else {
- cputbl=cpufunctbl;
- comptbl=compfunctbl;
- }
+ comptbl=nfcompfunctbl;
+ }
+ else {
+ cputbl=cpufunctbl;
+ comptbl=compfunctbl;
+ }
#ifdef FLIGHT_RECORDER
- {
- mov_l_ri(S1, ((uintptr)(pc_hist[i].location)) | 1);
- /* store also opcode to second register */
- clobber_flags();
- remove_all_offsets();
- int arg = readreg_specific(S1,4,REG_PAR1);
- prepare_for_call_1();
- unlock2(arg);
- prepare_for_call_2();
- raw_dec_sp(STACK_SHADOW_SPACE);
- compemu_raw_call((uintptr)m68k_record_step);
- raw_inc_sp(STACK_SHADOW_SPACE);
- }
+ {
+ /* store also opcode to second register */
+ clobber_flags();
+ remove_all_offsets();
+ prepare_for_call_1();
+ prepare_for_call_2();
+ raw_mov_l_ri(REG_PAR1, ((uintptr)(pc_hist[i].location)) - MEMBaseDiff);
+ raw_mov_w_ri(REG_PAR2, opcode);
+ raw_dec_sp(STACK_SHADOW_SPACE);
+ compemu_raw_call((uintptr)m68k_record_step);
+ raw_inc_sp(STACK_SHADOW_SPACE);
+ }
#endif
- failure = 1; // gb-- defaults to failure state
- if (comptbl[opcode] && optlev>1) {
- failure=0;
- if (!was_comp) {
- comp_pc_p=(uae_u8*)pc_hist[i].location;
- init_comp();
- }
- was_comp=1;
-
- comptbl[opcode](opcode);
- freescratch();
- if (!(liveflags[i+1] & FLAG_CZNV)) {
- /* We can forget about flags */
- dont_care_flags();
- }
+ failure = 1; // gb-- defaults to failure state
+ if (comptbl[opcode] && optlev>1) {
+ failure=0;
+ if (!was_comp) {
+ comp_pc_p=(uae_u8*)pc_hist[i].location;
+ init_comp();
+ }
+ was_comp=1;
+
+#ifdef WINUAE_ARANYM
+ bool isnop = do_get_mem_word(pc_hist[i].location) == 0x4e71 ||
+ ((i + 1) < blocklen && do_get_mem_word(pc_hist[i+1].location) == 0x4e71);
+
+ if (isnop)
+ compemu_raw_mov_l_mi((uintptr)®s.fault_pc, ((uintptr)(pc_hist[i].location)) - MEMBaseDiff);
+#endif
+
+ comptbl[opcode](opcode);
+ freescratch();
+ if (!(liveflags[i+1] & FLAG_CZNV)) {
+ /* We can forget about flags */
+ dont_care_flags();
+ }
#if INDIVIDUAL_INST
+ flush(1);
+ nop();
+ flush(1);
+ was_comp=0;
+#endif
+
+#ifdef WINUAE_ARANYM
+ /*
+ * workaround for buserror handling: on a "nop", write registers back
+ */
+ if (isnop)
+ {
flush(1);
nop();
- flush(1);
was_comp=0;
-#endif
}
+#endif
+ }
- if (failure) {
- if (was_comp) {
- flush(1);
- was_comp=0;
- }
- compemu_raw_mov_l_ri(REG_PAR1,(uae_u32)opcode);
+ if (failure) {
+ if (was_comp) {
+ flush(1);
+ was_comp=0;
+ }
+ compemu_raw_mov_l_ri(REG_PAR1,(uae_u32)opcode);
#if USE_NORMAL_CALLING_CONVENTION
- raw_push_l_r(REG_PAR1);
+ raw_push_l_r(REG_PAR1);
#endif
- compemu_raw_mov_l_mi((uintptr)®s.pc_p,
- (uintptr)pc_hist[i].location);
- raw_dec_sp(STACK_SHADOW_SPACE);
- compemu_raw_call((uintptr)cputbl[opcode]);
- raw_inc_sp(STACK_SHADOW_SPACE);
+ compemu_raw_mov_l_mi((uintptr)®s.pc_p,
+ (uintptr)pc_hist[i].location);
+ raw_dec_sp(STACK_SHADOW_SPACE);
+ compemu_raw_call((uintptr)cputbl[opcode]);
+ raw_inc_sp(STACK_SHADOW_SPACE);
#ifdef PROFILE_UNTRANSLATED_INSNS
- // raw_cputbl_count[] is indexed with plain opcode (in m68k order)
- compemu_raw_add_l_mi((uintptr)&raw_cputbl_count[cft_map(opcode)],1);
+ // raw_cputbl_count[] is indexed with plain opcode (in m68k order)
+ compemu_raw_add_l_mi((uintptr)&raw_cputbl_count[cft_map(opcode)],1);
#endif
#if USE_NORMAL_CALLING_CONVENTION
- raw_inc_sp(4);
+ raw_inc_sp(4);
#endif
- if (i<blocklen-1) {
- uae_s8* branchadd;
+ if (i < blocklen - 1) {
+ uae_s8* branchadd;
- compemu_raw_mov_l_rm(0,(uintptr)specflags);
- compemu_raw_test_l_rr(0,0);
+ /* if (SPCFLAGS_TEST(SPCFLAG_STOP)) popall_do_nothing() */
+ compemu_raw_mov_l_rm(0,(uintptr)specflags);
+ compemu_raw_test_l_rr(0,0);
#if defined(USE_DATA_BUFFER)
- data_check_end(8, 64); // just a pessimistic guess...
+ data_check_end(8, 64); // just a pessimistic guess...
#endif
- compemu_raw_jz_b_oponly();
- branchadd=(uae_s8*)get_target();
- skip_byte();
+ compemu_raw_jz_b_oponly();
+ branchadd=(uae_s8*)get_target();
+ skip_byte();
#ifdef UAE
- raw_sub_l_mi(uae_p32(&countdown),scaled_cycles(totcycles));
+ raw_sub_l_mi(uae_p32(&countdown),scaled_cycles(totcycles));
#endif
- compemu_raw_jmp((uintptr)popall_do_nothing);
- *branchadd=(uintptr)get_target()-(uintptr)branchadd-1;
- }
+ compemu_raw_jmp((uintptr)popall_do_nothing);
+ *branchadd=(uintptr)get_target()-(uintptr)branchadd-1;
}
+ }
}
#if 1 /* This isn't completely kosher yet; It really needs to be
- be integrated into a general inter-block-dependency scheme */
+ be integrated into a general inter-block-dependency scheme */
if (next_pc_p && taken_pc_p &&
- was_comp && taken_pc_p==current_block_pc_p) {
- blockinfo* bi1=get_blockinfo_addr_new((void*)next_pc_p,0);
- blockinfo* bi2=get_blockinfo_addr_new((void*)taken_pc_p,0);
- uae_u8 x=bi1->needed_flags;
-
- if (x==0xff || 1) { /* To be on the safe side */
- uae_u16* next=(uae_u16*)next_pc_p;
- uae_u32 op=DO_GET_OPCODE(next);
-
- x=0x1f;
- x&=(~prop[op].set_flags);
- x|=prop[op].use_flags;
- }
+ was_comp && taken_pc_p==current_block_pc_p)
+ {
+ blockinfo* bi1=get_blockinfo_addr_new((void*)next_pc_p,0);
+ blockinfo* bi2=get_blockinfo_addr_new((void*)taken_pc_p,0);
+ uae_u8 x=bi1->needed_flags;
- x|=bi2->needed_flags;
- if (!(x & FLAG_CZNV)) {
- /* We can forget about flags */
- dont_care_flags();
- extra_len+=2; /* The next instruction now is part of this
- block */
- }
+ if (x==0xff || 1) { /* To be on the safe side */
+ uae_u16* next=(uae_u16*)next_pc_p;
+ uae_u32 op=DO_GET_OPCODE(next);
+
+ x=FLAG_ALL;
+ x&=(~prop[op].set_flags);
+ x|=prop[op].use_flags;
+ }
+ x|=bi2->needed_flags;
+ if (!(x & FLAG_CZNV)) {
+ /* We can forget about flags */
+ dont_care_flags();
+ extra_len+=2; /* The next instruction now is part of this block */
+ }
}
#endif
log_flush();
if (taken_pc_p<next_pc_p) {
/* backward branch. Optimize for the "taken" case ---
- which means the raw_jcc should fall through when
- the 68k branch is taken. */
+ which means the raw_jcc should fall through when
+ the 68k branch is taken. */
t1=taken_pc_p;
t2=next_pc_p;
cc=branch_cc^1;
compemu_raw_jcc_l_oponly(cc);
branchadd=(uae_u32*)get_target();
skip_long();
-
+
/* predicted outcome */
tbi=get_blockinfo_addr_new((void*)t1,1);
match_states(tbi);
#ifdef UAE
raw_sub_l_mi(uae_p32(&countdown),scaled_cycles(totcycles));
- raw_jcc_l_oponly(9);
+ raw_jcc_l_oponly(NATIVE_CC_PL);
#else
compemu_raw_cmp_l_mi8((uintptr)specflags,0);
compemu_raw_jcc_l_oponly(NATIVE_CC_EQ);
//flush(1); /* Can only get here if was_comp==1 */
#ifdef UAE
raw_sub_l_mi(uae_p32(&countdown),scaled_cycles(totcycles));
- raw_jcc_l_oponly(9);
+ raw_jcc_l_oponly(NATIVE_CC_PL);
#else
compemu_raw_cmp_l_mi8((uintptr)specflags,0);
compemu_raw_jcc_l_oponly(NATIVE_CC_EQ);
compemu_raw_mov_l_ri(r2,(uintptr)popall_do_nothing);
#ifdef UAE
raw_sub_l_mi(uae_p32(&countdown),scaled_cycles(totcycles));
- raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,SIZEOF_VOID_P,9);
+ raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,sizeof(void *),NATIVE_CC_PL);
#else
compemu_raw_cmp_l_mi8((uintptr)specflags,0);
- compemu_raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,SIZEOF_VOID_P,NATIVE_CC_EQ);
+ compemu_raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,sizeof(void *),NATIVE_CC_EQ);
#endif
compemu_raw_jmp_r(r2);
}
#ifdef UAE
raw_sub_l_mi(uae_p32(&countdown),scaled_cycles(totcycles));
- raw_jcc_l_oponly(9);
+ raw_jcc_l_oponly(NATIVE_CC_PL);
#else
compemu_raw_cmp_l_mi8((uintptr)specflags,0);
compemu_raw_jcc_l_oponly(NATIVE_CC_EQ);
compemu_raw_mov_l_ri(r2,(uintptr)popall_do_nothing);
#ifdef UAE
raw_sub_l_mi(uae_p32(&countdown),scaled_cycles(totcycles));
- raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,SIZEOF_VOID_P,9);
+ raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,sizeof(void *),NATIVE_CC_PL);
#else
compemu_raw_cmp_l_mi8((uintptr)specflags,0);
- compemu_raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,SIZEOF_VOID_P,NATIVE_CC_EQ);
+ compemu_raw_cmov_l_rm_indexed(r2,(uintptr)cache_tags,r,sizeof(void *),NATIVE_CC_EQ);
#endif
compemu_raw_jmp_r(r2);
}
}
#if USE_MATCH
- if (callers_need_recompile(&live,&(bi->env))) {
- mark_callers_recompile(bi);
- }
+ if (callers_need_recompile(&live,&(bi->env))) {
+ mark_callers_recompile(bi);
+ }
- big_to_small_state(&live,&(bi->env));
+ big_to_small_state(&live,&(bi->env));
#endif
#if USE_CHECKSUM_INFO
remove_from_list(bi);
if (isinrom(min_pcp) && isinrom(max_pcp)) {
add_to_dormant(bi); /* No need to checksum it on cache flush.
- Please don't start changing ROMs in
- flight! */
+ Please don't start changing ROMs in
+ flight! */
}
else {
calc_checksum(bi,&(bi->c1),&(bi->c2));
current_cache_size += get_target() - (uae_u8 *)current_compile_p;
#ifdef JIT_DEBUG
- if (JITDebug)
- bi->direct_handler_size = get_target() - (uae_u8 *)current_block_start_target;
+ bi->direct_handler_size = get_target() - (uae_u8 *)current_block_start_target;
if (JITDebug && disasm_block) {
uaecptr block_addr = start_pc + ((char *)pc_hist[0].location - (char *)start_pc_p);
- D(bug("M68K block @ 0x%08x (%d insns)\n", block_addr, blocklen));
+ jit_log("M68K block @ 0x%08x (%d insns)", block_addr, blocklen);
uae_u32 block_size = ((uae_u8 *)pc_hist[blocklen - 1].location - (uae_u8 *)pc_hist[0].location) + 1;
- disasm_m68k_block((uae_u8 *)pc_hist[0].location, block_size);
- D(bug("Compiled block @ 0x%08x\n", pc_hist[0].location));
- disasm_native_block((uae_u8 *)current_block_start_target, bi->direct_handler_size);
- getchar();
+#ifdef WINUAE_ARANYM
+ disasm_m68k_block((const uae_u8 *)pc_hist[0].location, block_size);
+#endif
+ jit_log("Compiled block @ %p", pc_hist[0].location);
+#ifdef WINUAE_ARANYM
+ disasm_native_block((const uae_u8 *)current_block_start_target, bi->direct_handler_size);
+#endif
+ UNUSED(block_addr);
}
#endif
flush_cpu_icache((void *)current_block_start_target, (void *)target);
current_compile_p=get_target();
raise_in_cl_list(bi);
+#ifdef UAE
bi->nexthandler=current_compile_p;
+#endif
/* We will flush soon, anyway, so let's do it now */
if (current_compile_p >= MAX_COMPILE_PTR)
- flush_icache_hard(3);
+ flush_icache_hard(7);
bi->status=BI_ACTIVE;
if (redo_current_block)
#ifdef UAE
/* Account for compilation time */
do_extra_cycles(totcycles);
- }
-#else
- }
-
- /* Account for compilation time */
- cpu_do_check_ticks();
#endif
+ }
}
#ifdef UAE
#else
void do_nothing(void)
{
- /* What did you expect this to do? */
+ /* What did you expect this to do? */
}
#endif
start_pc_p = regs.pc_p;
start_pc = get_virtual_address(regs.pc_p);
#else
- start_pc_p = regs.pc_oldp;
+ start_pc_p = regs.pc_oldp;
start_pc = regs.pc;
#endif
for (;;) { /* Take note: This is the do-it-normal loop */
}
}
CATCH(prb) {
+ jit_log("m68k_compile_execute: exception %d pc=%08x (%08x+%p-%p) fault_pc=%08x addr=%08x -> %08x sp=%08x",
+ int(prb),
+ m68k_getpc(),
+ regs.pc, regs.pc_p, regs.pc_oldp,
+ regs.fault_pc,
+ regs.mmu_fault_addr, get_long (regs.vbr + 4*prb),
+ regs.regs[15]);
flush_icache(0);
Exception(prb, 0);
goto setjmpagain;
write_log(_T("JIT: Create jump to %p\n"), veccode);
write_log(_T("JIT: Handled one access!\n"));
#endif
- segvcount++;
target = veccode;
if (dir == SIG_READ) {
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifdef UAE
-#include "sysconfig.h"
-#else
#define CC_FOR_BUILD 1
-#endif
+#include "sysconfig.h"
#include "sysdeps.h"
#include "readcpu.h"
+#undef NDEBUG
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define JIT_PATH "jit/"
#define GEN_PATH "jit/"
#define RETURN "return 0;"
+#define RETTYPE "uae_u32"
+#define NEXT_CPU_LEVEL 5
#else
#define JIT_PATH "compiler/"
#define GEN_PATH ""
#define RETURN "return;"
+#define RETTYPE "void"
+#define NEXT_CPU_LEVEL 4
+#define ua(s) s
#endif
-#define BOOL_TYPE "int"
-#define failure global_failure=1
-#define FAILURE global_failure=1
-#define isjump global_isjump=1
-#define is_const_jump global_iscjump=1;
-#define isaddx global_isaddx=1
-#define uses_cmov global_cmov=1
-#define mayfail global_mayfail=1
+#define BOOL_TYPE "int"
+#define failure global_failure=1
+#define FAILURE global_failure=1
+#define isjump global_isjump=1
+#define is_const_jump global_iscjump=1;
+#define isaddx global_isaddx=1
+#define uses_cmov global_cmov=1
+#define mayfail global_mayfail=1
#define uses_fpu global_fpu=1
int hack_opcode;
if (file)
{
if (fscanf (file, "Total: %lu\n", &total) != 1) {
- abort();
+ assert(0);
}
while (fscanf (file, "%lx: %lu %s\n", &opcode, &count, name) == 3)
{
- opcode_next_clev[nr] = 5;
+ opcode_next_clev[nr] = NEXT_CPU_LEVEL;
opcode_last_postfix[nr] = -1;
opcode_map[nr++] = opcode;
counts[opcode] = count;
if (table68k[opcode].handler == -1 && table68k[opcode].mnemo != i_ILLG
&& counts[opcode] == 0)
{
- opcode_next_clev[nr] = 5;
+ opcode_next_clev[nr] = NEXT_CPU_LEVEL;
opcode_last_postfix[nr] = -1;
opcode_map[nr++] = opcode;
counts[opcode] = count;
}
}
- if (nr != nr_cpuop_funcs)
- abort ();
+ assert (nr == nr_cpuop_funcs);
}
static int n_braces = 0;
switch (mode)
{
case Dreg: /* Do we need to check dodgy here? */
- if (movem)
- abort ();
+ assert (!movem);
if (getv == 1 || getv==2) {
/* We generate the variable even for getv==2, so we can use
it as a destination for MOVE */
return;
case Areg:
- if (movem)
- abort ();
+ assert (!movem);
if (getv == 1 || getv==2) {
/* see above */
comprintf ("\tint %s=dodgy?scratchie++:%s+8;\n",name,reg);
}
break;
default:
- abort ();
+ assert(0);
}
break;
case Ad16:
comprintf ("\tmov_l_ri(%sa,%s); /* absl */\n", name, gen_nextilong ());
break;
case imm:
- if (getv != 1)
- abort ();
+ assert (getv == 1);
switch (size)
{
case sz_byte:
comprintf ("\tmov_l_ri(%s,%s);\n", name, gen_nextilong ());
break;
default:
- abort ();
+ assert(0);
}
return;
case imm0:
- if (getv != 1)
- abort ();
+ assert (getv == 1);
comprintf ("\tint %s = scratchie++;\n",name);
comprintf ("\tmov_l_ri(%s,(uae_s32)(uae_s8)%s);\n", name, gen_nextibyte ());
return;
case imm1:
- if (getv != 1)
- abort ();
+ assert (getv == 1);
comprintf ("\tint %s = scratchie++;\n",name);
comprintf ("\tmov_l_ri(%s,(uae_s32)(uae_s16)%s);\n", name, gen_nextiword ());
return;
case imm2:
- if (getv != 1)
- abort ();
+ assert (getv == 1);
comprintf ("\tint %s = scratchie++;\n",name);
comprintf ("\tmov_l_ri(%s,%s);\n", name, gen_nextilong ());
return;
case immi:
- if (getv != 1)
- abort ();
+ assert (getv == 1);
comprintf ("\tint %s = scratchie++;\n",name);
comprintf ("\tmov_l_ri(%s,%s);\n", name, reg);
return;
default:
- abort ();
+ assert(0);
}
/* We get here for all non-reg non-immediate addressing modes to
insn_n_cycles += 4;
break;
default:
- abort ();
+ assert(0);
}
start_brace ();
comprintf("\tint %s=scratchie++;\n",name);
gen_readlong(astring,name);
break;
default:
- abort ();
+ assert(0);
}
}
comprintf("\tlea_l_brr(%s+8,%s+8,4);\n",reg,reg);
break;
default:
- abort ();
+ assert(0);
}
break;
case Apdi:
comprintf ("\t\tmov_l_rr(%s,%s);\n", reg, from);
break;
default:
- abort ();
+ assert(0);
}
break;
case Areg:
comprintf ("\t\tmov_l_rr(%s+8,%s);\n", reg, from);
break;
default:
- abort ();
+ assert(0);
}
break;
gen_writelong(astring,from);
break;
default:
- abort ();
+ assert(0);
}
}
break;
case imm1:
case imm2:
case immi:
- abort ();
+ assert(0);
break;
default:
- abort ();
+ assert(0);
}
}
static void genmov16(uae_u32 opcode, struct instr *curi)
{
- comprintf("\tint src=scratchie++;\n");
- comprintf("\tint dst=scratchie++;\n");
+ comprintf("\tint src=scratchie++;\n");
+ comprintf("\tint dst=scratchie++;\n");
- if ((opcode & 0xfff8) == 0xf620) {
- /* MOVE16 (Ax)+,(Ay)+ */
- comprintf("\tuae_u16 dstreg=((%s)>>12)&0x07;\n", gen_nextiword());
- comprintf("\tmov_l_rr(src,8+srcreg);\n");
- comprintf("\tmov_l_rr(dst,8+dstreg);\n");
+ if ((opcode & 0xfff8) == 0xf620) {
+ /* MOVE16 (Ax)+,(Ay)+ */
+ comprintf("\tuae_u16 dstreg=((%s)>>12)&0x07;\n", gen_nextiword());
+ comprintf("\tmov_l_rr(src,8+srcreg);\n");
+ comprintf("\tmov_l_rr(dst,8+dstreg);\n");
}
else {
- /* Other variants */
- genamode (curi->smode, "srcreg", curi->size, "src", 0, 2);
- genamode (curi->dmode, "dstreg", curi->size, "dst", 0, 2);
- comprintf("\tmov_l_rr(src,srca);\n");
- comprintf("\tmov_l_rr(dst,dsta);\n");
- }
+ /* Other variants */
+ genamode (curi->smode, "srcreg", curi->size, "src", 0, 2);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 0, 2);
+ comprintf("\tmov_l_rr(src,srca);\n");
+ comprintf("\tmov_l_rr(dst,dsta);\n");
+ }
- /* Align on 16-byte boundaries */
- comprintf("\tand_l_ri(src,~15);\n");
- comprintf("\tand_l_ri(dst,~15);\n");
+ /* Align on 16-byte boundaries */
+ comprintf("\tand_l_ri(src,~15);\n");
+ comprintf("\tand_l_ri(dst,~15);\n");
- if ((opcode & 0xfff8) == 0xf620) {
- comprintf("\tif (srcreg != dstreg)\n");
- comprintf("\tadd_l_ri(srcreg+8,16);\n");
- comprintf("\tadd_l_ri(dstreg+8,16);\n");
- }
- else if ((opcode & 0xfff8) == 0xf600)
- comprintf("\tadd_l_ri(srcreg+8,16);\n");
- else if ((opcode & 0xfff8) == 0xf608)
- comprintf("\tadd_l_ri(dstreg+8,16);\n");
-
- comprintf("\tif (special_mem) {\n");
- comprintf("\t\tint tmp=scratchie;\n");
- comprintf("\tscratchie+=4;\n"
- "\treadlong(src,tmp,scratchie);\n"
- "\twritelong_clobber(dst,tmp,scratchie);\n"
- "\tadd_l_ri(src,4);\n"
- "\tadd_l_ri(dst,4);\n"
- "\treadlong(src,tmp,scratchie);\n"
- "\twritelong_clobber(dst,tmp,scratchie);\n"
- "\tadd_l_ri(src,4);\n"
- "\tadd_l_ri(dst,4);\n"
- "\treadlong(src,tmp,scratchie);\n"
- "\twritelong_clobber(dst,tmp,scratchie);\n"
- "\tadd_l_ri(src,4);\n"
- "\tadd_l_ri(dst,4);\n"
- "\treadlong(src,tmp,scratchie);\n"
- "\twritelong_clobber(dst,tmp,scratchie);\n");
- comprintf("\t} else {\n");
- comprintf("\tint tmp=scratchie;\n");
- comprintf("\tscratchie+=4;\n");
-
- comprintf("\tget_n_addr(src,src,scratchie);\n"
- "\tget_n_addr(dst,dst,scratchie);\n"
- "\tmov_l_rR(tmp+0,src,0);\n"
- "\tmov_l_rR(tmp+1,src,4);\n"
- "\tmov_l_rR(tmp+2,src,8);\n"
- "\tmov_l_rR(tmp+3,src,12);\n"
- "\tmov_l_Rr(dst,tmp+0,0);\n"
- "\tforget_about(tmp+0);\n"
- "\tmov_l_Rr(dst,tmp+1,4);\n"
- "\tforget_about(tmp+1);\n"
- "\tmov_l_Rr(dst,tmp+2,8);\n"
- "\tforget_about(tmp+2);\n"
- "\tmov_l_Rr(dst,tmp+3,12);\n");
+ if ((opcode & 0xfff8) == 0xf620) {
+ comprintf("\tif (srcreg != dstreg)\n");
+ comprintf("\tadd_l_ri(srcreg+8,16);\n");
+ comprintf("\tadd_l_ri(dstreg+8,16);\n");
+ }
+ else if ((opcode & 0xfff8) == 0xf600)
+ comprintf("\tadd_l_ri(srcreg+8,16);\n");
+ else if ((opcode & 0xfff8) == 0xf608)
+ comprintf("\tadd_l_ri(dstreg+8,16);\n");
+
+#ifdef UAE
+ comprintf("\tif (special_mem) {\n");
+ comprintf("\t\tint tmp=scratchie;\n");
+ comprintf("\tscratchie+=4;\n"
+ "\treadlong(src,tmp,scratchie);\n"
+ "\twritelong_clobber(dst,tmp,scratchie);\n"
+ "\tadd_l_ri(src,4);\n"
+ "\tadd_l_ri(dst,4);\n"
+ "\treadlong(src,tmp,scratchie);\n"
+ "\twritelong_clobber(dst,tmp,scratchie);\n"
+ "\tadd_l_ri(src,4);\n"
+ "\tadd_l_ri(dst,4);\n"
+ "\treadlong(src,tmp,scratchie);\n"
+ "\twritelong_clobber(dst,tmp,scratchie);\n"
+ "\tadd_l_ri(src,4);\n"
+ "\tadd_l_ri(dst,4);\n"
+ "\treadlong(src,tmp,scratchie);\n"
+ "\twritelong_clobber(dst,tmp,scratchie);\n");
+ comprintf("\t} else {\n");
+#endif
+ comprintf("\tint tmp=scratchie;\n");
+ comprintf("\tscratchie+=4;\n"
+ "\tget_n_addr(src,src,scratchie);\n"
+ "\tget_n_addr(dst,dst,scratchie);\n"
+ "\tmov_l_rR(tmp+0,src,0);\n"
+ "\tmov_l_rR(tmp+1,src,4);\n"
+ "\tmov_l_rR(tmp+2,src,8);\n"
+ "\tmov_l_rR(tmp+3,src,12);\n"
+ "\tmov_l_Rr(dst,tmp+0,0);\n"
+ "\tforget_about(tmp+0);\n"
+ "\tmov_l_Rr(dst,tmp+1,4);\n"
+ "\tforget_about(tmp+1);\n"
+ "\tmov_l_Rr(dst,tmp+2,8);\n"
+ "\tforget_about(tmp+2);\n"
+ "\tmov_l_Rr(dst,tmp+3,12);\n");
+#ifdef UAE
comprintf("\t}\n");
+#endif
}
static void
comprintf ("\tint i;\n");
comprintf ("\tsigned char offset=0;\n");
genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
+#ifdef UAE
if (table68k[opcode].size == sz_long)
comprintf("\tif (1 && !special_mem) {\n");
else
comprintf("\tif (1 && !special_mem) {\n");
+#endif
/* Fast but unsafe... */
comprintf("\tget_n_addr(srca,native,scratchie);\n");
"\t\t\tsign_extend_16_rr(i,i);\n"
"\t\t\toffset+=2;\n");
break;
- default: abort();
+ default: assert(0);
}
comprintf("\t\t}\n"
"\t}");
}
/* End fast but unsafe. */
+#ifdef UAE
comprintf("\t} else {\n");
comprintf ("\t\tint tmp=scratchie++;\n");
comprintf("\t\t\t\treadword(tmp,i,scratchie);\n"
"\t\t\t\tadd_l_ri(tmp,2);\n");
break;
- default: abort();
+ default: assert(0);
}
comprintf("\t\t\t}\n"
comprintf("\t\tmov_l_rr(8+dstreg,tmp);\n");
}
comprintf("\t}\n");
+#endif
}
comprintf ("\tsigned char offset=0;\n");
genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
+#ifdef UAE
/* *Sigh* Some clever geek realized that the fastest way to copy a
buffer from main memory to the gfx card is by using movmle. Good
on her, but unfortunately, gfx mem isn't "real" mem, and thus that
comprintf("\tif (1 && !special_mem) {\n");
else
comprintf("\tif (1 && !special_mem) {\n");
+#endif
comprintf("\tget_n_addr(srca,native,scratchie);\n");
if (table68k[opcode].dmode!=Apdi) {
"\t\t\tmov_w_Rr(native,tmp,offset);\n"
"\t\t\toffset+=2;\n");
break;
- default: abort();
+ default: assert(0);
}
}
else { /* Pre-decrement */
"\t\t\tmov_w_Rr(native,tmp,offset);\n"
);
break;
- default: abort();
+ default: assert(0);
}
}
if (table68k[opcode].dmode == Apdi) {
comprintf("\t\t\tlea_l_brr(8+dstreg,srca,(uae_s32)offset);\n");
}
+#ifdef UAE
comprintf("\t} else {\n");
if (table68k[opcode].dmode!=Apdi) {
comprintf("\t\t\twriteword(tmp,i,scratchie);\n"
"\t\t\tadd_l_ri(tmp,2);\n");
break;
- default: abort();
+ default: assert(0);
}
}
else { /* Pre-decrement */
comprintf("\t\t\tsub_l_ri(srca,2);\n"
"\t\t\twriteword(srca,15-i,scratchie);\n");
break;
- default: abort();
+ default: assert(0);
}
}
comprintf("\t\t\tmov_l_rr(8+dstreg,srca);\n");
}
comprintf("\t}\n");
+#endif
}
switch(type) {
case flag_add: op="add"; break;
case flag_sub: op="sub"; break;
- default: abort();
+ default: assert(0);
}
switch (size)
{
switch(type) {
case flag_or: op="or"; break;
case flag_eor: op="xor"; break;
- default: abort();
+ default: assert(0);
}
switch (size)
{
switch(type) {
case flag_addx: op="adc"; break;
case flag_subx: op="sbb"; break;
- default: abort();
+ default: assert(0);
}
comprintf("\trestore_carry();\n"); /* Reload the X flag into C */
switch (size)
case flag_and: op="and"; break;
case flag_or: op="or"; break;
case flag_eor: op="xor"; break;
- default: abort();
+ default: assert(0);
}
switch (size)
{
case flag_add: op="add"; break;
case flag_sub: op="sub"; break;
case flag_cmp: op="cmp"; break;
- default: abort();
+ default: assert(0);
}
switch (size)
{
switch(type) {
case flag_addx: op="adc"; break;
case flag_subx: op="sbb"; break;
- default: abort();
+ default: assert(0);
}
start_brace();
comprintf("\tint zero=scratchie++;\n"
case sz_byte: ssize="b"; break;
case sz_word: ssize="w"; break;
case sz_long: ssize="l"; break;
- default: abort();
+ default: assert(0);
}
(void)ssize;
switch (curi->mnemo)
{
-
case i_OR:
case i_AND:
case i_EOR:
case sz_byte: comprintf("\tsign_extend_8_rr(tmp,src);\n"); break;
case sz_word: comprintf("\tsign_extend_16_rr(tmp,src);\n"); break;
case sz_long: comprintf("\ttmp=src;\n"); break;
- default: abort();
+ default: assert(0);
}
comprintf("\tsub_l(dst,tmp);\n");
genastore ("dst", curi->dmode, "dstreg", sz_long, "dst");
genflags (flag_add, curi->size, "", "src", "dst");
genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
break;
- case i_ADDA:
+ case i_ADDA:
#ifdef DISABLE_I_ADDA
failure;
#endif
case sz_byte: comprintf("\tsign_extend_8_rr(tmp,src);\n"); break;
case sz_word: comprintf("\tsign_extend_16_rr(tmp,src);\n"); break;
case sz_long: comprintf("\ttmp=src;\n"); break;
- default: abort();
+ default: assert(0);
}
comprintf("\tadd_l(dst,tmp);\n");
genastore ("dst", curi->dmode, "dstreg", sz_long, "dst");
case i_BCLR: op="btr"; break;
case i_BSET: op="bts"; break;
case i_BTST: op="bt"; need_write=0; break;
- default: abort();
+ default: assert(0);
}
comprintf("\t%s_l_rr(dst,s);\n" /* Answer now in C */
"\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */
case sz_byte: comprintf("\tsign_extend_8_rr(tmps,src);\n"); break;
case sz_word: comprintf("\tsign_extend_16_rr(tmps,src);\n"); break;
case sz_long: comprintf("tmps=src;\n"); break;
- default: abort();
+ default: assert(0);
}
genflags (flag_cmp, sz_long, "", "tmps", "dst");
break;
switch(curi->size) {
case sz_word: comprintf("\tsign_extend_16_rr(dst,src);\n"); break;
case sz_long: comprintf("\tmov_l_rr(dst,src);\n"); break;
- default: abort();
+ default: assert(0);
}
genastore ("dst", curi->dmode, "dstreg", sz_long, "dst");
break;
genastore ("tmp", curi->dmode, "dstreg", curi->size, "dst");
break;
-case i_EXT:
+ case i_EXT:
#ifdef DISABLE_I_EXT
failure;
#endif
"\tsign_extend_16_rr(src,src);\n");
break;
default:
- abort ();
+ assert(0);
}
genflags (flag_logical,
curi->size == sz_word ? sz_word : sz_long, "dst", "", "");
curi->size == sz_word ? sz_word : sz_long, "src");
break;
-case i_MVMEL:
+ case i_MVMEL:
#ifdef DISABLE_I_MVEL
failure;
#endif
genmovemle (opcode);
break;
-case i_TRAP:
+ case i_TRAP:
isjump;
failure;
break;
genastore ("src", curi->smode, "srcreg", curi->size, "src");
break;
-case i_RTS:
+ case i_RTS:
#ifdef DISABLE_I_RTS
failure;
#endif
case 14:
case 15:
break;
- default: abort();
+ default: assert(0);
}
break;
/* That offs is an immediate, so we can clobber it with abandon */
switch(curi->size) {
case sz_word: comprintf("\tsign_extend_16_rr(offs,offs);\n"); break;
- default: abort(); /* Seems this only comes in word flavour */
+ default: assert(0); /* Seems this only comes in word flavour */
}
comprintf("\tsub_l_ri(offs,m68k_pc_offset-m68k_pc_offset_thisinst-2);\n");
comprintf("\tadd_l_ri(offs,(uintptr)comp_pc_p);\n"); /* New PC,
comprintf("\tmake_flags_live();\n"); /* Load the flags */
}
- if (curi->size!=sz_word)
- abort();
-
+ assert (curi->size==sz_word);
switch(curi->cc) {
case 0: /* This is an elaborate nop? */
comprintf("\t end_needflags();\n");
comprintf("\tcmov_l_rr(PC_P,offs,%d);\n", NATIVE_CC_NE);
break;
- default: abort();
+ default: assert(0);
}
genastore ("src", curi->smode, "srcreg", curi->size, "src");
gen_update_next_handler();
/* All condition codes can be inverted by changing the LSB */
comprintf("\tsetcc(val,%d);\n",
cond_codes[curi->cc]^1); break;
- default: abort();
+ default: assert(0);
}
comprintf("\tsub_b_ri(val,1);\n");
genastore ("val", curi->smode, "srcreg", curi->size, "src");
break;
-case i_DIVU:
+ case i_DIVU:
isjump;
failure;
break;
failure;
break;
-case i_MULU:
+ case i_MULU:
#ifdef DISABLE_I_MULU
failure;
#endif
genastore ("dst", curi->dmode, "dstreg", sz_long, "dst");
break;
-case i_CHK:
+ case i_CHK:
isjump;
failure;
break;
"\thighmask=0x20;\n"
"\twidth=32;\n");
break;
- default: abort();
+ default: assert(0);
}
comprintf("test_l_ri(cnt,highmask);\n"
"mov_l_ri(highshift,0);\n"
case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break;
case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break;
case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break;
- default: abort();
+ default: assert(0);
}
/* And again */
switch(curi->size) {
case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break;
case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break;
case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break;
- default: abort();
+ default: assert(0);
}
/* Result of shift is now in data. Now we need to determine
case sz_byte: comprintf("\tshra_b_rr(cdata,tmpcnt);\n");break;
case sz_word: comprintf("\tshra_w_rr(cdata,tmpcnt);\n");break;
case sz_long: comprintf("\tshra_l_rr(cdata,tmpcnt);\n");break;
- default: abort();
+ default: assert(0);
}
/* If the shift count was higher than the width, we need
to pick up the sign from data */
"\thighmask=0x20;\n"
"\twidth=32;\n");
break;
- default: abort();
+ default: assert(0);
}
comprintf("test_l_ri(cnt,highmask);\n"
"mov_l_ri(highshift,0);\n"
case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break;
case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break;
case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break;
- default: abort();
+ default: assert(0);
}
/* And again */
switch(curi->size) {
case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break;
case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break;
case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break;
- default: abort();
+ default: assert(0);
}
genastore ("data", curi->dmode, "dstreg", curi->size, "data");
}
"\tbp=srcreg-1;\n"); break;
case sz_long: comprintf("\tshra_l_ri(data,srcreg);\n"
"\tbp=srcreg-1;\n"); break;
- default: abort();
+ default: assert(0);
}
if (!noflags) {
case sz_long: comprintf("\tshll_l_rr(data,cnt);\n"
"\thighmask=0x20;\n");
break;
- default: abort();
+ default: assert(0);
}
comprintf("test_l_ri(cnt,highmask);\n"
"mov_l_ri(scratchie,0);\n"
case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break;
case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break;
case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break;
- default: abort();
+ default: assert(0);
}
/* Result of shift is now in data. Now we need to determine
the carry by shifting cdata one less */
case sz_byte: comprintf("\tshll_b_rr(cdata,tmpcnt);\n");break;
case sz_word: comprintf("\tshll_w_rr(cdata,tmpcnt);\n");break;
case sz_long: comprintf("\tshll_l_rr(cdata,tmpcnt);\n");break;
- default: abort();
+ default: assert(0);
}
comprintf("test_l_ri(tmpcnt,highmask);\n"
"mov_l_ri(scratchie,0);\n"
case sz_long: comprintf("\tshll_l_rr(data,cnt);\n"
"\thighmask=0x20;\n");
break;
- default: abort();
+ default: assert(0);
}
comprintf("test_l_ri(cnt,highmask);\n"
"mov_l_ri(scratchie,0);\n"
case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break;
case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break;
case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break;
- default: abort();
+ default: assert(0);
}
genastore ("data", curi->dmode, "dstreg", curi->size, "data");
}
"\tbp=16-srcreg;\n"); break;
case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n"
"\tbp=32-srcreg;\n"); break;
- default: abort();
+ default: assert(0);
}
if (!noflags) {
}
break;
-case i_LSR:
+ case i_LSR:
#ifdef DISABLE_I_LSR
failure;
#endif
case sz_long: comprintf("\tshrl_l_rr(data,cnt);\n"
"\thighmask=0x20;\n");
break;
- default: abort();
+ default: assert(0);
}
comprintf("test_l_ri(cnt,highmask);\n"
"mov_l_ri(scratchie,0);\n"
case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break;
case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break;
case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break;
- default: abort();
+ default: assert(0);
}
/* Result of shift is now in data. Now we need to determine
the carry by shifting cdata one less */
case sz_byte: comprintf("\tshrl_b_rr(cdata,tmpcnt);\n");break;
case sz_word: comprintf("\tshrl_w_rr(cdata,tmpcnt);\n");break;
case sz_long: comprintf("\tshrl_l_rr(cdata,tmpcnt);\n");break;
- default: abort();
+ default: assert(0);
}
comprintf("test_l_ri(tmpcnt,highmask);\n"
"mov_l_ri(scratchie,0);\n"
case sz_long: comprintf("\tshrl_l_rr(data,cnt);\n"
"\thighmask=0x20;\n");
break;
- default: abort();
+ default: assert(0);
}
comprintf("test_l_ri(cnt,highmask);\n"
"mov_l_ri(scratchie,0);\n"
case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break;
case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break;
case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break;
- default: abort();
+ default: assert(0);
}
genastore ("data", curi->dmode, "dstreg", curi->size, "data");
}
"\tbp=srcreg-1;\n"); break;
case sz_long: comprintf("\tshrl_l_ri(data,srcreg);\n"
"\tbp=srcreg-1;\n"); break;
- default: abort();
+ default: assert(0);
}
if (!noflags) {
}
break;
-case i_LSL:
+ case i_LSL:
#ifdef DISABLE_I_LSL
failure;
#endif
case sz_long: comprintf("\tshll_l_rr(data,cnt);\n"
"\thighmask=0x20;\n");
break;
- default: abort();
+ default: assert(0);
}
comprintf("test_l_ri(cnt,highmask);\n"
"mov_l_ri(scratchie,0);\n"
case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break;
case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break;
case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break;
- default: abort();
+ default: assert(0);
}
/* Result of shift is now in data. Now we need to determine
the carry by shifting cdata one less */
case sz_byte: comprintf("\tshll_b_rr(cdata,tmpcnt);\n");break;
case sz_word: comprintf("\tshll_w_rr(cdata,tmpcnt);\n");break;
case sz_long: comprintf("\tshll_l_rr(cdata,tmpcnt);\n");break;
- default: abort();
+ default: assert(0);
}
comprintf("test_l_ri(tmpcnt,highmask);\n"
"mov_l_ri(scratchie,0);\n"
case sz_long: comprintf("\tshll_l_rr(data,cnt);\n"
"\thighmask=0x20;\n");
break;
- default: abort();
+ default: assert(0);
}
comprintf("test_l_ri(cnt,highmask);\n"
"mov_l_ri(scratchie,0);\n"
case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break;
case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break;
case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break;
- default: abort();
+ default: assert(0);
}
genastore ("data", curi->dmode, "dstreg", curi->size, "data");
}
"\tbp=16-srcreg;\n"); break;
case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n"
"\tbp=32-srcreg;\n"); break;
- default: abort();
+ default: assert(0);
}
if (!noflags) {
}
break;
-case i_ROL:
+ case i_ROL:
#ifdef DISABLE_I_ROL
failure;
#endif
failure;
break;
-case i_TAS:
+ case i_TAS:
failure;
break;
#ifdef DISABLE_I_FBCC
failure;
#endif
+ uses_fpu;
isjump;
uses_cmov;
mayfail;
#ifdef DISABLE_I_FSCC
failure;
#endif
+ uses_fpu;
mayfail;
uses_cmov;
comprintf("#ifdef USE_JIT_FPU\n");
genmov16(opcode,curi);
break;
+#ifdef UAE
case i_MMUOP030:
case i_PFLUSHN:
case i_PFLUSH:
isjump;
failure;
break;
+#endif
+
+#ifdef WINUAE_ARANYM
+ case i_EMULOP_RETURN:
+ isjump;
+ failure;
+ break;
+
+ case i_EMULOP:
+ failure;
+ break;
+
+ case i_NATFEAT_ID:
+ case i_NATFEAT_CALL:
+ failure;
+ break;
+
+ case i_MMUOP:
+ isjump;
+ failure;
+ break;
+#endif
default:
- abort();
+ assert(0);
break;
}
comprintf("%s",endstr);
static int postfix;
+#ifdef UAE
static char *decodeEA (amodes mode, wordsizes size)
{
static char buffer[80];
}
return out;
}
+#endif
+
static void
generate_one_opcode (int rp, int noflags)
int aborted=0;
int have_srcreg=0;
int have_dstreg=0;
+#ifdef UAE
+ char *name;
+#else
+ const char *name;
+#endif
if (table68k[opcode].mnemo == i_ILLG
|| table68k[opcode].clev > cpu_level)
case 5:
smsk = 63;
break;
- case 7:
+#ifndef UAE
+ case 6:
+ smsk = 255;
+ break;
+#endif
+ case 7:
smsk = 3;
break;
default:
- abort ();
+ assert(0);
}
dmsk = 7;
char source[100];
int pos = table68k[opcode].spos;
+#ifndef UAE
+ comprintf ("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n");
+
+ if (pos < 8 && (smsk >> (8 - pos)) != 0)
+ sprintf (source, "(((opcode >> %d) | (opcode << %d)) & %d)",
+ pos ^ 8, 8 - pos, dmsk);
+ else if (pos != 8)
+ sprintf (source, "((opcode >> %d) & %d)", pos ^ 8, smsk);
+ else
+ sprintf (source, "(opcode & %d)", smsk);
+
+ if (table68k[opcode].stype == 3)
+ comprintf ("\tuae_u32 srcreg = imm8_table[%s];\n", source);
+ else if (table68k[opcode].stype == 1)
+ comprintf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source);
+ else
+ comprintf ("\tuae_u32 srcreg = %s;\n", source);
+
+ comprintf ("#else\n");
+#endif
+
if (pos)
sprintf (source, "((opcode >> %d) & %d)", pos, smsk);
else
comprintf ("\tuae_s32 srcreg = (uae_s32)(uae_s8)%s;\n", source);
else
comprintf ("\tuae_s32 srcreg = %s;\n", source);
+
+#ifndef UAE
+ comprintf ("#endif\n");
+#endif
}
}
if (table68k[opcode].duse
{
int pos = table68k[opcode].dpos;
+#ifndef UAE
+ comprintf ("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n");
+
+ if (pos < 8 && (dmsk >> (8 - pos)) != 0)
+ comprintf ("\tuae_u32 dstreg = ((opcode >> %d) | (opcode << %d)) & %d;\n",
+ pos ^ 8, 8 - pos, dmsk);
+ else if (pos != 8)
+ comprintf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n",
+ pos ^ 8, dmsk);
+ else
+ comprintf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk);
+
+ comprintf ("#else\n");
+#endif
+
if (pos)
comprintf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n",
pos, dmsk);
else
comprintf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk);
+
+#ifndef UAE
+ comprintf ("#endif\n");
+#endif
}
}
#endif
comprintf ("}\n");
- char *name = ua (lookuptab[i].name);
+#ifdef UAE
+ name = ua (lookuptab[i].name);
+#else
+ name = lookuptab[i].name;
+#endif
if (aborted) {
fprintf (stblfile, "{ NULL, %u, %s }, /* %s */\n", opcode, flags, name);
com_discard();
} else {
const char *tbl = noflags ? "nf" : "ff";
+#ifdef UAE
printf ("/* %s */\n", outopcode (opcode));
+#else
+ printf ("/* %s */\n", name);
+#endif
fprintf (stblfile, "{ op_%x_%d_comp_%s, %u, %s }, /* %s */\n", opcode, postfix, tbl, opcode, flags, name);
fprintf (headerfile, "extern compop_func op_%x_%d_comp_%s;\n", opcode, postfix, tbl);
- printf ("uae_u32 REGPARAM2 op_%x_%d_comp_%s(uae_u32 opcode)\n{\n", opcode, postfix, tbl);
+ printf (RETTYPE " REGPARAM2 op_%x_%d_comp_%s(uae_u32 opcode)\n{\n", opcode, postfix, tbl);
com_flush();
}
+#ifdef UAE
xfree (name);
+#endif
}
opcode_next_clev[rp] = next_cpu_level;
opcode_last_postfix[rp] = postfix;
generate_func (int noflags)
{
int i, j, rp;
+ const char *tbl = noflags ? "nf" : "ff";
using_prefetch = 0;
using_exception_3 = 0;
for (i = 0; i < 1; i++) /* We only do one level! */
{
- cpu_level = 5 - i;
+ cpu_level = NEXT_CPU_LEVEL - i;
postfix = i;
- if (noflags)
- fprintf (stblfile, "const struct comptbl op_smalltbl_%d_comp_nf[] = {\n", postfix);
- else
- fprintf (stblfile, "const struct comptbl op_smalltbl_%d_comp_ff[] = {\n", postfix);
-
+ fprintf (stblfile, "const struct comptbl op_smalltbl_%d_comp_%s[] = {\n", postfix, tbl);
/* sam: this is for people with low memory (eg. me :)) */
printf ("\n"
}
-int main(int argc, char *argv[])
+#ifdef __cplusplus
+int main(int, char **)
+#else
+int main()
+#endif
{
read_table68k ();
do_merges ();
* I don't dare to touch the 68k version. */
headerfile = fopen (GEN_PATH "comptbl.h", "wb");
-
- fprintf (headerfile, "" \
- "#ifdef NOFLAGS_SUPPORT\n" \
- "/* 68040 */\n" \
- "extern const struct comptbl op_smalltbl_0_nf[];\n" \
- "#endif\n" \
- "extern const struct comptbl op_smalltbl_0_comp_nf[];\n" \
- "extern const struct comptbl op_smalltbl_0_comp_ff[];\n" \
+ fprintf (headerfile, ""
+ "extern const struct comptbl op_smalltbl_0_comp_nf[];\n"
+ "extern const struct comptbl op_smalltbl_0_comp_ff[];\n"
"");
stblfile = fopen (GEN_PATH "compstbl.cpp", "wb");
return 0;
}
+#ifdef UAE
void write_log (const TCHAR *format,...)
{
}
+#endif