From ac26506b6d1416b6e9b88dadbb5d9cf33f08a3bc Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 21 Aug 2022 20:06:22 +0300 Subject: [PATCH] Warning fixes, preparing for future ARM64 build. --- gencpu.cpp | 10 +- include/sysdeps.h | 7 +- include/uae/time.h | 1 + jit/codegen_arm.cpp | 2730 ++++++++++++++++++ jit/codegen_arm.h | 1292 +++++++++ jit/compemu_midfunc_arm.cpp | 1967 +++++++++++++ jit/compemu_midfunc_arm.h | 186 ++ jit/compemu_midfunc_arm2.cpp | 5195 ++++++++++++++++++++++++++++++++++ jit/compemu_midfunc_arm2.h | 348 +++ jit/flags_arm.h | 52 + jit/gencomp_arm.c | 5082 +++++++++++++++++++++++++++++++++ od-win32/sysconfig.h | 5 + od-win32/win32.cpp | 6 +- od-win32/win32gfx.cpp | 8 +- support/time.cpp | 20 +- 15 files changed, 16880 insertions(+), 29 deletions(-) create mode 100644 jit/codegen_arm.cpp create mode 100644 jit/codegen_arm.h create mode 100644 jit/compemu_midfunc_arm.cpp create mode 100644 jit/compemu_midfunc_arm.h create mode 100644 jit/compemu_midfunc_arm2.cpp create mode 100644 jit/compemu_midfunc_arm2.h create mode 100644 jit/flags_arm.h create mode 100644 jit/gencomp_arm.c diff --git a/gencpu.cpp b/gencpu.cpp index 43207104..3b835b4d 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -2383,7 +2383,7 @@ static void check_bus_error(const char *name, int offset, int write, int size, c out("opcode |= 0x80000;\n"); } else if (g_instr->mnemo == i_CLR) { if (g_instr->smode < Ad16) { - out("regflags.cznv = oldflags;\n"); + out("regflags.cznv = oldflags.cznv;\n"); } // (an)+ and -(an) is done later if (g_instr->smode == Aipi || g_instr->smode == Apdi) { @@ -3036,7 +3036,7 @@ static void move_68010_address_error(int size, int *setapdi, int *fcmodeflags) out("regs.irc = dsta >> 16;\n"); } if (reset_ccr) { - out("regflags.cznv = oldflags;\n"); + out("regflags.cznv = oldflags.cznv;\n"); } if (set_ccr) { out("ccr_68000_word_move_ae_normal((uae_s16)(src));\n"); @@ -5998,7 +5998,8 @@ static void gen_opcode (unsigned int opcode) genastore_rev("0", curi->smode, "srcreg", curi->size, "src"); } } else if (cpu_level == 1) { - out("uae_u16 oldflags = regflags.cznv;\n"); + out("struct flag_struct oldflags;\n"); + out("oldflags.cznv = regflags.cznv;\n"); genamode(curi, curi->smode, "srcreg", curi->size, "src", 3, 0, GF_CLR68010); if (isreg(curi->smode) && curi->size == sz_long) { addcycles000(2); @@ -6461,7 +6462,8 @@ static void gen_opcode (unsigned int opcode) if (curi->mnemo == i_MOVE) { if (cpu_level == 1 && (isreg(curi->smode) || curi->smode == imm)) { - out("uae_u16 oldflags = regflags.cznv;\n"); + out("struct flag_struct oldflags;\n"); + out("oldflags.cznv = regflags.cznv;\n"); } if (curi->size == sz_long && (using_prefetch || using_ce) && curi->dmode >= Aind) { // to support bus error exception correct flags, flags needs to be set diff --git a/include/sysdeps.h b/include/sysdeps.h index 5b4dfd76..de16bb20 100644 --- a/include/sysdeps.h +++ b/include/sysdeps.h @@ -40,7 +40,10 @@ using namespace std; #define UAE #endif -#if defined(__x86_64__) || defined(_M_AMD64) +#if defined(__arm__) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) +#define CPU_arm 1 +#define ARM_ASSEMBLY 1 +#elif defined(__x86_64__) || defined(_M_AMD64) #define CPU_x86_64 1 #define CPU_64_BIT 1 #define X86_64_ASSEMBLY 1 @@ -48,8 +51,6 @@ using namespace std; #define CPU_i386 1 #define X86_ASSEMBLY 1 #define SAHF_SETO_PROFITABLE -#elif defined(__arm__) || defined(_M_ARM) -#define CPU_arm 1 #elif defined(__powerpc__) || defined(_M_PPC) #define CPU_powerpc 1 #else diff --git a/include/uae/time.h b/include/uae/time.h index 0a9a9ed5..291f57dd 100644 --- a/include/uae/time.h +++ b/include/uae/time.h @@ -13,6 +13,7 @@ uae_time_t uae_time(void); #ifdef _WIN32 void uae_time_use_rdtsc(bool enable); uae_s64 read_system_time(void); +uae_s64 read_processor_time_rdtsc(void); #endif typedef uae_time_t frame_time_t; diff --git a/jit/codegen_arm.cpp b/jit/codegen_arm.cpp new file mode 100644 index 00000000..334ae753 --- /dev/null +++ b/jit/codegen_arm.cpp @@ -0,0 +1,2730 @@ +/* + * compiler/codegen_arm.cpp - ARM code generator + * + * Copyright (c) 2013 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * JIT compiler m68k -> ARM + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne + * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Current state: + * - Experimental + * - Still optimizable + * - Not clock cycle optimized + * - as a first step this compiler emulates x86 instruction to be compatible + * with gencomp. Better would be a specialized version of gencomp compiling + * 68k instructions to ARM compatible instructions. This is a step for the + * future + * + */ + +#include "flags_arm.h" + +// Declare the built-in __clear_cache function. +extern void __clear_cache (char*, char*); + +/************************************************************************* + * Some basic information about the the target CPU * + *************************************************************************/ + +#define R0_INDEX 0 +#define R1_INDEX 1 +#define R2_INDEX 2 +#define R3_INDEX 3 +#define R4_INDEX 4 +#define R5_INDEX 5 +#define R6_INDEX 6 +#define R7_INDEX 7 +#define R8_INDEX 8 +#define R9_INDEX 9 +#define R10_INDEX 10 +#define R11_INDEX 11 +#define R12_INDEX 12 +#define R13_INDEX 13 +#define R14_INDEX 14 +#define R15_INDEX 15 + +#define RSP_INDEX 13 +#define RLR_INDEX 14 +#define RPC_INDEX 15 + +/* The register in which subroutines return an integer return value */ +#define REG_RESULT R0_INDEX + +/* The registers subroutines take their first and second argument in */ +#define REG_PAR1 R0_INDEX +#define REG_PAR2 R1_INDEX + +#define REG_WORK1 R2_INDEX +#define REG_WORK2 R3_INDEX + +//#define REG_DATAPTR R10_INDEX + +#define REG_PC_PRE R0_INDEX /* The register we use for preloading regs.pc_p */ +#define REG_PC_TMP R1_INDEX /* Another register that is not the above */ + +#define SHIFTCOUNT_NREG R1_INDEX /* Register that can be used for shiftcount. + -1 if any reg will do. Normally this can be set to -1 but compemu_support is tied to 1 */ +#define MUL_NREG1 R0_INDEX /* %r4 will hold the low 32 bits after a 32x32 mul */ +#define MUL_NREG2 R1_INDEX /* %r5 will hold the high 32 bits */ + +#define STACK_ALIGN 4 +#define STACK_OFFSET sizeof(void *) +#define STACK_SHADOW_SPACE 0 + +uae_s8 always_used[]={2,3,-1}; +uae_s8 can_byte[]={0,1,4,5,6,7,8,9,10,11,12,-1}; +uae_s8 can_word[]={0,1,4,5,6,7,8,9,10,11,12,-1}; + +uae_u8 call_saved[]={0,0,0,0,1,1,1,1,1,1,1,1,0,1,1,1}; + +/* This *should* be the same as call_saved. But: + - We might not really know which registers are saved, and which aren't, + so we need to preserve some, but don't want to rely on everyone else + also saving those registers + - Special registers (such like the stack pointer) should not be "preserved" + by pushing, even though they are "saved" across function calls +*/ +static const uae_u8 need_to_preserve[]={0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0}; +static const uae_u32 PRESERVE_MASK = ((1<=-128 && x<=127); +} + +static inline int is8bit(uae_s32 x) +{ + return (x>=-255 && x<=255); +} + +static inline int isword(uae_s32 x) +{ + return (x>=-32768 && x<=32767); +} + +#define jit_unimplemented(fmt, ...) do{ panicbug("**** Unimplemented ****"); panicbug(fmt, ## __VA_ARGS__); abort(); }while (0) + +#if 0 /* currently unused */ +static void jit_fail(const char *msg, const char *file, int line, const char *function) +{ + panicbug("JIT failure in function %s from file %s at line %d: %s", + function, file, line, msg); + abort(); +} +#endif + +LOWFUNC(NONE,WRITE,1,raw_push_l_r,(RR4 r)) +{ + PUSH(r); +} + +LOWFUNC(NONE,READ,1,raw_pop_l_r,(RR4 r)) +{ + POP(r); +} + +LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, RR1 s)) +{ + MVN_ri(REG_WORK1, 0); // mvn r2,#0 + LSL_rri(REG_WORK2, d, 24); // lsl r3, %[d], #24 + ORR_rrrLSRi(REG_WORK2, REG_WORK2, REG_WORK1, 8); // orr r3, r3, r2, lsr #8 + LSL_rri(REG_WORK1, s, 24); // lsl r2, %[s], #24 + + ADCS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adcs r3, r3, r2 + + BIC_rri(d, d, 0xFF); // bic %[d],%[d],#0xFF + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr %[d],%[d], R3 LSR #24 +} + +LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, RR2 s)) +{ + MVN_ri(REG_WORK1, 0); // mvn r2,#0 + LSL_rri(REG_WORK2, d, 16); // lsl r3, %[d], #16 + ORR_rrrLSRi(REG_WORK2, REG_WORK2, REG_WORK1, 16); // orr r3, r3, r2, lsr #16 + LSL_rri(REG_WORK1, s, 16); // lsl r2, %[s], #16 + + ADCS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 +#ifdef ARMV6_ASSEMBLY + PKHTB_rrrASRi(d,d,REG_WORK2,16); +#else + BIC_rri(d, d, 0xff); // bic %[d],%[d],#0xff + BIC_rri(d, d, 0xff00); // bic %[d],%[d],#0xff00 + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr %[d], %[d], r3, lsr #16 +#endif +} + +LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, RR4 s)) +{ + ADCS_rrr(d, d, s); // adcs %[d],%[d],%[s] +} + +LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, RR1 s)) +{ + LSL_rri(REG_WORK1, s, 24); // lsl r2, %[s], #24 + LSL_rri(REG_WORK2, d, 24); // lsl r3, %[d], #24 + + ADDS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 + + BIC_rri(d, d, 0xFF); // bic %[d],%[d],#0xFF + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr %[d],%[d], r3 LSR #24 +} + +LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, RR2 s)) +{ + LSL_rri(REG_WORK1, s, 16); // lsl r2, %[s], #16 + LSL_rri(REG_WORK2, d, 16); // lsl r3, %[d], #16 + + ADDS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 + +#ifdef ARMV6_ASSEMBLY + PKHTB_rrrASRi(d,d,REG_WORK2,16); +#else + BIC_rri(d, d, 0xff); // bic %[d],%[d],#0xff + BIC_rri(d, d, 0xff00); // bic %[d],%[d],#0xff00 + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr r7, r7, r3, LSR #16 +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, RR4 s)) +{ + ADDS_rrr(d, d, s); // adds %[d], %[d], %[s] +} + +LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_word_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldrh r2, [pc, #offs] +#else +# ifdef ARMV6_ASSEMBLY + LDRH_rRI(REG_WORK1, RPC_INDEX, 24); // ldrh r2, [pc, #24] ; +# else + LDRH_rRI(REG_WORK1, RPC_INDEX, 16); // ldrh r2, [pc, #16] ; +# endif +#endif + LSL_rri(REG_WORK2, d, 16); // lsl r3, %[d], #16 + LSL_rri(REG_WORK1, REG_WORK1, 16); // lsl r2, r2, #16 + + ADDS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 + +#ifdef ARMV6_ASSEMBLY + PKHTB_rrrASRi(d,d,REG_WORK2,16); +#else + BIC_rri(d, d, 0xff); // bic %[d],%[d],#0xff + BIC_rri(d, d, 0xff00); // bic %[d],%[d],#0xff00 + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr %[d],%[d], r3, LSR #16 +#endif + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_word(i); + skip_word(0); + //: +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) +{ + LSL_rri(REG_WORK2, d, 24); // lsl r3, %[d], #24 + + ADDS_rri(REG_WORK2, REG_WORK2, i << 24); // adds r3, r3, #0x12000000 + + BIC_rri(d, d, 0xFF); // bic %[d],%[d], #0xFF + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr %[d],%[d], r3, lsr #24 +} + +LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + ADDS_rrr(d, d, REG_WORK1); // adds %[d], %[d], r2 +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + ADDS_rrr(d, d, REG_WORK1); // adds %[d], %[d], r2 + B_i(0); // b + + //: + emit_long(i); + //: +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, RR1 s)) +{ + MVN_rrLSLi(REG_WORK1, s, 24); // mvn r2, %[s], lsl #24 + MVN_rrLSRi(REG_WORK1, REG_WORK1, 24); // mvn r2, %[s], lsr #24 + AND_rrr(d, d, REG_WORK1); // and %[d], %[d], r2 + + LSLS_rri(REG_WORK1, d, 24); // lsls r2, %[d], #24 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, RR2 s)) +{ + MVN_rrLSLi(REG_WORK1, s, 16); // mvn r2, %[s], lsl #16 + MVN_rrLSRi(REG_WORK1, REG_WORK1, 16); // mvn r2, %[s], lsr #16 + AND_rrr(d, d, REG_WORK1); // and %[d], %[d], r2 + + LSLS_rri(REG_WORK1, d, 16); // lsls r2, %[d], #16 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, RR4 s)) +{ + ANDS_rrr(d, d, s); // ands r7, r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #16] ; +#endif + ANDS_rrr(d, d, REG_WORK1); // ands %[d], %[d], r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(i); + //: +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, RR4 s)) +{ + MOV_rr(REG_WORK1, s); // mov r2,%[s] + RSB_rri(REG_WORK2, REG_WORK1, 0); // rsb r3,r2,#0 + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // and r2,r2,r3 + CLZ_rr(REG_WORK2, REG_WORK1); // clz r3,r2 + MOV_ri(d, 32); // mov %[d],#32 + SUB_rrr(d, d, REG_WORK2); // sub %[d],%[d],r3 + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TEQ_ri(d, 0); // teq %[d],#0 + CC_SUBS_rri(NATIVE_CC_NE, d,d,1); // sub %[d],%[d],#1 + CC_BIC_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_Z_FLAG); // bic r3,r3,#0x40000000 + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_Z_FLAG); // orr r3,r3,#0x40000000 + MSR_CPSR_r(REG_WORK2); // msr cpsr,r3 +} + +LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) +{ +#if defined(ARMV6_ASSEMBLY) + REVSH_rr(REG_WORK1,r); // revsh r2,%[r] + UXTH_rr(REG_WORK1, REG_WORK1); // utxh r2,r2 + LSR_rri(r, r, 16); + ORR_rrrLSLi(r, REG_WORK1, r, 16); // orr %[r], %[r], r2 +#else + MOV_rr(REG_WORK1, r); // mov r2, r6 + BIC_rri(REG_WORK1, REG_WORK1, 0xff0000); // bic r2, r2, #0xff0000 + BIC_rri(REG_WORK1, REG_WORK1, 0xff000000); // bic r2, r2, #0xff000000 + + EOR_rrr(r, r, REG_WORK1); // eor r6, r6, r2 + + ORR_rrrLSRi(r, r, REG_WORK1, 8); // orr r6, r6, r2, lsr #8 + BIC_rri(REG_WORK1, REG_WORK1, 0xff00); // bic r2, r2, #0xff00 + ORR_rrrLSLi(r,r,REG_WORK1, 8); // orr r6, r6, r2, lsl #8 +#endif +} + +LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) +{ +#if defined(ARMV6_ASSEMBLY) + REV_rr(r,r); // rev %[r],%[r] +#else + EOR_rrrRORi(REG_WORK1, r, r, 16); // eor r2, r6, r6, ror #16 + BIC_rri(REG_WORK1, REG_WORK1, 0xff0000); // bic r2, r2, #0xff0000 + ROR_rri(r, r, 8); // ror r6, r6, #8 + EOR_rrrLSRi(r, r, REG_WORK1, 8); // eor r6, r6, r2, lsr #8 +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(RR4 r, IMM i)) +{ + int imm = (1 << (i & 0x1f)); + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_ri(r, imm); // tst r6, #0x1000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} + +LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(RR4 r, RR4 b)) +{ + AND_rri(REG_WORK2, b, 0x1f); // and r3, r7, #0x1f + LSR_rrr(REG_WORK1, r, REG_WORK2); // lsr r2, r6, r3 + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_ri(REG_WORK1, 1); // tst r2, #1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} + +LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, RR4 b)) +{ + MOV_ri(REG_WORK1, 1); // mov r2, #1 + AND_rri(REG_WORK2, b, 0x1f); // and r3, r7, #0x1f + LSL_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // lsl r2, r2, r3 + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_rr(r, REG_WORK1); // tst r6, r2 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + EOR_rrr(r, r, REG_WORK1); // eor r6, r6, r2 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} + +LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, RR4 b)) +{ + MOV_ri(REG_WORK1, 1); // mov r2, #1 + AND_rri(REG_WORK2, b, 0x1f); // and r3, r7, #0x1f + LSL_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // lsl r2, r2, r3 + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_rr(r, REG_WORK1); // tst r6, r2 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + BIC_rrr(r, r, REG_WORK1); // bic r6, r6, r2 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} + +LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, RR4 b)) +{ + MOV_ri(REG_WORK1, 1); // mov r2, #1 + AND_rri(REG_WORK2, b, 0x1f); // and r3, r7, #0x1f + LSL_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // lsl r2, r2, r3 + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_rr(r, REG_WORK1); // tst r6, r2 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + ORR_rrr(r, r, REG_WORK1); // orr r6, r6, r2 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} + +LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, RR4 s, IMM cc)) +{ + switch (cc) { + case 9: // LS + BEQ_i(0); // beq Z != 0 + BCC_i(0); // bcc C == 0 + + //: + MOV_rr(d, s); // mov r7,r6 + break; + + case 8: // HI + BEQ_i(1); // beq Z != 0 + BCS_i(0); // bcs C != 0 + MOV_rr(d, s); // mov r7,#0 + break; + + default: + CC_MOV_rr(cc, d, s); // MOVcc R7,#1 + break; + } + //: +} + +LOWFUNC(WRITE,NONE,2,raw_cmp_b,(RR1 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + SXTB_rr(REG_WORK1, d); // sxtb r2,%[d] + SXTB_rr(REG_WORK2, s); // sxtb r3,%[s] +#else + LSL_rri(REG_WORK1, d, 24); // lsl r2,r6,#24 + LSL_rri(REG_WORK2, s, 24); // lsl r3,r7,#24 +#endif + CMP_rr(REG_WORK1, REG_WORK2); // cmp r2, r3 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_cmp_w,(RR2 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + SXTH_rr(REG_WORK1, d); // sxtb r2,%[d] + SXTH_rr(REG_WORK2, s); // sxtb r3,%[s] +#else + LSL_rri(REG_WORK1, d, 16); // lsl r6, r1, #16 + LSL_rri(REG_WORK2, s, 16); // lsl r7, r2, #16 +#endif + + CMP_rr(REG_WORK1, REG_WORK2); // cmp r7, r6, asr #16 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_cmp_l,(RR4 d, RR4 s)) +{ + CMP_rr(d, s); // cmp r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, RR4 s)) +{ + SMULL_rrrr(REG_WORK1, REG_WORK2, d, s); // smull r2,r3,r7,r6 + MOV_rr(d, REG_WORK1); // mov r7,r2 +} + +LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) +{ + SMULL_rrrr(REG_WORK1, REG_WORK2, d, s); // smull r2,r3,r7,r6 + MOV_rr(MUL_NREG1, REG_WORK1); // mov r7,r2 + MOV_rr(MUL_NREG2, REG_WORK2); +} + +LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + ADD_rrr(d, s, REG_WORK1); // add r7, r6, r2 +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + ADD_rrr(d, s, REG_WORK1); // add r7, r6, r2 + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} + +LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) +{ + int shft; + switch(factor) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // LDR R2,[PC, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // LDR R2,[PC, #8] +#endif + ADD_rrr(REG_WORK1, s, REG_WORK1); // ADD R7,R6,R2 + ADD_rrrLSLi(d, REG_WORK1, index, shft); // ADD R7,R7,R5,LSL #2 +#if !defined(USE_DATA_BUFFER) + B_i(0); // B jp + + emit_long(offset); + //; +#endif +} + +LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) +{ + int shft; + switch(factor) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + + ADD_rrrLSLi(d, s, index, shft); // ADD R7,R6,R5,LSL #2 +} + +LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 12); // ldr r2, [pc, #12] ; +#endif + LDRB_rRR(REG_WORK1, REG_WORK1, s); // ldrb r2, [r2, r6] + + BIC_rri(d, d, 0xff); // bic r7, r7, #0xff + ORR_rrr(d, d, REG_WORK1); // orr r7, r7, r2 +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} + +LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(RR4 d, RR1 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2,[pc, #offs] + STRB_rRR(s, d, REG_WORK1); // strb r6,[r7, r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2,[pc,#4] + STRB_rRR(s, d, REG_WORK1); // strb r6,[r7, r2] + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} + +LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // ldr r2, [pc, #8] ; +#endif + MOV_ri(REG_WORK2, s & 0xFF); // mov r3, #0x34 + STRB_rR(REG_WORK2, REG_WORK1); // strb r3, [r2] +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //d: + emit_long(d); + + //: +#endif +} + +LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, RR1 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + STRB_rR(s, REG_WORK1); // strb r6, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STRB_rR(s, REG_WORK1); // strb r6, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} + +LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) +{ + BIC_rri(d, d, 0xff); // bic %[d], %[d], #0xff + ORR_rri(d, d, (s & 0xff)); // orr %[d], %[d], #%[s] +} + +LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 12); // ldr r2, [pc, #12] ; +#endif + LDRB_rR(REG_WORK2, REG_WORK1); // ldrb r2, [r2] + BIC_rri(d, d, 0xff); // bic r7, r7, #0xff + ORR_rrr(d, REG_WORK2, d); // orr r7, r2, r7 +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(s); + //: +#endif +} + +LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, RR1 s)) +{ + AND_rri(REG_WORK1, s, 0xff); // and r2,r2, #0xff + BIC_rri(d, d, 0x0ff); // bic %[d], %[d], #0xff + ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 +} + +LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + LDR_rRR(d, REG_WORK1, s); // ldr r7, [r2, r6] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + LDR_rRR(d, REG_WORK1, s); // ldr r7, [r2, r6] + + B_i(0); // b + + emit_long(offset); //: + //: +#endif +} + +LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(RR4 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2,[pc, #offs] + STR_rRR(s, d, REG_WORK1); // str R6,[R7, r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2,[pc,#4] ; + STR_rRR(s, d, REG_WORK1); // str R6,[R7, r2] + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} + +LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) +{ + // TODO: optimize imm + +#if defined(USE_DATA_BUFFER) + data_check_end(8, 12); + long offs = data_long_offs(d); + + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + + offs = data_long_offs(s); + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // ldr r3, [pc, #offs] ; s + + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // ldr r2, [pc, #8] ; + LDR_rRI(REG_WORK2, RPC_INDEX, 8); // ldr r3, [pc, #8] ; + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] + B_i(1); // b + + emit_long(d); //: + emit_long(s); //: + + //: +#endif +} + +LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else +# ifdef ARMV6_ASSEMBLY + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // ldr r2, [pc, #16] ; +# else + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #16] ; +# endif +#endif + LDRH_rRR(REG_WORK1, REG_WORK1, s); // ldrh r2, [r2, r6] + +#ifdef ARMV6_ASSEMBLY + PKHBT_rrr(d,REG_WORK1,d); +#else + BIC_rri(d, d, 0xff); // bic r7, r7, #0xff + BIC_rri(d, d, 0xff00); // bic r7, r7, #0xff00 + ORR_rrr(d, d, REG_WORK1); // orr r7, r7, r2 +#endif + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + emit_long(offset); //: + //: +#endif +} + +LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(RR4 d, RR2 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2,[pc, #offs] + STRH_rRR(s, d, REG_WORK1); // strh r6,[r7, r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2,[pc,#4] + STRH_rRR(s, d, REG_WORK1); // strh r6,[r7, r2] + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} + +LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, RR2 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc,#offs] + STRH_rR(s, REG_WORK1); // strh r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STRH_rR(s, REG_WORK1); // strh r3, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} + +LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_word_offs(s); + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // ldrh r3, [pc, #offs] +#else +# ifdef ARMV6_ASSEMBLY + LDRH_rRI(REG_WORK2, RPC_INDEX, 12); // ldrh r3, [pc, #12] ; +# else + LDRH_rRI(REG_WORK2, RPC_INDEX, 4); // ldrh r3, [pc, #12] ; +# endif +#endif + +#ifdef ARMV6_ASSEMBLY + PKHBT_rrr(d,REG_WORK2,d); +#else + BIC_rri(REG_WORK1, d, 0xff); // bic r2, r7, #0xff + BIC_rri(REG_WORK1, REG_WORK1, 0xff00); // bic r2, r2, #0xff00 + ORR_rrr(d, REG_WORK2, REG_WORK1); // orr r7, r3, r2 +#endif + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_word(s); + skip_word(0); + //: +#endif +} + +LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) +{ + // TODO: optimize imm + +#if defined(USE_DATA_BUFFER) + data_check_end(8, 12); + long offs = data_long_offs(d); + + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // ldr r3, [pc, #offs] ; + + offs = data_word_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + + STRH_rR(REG_WORK1, REG_WORK2); // strh r2, [r3] +#else + LDR_rRI(REG_WORK2, RPC_INDEX, 8); // ldr r3, [pc, #8] ; + LDRH_rRI(REG_WORK1, RPC_INDEX, 8); // ldrh r2, [pc, #8] ; + STRH_rR(REG_WORK1, REG_WORK2); // strh r2, [r3] + B_i(1); // b + + //mem: + emit_long(d); + //imm: + emit_word(s); + skip_word(0); // Alignment + + //: +#endif +} + +LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, RR4 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + STR_rR(s, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STR_rR(s, REG_WORK1); // str r3, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} + +LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(RR4 d, IMM i, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + +#if defined(USE_DATA_BUFFER) + long offs = data_word_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDRH_rRI(REG_WORK1, RPC_INDEX, 4); // ldrh r2, [pc, #4] ; +#endif + if (offset >= 0) + STRH_rRI(REG_WORK1, d, offset); // strh r2, [r7, #0x54] + else + STRH_rRi(REG_WORK1, d, -offset);// strh r2, [r7, #-0x54] +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_word(i); + skip_word(0); + //: +#endif +} + +LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 12); // ldr r2, [pc, #12] ; +#endif + LDRH_rR(REG_WORK1, REG_WORK1); // ldrh r2, [r2] + LSR_rri(d, d, 16); // lsr r7, r7, #16 + ORR_rrrLSLi(d, REG_WORK1, d, 16); // orr r7, r2, r7, lsl #16 +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(s); + //: +#endif +} + +LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, RR2 s)) +{ + LSL_rri(REG_WORK1, s, 16); // lsl r2, r6, #16 + ORR_rrrLSRi(d, REG_WORK1, d, 16); // orr r7, r2, r7, lsr #16 + ROR_rri(d, d, 16); // ror r7, r7, #16 +} + +LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, RR4 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + + if (offset >= 0) + LDRH_rRI(REG_WORK1, s, offset); // ldrh r2, [r6, #12] + else + LDRH_rRi(REG_WORK1, s, -offset); // ldrh r2, [r6, #-12] + +#ifdef ARMV6_ASSEMBLY + PKHBT_rrr(d,REG_WORK1,d); +#else + BIC_rri(d, d, 0xff); // bic r7, r7, #0xff + BIC_rri(d, d, 0xff00); // bic r7, r7, #0xff00 + ORR_rrr(d, d, REG_WORK1); // orr r7, r7, r2 +#endif +} + +LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(RR4 d, RR2 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + + if (offset >= 0) + STRH_rRI(s, d, offset); // strh r6, [r7, #0x7f] + else + STRH_rRi(s, d, -offset);// strh r6, [r7, #-0x7f] +} + +LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [r10, #offs] + LDR_rR(d, REG_WORK1); // ldr r7, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + LDR_rR(d, REG_WORK1); // ldr r7, [r2] + B_i(0); // b + + emit_long(s); //: + + //: +#endif +} + +LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, MEMR base, RR4 index, IMM factor)) +{ + int shft; + switch(factor) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(base); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + LDR_rRR_LSLi(d, REG_WORK1, index, shft); // ldr %[d], [r2, %[index], lsl #[shift]] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + LDR_rRR_LSLi(d, REG_WORK1, index, shft); // ldr %[d], [r2, %[index], lsl #[shift]] + + B_i(0); // b + emit_long(base); //: + //: +#endif +} + +LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(RR4 d, IMM i, IMM offset8)) +{ + Dif(!isbyte(offset8)) abort(); + +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; +#endif + if (offset8 >= 0) + STR_rRI(REG_WORK1, d, offset8); // str r2, [r7, #0x54] + else + STR_rRi(REG_WORK1, d, -offset8); // str r2, [r7, #-0x54] +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(i); + //: +#endif +} + +LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, RR4 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + + if (offset >= 0) { + LDR_rRI(d, s, offset); // ldr r2, [r1, #-12] + } else + LDR_rRi(d, s, -offset); // ldr r2, [r1, #12] +} + +LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, RR4 s)) +{ + MOV_rr(d, s); // mov %[d], %[s] +} + +LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(RR4 d, RR4 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + + if (offset >= 0) + STR_rRI(s, d, offset); // str r6, [r7, #12] + else + STR_rRi(s, d, -offset); // str r6, [r7, #-12] +} + +LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) +{ + UMULL_rrrr(REG_WORK1, REG_WORK2, d, s); // umull r2,r3,r7,r6 + MOV_rr(MUL_NREG1, REG_WORK1); // mov r7,r2 + MOV_rr(MUL_NREG2, REG_WORK2); +} + +LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, RR1 s)) +{ + AND_rri(REG_WORK1, s, 0xFF); // and r2, %[s], 0xFF + ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 + LSLS_rri(REG_WORK1, d, 24); // lsls r2, %[d], #24 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, s); // UXTH r2, %[s] +#else + BIC_rri(REG_WORK1, s, 0xff000000); // bic r2, %[s], #0xff000000 + BIC_rri(REG_WORK1, REG_WORK1, 0x00ff0000); // bic r2, r2, #0x00ff0000 +#endif + ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 + LSLS_rri(REG_WORK1, d, 16); // lsls r2, %[d], #16 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, RR4 s)) +{ + ORRS_rrr(d, d, s); // orrs r7, r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // LDR r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // LDR r2, [pc,#16] ; +#endif + ORRS_rrr(d, d, REG_WORK1); // ORRS r7,r7,r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + // value: + emit_long(i); + //jp: +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + int imm = 32 - (i & 0x1f); + + MOV_rrLSLi(REG_WORK1, r, 24); // mov r2,r7,lsl #24 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 8); // orr r2,r2,r2,lsr #8 + + RORS_rri(REG_WORK1, REG_WORK1, imm); // rors r2,r2,#(32 - (i & 0x1f)) + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(REG_WORK1, 1); // tst r2,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(r, r, 0xff); // bic r7,r7,#0xff + ORR_rrr(r, r, REG_WORK1); // orr r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, RR1 r)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + + MOV_ri(REG_WORK2, 32); // mov r3,#32 + AND_rri(REG_WORK1, r, 0x1f); // and r2,r6,#0x1f + SUB_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // sub r3,r3,r2 + + MOV_rrLSLi(REG_WORK1, d, 24); // mov r2,r7,lsl #24 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 8); // orr r2,r2,r2,lsr #8 + + RORS_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // rors r2,r2,r3 + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(REG_WORK1, 1); // tst r2,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(d, d, 0xff); // bic r7,r7,#0xff + + ORR_rrr(d, d, REG_WORK1); // orr r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + int imm = 32 - (i & 0x1f); + + MOV_rrLSLi(REG_WORK1, r, 16); // mov r2,r7,lsl #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + + RORS_rri(REG_WORK1, REG_WORK1, imm); // rors r2,r2,#(32 - (i & 0x1f)) + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(REG_WORK1, 1); // tst r2,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); + + BIC_rri(r, r, 0xff00); // bic r2,r2,#0xff00 + BIC_rri(r, r, 0xff); // bic r2,r2,#0xff + + ORR_rrrLSRi(r, r, REG_WORK1, 16); // orr r7,r7,r2,lsr #16 +} + +LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, RR1 r)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + + MOV_ri(REG_WORK2, 32); // mov r3,#32 + AND_rri(REG_WORK1, r, 0x1f); // and r2,r6,#0x1f + SUB_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // sub r3,r3,r2 + + MOV_rrLSLi(REG_WORK1, d, 16); // mov r2,r7,lsl #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + + RORS_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // rors r2,r2,r3 + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(REG_WORK1, 1); // tst r2,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); + + BIC_rri(d, d, 0xff00); // bic r2,r2,#0xff00 + BIC_rri(d, d, 0xff); // bic r2,r2,#0xff + + ORR_rrrLSRi(d, d, REG_WORK1, 16); // orr r2,r2,r7,lsr #16 +} + +LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + int imm = 32 - (i & 0x1f); + + RORS_rri(r, r, imm); // rors r7,r7,#(32 - (i & 0x1f)) + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(r, 1); // tst r7,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); +} + +LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) +{ + RORS_rri(r, r, i & 0x1F); // RORS r7,r7,#12 +} + +LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, RR1 r)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + + MOV_ri(REG_WORK1, 32); // mov r2,#32 + AND_rri(REG_WORK2, r, 0x1f); // and r3,r6,#0x1f + SUB_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // sub r2,r2,r3 + + RORS_rrr(d, d, REG_WORK1); // rors r7,r7,r2 + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(d, 1); // tst r7,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); +} + +LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, RR1 r)) +{ + RORS_rrr(d, d, r); // RORS r7,r7,r6 +} + +LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) +{ + MOV_rrLSLi(REG_WORK1, r, 24); // mov r2,r7,lsl #24 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 8); // orr r2,r2,r2,lsr #8 + + RORS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // rors r2,r2,#12 + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(r, r, 0xff); // bic r7,r7,#0xff + ORR_rrr(r, r, REG_WORK1); // orr r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, RR1 r)) +{ + MOV_rrLSLi(REG_WORK1, d, 24); // mov r2,r7,lsl #24 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 8); // orr r2,r2,r2,lsr #8 + + RORS_rrr(REG_WORK1, REG_WORK1, r); // rors r2,r2,r6 + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(d, d, 0xff); // bic r7,r7,#0xff + ORR_rrr(d, d, REG_WORK1); // orr r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) +{ + MOV_rrLSLi(REG_WORK1, r, 16); // mov r2,r7,lsl #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + + RORS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // RORS r2,r2,#12 + + BIC_rri(r, r, 0xff00); // bic r7,r7,#0xff00 + BIC_rri(r, r, 0xff); // bic r7,r7,#0xff + + ORR_rrrLSRi(r, r, REG_WORK1, 16); // orr r7,r7,r2,lsr #16 +} + +LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, RR1 r)) +{ + MOV_rrLSLi(REG_WORK1, d, 16); // mov r2,r7,lsl #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + + RORS_rrr(REG_WORK1, REG_WORK1, r); // RORS r2,r2,r6 + + BIC_rri(d, d, 0xff00); // bic r7,r7,#0xff00 + BIC_rri(d, d, 0xff); // bic r7,r7,#0xff + + ORR_rrrLSRi(d, d, REG_WORK1, 16); // orr r7,r7,r2,lsr #16 +} + +LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, RR1 s)) +{ + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + + LSL_rri(REG_WORK2, d, 24); // lsl r3, %[d], #24 + LSL_rri(REG_WORK1, s, 24); // lsl r2, r6, #24 + + SBCS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + BIC_rri(d, d, 0xFF); + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr r7, r7, r3 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, RR4 s)) +{ + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + + SBCS_rrr(d, d, s); // sbcs r7, r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, RR2 s)) +{ + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + + LSL_rri(REG_WORK2, d, 16); // lsl r3, %[d], #24 + LSL_rri(REG_WORK1, s, 16); // lsl r2, r6, #16 + + SBCS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + BIC_rri(d,d, 0xff); + BIC_rri(d,d, 0xff00); + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr r7, r7, r3 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) +{ + switch (cc) { + case 9: // LS + BEQ_i(0); // beq + BCC_i(1); // bcs + + MOV_ri(d, 1); // mov r7,#0 + B_i(0); // b + + //: + MOV_ri(d, 0); // mov r7,#1 + break; + + case 8: // HI + BEQ_i(2); // beq Z != 0 + BCS_i(1); // bcc C = 0 + + //: + MOV_ri(d, 1); // mov r7,#0 + B_i(0); // b + + //: + MOV_ri(d, 0); // mov r7,#1 + break; + + default: + CC_MOV_ri(cc, d, 1); // MOVcc R7,#1 + CC_MOV_ri(cc^1, d, 0); // MOVcc^1 R7,#0 + break; + } + //: +} + +LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) +{ + switch (cc) { + case 9: // LS + BEQ_i(0); // beq + BCC_i(1); // bcs + + MOV_ri(REG_WORK1, 1); // mov r2,#0 + B_i(0); // b + + //: + MOV_ri(REG_WORK1, 0); // mov r2,#1 + break; + + case 8: // HI + BEQ_i(2); // beq Z != 0 + BCS_i(1); // bcc C = 0 + + MOV_ri(REG_WORK1, 1); // mov r2,#0 + B_i(0); // b + + //: + MOV_ri(REG_WORK1, 0); // mov r2,#1 + break; + + default: + CC_MOV_ri(cc, REG_WORK1, 1); // MOVcc R2,#1 + CC_MOV_ri(cc^1, REG_WORK1, 0); // MOVcc^1 R2,#0 + break; + } + //: +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // LDR R3,[PC, #offs] +#else + LDR_rRI(REG_WORK2, RPC_INDEX, 4); // LDR R3,[PC, #4] +#endif + STRB_rR(REG_WORK1, REG_WORK2); // STRB R2,[R3] +#if !defined(USE_DATA_BUFFER) + B_i(0); // B + + emit_long(d); + //: +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) +{ + LSL_rri(REG_WORK1, r, 24); // LSL r2,r7,#24 + + LSLS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // LSLS r2,r2,#12 + + BIC_rri(r, r, 0xff); // BIC r7,r7,0xff + ORR_rrrLSRi(r, r, REG_WORK1, 24); // ORR r7,r7,r2,lsr #24 +} + +LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, RR1 r)) +{ + LSL_rri(REG_WORK1, d, 24); // LSL r2,r7,#24 + LSLS_rrr(REG_WORK1, REG_WORK1, r); // LSLS r2,r2,r6 + BIC_rri(d, d, 0xff); // BIC r7,r7,#0xff + ORR_rrrLSRi(d, d, REG_WORK1, 24); // ORR r7,r7,r2,lsr #24 +} + +LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) +{ + LSLS_rri(r,r, i & 0x1f); // lsls r7,r7,#12 +} + +LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, RR1 r)) +{ + LSLS_rrr(d, d, r); +} + +LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) +{ + LSL_rri(REG_WORK1, r, 16); // LSL r2,r7,#16 + LSLS_rri(REG_WORK1, REG_WORK1, i&0x1f); // LSLS r2,r2,#12 + + ORR_rrrLSRi(REG_WORK1, REG_WORK1, r, 16); // ORR r2,r2,r7,lsr #16 + + ROR_rri(r, REG_WORK1, 16); // ROR r7,r2,#16 +} + +LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, RR1 r)) +{ + LSL_rri(REG_WORK1, d, 16); // LSL r2,r7,#16 + LSLS_rrr(REG_WORK1, REG_WORK1, r); // LSLS r2,r2,r6 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, d, 16); // ORR r2,r2,r7,lsr #16 + ROR_rri(d, REG_WORK1, 16); // ROR r7,r2,#16 +} + +LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) +{ + LSL_rri(REG_WORK1, r, 24); // lsl r2,r7,#24 + ASR_rri(REG_WORK1, REG_WORK1, 24); // asr r2,r2,#24 + + ASRS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // asrs r2,r2,#12 + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(r,r, 0xff); // bic r7,r7,#0xff + ORR_rrr(r,r,REG_WORK1); // orr r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, RR1 r)) +{ + LSL_rri(REG_WORK1, d, 24); // lsl r2,r7,#24 + ASR_rri(REG_WORK1, REG_WORK1, 24); // asr r2,r2,#24 + + ASRS_rrr(REG_WORK1, REG_WORK1, r); // asrs r2,r2,r6 + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(d,d, 0xff); // bic r7,r7,#0xff + + ORR_rrr(d,d,REG_WORK1); // orr r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) +{ + LSL_rri(REG_WORK1, r, 16); // lsl r2,r7,#16 + ASR_rri(REG_WORK1, REG_WORK1, 16); // asr r2,r2,#16 + + ASRS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // asrs r2,r2,#12 + +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, REG_WORK1); +#else + BIC_rri(REG_WORK1, REG_WORK1, 0xff000000); + BIC_rri(REG_WORK1, REG_WORK1, 0xff0000); +#endif + + BIC_rri(r,r,0xff00); // bic r7,r7,#0xff00 + BIC_rri(r,r,0xff); // bic r7,r7,#0xff + + ORR_rrr(r,r,REG_WORK1); // orr r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, RR1 r)) +{ + LSL_rri(REG_WORK1, d, 16); // lsl r2,r7,#16 + ASR_rri(REG_WORK1, REG_WORK1, 16); // asr r2,r2,#16 + + ASRS_rrr(REG_WORK1, REG_WORK1, r); // asrs r2,r2,r6 + +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, REG_WORK1); +#else + BIC_rri(REG_WORK1, REG_WORK1, 0xff000000); // bic r2,r2,#0xff000000 + BIC_rri(REG_WORK1, REG_WORK1, 0xff0000); // bic r2,r2,#0xff0000 +#endif + + BIC_rri(d,d, 0xff00); // bic r7,r7,#0xff00 + BIC_rri(d,d, 0xff); // bic r7,r7,#0xff + + ORR_rrr(d,d,REG_WORK1); // orr r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) +{ + ASRS_rri(r, r, i & 0x1f); // ASRS r7,r7,#12 +} + +LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, RR1 r)) +{ + ASRS_rrr(d, d, r); // ASRS r7,r7,r6 +} + +LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) +{ + AND_rri(REG_WORK1, r, 0xff); // AND r2,r7,#0xFF + + LSRS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // LSRS r2,r2,r6 + + BIC_rri(r, r, 0xFF); // BIC r7,r7,#0xff + ORR_rrr(r, r, REG_WORK1); // ORR r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, RR1 r)) +{ + AND_rri(REG_WORK1, d, 0xff); // AND r2,r7,#0xFF + + LSRS_rrr(REG_WORK1, REG_WORK1, r); // LSRS r2,r2,r6 + + BIC_rri(d, d, 0xFF); // BIC r7,r7,#0xff + ORR_rrr(d, d, REG_WORK1); // ORR r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) +{ + LSRS_rri(r, r, i & 0x1f); // LSRS r7,r7,#12 +} + +LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, r); +#else + BIC_rri(REG_WORK1, r, 0xff0000); // BIC r2,r7,#0xff0000 + BIC_rri(REG_WORK1, REG_WORK1, 0xff000000); // BIC r2,r2,#0xff000000 +#endif + + LSRS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // LSRS r2,r2,#12 + + BIC_rri(r, r, 0xFF); // BIC r7,r7,#0xff + BIC_rri(r, r, 0xFF00); // BIC r7,r7,#0xff00 + ORR_rrr(r, r, REG_WORK1); // ORR r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, RR1 r)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, d); +#else + BIC_rri(REG_WORK1, d, 0xff0000); // BIC r2,r7,#0xff0000 + BIC_rri(REG_WORK1, REG_WORK1, 0xff000000); // BIC r2,r2,#0xff000000 +#endif + + LSRS_rrr(REG_WORK1, REG_WORK1, r); // LSRS r2,r2,r6 + + BIC_rri(d, d, 0xFF); // BIC r7,r7,#0xff + BIC_rri(d, d, 0xFF00); // BIC r7,r7,#0xff00 + ORR_rrr(d, d, REG_WORK1); // ORR r7,r7,r2 +} + +LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, RR1 r)) +{ + LSRS_rrr(d, d, r); +} + +LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, RR1 s)) +{ + LSL_rri(REG_WORK1, s, 24); // lsl r2, r6, #24 + LSL_rri(REG_WORK2, d, 24); // lsl r3, r7, #24 + + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + BIC_rri(d, d, 0xFF); + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr r7, r7, r3 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) +{ + LSL_rri(REG_WORK2, d, 24); // lsl r3, r7, #24 + + SUBS_rri(REG_WORK2, REG_WORK2, i << 24); // subs r3, r3, #0x12000000 + BIC_rri(d, d, 0xFF); // bic r7, r7, #0xFF + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr r7, r7, r3, lsr #24 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, RR4 s)) +{ + SUBS_rrr(d, d, s); // subs r7, r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #16] ; +#endif + SUBS_rrr(d, d, REG_WORK1); // subs r7, r7, r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(i); + //: +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, RR2 s)) +{ + LSL_rri(REG_WORK1, s, 16); // lsl r2, r6, #16 + LSL_rri(REG_WORK2, d, 16); // lsl r3, r7, #16 + + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + BIC_rri(d, d, 0xff); + BIC_rri(d, d, 0xff00); + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr r7, r7, r3 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) +{ + // TODO: optimize_imm + +#if defined(USE_DATA_BUFFER) + long offs = data_word_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; +#else + LDRH_rRI(REG_WORK1, RPC_INDEX, 36); // ldrh r2, [pc, #36] ; +#endif + LSL_rri(REG_WORK1, REG_WORK1, 16); // lsl r2, r2, #16 + LSL_rri(REG_WORK2, d, 16); // lsl r3, r6, #16 + + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + BIC_rri(d, d, 0xff); + BIC_rri(d, d, 0xff00); + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr r6, r3, r6, lsr #16 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + emit_word(i); + skip_word(0); //: + + //: +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(RR1 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + SXTB_rr(REG_WORK1, s); + SXTB_rr(REG_WORK2, d); +#else + LSL_rri(REG_WORK1, s, 24); // lsl r2, r6, #24 + LSL_rri(REG_WORK2, d, 24); // lsl r3, r7, #24 +#endif + + TST_rr(REG_WORK2, REG_WORK1); // tst r3, r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(RR4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #16] ; +#endif + TST_rr(d, REG_WORK1); // tst r7, r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(i); + //: +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(RR4 d, RR4 s)) +{ + TST_rr(d, s); // tst r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(RR2 d, RR2 s)) +{ +#ifdef ARMV6_ASSEMBLY + SXTH_rr(REG_WORK1, s); + SXTH_rr(REG_WORK2, d); +#else + LSL_rri(REG_WORK1, s, 16); // lsl r2, r6, #16 + LSL_rri(REG_WORK2, d, 16); // lsl r3, r7, #16 +#endif + + TST_rr(REG_WORK2, REG_WORK1); // tst r3, r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, RR1 s)) +{ + AND_rri(REG_WORK1, s, 0xFF); // and r2, %[s], 0xFF + EOR_rrr(d, d, REG_WORK1); // eor %[d], %[d], r2 + LSLS_rri(REG_WORK1, d, 24); // lsls r2, %[d], #24 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, s); // UXTH r2, %[s] +#else + BIC_rri(REG_WORK1, s, 0xff000000); // bic r2, %[s], #0xff000000 + BIC_rri(REG_WORK1, REG_WORK1, 0x00ff0000); // bic r2, r2, #0x00ff0000 +#endif + EOR_rrr(d, d, REG_WORK1); // eor %[d], %[d], r2 + LSLS_rri(REG_WORK1, d, 16); // lsls r2, %[d], #16 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, RR4 s)) +{ + EORS_rrr(d, d, s); // eors r7, r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} + +LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + SXTH_rr(d, s); // sxth %[d],%[s] +#else + LSL_rri(d, s, 16); // lsl r6, r7, #16 + ASR_rri(d, d, 16); // asr r6, r6, #16 +#endif +} + +LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + SXTB_rr(d, s); // SXTB %[d],%[s] +#else + ROR_rri(d, s, 8); // ror r6, r7, #8 + ASR_rri(d, d, 24); // asr r6, r6, #24 +#endif +} + +LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(d, s); // UXTB %[d], %[s] +#else + ROR_rri(d, s, 8); // ror r2, r1, #8 + LSR_rri(d, d, 24); // lsr r2, r2, #24 +#endif +} + +LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(d, s); // UXTH %[d], %[s] +#else + BIC_rri(d, s, 0xff000000); // bic %[d], %[s], #0xff000000 + BIC_rri(d, d, 0x00ff0000); // bic %[d], %[d], #0x00ff0000 +#endif +} + +static inline void raw_dec_sp(int off) +{ + if (off) { + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + SUB_rrr(RSP_INDEX, RSP_INDEX, REG_WORK1); // sub r7, r7, r2 + B_i(0); // b + //: + emit_long(off); + } +} + +static inline void raw_inc_sp(int off) +{ + if (off) { + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + ADD_rrr(RSP_INDEX, RSP_INDEX, REG_WORK1); // sub r7, r7, r2 + B_i(0); // b + //: + emit_long(off); + } +} + +static inline void raw_push_regs_to_preserve(void) { + PUSH_REGS(PRESERVE_MASK); +} + +static inline void raw_pop_preserved_regs(void) { + POP_REGS(PRESERVE_MASK); +} + +// Verify!!! +/* FLAGX is byte sized, and we *do* write it at that size */ +static inline void raw_load_flagx(uae_u32 t) +{ + raw_mov_l_rm(t,(uintptr)live.state[FLAGX].mem); +} + +static inline void raw_flags_evicted(int r) +{ + //live.state[FLAGTMP].status=CLEAN; + live.state[FLAGTMP].status=INMEM; + live.state[FLAGTMP].realreg=-1; + /* We just "evicted" FLAGTMP. */ + if (live.nat[r].nholds!=1) { + /* Huh? */ + abort(); + } + live.nat[r].nholds=0; +} + +static inline void raw_flags_init(void) { +} + +static __inline__ void raw_flags_set_zero(int s, int tmp) +{ + raw_mov_l_rr(tmp,s); + MRS_CPSR(s); + BIC_rri(s,s,ARM_Z_FLAG); + AND_rri(tmp,tmp,ARM_Z_FLAG); + EOR_rri(tmp,tmp,ARM_Z_FLAG); + ORR_rrr(s,s,tmp); + MSR_CPSR_r(s); +} + +static inline void raw_flags_to_reg(int r) +{ + MRS_CPSR(r); + raw_mov_l_mr((uintptr)live.state[FLAGTMP].mem,r); + raw_flags_evicted(r); +} + +static inline void raw_reg_to_flags(int r) +{ + MSR_CPSR_r(r); // msr CPSR_fc, %r +} + +/* Apparently, there are enough instructions between flag store and + flag reload to avoid the partial memory stall */ +static inline void raw_load_flagreg(uae_u32 t) +{ + raw_mov_l_rm(t,(uintptr)live.state[FLAGTMP].mem); +} + +/* %eax register is clobbered if target processor doesn't support fucomi */ +#define FFLAG_NREG_CLOBBER_CONDITION !have_cmov +#define FFLAG_NREG R0_INDEX +#define FLAG_NREG2 -1 +#define FLAG_NREG1 -1 +#define FLAG_NREG3 -1 + +static inline void raw_fflags_into_flags(int r) +{ + jit_unimplemented("raw_fflags_into_flags %x", r); +} + +static inline void raw_fp_init(void) +{ + int i; + + for (i=0;i=1) { +// emit_byte(0xde); +// emit_byte(0xd9); + live.tos-=2; + } + while (live.tos>=0) { +// emit_byte(0xdd); +// emit_byte(0xd8); + live.tos--; + } + raw_fp_init(); +} + +LOWFUNC(NONE,WRITE,2,raw_fmov_mr_drop,(MEMPTRW m, FR r)) +{ + jit_unimplemented("raw_fmov_mr_drop %x %x", m, r); +} + +LOWFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMPTRW m, FR r)) +{ + jit_unimplemented("raw_fmov_mr %x %x", m, r); +} + +LOWFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMPTRR m)) +{ + jit_unimplemented("raw_fmov_rm %x %x", r, m); +} + +LOWFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) +{ + jit_unimplemented("raw_fmov_rr %x %x", d, s); +} + +static inline void raw_emit_nop_filler(int nbytes) +{ + nbytes >>= 2; + while(nbytes--) { NOP(); } +} + +static inline void raw_emit_nop(void) +{ + NOP(); +} + +#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)); +} + +// +// ARM doesn't have bsf, but clz is a good alternative instruction for it +// +static bool target_check_bsf(void) +{ + return false; +} + +static void raw_init_cpu(void) +{ + /* Have CMOV support, because ARM support conditions for all instructions */ + have_cmov = true; + + align_loops = 0; + align_jumps = 0; + + raw_flags_init(); +} + +// +// Arm instructions +// +LOWFUNC(WRITE,NONE,2,raw_ADD_l_rr,(RW4 d, RR4 s)) +{ + ADD_rrr(d, d, s); +} + +LOWFUNC(WRITE,NONE,2,raw_ADD_l_rri,(RW4 d, RR4 s, IMM i)) +{ + ADD_rri(d, s, i); +} + +LOWFUNC(WRITE,NONE,2,raw_SUB_l_rri,(RW4 d, RR4 s, IMM i)) +{ + SUB_rri(d, s, i); +} + +LOWFUNC(WRITE,NONE,2,raw_AND_b_rr,(RW1 d, RR1 s)) +{ + MVN_rrLSLi(REG_WORK1, s, 24); // mvn r2, %[s], lsl #24 + MVN_rrLSRi(REG_WORK1, REG_WORK1, 24); // mvn r2, %[s], lsr #24 + AND_rrr(d, d, REG_WORK1); // and %[d], %[d], r2 +} + +LOWFUNC(WRITE,NONE,2,raw_AND_l_rr,(RW4 d, RR4 s)) +{ + AND_rrr(d, d, s); +} + +LOWFUNC(WRITE,NONE,2,raw_AND_l_ri,(RW4 d, IMM i)) +{ + AND_rri(d, d, i); +} + +LOWFUNC(WRITE,NONE,2,raw_AND_w_rr,(RW2 d, RR2 s)) +{ + MVN_rrLSLi(REG_WORK1, s, 16); // mvn r2, %[s], lsl #16 + MVN_rrLSRi(REG_WORK1, REG_WORK1, 16); // mvn r2, %[s], lsr #16 + AND_rrr(d, d, REG_WORK1); // and %[d], %[d], r2 +} + +LOWFUNC(WRITE,NONE,2,raw_EOR_b_rr,(RW1 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(REG_WORK1, s); // UXTH r2, %[s] +#else + AND_rri(REG_WORK1, s, 0xFF); // and r2, %[s], 0xFF +#endif + EOR_rrr(d, d, REG_WORK1); // eor %[d], %[d], r2 +} + +LOWFUNC(WRITE,NONE,2,raw_EOR_l_rr,(RW4 d, RR4 s)) +{ + EOR_rrr(d, d, s); // eors r7, r7, r6 +} + +LOWFUNC(WRITE,NONE,2,raw_EOR_w_rr,(RW2 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, s); // UXTH r2, %[s] + EOR_rrr(d, d, REG_WORK1); // eor %[d], %[d], r2 +#else + LSL_rri(REG_WORK1, s, 16); // bic r2, %[s], #0xff000000 + EOR_rrrLSRi(d, d, REG_WORK1, 16); // orr %[d], %[d], r2 +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_LDR_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(d, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rR(d, RPC_INDEX); + B_i(0); + emit_long(i); +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_MOV_l_ri8,(RW4 d, IMM i)) +{ + MOV_ri(d, i); +} + +LOWFUNC(WRITE,NONE,2,raw_ORR_b_rr,(RW1 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(REG_WORK1, s); // UXTH r2, %[s] +#else + AND_rri(REG_WORK1, s, 0xFF); // and r2, %[s], 0xFF +#endif + ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 +} + +LOWFUNC(WRITE,NONE,2,raw_ORR_l_rr,(RW4 d, RR4 s)) +{ + ORR_rrr(d, d, s); +} + +LOWFUNC(WRITE,NONE,2,raw_ORR_w_rr,(RW2 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, s); // UXTH r2, %[s] + ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 +#else + LSL_rri(REG_WORK1, s, 16); // bic r2, %[s], #0xff000000 + ORR_rrrLSRi(d, d, REG_WORK1, 16); // orr %[d], %[d], r2 +#endif +} + +LOWFUNC(WRITE,NONE,2,raw_ROR_l_ri,(RW4 r, IMM i)) +{ + ROR_rri(r, r, i); +} + +// +// compuemu_support used raw calls +// +LOWFUNC(WRITE,RMW,2,compemu_raw_add_l_mi,(IMM d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + data_check_end(8, 24); + long target = data_long(d, 24); + long offs = get_data_offset(target); + + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + LDR_rR(REG_WORK2, REG_WORK1); // ldr r3, [r2] + + offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; s + + ADD_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 + + offs = get_data_offset(target); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 20); // ldr r2, [pc, #20] ; + LDR_rR(REG_WORK2, REG_WORK1); // ldr r3, [r2] + + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #16] ; + + ADD_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 + + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] + + B_i(1); // b + + //: + emit_long(d); + //: + emit_long(s); + //: +#endif +} + +LOWFUNC(WRITE,NONE,2,compemu_raw_and_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + AND_rrr(d, d, REG_WORK1); // ands %[d], %[d], r2 +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #16] ; + AND_rrr(d, d, REG_WORK1); // ands %[d], %[d], r2 + B_i(0); + emit_long(i); +#endif +} + +LOWFUNC(NONE,NONE,1,compemu_raw_bswap_32,(RW4 r)) +{ +#if defined(ARMV6_ASSEMBLY) + REV_rr(r,r); // rev %[r],%[r] +#else + EOR_rrrRORi(REG_WORK1, r, r, 16); // eor r2, r6, r6, ror #16 + BIC_rri(REG_WORK1, REG_WORK1, 0xff0000); // bic r2, r2, #0xff0000 + ROR_rri(r, r, 8); // ror r6, r6, #8 + EOR_rrrLSRi(r, r, REG_WORK1, 8); // eor r6, r6, r2, lsr #8 +#endif +} + +LOWFUNC(WRITE,NONE,2,compemu_raw_bt_l_ri,(RR4 r, IMM i)) +{ + int imm = (1 << (i & 0x1f)); + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_ri(r, imm); // tst r6, #0x1000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} + +LOWFUNC(NONE,READ,5,compemu_raw_cmov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor, IMM cond)) +{ + int shft; + switch(factor) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + + switch (cond) { + case 9: // LS + jit_unimplemented("cmov LS not implemented"); + abort(); + case 8: // HI + jit_unimplemented("cmov HI not implemented"); + abort(); + default: +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(base); + CC_LDR_rRI(cond, REG_WORK1, RPC_INDEX, offs); // ldrcc r2, [pc, #offs] ; + CC_LDR_rRR_LSLi(cond, d, REG_WORK1, index, shft); // ldrcc %[d], [r2, %[index], lsl #[shift]] +#else + CC_LDR_rRI(cond, REG_WORK1, RPC_INDEX, 4); // ldrcc r2, [pc, #4] ; + CC_LDR_rRR_LSLi(cond, d, REG_WORK1, index, shft); // ldrcc %[d], [r2, %[index], lsl #[shift]] + B_i(0); // b +#endif + break; + } +#if !defined(USE_DATA_BUFFER) + emit_long(base); // : + //: +#endif +} + +LOWFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi,(MEMR d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + data_check_end(8, 16); + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + LDR_rR(REG_WORK1, REG_WORK1); // ldr r2, [r2] + + offs = data_long_offs(s); + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // ldr r3, [pc, #offs] ; s + + CMP_rr(REG_WORK1, REG_WORK2); // cmp r2, r3 + +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 12); // ldr r2, [pc, #24] ; + LDR_rR(REG_WORK1, REG_WORK1); // ldr r2, [r2] + + LDR_rRI(REG_WORK2, RPC_INDEX, 8); // ldr r3, [pc, #20] ; + + CMP_rr(REG_WORK1, REG_WORK2); // cmp r2, r3 + + B_i(1); // b + + //: + emit_long(d); + //: + emit_long(s); + //: +#endif +} + +LOWFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi8,(MEMR d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // ldr r2, [pc, #8] ; +#endif + LDR_rR(REG_WORK1, REG_WORK1); // ldr r2, [r2] + + CMP_ri(REG_WORK1, s); // cmp r2, r3 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} + +LOWFUNC(NONE,NONE,3,compemu_raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + ADD_rrr(d, s, REG_WORK1); // add r7, r6, r2 +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + ADD_rrr(d, s, REG_WORK1); // add r7, r6, r2 + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} + +LOWFUNC(NONE,NONE,4,compemu_raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) +{ + int shft; + switch(factor) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + + ADD_rrrLSLi(d, s, index, shft); // ADD R7,R6,R5,LSL #2 +} + +LOWFUNC(NONE,WRITE,2,compemu_raw_mov_b_mr,(IMM d, RR1 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + STRB_rR(s, REG_WORK1); // strb r6, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STRB_rR(s, REG_WORK1); // strb r6, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} + +LOWFUNC(NONE,WRITE,2,compemu_raw_mov_l_mi,(MEMW d, IMM s)) +{ + // TODO: optimize imm + +#if defined(USE_DATA_BUFFER) + data_check_end(8, 12); + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + offs = data_long_offs(s); + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // ldr r3, [pc, #offs] ; s + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // ldr r2, [pc, #8] ; + LDR_rRI(REG_WORK2, RPC_INDEX, 8); // ldr r3, [pc, #8] ; + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] + B_i(1); // b + + emit_long(d); //: + emit_long(s); //: + + //: +#endif +} + +LOWFUNC(NONE,WRITE,2,compemu_raw_mov_l_mr,(IMM d, RR4 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + STR_rR(s, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STR_rR(s, REG_WORK1); // str r3, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} + +LOWFUNC(NONE,NONE,2,compemu_raw_mov_l_ri,(W4 d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(s); + LDR_rRI(d, RPC_INDEX, offs); // ldr %[d], [pc, #offs] ; +#else + LDR_rR(d, RPC_INDEX); // ldr %[d], [pc] ; + B_i(0); // b + + //: + emit_long(s); + //: +#endif +} + +LOWFUNC(NONE,READ,2,compemu_raw_mov_l_rm,(W4 d, MEMR s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + LDR_rR(d, REG_WORK1); // ldr r7, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + LDR_rR(d, REG_WORK1); // ldr r7, [r2] + B_i(0); // b + + emit_long(s); //: + //: +#endif +} + +LOWFUNC(NONE,NONE,2,compemu_raw_mov_l_rr,(W4 d, RR4 s)) +{ + MOV_rr(d, s); // mov %[d], %[s] +} + +LOWFUNC(NONE,WRITE,2,compemu_raw_mov_w_mr,(IMM d, RR2 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + STRH_rR(s, REG_WORK1); // strh r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STRH_rR(s, REG_WORK1); // strh r3, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} + +LOWFUNC(WRITE,RMW,2,compemu_raw_sub_l_mi,(MEMRW d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + data_check_end(8, 24); + long target = data_long(d, 24); + long offs = get_data_offset(target); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + LDR_rR(REG_WORK2, REG_WORK1); // ldr r3, [r2] + + offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; s + + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + + offs = get_data_offset(target); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 20); // ldr r2, [pc, #32] ; + LDR_rR(REG_WORK2, REG_WORK1); // ldr r3, [r2] + + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #28] ; + + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #16] ; + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] + + B_i(1); // b + + //: + emit_long(d); + //: + emit_long(s); + //: +#endif +} + +LOWFUNC(WRITE,NONE,2,compemu_raw_test_l_rr,(RR4 d, RR4 s)) +{ + TST_rr(d, s); // tst r7, r6 +} + +LOWFUNC(NONE,NONE,2,compemu_raw_zero_extend_16_rr,(W4 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(d, s); // UXTH %[d], %[s] +#else + BIC_rri(d, s, 0xff000000); // bic %[d], %[s], #0xff000000 + BIC_rri(d, d, 0x00ff0000); // bic %[d], %[d], #0x00ff0000 +#endif +} + +static inline void compemu_raw_call(uae_u32 t) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(t); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 12); // ldr r2, [pc, #12] ; +#endif + PUSH(RLR_INDEX); // push {lr} + BLX_r(REG_WORK1); // blx r2 + POP(RLR_INDEX); // pop {lr} +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(t); + //: +#endif +} + +#if defined(UAE) +static inline void compemu_raw_call_r(RR4 r) +{ + PUSH(RLR_INDEX); // push {lr} + BLX_r(r); // blx r0 + POP(RLR_INDEX); // pop {lr} +} +#endif + +static inline void compemu_raw_jcc_l_oponly(int cc) +{ + switch (cc) { + case 9: // LS + BEQ_i(0); // beq + BCC_i(2); // bcc + + //: + LDR_rR(REG_WORK1, RPC_INDEX); // ldr r2, [pc] ; + BX_r(REG_WORK1); // bx r2 + break; + + case 8: // HI + BEQ_i(3); // beq + BCS_i(2); // bcs + + //: + LDR_rR(REG_WORK1, RPC_INDEX); // ldr r2, [pc] ; + BX_r(REG_WORK1); // bx r2 + break; + + default: + CC_LDR_rRI(cc, REG_WORK1, RPC_INDEX, 4); // ldrlt r2, [pc, #4] ; + CC_BX_r(cc, REG_WORK1); // bxlt r2 + B_i(0); // b + break; + } + // emit of target will be done by caller +} + +static inline void compemu_raw_jl(uae_u32 t) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(t); + CC_LDR_rRI(NATIVE_CC_LT, RPC_INDEX, RPC_INDEX, offs); // ldrlt pc, [pc, offs] +#else + CC_LDR_rR(NATIVE_CC_LT, RPC_INDEX, RPC_INDEX); // ldrlt pc, [pc] + B_i(0); // b + + //: + emit_long(t); + //: +#endif +} + +static inline void compemu_raw_jmp(uae_u32 t) +{ + LDR_rR(REG_WORK1, RPC_INDEX); // ldr r2, [pc] + BX_r(REG_WORK1); // bx r2 + emit_long(t); +} + +static inline void compemu_raw_jmp_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m) +{ + int shft; + switch(m) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + + LDR_rR(REG_WORK1, RPC_INDEX); // ldr r2, [pc] ; + LDR_rRR_LSLi(RPC_INDEX, REG_WORK1, r, shft); // ldr pc, [r2, r6, lsl #3] + emit_long(base); +} + +static inline void compemu_raw_jmp_r(RR4 r) +{ + BX_r(r); +} + +static inline void compemu_raw_jnz(uae_u32 t) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(t); + CC_LDR_rRI(NATIVE_CC_NE, RPC_INDEX, RPC_INDEX, offs); // ldrne pc, [pc, offs] +#else + CC_LDR_rR(NATIVE_CC_NE, RPC_INDEX, RPC_INDEX); // ldrne pc, [pc] + B_i(0); // b + + emit_long(t); + //: +#endif +} + +static inline void compemu_raw_jz_b_oponly(void) +{ + BNE_i(2); // bne jp + LDRSB_rRI(REG_WORK1, RPC_INDEX, 3); // ldrsb r2,[pc,#3] + ADD_rrr(RPC_INDEX, RPC_INDEX, REG_WORK1); // add pc,pc,r2 + + skip_n_bytes(3); /* additionally 1 byte skipped by generic code */ + + // +} + +static inline void compemu_raw_jnz_b_oponly(void) +{ + BEQ_i(2); // beq jp + LDRSB_rRI(REG_WORK1, RPC_INDEX, 3); // ldrsb r2,[pc,#3] + ADD_rrr(RPC_INDEX, RPC_INDEX, REG_WORK1); // add pc,pc,r2 + + skip_n_bytes(3); /* additionally 1 byte skipped by generic code */ + + // +} + +static inline void compemu_raw_branch(IMM d) +{ + B_i((d >> 2) - 1); +} diff --git a/jit/codegen_arm.h b/jit/codegen_arm.h new file mode 100644 index 00000000..e04ab9b8 --- /dev/null +++ b/jit/codegen_arm.h @@ -0,0 +1,1292 @@ +/* + * compiler/codegen_arm.h - IA-32 and AMD64 code generator + * + * Copyright (c) 2013 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * JIT compiler m68k -> ARM + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * This file is derived from CCG, copyright 1999-2003 Ian Piumarta + * Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne + * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ARM_RTASM_H +#define ARM_RTASM_H + +/* NOTES + * + */ + +/* --- Configuration ------------------------------------------------------- */ + +/* CPSR flags */ + +#define ARM_N_FLAG 0x80000000 +#define ARM_Z_FLAG 0x40000000 +#define ARM_C_FLAG 0x20000000 +#define ARM_V_FLAG 0x10000000 +#define ARM_Q_FLAG 0x08000000 +#define ARM_CV_FLAGS (ARM_C_FLAG|ARM_V_FLAG) + +#define ARM_GE3 0x00080000 +#define ARM_GE2 0x00040000 +#define ARM_GE1 0x00020000 +#define ARM_GE0 0x00010000 + +/* --- Macros -------------------------------------------------------------- */ + +/* ========================================================================= */ +/* --- UTILITY ------------------------------------------------------------- */ +/* ========================================================================= */ + +#define _W(c) emit_long(c) +#define _LS2_ADDR(a) (((a) & 0x01f0000f) | (((a) & 0xf0) << 4)) + +/* ========================================================================= */ +/* --- ENCODINGS ----------------------------------------------------------- */ +/* ========================================================================= */ + +#define IMM32(c) (((c) & 0xffffff00) == 0 ? (c) : \ + ((c) & 0x3fffffc0) == 0 ? (0x100 | (((c) >> 30) & 0x3) | ((((c) & 0x0000003f) << 2))) : \ + ((c) & 0x0ffffff0) == 0 ? (0x200 | (((c) >> 28) & 0xf) | ((((c) & 0x0000000f) << 4))) : \ + ((c) & 0x03fffffc) == 0 ? (0x300 | (((c) >> 26) & 0x3f) | ((((c) & 0x00000003) << 6)) ) : \ + ((c) & 0x00ffffff) == 0 ? (0x400 | (((c) >> 24) & 0xff)) : \ + ((c) & 0xc03fffff) == 0 ? (0x500 | ((c) >> 22)) : \ + ((c) & 0xf00fffff) == 0 ? (0x600 | ((c) >> 20)) : \ + ((c) & 0xfc03ffff) == 0 ? (0x700 | ((c) >> 18)) : \ + ((c) & 0xff00ffff) == 0 ? (0x800 | ((c) >> 16)) : \ + ((c) & 0xffc03fff) == 0 ? (0x900 | ((c) >> 14)) : \ + ((c) & 0xfff00fff) == 0 ? (0xa00 | ((c) >> 12)) : \ + ((c) & 0xfffc03ff) == 0 ? (0xb00 | ((c) >> 10)) : \ + ((c) & 0xffff00ff) == 0 ? (0xc00 | ((c) >> 8)) : \ + ((c) & 0xffffc03f) == 0 ? (0xd00 | ((c) >> 6)) : \ + ((c) & 0xfffff00f) == 0 ? (0xe00 | ((c) >> 4)) : \ + ((c) & 0xfffffc03) == 0 ? (0xf00 | ((c) >> 2)) : \ + 0\ + ) + +#define SHIFT_IMM(c) (0x02000000 | (IMM32((c)))) + +#define UNSHIFTED_IMM8(c) (0x02000000 | (c)) +#define SHIFT_IMM8_ROR(c,r) (0x02000000 | (c) | ((r >> 1) << 8)) + +#define SHIFT_REG(Rm) (Rm) +#define SHIFT_LSL_i(Rm,s) ((Rm) | ((s) << 7)) +#define SHIFT_LSL_r(Rm,Rs) ((Rm) | ((Rs) << 8) | 0x10) +#define SHIFT_LSR_i(Rm,s) ((Rm) | ((s) << 7) | 0x20) +#define SHIFT_LSR_r(Rm,Rs) ((Rm) | ((Rs) << 8) | 0x30) +#define SHIFT_ASR_i(Rm,s) ((Rm) | ((s) << 7) | 0x40) +#define SHIFT_ASR_r(Rm,Rs) ((Rm) | ((Rs) << 8) | 0x50) +#define SHIFT_ROR_i(Rm,s) ((Rm) | ((s) << 7) | 0x60) +#define SHIFT_ROR_r(Rm,Rs) ((Rm) | ((Rs) << 8) | 0x70) +#define SHIFT_RRX(Rm) ((Rm) | 0x60) +#define SHIFT_PK(Rm,s) ((Rm) | ((s) << 7)) + +/* Load/Store addressings */ +#define ADR_ADD(v) ((1 << 23) | (v)) +#define ADR_SUB(v) (v) + +#define ADR_IMM(v) ((v) | (1 << 24)) +#define ADR_IMMPOST(v) (v) +#define ADR_REG(Rm) ((1 << 25) | (1 << 24) | (Rm)) +#define ADR_REGPOST(Rm) ((1 << 25) | (Rm)) + +#define ADD_IMM(i) ADR_ADD(ADR_IMM(i)) +#define SUB_IMM(i) ADR_SUB(ADR_IMM(i)) + +#define ADD_REG(Rm) ADR_ADD(ADR_REG(Rm)) +#define SUB_REG(Rm) ADR_SUB(ADR_REG(Rm)) + +#define ADD_LSL(Rm,i) ADR_ADD(ADR_REG(Rm) | ((i) << 7)) +#define SUB_LSL(Rm,i) ADR_SUB(ADR_REG(Rm) | ((i) << 7)) + +#define ADD_LSR(Rm,i) ADR_ADD(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (1 << 5)) +#define SUB_LSR(Rm,i) ADR_SUB(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (1 << 5)) + +#define ADD_ASR(Rm,i) ADR_ADD(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (2 << 5)) +#define SUB_ASR(Rm,i) ADR_SUB(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (2 << 5)) + +#define ADD_ROR(Rm,i) ADR_ADD(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (3 << 5)) +#define SUB_ROR(Rm,i) ADR_SUB(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (3 << 5)) + +#define ADD_RRX(Rm) ADR_ADD(ADR_REG(Rm) | (3 << 5)) +#define SUB_RRX(Rm) ADR_SUB(ADR_REG(Rm) | (3 << 5)) + +#define ADD2_IMM(i) ADR_ADD(i | (1 << 22)) +#define SUB2_IMM(i) ADR_SUB(i | (1 << 22)) + +#define ADD2_REG(Rm) ADR_ADD(Rm) +#define SUB2_REG(Rm) ADR_SUB(Rm) + +/* MOV, MVN */ +#define _OP1(cc,op,s,Rd,shift) _W(((cc) << 28) | ((op) << 21) | ((s) << 20) | ((Rd) << 12) | (shift)) + +/* CMP, CMN, TST, TEQ */ +#define _OP2(cc,op,Rn,shift) _W(((cc) << 28) | ((op) << 21) | (1 << 20) | ((Rn) << 16) | (shift)) + +/* ADD, SUB, RSB, ADC, SBC, RSC, AND, BIC, EOR, ORR */ +#define _OP3(cc,op,s,Rd,Rn,shift) _W(((cc) << 28) | ((op) << 21) | ((s) << 20) | ((Rn) << 16) | ((Rd) << 12) | (shift)) + +/* LDR, STR */ +#define _LS1(cc,l,b,Rd,Rn,a) _W(((cc) << 28) | (0x01 << 26) | ((l) << 20) | ((b) << 22) | ((Rn) << 16) | ((Rd) << 12) | (a)) +#define _LS2(cc,p,l,s,h,Rd,Rn,a) _W(((cc) << 28) | ((p) << 24) | ((l) << 20) | ((Rn) << 16) | ((Rd) << 12) | ((s) << 6) | ((h) << 5) | 0x90 | _LS2_ADDR((a))) + +/* ========================================================================= */ +/* --- OPCODES ------------------------------------------------------------- */ +/* ========================================================================= */ + +/* Branch instructions */ +#ifndef __ANDROID__ +enum { + _B, _BL, _BLX, _BX, _BXJ +}; +#endif + +/* Data processing instructions */ +enum { + _AND = 0, + _EOR, + _SUB, + _RSB, + _ADD, + _ADC, + _SBC, + _RSC, + _TST, + _TEQ, + _CMP, + _CMN, + _ORR, + _MOV, + _BIC, + _MVN +}; + +/* Single instruction Multiple Data (SIMD) instructions */ + +/* Multiply instructions */ + +/* Parallel instructions */ + +/* Extend instructions */ + +/* Miscellaneous arithmetic instrations */ + +/* Status register transfer instructions */ + +/* Load and Store instructions */ + +/* Coprocessor instructions */ + +/* Exception generation instructions */ + +/* ========================================================================= */ +/* --- ASSEMBLER ----------------------------------------------------------- */ +/* ========================================================================= */ + +#define NOP() _W(0xe1a00000) +#define SETEND_BE() _W(0xf1010200) +#define SETEND_LE() _W(0xf1010000) + +/* Data processing instructions */ + +/* Opcodes Type 1 */ +/* MOVcc rd,#i */ +#define CC_MOV_ri8(cc,Rd,i) _OP1(cc,_MOV,0,Rd,UNSHIFTED_IMM8(i)) +/* MOVcc Rd,#i ROR #s */ +#define CC_MOV_ri8RORi(cc,Rd,i,s) _OP1(cc,_MOV,0,Rd,SHIFT_IMM8_ROR(i,s)) +#define CC_MOV_ri(cc,Rd,i) _OP1(cc,_MOV,0,Rd,SHIFT_IMM(i)) +#define CC_MOV_rr(cc,Rd,Rm) _OP1(cc,_MOV,0,Rd,SHIFT_REG(Rm)) +#define CC_MOV_rrLSLi(cc,Rd,Rm,i) _OP1(cc,_MOV,0,Rd,SHIFT_LSL_i(Rm,i)) +#define CC_MOV_rrLSLr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,0,Rd,SHIFT_LSL_r(Rm,Rs)) +#define CC_MOV_rrLSRi(cc,Rd,Rm,i) _OP1(cc,_MOV,0,Rd,SHIFT_LSR_i(Rm,i)) +#define CC_MOV_rrLSRr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,0,Rd,SHIFT_LSR_r(Rm,Rs)) +#define CC_MOV_rrASRi(cc,Rd,Rm,i) _OP1(cc,_MOV,0,Rd,SHIFT_ASR_i(Rm,i)) +#define CC_MOV_rrASRr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,0,Rd,SHIFT_ASR_r(Rm,Rs)) +#define CC_MOV_rrRORi(cc,Rd,Rm,i) _OP1(cc,_MOV,0,Rd,SHIFT_ROR_i(Rm,i)) +#define CC_MOV_rrRORr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,0,Rd,SHIFT_ROR_r(Rm,Rs)) +#define CC_MOV_rrRRX(cc,Rd,Rm) _OP1(cc,_MOV,0,Rd,SHIFT_RRX(Rm)) + +/* MOV rd,#i */ +#define MOV_ri8(Rd,i) CC_MOV_ri8(NATIVE_CC_AL,Rd,i) +/* MOV Rd,#i ROR #s */ +#define MOV_ri8RORi(Rd,i,s) CC_MOV_ri8RORi(NATIVE_CC_AL,Rd,i,s) +#define MOV_ri(Rd,i) CC_MOV_ri(NATIVE_CC_AL,Rd,i) +#define MOV_rr(Rd,Rm) CC_MOV_rr(NATIVE_CC_AL,Rd,Rm) +#define MOV_rrLSLi(Rd,Rm,i) CC_MOV_rrLSLi(NATIVE_CC_AL,Rd,Rm,i) +#define MOV_rrLSLr(Rd,Rm,Rs) CC_MOV_rrLSLr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOV_rrLSRi(Rd,Rm,i) CC_MOV_rrLSRi(NATIVE_CC_AL,Rd,Rm,i) +#define MOV_rrLSRr(Rd,Rm,Rs) CC_MOV_rrLSRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOV_rrASRi(Rd,Rm,i) CC_MOV_rrASRi(NATIVE_CC_AL,Rd,Rm,i) +#define MOV_rrASRr(Rd,Rm,Rs) CC_MOV_rrASRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOV_rrRORi(Rd,Rm,i) CC_MOV_rrRORi(NATIVE_CC_AL,Rd,Rm,i) +#define MOV_rrRORr(Rd,Rm,Rs) CC_MOV_rrRORr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOV_rrRRX(Rd,Rm) CC_MOV_rrRRX(NATIVE_CC_AL,Rd,Rm) + +#define CC_MOVS_ri(cc,Rd,i) _OP1(cc,_MOV,1,Rd,SHIFT_IMM(i)) +#define CC_MOVS_rr(cc,Rd,Rm) _OP1(cc,_MOV,1,Rd,SHIFT_REG(Rm)) +#define CC_MOVS_rrLSLi(cc,Rd,Rm,i) _OP1(cc,_MOV,1,Rd,SHIFT_LSL_i(Rm,i)) +#define CC_MOVS_rrLSLr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,1,Rd,SHIFT_LSL_r(Rm,Rs)) +#define CC_MOVS_rrLSRi(cc,Rd,Rm,i) _OP1(cc,_MOV,1,Rd,SHIFT_LSR_i(Rm,i)) +#define CC_MOVS_rrLSRr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,1,Rd,SHIFT_LSR_r(Rm,Rs)) +#define CC_MOVS_rrASRi(cc,Rd,Rm,i) _OP1(cc,_MOV,1,Rd,SHIFT_ASR_i(Rm,i)) +#define CC_MOVS_rrASRr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,1,Rd,SHIFT_ASR_r(Rm,Rs)) +#define CC_MOVS_rrRORi(cc,Rd,Rm,i) _OP1(cc,_MOV,1,Rd,SHIFT_ROR_i(Rm,i)) +#define CC_MOVS_rrRORr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,1,Rd,SHIFT_ROR_r(Rm,Rs)) +#define CC_MOVS_rrRRX(cc,Rd,Rm) _OP1(cc,_MOV,1,Rd,SHIFT_RRX(Rm)) + +#define MOVS_ri(Rd,i) CC_MOVS_ri(NATIVE_CC_AL,Rd,i) +#define MOVS_rr(Rd,Rm) CC_MOVS_rr(NATIVE_CC_AL,Rd,Rm) +#define MOVS_rrLSLi(Rd,Rm,i) CC_MOVS_rrLSLi(NATIVE_CC_AL,Rd,Rm,i) +#define MOVS_rrLSLr(Rd,Rm,Rs) CC_MOVS_rrLSLr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOVS_rrLSRi(Rd,Rm,i) CC_MOVS_rrLSRi(NATIVE_CC_AL,Rd,Rm,i) +#define MOVS_rrLSRr(Rd,Rm,Rs) CC_MOVS_rrLSRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOVS_rrASRi(Rd,Rm,i) CC_MOVS_rrASRi(NATIVE_CC_AL,Rd,Rm,i) +#define MOVS_rrASRr(Rd,Rm,Rs) CC_MOVS_rrASRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOVS_rrRORi(Rd,Rm,i) CC_MOVS_rrRORi(NATIVE_CC_AL,Rd,Rm,i) +#define MOVS_rrRORr(Rd,Rm,Rs) CC_MOVS_rrRORr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOVS_rrRRX(Rd,Rm) CC_MOVS_rrRRX(NATIVE_CC_AL,Rd,Rm) + +/* MVNcc rd,#i */ +#define CC_MVN_ri8(cc,Rd,i) _OP1(cc,_MVN,0,Rd,UNSHIFTED_IMM8(i)) +/* MVNcc Rd,#i ROR #s */ +#define CC_MVN_ri8RORi(cc,Rd,i,s) _OP1(cc,_MVN,0,Rd,SHIFT_IMM8_ROR(i,s)) +#define CC_MVN_ri(cc,Rd,i) _OP1(cc,_MVN,0,Rd,SHIFT_IMM(i)) +#define CC_MVN_rr(cc,Rd,Rm) _OP1(cc,_MVN,0,Rd,SHIFT_REG(Rm)) +#define CC_MVN_rrLSLi(cc,Rd,Rm,i) _OP1(cc,_MVN,0,Rd,SHIFT_LSL_i(Rm,i)) +#define CC_MVN_rrLSLr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,0,Rd,SHIFT_LSL_r(Rm,Rs)) +#define CC_MVN_rrLSRi(cc,Rd,Rm,i) _OP1(cc,_MVN,0,Rd,SHIFT_LSR_i(Rm,i)) +#define CC_MVN_rrLSRr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,0,Rd,SHIFT_LSR_r(Rm,Rs)) +#define CC_MVN_rrASRi(cc,Rd,Rm,i) _OP1(cc,_MVN,0,Rd,SHIFT_ASR_i(Rm,i)) +#define CC_MVN_rrASRr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,0,Rd,SHIFT_ASR_r(Rm,Rs)) +#define CC_MVN_rrRORi(cc,Rd,Rm,i) _OP1(cc,_MVN,0,Rd,SHIFT_ROR_i(Rm,i)) +#define CC_MVN_rrRORr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,0,Rd,SHIFT_ROR_r(Rm,Rs)) +#define CC_MVN_rrRRX(cc,Rd,Rm) _OP1(cc,_MVN,0,Rd,SHIFT_RRX(Rm)) + +/* MVN rd,#i */ +#define MVN_ri8(Rd,i) CC_MVN_ri8(NATIVE_CC_AL,Rd,i) +/* MVN Rd,#i ROR #s */ +#define MVN_ri8RORi(Rd,i,s) CC_MVN_ri8RORi(NATIVE_CC_AL,Rd,i,s) +#define MVN_ri(Rd,i) CC_MVN_ri(NATIVE_CC_AL,Rd,i) +#define MVN_rr(Rd,Rm) CC_MVN_rr(NATIVE_CC_AL,Rd,Rm) +#define MVN_rrLSLi(Rd,Rm,i) CC_MVN_rrLSLi(NATIVE_CC_AL,Rd,Rm,i) +#define MVN_rrLSLr(Rd,Rm,Rs) CC_MVN_rrLSLr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVN_rrLSRi(Rd,Rm,i) CC_MVN_rrLSRi(NATIVE_CC_AL,Rd,Rm,i) +#define MVN_rrLSRr(Rd,Rm,Rs) CC_MVN_rrLSRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVN_rrASRi(Rd,Rm,i) CC_MVN_rrASRi(NATIVE_CC_AL,Rd,Rm,i) +#define MVN_rrASRr(Rd,Rm,Rs) CC_MVN_rrASRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVN_rrRORi(Rd,Rm,i) CC_MVN_rrRORi(NATIVE_CC_AL,Rd,Rm,i) +#define MVN_rrRORr(Rd,Rm,Rs) CC_MVN_rrRORr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVN_rrRRX(Rd,Rm) CC_MVN_rrRRX(NATIVE_CC_AL,Rd,Rm) + +#define CC_MVNS_ri(cc,Rd,i) _OP1(cc,_MVN,1,Rd,SHIFT_IMM(i)) +#define CC_MVNS_rr(cc,Rd,Rm) _OP1(cc,_MVN,1,Rd,SHIFT_REG(Rm)) +#define CC_MVNS_rrLSLi(cc,Rd,Rm,i) _OP1(cc,_MVN,1,Rd,SHIFT_LSL_i(Rm,i)) +#define CC_MVNS_rrLSLr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,1,Rd,SHIFT_LSL_r(Rm,Rs)) +#define CC_MVNS_rrLSRi(cc,Rd,Rm,i) _OP1(cc,_MVN,1,Rd,SHIFT_LSR_i(Rm,i)) +#define CC_MVNS_rrLSRr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,1,Rd,SHIFT_LSR_r(Rm,Rs)) +#define CC_MVNS_rrASRi(cc,Rd,Rm,i) _OP1(cc,_MVN,1,Rd,SHIFT_ASR_i(Rm,i)) +#define CC_MVNS_rrASRr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,1,Rd,SHIFT_ASR_r(Rm,Rs)) +#define CC_MVNS_rrRORi(cc,Rd,Rm,i) _OP1(cc,_MVN,1,Rd,SHIFT_ROR_i(Rm,i)) +#define CC_MVNS_rrRORr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,1,Rd,SHIFT_ROR_r(Rm,Rs)) +#define CC_MVNS_rrRRX(cc,Rd,Rm) _OP1(cc,_MVN,1,Rd,SHIFT_RRX(Rm)) + +#define MVNS_ri(Rd,i) CC_MVNS_ri(NATIVE_CC_AL,Rd,i) +#define MVNS_rr(Rd,Rm) CC_MVNS_rr(NATIVE_CC_AL,Rd,Rm) +#define MVNS_rrLSLi(Rd,Rm,i) CC_MVNS_rrLSLi(NATIVE_CC_AL,Rd,Rm,i) +#define MVNS_rrLSLr(Rd,Rm,Rs) CC_MVNS_rrLSLr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVNS_rrLSRi(Rd,Rm,i) CC_MVNS_rrLSRi(NATIVE_CC_AL,Rd,Rm,i) +#define MVNS_rrLSRr(Rd,Rm,Rs) CC_MVNS_rrLSRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVNS_rrASRi(Rd,Rm,i) CC_MVNS_rrASRi(NATIVE_CC_AL,Rd,Rm,i) +#define MVNS_rrASRr(Rd,Rm,Rs) CC_MVNS_rrASRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVNS_rrRORi(Rd,Rm,i) CC_MVNS_rrRORi(NATIVE_CC_AL,Rd,Rm,i) +#define MVNS_rrRORr(Rd,Rm,Rs) CC_MVNS_rrRORr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVNS_rrRRX(Rd,Rm) CC_MVNS_rrRRX(NATIVE_CC_AL,Rd,Rm) + +/* Opcodes Type 2 */ +#define CC_CMP_ri(cc,Rn,i) _OP2(cc,_CMP,Rn,SHIFT_IMM(i)) +#define CC_CMP_rr(cc,Rn,Rm) _OP2(cc,_CMP,Rn,SHIFT_REG(Rm)) +#define CC_CMP_rrLSLi(cc,Rn,Rm,i) _OP2(cc,_CMP,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_CMP_rrLSLr(cc,Rn,Rm,Rs) _OP2(cc,_CMP,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_CMP_rrLSRi(cc,Rn,Rm,i) _OP2(cc,_CMP,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_CMP_rrLSRr(cc,Rn,Rm,Rs) _OP2(cc,_CMP,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_CMP_rrASRi(cc,Rn,Rm,i) _OP2(cc,_CMP,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_CMP_rrASRr(cc,Rn,Rm,Rs) _OP2(cc,_CMP,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_CMP_rrRORi(cc,Rn,Rm,i) _OP2(cc,_CMP,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_CMP_rrRORr(cc,Rn,Rm,Rs) _OP2(cc,_CMP,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_CMP_rrRRX(cc,Rn,Rm) _OP2(cc,_CMP,Rn,SHIFT_RRX(Rm)) + +#define CMP_ri(Rn,i) CC_CMP_ri(NATIVE_CC_AL,Rn,i) +#define CMP_rr(Rn,Rm) CC_CMP_rr(NATIVE_CC_AL,Rn,Rm) +#define CMP_rrLSLi(Rn,Rm,i) CC_CMP_rrLSLi(NATIVE_CC_AL,Rn,Rm,i) +#define CMP_rrLSLr(Rn,Rm,Rs) CC_CMP_rrLSLr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMP_rrLSRi(Rn,Rm,i) CC_CMP_rrLSRi(NATIVE_CC_AL,Rn,Rm,i) +#define CMP_rrLSRr(Rn,Rm,Rs) CC_CMP_rrLSRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMP_rrASRi(Rn,Rm,i) CC_CMP_rrASRi(NATIVE_CC_AL,Rn,Rm,i) +#define CMP_rrASRr(Rn,Rm,Rs) CC_CMP_rrASRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMP_rrRORi(Rn,Rm,i) CC_CMP_rrRORi(NATIVE_CC_AL,Rn,Rm,i) +#define CMP_rrRORr(Rn,Rm,Rs) CC_CMP_rrRORr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMP_rrRRX(Rn,Rm) CC_CMP_rrRRX(NATIVE_CC_AL,Rn,Rm) + +#define CC_CMN_ri(cc,Rn,i) _OP2(cc,_CMN,Rn,SHIFT_IMM(i)) +#define CC_CMN_rr(cc,Rn,r) _OP2(cc,_CMN,Rn,SHIFT_REG(r)) +#define CC_CMN_rrLSLi(cc,Rn,Rm,i) _OP2(cc,_CMN,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_CMN_rrLSLr(cc,Rn,Rm,Rs) _OP2(cc,_CMN,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_CMN_rrLSRi(cc,Rn,Rm,i) _OP2(cc,_CMN,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_CMN_rrLSRr(cc,Rn,Rm,Rs) _OP2(cc,_CMN,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_CMN_rrASRi(cc,Rn,Rm,i) _OP2(cc,_CMN,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_CMN_rrASRr(cc,Rn,Rm,Rs) _OP2(cc,_CMN,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_CMN_rrRORi(cc,Rn,Rm,i) _OP2(cc,_CMN,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_CMN_rrRORr(cc,Rn,Rm,Rs) _OP2(cc,_CMN,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_CMN_rrRRX(cc,Rn,Rm) _OP2(cc,_CMN,Rn,SHIFT_RRX(Rm)) + +#define CMN_ri(Rn,i) CC_CMN_ri(NATIVE_CC_AL,Rn,i) +#define CMN_rr(Rn,r) CC_CMN_rr(NATIVE_CC_AL,Rn,r) +#define CMN_rrLSLi(Rn,Rm,i) CC_CMN_rrLSLi(NATIVE_CC_AL,Rn,Rm,i) +#define CMN_rrLSLr(Rn,Rm,Rs) CC_CMN_rrLSLr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMN_rrLSRi(Rn,Rm,i) CC_CMN_rrLSRi(NATIVE_CC_AL,Rn,Rm,i) +#define CMN_rrLSRr(Rn,Rm,Rs) CC_CMN_rrLSRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMN_rrASRi(Rn,Rm,i) CC_CMN_rrASRi(NATIVE_CC_AL,Rn,Rm,i) +#define CMN_rrASRr(Rn,Rm,Rs) CC_CMN_rrASRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMN_rrRORi(Rn,Rm,i) CC_CMN_rrRORi(NATIVE_CC_AL,Rn,Rm,i) +#define CMN_rrRORr(Rn,Rm,Rs) CC_CMN_rrRORr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMN_rrRRX(Rn,Rm) CC_CMN_rrRRX(NATIVE_CC_AL,Rn,Rm) + +#define CC_TST_ri(cc,Rn,i) _OP2(cc,_TST,Rn,SHIFT_IMM(i)) +#define CC_TST_rr(cc,Rn,r) _OP2(cc,_TST,Rn,SHIFT_REG(r)) +#define CC_TST_rrLSLi(cc,Rn,Rm,i) _OP2(cc,_TST,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_TST_rrLSLr(cc,Rn,Rm,Rs) _OP2(cc,_TST,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_TST_rrLSRi(cc,Rn,Rm,i) _OP2(cc,_TST,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_TST_rrLSRr(cc,Rn,Rm,Rs) _OP2(cc,_TST,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_TST_rrASRi(cc,Rn,Rm,i) _OP2(cc,_TST,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_TST_rrASRr(cc,Rn,Rm,Rs) _OP2(cc,_TST,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_TST_rrRORi(cc,Rn,Rm,i) _OP2(cc,_TST,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_TST_rrRORr(cc,Rn,Rm,Rs) _OP2(cc,_TST,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_TST_rrRRX(cc,Rn,Rm) _OP2(cc,_TST,Rn,SHIFT_RRX(Rm)) + +#define TST_ri(Rn,i) CC_TST_ri(NATIVE_CC_AL,Rn,i) +#define TST_rr(Rn,r) CC_TST_rr(NATIVE_CC_AL,Rn,r) +#define TST_rrLSLi(Rn,Rm,i) CC_TST_rrLSLi(NATIVE_CC_AL,Rn,Rm,i) +#define TST_rrLSLr(Rn,Rm,Rs) CC_TST_rrLSLr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TST_rrLSRi(Rn,Rm,i) CC_TST_rrLSRi(NATIVE_CC_AL,Rn,Rm,i) +#define TST_rrLSRr(Rn,Rm,Rs) CC_TST_rrLSRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TST_rrASRi(Rn,Rm,i) CC_TST_rrASRi(NATIVE_CC_AL,Rn,Rm,i) +#define TST_rrASRr(Rn,Rm,Rs) CC_TST_rrASRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TST_rrRORi(Rn,Rm,i) CC_TST_rrRORi(NATIVE_CC_AL,Rn,Rm,i) +#define TST_rrRORr(Rn,Rm,Rs) CC_TST_rrRORr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TST_rrRRX(Rn,Rm) CC_TST_rrRRX(NATIVE_CC_AL,Rn,Rm) + +#define CC_TEQ_ri(cc,Rn,i) _OP2(cc,_TEQ,Rn,SHIFT_IMM(i)) +#define CC_TEQ_rr(cc,Rn,r) _OP2(cc,_TEQ,Rn,SHIFT_REG(r)) +#define CC_TEQ_rrLSLi(cc,Rn,Rm,i) _OP2(cc,_TEQ,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_TEQ_rrLSLr(cc,Rn,Rm,Rs) _OP2(cc,_TEQ,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_TEQ_rrLSRi(cc,Rn,Rm,i) _OP2(cc,_TEQ,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_TEQ_rrLSRr(cc,Rn,Rm,Rs) _OP2(cc,_TEQ,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_TEQ_rrASRi(cc,Rn,Rm,i) _OP2(cc,_TEQ,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_TEQ_rrASRr(cc,Rn,Rm,Rs) _OP2(cc,_TEQ,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_TEQ_rrRORi(cc,Rn,Rm,i) _OP2(cc,_TEQ,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_TEQ_rrRORr(cc,Rn,Rm,Rs) _OP2(cc,_TEQ,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_TEQ_rrRRX(cc,Rn,Rm) _OP2(cc,_TEQ,Rn,SHIFT_RRX(Rm)) + +#define TEQ_ri(Rn,i) CC_TEQ_ri(NATIVE_CC_AL,Rn,i) +#define TEQ_rr(Rn,r) CC_TEQ_rr(NATIVE_CC_AL,Rn,r) +#define TEQ_rrLSLi(Rn,Rm,i) CC_TEQ_rrLSLi(NATIVE_CC_AL,Rn,Rm,i) +#define TEQ_rrLSLr(Rn,Rm,Rs) CC_TEQ_rrLSLr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TEQ_rrLSRi(Rn,Rm,i) CC_TEQ_rrLSRi(NATIVE_CC_AL,Rn,Rm,i) +#define TEQ_rrLSRr(Rn,Rm,Rs) CC_TEQ_rrLSRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TEQ_rrASRi(Rn,Rm,i) CC_TEQ_rrASRi(NATIVE_CC_AL,Rn,Rm,i) +#define TEQ_rrASRr(Rn,Rm,Rs) CC_TEQ_rrASRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TEQ_rrRORi(Rn,Rm,i) CC_TEQ_rrRORi(NATIVE_CC_AL,Rn,Rm,i) +#define TEQ_rrRORr(Rn,Rm,Rs) CC_TEQ_rrRORr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TEQ_rrRRX(Rn,Rm) CC_TEQ_rrRRX(NATIVE_CC_AL,Rn,Rm) + +/* Opcodes Type 3 */ +#define CC_AND_rri(cc,Rd,Rn,i) _OP3(cc,_AND,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_AND_rrr(cc,Rd,Rn,Rm) _OP3(cc,_AND,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_AND_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_AND_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_AND_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_AND_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_AND_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_AND_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_AND_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_AND_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_AND_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_AND,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define AND_rri(Rd,Rn,i) CC_AND_rri(NATIVE_CC_AL,Rd,Rn,i) +#define AND_rrr(Rd,Rn,Rm) CC_AND_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define AND_rrrLSLi(Rd,Rn,Rm,i) CC_AND_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define AND_rrrLSLr(Rd,Rn,Rm,Rs) CC_AND_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define AND_rrrLSRi(Rd,Rn,Rm,i) CC_AND_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define AND_rrrLSRr(Rd,Rn,Rm,Rs) CC_AND_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define AND_rrrASRi(Rd,Rn,Rm,i) CC_AND_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define AND_rrrASRr(Rd,Rn,Rm,Rs) CC_AND_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define AND_rrrRORi(Rd,Rn,Rm,i) CC_AND_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define AND_rrrRORr(Rd,Rn,Rm,Rs) CC_AND_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define AND_rrrRRX(Rd,Rn,Rm) CC_AND_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ANDS_rri(cc,Rd,Rn,i) _OP3(cc,_AND,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_ANDS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_AND,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ANDS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ANDS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ANDS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ANDS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ANDS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ANDS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ANDS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ANDS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ANDS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_AND,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define ANDS_rri(Rd,Rn,i) CC_ANDS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ANDS_rrr(Rd,Rn,Rm) CC_ANDS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ANDS_rrrLSLi(Rd,Rn,Rm,i) CC_ANDS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ANDS_rrrLSLr(Rd,Rn,Rm,Rs) CC_ANDS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ANDS_rrrLSRi(Rd,Rn,Rm,i) CC_ANDS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ANDS_rrrLSRr(Rd,Rn,Rm,Rs) CC_ANDS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ANDS_rrrASRi(Rd,Rn,Rm,i) CC_ANDS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ANDS_rrrASRr(Rd,Rn,Rm,Rs) CC_ANDS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ANDS_rrrRORi(Rd,Rn,Rm,i) CC_ANDS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ANDS_rrrRORr(Rd,Rn,Rm,Rs) CC_ANDS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ANDS_rrrRRX(Rd,Rn,Rm) CC_ANDS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_EOR_rri(cc,Rd,Rn,i) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_EOR_rrr(cc,Rd,Rn,Rm) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_EOR_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_EOR_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_EOR_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_EOR_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_EOR_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_EOR_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_EOR_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_EOR_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_EOR_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define EOR_rri(Rd,Rn,i) CC_EOR_rri(NATIVE_CC_AL,Rd,Rn,i) +#define EOR_rrr(Rd,Rn,Rm) CC_EOR_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define EOR_rrrLSLi(Rd,Rn,Rm,i) CC_EOR_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EOR_rrrLSLr(Rd,Rn,Rm,Rs) CC_EOR_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EOR_rrrLSRi(Rd,Rn,Rm,i) CC_EOR_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EOR_rrrLSRr(Rd,Rn,Rm,Rs) CC_EOR_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EOR_rrrASRi(Rd,Rn,Rm,i) CC_EOR_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EOR_rrrASRr(Rd,Rn,Rm,Rs) CC_EOR_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EOR_rrrRORi(Rd,Rn,Rm,i) CC_EOR_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EOR_rrrRORr(Rd,Rn,Rm,Rs) CC_EOR_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EOR_rrrRRX(Rd,Rn,Rm) CC_EOR_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_EORS_rri(cc,Rd,Rn,i) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_EORS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_EORS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_EORS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_EORS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_EORS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_EORS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_EORS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_EORS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_EORS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_EORS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define EORS_rri(Rd,Rn,i) CC_EORS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define EORS_rrr(Rd,Rn,Rm) CC_EORS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define EORS_rrrLSLi(Rd,Rn,Rm,i) CC_EORS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EORS_rrrLSLr(Rd,Rn,Rm,Rs) CC_EORS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EORS_rrrLSRi(Rd,Rn,Rm,i) CC_EORS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EORS_rrrLSRr(Rd,Rn,Rm,Rs) CC_EORS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EORS_rrrASRi(Rd,Rn,Rm,i) CC_EORS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EORS_rrrASRr(Rd,Rn,Rm,Rs) CC_EORS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EORS_rrrRORi(Rd,Rn,Rm,i) CC_EORS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EORS_rrrRORr(Rd,Rn,Rm,Rs) CC_EORS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EORS_rrrRRX(Rd,Rn,Rm) CC_EORS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_SUB_rri(cc,Rd,Rn,i) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_SUB_rrr(cc,Rd,Rn,Rm) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_SUB_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_SUB_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_SUB_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_SUB_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_SUB_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_SUB_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_SUB_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_SUB_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_SUB_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define SUB_rri(Rd,Rn,i) CC_SUB_rri(NATIVE_CC_AL,Rd,Rn,i) +#define SUB_rrr(Rd,Rn,Rm) CC_SUB_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define SUB_rrrLSLi(Rd,Rn,Rm,i) CC_SUB_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUB_rrrLSLr(Rd,Rn,Rm,Rs) CC_SUB_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUB_rrrLSRi(Rd,Rn,Rm,i) CC_SUB_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUB_rrrLSRr(Rd,Rn,Rm,Rs) CC_SUB_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUB_rrrASRi(Rd,Rn,Rm,i) CC_SUB_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUB_rrrASRr(Rd,Rn,Rm,Rs) CC_SUB_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUB_rrrRORi(Rd,Rn,Rm,i) CC_SUB_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUB_rrrRORr(Rd,Rn,Rm,Rs) CC_SUB_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUB_rrrRRX(Rd,Rn,Rm) CC_SUB_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_SUBS_rri(cc,Rd,Rn,i) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_SUBS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_SUBS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_SUBS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_SUBS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_SUBS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_SUBS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_SUBS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_SUBS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_SUBS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_SUBS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define SUBS_rri(Rd,Rn,i) CC_SUBS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define SUBS_rrr(Rd,Rn,Rm) CC_SUBS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define SUBS_rrrLSLi(Rd,Rn,Rm,i) CC_SUBS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUBS_rrrLSLr(Rd,Rn,Rm,Rs) CC_SUBS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUBS_rrrLSRi(Rd,Rn,Rm,i) CC_SUBS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUBS_rrrLSRr(Rd,Rn,Rm,Rs) CC_SUBS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUBS_rrrASRi(Rd,Rn,Rm,i) CC_SUBS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUBS_rrrASRr(Rd,Rn,Rm,Rs) CC_SUBS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUBS_rrrRORi(Rd,Rn,Rm,i) CC_SUBS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUBS_rrrRORr(Rd,Rn,Rm,Rs) CC_SUBS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUBS_rrrRRX(Rd,Rn,Rm) CC_SUBS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_RSB_rri(cc,Rd,Rn,i) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_RSB_rrr(cc,Rd,Rn,Rm) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_RSB_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_RSB_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_RSB_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_RSB_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_RSB_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_RSB_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_RSB_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_RSB_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_RSB_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define RSB_rri(Rd,Rn,i) CC_RSB_rri(NATIVE_CC_AL,Rd,Rn,i) +#define RSB_rrr(Rd,Rn,Rm) CC_RSB_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define RSB_rrrLSLi(Rd,Rn,Rm,i) CC_RSB_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSB_rrrLSLr(Rd,Rn,Rm,Rs) CC_RSB_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSB_rrrLSRi(Rd,Rn,Rm,i) CC_RSB_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSB_rrrLSRr(Rd,Rn,Rm,Rs) CC_RSB_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSB_rrrASRi(Rd,Rn,Rm,i) CC_RSB_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSB_rrrASRr(Rd,Rn,Rm,Rs) CC_RSB_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSB_rrrRORi(Rd,Rn,Rm,i) CC_RSB_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSB_rrrRORr(Rd,Rn,Rm,Rs) CC_RSB_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSB_rrrRRX(Rd,Rn,Rm) CC_RSB_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_RSBS_rri(cc,Rd,Rn,i) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_RSBS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_RSBS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_RSBS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_RSBS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_RSBS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_RSBS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_RSBS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_RSBS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_RSBS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_RSBS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define RSBS_rri(Rd,Rn,i) CC_RSBS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define RSBS_rrr(Rd,Rn,Rm) CC_RSBS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define RSBS_rrrLSLi(Rd,Rn,Rm,i) CC_RSBS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSBS_rrrLSLr(Rd,Rn,Rm,Rs) CC_RSBS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSBS_rrrLSRi(Rd,Rn,Rm,i) CC_RSBS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSBS_rrrLSRr(Rd,Rn,Rm,Rs) CC_RSBS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSBS_rrrASRi(Rd,Rn,Rm,i) CC_RSBS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSBS_rrrASRr(Rd,Rn,Rm,Rs) CC_RSBS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSBS_rrrRORi(Rd,Rn,Rm,i) CC_RSBS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSBS_rrrRORr(Rd,Rn,Rm,Rs) CC_RSBS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSBS_rrrRRX(Rd,Rn,Rm) CC_RSBS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ADD_rri8(cc,Rd,Rn,i) _OP3(cc,_ADD,0,Rd,Rn,UNSHIFT_IMM8(i)) +#define CC_ADD_rri8RORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_IMM8_ROR(Rm,i)) + +#define CC_ADD_rri(cc,Rd,Rn,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_ADD_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ADD_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ADD_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ADD_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ADD_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ADD_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ADD_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ADD_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ADD_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ADD_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define ADD_rri8(cc,Rd,Rn,i) CC_ADD_rri8(NATIVE_CC_AL,Rd,Rn,i) +#define ADD_rri8RORi(cc,Rd,Rn,Rm,i) CC_ADD_rri8RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) + +#define ADD_rri(Rd,Rn,i) CC_ADD_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ADD_rrr(Rd,Rn,Rm) CC_ADD_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ADD_rrrLSLi(Rd,Rn,Rm,i) CC_ADD_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADD_rrrLSLr(Rd,Rn,Rm,Rs) CC_ADD_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADD_rrrLSRi(Rd,Rn,Rm,i) CC_ADD_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADD_rrrLSRr(Rd,Rn,Rm,Rs) CC_ADD_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADD_rrrASRi(Rd,Rn,Rm,i) CC_ADD_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADD_rrrASRr(Rd,Rn,Rm,Rs) CC_ADD_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADD_rrrRORi(Rd,Rn,Rm,i) CC_ADD_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADD_rrrRORr(Rd,Rn,Rm,Rs) CC_ADD_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADD_rrrRRX(Rd,Rn,Rm) CC_ADD_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ADDS_rri(cc,Rd,Rn,i) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_ADDS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ADDS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ADDS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ADDS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ADDS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ADDS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ADDS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ADDS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ADDS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ADDS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define ADDS_rri(Rd,Rn,i) CC_ADDS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ADDS_rrr(Rd,Rn,Rm) CC_ADDS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ADDS_rrrLSLi(Rd,Rn,Rm,i) CC_ADDS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADDS_rrrLSLr(Rd,Rn,Rm,Rs) CC_ADDS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADDS_rrrLSRi(Rd,Rn,Rm,i) CC_ADDS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADDS_rrrLSRr(Rd,Rn,Rm,Rs) CC_ADDS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADDS_rrrASRi(Rd,Rn,Rm,i) CC_ADDS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADDS_rrrASRr(Rd,Rn,Rm,Rs) CC_ADDS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADDS_rrrRORi(Rd,Rn,Rm,i) CC_ADDS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADDS_rrrRORr(Rd,Rn,Rm,Rs) CC_ADDS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADDS_rrrRRX(Rd,Rn,Rm) CC_ADDS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ADC_rri(cc,Rd,Rn,i) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_ADC_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ADC_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ADC_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ADC_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ADC_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ADC_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ADC_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ADC_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ADC_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ADC_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define ADC_rri(Rd,Rn,i) CC_ADC_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ADC_rrr(Rd,Rn,Rm) CC_ADC_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ADC_rrrLSLi(Rd,Rn,Rm,i) CC_ADC_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADC_rrrLSLr(Rd,Rn,Rm,Rs) CC_ADC_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADC_rrrLSRi(Rd,Rn,Rm,i) CC_ADC_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADC_rrrLSRr(Rd,Rn,Rm,Rs) CC_ADC_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADC_rrrASRi(Rd,Rn,Rm,i) CC_ADC_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADC_rrrASRr(Rd,Rn,Rm,Rs) CC_ADC_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADC_rrrRORi(Rd,Rn,Rm,i) CC_ADC_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADC_rrrRORr(Rd,Rn,Rm,Rs) CC_ADC_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADC_rrrRRX(Rd,Rn,Rm) CC_ADC_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ADCS_rri(cc,Rd,Rn,i) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_ADCS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ADCS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ADCS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ADCS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ADCS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ADCS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ADCS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ADCS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ADCS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ADCS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define ADCS_rri(Rd,Rn,i) CC_ADCS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ADCS_rrr(Rd,Rn,Rm) CC_ADCS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ADCS_rrrLSLi(Rd,Rn,Rm,i) CC_ADCS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADCS_rrrLSLr(Rd,Rn,Rm,Rs) CC_ADCS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADCS_rrrLSRi(Rd,Rn,Rm,i) CC_ADCS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADCS_rrrLSRr(Rd,Rn,Rm,Rs) CC_ADCS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADCS_rrrASRi(Rd,Rn,Rm,i) CC_ADCS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADCS_rrrASRr(Rd,Rn,Rm,Rs) CC_ADCS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADCS_rrrRORi(Rd,Rn,Rm,i) CC_ADCS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADCS_rrrRORr(Rd,Rn,Rm,Rs) CC_ADCS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADCS_rrrRRX(Rd,Rn,Rm) CC_ADCS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_SBC_rri(cc,Rd,Rn,i) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_SBC_rrr(cc,Rd,Rn,Rm) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_SBC_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_SBC_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_SBC_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_SBC_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_SBC_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_SBC_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_SBC_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_SBC_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_SBC_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define SBC_rri(Rd,Rn,i) CC_SBC_rri(NATIVE_CC_AL,Rd,Rn,i) +#define SBC_rrr(Rd,Rn,Rm) CC_SBC_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define SBC_rrrLSLi(Rd,Rn,Rm,i) CC_SBC_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBC_rrrLSLr(Rd,Rn,Rm,Rs) CC_SBC_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBC_rrrLSRi(Rd,Rn,Rm,i) CC_SBC_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBC_rrrLSRr(Rd,Rn,Rm,Rs) CC_SBC_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBC_rrrASRi(Rd,Rn,Rm,i) CC_SBC_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBC_rrrASRr(Rd,Rn,Rm,Rs) CC_SBC_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBC_rrrRORi(Rd,Rn,Rm,i) CC_SBC_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBC_rrrRORr(Rd,Rn,Rm,Rs) CC_SBC_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBC_rrrRRX(Rd,Rn,Rm) CC_SBC_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_SBCS_rri(cc,Rd,Rn,i) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_SBCS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_SBCS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_SBCS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_SBCS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_SBCS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_SBCS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_SBCS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_SBCS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_SBCS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_SBCS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define SBCS_rri(Rd,Rn,i) CC_SBCS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define SBCS_rrr(Rd,Rn,Rm) CC_SBCS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define SBCS_rrrLSLi(Rd,Rn,Rm,i) CC_SBCS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBCS_rrrLSLr(Rd,Rn,Rm,Rs) CC_SBCS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBCS_rrrLSRi(Rd,Rn,Rm,i) CC_SBCS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBCS_rrrLSRr(Rd,Rn,Rm,Rs) CC_SBCS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBCS_rrrASRi(Rd,Rn,Rm,i) CC_SBCS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBCS_rrrASRr(Rd,Rn,Rm,Rs) CC_SBCS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBCS_rrrRORi(Rd,Rn,Rm,i) CC_SBCS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBCS_rrrRORr(Rd,Rn,Rm,Rs) CC_SBCS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBCS_rrrRRX(Rd,Rn,Rm) CC_SBCS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_RSC_rri(cc,Rd,Rn,i) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_RSC_rrr(cc,Rd,Rn,Rm) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_RSC_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_RSC_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_RSC_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_RSC_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_RSC_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_RSC_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_RSC_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_RSC_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_RSC_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define RSC_rri(Rd,Rn,i) CC_RSC_rri(NATIVE_CC_AL,Rd,Rn,i) +#define RSC_rrr(Rd,Rn,Rm) CC_RSC_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define RSC_rrrLSLi(Rd,Rn,Rm,i) CC_RSC_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSC_rrrLSLr(Rd,Rn,Rm,Rs) CC_RSC_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSC_rrrLSRi(Rd,Rn,Rm,i) CC_RSC_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSC_rrrLSRr(Rd,Rn,Rm,Rs) CC_RSC_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSC_rrrASRi(Rd,Rn,Rm,i) CC_RSC_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSC_rrrASRr(Rd,Rn,Rm,Rs) CC_RSC_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSC_rrrRORi(Rd,Rn,Rm,i) CC_RSC_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSC_rrrRORr(Rd,Rn,Rm,Rs) CC_RSC_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSC_rrrRRX(Rd,Rn,Rm) CC_RSC_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_RSCS_rri(cc,Rd,Rn,i) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_RSCS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_RSCS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_RSCS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_RSCS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_RSCS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_RSCS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_RSCS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_RSCS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_RSCS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_RSCS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define RSCS_rri(Rd,Rn,i) CC_RSCS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define RSCS_rrr(Rd,Rn,Rm) CC_RSCS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define RSCS_rrrLSLi(Rd,Rn,Rm,i) CC_RSCS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSCS_rrrLSLr(Rd,Rn,Rm,Rs) CC_RSCS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSCS_rrrLSRi(Rd,Rn,Rm,i) CC_RSCS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSCS_rrrLSRr(Rd,Rn,Rm,Rs) CC_RSCS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSCS_rrrASRi(Rd,Rn,Rm,i) CC_RSCS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSCS_rrrASRr(Rd,Rn,Rm,Rs) CC_RSCS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSCS_rrrRORi(Rd,Rn,Rm,i) CC_RSCS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSCS_rrrRORr(Rd,Rn,Rm,Rs) CC_RSCS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSCS_rrrRRX(Rd,Rn,Rm) CC_RSCS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +/* ORRcc Rd,Rn,#i */ +#define CC_ORR_rri8(cc,Rd,Rn,i) _OP3(cc,_ORR,0,Rd,Rn,UNSHIFTED_IMM8(i)) +/* ORRcc Rd,Rn,#i ROR #s */ +#define CC_ORR_rri8RORi(cc,Rd,Rn,i,s) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_IMM8_ROR(i,s)) + +#define CC_ORR_rri(cc,Rd,Rn,i) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_ORR_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ORR_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ORR_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ORR_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ORR_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ORR_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ORR_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ORR_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ORR_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ORR_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_RRX(Rm)) + +/* ORR Rd,Rn,#i */ +#define ORR_rri8(Rd,Rn,i) CC_ORR_rri8(NATIVE_CC_AL,Rd,Rn,i) +/* ORR Rd,Rn,#i ROR #s */ +#define ORR_rri8RORi(Rd,Rn,i,s) CC_ORR_rri8RORi(NATIVE_CC_AL,Rd,Rn,i,s) + +#define ORR_rri(Rd,Rn,i) CC_ORR_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ORR_rrr(Rd,Rn,Rm) CC_ORR_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ORR_rrrLSLi(Rd,Rn,Rm,i) CC_ORR_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORR_rrrLSLr(Rd,Rn,Rm,Rs) CC_ORR_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORR_rrrLSRi(Rd,Rn,Rm,i) CC_ORR_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORR_rrrLSRr(Rd,Rn,Rm,Rs) CC_ORR_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORR_rrrASRi(Rd,Rn,Rm,i) CC_ORR_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORR_rrrASRr(Rd,Rn,Rm,Rs) CC_ORR_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORR_rrrRORi(Rd,Rn,Rm,i) CC_ORR_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORR_rrrRORr(Rd,Rn,Rm,Rs) CC_ORR_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORR_rrrRRX(Rd,Rn,Rm) CC_ORR_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ORRS_rri(cc,Rd,Rn,i) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_ORRS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ORRS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ORRS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ORRS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ORRS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ORRS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ORRS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ORRS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ORRS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ORRS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define ORRS_rri(Rd,Rn,i) CC_ORRS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ORRS_rrr(Rd,Rn,Rm) CC_ORRS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ORRS_rrrLSLi(Rd,Rn,Rm,i) CC_ORRS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORRS_rrrLSLr(Rd,Rn,Rm,Rs) CC_ORRS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORRS_rrrLSRi(Rd,Rn,Rm,i) CC_ORRS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORRS_rrrLSRr(Rd,Rn,Rm,Rs) CC_ORRS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORRS_rrrASRi(Rd,Rn,Rm,i) CC_ORRS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORRS_rrrASRr(Rd,Rn,Rm,Rs) CC_ORRS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORRS_rrrRORi(Rd,Rn,Rm,i) CC_ORRS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORRS_rrrRORr(Rd,Rn,Rm,Rs) CC_ORRS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORRS_rrrRRX(Rd,Rn,Rm) CC_ORRS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_BIC_rri(cc,Rd,Rn,i) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_BIC_rrr(cc,Rd,Rn,Rm) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_BIC_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_BIC_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_BIC_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_BIC_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_BIC_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_BIC_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_BIC_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_BIC_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_BIC_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define BIC_rri(Rd,Rn,i) CC_BIC_rri(NATIVE_CC_AL,Rd,Rn,i) +#define BIC_rrr(Rd,Rn,Rm) CC_BIC_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define BIC_rrrLSLi(Rd,Rn,Rm,i) CC_BIC_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BIC_rrrLSLr(Rd,Rn,Rm,Rs) CC_BIC_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BIC_rrrLSRi(Rd,Rn,Rm,i) CC_BIC_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BIC_rrrLSRr(Rd,Rn,Rm,Rs) CC_BIC_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BIC_rrrASRi(Rd,Rn,Rm,i) CC_BIC_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BIC_rrrASRr(Rd,Rn,Rm,Rs) CC_BIC_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BIC_rrrRORi(Rd,Rn,Rm,i) CC_BIC_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BIC_rrrRORr(Rd,Rn,Rm,Rs) CC_BIC_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BIC_rrrRRX(Rd,Rn,Rm) CC_BIC_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_BICS_rri(cc,Rd,Rn,i) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_BICS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_BICS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_BICS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_BICS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_BICS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_BICS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_BICS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_BICS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_BICS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_BICS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define BICS_rri(Rd,Rn,i) CC_BICS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define BICS_rrr(Rd,Rn,Rm) CC_BICS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define BICS_rrrLSLi(Rd,Rn,Rm,i) CC_BICS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BICS_rrrLSLr(Rd,Rn,Rm,Rs) CC_BICS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BICS_rrrLSRi(Rd,Rn,Rm,i) CC_BICS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BICS_rrrLSRr(Rd,Rn,Rm,Rs) CC_BICS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BICS_rrrASRi(Rd,Rn,Rm,i) CC_BICS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BICS_rrrASRr(Rd,Rn,Rm,Rs) CC_BICS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BICS_rrrRORi(Rd,Rn,Rm,i) CC_BICS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BICS_rrrRORr(Rd,Rn,Rm,Rs) CC_BICS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BICS_rrrRRX(Rd,Rn,Rm) CC_BICS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +/* Branch instructions */ +#define CC_B_i(cc,i) _W(((cc) << 28) | (10 << 24) | (i)) +#define CC_BL_i(cc,i) _W(((cc) << 28) | (11 << 24) | (i)) +#define CC_BLX_r(cc,r) _W(((cc) << 28) | (0x12 << 20) | (3 << 4) | (0xfff << 8) | (r)) +#define CC_BX_r(cc,r) _W(((cc) << 28) | (0x12 << 20) | (1 << 4) | (0xfff << 8) | (r)) +#define CC_BXJ_r(cc,r) _W(((cc) << 28) | (0x12 << 20) | (2 << 4) | (0xfff << 8) | (r)) + +#define BEQ_i(i) CC_B_i(NATIVE_CC_EQ,i) +#define BNE_i(i) CC_B_i(NATIVE_CC_NE,i) +#define BCS_i(i) CC_B_i(NATIVE_CC_CS,i) +#define BCC_i(i) CC_B_i(NATIVE_CC_CC,i) +#define BMI_i(i) CC_B_i(NATIVE_CC_MI,i) +#define BPL_i(i) CC_B_i(NATIVE_CC_PL,i) +#define BVS_i(i) CC_B_i(NATIVE_CC_VS,i) +#define BVC_i(i) CC_B_i(NATIVE_CC_VC,i) +#define BHI_i(i) CC_B_i(NATIVE_CC_HI,i) +#define BLS_i(i) CC_B_i(NATIVE_CC_LS,i) +#define BGE_i(i) CC_B_i(NATIVE_CC_GE,i) +#define BLT_i(i) CC_B_i(NATIVE_CC_LT,i) +#define BGT_i(i) CC_B_i(NATIVE_CC_GT,i) +#define BLE_i(i) CC_B_i(NATIVE_CC_LE,i) +#define B_i(i) CC_B_i(NATIVE_CC_AL,i) + +#define BL_i(i) CC_BL_i(NATIVE_CC_AL,i) +#define BLX_i(i) _W((NATIVE_CC_AL << 28) | (10 << 24) | (i)) +#define BLX_r(r) CC_BLX_r(NATIVE_CC_AL,r) +#define BX_r(r) CC_BX_r(NATIVE_CC_AL,r) +#define BXJ_r(r) CC_BXJ_r(NATIVE_CC_AL,r) + +/* Status register instructions */ +#define CC_MRS_CPSR(cc,Rd) _W(((cc) << 28) | (0x10 << 20) | ((Rd) << 12) | (0xf << 16)) +#define MRS_CPSR(Rd) CC_MRS_CPSR(NATIVE_CC_AL,Rd) +#define CC_MRS_SPSR(cc,Rd) _W(((cc) << 28) | (0x14 << 20) | ((Rd) << 12) | (0xf << 16)) +#define MRS_SPSR(Rd) CC_MRS_SPSR(NATIVE_CC_AL,Rd) + +#define CC_MSR_CPSR_i(cc,i) _W(((cc) << 28) | (0x32 << 20) | (0x9 << 16) | (0xf << 12) | SHIFT_IMM(i)) +#define CC_MSR_CPSR_r(cc,Rm) _W(((cc) << 28) | (0x12 << 20) | (0x9 << 16) | (0xf << 12) | (Rm)) + +#define MSR_CPSR_i(i) CC_MSR_CPSR_i(NATIVE_CC_AL,(i)) +#define MSR_CPSR_r(Rm) CC_MSR_CPSR_r(NATIVE_CC_AL,(Rm)) + +#define CC_MSR_CPSRf_i(cc,i) _W(((cc) << 28) | (0x32 << 20) | (0x8 << 16) | (0xf << 12) | SHIFT_IMM(i)) +#define CC_MSR_CPSRf_r(cc,Rm) _W(((cc) << 28) | (0x12 << 20) | (0x8 << 16) | (0xf << 12) | (Rm)) + +#define MSR_CPSRf_i(i) CC_MSR_CPSRf_i(NATIVE_CC_AL,(i)) +#define MSR_CPSRf_r(Rm) CC_MSR_CPSRf_r(NATIVE_CC_AL,(Rm)) + +#define CC_MSR_CPSRc_i(cc,i) _W(((cc) << 28) | (0x32 << 20) | (0x1 << 16) | (0xf << 12) | SHIFT_IMM(i)) +#define CC_MSR_CPSRc_r(cc,Rm) _W(((cc) << 28) | (0x12 << 20) | (0x1 << 16) | (0xf << 12) | (Rm)) + +#define MSR_CPSRc_i(i) CC_MSR_CPSRc_i(NATIVE_CC_AL,(i)) +#define MSR_CPSRc_r(Rm) CC_MSR_CPSRc_r(NATIVE_CC_AL,(Rm)) + +/* Load Store instructions */ + +#define CC_PUSH(cc,r) _W(((cc) << 28) | (0x92d << 16) | (1 << (r))) +#define PUSH(r) CC_PUSH(NATIVE_CC_AL, r) + +#define CC_PUSH_REGS(cc,r) _W(((cc) << 28) | (0x92d << 16) | (r)) +#define PUSH_REGS(r) CC_PUSH_REGS(NATIVE_CC_AL, r) + +#define CC_POP(cc,r) _W(((cc) << 28) | (0x8bd << 16) | (1 << (r))) +#define POP(r) CC_POP(NATIVE_CC_AL, r) + +#define CC_POP_REGS(cc,r) _W(((cc) << 28) | (0x8bd << 16) | (r)) +#define POP_REGS(r) CC_POP_REGS(NATIVE_CC_AL, r) + +#define CC_LDR_rR(cc,Rd,Rn) _LS1(cc,1,0,Rd,Rn,ADD_IMM(0)) +#define CC_LDR_rRI(cc,Rd,Rn,i) _LS1(cc,1,0,Rd,Rn,(i) >= 0 ? ADD_IMM(i) : SUB_IMM(-(i))) +#define CC_LDR_rRi(cc,Rd,Rn,i) _LS1(cc,1,0,Rd,Rn,SUB_IMM(i)) +#define CC_LDR_rRR(cc,Rd,Rn,Rm) _LS1(cc,1,0,Rd,Rn,ADD_REG(Rm)) +#define CC_LDR_rRr(cc,Rd,Rn,Rm) _LS1(cc,1,0,Rd,Rn,SUB_REG(Rm)) +#define CC_LDR_rRR_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,ADD_LSL(Rm,i)) +#define CC_LDR_rRr_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,SUB_LSL(Rm,i)) +#define CC_LDR_rRR_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,ADD_LSR(Rm,i)) +#define CC_LDR_rRr_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,SUB_LSR(Rm,i)) +#define CC_LDR_rRR_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,ADD_ASR(Rm,i)) +#define CC_LDR_rRr_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,SUB_ASR(Rm,i)) +#define CC_LDR_rRR_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,ADD_ROR(Rm,i)) +#define CC_LDR_rRr_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,SUB_ROR(Rm,i)) +#define CC_LDR_rRR_RRX(cc,Rd,Rn,Rm) _LS1(cc,1,0,Rd,Rn,ADD_RRX(Rm)) +#define CC_LDR_rRr_RRX(cc,Rd,Rn,Rm) _LS1(cc,1,0,Rd,Rn,SUB_RRX(Rm)) + +#define LDR_rR(Rd,Rn) CC_LDR_rR(NATIVE_CC_AL,Rd,Rn) +#define LDR_rRI(Rd,Rn,i) CC_LDR_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDR_rRi(Rd,Rn,i) CC_LDR_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDR_rRR(Rd,Rn,Rm) CC_LDR_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDR_rRr(Rd,Rn,Rm) CC_LDR_rRr(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDR_rRR_LSLi(Rd,Rn,Rm,i) CC_LDR_rRR_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRr_LSLi(Rd,Rn,Rm,i) CC_LDR_rRr_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRR_LSRi(Rd,Rn,Rm,i) CC_LDR_rRR_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRr_LSRi(Rd,Rn,Rm,i) CC_LDR_rRr_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRR_ASRi(Rd,Rn,Rm,i) CC_LDR_rRR_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRr_ASRi(Rd,Rn,Rm,i) CC_LDR_rRr_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRR_RORi(Rd,Rn,Rm,i) CC_LDR_rRR_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRr_RORi(Rd,Rn,Rm,i) CC_LDR_rRr_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRR_RRX(Rd,Rn,Rm) CC_LDR_rRR_RRX(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDR_rRr_RRX(Rd,Rn,Rm) CC_LDR_rRr_RRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_STR_rR(cc,Rd,Rn) _LS1(cc,0,0,Rd,Rn,ADD_IMM(0)) +#define CC_STR_rRI(cc,Rd,Rn,i) _LS1(cc,0,0,Rd,Rn,ADD_IMM(i)) +#define CC_STR_rRi(cc,Rd,Rn,i) _LS1(cc,0,0,Rd,Rn,SUB_IMM(i)) +#define CC_STR_rRR(cc,Rd,Rn,Rm) _LS1(cc,0,0,Rd,Rn,ADD_REG(Rm)) +#define CC_STR_rRr(cc,Rd,Rn,Rm) _LS1(cc,0,0,Rd,Rn,SUB_REG(Rm)) +#define CC_STR_rRR_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,ADD_LSL(Rm,i)) +#define CC_STR_rRr_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,SUB_LSL(Rm,i)) +#define CC_STR_rRR_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,ADD_LSR(Rm,i)) +#define CC_STR_rRr_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,SUB_LSR(Rm,i)) +#define CC_STR_rRR_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,ADD_ASR(Rm,i)) +#define CC_STR_rRr_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,SUB_ASR(Rm,i)) +#define CC_STR_rRR_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,ADD_ROR(Rm,i)) +#define CC_STR_rRr_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,SUB_ROR(Rm,i)) +#define CC_STR_rRR_RRX(cc,Rd,Rn,Rm) _LS1(cc,0,0,Rd,Rn,ADD_RRX(Rm)) +#define CC_STR_rRr_RRX(cc,Rd,Rn,Rm) _LS1(cc,0,0,Rd,Rn,SUB_RRX(Rm)) + +#define STR_rR(Rd,Rn) CC_STR_rR(NATIVE_CC_AL,Rd,Rn) +#define STR_rRI(Rd,Rn,i) CC_STR_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define STR_rRi(Rd,Rn,i) CC_STR_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define STR_rRR(Rd,Rn,Rm) CC_STR_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define STR_rRr(Rd,Rn,Rm) CC_STR_rRr(NATIVE_CC_AL,Rd,Rn,Rm) +#define STR_rRR_LSLi(Rd,Rn,Rm,i) CC_STR_rRR_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRr_LSLi(Rd,Rn,Rm,i) CC_STR_rRr_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRR_LSRi(Rd,Rn,Rm,i) CC_STR_rRR_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRr_LSRi(Rd,Rn,Rm,i) CC_STR_rRr_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRR_ASRi(Rd,Rn,Rm,i) CC_STR_rRR_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRr_ASRi(Rd,Rn,Rm,i) CC_STR_rRr_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRR_RORi(Rd,Rn,Rm,i) CC_STR_rRR_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRr_RORi(Rd,Rn,Rm,i) CC_STR_rRr_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRR_RRX(Rd,Rn,Rm) CC_STR_rRR_RRX(NATIVE_CC_AL,Rd,Rn,Rm) +#define STR_rRr_RRX(Rd,Rn,Rm) CC_STR_rRr_RRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_LDRB_rR(cc,Rd,Rn) _LS1(cc,1,1,Rd,Rn,ADD_IMM(0)) +#define CC_LDRB_rRI(cc,Rd,Rn,i) _LS1(cc,1,1,Rd,Rn,ADD_IMM(i)) +#define CC_LDRB_rRi(cc,Rd,Rn,i) _LS1(cc,1,1,Rd,Rn,SUB_IMM(i)) +#define CC_LDRB_rRR(cc,Rd,Rn,Rm) _LS1(cc,1,1,Rd,Rn,ADD_REG(Rm)) +#define CC_LDRB_rRr(cc,Rd,Rn,Rm) _LS1(cc,1,1,Rd,Rn,SUB_REG(Rm)) +#define CC_LDRB_rRR_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,ADD_LSL(Rm,i)) +#define CC_LDRB_rRr_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,SUB_LSL(Rm,i)) +#define CC_LDRB_rRR_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,ADD_LSR(Rm,i)) +#define CC_LDRB_rRr_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,SUB_LSR(Rm,i)) +#define CC_LDRB_rRR_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,ADD_ASR(Rm,i)) +#define CC_LDRB_rRr_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,SUB_ASR(Rm,i)) +#define CC_LDRB_rRR_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,ADD_ROR(Rm,i)) +#define CC_LDRB_rRr_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,SUB_ROR(Rm,i)) +#define CC_LDRB_rRR_RRX(cc,Rd,Rn,Rm) _LS1(cc,1,1,Rd,Rn,ADD_RRX(Rm)) +#define CC_LDRB_rRr_RRX(cc,Rd,Rn,Rm) _LS1(cc,1,1,Rd,Rn,SUB_RRX(Rm)) + +#define LDRB_rR(Rd,Rn) CC_LDRB_rR(NATIVE_CC_AL,Rd,Rn) +#define LDRB_rRI(Rd,Rn,i) CC_LDRB_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDRB_rRi(Rd,Rn,i) CC_LDRB_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDRB_rRR(Rd,Rn,Rm) CC_LDRB_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRB_rRr(Rd,Rn,Rm) CC_LDRB_rRr(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRB_rRR_LSLi(Rd,Rn,Rm,i) CC_LDRB_rRR_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRr_LSLi(Rd,Rn,Rm,i) CC_LDRB_rRr_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRR_LSRi(Rd,Rn,Rm,i) CC_LDRB_rRR_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRr_LSRi(Rd,Rn,Rm,i) CC_LDRB_rRr_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRR_ASRi(Rd,Rn,Rm,i) CC_LDRB_rRR_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRr_ASRi(Rd,Rn,Rm,i) CC_LDRB_rRr_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRR_RORi(Rd,Rn,Rm,i) CC_LDRB_rRR_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRr_RORi(Rd,Rn,Rm,i) CC_LDRB_rRr_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRR_RRX(Rd,Rn,Rm) CC_LDRB_rRR_RRX(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRB_rRr_RRX(Rd,Rn,Rm) CC_LDRB_rRr_RRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_STRB_rR(cc,Rd,Rn) _LS1(cc,0,1,Rd,Rn,ADD_IMM(0)) +#define CC_STRB_rRI(cc,Rd,Rn,i) _LS1(cc,0,1,Rd,Rn,ADD_IMM(i)) +#define CC_STRB_rRi(cc,Rd,Rn,i) _LS1(cc,0,1,Rd,Rn,SUB_IMM(i)) +#define CC_STRB_rRR(cc,Rd,Rn,Rm) _LS1(cc,0,1,Rd,Rn,ADD_REG(Rm)) +#define CC_STRB_rRr(cc,Rd,Rn,Rm) _LS1(cc,0,1,Rd,Rn,SUB_REG(Rm)) +#define CC_STRB_rRR_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,ADD_LSL(Rm,i)) +#define CC_STRB_rRr_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,SUB_LSL(Rm,i)) +#define CC_STRB_rRR_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,ADD_LSR(Rm,i)) +#define CC_STRB_rRr_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,SUB_LSR(Rm,i)) +#define CC_STRB_rRR_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,ADD_ASR(Rm,i)) +#define CC_STRB_rRr_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,SUB_ASR(Rm,i)) +#define CC_STRB_rRR_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,ADD_ROR(Rm,i)) +#define CC_STRB_rRr_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,SUB_ROR(Rm,i)) +#define CC_STRB_rRR_RRX(cc,Rd,Rn,Rm) _LS1(cc,0,1,Rd,Rn,ADD_RRX(Rm)) +#define CC_STRB_rRr_RRX(cc,Rd,Rn,Rm) _LS1(cc,0,1,Rd,Rn,SUB_RRX(Rm)) + +#define STRB_rR(Rd,Rn) CC_STRB_rR(NATIVE_CC_AL,Rd,Rn) +#define STRB_rRI(Rd,Rn,i) CC_STRB_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define STRB_rRi(Rd,Rn,i) CC_STRB_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define STRB_rRR(Rd,Rn,Rm) CC_STRB_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define STRB_rRr(Rd,Rn,Rm) CC_STRB_rRr(NATIVE_CC_AL,Rd,Rn,Rm) +#define STRB_rRR_LSLi(Rd,Rn,Rm,i) CC_STRB_rRR_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRr_LSLi(Rd,Rn,Rm,i) CC_STRB_rRr_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRR_LSRi(Rd,Rn,Rm,i) CC_STRB_rRR_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRr_LSRi(Rd,Rn,Rm,i) CC_STRB_rRr_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRR_ASRi(Rd,Rn,Rm,i) CC_STRB_rRR_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRr_ASRi(Rd,Rn,Rm,i) CC_STRB_rRr_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRR_RORi(Rd,Rn,Rm,i) CC_STRB_rRR_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRr_RORi(Rd,Rn,Rm,i) CC_STRB_rRr_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRR_RRX(Rd,Rn,Rm) CC_STRB_rRR_RRX(NATIVE_CC_AL,Rd,Rn,Rm) +#define STRB_rRr_RRX(Rd,Rn,Rm) CC_STRB_rRr_RRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_LDRSH_rR(cc,Rd,Rn) _LS2(cc,1,1,1,1,Rd,Rn,ADD2_IMM(0)) +#define CC_LDRSH_rRI(cc,Rd,Rn,i) _LS2(cc,1,1,1,1,Rd,Rn,ADD2_IMM(i)) +#define CC_LDRSH_rRi(cc,Rd,Rn,i) _LS2(cc,1,1,1,1,Rd,Rn,SUB2_IMM(i)) +#define CC_LDRSH_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,1,1,1,Rd,Rn,ADD2_REG(Rm)) +#define CC_LDRSH_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,1,1,1,Rd,Rn,SUB2_REG(Rm)) + +#define LDRSH_rR(Rd,Rn) CC_LDRSH_rR(NATIVE_CC_AL,Rd,Rn) +#define LDRSH_rRI(Rd,Rn,i) CC_LDRSH_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDRSH_rRi(Rd,Rn,i) CC_LDRSH_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDRSH_rRR(Rd,Rn,Rm) CC_LDRSH_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRSH_rRr(Rd,Rn,Rm) CC_LDRSH_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_LDRH_rR(cc,Rd,Rn) _LS2(cc,1,1,0,1,Rd,Rn,ADD2_IMM(0)) +#define CC_LDRH_rRI(cc,Rd,Rn,i) _LS2(cc,1,1,0,1,Rd,Rn,(i) >= 0 ? ADD2_IMM(i) : SUB2_IMM(-(i))) +#define CC_LDRH_rRi(cc,Rd,Rn,i) _LS2(cc,1,1,0,1,Rd,Rn,SUB2_IMM(i)) +#define CC_LDRH_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,1,0,1,Rd,Rn,ADD2_REG(Rm)) +#define CC_LDRH_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,1,0,1,Rd,Rn,SUB2_REG(Rm)) + +#define LDRH_rR(Rd,Rn) CC_LDRH_rR(NATIVE_CC_AL,Rd,Rn) +#define LDRH_rRI(Rd,Rn,i) CC_LDRH_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDRH_rRi(Rd,Rn,i) CC_LDRH_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDRH_rRR(Rd,Rn,Rm) CC_LDRH_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRH_rRr(Rd,Rn,Rm) CC_LDRH_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_STRD_rR(cc,Rd,Rn) _LS2(cc,1,0,1,1,Rd,Rn,ADD2_IMM(0)) +#define CC_STRD_rRI(cc,Rd,Rn,i) _LS2(cc,1,0,1,1,Rd,Rn,ADD2_IMM(i)) +#define CC_STRD_rRi(cc,Rd,Rn,i) _LS2(cc,1,0,1,1,Rd,Rn,SUB2_IMM(i)) +#define CC_STRD_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,0,1,1,Rd,Rn,ADD2_REG(Rm)) +#define CC_STRD_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,0,1,1,Rd,Rn,SUB2_REG(Rm)) + +#define STRD_rR(Rd,Rn) CC_STRD_rR(NATIVE_CC_AL,Rd,Rn) +#define STRD_rRI(Rd,Rn,i) CC_STRD_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define STRD_rRi(Rd,Rn,i) CC_STRD_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define STRD_rRR(Rd,Rn,Rm) CC_STRD_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define STRD_rRr(Rd,Rn,Rm) CC_STRD_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_STRH_rR(cc,Rd,Rn) _LS2(cc,1,0,0,1,Rd,Rn,ADD2_IMM(0)) +#define CC_STRH_rRI(cc,Rd,Rn,i) _LS2(cc,1,0,0,1,Rd,Rn,ADD2_IMM(i)) +#define CC_STRH_rRi(cc,Rd,Rn,i) _LS2(cc,1,0,0,1,Rd,Rn,SUB2_IMM(i)) +#define CC_STRH_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,0,0,1,Rd,Rn,ADD2_REG(Rm)) +#define CC_STRH_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,0,0,1,Rd,Rn,SUB2_REG(Rm)) + +#define STRH_rR(Rd,Rn) CC_STRH_rR(NATIVE_CC_AL,Rd,Rn) +#define STRH_rRI(Rd,Rn,i) CC_STRH_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define STRH_rRi(Rd,Rn,i) CC_STRH_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define STRH_rRR(Rd,Rn,Rm) CC_STRH_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define STRH_rRr(Rd,Rn,Rm) CC_STRH_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_LDRSB_rR(cc,Rd,Rn) _LS2(cc,1,1,1,0,Rd,Rn,ADD2_IMM(0)) +#define CC_LDRSB_rRI(cc,Rd,Rn,i) _LS2(cc,1,1,1,0,Rd,Rn,ADD2_IMM(i)) +#define CC_LDRSB_rRi(cc,Rd,Rn,i) _LS2(cc,1,1,1,0,Rd,Rn,SUB2_IMM(i)) +#define CC_LDRSB_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,1,1,0,Rd,Rn,ADD2_REG(Rm)) +#define CC_LDRSB_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,1,1,0,Rd,Rn,SUB2_REG(Rm)) + +#define LDRSB_rR(Rd,Rn) CC_LDRSB_rR(NATIVE_CC_AL,Rd,Rn) +#define LDRSB_rRI(Rd,Rn,i) CC_LDRSB_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDRSB_rRi(Rd,Rn,i) CC_LDRSB_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDRSB_rRR(Rd,Rn,Rm) CC_LDRSB_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRSB_rRr(Rd,Rn,Rm) CC_LDRSB_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_LDRD_rR(cc,Rd,Rn) _LS2(cc,1,0,1,0,Rd,Rn,ADD2_IMM(0)) +#define CC_LDRD_rRI(cc,Rd,Rn,i) _LS2(cc,1,0,1,0,Rd,Rn,ADD2_IMM(i)) +#define CC_LDRD_rRi(cc,Rd,Rn,i) _LS2(cc,1,0,1,0,Rd,Rn,SUB2_IMM(i)) +#define CC_LDRD_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,0,1,0,Rd,Rn,ADD2_REG(Rm)) +#define CC_LDRD_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,0,1,0,Rd,Rn,SUB2_REG(Rm)) + +#define LDRD_rR(Rd,Rn) CC_LDRD_rR(NATIVE_CC_AL,Rd,Rn) +#define LDRD_rRI(Rd,Rn,i) CC_LDRD_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDRD_rRi(Rd,Rn,i) CC_LDRD_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDRD_rRR(Rd,Rn,Rm) CC_LDRD_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRD_rRr(Rd,Rn,Rm) CC_LDRD_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +/* Multiply */ +#define CC_SMULL_rrrr(cc, RdLo, RdHi, Rm, Rs) _W(((cc) << 28) | (0x0C << 20) | ((RdHi) << 16) | ((RdLo) << 12) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define SMULL_rrrr(RdLo,RdHi,Rm,Rs) CC_SMULL_rrrr(NATIVE_CC_AL,RdLo,RdHi,Rm,Rs) +#define CC_SMULLS_rrrr(cc, RdLo, RdHi, Rm, Rs) _W(((cc) << 28) | (0x0D << 20) | ((RdHi) << 16) | ((RdLo) << 12) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define SMULLS_rrrr(RdLo,RdHi,Rm,Rs) CC_SMULLS_rrrr(NATIVE_CC_AL,RdLo,RdHi,Rm,Rs) +#define CC_MUL_rrr(cc, Rd, Rm, Rs) _W(((cc) << 28) | (0x00 << 20) | ((Rd) << 16) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define MUL_rrr(Rd, Rm, Rs) CC_MUL_rrr(NATIVE_CC_AL, Rd, Rm, Rs) +#define CC_MULS_rrr(cc, Rd, Rm, Rs) _W(((cc) << 28) | (0x01 << 20) | ((Rd) << 16) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define MULS_rrr(Rd, Rm, Rs) CC_MULS_rrr(NATIVE_CC_AL, Rd, Rm, Rs) + +#define CC_UMULL_rrrr(cc, RdLo, RdHi, Rm, Rs) _W(((cc) << 28) | (0x08 << 20) | ((RdHi) << 16) | ((RdLo) << 12) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define UMULL_rrrr(RdLo,RdHi,Rm,Rs) CC_UMULL_rrrr(NATIVE_CC_AL,RdLo,RdHi,Rm,Rs) +#define CC_UMULLS_rrrr(cc, RdLo, RdHi, Rm, Rs) _W(((cc) << 28) | (0x09 << 20) | ((RdHi) << 16) | ((RdLo) << 12) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define UMULLS_rrrr(RdLo,RdHi,Rm,Rs) CC_UMULLS_rrrr(NATIVE_CC_AL,RdLo,RdHi,Rm,Rs) + +/* Others */ +#define CC_CLZ_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x16 << 20) | (0xf << 16) | ((Rd) << 12) | (0xf << 8) | (0x1 << 4) | SHIFT_REG(Rm)) +#define CLZ_rr(Rd,Rm) CC_CLZ_rr(NATIVE_CC_AL,Rd,Rm) + +/* Alias */ +#define LSL_rri(Rd,Rm,i) MOV_rrLSLi(Rd,Rm,i) +#define LSL_rrr(Rd,Rm,Rs) MOV_rrLSLr(Rd,Rm,Rs) +#define LSR_rri(Rd,Rm,i) MOV_rrLSRi(Rd,Rm,i) +#define LSR_rrr(Rd,Rm,Rs) MOV_rrLSRr(Rd,Rm,Rs) +#define ASR_rri(Rd,Rm,i) MOV_rrASRi(Rd,Rm,i) +#define ASR_rrr(Rd,Rm,Rs) MOV_rrASRr(Rd,Rm,Rs) +#define ROR_rri(Rd,Rm,i) MOV_rrRORi(Rd,Rm,i) +#define ROR_rrr(Rd,Rm,Rs) MOV_rrRORr(Rd,Rm,Rs) +#define RRX_rr(Rd,Rm) MOV_rrRRX(Rd,Rm) +#define LSLS_rri(Rd,Rm,i) MOVS_rrLSLi(Rd,Rm,i) +#define LSLS_rrr(Rd,Rm,Rs) MOVS_rrLSLr(Rd,Rm,Rs) +#define LSRS_rri(Rd,Rm,i) MOVS_rrLSRi(Rd,Rm,i) +#define LSRS_rrr(Rd,Rm,Rs) MOVS_rrLSRr(Rd,Rm,Rs) +#define ASRS_rri(Rd,Rm,i) MOVS_rrASRi(Rd,Rm,i) +#define ASRS_rrr(Rd,Rm,Rs) MOVS_rrASRr(Rd,Rm,Rs) +#define RORS_rri(Rd,Rm,i) MOVS_rrRORi(Rd,Rm,i) +#define RORS_rrr(Rd,Rm,Rs) MOVS_rrRORr(Rd,Rm,Rs) +#define RRXS_rr(Rd,Rm) MOVS_rrRRX(Rd,Rm) + +/* ARMV6 ops */ +#define CC_SXTB_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6a << 20) | (0xf << 16) | ((Rd) << 12) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTB_rr(Rd,Rm) CC_SXTB_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTB_rr_ROR8(cc,Rd,Rm) _W(((cc) << 28) | (0x6a << 20) | (0xf << 16) | ((Rd) << 12) | (1 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTB_rr_ROR8(Rd,Rm) CC_SXTB_rr_ROR8(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTB_rr_ROR16(cc,Rd,Rm) _W(((cc) << 28) | (0x6a << 20) | (0xf << 16) | ((Rd) << 12) | (2 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTB_rr_ROR16(Rd,Rm) CC_SXTB_rr_ROR16(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTB_rr_ROR24(cc,Rd,Rm) _W(((cc) << 28) | (0x6a << 20) | (0xf << 16) | ((Rd) << 12) | (3 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTB_rr_ROR24(Rd,Rm) CC_SXTB_rr_ROR24(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTH_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | ((Rd) << 12) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTH_rr(Rd,Rm) CC_SXTH_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTH_rr_ROR8(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | ((Rd) << 12) | (1 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTH_rr_ROR8(Rd,Rm) CC_SXTH_rr_ROR8(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTH_rr_ROR16(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | ((Rd) << 12) | (2 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTH_rr_ROR16(Rd,Rm) CC_SXTH_rr_ROR16(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTH_rr_ROR24(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | ((Rd) << 12) | (3 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTH_rr_ROR24(Rd,Rm) CC_SXTH_rr_ROR24(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTB_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6e << 20) | (0xf << 16) | ((Rd) << 12) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTB_rr(Rd,Rm) CC_UXTB_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTB_rr_ROR8(cc,Rd,Rm) _W(((cc) << 28) | (0x6e << 20) | (0xf << 16) | ((Rd) << 12) | (1 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTB_rr_ROR8(Rd,Rm) CC_UXTB_rr_ROR8(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTB_rr_ROR16(cc,Rd,Rm) _W(((cc) << 28) | (0x6e << 20) | (0xf << 16) | ((Rd) << 12) | (2 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTB_rr_ROR16(Rd,Rm) CC_UXTB_rr_ROR16(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTB_rr_ROR24(cc,Rd,Rm) _W(((cc) << 28) | (0x6e << 20) | (0xf << 16) | ((Rd) << 12) | (3 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTB_rr_ROR24(Rd,Rm) CC_UXTB_rr_ROR24(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTH_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6f << 20) | (0xf << 16) | ((Rd) << 12) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTH_rr(Rd,Rm) CC_UXTH_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTH_rr_ROR8(cc,Rd,Rm) _W(((cc) << 28) | (0x6f << 20) | (0xf << 16) | ((Rd) << 12) | (1 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTH_rr_ROR8(Rd,Rm) CC_UXTH_rr_ROR8(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTH_rr_ROR16(cc,Rd,Rm) _W(((cc) << 28) | (0x6f << 20) | (0xf << 16) | ((Rd) << 12) | (2 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTH_rr_ROR16(Rd,Rm) CC_UXTH_rr_ROR16(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTH_rr_ROR24(cc,Rd,Rm) _W(((cc) << 28) | (0x6f << 20) | (0xf << 16) | ((Rd) << 12) | (3 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTH_rr_ROR24(Rd,Rm) CC_UXTH_rr_ROR24(NATIVE_CC_AL,Rd,Rm) + +#define CC_REV_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | (0xf << 8) | ((Rd) << 12) | (0x3 << 4) | SHIFT_REG(Rm)) +#define REV_rr(Rd,Rm) CC_REV_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_REV16_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | (0xf << 8) | ((Rd) << 12) | (0xB << 4) | SHIFT_REG(Rm)) +#define REV16_rr(Rd,Rm) CC_REV16_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_REVSH_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6f << 20) | (0xf << 16) | (0xf << 8) | ((Rd) << 12) | (0xB << 4) | SHIFT_REG(Rm)) +#define REVSH_rr(Rd,Rm) CC_REVSH_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_PKHBT_rrr(cc,Rd,Rn,Rm) _W(((cc) << 28) | (0x68 << 20) | (Rn << 16) | (Rd << 12) | (0x1 << 4) | (Rm)) +#define CC_PKHBT_rrrLSLi(cc,Rd,Rn,Rm,s) _W(((cc) << 28) | (0x68 << 20) | (Rn << 16) | (Rd << 12) | (0x1 << 4) | SHIFT_PK(Rm, s)) +#define PKHBT_rrr(Rd,Rn,Rm) CC_PKHBT_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define PKHBT_rrrLSLi(Rd,Rn,Rm,s) CC_PKHBT_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,s) + +#define CC_PKHTB_rrrASRi(cc,Rd,Rn,Rm,s) _W(((cc) << 28) | (0x68 << 20) | (Rn << 16) | (Rd << 12) | (0x5 << 4) | SHIFT_PK(Rm, s)) +#define PKHTB_rrrASRi(Rd,Rn,Rm,s) CC_PKHTB_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,s) + +#endif /* ARM_RTASM_H */ diff --git a/jit/compemu_midfunc_arm.cpp b/jit/compemu_midfunc_arm.cpp new file mode 100644 index 00000000..aa9a7181 --- /dev/null +++ b/jit/compemu_midfunc_arm.cpp @@ -0,0 +1,1967 @@ +/* + * compiler/compemu_midfunc_arm.cpp - Native MIDFUNCS for ARM + * + * Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note: + * File is included by compemu_support.cpp + * + */ + +/******************************************************************** + * CPU functions exposed to gencomp. Both CREATE and EMIT time * + ********************************************************************/ + +/* + * RULES FOR HANDLING REGISTERS: + * + * * In the function headers, order the parameters + * - 1st registers written to + * - 2nd read/modify/write registers + * - 3rd registers read from + * * Before calling raw_*, you must call readreg, writereg or rmw for + * each register + * * The order for this is + * - 1st call remove_offset for all registers written to with size<4 + * - 2nd call readreg for all registers read without offset + * - 3rd call rmw for all rmw registers + * - 4th call readreg_offset for all registers that can handle offsets + * - 5th call get_offset for all the registers from the previous step + * - 6th call writereg for all written-to registers + * - 7th call raw_* + * - 8th unlock2 all registers that were locked + */ + +MIDFUNC(0,live_flags,(void)) +{ + live.flags_on_stack=TRASH; + live.flags_in_flags=VALID; + live.flags_are_important=1; +} + +MIDFUNC(0,dont_care_flags,(void)) +{ + live.flags_are_important=0; +} + +MIDFUNC(0,duplicate_carry,(void)) +{ + evict(FLAGX); + make_flags_live_internal(); + COMPCALL(setcc_m)((uintptr)live.state[FLAGX].mem,NATIVE_CC_CS); + log_vwrite(FLAGX); +} + +MIDFUNC(0,restore_carry,(void)) +{ +#if defined(USE_JIT2) + RR4 r=readreg(FLAGX,4); + MRS_CPSR(REG_WORK1); + TEQ_ri(r,1); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_C_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSRf_r(REG_WORK1); + unlock2(r); +#else + if (!have_rat_stall) { /* Not a P6 core, i.e. no partial stalls */ + bt_l_ri_noclobber(FLAGX,0); + } + else { /* Avoid the stall the above creates. + This is slow on non-P6, though. + */ + COMPCALL(rol_b_ri(FLAGX,8)); + isclean(FLAGX); + } +#endif +} + +MIDFUNC(0,start_needflags,(void)) +{ + needflags=1; +} + +MIDFUNC(0,end_needflags,(void)) +{ + needflags=0; +} + +MIDFUNC(0,make_flags_live,(void)) +{ + make_flags_live_internal(); +} + +MIDFUNC(2,bt_l_ri,(RR4 r, IMM i)) /* This is defined as only affecting C */ +{ + int size=4; + if (i<16) + size=2; + CLOBBER_BT; + r=readreg(r,size); + raw_bt_l_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,bt_l_rr,(RR4 r, RR4 b)) /* This is defined as only affecting C */ +{ + CLOBBER_BT; + r=readreg(r,4); + b=readreg(b,4); + raw_bt_l_rr(r,b); + unlock2(r); + unlock2(b); +} + +MIDFUNC(2,btc_l_rr,(RW4 r, RR4 b)) +{ + CLOBBER_BT; + b=readreg(b,4); + r=rmw(r,4,4); + raw_btc_l_rr(r,b); + unlock2(r); + unlock2(b); +} + +MIDFUNC(2,btr_l_rr,(RW4 r, RR4 b)) +{ + CLOBBER_BT; + b=readreg(b,4); + r=rmw(r,4,4); + raw_btr_l_rr(r,b); + unlock2(r); + unlock2(b); +} + +MIDFUNC(2,bts_l_rr,(RW4 r, RR4 b)) +{ + CLOBBER_BT; + b=readreg(b,4); + r=rmw(r,4,4); + raw_bts_l_rr(r,b); + unlock2(r); + unlock2(b); +} + +MIDFUNC(2,mov_l_rm,(W4 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,4); + raw_mov_l_rm(d,s); + unlock2(d); +} + +MIDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor)) +{ + CLOBBER_MOV; + index=readreg(index,4); + d=writereg(d,4); + raw_mov_l_rm_indexed(d,base,index,factor); + unlock2(index); + unlock2(d); +} + +MIDFUNC(2,mov_l_mi,(IMM d, IMM s)) +{ + CLOBBER_MOV; + raw_mov_l_mi(d,s); +} + +MIDFUNC(2,mov_w_mi,(IMM d, IMM s)) +{ + CLOBBER_MOV; + raw_mov_w_mi(d,s); +} + +MIDFUNC(2,mov_b_mi,(IMM d, IMM s)) +{ + CLOBBER_MOV; + raw_mov_b_mi(d,s); +} + +MIDFUNC(2,rol_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROL; + r=rmw(r,1,1); + raw_rol_b_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,rol_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROL; + r=rmw(r,2,2); + raw_rol_w_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,rol_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROL; + r=rmw(r,4,4); + raw_rol_l_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,rol_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(rol_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROL; + r=readreg(r,1); + d=rmw(d,4,4); + raw_rol_l_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,rol_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(rol_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROL; + r=readreg(r,1); + d=rmw(d,2,2); + raw_rol_w_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,rol_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(rol_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROL; + r=readreg(r,1); + d=rmw(d,1,1); + raw_rol_b_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,shll_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(shll_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHLL; + r=readreg(r,1); + d=rmw(d,4,4); + raw_shll_l_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,shll_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shll_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHLL; + r=readreg(r,1); + d=rmw(d,2,2); + raw_shll_w_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,shll_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shll_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHLL; + r=readreg(r,1); + d=rmw(d,1,1); + raw_shll_b_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,ror_b_ri,(RR1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROR; + r=rmw(r,1,1); + raw_ror_b_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,ror_w_ri,(RR2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROR; + r=rmw(r,2,2); + raw_ror_w_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,ror_l_ri,(RR4 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROR; + r=rmw(r,4,4); + raw_ror_l_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,ror_l_rr,(RR4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(ror_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROR; + r=readreg(r,1); + d=rmw(d,4,4); + raw_ror_l_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,ror_w_rr,(RR2 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(ror_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROR; + r=readreg(r,1); + d=rmw(d,2,2); + raw_ror_w_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,ror_b_rr,(RR1 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(ror_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + + CLOBBER_ROR; + r=readreg(r,1); + d=rmw(d,1,1); + raw_ror_b_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,shrl_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(shrl_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRL; + r=readreg(r,1); + d=rmw(d,4,4); + raw_shrl_l_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,shrl_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shrl_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRL; + r=readreg(r,1); + d=rmw(d,2,2); + raw_shrl_w_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,shrl_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shrl_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + + CLOBBER_SHRL; + r=readreg(r,1); + d=rmw(d,1,1); + raw_shrl_b_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,shll_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(r) && !needflags) { + live.state[r].val<<=i; + return; + } + CLOBBER_SHLL; + r=rmw(r,4,4); + raw_shll_l_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,shll_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHLL; + r=rmw(r,2,2); + raw_shll_w_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,shll_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHLL; + r=rmw(r,1,1); + raw_shll_b_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(r) && !needflags) { + live.state[r].val>>=i; + return; + } + CLOBBER_SHRL; + r=rmw(r,4,4); + raw_shrl_l_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRL; + r=rmw(r,2,2); + raw_shrl_w_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRL; + r=rmw(r,1,1); + raw_shrl_b_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,shra_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRA; + r=rmw(r,4,4); + raw_shra_l_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,shra_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRA; + r=rmw(r,2,2); + raw_shra_w_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,shra_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRA; + r=rmw(r,1,1); + raw_shra_b_ri(r,i); + unlock2(r); +} + +MIDFUNC(2,shra_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(shra_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRA; + r=readreg(r,1); + d=rmw(d,4,4); + raw_shra_l_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,shra_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shra_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRA; + r=readreg(r,1); + d=rmw(d,2,2); + raw_shra_w_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,shra_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shra_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + + CLOBBER_SHRA; + r=readreg(r,1); + d=rmw(d,1,1); + raw_shra_b_rr(d,r); + unlock2(r); + unlock2(d); +} + +MIDFUNC(2,setcc,(W1 d, IMM cc)) +{ + CLOBBER_SETCC; + d=writereg(d,1); + raw_setcc(d,cc); + unlock2(d); +} + +MIDFUNC(2,setcc_m,(IMM d, IMM cc)) +{ + CLOBBER_SETCC; + raw_setcc_m(d,cc); +} + +MIDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc)) +{ + if (d==s) + return; + CLOBBER_CMOV; + s=readreg(s,4); + d=rmw(d,4,4); + raw_cmov_l_rr(d,s,cc); + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,bsf_l_rr,(W4 d, W4 s)) +{ + CLOBBER_BSF; + s = readreg(s, 4); + d = writereg(d, 4); + raw_bsf_l_rr(d, s); + unlock2(s); + unlock2(d); +} + +/* 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); +} + +MIDFUNC(2,imul_32_32,(RW4 d, RR4 s)) +{ + CLOBBER_MUL; + s=readreg(s,4); + d=rmw(d,4,4); + raw_imul_32_32(d,s); + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,imul_64_32,(RW4 d, RW4 s)) +{ + CLOBBER_MUL; + s=rmw_specific(s,4,4,MUL_NREG2); + d=rmw_specific(d,4,4,MUL_NREG1); + raw_imul_64_32(d,s); + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,mul_64_32,(RW4 d, RW4 s)) +{ + CLOBBER_MUL; + s=rmw_specific(s,4,4,MUL_NREG2); + d=rmw_specific(d,4,4,MUL_NREG1); + raw_mul_64_32(d,s); + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) +{ + int isrmw; + + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s16)live.state[s].val); + return; + } + + CLOBBER_SE16; + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,2); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,2); + } + raw_sign_extend_16_rr(d,s); + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} + +MIDFUNC(2,sign_extend_8_rr,(W4 d, RR1 s)) +{ + int isrmw; + + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s8)live.state[s].val); + return; + } + + isrmw=(s==d); + CLOBBER_SE8; + if (!isrmw) { + s=readreg(s,1); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,1); + } + + raw_sign_extend_8_rr(d,s); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} + +MIDFUNC(2,zero_extend_16_rr,(W4 d, RR2 s)) +{ + int isrmw; + + if (isconst(s)) { + set_const(d,(uae_u32)(uae_u16)live.state[s].val); + return; + } + + isrmw=(s==d); + CLOBBER_ZE16; + if (!isrmw) { + s=readreg(s,2); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,2); + } + raw_zero_extend_16_rr(d,s); + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} + +MIDFUNC(2,zero_extend_8_rr,(W4 d, RR1 s)) +{ + int isrmw; + if (isconst(s)) { + set_const(d,(uae_u32)(uae_u8)live.state[s].val); + return; + } + + isrmw=(s==d); + CLOBBER_ZE8; + if (!isrmw) { + s=readreg(s,1); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,1); + } + + raw_zero_extend_8_rr(d,s); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} + +MIDFUNC(2,mov_b_rr,(W1 d, RR1 s)) +{ + if (d==s) + return; + if (isconst(s)) { + COMPCALL(mov_b_ri)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_MOV; + s=readreg(s,1); + d=writereg(d,1); + raw_mov_b_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,mov_w_rr,(W2 d, RR2 s)) +{ + if (d==s) + return; + if (isconst(s)) { + COMPCALL(mov_w_ri)(d,(uae_u16)live.state[s].val); + return; + } + + CLOBBER_MOV; + s=readreg(s,2); + d=writereg(d,2); + raw_mov_w_rr(d,s); + unlock2(d); + unlock2(s); +} + +/* read the long at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset)) +{ + if (isconst(s)) { + COMPCALL(mov_l_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + s=readreg(s,4); + d=writereg(d,4); + + raw_mov_l_rR(d,s,offset); + unlock2(d); + unlock2(s); +} + +/* read the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset)) +{ + if (isconst(s)) { + COMPCALL(mov_w_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + s=readreg(s,4); + d=writereg(d,2); + + raw_mov_w_rR(d,s,offset); + unlock2(d); + unlock2(s); +} + +/* read the long at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMM offset)) +{ + int sreg=s; + if (isconst(s)) { + COMPCALL(mov_l_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + s=readreg_offset(s,4); + offset+=get_offset(sreg); + d=writereg(d,4); + + raw_mov_l_brR(d,s,offset); + unlock2(d); + unlock2(s); +} + +/* read the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMM offset)) +{ + int sreg=s; + if (isconst(s)) { + COMPCALL(mov_w_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + remove_offset(d,-1); + s=readreg_offset(s,4); + offset+=get_offset(sreg); + d=writereg(d,2); + + raw_mov_w_brR(d,s,offset); + unlock2(d); + unlock2(s); +} + +/* read the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset)) +{ + int sreg=s; + if (isconst(s)) { + COMPCALL(mov_b_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + remove_offset(d,-1); + s=readreg_offset(s,4); + offset+=get_offset(sreg); + d=writereg(d,1); + + raw_mov_b_brR(d,s,offset); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_l_mi)(live.state[d].val+offset,i); + return; + } + + CLOBBER_MOV; + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_l_Ri(d,i,offset); + unlock2(d); +} + +MIDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_w_mi)(live.state[d].val+offset,i); + return; + } + + CLOBBER_MOV; + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_w_Ri(d,i,offset); + unlock2(d); +} + +/* Warning! OFFSET is byte sized only! */ +MIDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset)) +{ + if (isconst(d)) { + COMPCALL(mov_l_mr)(live.state[d].val+offset,s); + return; + } + if (isconst(s)) { + COMPCALL(mov_l_Ri)(d,live.state[s].val,offset); + return; + } + + CLOBBER_MOV; + s=readreg(s,4); + d=readreg(d,4); + + raw_mov_l_Rr(d,s,offset); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset)) +{ + if (isconst(d)) { + COMPCALL(mov_w_mr)(live.state[d].val+offset,s); + return; + } + if (isconst(s)) { + COMPCALL(mov_w_Ri)(d,(uae_u16)live.state[s].val,offset); + return; + } + + CLOBBER_MOV; + s=readreg(s,2); + d=readreg(d,4); + raw_mov_w_Rr(d,s,offset); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) +{ + if (isconst(s)) { + COMPCALL(mov_l_ri)(d,live.state[s].val+offset); + return; + } +#if USE_OFFSET + if (d==s) { + add_offset(d,offset); + return; + } +#endif + CLOBBER_LEA; + s=readreg(s,4); + d=writereg(d,4); + raw_lea_l_brr(d,s,offset); + unlock2(d); + unlock2(s); +} + +MIDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) +{ + if (!offset) { + COMPCALL(lea_l_rr_indexed)(d,s,index,factor); + return; + } + CLOBBER_LEA; + s=readreg(s,4); + index=readreg(index,4); + d=writereg(d,4); + + raw_lea_l_brr_indexed(d,s,index,factor,offset); + unlock2(d); + unlock2(index); + unlock2(s); +} + +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); + + raw_lea_l_rr_indexed(d,s,index,factor); + unlock2(d); + unlock2(index); + unlock2(s); +} + +/* write d to the long at the address contained in s+offset */ +MIDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_l_mr)(live.state[d].val+offset,s); + return; + } + + CLOBBER_MOV; + s=readreg(s,4); + d=readreg_offset(d,4); + offset+=get_offset(dreg); + + raw_mov_l_bRr(d,s,offset); + unlock2(d); + unlock2(s); +} + +/* write the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMM offset)) +{ + int dreg=d; + + if (isconst(d)) { + COMPCALL(mov_w_mr)(live.state[d].val+offset,s); + return; + } + + CLOBBER_MOV; + s=readreg(s,2); + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_w_bRr(d,s,offset); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_b_mr)(live.state[d].val+offset,s); + return; + } + + CLOBBER_MOV; + s=readreg(s,1); + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_b_bRr(d,s,offset); + unlock2(d); + unlock2(s); +} + +MIDFUNC(1,mid_bswap_32,(RW4 r)) +{ + + if (isconst(r)) { + uae_u32 oldv=live.state[r].val; + live.state[r].val=reverse32(oldv); + return; + } + + CLOBBER_SW32; + r=rmw(r,4,4); + raw_bswap_32(r); + unlock2(r); +} + +MIDFUNC(1,mid_bswap_16,(RW2 r)) +{ + if (isconst(r)) { + uae_u32 oldv=live.state[r].val; + live.state[r].val=((oldv>>8)&0xff) | ((oldv<<8)&0xff00) | + (oldv&0xffff0000); + return; + } + + CLOBBER_SW16; + r=rmw(r,2,2); + + raw_bswap_16(r); + unlock2(r); +} + +MIDFUNC(2,mov_l_rr,(W4 d, RR4 s)) +{ + int olds; + + if (d==s) { /* How pointless! */ + return; + } + if (isconst(s)) { + COMPCALL(mov_l_ri)(d,live.state[s].val); + return; + } + olds=s; + disassociate(d); + s=readreg_offset(s,4); + live.state[d].realreg=s; + live.state[d].realind=live.nat[s].nholds; + live.state[d].val=live.state[olds].val; + live.state[d].validsize=4; + live.state[d].dirtysize=4; + set_status(d,DIRTY); + + live.nat[s].holds[live.nat[s].nholds]=d; + live.nat[s].nholds++; + log_clobberreg(d); + D2(panicbug("Added %d to nreg %d(%d), now holds %d regs", d,s,live.state[d].realind,live.nat[s].nholds)); + unlock2(s); +} + +MIDFUNC(2,mov_l_mr,(IMM d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(mov_l_mi)(d,live.state[s].val); + return; + } + CLOBBER_MOV; + s=readreg(s,4); + + raw_mov_l_mr(d,s); + unlock2(s); +} + +MIDFUNC(2,mov_w_mr,(IMM d, RR2 s)) +{ + if (isconst(s)) { + COMPCALL(mov_w_mi)(d,(uae_u16)live.state[s].val); + return; + } + CLOBBER_MOV; + s=readreg(s,2); + + raw_mov_w_mr(d,s); + unlock2(s); +} + +MIDFUNC(2,mov_w_rm,(W2 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,2); + + raw_mov_w_rm(d,s); + unlock2(d); +} + +MIDFUNC(2,mov_b_mr,(IMM d, RR1 s)) +{ + if (isconst(s)) { + COMPCALL(mov_b_mi)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_MOV; + s=readreg(s,1); + + raw_mov_b_mr(d,s); + unlock2(s); +} + +MIDFUNC(2,mov_b_rm,(W1 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,1); + + raw_mov_b_rm(d,s); + unlock2(d); +} + +MIDFUNC(2,mov_l_ri,(W4 d, IMM s)) +{ + set_const(d,s); + return; +} + +MIDFUNC(2,mov_w_ri,(W2 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,2); + + raw_mov_w_ri(d,s); + unlock2(d); +} + +MIDFUNC(2,mov_b_ri,(W1 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,1); + + raw_mov_b_ri(d,s); + unlock2(d); +} + +MIDFUNC(2,test_l_ri,(RR4 d, IMM i)) +{ + CLOBBER_TEST; + d=readreg(d,4); + + raw_test_l_ri(d,i); + unlock2(d); +} + +MIDFUNC(2,test_l_rr,(RR4 d, RR4 s)) +{ + CLOBBER_TEST; + d=readreg(d,4); + s=readreg(s,4); + + raw_test_l_rr(d,s);; + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,test_w_rr,(RR2 d, RR2 s)) +{ + CLOBBER_TEST; + d=readreg(d,2); + s=readreg(s,2); + + raw_test_w_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,test_b_rr,(RR1 d, RR1 s)) +{ + CLOBBER_TEST; + d=readreg(d,1); + s=readreg(s,1); + + raw_test_b_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,and_l_ri,(RW4 d, IMM i)) +{ + if (isconst(d) && !needflags) { + live.state[d].val &= i; + return; + } + + CLOBBER_AND; + d=rmw(d,4,4); + + raw_and_l_ri(d,i); + unlock2(d); +} + +MIDFUNC(2,and_l,(RW4 d, RR4 s)) +{ + CLOBBER_AND; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_and_l(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,and_w,(RW2 d, RR2 s)) +{ + CLOBBER_AND; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_and_w(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,and_b,(RW1 d, RR1 s)) +{ + CLOBBER_AND; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_and_b(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,or_l_ri,(RW4 d, IMM i)) +{ + if (isconst(d) && !needflags) { + live.state[d].val|=i; + return; + } + CLOBBER_OR; + d=rmw(d,4,4); + + raw_or_l_ri(d,i); + unlock2(d); +} + +MIDFUNC(2,or_l,(RW4 d, RR4 s)) +{ + if (isconst(d) && isconst(s) && !needflags) { + live.state[d].val|=live.state[s].val; + return; + } + CLOBBER_OR; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_or_l(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,or_w,(RW2 d, RR2 s)) +{ + CLOBBER_OR; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_or_w(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,or_b,(RW1 d, RR1 s)) +{ + CLOBBER_OR; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_or_b(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,adc_l,(RW4 d, RR4 s)) +{ + CLOBBER_ADC; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_adc_l(d,s); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,adc_w,(RW2 d, RR2 s)) +{ + CLOBBER_ADC; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_adc_w(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,adc_b,(RW1 d, RR1 s)) +{ + CLOBBER_ADC; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_adc_b(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,add_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(add_l_ri)(d,live.state[s].val); + return; + } + + CLOBBER_ADD; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_add_l(d,s); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,add_w,(RW2 d, RR2 s)) +{ + if (isconst(s)) { + COMPCALL(add_w_ri)(d,(uae_u16)live.state[s].val); + return; + } + + CLOBBER_ADD; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_add_w(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,add_b,(RW1 d, RR1 s)) +{ + if (isconst(s)) { + COMPCALL(add_b_ri)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_ADD; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_add_b(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,sub_l_ri,(RW4 d, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(d) && !needflags) { + live.state[d].val-=i; + return; + } +#if USE_OFFSET + if (!needflags) { + add_offset(d,-i); + return; + } +#endif + + CLOBBER_SUB; + d=rmw(d,4,4); + + raw_sub_l_ri(d,i); + unlock2(d); +} + +MIDFUNC(2,sub_w_ri,(RW2 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_SUB; + d=rmw(d,2,2); + + raw_sub_w_ri(d,i); + unlock2(d); +} + +MIDFUNC(2,sub_b_ri,(RW1 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_SUB; + d=rmw(d,1,1); + + raw_sub_b_ri(d,i); + + unlock2(d); +} + +MIDFUNC(2,add_l_ri,(RW4 d, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(d) && !needflags) { + live.state[d].val+=i; + return; + } +#if USE_OFFSET + if (!needflags) { + add_offset(d,i); + return; + } +#endif + CLOBBER_ADD; + d=rmw(d,4,4); + raw_add_l_ri(d,i); + unlock2(d); +} + +MIDFUNC(2,add_w_ri,(RW2 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_ADD; + d=rmw(d,2,2); + + raw_add_w_ri(d,i); + unlock2(d); +} + +MIDFUNC(2,add_b_ri,(RW1 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_ADD; + d=rmw(d,1,1); + + raw_add_b_ri(d,i); + + unlock2(d); +} + +MIDFUNC(2,sbb_l,(RW4 d, RR4 s)) +{ + CLOBBER_SBB; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_sbb_l(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,sbb_w,(RW2 d, RR2 s)) +{ + CLOBBER_SBB; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_sbb_w(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,sbb_b,(RW1 d, RR1 s)) +{ + CLOBBER_SBB; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_sbb_b(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,sub_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(sub_l_ri)(d,live.state[s].val); + return; + } + + CLOBBER_SUB; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_sub_l(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,sub_w,(RW2 d, RR2 s)) +{ + if (isconst(s)) { + COMPCALL(sub_w_ri)(d,(uae_u16)live.state[s].val); + return; + } + + CLOBBER_SUB; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_sub_w(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,sub_b,(RW1 d, RR1 s)) +{ + if (isconst(s)) { + COMPCALL(sub_b_ri)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_SUB; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_sub_b(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,cmp_l,(RR4 d, RR4 s)) +{ + CLOBBER_CMP; + s=readreg(s,4); + d=readreg(d,4); + + raw_cmp_l(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,cmp_w,(RR2 d, RR2 s)) +{ + CLOBBER_CMP; + s=readreg(s,2); + d=readreg(d,2); + + raw_cmp_w(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,cmp_b,(RR1 d, RR1 s)) +{ + CLOBBER_CMP; + s=readreg(s,1); + d=readreg(d,1); + + raw_cmp_b(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,xor_l,(RW4 d, RR4 s)) +{ + CLOBBER_XOR; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_xor_l(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,xor_w,(RW2 d, RR2 s)) +{ + CLOBBER_XOR; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_xor_w(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,xor_b,(RW1 d, RR1 s)) +{ + CLOBBER_XOR; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_xor_b(d,s); + unlock2(d); + unlock2(s); +} + +#if defined(UAE) +MIDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) +{ + clobber_flags(); + in1=readreg_specific(in1,isize1,REG_PAR1); + in2=readreg_specific(in2,isize2,REG_PAR2); + r=readreg(r,4); + prepare_for_call_1(); + unlock2(r); + unlock2(in1); + unlock2(in2); + prepare_for_call_2(); + compemu_raw_call_r(r); +} +#endif + +#if defined(UAE) +MIDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) +{ + clobber_flags(); + + if (osize==4) { + if (out1!=in1 && out1!=r) { + COMPCALL(forget_about)(out1); + } + } + else { + tomem_c(out1); + } + + in1=readreg_specific(in1,isize,REG_PAR1); + r=readreg(r,4); + + prepare_for_call_1(); + unlock2(in1); + unlock2(r); + + prepare_for_call_2(); + + compemu_raw_call_r(r); + + live.nat[REG_RESULT].holds[0]=out1; + live.nat[REG_RESULT].nholds=1; + live.nat[REG_RESULT].touched=touchcnt++; + + live.state[out1].realreg=REG_RESULT; + live.state[out1].realind=0; + live.state[out1].val=0; + live.state[out1].validsize=osize; + live.state[out1].dirtysize=osize; + set_status(out1,DIRTY); +} +#endif + +MIDFUNC(0,nop,(void)) +{ + raw_emit_nop(); +} + +/* forget_about() takes a mid-layer register */ +MIDFUNC(1,forget_about,(W4 r)) +{ + if (isinreg(r)) + disassociate(r); + live.state[r].val=0; + set_status(r,UNDEF); +} + +MIDFUNC(1,f_forget_about,(FW r)) +{ + if (f_isinreg(r)) + f_disassociate(r); + live.fate[r].status=UNDEF; +} + +// ARM optimized functions + +MIDFUNC(2,arm_ADD_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(arm_ADD_l_ri)(d,live.state[s].val); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + raw_ADD_l_rr(d,s); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,arm_ADD_l_ri,(RW4 d, IMM i)) +{ + if (!i) return; + if (isconst(d)) { + live.state[d].val+=i; + return; + } +#if USE_OFFSET + add_offset(d,i); + return; +#endif + d=rmw(d,4,4); + + raw_LDR_l_ri(REG_WORK1, i); + raw_ADD_l_rr(d,REG_WORK1); + unlock2(d); +} + +MIDFUNC(2,arm_ADD_l_ri8,(RW4 d, IMM i)) +{ + if (!i) return; + if (isconst(d)) { + live.state[d].val+=i; + return; + } +#if USE_OFFSET + add_offset(d,i); + return; +#endif + d=rmw(d,4,4); + + raw_ADD_l_rri(d,d,i); + unlock2(d); +} + +MIDFUNC(2,arm_SUB_l_ri8,(RW4 d, IMM i)) +{ + if (!i) return; + if (isconst(d)) { + live.state[d].val-=i; + return; + } +#if USE_OFFSET + add_offset(d,-i); + return; +#endif + d=rmw(d,4,4); + + raw_SUB_l_rri(d,d,i); + unlock2(d); +} + +MIDFUNC(2,arm_AND_l,(RW4 d, RR4 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + raw_AND_l_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,arm_AND_w,(RW2 d, RR2 s)) +{ + s=readreg(s,2); + d=rmw(d,2,2); + + raw_AND_w_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,arm_AND_b,(RW1 d, RR1 s)) +{ + s=readreg(s,1); + d=rmw(d,1,1); + + raw_AND_b_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,arm_AND_l_ri8,(RW4 d, IMM i)) +{ + if (isconst(d)) { + live.state[d].val &= i; + return; + } + + d=rmw(d,4,4); + + raw_AND_l_ri(d,i); + unlock2(d); +} + +MIDFUNC(2,arm_EOR_b,(RW1 d, RR1 s)) +{ + s=readreg(s,1); + d=rmw(d,1,1); + + raw_EOR_b_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,arm_EOR_l,(RW4 d, RR4 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + raw_EOR_l_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,arm_EOR_w,(RW2 d, RR2 s)) +{ + s=readreg(s,2); + d=rmw(d,2,2); + + raw_EOR_w_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,arm_ORR_b,(RW1 d, RR1 s)) +{ + s=readreg(s,1); + d=rmw(d,1,1); + + raw_ORR_b_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,arm_ORR_l,(RW4 d, RR4 s)) +{ + if (isconst(d) && isconst(s)) { + live.state[d].val|=live.state[s].val; + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + raw_ORR_l_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,arm_ORR_w,(RW2 d, RR2 s)) +{ + s=readreg(s,2); + d=rmw(d,2,2); + + raw_ORR_w_rr(d,s); + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,arm_ROR_l_ri8,(RW4 r, IMM i)) +{ + if (!i) + return; + + r=rmw(r,4,4); + raw_ROR_l_ri(r,i); + unlock2(r); +} + +// Other +static inline void flush_cpu_icache(void *start, void *stop) +{ + + register void *_beg __asm ("a1") = start; + register void *_end __asm ("a2") = stop; + register void *_flg __asm ("a3") = 0; +#ifdef __ARM_EABI__ + register unsigned long _scno __asm ("r7") = 0xf0002; + __asm __volatile ("swi 0x0 @ sys_cacheflush" + : "=r" (_beg) + : "0" (_beg), "r" (_end), "r" (_flg), "r" (_scno)); +#else + __asm __volatile ("swi 0x9f0002 @ sys_cacheflush" + : "=r" (_beg) + : "0" (_beg), "r" (_end), "r" (_flg)); +#endif +} + +static inline void write_jmp_target(uae_u32* jmpaddr, cpuop_func* a) { + *(jmpaddr) = (uae_u32) a; + flush_cpu_icache((void *) jmpaddr, (void *) &jmpaddr[1]); +} + +static inline void emit_jmp_target(uae_u32 a) { + emit_long((uae_u32) a); +} diff --git a/jit/compemu_midfunc_arm.h b/jit/compemu_midfunc_arm.h new file mode 100644 index 00000000..baedb153 --- /dev/null +++ b/jit/compemu_midfunc_arm.h @@ -0,0 +1,186 @@ +/* + * compiler/compemu_midfunc_arm.h - Native MIDFUNCS for ARM + * + * Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note: + * File is included by compemu.h + * + */ + +// Arm optimized midfunc +DECLARE_MIDFUNC(arm_ADD_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(arm_ADD_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(arm_ADD_l_ri8(RW4 d, IMM i)); +DECLARE_MIDFUNC(arm_SUB_l_ri8(RW4 d, IMM i)); +DECLARE_MIDFUNC(arm_AND_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(arm_AND_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(arm_AND_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(arm_AND_l_ri8(RW4 d, IMM i)); +DECLARE_MIDFUNC(arm_EOR_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(arm_EOR_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(arm_EOR_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(arm_ORR_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(arm_ORR_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(arm_ORR_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(arm_ROR_l_ri8(RW4 r, IMM i)); + +// Emulated midfunc +DECLARE_MIDFUNC(bt_l_ri(RR4 r, IMM i)); +DECLARE_MIDFUNC(bt_l_rr(RR4 r, RR4 b)); +DECLARE_MIDFUNC(btc_l_rr(RW4 r, RR4 b)); +DECLARE_MIDFUNC(bts_l_rr(RW4 r, RR4 b)); +DECLARE_MIDFUNC(btr_l_rr(RW4 r, RR4 b)); +DECLARE_MIDFUNC(mov_l_rm(W4 d, IMM s)); +DECLARE_MIDFUNC(mov_l_rm_indexed(W4 d, IMM base, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_l_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(mov_w_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(mov_b_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(rol_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(rol_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(rol_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(rol_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(rol_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(rol_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(shll_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(shll_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(shll_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(ror_b_ri(RR1 r, IMM i)); +DECLARE_MIDFUNC(ror_w_ri(RR2 r, IMM i)); +DECLARE_MIDFUNC(ror_l_ri(RR4 r, IMM i)); +DECLARE_MIDFUNC(ror_l_rr(RR4 d, RR1 r)); +DECLARE_MIDFUNC(ror_w_rr(RR2 d, RR1 r)); +DECLARE_MIDFUNC(ror_b_rr(RR1 d, RR1 r)); +DECLARE_MIDFUNC(shrl_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(shrl_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(shrl_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(shra_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(shra_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(shra_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(shll_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(shll_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(shll_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(shrl_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(shrl_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(shrl_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(shra_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(shra_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(shra_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(setcc(W1 d, IMM cc)); +DECLARE_MIDFUNC(setcc_m(IMM d, IMM cc)); +DECLARE_MIDFUNC(cmov_l_rr(RW4 d, RR4 s, IMM cc)); +DECLARE_MIDFUNC(bsf_l_rr(W4 d, RR4 s)); +DECLARE_MIDFUNC(pop_l(W4 d)); +DECLARE_MIDFUNC(push_l(RR4 s)); +DECLARE_MIDFUNC(sign_extend_16_rr(W4 d, RR2 s)); +DECLARE_MIDFUNC(sign_extend_8_rr(W4 d, RR1 s)); +DECLARE_MIDFUNC(zero_extend_16_rr(W4 d, RR2 s)); +DECLARE_MIDFUNC(zero_extend_8_rr(W4 d, RR1 s)); +DECLARE_MIDFUNC(simulate_bsf(W4 tmp, RW4 s)); +DECLARE_MIDFUNC(imul_64_32(RW4 d, RW4 s)); +DECLARE_MIDFUNC(mul_64_32(RW4 d, RW4 s)); +DECLARE_MIDFUNC(imul_32_32(RW4 d, RR4 s)); +DECLARE_MIDFUNC(mov_b_rr(W1 d, RR1 s)); +DECLARE_MIDFUNC(mov_w_rr(W2 d, RR2 s)); +DECLARE_MIDFUNC(mov_l_rR(W4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_rR(W2 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_l_brR(W4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_brR(W2 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_b_brR(W1 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_l_Ri(RR4 d, IMM i, IMM offset)); +DECLARE_MIDFUNC(mov_w_Ri(RR4 d, IMM i, IMM offset)); +DECLARE_MIDFUNC(mov_l_Rr(RR4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_Rr(RR4 d, RR2 s, IMM offset)); +DECLARE_MIDFUNC(lea_l_brr(W4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(lea_l_brr_indexed(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)); +DECLARE_MIDFUNC(lea_l_rr_indexed(W4 d, RR4 s, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_l_bRr(RR4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_bRr(RR4 d, RR2 s, IMM offset)); +DECLARE_MIDFUNC(mov_b_bRr(RR4 d, RR1 s, IMM offset)); +DECLARE_MIDFUNC(mid_bswap_32(RW4 r)); +DECLARE_MIDFUNC(mid_bswap_16(RW2 r)); +DECLARE_MIDFUNC(mov_l_rr(W4 d, RR4 s)); +DECLARE_MIDFUNC(mov_l_mr(IMM d, RR4 s)); +DECLARE_MIDFUNC(mov_w_mr(IMM d, RR2 s)); +DECLARE_MIDFUNC(mov_w_rm(W2 d, IMM s)); +DECLARE_MIDFUNC(mov_b_mr(IMM d, RR1 s)); +DECLARE_MIDFUNC(mov_b_rm(W1 d, IMM s)); +DECLARE_MIDFUNC(mov_l_ri(W4 d, IMM s)); +DECLARE_MIDFUNC(mov_w_ri(W2 d, IMM s)); +DECLARE_MIDFUNC(mov_b_ri(W1 d, IMM s)); +DECLARE_MIDFUNC(test_l_ri(RR4 d, IMM i)); +DECLARE_MIDFUNC(test_l_rr(RR4 d, RR4 s)); +DECLARE_MIDFUNC(test_w_rr(RR2 d, RR2 s)); +DECLARE_MIDFUNC(test_b_rr(RR1 d, RR1 s)); +DECLARE_MIDFUNC(and_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(and_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(and_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(and_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(or_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(or_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(or_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(or_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(adc_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(adc_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(adc_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(add_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(add_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(add_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(sub_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(sub_w_ri(RW2 d, IMM i)); +DECLARE_MIDFUNC(sub_b_ri(RW1 d, IMM i)); +DECLARE_MIDFUNC(add_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(add_w_ri(RW2 d, IMM i)); +DECLARE_MIDFUNC(add_b_ri(RW1 d, IMM i)); +DECLARE_MIDFUNC(sbb_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(sbb_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(sbb_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(sub_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(sub_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(sub_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(cmp_l(RR4 d, RR4 s)); +DECLARE_MIDFUNC(cmp_w(RR2 d, RR2 s)); +DECLARE_MIDFUNC(cmp_b(RR1 d, RR1 s)); +DECLARE_MIDFUNC(xor_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(xor_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(xor_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(call_r_02(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)); +DECLARE_MIDFUNC(call_r_11(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)); +DECLARE_MIDFUNC(live_flags(void)); +DECLARE_MIDFUNC(dont_care_flags(void)); +DECLARE_MIDFUNC(duplicate_carry(void)); +DECLARE_MIDFUNC(restore_carry(void)); +DECLARE_MIDFUNC(start_needflags(void)); +DECLARE_MIDFUNC(end_needflags(void)); +DECLARE_MIDFUNC(make_flags_live(void)); +DECLARE_MIDFUNC(forget_about(W4 r)); +DECLARE_MIDFUNC(nop(void)); + +DECLARE_MIDFUNC(f_forget_about(FW r)); + + + + diff --git a/jit/compemu_midfunc_arm2.cpp b/jit/compemu_midfunc_arm2.cpp new file mode 100644 index 00000000..5f55d1bf --- /dev/null +++ b/jit/compemu_midfunc_arm2.cpp @@ -0,0 +1,5195 @@ +/* + * compiler/compemu_midfunc_arm.cpp - Native MIDFUNCS for ARM (JIT v2) + * + * Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note: + * File is included by compemu_support.cpp + * + */ + +const uae_u32 ARM_CCR_MAP[] = { 0, ARM_C_FLAG, // 1 C + ARM_V_FLAG, // 2 V + ARM_C_FLAG | ARM_V_FLAG, // 3 VC + ARM_Z_FLAG, // 4 Z + ARM_Z_FLAG | ARM_C_FLAG, // 5 ZC + ARM_Z_FLAG | ARM_V_FLAG, // 6 ZV + ARM_Z_FLAG | ARM_C_FLAG | ARM_V_FLAG, // 7 ZVC + ARM_N_FLAG, // 8 N + ARM_N_FLAG | ARM_C_FLAG, // 9 NC + ARM_N_FLAG | ARM_V_FLAG, // 10 NV + ARM_N_FLAG | ARM_C_FLAG | ARM_V_FLAG, // 11 NVC + ARM_N_FLAG | ARM_Z_FLAG, // 12 NZ + ARM_N_FLAG | ARM_Z_FLAG | ARM_C_FLAG, // 13 NZC + ARM_N_FLAG | ARM_Z_FLAG | ARM_V_FLAG, // 14 NZV + ARM_N_FLAG | ARM_Z_FLAG | ARM_C_FLAG | ARM_V_FLAG, // 15 NZVC + }; + +// First we start with some helper functions (may be moved to codegen_arm) +static inline void UNSIGNED8_IMM_2_REG(W4 r, IMM v) { + MOV_ri8(r, (uint8) v); +} + +static inline void SIGNED8_IMM_2_REG(W4 r, IMM v) { + if (v & 0x80) { + MVN_ri8(r, (uint8) ~v); + } else { + MOV_ri8(r, (uint8) v); + } +} + +static inline void UNSIGNED16_IMM_2_REG(W4 r, IMM v) { + MOV_ri8(r, (uint8) v); + ORR_rri8RORi(r, r, (uint8)(v >> 8), 24); +} + +static inline void SIGNED16_IMM_2_REG(W4 r, IMM v) { +#if defined(ARMV6_ASSEMBLY) + MOV_ri8(r, (uint8) v); + ORR_rri8RORi(r, r, (uint8)(v >> 8), 24); + SXTH_rr(r, r); +#else + MOV_ri8(r, (uint8)(v << 16)); + ORR_rri8RORi(r, r, (uint8)(v >> 8), 8); + ASR_rri(r, r, 16); +#endif +} + +static inline void UNSIGNED8_REG_2_REG(W4 d, RR4 s) { +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(d, s); +#else + ROR_rri(d, s, 8); + LSR_rri(d, d, 24); +#endif +} + +static inline void SIGNED8_REG_2_REG(W4 d, RR4 s) { +#if defined(ARMV6_ASSEMBLY) + SXTB_rr(d, s); +#else + ROR_rri(d, s, 8); + ASR_rri(d, d, 24); +#endif +} + +static inline void UNSIGNED16_REG_2_REG(W4 d, RR4 s) { +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(d, s); +#else + LSL_rri(d, s, 16); + LSR_rri(d, d, 16); +#endif +} + +static inline void SIGNED16_REG_2_REG(W4 d, RR4 s) { +#if defined(ARMV6_ASSEMBLY) + SXTH_rr(d, s); +#else + LSL_rri(d, s, 16); + ASR_rri(d, d, 16); +#endif +} + +#define ZERO_EXTEND_8_REG_2_REG(d,s) UNSIGNED8_REG_2_REG(d,s) +#define ZERO_EXTEND_16_REG_2_REG(d,s) UNSIGNED16_REG_2_REG(d,s) +#define SIGN_EXTEND_8_REG_2_REG(d,s) SIGNED8_REG_2_REG(d,s) +#define SIGN_EXTEND_16_REG_2_REG(d,s) SIGNED16_REG_2_REG(d,s) + +MIDFUNC(0,restore_inverted_carry,(void)) +{ + RR4 r=readreg(FLAGX,4); + MRS_CPSR(REG_WORK1); + TEQ_ri(r,1); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_C_FLAG); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSRf_r(REG_WORK1); + unlock2(r); +} + +/* + * ADD + * Operand Syntax: , Dn + * Dn, + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if an overflow is generated. Cleared otherwise. + * C Set if a carry is generated. Cleared otherwise. + * + */ +MIDFUNC(3,jnf_ADD_imm,(W4 d, RR4 s, IMM v)) +{ + if (isconst(s)) { + set_const(d,live.state[s].val+v); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + compemu_raw_mov_l_ri(REG_WORK1, v); + ADD_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ADD,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jnf_ADD_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + ADD_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_ADD_b_imm,(W4 d, RR1 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_IMM_2_REG(REG_WORK2, (uint8)v); + SIGNED8_REG_2_REG(REG_WORK1, s); + ADDS_rrr(d,REG_WORK1,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ADD_b,(W4 d, RR1 s, RR1 v)) +{ + if (isconst(v)) { + COMPCALL(jff_ADD_b_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + ADDS_rrr(d,REG_WORK1,REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_ADD_w_imm,(W4 d, RR2 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_IMM_2_REG(REG_WORK2, (uint16)v); + SIGNED16_REG_2_REG(REG_WORK1, s); + ADDS_rrr(d,REG_WORK1,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ADD_w,(W4 d, RR2 s, RR2 v)) +{ + if (isconst(v)) { + COMPCALL(jff_ADD_w_imm)(d,s,live.state[v].val); + return; + } + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + ADDS_rrr(d,REG_WORK1,REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_ADD_l_imm,(W4 d, RR4 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + compemu_raw_mov_l_ri(REG_WORK2, v); + ADDS_rrr(d,s,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ADD_l,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jff_ADD_l_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + ADDS_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +/* + * ADDA + * Operand Syntax: , An + * + * Operand Size: 16,32 + * + * Flags: Not affected. + * + */ +MIDFUNC(2,jnf_ADDA_b,(W4 d, RR1 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + SIGNED8_REG_2_REG(REG_WORK1,s); + ADD_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jnf_ADDA_w,(W4 d, RR2 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + SIGNED16_REG_2_REG(REG_WORK1,s); + ADD_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jnf_ADDA_l,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + ADD_rrr(d,d,s); + + unlock2(d); + unlock2(s); +} + +/* + * ADDX + * Operand Syntax: Dy, Dx + * -(Ay), -(Ax) + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Cleared if the result is nonzero; unchanged otherwise. + * V Set if an overflow is generated. Cleared otherwise. + * C Set if a carry is generated. Cleared otherwise. + * + * Attention: Z is cleared only if the result is nonzero. Unchanged otherwise + * + */ +MIDFUNC(3,jnf_ADDX,(W4 d, RR4 s, RR4 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + ADC_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_ADDX_b,(W4 d, RR1 s, RR1 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + PUSH(REG_WORK2); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + ADCS_rrr(d,REG_WORK1,REG_WORK2); + + POP(REG_WORK2); + MRS_CPSR(REG_WORK1); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_ADDX_w,(W4 d, RR2 s, RR2 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + PUSH(REG_WORK2); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + ADCS_rrr(d,REG_WORK1,REG_WORK2); + + POP(REG_WORK2); + MRS_CPSR(REG_WORK1); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_ADDX_l,(W4 d, RR4 s, RR4 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + PUSH(REG_WORK2); + + ADCS_rrr(d,s,v); + + POP(REG_WORK2); + MRS_CPSR(REG_WORK1); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +/* + * ANDI + * Operand Syntax: #, CCR + * + * Operand Size: 8 + * + * X Cleared if bit 4 of immediate operand is zero. Unchanged otherwise. + * N Cleared if bit 3 of immediate operand is zero. Unchanged otherwise. + * Z Cleared if bit 2 of immediate operand is zero. Unchanged otherwise. + * V Cleared if bit 1 of immediate operand is zero. Unchanged otherwise. + * C Cleared if bit 0 of immediate operand is zero. Unchanged otherwise. + * + */ +MIDFUNC(1,jff_ANDSR,(IMM s, IMM x)) +{ + MRS_CPSR(REG_WORK1); + AND_rri(REG_WORK1, REG_WORK1, s); + MSR_CPSRf_r(REG_WORK1); + + if (!x) { + compemu_raw_mov_l_ri(REG_WORK1, (uintptr)live.state[FLAGX].mem); + MOV_ri(REG_WORK2, 0); + STRB_rR(REG_WORK2, REG_WORK1); + } +} + +/* + * AND + * Operand Syntax: , Dn + * Dn, + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the most significant bit of the result is set. + * Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(3,jnf_AND,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(s) && isconst(v)) { + set_const(d, + live.state[s].val&live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + AND_rrr(d, s, v); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_AND_b,(W4 d, RR1 s, RR1 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + ANDS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_AND_w,(W4 d, RR2 s, RR2 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + ANDS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_AND_l,(W4 d, RR4 s, RR4 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + ANDS_rrr(d, s,v); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +/* + * ASL + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if the most significant bit is changed at any time during the shift operation. Cleared otherwise. + * C Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * + */ +MIDFUNC(3,jff_ASL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d, s, 24); + if (i) { + MRS_CPSR(REG_WORK1); // store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except N & Z + PUSH(REG_WORK1); + + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rri(REG_WORK2, REG_WORK2, (i+1)); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, d, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// restore flags + + LSLS_rri(d,d,i); + } else { + MSR_CPSRf_i(0); + TST_rr(d,d); + } + REV_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ASL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d, s, 16); + if (i) { + MRS_CPSR(REG_WORK1); // store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except N & Z + PUSH(REG_WORK1); + + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rri(REG_WORK2, REG_WORK2, (i+1)); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, d, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// retore flags + + LSLS_rri(d,d,i); + } else { + MSR_CPSRf_i(0); + TST_rr(d,d); + } + ASR_rri(d,d, 16); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ASL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i) { + MRS_CPSR(REG_WORK1); // store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except C + PUSH(REG_WORK1); + + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rri(REG_WORK2, REG_WORK2, (i+1)); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, s, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// retore flags + + LSLS_rri(d,s,i); + } else { + MSR_CPSRf_i(0); + MOVS_rr(d, s); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ASL_b_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + // Calculate V Flag + MRS_CPSR(REG_WORK1);// store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except C + PUSH(REG_WORK1); + + LSL_rri(d, s, 24); + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rrr(REG_WORK2, REG_WORK2, i); + LSR_rri(REG_WORK2, REG_WORK2, 1); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, d, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// retore flags + + AND_rri(REG_WORK2, i, 63); + LSLS_rrr(d,d,REG_WORK2); + ASR_rri(d,d, 24); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ASL_w_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + // Calculate V Flag + MRS_CPSR(REG_WORK1);// store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except c + PUSH(REG_WORK1); + + LSL_rri(d, s, 16); + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rrr(REG_WORK2, REG_WORK2, i); + LSR_rri(REG_WORK2, REG_WORK2, 1); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, d, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// retore flags + + AND_rri(REG_WORK2, i, 63); + LSLS_rrr(d,d,REG_WORK2); + ASR_rri(d,d, 16); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ASL_l_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + // Calculate V Flag + MRS_CPSR(REG_WORK1);// store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except C + PUSH(REG_WORK1); + + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rrr(REG_WORK2, REG_WORK2, i); + LSR_rri(REG_WORK2, REG_WORK2, 1); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, s, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// retore flags + + AND_rri(REG_WORK2, i, 63); + LSLS_rrr(d,s,REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +/* + * ASLW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Set according to the last bit shifted out of the operand. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if the most significant bit is changed at any time during the shift operation. Cleared otherwise. + * C Set according to the last bit shifted out of the operand. + * + */ +MIDFUNC(2,jnf_ASLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_ASLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + LSLS_rri(d,s,17); + + MRS_CPSR(REG_WORK1); + CC_ORR_rri(NATIVE_CC_MI, REG_WORK1, REG_WORK1, ARM_V_FLAG); + CC_EOR_rri(NATIVE_CC_CS, REG_WORK1, REG_WORK1, ARM_V_FLAG); + MSR_CPSRf_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} + +/* + * ASR + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if the most significant bit is changed at any time during the shift operation. Cleared otherwise. + * C Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * + */ +MIDFUNC(3,jnf_ASR_b_imm,(W4 d, RR4 s, IMM i)) +{ + if (!i) return; + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + ASR_rri(d,d,i); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ASR_w_imm,(W4 d, RR4 s, IMM i)) +{ + if (!i) return; + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + ASR_rri(d,d,i); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ASR_l_imm,(W4 d, RR4 s, IMM i)) +{ + if (!i) return; + + s=readreg(s,4); + d=writereg(d,4); + + ASR_rri(d,s,i); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ASR_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + if (i) { + MSR_CPSRf_i(0); + ASRS_rri(d,d,i); + } else { + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + TST_rr(d,d); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ASR_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + if (i) { + MSR_CPSRf_i(0); + ASRS_rri(d,d,i); + } else { + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + TST_rr(d,d); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ASR_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i) { + MSR_CPSRf_i(0); + ASRS_rri(d,s,i); + } else { + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + TST_rr(s,s); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ASR_b_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + AND_rri(REG_WORK1, i, 63); + ASR_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jnf_ASR_w_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + AND_rri(REG_WORK1, i, 63); + ASR_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jnf_ASR_l_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 63); + ASR_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ASR_b_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + ASRS_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ASR_w_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + ASRS_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ASR_l_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + ASRS_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +/* + * ASRW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Set according to the last bit shifted out of the operand. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if the most significant bit is changed at any time during the shift operation. Cleared otherwise. + * C Set according to the last bit shifted out of the operand. + * + */ +MIDFUNC(2,jnf_ASRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + ASR_rri(d,d,1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_ASRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + MSR_CPSRf_i(0); + ASR_rri(d,d,1); + + unlock2(d); + unlock2(s); +} + +/* + * BCHG + * Operand Syntax: Dn, + * #, + * + * Operand Size: 8,32 + * + * X Not affected. + * N Not affected. + * Z Set if the bit tested is zero. Cleared otherwise. + * V Not affected. + * C Not affected. + * + */ +MIDFUNC(2,jnf_BCHG_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + EOR_rri(d,d,(1 << s)); + unlock2(d); +} + +MIDFUNC(2,jnf_BCHG_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + EOR_rri(d,d,(1 << s)); + unlock2(d); +} + +MIDFUNC(2,jnf_BCHG_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BCHG_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + EOR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jnf_BCHG_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BCHG_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + EOR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_BCHG_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + EOR_rri(d,d,v); + + unlock2(d); +} + +MIDFUNC(2,jff_BCHG_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + EOR_rri(d,d,v); + + unlock2(d); +} + +MIDFUNC(2,jff_BCHG_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BCHG_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + EOR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_BCHG_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BCHG_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + EOR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +/* + * BCLR + * Operand Syntax: Dn, + * #, + * + * Operand Size: 8,32 + * + * X Not affected. + * N Not affected. + * Z Set if the bit tested is zero. Cleared otherwise. + * V Not affected. + * C Not affected. + * + */ +MIDFUNC(2,jnf_BCLR_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + BIC_rri(d,d,(1 << s)); + unlock2(d); +} + +MIDFUNC(2,jnf_BCLR_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + BIC_rri(d,d,(1 << s)); + unlock2(d); +} + +MIDFUNC(2,jnf_BCLR_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BCLR_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + BIC_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jnf_BCLR_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BCLR_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + BIC_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_BCLR_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + BIC_rri(d,d,v); + + unlock2(d); +} + +MIDFUNC(2,jff_BCLR_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + BIC_rri(d,d,v); + + unlock2(d); +} + +MIDFUNC(2,jff_BCLR_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BCLR_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + BIC_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_BCLR_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BCLR_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + BIC_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +/* + * BSET + * Operand Syntax: Dn, + * #, + * + * Operand Size: 8,32 + * + * X Not affected. + * N Not affected. + * Z Set if the bit tested is zero. Cleared otherwise. + * V Not affected. + * C Not affected. + * + */ +MIDFUNC(2,jnf_BSET_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + ORR_rri(d,d,(1 << s)); + unlock2(d); +} + +MIDFUNC(2,jnf_BSET_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + ORR_rri(d,d,(1 << s)); + unlock2(d); +} + +MIDFUNC(2,jnf_BSET_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BSET_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + ORR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jnf_BSET_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BSET_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + ORR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_BSET_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + ORR_rri(d,d,v); + + unlock2(d); +} + +MIDFUNC(2,jff_BSET_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + ORR_rri(d,d,v); + + unlock2(d); +} + +MIDFUNC(2,jff_BSET_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BSET_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + ORR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_BSET_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BSET_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + ORR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} + +/* + * BTST + * Operand Syntax: Dn, + * #, + * + * Operand Size: 8,32 + * + * X Not affected + * N Not affected + * Z Set if the bit tested is zero. Cleared otherwise + * V Not affected + * C Not affected + * + */ +MIDFUNC(2,jff_BTST_b_imm,(RR4 d, IMM s)) +{ + d=readreg(d,4); + + MRS_CPSR(REG_WORK1); + TST_ri(d,(1 << s)); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); +} + +MIDFUNC(2,jff_BTST_l_imm,(RR4 d, IMM s)) +{ + d=readreg(d,4); + + MRS_CPSR(REG_WORK1); + TST_ri(d,(1 << s)); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); +} + +MIDFUNC(2,jff_BTST_b,(RR4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BTST_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=readreg(d,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_BTST_l,(RR4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BTST_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=readreg(d,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} + +/* + * CLR + * Operand Syntax: + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Always cleared. + * Z Always set. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(1,jnf_CLR,(W4 d)) +{ + d=writereg(d,4); + MOV_ri(d,0); + unlock2(d); +} + +MIDFUNC(1,jff_CLR,(W4 d)) +{ + d=writereg(d,4); + MOV_ri(d,0); + MSR_CPSR_i(ARM_Z_FLAG); + unlock2(d); +} + +/* + * CMP + * Operand Syntax: , Dn + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if an overflow occurs. Cleared otherwise. + * C Set if a borrow occurs. Cleared otherwise. + * + */ +MIDFUNC(2,jff_CMP_b,(RR1 d, RR1 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + SIGNED8_REG_2_REG(REG_WORK1, d); + SIGNED8_REG_2_REG(REG_WORK2, s); + CMP_rr(REG_WORK1,REG_WORK2); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // inverted_carry = true; + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jff_CMP_w,(RR2 d, RR2 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + SIGNED16_REG_2_REG(REG_WORK1, d); + SIGNED16_REG_2_REG(REG_WORK2, s); + CMP_rr(REG_WORK1,REG_WORK2); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // inverted_carry = true; + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jff_CMP_l,(RR4 d, RR4 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + CMP_rr(d,s); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // inverted_carry = true; + + unlock2(s); + unlock2(d); +} + +/* + * CMPA + * Operand Syntax: , An + * + * Operand Size: 16,32 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if an overflow occurs. Cleared otherwise. + * C Set if a borrow occurs. Cleared otherwise. + * + */ +MIDFUNC(2,jff_CMPA_b,(RR1 d, RR1 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + SIGNED8_REG_2_REG(REG_WORK2, s); + CMP_rr(d,REG_WORK2); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // invertedcarry = true; + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jff_CMPA_w,(RR2 d, RR2 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + SIGNED16_REG_2_REG(REG_WORK2, s); + CMP_rr(d,REG_WORK2); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // invertedcarry = true; + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jff_CMPA_l,(RR4 d, RR4 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + CMP_rr(d,s); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // invertedcarry = true; + + unlock2(s); + unlock2(d); +} + +/* + * EOR + * Operand Syntax: Dn, + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the most significant bit of the result is set. + * Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(3,jnf_EOR,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(s) && isconst(v)) { + set_const(d, + live.state[s].val^live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + EOR_rrr(d, s, v); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_EOR_b,(W4 d, RR1 s, RR1 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + EORS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_EOR_w,(W4 d, RR2 s, RR2 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + EORS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_EOR_l,(W4 d, RR4 s, RR4 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + EORS_rrr(d, s,v); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +/* + * EORI + * Operand Syntax: #, CCR + * + * Operand Size: 8 + * + * X — Changed if bit 4 of immediate operand is one; unchanged otherwise. + * N — Changed if bit 3 of immediate operand is one; unchanged otherwise. + * Z — Changed if bit 2 of immediate operand is one; unchanged otherwise. + * V — Changed if bit 1 of immediate operand is one; unchanged otherwise. + * C — Changed if bit 0 of immediate operand is one; unchanged otherwise. + * + */ +MIDFUNC(1,jff_EORSR,(IMM s, IMM x)) +{ + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, s); + MSR_CPSRf_r(REG_WORK1); + + if (x) { + compemu_raw_mov_l_ri(REG_WORK1, (uintptr)live.state[FLAGX].mem); + LDRB_rR(REG_WORK2, REG_WORK1); + EOR_rri(REG_WORK2, REG_WORK2, 1); + STRB_rR(REG_WORK2, REG_WORK1); + } +} + +/* + * EXT + * Operand Syntax: + * + * Operand Size: 16,32 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(2,jnf_EXT_b,(W4 d, RR4 s)) +{ + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s8)live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jnf_EXT_w,(W4 d, RR4 s)) +{ + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s8)live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jnf_EXT_l,(W4 d, RR4 s)) +{ + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s16)live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jff_EXT_b,(W4 d, RR4 s)) +{ + if (isconst(s)) { + d=writereg(d,4); + SIGNED8_IMM_2_REG(d, (uint8)live.state[s].val); + } else { + s=readreg(s,4); + d=writereg(d,4); + SIGNED8_REG_2_REG(d, s); + unlock2(s); + } + + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} + +MIDFUNC(2,jff_EXT_w,(W4 d, RR4 s)) +{ + if (isconst(s)) { + d=writereg(d,4); + SIGNED8_IMM_2_REG(d, (uint8)live.state[s].val); + } else { + s=readreg(s,4); + d=writereg(d,4); + SIGNED8_REG_2_REG(d, s); + unlock2(s); + } + + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} + +MIDFUNC(2,jff_EXT_l,(W4 d, RR4 s)) +{ + if (isconst(s)) { + d=writereg(d,4); + SIGNED16_IMM_2_REG(d, (uint16)live.state[s].val); + } else { + s=readreg(s,4); + d=writereg(d,4); + SIGNED16_REG_2_REG(d, s); + unlock2(s); + } + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} + +/* + * LSL + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit shifted out of the operand. Cleared for a shift count of zero. + * + */ +MIDFUNC(3,jnf_LSL_imm,(W4 d, RR4 s, IMM i)) +{ + if (!i) return; + + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,i); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_LSL_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 63); + LSL_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_LSL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED8_REG_2_REG(d, s); + MSR_CPSRf_i(0); + + REV_rr(d,d); + if (i) { + LSLS_rri(d,d,i); + } else { + TST_rr(d,d); + } + REV_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_LSL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + + LSL_rri(d,s,16); + if (i) { + LSLS_rri(d,d,i); + } else { + TST_rr(d,d); + } + LSR_rri(d,d,16); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_LSL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + if (i) { + LSLS_rri(d,s,i); + } else { + MOV_rr(d,s); + TST_rr(d,d); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_LSL_b_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED8_REG_2_REG(d,s); + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + REV_rr(d,d); + AND_rri(REG_WORK1, i, 63); + LSLS_rrr(d,d,REG_WORK1); + REV_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_LSL_w_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + LSL_rri(d, s, 16); + AND_rri(REG_WORK1, i, 63); + LSLS_rrr(d,d,REG_WORK1); + LSR_rri(d, d, 16); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_LSL_l_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + LSLS_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +/* + * LSLW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit shifted out of the operand. Cleared for a shift count of zero. + * + */ +MIDFUNC(2,jnf_LSLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_LSLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + LSLS_rri(d,s,17); + LSR_rri(d,d,16); + + unlock2(d); + unlock2(s); +} + +/* + * LSR + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit shifted out of the operand. + * Unaffected for a shift count of zero. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit shifted out of the operand. + * Cleared for a shift count of zero. + * + */ +MIDFUNC(3,jnf_LSR_b_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + if (!i) + return; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED8_REG_2_REG(d, s); + LSR_rri(d,d,i); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} + +MIDFUNC(3,jnf_LSR_w_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + if (!i) + return; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED16_REG_2_REG(d, s); + LSR_rri(d,d,i); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} + +MIDFUNC(3,jnf_LSR_l_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + if (!i) + return; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + LSR_rri(d,s,i); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} + +MIDFUNC(3,jff_LSR_b_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED8_REG_2_REG(d, s); + MSR_CPSRf_i(0); + if (i) { + LSRS_rri(d,d,i); + } else { + TST_rr(d,d); + } + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} + +MIDFUNC(3,jff_LSR_w_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED16_REG_2_REG(d, s); + MSR_CPSRf_i(0); + if (i) { + LSRS_rri(d,d,i); + } else { + TST_rr(d,d); + } + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} + +MIDFUNC(3,jff_LSR_l_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + MSR_CPSRf_i(0); + if (i) { + LSRS_rri(d,s,i); + } else { + TST_rr(s,s); + } + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} + +MIDFUNC(3,jnf_LSR_b_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED8_REG_2_REG(d, s); + AND_rri(REG_WORK1, i, 63); + LSR_rrr(d,d,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} + +MIDFUNC(3,jnf_LSR_w_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED16_REG_2_REG(d, s); + AND_rri(REG_WORK1, i, 63); + LSR_rrr(d,d,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} + +MIDFUNC(3,jnf_LSR_l_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + AND_rri(REG_WORK1, i, 63); + LSR_rrr(d,s,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} + +MIDFUNC(3,jff_LSR_b_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED8_REG_2_REG(d, s); + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + LSRS_rrr(d,d,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} + +MIDFUNC(3,jff_LSR_w_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED16_REG_2_REG(d, s); + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + LSRS_rrr(d,d,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} + +MIDFUNC(3,jff_LSR_l_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + LSRS_rrr(d,s,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} + +/* + * LSRW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit shifted out of the operand. Cleared for a shift count of zero. + * + */ +MIDFUNC(2,jnf_LSRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d, s); + LSR_rri(d,d,1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_LSRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d, s); + MSR_CPSRf_i(0); + LSR_rri(d,d,1); + + unlock2(d); + unlock2(s); +} + +/* + * MOVE + * Operand Syntax: , + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(2,jnf_MOVE,(W4 d, RR4 s)) +{ + if (isconst(s)) { + set_const(d,live.state[s].val); + return; + } + s=readreg(s,4); + d=writereg(d,4); + + MOV_rr(d, s); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_MOVE_b_imm,(W4 d, IMM s)) +{ + d=writereg(d,4); + + SIGNED8_IMM_2_REG(d, (uint8)s); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} + +MIDFUNC(2,jff_MOVE_w_imm,(W4 d, IMM s)) +{ + d=writereg(d,4); + + SIGNED16_IMM_2_REG(d, (uint16)s); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} + +MIDFUNC(2,jff_MOVE_l_imm,(W4 d, IMM s)) +{ + d=writereg(d,4); + + compemu_raw_mov_l_ri(d, s); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} + +MIDFUNC(2,jff_MOVE_b,(W4 d, RR1 s)) +{ + if (isconst(s)) { + COMPCALL(jff_MOVE_b_imm)(d,live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_MOVE_w,(W4 d, RR2 s)) +{ + if (isconst(s)) { + COMPCALL(jff_MOVE_w_imm)(d,live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_MOVE_l,(W4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_MOVE_l_imm)(d,live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + MOVS_rr(d,s); + + unlock2(d); + unlock2(s); +} + +/* + * MOVE16 + * + * Flags: Not affected. + * + */ +MIDFUNC(2,jnf_MOVE16,(RR4 d, RR4 s)) +{ + s=readreg(s,4); + d=readreg(d,4); + + BIC_rri(s, s, 0x000000FF); + BIC_rri(d, d, 0x000000FF); + + compemu_raw_mov_l_ri(REG_WORK1, (IMM)MEMBaseDiff); + ADD_rrr(s, s, REG_WORK1); + ADD_rrr(d, d, REG_WORK1); + + LDR_rRI(REG_WORK1, s, 8); + LDR_rRI(REG_WORK2, s, 12); + + PUSH_REGS((1<, An + * + * Operand Size: 16,32 + * + * Flags: Not affected. + * + */ +MIDFUNC(2,jnf_MOVEA_w,(W4 d, RR2 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d,s); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jnf_MOVEA_l,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MOV_rr(d,s); + + unlock2(d); + unlock2(s); +} + +/* + * MULS + * Operand Syntax: , Dn + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if overflow. Cleared otherwise. (32 Bit multiply only) + * C Always cleared. + * + */ +MIDFUNC(2,jnf_MULS,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + SIGN_EXTEND_16_REG_2_REG(d,d); + SIGN_EXTEND_16_REG_2_REG(REG_WORK1,s); + MUL_rrr(d, d, REG_WORK1); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jff_MULS,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + SIGN_EXTEND_16_REG_2_REG(d,d); + SIGN_EXTEND_16_REG_2_REG(REG_WORK1,s); + + MSR_CPSRf_i(0); + MULS_rrr(d, d, REG_WORK1); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jnf_MULS32,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + MUL_rrr(d, d, s); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jff_MULS32,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + MSR_CPSRf_i(0); + // L, H, + SMULLS_rrrr(d, REG_WORK2, d, s); + MRS_CPSR(REG_WORK1); + TEQ_rrASRi(REG_WORK2,d,31); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + MSR_CPSRf_r(REG_WORK1); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jnf_MULS64,(RW4 d, RW4 s)) +{ + s = rmw(s, 4, 4); + d = rmw(d, 4, 4); + + // L, H, + SMULL_rrrr(d, s, d, s); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jff_MULS64,(RW4 d, RW4 s)) +{ + s = rmw(s, 4, 4); + d = rmw(d, 4, 4); + + MSR_CPSRf_i(0); + // L, H, + SMULLS_rrrr(d, s, d, s); + MRS_CPSR(REG_WORK1); + TEQ_rrASRi(s,d,31); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + MSR_CPSRf_r(REG_WORK1); + + unlock2(s); + unlock2(d); +} + +/* + * MULU + * Operand Syntax: , Dn + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if overflow. Cleared otherwise. (32 Bit multiply only) + * C Always cleared. + * + */ +MIDFUNC(2,jnf_MULU,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + ZERO_EXTEND_16_REG_2_REG(d,d); + ZERO_EXTEND_16_REG_2_REG(REG_WORK1,s); + + MUL_rrr(d, d, REG_WORK1); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jff_MULU,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + ZERO_EXTEND_16_REG_2_REG(d,d); + ZERO_EXTEND_16_REG_2_REG(REG_WORK1, s); + + MSR_CPSRf_i(0); + MULS_rrr(d, d, REG_WORK1); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jnf_MULU32,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + MUL_rrr(d, d, s); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jff_MULU32,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + // L, H, + MSR_CPSRf_i(0); + UMULLS_rrrr(d, REG_WORK2, d, s); + MRS_CPSR(REG_WORK1); + TST_rr(REG_WORK2,REG_WORK2); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + MSR_CPSRf_r(REG_WORK1); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jnf_MULU64,(RW4 d, RW4 s)) +{ + s = rmw(s, 4, 4); + d = rmw(d, 4, 4); + + // L, H, + UMULL_rrrr(d, s, d, s); + + unlock2(s); + unlock2(d); +} + +MIDFUNC(2,jff_MULU64,(RW4 d, RW4 s)) +{ + s = rmw(s, 4, 4); + d = rmw(d, 4, 4); + + // L, H, + MSR_CPSRf_i(0); + UMULLS_rrrr(d, s, d, s); + MRS_CPSR(REG_WORK1); + TST_rr(s,s); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + MSR_CPSRf_r(REG_WORK1); + + unlock2(s); + unlock2(d); +} + +/* + * NEG + * Operand Syntax: + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if an overflow occurs. Cleared otherwise. + * C Cleared if the result is zero. Set otherwise. + * + */ +MIDFUNC(2,jnf_NEG,(W4 d, RR4 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + RSB_rri(d,s,0); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_NEG_b,(W4 d, RR1 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + RSBS_rri(d,REG_WORK1,0); + + // inverted_carry = true; + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_NEG_w,(W4 d, RR2 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + RSBS_rri(d,REG_WORK1,0); + + // inverted_carry = true; + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_NEG_l,(W4 d, RR4 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + RSBS_rri(d,s,0); + + // inverted_carry = true; + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} + +/* + * NEGX + * Operand Syntax: + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Cleared if the result is nonzero; unchanged otherwise. + * V Set if an overflow occurs. Cleared otherwise. + * C Cleared if the result is zero. Set otherwise. + * + * Attention: Z is cleared only if the result is nonzero. Unchanged otherwise + * + */ +MIDFUNC(2,jnf_NEGX,(W4 d, RR4 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + RSC_rri(d,s,0); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_NEGX_b,(W4 d, RR1 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + MRS_CPSR(REG_WORK2); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + + SIGNED8_REG_2_REG(REG_WORK1, s); + RSCS_rri(d,REG_WORK1,0); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_NEGX_w,(W4 d, RR2 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + MRS_CPSR(REG_WORK2); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + + SIGNED16_REG_2_REG(REG_WORK1, s); + RSCS_rri(d,REG_WORK1,0); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_NEGX_l,(W4 d, RR4 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + MRS_CPSR(REG_WORK2); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + + RSCS_rri(d,s,0); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} + +/* + * NOT + * Operand Syntax: + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(2,jnf_NOT,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MVN_rr(d,s); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_NOT_b,(W4 d, RR1 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED8_REG_2_REG(d,s); + MSR_CPSRf_i(0); // Clear flags + MVNS_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_NOT_w,(W4 d, RR2 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d,s); + MSR_CPSRf_i(0); // Clear flags + MVNS_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_NOT_l,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); // Clear flags + MVNS_rr(d,s); + + unlock2(d); + unlock2(s); +} + +/* + * OR + * Operand Syntax: , Dn + * Dn, + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(3,jnf_OR,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(s) && isconst(v)) { + set_const(d, + live.state[s].val|live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + ORR_rrr(d, s, v); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_OR_b,(W4 d, RR1 s, RR1 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + ORRS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_OR_w,(W4 d, RR2 s, RR2 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + ORRS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_OR_l,(W4 d, RR4 s, RR4 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + ORRS_rrr(d, s,v); + + unlock2(v); + unlock2(d); + unlock2(s); +} + +/* + * ORI + * Operand Syntax: #, CCR + * + * Operand Size: 8 + * + * X — Set if bit 4 of immediate operand is one; unchanged otherwise. + * N — Set if bit 3 of immediate operand is one; unchanged otherwise. + * Z — Set if bit 2 of immediate operand is one; unchanged otherwise. + * V — Set if bit 1 of immediate operand is one; unchanged otherwise. + * C — Set if bit 0 of immediate operand is one; unchanged otherwise. + * + */ +MIDFUNC(1,jff_ORSR,(IMM s, IMM x)) +{ + MRS_CPSR(REG_WORK1); + ORR_rri(REG_WORK1, REG_WORK1, s); + MSR_CPSRf_r(REG_WORK1); + + if (x) { + compemu_raw_mov_l_ri(REG_WORK1, (uintptr)live.state[FLAGX].mem); + MOV_ri(REG_WORK2, 1); + STRB_rR(REG_WORK2, REG_WORK1); + } +} + +/* + * ROL + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * + */ +MIDFUNC(3,jnf_ROL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,(32-(i&0x1f))); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,(32-(i&0x1f))); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + ROR_rri(d,s,(32-(i&0x1f))); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + if (i) { + RORS_rri(d,d,(32-(i&0x1f))); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + } else { + TST_rr(d,d); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + if (i) { + RORS_rri(d,d,(32-(i&0x1f))); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + } else { + TST_rr(d,d); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + if (i) { + RORS_rri(d,s,(32-(i&0x1f))); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + } else { + MOVS_rr(d,s); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROL_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROL_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + ROR_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jnf_ROL_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROL_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jnf_ROL_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROL_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + ROR_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROL_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROL_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rrr(d,d,REG_WORK1); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROL_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROL_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rrr(d,d,REG_WORK1); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROL_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROL_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + MSR_CPSRf_i(0); + RORS_rrr(d,s,REG_WORK1); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +/* + * ROLW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * + */ +MIDFUNC(2,jnf_ROLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,(32-1)); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_ROLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rri(d,d,(32-1)); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + unlock2(d); + unlock2(s); +} + +/* + * RORW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. + * + */ +MIDFUNC(2,jnf_RORW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_RORW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rri(d,d,1); + + unlock2(d); + unlock2(s); +} + +/* + * ROXL + * Operand Syntax: Dx, Dy + * #, Dy + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * + */ +MIDFUNC(3,jnf_ROXL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED8_REG_2_REG(d,s); + LSL_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,d,9); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROXL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED16_REG_2_REG(d,s); + LSL_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,d,17); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROXL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSL_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,s,(32-i)); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROXL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED8_REG_2_REG(d,s); + LSL_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,d,9); + TST_ri(s, (1<<(8-i))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + SIGNED8_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROXL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED16_REG_2_REG(d,s); + LSL_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,d,17); + TST_ri(s, (1<<(16-i))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + SIGNED16_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROXL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSL_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,s,(32-i)); + TST_ri(s, (1<<(32-i))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROXL_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXL_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 36); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 36); + CMP_ri(REG_WORK1, 18); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 18); + CMP_ri(REG_WORK1, 9); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 9); + CMP_ri(REG_WORK1, 0); +#if defined(ARMV6_ASSEMBLY) + BLE_i(8-1); +#else + BLE_i(9-1); +#endif + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 8); +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(REG_WORK2, s); +#else + ROR_rri(REG_WORK2, s, 8); + LSR_rri(REG_WORK2, REG_WORK2, 24); +#endif + ORR_rrrLSRr(d,d,REG_WORK2,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jnf_ROXL_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXL_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d,s); + MRS_CPSR(REG_WORK2); + + CMP_ri(REG_WORK1, 34); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 34); + CMP_ri(REG_WORK1, 17); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 17); + CMP_ri(REG_WORK1, 0); +#if defined(ARMV6_ASSEMBLY) + BLE_i(8-1); +#else + BLE_i(9-1); +#endif + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 16); +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK2, s); +#else + LSL_rri(REG_WORK2, s, 16); + LSR_rri(REG_WORK2, REG_WORK2, 16); +#endif + ORR_rrrLSRr(d,d,REG_WORK2,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jnf_ROXL_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXL_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + CMP_ri(REG_WORK1, 33); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 33); + CMP_ri(REG_WORK1, 0); + BLE_i(7-1); + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 32); + ORR_rrrLSRr(d,d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROXL_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXL_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 36); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 36); + CMP_ri(REG_WORK1, 18); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 18); + CMP_ri(REG_WORK1, 9); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 9); + CMP_ri(REG_WORK1, 0); +#if defined(ARMV6_ASSEMBLY) + BLE_i(16-1); // label +#else + BLE_i(17-1); // label +#endif + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 0x80); + LSR_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + PUSH(REG_WORK2); + + RSB_rri(REG_WORK1, REG_WORK1, 8); +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(REG_WORK2, s); +#else + ROR_rri(REG_WORK2, s, 8); + LSR_rri(REG_WORK2, REG_WORK2, 24); +#endif + ORR_rrrLSRr(d,d,REG_WORK2,REG_WORK1); + + POP(REG_WORK2); + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0); // label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + raw_sign_extend_8_rr(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROXL_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXL_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 34); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 34); + CMP_ri(REG_WORK1, 17); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 17); + CMP_ri(REG_WORK1, 0); +#if defined(ARMV6_ASSEMBLY) + BLE_i(16-1); // label +#else + BLE_i(17-1); // label +#endif + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 0x8000); + LSR_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + PUSH(REG_WORK2); + +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK2, s); +#else + LSL_rri(REG_WORK2, s, 16); + LSR_rri(REG_WORK2, REG_WORK2, 16); +#endif + + RSB_rri(REG_WORK1, REG_WORK1, 16); + ORR_rrrLSRr(d,d,REG_WORK2,REG_WORK1); + + POP(REG_WORK2); + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0); // label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + SIGNED16_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROXL_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXL_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 33); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 33); + CMP_ri(REG_WORK1, 0); + BLE_i(13-1); // label + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 0x80000000); + LSR_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + RSB_rri(REG_WORK1, REG_WORK1, 32); + ORR_rrrLSRr(d,d,s,REG_WORK1); + + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0);// label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +/* + * ROXLW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. + * + */ +MIDFUNC(2,jnf_ROXLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,1); + ADC_rri(d,d,0); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_ROXLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,1); + ADC_rri(d,d,0); + MSR_CPSRf_i(0); + LSLS_rri(d,d,15); + LSR_rri(d,d,16); + + unlock2(d); + unlock2(s); +} + +/* + * ROR + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * + */ +MIDFUNC(3,jnf_ROR_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,i); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROR_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,i); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROR_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + ROR_rri(d,s,i); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROR_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rri(d,d,i); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROR_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rrr(d,d,i); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROR_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + RORS_rrr(d,s,i); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROR_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROR_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + ROR_rrr(d,d,i); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jnf_ROR_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROR_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rrr(d,d,i); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jnf_ROR_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROR_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + ROR_rrr(d,s,i); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROR_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROR_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + AND_rri(REG_WORK1, i, 63); + RORS_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROR_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROR_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + AND_rri(REG_WORK1, i, 63); + RORS_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROR_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROR_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + AND_rri(REG_WORK1, i, 63); + RORS_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +/* + * ROXR + * Operand Syntax: Dx, Dy + * #, Dy + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * + */ +MIDFUNC(3,jnf_ROXR_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSR_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x80 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(9-i)); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROXR_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSR_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x8000 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(17-i)); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROXR_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSR_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x80000000 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(33-i)); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROXR_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED8_REG_2_REG(d,s); + LSR_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x80 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(9-i)); + TST_ri(s, (1<<(i-1))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + SIGNED8_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROXR_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED16_REG_2_REG(d,s); + LSR_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x8000 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(17-i)); + TST_ri(s, (1<<(i-1))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + SIGNED16_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_ROXR_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSR_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x80000000 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(33-i)); + TST_ri(s, (1<<(i-1))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_ROXR_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXR_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + UNSIGNED8_REG_2_REG(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 36); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 36); + CMP_ri(REG_WORK1, 18); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 18); + CMP_ri(REG_WORK1, 9); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 9); + CMP_ri(REG_WORK1, 0); + BLE_i(7-1); + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x80); + LSR_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 8); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jnf_ROXR_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXR_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d,s); + MRS_CPSR(REG_WORK2); + + CMP_ri(REG_WORK1, 34); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 34); + CMP_ri(REG_WORK1, 17); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 17); + CMP_ri(REG_WORK1, 0); + BLE_i(7-1); + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x8000); + LSR_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 16); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jnf_ROXR_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXR_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + CMP_ri(REG_WORK1, 33); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 33); + CMP_ri(REG_WORK1, 0); + BLE_i(7-1); + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x80000000); + LSR_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 32); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROXR_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXR_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + UNSIGNED8_REG_2_REG(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 36); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 36); + CMP_ri(REG_WORK1, 18); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 18); + CMP_ri(REG_WORK1, 9); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 9); + CMP_ri(REG_WORK1, 0); + BLE_i(13-1); // label + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x80); + LSR_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + RSB_rri(REG_WORK1, REG_WORK1, 8); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0);// label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + SIGNED8_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROXR_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXR_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 34); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 34); + CMP_ri(REG_WORK1, 17); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 17); + CMP_ri(REG_WORK1, 0); + BLE_i(13-1); // label + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x8000); + LSR_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + RSB_rri(REG_WORK1, REG_WORK1, 16); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0);// label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + SIGNED16_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +MIDFUNC(3,jff_ROXR_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXR_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 33); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 33); + CMP_ri(REG_WORK1, 0); + BLE_i(13-1); // label + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x80000000); + LSR_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + RSB_rri(REG_WORK1, REG_WORK1, 32); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0);// label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} + +/* + * ROXRW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. + * + */ +MIDFUNC(2,jnf_ROXRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + RRX_rr(d,d); + LSR_rri(d,d,16); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jff_ROXRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + MSR_CPSRf_i(0); + RRXS_rr(d,d); + LSR_rri(d,d,16); + + unlock2(d); + unlock2(s); +} + +/* + * SUB + * Operand Syntax: , Dn + * Dn, + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if an overflow is generated. Cleared otherwise. + * C Set if a carry is generated. Cleared otherwise. + * + */ +MIDFUNC(3,jnf_SUB_b_imm,(W4 d, RR4 s, IMM v)) +{ + if (isconst(s)) { + set_const(d,live.state[s].val-v); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED8_IMM_2_REG(REG_WORK1, (uint8)v); + SUB_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_SUB_b,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jnf_SUB_b_imm)(d,s,live.state[v].val); + return; + } + + // d has to be different to s and v + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SUB_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jnf_SUB_w_imm,(W4 d, RR4 s, IMM v)) +{ + if (isconst(s)) { + set_const(d,live.state[s].val-v); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED16_IMM_2_REG(REG_WORK1, (uint16)v); + SUB_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_SUB_w,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jnf_SUB_w_imm)(d,s,live.state[v].val); + return; + } + + // d has to be different to s and v + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SUB_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jnf_SUB_l_imm,(W4 d, RR4 s, IMM v)) +{ + if (isconst(s)) { + set_const(d,live.state[s].val-v); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + compemu_raw_mov_l_ri(REG_WORK1, v); + SUB_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jnf_SUB_l,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jnf_SUB_l_imm)(d,s,live.state[v].val); + return; + } + + // d has to be different to s and v + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SUB_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_SUB_b_imm,(W4 d, RR1 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_IMM_2_REG(REG_WORK2, (uint8)v); + SIGNED8_REG_2_REG(REG_WORK1, s); + SUBS_rrr(d,REG_WORK1,REG_WORK2); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_SUB_b,(W4 d, RR1 s, RR1 v)) +{ + if (isconst(v)) { + COMPCALL(jff_SUB_b_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + SUBS_rrr(d,REG_WORK1,REG_WORK2); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_SUB_w_imm,(W4 d, RR2 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_IMM_2_REG(REG_WORK2, (uint16)v); + SIGNED16_REG_2_REG(REG_WORK1, s); + SUBS_rrr(d,REG_WORK1,REG_WORK2); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_SUB_w,(W4 d, RR2 s, RR2 v)) +{ + if (isconst(v)) { + COMPCALL(jff_SUB_w_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + SUBS_rrr(d,REG_WORK1,REG_WORK2); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_SUB_l_imm,(W4 d, RR4 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + compemu_raw_mov_l_ri(REG_WORK2, v); + SUBS_rrr(d,s,REG_WORK2); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); +} + +MIDFUNC(3,jff_SUB_l,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jff_SUB_l_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SUBS_rrr(d,s,v); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); + unlock2(v); +} + +/* + * SUBA + * + * Operand Syntax: , Dn + * + * Operand Size: 16,32 + * + * Flags: Not affected. + * + */ +MIDFUNC(2,jnf_SUBA_b,(W4 d, RR1 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + SIGNED8_REG_2_REG(REG_WORK1,s); + SUB_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jnf_SUBA_w,(W4 d, RR2 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + SIGNED16_REG_2_REG(REG_WORK1,s); + SUB_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); +} + +MIDFUNC(2,jnf_SUBA_l,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + SUB_rrr(d,d,s); + + unlock2(d); + unlock2(s); +} + +/* + * SUBX + * Operand Syntax: Dy, Dx + * -(Ay), -(Ax) + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Cleared if the result is nonzero. Unchanged otherwise. + * V Set if an overflow is generated. Cleared otherwise. + * C Set if a carry is generated. Cleared otherwise. + * + * Attention: Z is cleared only if the result is nonzero. Unchanged otherwise + * + */ +MIDFUNC(3,jnf_SUBX,(W4 d, RR4 s, RR4 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + SBC_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_SUBX_b,(W4 d, RR1 s, RR1 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + MRS_CPSR(REG_WORK1); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK1, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK1, ARM_Z_FLAG); + PUSH(REG_WORK1); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + SBCS_rrr(d,REG_WORK1,REG_WORK2); + + POP(REG_WORK2); + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_SUBX_w,(W4 d, RR2 s, RR2 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + MRS_CPSR(REG_WORK1); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK1, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK1, ARM_Z_FLAG); + PUSH(REG_WORK1); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + SBCS_rrr(d,REG_WORK1,REG_WORK2); + + POP(REG_WORK2); + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +MIDFUNC(3,jff_SUBX_l,(W4 d, RR4 s, RR4 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + MRS_CPSR(REG_WORK2); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + + SBCS_rrr(d,s,v); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} + +/* + * SWAP + * Operand Syntax: Dn + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the most significant bit of the 32-bit result is set. Cleared otherwise. + * Z Set if the 32-bit result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(1,jnf_SWAP,(RW4 d)) +{ + d=rmw(d,4,4); + + ROR_rri(d,d,16); + + unlock2(d); +} + +MIDFUNC(1,jff_SWAP,(RW4 d)) +{ + d=rmw(d,4,4); + + ROR_rri(d,d,16); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} + +/* + * TST + * Operand Syntax: + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the operand is negative. Cleared otherwise. + * Z Set if the operand is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(1,jff_TST_b,(RR1 s)) +{ + if (isconst(s)) { + SIGNED8_IMM_2_REG(REG_WORK1, (uint8)live.state[s].val); + } else { + s=readreg(s,4); + SIGNED8_REG_2_REG(REG_WORK1, s); + unlock2(s); + } + MSR_CPSRf_i(0); + TST_rr(REG_WORK1,REG_WORK1); +} + +MIDFUNC(1,jff_TST_w,(RR2 s)) +{ + if (isconst(s)) { + SIGNED16_IMM_2_REG(REG_WORK1, (uint16)live.state[s].val); + } else { + s=readreg(s,4); + SIGNED16_REG_2_REG(REG_WORK1, s); + unlock2(s); + } + MSR_CPSRf_i(0); + TST_rr(REG_WORK1,REG_WORK1); +} + +MIDFUNC(1,jff_TST_l,(RR4 s)) +{ + MSR_CPSRf_i(0); + + if (isconst(s)) { + compemu_raw_mov_l_ri(REG_WORK1, live.state[s].val); + TST_rr(REG_WORK1,REG_WORK1); + } + else { + s=readreg(s,4); + TST_rr(s,s); + unlock2(s); + } +} diff --git a/jit/compemu_midfunc_arm2.h b/jit/compemu_midfunc_arm2.h new file mode 100644 index 00000000..ecbc2fdf --- /dev/null +++ b/jit/compemu_midfunc_arm2.h @@ -0,0 +1,348 @@ +/* + * compiler/compemu_midfunc_arm2.h - Native MIDFUNCS for ARM (JIT v2) + * + * Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note: + * File is included by compemu.h + * + */ + +// Arm optimized midfunc +extern const uae_u32 ARM_CCR_MAP[]; + +DECLARE_MIDFUNC(restore_inverted_carry(void)); + +// ADD +DECLARE_MIDFUNC(jnf_ADD(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jnf_ADD_imm(W4 d, RR4 s, IMM v)); +DECLARE_MIDFUNC(jff_ADD_b(W4 d, RR1 s, RR1 v)); +DECLARE_MIDFUNC(jff_ADD_w(W4 d, RR2 s, RR2 v)); +DECLARE_MIDFUNC(jff_ADD_l(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_ADD_b_imm(W4 d, RR1 s, IMM v)); +DECLARE_MIDFUNC(jff_ADD_w_imm(W4 d, RR2 s, IMM v)); +DECLARE_MIDFUNC(jff_ADD_l_imm(W4 d, RR4 s, IMM v)); + +// ADDA +DECLARE_MIDFUNC(jnf_ADDA_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jnf_ADDA_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jnf_ADDA_l(W4 d, RR4 s)); + +// ADDX +DECLARE_MIDFUNC(jnf_ADDX(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_ADDX_b(W4 d, RR1 s, RR4 v)); +DECLARE_MIDFUNC(jff_ADDX_w(W4 d, RR2 s, RR4 v)); +DECLARE_MIDFUNC(jff_ADDX_l(W4 d, RR4 s, RR4 v)); + +// AND +DECLARE_MIDFUNC(jnf_AND(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_AND_b(W4 d, RR1 s, RR1 v)); +DECLARE_MIDFUNC(jff_AND_w(W4 d, RR2 s, RR2 v)); +DECLARE_MIDFUNC(jff_AND_l(W4 d, RR4 s, RR4 v)); + +// ANDSR +DECLARE_MIDFUNC(jff_ANDSR(IMM s, IMM x)); + +// ASL +DECLARE_MIDFUNC(jff_ASL_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASL_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASL_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASL_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ASL_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ASL_l_reg(W4 d, RR4 s, RR4 i)); + +// ASLW +DECLARE_MIDFUNC(jff_ASLW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_ASLW(W4 d, RR4 s)); + +// ASR +DECLARE_MIDFUNC(jnf_ASR_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_ASR_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_ASR_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASR_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASR_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASR_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_ASR_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ASR_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ASR_l_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ASR_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ASR_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ASR_l_reg(W4 d, RR4 s, RR4 i)); + +// ASRW +DECLARE_MIDFUNC(jff_ASRW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_ASRW(W4 d, RR4 s)); + +// BCHG +DECLARE_MIDFUNC(jnf_BCHG_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jnf_BCHG_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jff_BCHG_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jff_BCHG_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jnf_BCHG_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_BCHG_l(RW4 d, RR4 s)); + +DECLARE_MIDFUNC(jff_BCHG_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jff_BCHG_l(RW4 d, RR4 s)); + +// BCLR +DECLARE_MIDFUNC(jnf_BCLR_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jnf_BCLR_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jnf_BCLR_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_BCLR_l(RW4 d, RR4 s)); + +DECLARE_MIDFUNC(jff_BCLR_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jff_BCLR_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jff_BCLR_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jff_BCLR_l(RW4 d, RR4 s)); + +// BSET +DECLARE_MIDFUNC(jnf_BSET_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jnf_BSET_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jnf_BSET_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_BSET_l(RW4 d, RR4 s)); + +DECLARE_MIDFUNC(jff_BSET_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jff_BSET_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jff_BSET_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jff_BSET_l(RW4 d, RR4 s)); + +// BTST +DECLARE_MIDFUNC(jff_BTST_b_imm(RR4 d, IMM s)); +DECLARE_MIDFUNC(jff_BTST_l_imm(RR4 d, IMM s)); + +DECLARE_MIDFUNC(jff_BTST_b(RR4 d, RR4 s)); +DECLARE_MIDFUNC(jff_BTST_l(RR4 d, RR4 s)); + +// CLR +DECLARE_MIDFUNC (jnf_CLR(W4 d)); +DECLARE_MIDFUNC (jff_CLR(W4 d)); + +// CMP +DECLARE_MIDFUNC(jff_CMP_b(RR1 d, RR1 s)); +DECLARE_MIDFUNC(jff_CMP_w(RR2 d, RR2 s)); +DECLARE_MIDFUNC(jff_CMP_l(RR4 d, RR4 s)); + +// CMPA +DECLARE_MIDFUNC(jff_CMPA_b(RR1 d, RR1 s)); +DECLARE_MIDFUNC(jff_CMPA_w(RR2 d, RR2 s)); +DECLARE_MIDFUNC(jff_CMPA_l(RR4 d, RR4 s)); + +// EOR +DECLARE_MIDFUNC(jnf_EOR(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_EOR_b(W4 d, RR1 s, RR1 v)); +DECLARE_MIDFUNC(jff_EOR_w(W4 d, RR2 s, RR2 v)); +DECLARE_MIDFUNC(jff_EOR_l(W4 d, RR4 s, RR4 v)); + +// EORSR +DECLARE_MIDFUNC(jff_EORSR(IMM s, IMM x)); + +// EXT +DECLARE_MIDFUNC(jnf_EXT_b(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_EXT_w(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_EXT_l(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_EXT_b(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_EXT_w(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_EXT_l(W4 d, RR4 s)); + +// LSL +DECLARE_MIDFUNC(jnf_LSL_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_LSL_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSL_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSL_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSL_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSL_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSL_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSL_l_reg(W4 d, RR4 s, RR4 i)); + +// LSLW +DECLARE_MIDFUNC(jff_LSLW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_LSLW(W4 d, RR4 s)); + +// LSR +DECLARE_MIDFUNC(jnf_LSR_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_LSR_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_LSR_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSR_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSR_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSR_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_LSR_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_LSR_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_LSR_l_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSR_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSR_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSR_l_reg(W4 d, RR4 s, RR4 i)); + +// LSRW +DECLARE_MIDFUNC(jff_LSRW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_LSRW(W4 d, RR4 s)); + +// MOVE +DECLARE_MIDFUNC(jnf_MOVE(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_MOVE_b_imm(W4 d, IMM i)); +DECLARE_MIDFUNC(jff_MOVE_w_imm(W4 d, IMM i)); +DECLARE_MIDFUNC(jff_MOVE_l_imm(W4 d, IMM i)); +DECLARE_MIDFUNC(jff_MOVE_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jff_MOVE_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jff_MOVE_l(W4 d, RR4 s)); + +// MOVE16 +DECLARE_MIDFUNC(jnf_MOVE16(RR4 d, RR4 s)); + +// MOVEA +DECLARE_MIDFUNC(jnf_MOVEA_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jnf_MOVEA_l(W4 d, RR4 s)); + +// MULS +DECLARE_MIDFUNC (jnf_MULS(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jff_MULS(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jnf_MULS32(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jff_MULS32(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jnf_MULS64(RW4 d, RW4 s)); +DECLARE_MIDFUNC (jff_MULS64(RW4 d, RW4 s)); + +// MULU +DECLARE_MIDFUNC (jnf_MULU(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jff_MULU(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jnf_MULU32(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jff_MULU32(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jnf_MULU64(RW4 d, RW4 s)); +DECLARE_MIDFUNC (jff_MULU64(RW4 d, RW4 s)); + +// NEG +DECLARE_MIDFUNC(jnf_NEG(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_NEG_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jff_NEG_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jff_NEG_l(W4 d, RR4 s)); + +// NEGX +DECLARE_MIDFUNC(jnf_NEGX(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_NEGX_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jff_NEGX_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jff_NEGX_l(W4 d, RR4 s)); + +// NOT +DECLARE_MIDFUNC(jnf_NOT(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_NOT_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jff_NOT_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jff_NOT_l(W4 d, RR4 s)); + +// OR +DECLARE_MIDFUNC(jnf_OR(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_OR_b(W4 d, RR1 s, RR1 v)); +DECLARE_MIDFUNC(jff_OR_w(W4 d, RR2 s, RR2 v)); +DECLARE_MIDFUNC(jff_OR_l(W4 d, RR4 s, RR4 v)); + +// ORSR +DECLARE_MIDFUNC(jff_ORSR(IMM s, IMM x)); + +// ROL +DECLARE_MIDFUNC(jnf_ROL_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROL_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROL_l(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROL_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROL_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROL_l(W4 d, RR4 s, RR4 i)); + +// ROLW +DECLARE_MIDFUNC(jff_ROLW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_ROLW(W4 d, RR4 s)); + +// RORW +DECLARE_MIDFUNC(jff_RORW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_RORW(W4 d, RR4 s)); + +// ROXL +DECLARE_MIDFUNC(jnf_ROXL_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROXL_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROXL_l(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXL_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXL_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXL_l(W4 d, RR4 s, RR4 i)); + +// ROXLW +DECLARE_MIDFUNC(jff_ROXLW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_ROXLW(W4 d, RR4 s)); + +// ROR +DECLARE_MIDFUNC(jnf_ROR_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROR_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROR_l(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROR_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROR_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROR_l(W4 d, RR4 s, RR4 i)); + +// ROXR +DECLARE_MIDFUNC(jnf_ROXR_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROXR_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROXR_l(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXR_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXR_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXR_l(W4 d, RR4 s, RR4 i)); + +// ROXRW +DECLARE_MIDFUNC(jff_ROXRW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_ROXRW(W4 d, RR4 s)); + +// SUB +DECLARE_MIDFUNC(jnf_SUB_b_imm(W4 d, RR4 s, IMM v)); +DECLARE_MIDFUNC(jnf_SUB_b(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jnf_SUB_w_imm(W4 d, RR4 s, IMM v)); +DECLARE_MIDFUNC(jnf_SUB_w(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jnf_SUB_l_imm(W4 d, RR4 s, IMM v)); +DECLARE_MIDFUNC(jnf_SUB_l(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_SUB_b(W4 d, RR1 s, RR1 v)); +DECLARE_MIDFUNC(jff_SUB_w(W4 d, RR2 s, RR2 v)); +DECLARE_MIDFUNC(jff_SUB_l(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_SUB_b_imm(W4 d, RR1 s, IMM v)); +DECLARE_MIDFUNC(jff_SUB_w_imm(W4 d, RR2 s, IMM v)); +DECLARE_MIDFUNC(jff_SUB_l_imm(W4 d, RR4 s, IMM v)); + +// SUBA +DECLARE_MIDFUNC(jnf_SUBA_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jnf_SUBA_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jnf_SUBA_l(W4 d, RR4 s)); + +// SUBX +DECLARE_MIDFUNC(jnf_SUBX(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_SUBX_b(W4 d, RR1 s, RR4 v)); +DECLARE_MIDFUNC(jff_SUBX_w(W4 d, RR2 s, RR4 v)); +DECLARE_MIDFUNC(jff_SUBX_l(W4 d, RR4 s, RR4 v)); + +// SWAP +DECLARE_MIDFUNC (jnf_SWAP(RW4 d)); +DECLARE_MIDFUNC (jff_SWAP(RW4 d)); + +// TST +DECLARE_MIDFUNC (jff_TST_b(RR1 s)); +DECLARE_MIDFUNC (jff_TST_w(RR2 s)); +DECLARE_MIDFUNC (jff_TST_l(RR4 s)); + diff --git a/jit/flags_arm.h b/jit/flags_arm.h new file mode 100644 index 00000000..c9a60490 --- /dev/null +++ b/jit/flags_arm.h @@ -0,0 +1,52 @@ +/* + * compiler/flags_arm.h - Native flags definitions for ARM + * + * Copyright (c) 2013 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef NATIVE_FLAGS_ARM_H +#define NATIVE_FLAGS_ARM_H + +/* Native integer code conditions */ +enum { + NATIVE_CC_EQ = 0, + NATIVE_CC_NE = 1, + NATIVE_CC_CS = 2, + NATIVE_CC_CC = 3, + NATIVE_CC_MI = 4, + NATIVE_CC_PL = 5, + NATIVE_CC_VS = 6, + NATIVE_CC_VC = 7, + NATIVE_CC_HI = 8, + NATIVE_CC_LS = 9, + NATIVE_CC_GE = 10, + NATIVE_CC_LT = 11, + NATIVE_CC_GT = 12, + NATIVE_CC_LE = 13, + NATIVE_CC_AL = 14 +}; + +#endif /* NATIVE_FLAGS_ARM_H */ diff --git a/jit/gencomp_arm.c b/jit/gencomp_arm.c new file mode 100644 index 00000000..4742bff3 --- /dev/null +++ b/jit/gencomp_arm.c @@ -0,0 +1,5082 @@ +/* + * compiler/gencomp_arm2.c - MC680x0 compilation generator (ARM Adaption JIT v1 & JIT v2) + * + * Based on work Copyright 1995, 1996 Bernd Schmidt + * Changes for UAE-JIT Copyright 2000 Bernd Meyer + * + * Adaptation for ARAnyM/ARM, copyright 2001-2015 + * Milan Jurik, Jens Heitmann + * + * Basilisk II (C) 1997-2005 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Notes + * ===== + * + * Advantages of JIT v2 + * - Processor independent style + * - Reduced overhead + * - Easier to understand / read + * - Easier to optimize + * - More precise flag handling + * - Better optimization for different CPU version ARM, ARMv6 etc.. + * + * Disadvantages of JIT v2 + * - Less generated + * - Requires more code implementation by hand (MidFunc) + * - MIDFUNCS are more CPU minded (closer to raw) + * - Separate code for each instruction (but this could be also an advantage, because you can concentrate on it) + * + * Additional note: + * - current using jnf_xxx calls for non-flag operations and + * jff_xxx for flag operations + * + * Still todo: + * - Optimize genamode, genastore, gen_writeXXX, gen_readXXX, genmovemXXX + * + */ + +#define CC_FOR_BUILD 1 +#include "sysconfig.h" + +#include "sysdeps.h" +#include "readcpu.h" + +#include +#include +#include +#include +#include +#include +#undef abort + +#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; + +static int global_failure; +static int global_isjump; +static int global_iscjump; +static int global_isaddx; +static int global_cmov; +static int long_opcode; +static int global_mayfail; +static int global_fpu; + +static char endstr[1000]; +static char lines[100000]; +static int comp_index = 0; + +#include "flags_arm.h" + +#ifndef __attribute__ +# ifndef __GNUC__ +# define __attribute__(x) +# endif +#endif + + +static int cond_codes[] = { // + NATIVE_CC_AL, -1, // + NATIVE_CC_HI, NATIVE_CC_LS, // + NATIVE_CC_CC, NATIVE_CC_CS, // + NATIVE_CC_NE, NATIVE_CC_EQ, // + NATIVE_CC_VC, NATIVE_CC_VS, // + NATIVE_CC_PL, NATIVE_CC_MI, // + NATIVE_CC_GE, NATIVE_CC_LT, // + NATIVE_CC_GT, NATIVE_CC_LE // + }; + +__attribute__((format(printf, 1, 2))) +static void comprintf(const char *format, ...) +{ + va_list args; + + va_start(args, format); + comp_index += vsprintf(lines + comp_index, format, args); + va_end(args); +} + +static void com_discard(void) +{ + comp_index = 0; +} + +static void com_flush(void) +{ + int i; + for (i = 0; i < comp_index; i++) + putchar(lines[i]); + com_discard(); +} + + +static FILE *headerfile; +static FILE *stblfile; + +static int using_prefetch; +static int using_exception_3; +static int cpu_level; +static int noflags; + +/* For the current opcode, the next lower level that will have different code. + * Initialized to -1 for each opcode. If it remains unchanged, indicates we + * are done with that opcode. */ +static int next_cpu_level; + +static int *opcode_map; +static int *opcode_next_clev; +static int *opcode_last_postfix; +static unsigned long *counts; + +static void read_counts(void) +{ + FILE *file; + unsigned long opcode, count, total; + char name[20]; + int nr = 0; + memset(counts, 0, 65536 * sizeof *counts); + + file = fopen("frequent.68k", "r"); + if (file) { + if (fscanf(file, "Total: %lu\n", &total) != 1) + { + assert(0); + } + while (fscanf(file, "%lx: %lu %s\n", &opcode, &count, name) == 3) { + opcode_next_clev[nr] = 4; + opcode_last_postfix[nr] = -1; + opcode_map[nr++] = opcode; + counts[opcode] = count; + } + fclose(file); + } + if (nr == nr_cpuop_funcs) + return; + for (opcode = 0; opcode < 0x10000; opcode++) { + if (table68k[opcode].handler == -1 && table68k[opcode].mnemo != i_ILLG + && counts[opcode] == 0) { + opcode_next_clev[nr] = 4; + opcode_last_postfix[nr] = -1; + opcode_map[nr++] = opcode; + counts[opcode] = count; + } + } + assert (nr == nr_cpuop_funcs); +} + +static int n_braces = 0; +static int insn_n_cycles; + +static void start_brace(void) { + n_braces++; + comprintf("{"); +} + +static void close_brace(void) { + assert(n_braces > 0); + n_braces--; + comprintf("}"); +} + +static void finish_braces(void) { + while (n_braces > 0) + close_brace(); +} + +static inline void gen_update_next_handler(void) { + return; /* Can anything clever be done here? */ +} + +static void gen_writebyte(const char *address, const char *source) +{ + comprintf("\twritebyte(%s, %s, scratchie);\n", address, source); +} + +static void gen_writeword(const char *address, const char *source) +{ + comprintf("\twriteword(%s, %s, scratchie);\n", address, source); +} + +static void gen_writelong(const char *address, const char *source) +{ + comprintf("\twritelong(%s, %s, scratchie);\n", address, source); +} + +static void gen_readbyte(const char *address, const char* dest) +{ + comprintf("\treadbyte(%s, %s, scratchie);\n", address, dest); +} + +static void gen_readword(const char *address, const char *dest) +{ + comprintf("\treadword(%s,%s,scratchie);\n", address, dest); +} + +static void gen_readlong(const char *address, const char *dest) +{ + comprintf("\treadlong(%s, %s, scratchie);\n", address, dest); +} + +static const char * +gen_nextilong(void) { + static char buffer[80]; + + sprintf(buffer, "comp_get_ilong((m68k_pc_offset+=4)-4)"); + insn_n_cycles += 4; + + long_opcode = 1; + return buffer; +} + +static const char * +gen_nextiword(void) { + static char buffer[80]; + + sprintf(buffer, "comp_get_iword((m68k_pc_offset+=2)-2)"); + insn_n_cycles += 2; + + long_opcode = 1; + return buffer; +} + +static const char * +gen_nextibyte(void) { + static char buffer[80]; + + sprintf(buffer, "comp_get_ibyte((m68k_pc_offset+=2)-2)"); + insn_n_cycles += 2; + + long_opcode = 1; + return buffer; +} + +#if defined(USE_JIT_FPU) +// Only used by FPU (future), get rid of unused warning +static void +swap_opcode (void) +{ + comprintf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); + comprintf("\topcode = do_byteswap_16(opcode);\n"); + comprintf("#endif\n"); +} +#endif + +static void sync_m68k_pc(void) { + comprintf("\t if (m68k_pc_offset>SYNC_PC_OFFSET) sync_m68k_pc();\n"); +} + +/* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, + * the calling routine handles Apdi and Aipi modes. + * gb-- movem == 2 means the same thing but for a MOVE16 instruction */ +static void genamode(amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem) +{ + start_brace(); + switch (mode) + { + case Dreg: /* Do we need to check dodgy here? */ + 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 */ + comprintf("\tint %s = %s;\n", name, reg); + } + return; + + case Areg: + assert (!movem); + if (getv == 1 || getv == 2) + { + /* see above */ + comprintf("\tint %s = dodgy ? scratchie++ : %s + 8;\n", name, reg); + if (getv == 1) + { + comprintf("\tif (dodgy) \n"); + comprintf("\t\tmov_l_rr(%s, %s + 8);\n", name, reg); + } + } + return; + + case Aind: + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, %s + 8);\n", name, reg); + break; + case Aipi: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_rr(%sa, %s + 8);\n", name, reg); + break; + case Apdi: + switch (size) + { + case sz_byte: + if (movem) + { + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } else + { + start_brace(); + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tlea_l_brr(%s + 8, %s + 8, (uae_s32)-areg_byteinc[%s]);\n", reg, reg, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } + break; + case sz_word: + if (movem) + { + comprintf("\tint %sa=dodgy?scratchie++:%s+8;\n", name, reg); + comprintf("\tif (dodgy) \n"); + comprintf("\tmov_l_rr(%sa,8+%s);\n", name, reg); + } else + { + start_brace(); + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tlea_l_brr(%s + 8, %s + 8, -2);\n", reg, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } + break; + case sz_long: + if (movem) + { + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } else + { + start_brace(); + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tlea_l_brr(%s + 8, %s + 8, -4);\n", reg, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } + break; + default: + assert(0); + break; + } + break; + case Ad16: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + comprintf("\tlea_l_brr(%sa, %sa, (uae_s32)(uae_s16)%s);\n", name, name, gen_nextiword()); + break; + case Ad8r: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tcalc_disp_ea_020(%s + 8, %s, %sa, scratchie);\n", reg, gen_nextiword(), name); + break; + + case PC16: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tuae_u32 address = start_pc + ((char *)comp_pc_p - (char *)start_pc_p) + m68k_pc_offset;\n"); + comprintf("\tuae_s32 PC16off = (uae_s32)(uae_s16)%s;\n", gen_nextiword()); + comprintf("\tmov_l_ri(%sa, address + PC16off);\n", name); + break; + + case PC8r: + comprintf("\tint pctmp = scratchie++;\n"); + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tuae_u32 address = start_pc + ((char *)comp_pc_p - (char *)start_pc_p) + m68k_pc_offset;\n"); + start_brace(); + comprintf("\tmov_l_ri(pctmp,address);\n"); + + comprintf("\tcalc_disp_ea_020(pctmp, %s, %sa, scratchie);\n", gen_nextiword(), name); + break; + case absw: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_ri(%sa, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword()); + break; + case absl: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_ri(%sa, %s); /* absl */\n", name, gen_nextilong()); + break; + case imm: + assert (getv == 1); + switch (size) + { + case sz_byte: + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s8)%s);\n", name, gen_nextibyte()); + break; + case sz_word: + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword()); + break; + case sz_long: + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, %s);\n", name, gen_nextilong()); + break; + default: + assert(0); + break; + } + return; + case imm0: + 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: + 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: + assert (getv == 1); + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, %s);\n", name, gen_nextilong()); + return; + case immi: + assert (getv == 1); + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, %s);\n", name, reg); + return; + default: + assert(0); + break; + } + + /* We get here for all non-reg non-immediate addressing modes to + * actually fetch the value. */ + if (getv == 1) + { + char astring[80]; + sprintf(astring, "%sa", name); + switch (size) + { + case sz_byte: + insn_n_cycles += 2; + break; + case sz_word: + insn_n_cycles += 2; + break; + case sz_long: + insn_n_cycles += 4; + break; + default: + assert(0); + break; + } + start_brace(); + comprintf("\tint %s = scratchie++;\n", name); + switch (size) + { + case sz_byte: + gen_readbyte(astring, name); + break; + case sz_word: + gen_readword(astring, name); + break; + case sz_long: + gen_readlong(astring, name); + break; + default: + assert(0); + break; + } + } + + /* We now might have to fix up the register for pre-dec or post-inc + * addressing modes. */ + if (!movem) + { + switch (mode) + { + case Aipi: + switch (size) + { + case sz_byte: + comprintf("\tlea_l_brr(%s + 8,%s + 8, areg_byteinc[%s]);\n", reg, reg, reg); + break; + case sz_word: + comprintf("\tlea_l_brr(%s + 8, %s + 8, 2);\n", reg, reg); + break; + case sz_long: + comprintf("\tlea_l_brr(%s + 8, %s + 8, 4);\n", reg, reg); + break; + default: + assert(0); + break; + } + break; + case Apdi: + break; + default: + break; + } + } +} + +static void genastore(const char *from, amodes mode, const char *reg, wordsizes size, const char *to) +{ + switch (mode) + { + case Dreg: + switch (size) + { + case sz_byte: + comprintf("\tif(%s != %s)\n", reg, from); + comprintf("\t\tmov_b_rr(%s, %s);\n", reg, from); + break; + case sz_word: + comprintf("\tif(%s != %s)\n", reg, from); + comprintf("\t\tmov_w_rr(%s, %s);\n", reg, from); + break; + case sz_long: + comprintf("\tif(%s != %s)\n", reg, from); + comprintf("\t\tmov_l_rr(%s, %s);\n", reg, from); + break; + default: + assert(0); + break; + } + break; + case Areg: + switch (size) + { + case sz_word: + comprintf("\tif(%s + 8 != %s)\n", reg, from); + comprintf("\t\tmov_w_rr(%s + 8, %s);\n", reg, from); + break; + case sz_long: + comprintf("\tif(%s + 8 != %s)\n", reg, from); + comprintf("\t\tmov_l_rr(%s + 8, %s);\n", reg, from); + break; + default: + assert(0); + break; + } + break; + + case Apdi: + case absw: + case PC16: + case PC8r: + case Ad16: + case Ad8r: + case Aipi: + case Aind: + case absl: + { + char astring[80]; + sprintf(astring, "%sa", to); + + switch (size) + { + case sz_byte: + insn_n_cycles += 2; + gen_writebyte(astring, from); + break; + case sz_word: + insn_n_cycles += 2; + gen_writeword(astring, from); + break; + case sz_long: + insn_n_cycles += 4; + gen_writelong(astring, from); + break; + default: + assert(0); + break; + } + } + break; + case imm: + case imm0: + case imm1: + case imm2: + case immi: + assert(0); + break; + default: + assert(0); + break; + } +} + +static void gen_move16(uae_u32 opcode, struct instr *curi) { +#if defined(USE_JIT2) + comprintf("\tint src=scratchie++;\n"); + comprintf("\tint dst=scratchie++;\n"); + + uae_u32 masked_op = (opcode & 0xfff8); + if (masked_op == 0xf620) { + // POSTINCREMENT SOURCE AND DESTINATION version + comprintf("\t uae_u16 dstreg = ((%s)>>12) & 0x07;\n", gen_nextiword()); + comprintf("\t jnf_MOVE(src, srcreg + 8);"); + comprintf("\t jnf_MOVE(dst, dstreg + 8);"); + comprintf("\t if (srcreg != dstreg)\n"); + comprintf("\t jnf_ADD_imm(srcreg + 8, srcreg + 8, 16);"); + comprintf("\t jnf_ADD_imm(dstreg + 8, dstreg + 8, 16);"); + } else { + /* Other variants */ + genamode(curi->smode, "srcreg", curi->size, "src", 0, 2); + genamode(curi->dmode, "dstreg", curi->size, "dst", 0, 2); + switch (masked_op) { + case 0xf600: + comprintf("\t jnf_ADD_imm(srcreg + 8, srcreg + 8, 16);"); + break; + case 0xf608: + comprintf("\t jnf_ADD_imm(dstreg + 8, dstreg + 8, 16);"); + break; + } + } + comprintf("\t jnf_MOVE16(dst, src);"); +#else + 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"); + } 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"); + } + + /* 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("\tarm_ADD_l_ri8(srcreg+8,16);\n"); + comprintf("\tarm_ADD_l_ri8(dstreg+8,16);\n"); + } else if ((opcode & 0xfff8) == 0xf600) + comprintf("\tarm_ADD_l_ri8(srcreg+8,16);\n"); + else if ((opcode & 0xfff8) == 0xf608) + comprintf("\tarm_ADD_l_ri8(dstreg+8,16);\n"); + + start_brace(); + 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"); + close_brace(); +#endif +} + +static void genmovemel(uae_u16 opcode) { + comprintf("\tuae_u16 mask = %s;\n", gen_nextiword()); + comprintf("\tint native=scratchie++;\n"); + comprintf("\tint i;\n"); + comprintf("\tsigned char offset=0;\n"); + genamode(table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, + 1); + comprintf("\tget_n_addr(srca,native,scratchie);\n"); + + comprintf("\tfor (i=0;i<16;i++) {\n" + "\t\tif ((mask>>i)&1) {\n"); + switch (table68k[opcode].size) { + case sz_long: + comprintf("\t\t\tmov_l_rR(i,native,offset);\n" + "\t\t\tmid_bswap_32(i);\n" + "\t\t\toffset+=4;\n"); + break; + case sz_word: + comprintf("\t\t\tmov_w_rR(i,native,offset);\n" + "\t\t\tmid_bswap_16(i);\n" + "\t\t\tsign_extend_16_rr(i,i);\n" + "\t\t\toffset+=2;\n"); + break; + default: + assert(0); + break; + } + comprintf("\t\t}\n" + "\t}"); + if (table68k[opcode].dmode == Aipi) { + comprintf("\t\t\tlea_l_brr(8+dstreg,srca,offset);\n"); + } +} + +static void genmovemle(uae_u16 opcode) { + comprintf("\tuae_u16 mask = %s;\n", gen_nextiword()); + comprintf("\tint native=scratchie++;\n"); + comprintf("\tint i;\n"); + comprintf("\tint tmp=scratchie++;\n"); + comprintf("\tsigned char offset=0;\n"); + genamode(table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, + 1); + + comprintf("\tget_n_addr(srca,native,scratchie);\n"); + + if (table68k[opcode].dmode != Apdi) { + comprintf("\tfor (i=0;i<16;i++) {\n" + "\t\tif ((mask>>i)&1) {\n"); + switch (table68k[opcode].size) { + case sz_long: + comprintf("\t\t\tmov_l_rr(tmp,i);\n" + "\t\t\tmid_bswap_32(tmp);\n" + "\t\t\tmov_l_Rr(native,tmp,offset);\n" + "\t\t\toffset+=4;\n"); + break; + case sz_word: + comprintf("\t\t\tmov_l_rr(tmp,i);\n" + "\t\t\tmid_bswap_16(tmp);\n" + "\t\t\tmov_w_Rr(native,tmp,offset);\n" + "\t\t\toffset+=2;\n"); + break; + default: + assert(0); + break; + } + } else { /* Pre-decrement */ + comprintf("\tfor (i=0;i<16;i++) {\n" + "\t\tif ((mask>>i)&1) {\n"); + switch (table68k[opcode].size) { + case sz_long: + comprintf("\t\t\toffset-=4;\n" + "\t\t\tmov_l_rr(tmp,15-i);\n" + "\t\t\tmid_bswap_32(tmp);\n" + "\t\t\tmov_l_Rr(native,tmp,offset);\n"); + break; + case sz_word: + comprintf("\t\t\toffset-=2;\n" + "\t\t\tmov_l_rr(tmp,15-i);\n" + "\t\t\tmid_bswap_16(tmp);\n" + "\t\t\tmov_w_Rr(native,tmp,offset);\n"); + break; + default: + assert(0); + break; + } + } + + comprintf("\t\t}\n" + "\t}"); + if (table68k[opcode].dmode == Apdi) { + comprintf("\t\t\tlea_l_brr(8+dstreg,srca,(uae_s32)offset);\n"); + } +} + +static void duplicate_carry(void) { + comprintf("\tif (needed_flags&FLAG_X) duplicate_carry();\n"); +} + +typedef enum { + flag_logical_noclobber, + flag_logical, + flag_add, + flag_sub, + flag_cmp, + flag_addx, + flag_subx, + flag_zn, + flag_av, + flag_sv, + flag_and, + flag_or, + flag_eor, + flag_mov +} flagtypes; + +#if !defined(USE_JIT2) +static void genflags(flagtypes type, wordsizes size, const char *value, const char *src, const char *dst) +{ + if (noflags) { + switch (type) { + case flag_cmp: + comprintf("\tdont_care_flags();\n"); + comprintf("/* Weird --- CMP with noflags ;-) */\n"); + return; + case flag_add: + case flag_sub: + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch (type) { + case flag_add: + op = "add"; + break; // nf + case flag_sub: + op = "sub"; + break; // nf + default: + assert(0); + break; + } + switch (size) { + case sz_byte: + comprintf("\t%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("\t%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\t%s_l(%s,%s);\n", op, dst, src); + break; + } + return; + } + break; + + case flag_and: + comprintf("\tdont_care_flags();\n"); + switch (size) { + case sz_byte: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_8_rr(scratchie,%s);\n", src); + comprintf("\tor_l_ri(scratchie,0xffffff00);\n"); // nf + comprintf("\tarm_AND_l(%s,scratchie);\n", dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tarm_AND_b(%s,%s);\n", dst, src); + break; + case sz_word: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_16_rr(scratchie,%s);\n", src); + comprintf("\tor_l_ri(scratchie,0xffff0000);\n"); // nf + comprintf("\tarm_AND_l(%s,scratchie);\n", dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tarm_AND_w(%s,%s);\n", dst, src); + break; + case sz_long: + comprintf("\tarm_AND_l(%s,%s);\n", dst, src); + break; + } + return; + + case flag_mov: + comprintf("\tdont_care_flags();\n"); + switch (size) { + case sz_byte: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_8_rr(scratchie,%s);\n", src); + comprintf("\tand_l_ri(%s,0xffffff00);\n", dst); // nf + comprintf("\tarm_ORR_l(%s,scratchie);\n", dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tmov_b_rr(%s,%s);\n", dst, src); + break; + case sz_word: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_16_rr(scratchie,%s);\n", src); + comprintf("\tand_l_ri(%s,0xffff0000);\n", dst); // nf + comprintf("\tarm_ORR_l(%s,scratchie);\n", dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tmov_w_rr(%s,%s);\n", dst, src); + break; + case sz_long: + comprintf("\tmov_l_rr(%s,%s);\n", dst, src); + break; + } + return; + + case flag_or: + case flag_eor: + comprintf("\tdont_care_flags();\n"); + start_brace(); + { + const char* op; + switch (type) { + case flag_or: + op = "ORR"; + break; // nf + case flag_eor: + op = "EOR"; + break; // nf + default: + assert(0); + break; + } + switch (size) { + case sz_byte: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_8_rr(scratchie,%s);\n", src); + comprintf("\tarm_%s_l(%s,scratchie);\n", op, dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tarm_%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_16_rr(scratchie,%s);\n", src); + comprintf("\tarm_%s_l(%s,scratchie);\n", op, dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tarm_%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\tarm_%s_l(%s,%s);\n", op, dst, src); + break; + } + close_brace(); + return; + } + + case flag_addx: + case flag_subx: + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch (type) { + case flag_addx: + op = "adc"; + break; + case flag_subx: + op = "sbb"; + break; + default: + assert(0); + break; + } + comprintf("\trestore_carry();\n"); /* Reload the X flag into C */ + switch (size) { + case sz_byte: + comprintf("\t%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("\t%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\t%s_l(%s,%s);\n", op, dst, src); + break; + } + return; + } + break; + default: + return; + } + } + + /* Need the flags, but possibly not all of them */ + switch (type) { + case flag_logical_noclobber: + failure; + /* fall through */ + + case flag_and: + case flag_or: + case flag_eor: + comprintf("\tdont_care_flags();\n"); + start_brace(); + { + const char* op; + switch (type) { + case flag_and: + op = "and"; + break; + case flag_or: + op = "or"; + break; + case flag_eor: + op = "xor"; + break; + default: + assert(0); + break; + } + switch (size) { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\t%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\t%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\t%s_l(%s,%s);\n", op, dst, src); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + close_brace(); + return; + } + + case flag_mov: + comprintf("\tdont_care_flags();\n"); + start_brace(); + { + switch (size) { + case sz_byte: + comprintf("\tif (%s!=%s) {\n", src, dst); + comprintf("\tmov_b_ri(%s,0);\n" + "\tstart_needflags();\n", dst); + comprintf("\tor_b(%s,%s);\n", dst, src); + comprintf("\t} else {\n"); + comprintf("\tmov_b_rr(%s,%s);\n", dst, src); + comprintf("\ttest_b_rr(%s,%s);\n", dst, dst); + comprintf("\t}\n"); + break; + case sz_word: + comprintf("\tif (%s!=%s) {\n", src, dst); + comprintf("\tmov_w_ri(%s,0);\n" + "\tstart_needflags();\n", dst); + comprintf("\tor_w(%s,%s);\n", dst, src); + comprintf("\t} else {\n"); + comprintf("\tmov_w_rr(%s,%s);\n", dst, src); + comprintf("\ttest_w_rr(%s,%s);\n", dst, dst); + comprintf("\t}\n"); + break; + case sz_long: + comprintf("\tif (%s!=%s) {\n", src, dst); + comprintf("\tmov_l_ri(%s,0);\n" + "\tstart_needflags();\n", dst); + comprintf("\tor_l(%s,%s);\n", dst, src); + comprintf("\t} else {\n"); + comprintf("\tmov_l_rr(%s,%s);\n", dst, src); + comprintf("\ttest_l_rr(%s,%s);\n", dst, dst); + comprintf("\t}\n"); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + close_brace(); + return; + } + + case flag_logical: + comprintf("\tdont_care_flags();\n"); + start_brace(); + switch (size) { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\ttest_b_rr(%s,%s);\n", value, value); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\ttest_w_rr(%s,%s);\n", value, value); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\ttest_l_rr(%s,%s);\n", value, value); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + close_brace(); + return; + + case flag_add: + case flag_sub: + case flag_cmp: + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch (type) { + case flag_add: + op = "add"; + break; + case flag_sub: + op = "sub"; + break; + case flag_cmp: + op = "cmp"; + break; + default: + assert(0); + break; + } + switch (size) { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\t%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\t%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\t%s_l(%s,%s);\n", op, dst, src); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + if (type != flag_cmp) { + duplicate_carry(); + } + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + + return; + } + + case flag_addx: + case flag_subx: + uses_cmov; + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch (type) { + case flag_addx: + op = "adc"; + break; + case flag_subx: + op = "sbb"; + break; + default: + assert(0); + break; + } + start_brace(); + comprintf("\tint zero=scratchie++;\n" + "\tint one=scratchie++;\n" + "\tif (needed_flags&FLAG_Z) {\n" + "\tmov_l_ri(zero,0);\n" + "\tmov_l_ri(one,-1);\n" + "\tmake_flags_live();\n" + "\tcmov_l_rr(zero,one,%d);\n" + "\t}\n", NATIVE_CC_NE); + comprintf("\trestore_carry();\n"); /* Reload the X flag into C */ + switch (size) { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\t%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\t%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\t%s_l(%s,%s);\n", op, dst, src); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tif (needed_flags&FLAG_Z) {\n" + "\tcmov_l_rr(zero,one,%d);\n" + "\tset_zero(zero, one);\n" /* No longer need one */ + "\tlive_flags();\n" + "\t}\n", NATIVE_CC_NE); + comprintf("\tend_needflags();\n"); + duplicate_carry(); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + return; + } + default: + failure; + break; + } +} +#endif + +static void gen_abcd(uae_u32 opcode, struct instr *curi, const char* ssize) { +#if 0 +#else + (void) opcode; + (void) curi; + (void) ssize; + failure; + /* No BCD maths for me.... */ +#endif +} + +static void gen_add(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + // Use tmp register to avoid destroying upper part in .B., .W cases + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ADD_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_ADD(tmp,dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_add, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_adda(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\t jnf_ADDA_%s(dst, src);\n", ssize); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\tint tmp=scratchie++;\n"); + switch (curi->size) { + 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: + assert(0); + break; + } + comprintf("\tarm_ADD_l(dst,tmp);\n"); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#endif +} + +static void gen_addx(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + + // Use tmp register to avoid destroying upper part in .B., .W cases + comprintf("\t dont_care_flags();\n"); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ADDX_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf("\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_ADDX(tmp,dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + genflags(flag_addx, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_and(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + + comprintf("\t dont_care_flags();\n"); + comprintf("\t int tmp=scratchie++;\n"); + start_brace(); + if (!noflags) { + comprintf("\t jff_AND_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_AND(tmp,dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_and, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_andsr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ANDSR(ARM_CCR_MAP[src & 0xF], (src & 0x10));\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } +#else + (void) curi; + failure; + isjump; +#endif +} + +static void gen_asl(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\t dont_care_flags();\n"); + comprintf("\t int tmp=scratchie++;\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + + if (curi->smode != immi) { + if (!noflags) { + start_brace(); + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ASL_%s_reg(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + start_brace(); + comprintf("\t jnf_LSL_reg(tmp,data,cnt);\n"); + } + } else { + start_brace(); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ASL_%s_imm(tmp,data,srcreg);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_LSL_imm(tmp,data,srcreg);\n"); + } + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) ssize; + + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + /* Except for the handling of the V flag, this is identical to + LSL. The handling of V is, uhm, unpleasant, so if it's needed, + let the normal emulation handle it. Shoulders of giants kinda + thing ;-) */ + comprintf("if (needed_flags & FLAG_V) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode != immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + 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: + assert(0); + break; + } + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch (curi->size) { + 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: + assert(0); + break; + } + comprintf("test_l_ri(tmpcnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(cdata,scratchie,%d);\n", NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,7);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,15);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,31);\n"); + break; + } + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + 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: + assert(0); + break; + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } + } else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_ri(data,srcreg);\n" + "\tbp=8-srcreg;\n"); + break; + case sz_word: + comprintf("\tshll_w_ri(data,srcreg);\n" + "\tbp=16-srcreg;\n"); + break; + case sz_long: + comprintf("\tshll_l_ri(data,srcreg);\n" + "\tbp=32-srcreg;\n"); + break; + default: + assert(0); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } +#endif +} + +static void gen_aslw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ASLW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_ASLW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_asr(uae_u32 opcode, struct instr *curi, const char* ssize) { +#if defined(USE_JIT2) + (void)opcode; + + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\t dont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (curi->smode != immi) { + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ASR_%s_reg(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_ASR_%s_reg(tmp,data,cnt);\n", ssize); + } + } else { + char *op; + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + op = "ff"; + } else + op = "nf"; + + comprintf("\t j%s_ASR_%s_imm(tmp,data,srcreg);\n", op, ssize); + if (!noflags) { + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) opcode; + (void) ssize; + + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode != immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint width;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n" + "\tint highshift=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch (curi->size) { + case sz_byte: + comprintf("\tshra_b_rr(data,cnt);\n" + "\thighmask=0x38;\n" + "\twidth=8;\n"); + break; + case sz_word: + comprintf("\tshra_w_rr(data,cnt);\n" + "\thighmask=0x30;\n" + "\twidth=16;\n"); + break; + case sz_long: + comprintf("\tshra_l_rr(data,cnt);\n" + "\thighmask=0x20;\n" + "\twidth=32;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(highshift,0);\n" + "mov_l_ri(scratchie,width/2);\n" + "cmov_l_rr(highshift,scratchie,%d);\n", NATIVE_CC_NE); + /* The x86 masks out bits, so we now make sure that things + really get shifted as much as planned */ + 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: + assert(0); + break; + } + /* 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: + assert(0); + break; + } + + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch (curi->size) { + 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: + assert(0); + break; + } + /* If the shift count was higher than the width, we need + to pick up the sign from data */ + comprintf("test_l_ri(tmpcnt,highmask);\n" + "cmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint width;\n" + "\tint highshift=scratchie++;\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshra_b_rr(data,cnt);\n" + "\thighmask=0x38;\n" + "\twidth=8;\n"); + break; + case sz_word: + comprintf("\tshra_w_rr(data,cnt);\n" + "\thighmask=0x30;\n" + "\twidth=16;\n"); + break; + case sz_long: + comprintf("\tshra_l_rr(data,cnt);\n" + "\thighmask=0x20;\n" + "\twidth=32;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(highshift,0);\n" + "mov_l_ri(scratchie,width/2);\n" + "cmov_l_rr(highshift,scratchie,%d);\n", NATIVE_CC_NE); + /* The x86 masks out bits, so we now make sure that things + really get shifted as much as planned */ + 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: + assert(0); + break; + } + /* 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: + assert(0); + break; + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } + } else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshra_b_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + case sz_word: + comprintf("\tshra_w_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + case sz_long: + comprintf("\tshra_l_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + default: + assert(0); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } +#endif +} + +static void gen_asrw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ASRW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_ASRW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_bchg(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_BCHG_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_BCHG_%s(dst,src);\n", ssize); + comprintf("\t dont_care_flags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint s=scratchie++;\n" + "\tint tmp=scratchie++;\n" + "\tmov_l_rr(s,src);\n"); + if (curi->size == sz_byte) + comprintf("\tand_l_ri(s,7);\n"); + else + comprintf("\tand_l_ri(s,31);\n"); + + comprintf("\tbtc_l_rr(dst,s);\n" /* Answer now in C */ + "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */ + "\tmake_flags_live();\n" /* Get the flags back */ + "\tdont_care_flags();\n"); + if (!noflags) { + comprintf("\tstart_needflags();\n" + "\tset_zero(s,tmp);\n" + "\tlive_flags();\n" + "\tend_needflags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_bclr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_BCLR_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_BCLR_%s(dst,src);\n", ssize); + comprintf("\t dont_care_flags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint s=scratchie++;\n" + "\tint tmp=scratchie++;\n" + "\tmov_l_rr(s,src);\n"); + if (curi->size == sz_byte) + comprintf("\tand_l_ri(s,7);\n"); + else + comprintf("\tand_l_ri(s,31);\n"); + + comprintf("\tbtr_l_rr(dst,s);\n" /* Answer now in C */ + "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */ + "\tmake_flags_live();\n" /* Get the flags back */ + "\tdont_care_flags();\n"); + if (!noflags) { + comprintf("\tstart_needflags();\n" + "\tset_zero(s,tmp);\n" + "\tlive_flags();\n" + "\tend_needflags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_bset(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_BSET_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_BSET_%s(dst,src);\n", ssize); + comprintf("\t dont_care_flags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint s=scratchie++;\n" + "\tint tmp=scratchie++;\n" + "\tmov_l_rr(s,src);\n"); + if (curi->size == sz_byte) + comprintf("\tand_l_ri(s,7);\n"); + else + comprintf("\tand_l_ri(s,31);\n"); + + comprintf("\tbts_l_rr(dst,s);\n" /* Answer now in C */ + "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */ + "\tmake_flags_live();\n" /* Get the flags back */ + "\tdont_care_flags();\n"); + if (!noflags) { + comprintf("\tstart_needflags();\n" + "\tset_zero(s,tmp);\n" + "\tlive_flags();\n" + "\tend_needflags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_btst(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + + // If we are not interested in flags it is not necessary to do + // anything with the data + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_BTST_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t dont_care_flags();\n"); + } +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint s=scratchie++;\n" + "\tint tmp=scratchie++;\n" + "\tmov_l_rr(s,src);\n"); + if (curi->size == sz_byte) + comprintf("\tand_l_ri(s,7);\n"); + else + comprintf("\tand_l_ri(s,31);\n"); + + comprintf("\tbt_l_rr(dst,s);\n" /* Answer now in C */ + "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */ + "\tmake_flags_live();\n" /* Get the flags back */ + "\tdont_care_flags();\n"); + if (!noflags) { + comprintf("\tstart_needflags();\n" + "\tset_zero(s,tmp);\n" + "\tlive_flags();\n" + "\tend_needflags();\n"); + } +#endif +} + +static void gen_clr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 2, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_CLR(tmp);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_CLR(tmp);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + genamode(curi->smode, "srcreg", curi->size, "src", 2, 0); + start_brace(); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0);\n"); + genflags(flag_logical, curi->size, "dst", "", ""); + genastore("dst", curi->smode, "srcreg", curi->size, "src"); +#endif +} + +static void gen_cmp(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\t dont_care_flags();\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_CMP_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("/* Weird --- CMP with noflags ;-) */\n"); + } +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + genflags(flag_cmp, curi->size, "", "src", "dst"); +#endif +} + +static void gen_cmpa(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + if (!noflags) { + comprintf("\t dont_care_flags();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_CMPA_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\tdont_care_flags();\n"); + comprintf("/* Weird --- CMP with noflags ;-) */\n"); + } +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\tint tmps=scratchie++;\n"); + switch (curi->size) { + 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: + assert(0); + break; + } + genflags(flag_cmp, sz_long, "", "tmps", "dst"); +#endif +} + +static void gen_dbcc(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if 0 + isjump; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "offs", 1, 0); + + comprintf("uae_u32 voffs;\n"); + comprintf("voffs = get_const(offs);\n"); + /* That offs is an immediate, so we can clobber it with abandon */ + switch (curi->size) { + case sz_word: + comprintf("\t voffs = (uae_s32)((uae_s16)voffs);\n"); + break; + default: + assert(0); /* Seems this only comes in word flavour */ + break; + } + comprintf("\t voffs -= m68k_pc_offset - m68k_pc_offset_thisinst - 2;\n"); + comprintf("\t voffs += (uintptr)comp_pc_p + m68k_pc_offset;\n"); + + comprintf("\t add_const_v(PC_P, m68k_pc_offset);\n"); + comprintf("\t m68k_pc_offset = 0;\n"); + + start_brace(); + + if (curi->cc >= 2) { + comprintf("\t make_flags_live();\n"); /* Load the flags */ + } + + assert(curi->size == sz_word); + + switch (curi->cc) { + case 0: /* This is an elaborate nop? */ + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + comprintf("\t start_needflags();\n"); + comprintf("\t jnf_DBcc(src,voffs,%d);\n", curi->cc); + comprintf("\t end_needflags();\n"); + break; + default: + assert(0); + break; + } + genastore("src", curi->smode, "srcreg", curi->size, "src"); + gen_update_next_handler(); +#else + isjump; + uses_cmov; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "offs", 1, 0); + + /* 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: + assert(0); /* Seems this only comes in word flavour */ + break; + } + comprintf("\tsub_l_ri(offs,m68k_pc_offset-m68k_pc_offset_thisinst-2);\n"); + comprintf("\tarm_ADD_l_ri(offs,(uintptr)comp_pc_p);\n"); + /* New PC, + once the + offset_68k is + * also added */ + /* Let's fold in the m68k_pc_offset at this point */ + comprintf("\tarm_ADD_l_ri(offs,m68k_pc_offset);\n"); + comprintf("\tarm_ADD_l_ri(PC_P,m68k_pc_offset);\n"); + comprintf("\tm68k_pc_offset=0;\n"); + + start_brace(); + comprintf("\tint nsrc=scratchie++;\n"); + + if (curi->cc >= 2) { + comprintf("\tmake_flags_live();\n"); /* Load the flags */ + } + + assert (curi->size == sz_word); + + switch (curi->cc) { + case 0: /* This is an elaborate nop? */ + break; + case 1: + comprintf("\tstart_needflags();\n"); + comprintf("\tsub_w_ri(src,1);\n"); + comprintf("\t end_needflags();\n"); + start_brace(); + comprintf("\tuae_u32 v2,v;\n" + "\tuae_u32 v1=get_const(PC_P);\n"); + comprintf("\tv2=get_const(offs);\n" + "\tregister_branch(v1,v2,%d);\n", NATIVE_CC_CC); + break; + + case 8: + failure; + break; /* Work out details! FIXME */ + case 9: + failure; + break; /* Not critical, though! */ + + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + comprintf("\tmov_l_rr(nsrc,src);\n"); + comprintf("\tlea_l_brr(scratchie,src,(uae_s32)-1);\n" + "\tmov_w_rr(src,scratchie);\n"); + comprintf("\tcmov_l_rr(offs,PC_P,%d);\n", cond_codes[curi->cc]); + comprintf("\tcmov_l_rr(src,nsrc,%d);\n", cond_codes[curi->cc]); + /* OK, now for cc=true, we have src==nsrc and offs==PC_P, + so whether we move them around doesn't matter. However, + if cc=false, we have offs==jump_pc, and src==nsrc-1 */ + + comprintf("\t start_needflags();\n"); + comprintf("\ttest_w_rr(nsrc,nsrc);\n"); + comprintf("\t end_needflags();\n"); + comprintf("\tcmov_l_rr(PC_P,offs,%d);\n", NATIVE_CC_NE); + break; + default: + assert(0); + break; + } + genastore("src", curi->smode, "srcreg", curi->size, "src"); + gen_update_next_handler(); +#endif +} + +static void gen_eor(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t jff_EOR_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_EOR(tmp,dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_eor, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_eorsr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_EORSR(ARM_CCR_MAP[src & 0xF], ((src & 0x10) >> 4));\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } +#else + (void) curi; + failure; + isjump; +#endif +} + +static void gen_exg(uae_u32 opcode, struct instr *curi, const char* ssize) { +#if 0 +#else + (void) opcode; + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tmov_l_rr(tmp,src);\n"); + genastore("dst", curi->smode, "srcreg", curi->size, "src"); + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_ext(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", sz_long, "src", 1, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_EXT_%s(tmp,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_EXT_%s(tmp,src);\n", ssize); + } + genastore("tmp", curi->smode, "srcreg", + curi->size == sz_word ? sz_word : sz_long, "src"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", sz_long, "src", 1, 0); + comprintf("\tdont_care_flags();\n"); + start_brace(); + switch (curi->size) { + case sz_byte: + comprintf("\tint dst = src;\n" + "\tsign_extend_8_rr(src,src);\n"); + break; + case sz_word: + comprintf("\tint dst = scratchie++;\n" + "\tsign_extend_8_rr(dst,src);\n"); + break; + case sz_long: + comprintf("\tint dst = src;\n" + "\tsign_extend_16_rr(src,src);\n"); + break; + default: + assert(0); + break; + } + genflags(flag_logical, curi->size == sz_word ? sz_word : sz_long, "dst", "", + ""); + genastore("dst", curi->smode, "srcreg", + curi->size == sz_word ? sz_word : sz_long, "src"); +#endif +} + +static void gen_lsl(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + comprintf("\t int tmp=scratchie++;\n"); + if (curi->smode != immi) { + if (!noflags) { + start_brace(); + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_LSL_%s_reg(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + start_brace(); + comprintf("\t jnf_LSL_reg(tmp,data,cnt);\n"); + } + } else { + start_brace(); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_LSL_%s_imm(tmp,data,srcreg);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_LSL_imm(tmp,data,srcreg);\n"); + } + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode != immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + 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: + assert(0); + break; + } + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch (curi->size) { + 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: + assert(0); + break; + } + comprintf("test_l_ri(tmpcnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(cdata,scratchie,%d);\n", NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,7);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,15);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,31);\n"); + break; + } + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + 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: + assert(0); + break; + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } + } else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_ri(data,srcreg);\n" + "\tbp=8-srcreg;\n"); + break; + case sz_word: + comprintf("\tshll_w_ri(data,srcreg);\n" + "\tbp=16-srcreg;\n"); + break; + case sz_long: + comprintf("\tshll_l_ri(data,srcreg);\n" + "\tbp=32-srcreg;\n"); + break; + default: + assert(0); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } +#endif +} + +static void gen_lslw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_LSLW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_LSLW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_lsr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\t dont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + comprintf("\t int tmp=scratchie++;\n"); + if (curi->smode != immi) { + if (!noflags) { + start_brace(); + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_LSR_%s_reg(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + start_brace(); + comprintf("\t jnf_LSR_%s_reg(tmp,data,cnt);\n", ssize); + } + } else { + start_brace(); + char *op; + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + op = "ff"; + } else + op = "nf"; + + comprintf("\t j%s_LSR_%s_imm(tmp,data,srcreg);\n", op, ssize); + + if (!noflags) { + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) ssize; + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode != immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch (curi->size) { + case sz_byte: + comprintf("\tshrl_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshrl_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshrl_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + 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: + assert(0); + break; + } + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch (curi->size) { + 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: + assert(0); + break; + } + comprintf("test_l_ri(tmpcnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(cdata,scratchie,%d);\n", NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshrl_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshrl_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshrl_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + 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: + assert(0); + break; + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } + } else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshrl_b_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + case sz_word: + comprintf("\tshrl_w_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + case sz_long: + comprintf("\tshrl_l_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + default: + assert(0); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } +#endif +} + +static void gen_lsrw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_LSRW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_LSRW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_move(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + switch (curi->dmode) { + case Dreg: + case Areg: + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags && curi->dmode == Dreg) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_MOVE_%s(tmp, src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t tmp = src;\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); + break; + + default: /* It goes to memory, not a register */ + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_TST_%s(src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } + genastore("src", curi->dmode, "dstreg", curi->size, "dst"); + break; + } +#else + (void) ssize; + + switch (curi->dmode) { + case Dreg: + case Areg: + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genflags(flag_mov, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); + break; + default: /* It goes to memory, not a register */ + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genflags(flag_logical, curi->size, "src", "", ""); + genastore("src", curi->dmode, "dstreg", curi->size, "dst"); + break; + } +#endif +} + +static void gen_movea(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + + start_brace(); + comprintf("\t jnf_MOVEA_%s(dst, src);\n", ssize); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#else + (void) ssize; + + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + + start_brace(); + comprintf("\tint tmps=scratchie++;\n"); + 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: + assert(0); + break; + } + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#endif +} + +static void gen_mull(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t uae_u16 extra=%s;\n", gen_nextiword()); + comprintf("\t int r2=(extra>>12)&7;\n" + "\t int tmp=scratchie++;\n"); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + /* The two operands are in dst and r2 */ + if (!noflags) { + comprintf("\t if (extra & 0x0400) {\n"); /* Need full 64 bit result */ + comprintf("\t int r3=(extra & 7);\n"); + comprintf("\t mov_l_rr(r3,dst);\n"); /* operands now in r3 and r2 */ + comprintf("\t if (extra & 0x0800) { \n"); /* signed */ + comprintf("\t\t jff_MULS64(r2,r3);\n"); + comprintf("\t } else { \n"); + comprintf("\t\t jff_MULU64(r2,r3);\n"); + comprintf("\t } \n"); /* The result is in r2/r3, with r2 holding the lower 32 bits */ + comprintf("\t } else {\n"); /* Only want 32 bit result */ + /* operands in dst and r2, result goes into r2 */ + /* shouldn't matter whether it's signed or unsigned?!? */ + comprintf("\t if (extra & 0x0800) { \n"); /* signed */ + comprintf("\t jff_MULS32(r2,dst);\n"); + comprintf("\t } else { \n"); + comprintf("\t\t jff_MULU32(r2,dst);\n"); + comprintf("\t } \n"); /* The result is in r2, with r2 holding the lower 32 bits */ + comprintf("\t }\n"); + } else { + comprintf("\t if (extra & 0x0400) {\n"); /* Need full 64 bit result */ + comprintf("\t int r3=(extra & 7);\n"); + comprintf("\t mov_l_rr(r3,dst);\n"); /* operands now in r3 and r2 */ + comprintf("\t if (extra & 0x0800) { \n"); /* signed */ + comprintf("\t\t jnf_MULS64(r2,r3);\n"); + comprintf("\t } else { \n"); + comprintf("\t\t jnf_MULU64(r2,r3);\n"); + comprintf("\t } \n"); /* The result is in r2/r3, with r2 holding the lower 32 bits */ + comprintf("\t } else {\n"); /* Only want 32 bit result */ + /* operands in dst and r2, result foes into r2 */ + /* shouldn't matter whether it's signed or unsigned?!? */ + comprintf("\t if (extra & 0x0800) { \n"); /* signed */ + comprintf("\t jnf_MULS32(r2,dst);\n"); + comprintf("\t } else { \n"); + comprintf("\t\t jnf_MULU32(r2,dst);\n"); + comprintf("\t } \n"); /* The result is in r2, with r2 holding the lower 32 bits */ + comprintf("\t }\n"); + } +#else + if (!noflags) { + failure; + return; + } + comprintf("\tuae_u16 extra=%s;\n", gen_nextiword()); + comprintf("\tint r2=(extra>>12)&7;\n" + "\tint tmp=scratchie++;\n"); + + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + /* The two operands are in dst and r2 */ + comprintf("\tif (extra&0x0400) {\n" /* Need full 64 bit result */ + "\tint r3=(extra&7);\n" + "\tmov_l_rr(r3,dst);\n"); /* operands now in r3 and r2 */ + comprintf("\tif (extra&0x0800) { \n" /* signed */ + "\t\timul_64_32(r2,r3);\n" + "\t} else { \n" + "\t\tmul_64_32(r2,r3);\n" + "\t} \n"); + /* The result is in r2/tmp, with r2 holding the lower 32 bits */ + comprintf("\t} else {\n"); /* Only want 32 bit result */ + /* operands in dst and r2, result foes into r2 */ + /* shouldn't matter whether it's signed or unsigned?!? */ + comprintf("\timul_32_32(r2,dst);\n" + "\t}\n"); +#endif +} + +static void gen_muls(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_word, "dst", 1, 0); + start_brace(); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_MULS(dst,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_MULS(dst,src);\n"); + } + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#else + comprintf("\tdont_care_flags();\n"); + genamode(curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_word, "dst", 1, 0); + comprintf("\tsign_extend_16_rr(scratchie,src);\n" + "\tsign_extend_16_rr(dst,dst);\n" + "\timul_32_32(dst,scratchie);\n"); + genflags(flag_logical, sz_long, "dst", "", ""); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#endif +} + +static void gen_mulu(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_word, "dst", 1, 0); + start_brace(); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_MULU(dst,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_MULU(dst,src);\n"); + } + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#else + comprintf("\tdont_care_flags();\n"); + genamode(curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_word, "dst", 1, 0); + /* To do 16x16 unsigned multiplication, we actually use + 32x32 signed, and zero-extend the registers first. + That solves the problem of MUL needing dedicated registers + on the x86 */ + comprintf("\tzero_extend_16_rr(scratchie,src);\n" + "\tzero_extend_16_rr(dst,dst);\n" + "\timul_32_32(dst,scratchie);\n"); + genflags(flag_logical, sz_long, "dst", "", ""); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); + +#endif +} + +static void gen_nbcd(uae_u32 opcode, struct instr *curi, const char* ssize) { +#if 0 +#else + (void) opcode; + (void) curi; + (void) ssize; + failure; + /* Nope! */ +#endif +} + +static void gen_neg(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_NEG_%s(tmp,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf("\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_NEG(tmp,src);\n"); + } + + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0);\n"); + genflags(flag_sub, curi->size, "", "src", "dst"); + genastore("dst", curi->smode, "srcreg", curi->size, "src"); +#endif +} + +static void gen_negx(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int dst=scratchie++;\n"); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_inverted_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_NEGX_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf("\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t restore_inverted_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_NEGX(dst,src);\n"); + } + + genastore("dst", curi->smode, "srcreg", curi->size, "src"); +#else + (void) ssize; + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0);\n"); + genflags(flag_subx, curi->size, "", "src", "dst"); + genastore("dst", curi->smode, "srcreg", curi->size, "src"); +#endif +} + +static void gen_not(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_NOT_%s(tmp,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_NOT(tmp,src);\n", ssize); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0xffffffff);\n"); + genflags(flag_eor, curi->size, "", "src", "dst"); + genastore("dst", curi->smode, "srcreg", curi->size, "src"); +#endif +} + +static void gen_or(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t jff_OR_%s(tmp, dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_OR(tmp, dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_or, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_orsr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ORSR(ARM_CCR_MAP[src & 0xF], ((src & 0x10) >> 4));\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } +#else + (void) curi; + failure; + isjump; +#endif +} + +static void gen_rol(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROL_%s(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_ROL_%s(tmp,data,cnt);\n", ssize); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) ssize; + + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + + switch (curi->size) { + case sz_long: + comprintf("\t rol_l_rr(data,cnt);\n"); + break; + case sz_word: + comprintf("\t rol_w_rr(data,cnt);\n"); + break; + case sz_byte: + comprintf("\t rol_b_rr(data,cnt);\n"); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(data,0x00);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); +#endif +} + +static void gen_rolw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROLW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_ROLW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_ror(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROR_%s(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_ROR_%s(tmp,data,cnt);\n", ssize); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) ssize; + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + + switch (curi->size) { + case sz_long: + comprintf("\t ror_l_rr(data,cnt);\n"); + break; + case sz_word: + comprintf("\t ror_w_rr(data,cnt);\n"); + break; + case sz_byte: + comprintf("\t ror_b_rr(data,cnt);\n"); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + switch (curi->size) { + case sz_byte: + comprintf("\t bt_l_ri(data,0x07);\n"); + break; + case sz_word: + comprintf("\t bt_l_ri(data,0x0f);\n"); + break; + case sz_long: + comprintf("\t bt_l_ri(data,0x1f);\n"); + break; + } + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); +#endif +} + +static void gen_rorw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_RORW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_RORW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_roxl(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + isaddx; + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROXL_%s(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + } else { + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_ROXL_%s(tmp,data,cnt);\n", ssize); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) curi; + (void) ssize; + failure; +#endif +} + +static void gen_roxlw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + isaddx; + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROXLW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + } else { + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_ROXLW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_roxr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + isaddx; + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROXR_%s(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + } else { + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_ROXR_%s(tmp,data,cnt);\n", ssize); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) curi; + failure; +#endif +} + +static void gen_roxrw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + isaddx; + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROXRW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + } else { + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_ROXRW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_sbcd(uae_u32 opcode, struct instr *curi, const char* ssize) { +#if 0 +#else + (void) opcode; + (void) curi; + (void) ssize; + failure; + /* I don't think so! */ +#endif +} + +static void gen_scc(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if 0 + genamode(curi->smode, "srcreg", curi->size, "src", 2, 0); + start_brace(); + comprintf("\t int val = scratchie++;\n"); + switch (curi->cc) { + case 0: /* Unconditional set */ + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + comprintf("\t make_flags_live();\n"); /* Load the flags */ + comprintf("\t jnf_Scc_ri(val,%d);\n", curi->cc); + break; + default: + assert(0); + break; + } + genastore("val", curi->smode, "srcreg", curi->size, "src"); +#else + genamode(curi->smode, "srcreg", curi->size, "src", 2, 0); + start_brace(); + comprintf("\tint val = scratchie++;\n"); + + /* We set val to 0 if we really should use 255, and to 1 for real 0 */ + switch (curi->cc) { + case 0: /* Unconditional set */ + comprintf("\tmov_l_ri(val,0);\n"); + break; + case 1: + /* Unconditional not-set */ + comprintf("\tmov_l_ri(val,1);\n"); + break; + case 8: + failure; + break; /* Work out details! FIXME */ + case 9: + failure; + break; /* Not critical, though! */ + + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + comprintf("\tmake_flags_live();\n"); /* Load the flags */ + /* All condition codes can be inverted by changing the LSB */ + comprintf("\tsetcc(val,%d);\n", cond_codes[curi->cc] ^ 1); + break; + default: + assert(0); + break; + } + comprintf("\tsub_b_ri(val,1);\n"); + genastore("val", curi->smode, "srcreg", curi->size, "src"); +#endif +} + +static void gen_sub(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + + comprintf("\t dont_care_flags();\n"); + start_brace(); + // Use tmp register to avoid destroying upper part in .B., .W cases + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_SUB_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_SUB_%s(tmp,dst,src);\n", ssize); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_sub, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_suba(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\t jnf_SUBA_%s(dst, src);\n", ssize); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\tint tmp=scratchie++;\n"); + switch (curi->size) { + 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: + assert(0); + break; + } + comprintf("\tsub_l(dst,tmp);\n"); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#endif +} + +static void gen_subx(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint tmp=scratchie++;\n"); + comprintf("\tdont_care_flags();\n"); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_inverted_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_SUBX_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t restore_inverted_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_SUBX(tmp,dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_subx, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_swap(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", sz_long, "src", 1, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_SWAP(src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_SWAP(src);\n"); + } + genastore("src", curi->smode, "srcreg", sz_long, "src"); +#else + genamode(curi->smode, "srcreg", sz_long, "src", 1, 0); + comprintf("\tdont_care_flags();\n"); + comprintf("\tarm_ROR_l_ri8(src,16);\n"); + genflags(flag_logical, sz_long, "src", "", ""); + genastore("src", curi->smode, "srcreg", sz_long, "src"); +#endif +} + +static void gen_tst(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + comprintf("\t dont_care_flags();\n"); + if (!noflags) { + start_brace(); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_TST_%s(src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } +#else + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genflags(flag_logical, curi->size, "src", "", ""); +#endif +} + +static int /* returns zero for success, non-zero for failure */ +gen_opcode(unsigned long int opcode) { + struct instr *curi = table68k + opcode; + const char* ssize = NULL; + + insn_n_cycles = 2; + global_failure = 0; + long_opcode = 0; + global_isjump = 0; + global_iscjump = 0; + global_isaddx = 0; + global_cmov = 0; + global_fpu = 0; + global_mayfail = 0; + hack_opcode = opcode; + endstr[0] = 0; + + start_brace(); + comprintf("\tuae_u8 scratchie=S1;\n"); + switch (curi->plev) { + case 0: /* not privileged */ + break; + case 1: /* unprivileged only on 68000 */ + if (cpu_level == 0) + break; + if (next_cpu_level < 0) + next_cpu_level = 0; + + /* fall through */ + case 2: /* priviledged */ + failure; /* Easy ones first */ + break; + case 3: /* privileged if size == word */ + if (curi->size == sz_byte) + break; + failure; + break; + } + switch (curi->size) { + case sz_byte: + ssize = "b"; + break; + case sz_word: + ssize = "w"; + break; + case sz_long: + ssize = "l"; + break; + default: + assert(0); + break; + } + (void) ssize; + + switch (curi->mnemo) { + case i_AND: + gen_and(opcode, curi, ssize); + break; + + case i_OR: + gen_or(opcode, curi, ssize); + break; + + case i_EOR: + gen_eor(opcode, curi, ssize); + break; + + case i_ORSR: + gen_orsr(opcode, curi, ssize); + break; + + case i_EORSR: + gen_eorsr(opcode, curi, ssize); + break; + + case i_ANDSR: + gen_andsr(opcode, curi, ssize); + break; + + case i_SUB: + gen_sub(opcode, curi, ssize); + break; + + case i_SUBA: + gen_suba(opcode, curi, ssize); + break; + + case i_SUBX: + gen_subx(opcode, curi, ssize); + break; + + case i_SBCD: + gen_sbcd(opcode, curi, ssize); + break; + + case i_ADD: + gen_add(opcode, curi, ssize); + break; + + case i_ADDA: + gen_adda(opcode, curi, ssize); + break; + + case i_ADDX: + gen_addx(opcode, curi, ssize); + break; + + case i_ABCD: + gen_abcd(opcode, curi, ssize); + break; + + case i_NEG: + gen_neg(opcode, curi, ssize); + break; + + case i_NEGX: + gen_negx(opcode, curi, ssize); + break; + + case i_NBCD: + gen_nbcd(opcode, curi, ssize); + break; + + case i_CLR: + gen_clr(opcode, curi, ssize); + break; + + case i_NOT: + gen_not(opcode, curi, ssize); + break; + + case i_TST: + gen_tst(opcode, curi, ssize); + break; + + case i_BCHG: + gen_bchg(opcode, curi, ssize); + break; + + case i_BCLR: + gen_bclr(opcode, curi, ssize); + break; + + case i_BSET: + gen_bset(opcode, curi, ssize); + break; + + case i_BTST: + gen_btst(opcode, curi, ssize); + break; + + case i_CMPM: + case i_CMP: + gen_cmp(opcode, curi, ssize); + break; + + case i_CMPA: + gen_cmpa(opcode, curi, ssize); + break; + + /* The next two are coded a little unconventional, but they are doing + * weird things... */ + case i_MVPRM: + isjump; + failure; + break; + + case i_MVPMR: + isjump; + failure; + break; + + case i_MOVE: + gen_move(opcode, curi, ssize); + break; + + case i_MOVEA: + gen_movea(opcode, curi, ssize); + break; + + case i_MVSR2: + isjump; + failure; + break; + + case i_MV2SR: + isjump; + failure; + break; + + case i_SWAP: + gen_swap(opcode, curi, ssize); + break; + + case i_EXG: + gen_exg(opcode, curi, ssize); + break; + + case i_EXT: + gen_ext(opcode, curi, ssize); + break; + + case i_MVMEL: + genmovemel(opcode); + break; + + case i_MVMLE: + genmovemle(opcode); + break; + + case i_TRAP: + isjump; + failure; + break; + + case i_MVR2USP: + isjump; + failure; + break; + + case i_MVUSP2R: + isjump; + failure; + break; + + case i_RESET: + isjump; + failure; + break; + + case i_NOP: + break; + + case i_STOP: + isjump; + failure; + break; + + case i_RTE: + isjump; + failure; + break; + + case i_RTD: + genamode(curi->smode, "srcreg", curi->size, "offs", 1, 0); + /* offs is constant */ + comprintf("\tarm_ADD_l_ri8(offs,4);\n"); + start_brace(); + comprintf("\tint newad=scratchie++;\n" + "\treadlong(15,newad,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc,newad);\n" + "\tget_n_addr_jmp(newad,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n" + "\tarm_ADD_l(15,offs);\n"); + gen_update_next_handler(); + isjump; + break; + + case i_LINK: + genamode(curi->smode, "srcreg", sz_long, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "offs", 1, 0); + comprintf("\tsub_l_ri(15,4);\n" + "\twritelong_clobber(15,src,scratchie);\n" + "\tmov_l_rr(src,15);\n"); + if (curi->size == sz_word) + comprintf("\tsign_extend_16_rr(offs,offs);\n"); + comprintf("\tarm_ADD_l(15,offs);\n"); + genastore("src", curi->smode, "srcreg", sz_long, "src"); + break; + + case i_UNLK: + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + comprintf("\tmov_l_rr(15,src);\n" + "\treadlong(15,src,scratchie);\n" + "\tarm_ADD_l_ri8(15,4);\n"); + genastore("src", curi->smode, "srcreg", curi->size, "src"); + break; + + case i_RTS: + comprintf("\tint newad=scratchie++;\n" + "\treadlong(15,newad,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc,newad);\n" + "\tget_n_addr_jmp(newad,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n" + "\tlea_l_brr(15,15,4);\n"); + gen_update_next_handler(); + isjump; + break; + + case i_TRAPV: + isjump; + failure; + break; + + case i_RTR: + isjump; + failure; + break; + + case i_JSR: + isjump; + genamode(curi->smode, "srcreg", curi->size, "src", 0, 0); + start_brace(); + comprintf( + "\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); + comprintf("\tint ret=scratchie++;\n" + "\tmov_l_ri(ret,retadd);\n" + "\tsub_l_ri(15,4);\n" + "\twritelong_clobber(15,ret,scratchie);\n"); + comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n" + "\tget_n_addr_jmp(srca,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n"); + gen_update_next_handler(); + break; + + case i_JMP: + isjump; + genamode(curi->smode, "srcreg", curi->size, "src", 0, 0); + comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n" + "\tget_n_addr_jmp(srca,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n"); + gen_update_next_handler(); + break; + + case i_BSR: + is_const_jump; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf( + "\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); + comprintf("\tint ret=scratchie++;\n" + "\tmov_l_ri(ret,retadd);\n" + "\tsub_l_ri(15,4);\n" + "\twritelong_clobber(15,ret,scratchie);\n"); + comprintf("\tarm_ADD_l_ri(src,m68k_pc_offset_thisinst+2);\n"); + comprintf("\tm68k_pc_offset=0;\n"); + comprintf("\tarm_ADD_l(PC_P,src);\n"); + comprintf("\tcomp_pc_p=(uae_u8*)get_const(PC_P);\n"); + break; + + case i_Bcc: + comprintf("\tuae_u32 v,v1,v2;\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + /* That source is an immediate, so we can clobber it with abandon */ + switch (curi->size) { + case sz_byte: + comprintf("\tsign_extend_8_rr(src,src);\n"); + break; + case sz_word: + comprintf("\tsign_extend_16_rr(src,src);\n"); + break; + case sz_long: + break; + } + comprintf( + "\tsub_l_ri(src,m68k_pc_offset-m68k_pc_offset_thisinst-2);\n"); + /* Leave the following as "add" --- it will allow it to be optimized + away due to src being a constant ;-) */ + comprintf("\tarm_ADD_l_ri(src,(uintptr)comp_pc_p);\n"); + comprintf("\tmov_l_ri(PC_P,(uintptr)comp_pc_p);\n"); + /* Now they are both constant. Might as well fold in m68k_pc_offset */ + comprintf("\tarm_ADD_l_ri(src,m68k_pc_offset);\n"); + comprintf("\tarm_ADD_l_ri(PC_P,m68k_pc_offset);\n"); + comprintf("\tm68k_pc_offset=0;\n"); + + if (curi->cc >= 2) { + comprintf("\tv1=get_const(PC_P);\n" + "\tv2=get_const(src);\n" + "\tregister_branch(v1,v2,%d);\n", cond_codes[curi->cc]); + comprintf("\tmake_flags_live();\n"); /* Load the flags */ + isjump; + } else { + is_const_jump; + } + + switch (curi->cc) { + case 0: /* Unconditional jump */ + comprintf("\tmov_l_rr(PC_P,src);\n"); + comprintf("\tcomp_pc_p=(uae_u8*)get_const(PC_P);\n"); + break; + case 1: + break; /* This is silly! */ + case 8: + failure; + break; /* Work out details! FIXME */ + case 9: + failure; + break; /* Not critical, though! */ + + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + break; + default: + assert(0); + break; + } + break; + + case i_LEA: + genamode(curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genastore("srca", curi->dmode, "dstreg", curi->size, "dst"); + break; + + case i_PEA: + if (table68k[opcode].smode == Areg || table68k[opcode].smode == Aind + || table68k[opcode].smode == Aipi + || table68k[opcode].smode == Apdi + || table68k[opcode].smode == Ad16 + || table68k[opcode].smode == Ad8r) + comprintf("if (srcreg==7) dodgy=1;\n"); + + genamode(curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode(Apdi, "7", sz_long, "dst", 2, 0); + genastore("srca", Apdi, "7", sz_long, "dst"); + break; + + case i_DBcc: + gen_dbcc(opcode, curi, ssize); + break; + + case i_Scc: + gen_scc(opcode, curi, ssize); + break; + + case i_DIVU: + isjump; + failure; + break; + + case i_DIVS: + isjump; + failure; + break; + + case i_MULU: + gen_mulu(opcode, curi, ssize); + break; + + case i_MULS: + gen_muls(opcode, curi, ssize); + break; + + case i_CHK: + isjump; + failure; + break; + + case i_CHK2: + isjump; + failure; + break; + + case i_ASR: + gen_asr(opcode, curi, ssize); + break; + + case i_ASL: + gen_asl(opcode, curi, ssize); + break; + + case i_LSR: + gen_lsr(opcode, curi, ssize); + break; + + case i_LSL: + gen_lsl(opcode, curi, ssize); + break; + + case i_ROL: + gen_rol(opcode, curi, ssize); + break; + + case i_ROR: + gen_ror(opcode, curi, ssize); + break; + + case i_ROXL: + gen_roxl(opcode, curi, ssize); + break; + + case i_ROXR: + gen_roxr(opcode, curi, ssize); + break; + + case i_ASRW: + gen_asrw(opcode, curi, ssize); + break; + + case i_ASLW: + gen_aslw(opcode, curi, ssize); + break; + + case i_LSRW: + gen_lsrw(opcode, curi, ssize); + break; + + case i_LSLW: + gen_lslw(opcode, curi, ssize); + break; + + case i_ROLW: + gen_rolw(opcode, curi, ssize); + break; + + case i_RORW: + gen_rorw(opcode, curi, ssize); + break; + + case i_ROXLW: + gen_roxlw(opcode, curi, ssize); + break; + + case i_ROXRW: + gen_roxrw(opcode, curi, ssize); + break; + + case i_MOVEC2: + isjump; + failure; + break; + + case i_MOVE2C: + isjump; + failure; + break; + + case i_CAS: + failure; + break; + + case i_CAS2: + failure; + break; + + case i_MOVES: + /* ignore DFC and SFC because we have no MMU */ + isjump; + failure; + break; + + case i_BKPT: + /* only needed for hardware emulators */ + isjump; + failure; + break; + + case i_CALLM: + /* not present in 68030 */ + isjump; + failure; + break; + + case i_RTM: + /* not present in 68030 */ + isjump; + failure; + break; + + case i_TRAPcc: + isjump; + failure; + break; + + case i_DIVL: + isjump; + failure; + break; + + case i_MULL: + gen_mull(opcode, curi, ssize); + break; + + case i_BFTST: + case i_BFEXTU: + case i_BFCHG: + case i_BFEXTS: + case i_BFCLR: + case i_BFFFO: + case i_BFSET: + case i_BFINS: + failure; + break; + case i_PACK: + failure; + break; + case i_UNPK: + failure; + break; + case i_TAS: + failure; + break; + case i_FPP: + uses_fpu; +#ifdef USE_JIT_FPU + mayfail; + comprintf("\tuae_u16 extra=%s;\n",gen_nextiword()); + swap_opcode(); + comprintf("\tcomp_fpp_opp(opcode,extra);\n"); +#else + failure; +#endif + break; + case i_FBcc: + uses_fpu; +#ifdef USE_JIT_FPU + isjump; + uses_cmov; + mayfail; + swap_opcode(); + comprintf("\tcomp_fbcc_opp(opcode);\n"); +#else + isjump; + failure; +#endif + break; + case i_FDBcc: + uses_fpu; + isjump; + failure; + break; + case i_FScc: + uses_fpu; +#ifdef USE_JIT_FPU + mayfail; + uses_cmov; + comprintf("\tuae_u16 extra=%s;\n",gen_nextiword()); + swap_opcode(); + comprintf("\tcomp_fscc_opp(opcode,extra);\n"); +#else + failure; +#endif + break; + case i_FTRAPcc: + uses_fpu; + isjump; + failure; + break; + case i_FSAVE: + uses_fpu; + failure; + break; + case i_FRESTORE: + uses_fpu; + failure; + break; + + case i_CINVL: + case i_CINVP: + case i_CINVA: + isjump; /* Not really, but it's probably a good idea to stop + translating at this point */ + failure; + comprintf("\tflush_icache();\n"); /* Differentiate a bit more? */ + break; + case i_CPUSHL: + case i_CPUSHP: + case i_CPUSHA: + isjump; /* Not really, but it's probably a good idea to stop + translating at this point */ + failure; + break; + + case i_MOVE16: + gen_move16(opcode, curi); + break; + + 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; + default: + assert(0); + break; + } + comprintf("%s", endstr); + finish_braces(); + sync_m68k_pc(); + if (global_mayfail) + comprintf("\tif (failure) m68k_pc_offset=m68k_pc_offset_thisinst;\n"); + return global_failure; +} + +static void generate_includes(FILE * f) { + fprintf(f, "#include \"sysdeps.h\"\n"); + fprintf(f, "#include \"m68k.h\"\n"); + fprintf(f, "#include \"memory-uae.h\"\n"); + fprintf(f, "#include \"readcpu.h\"\n"); + fprintf(f, "#include \"newcpu.h\"\n"); + fprintf(f, "#include \"comptbl.h\"\n"); + fprintf(f, "#include \"debug.h\"\n"); +} + +static int postfix; + +static char *decodeEA (amodes mode, wordsizes size) +{ + static char buffer[80]; + + buffer[0] = 0; + switch (mode){ + case Dreg: + strcpy (buffer,"Dn"); + break; + case Areg: + strcpy (buffer,"An"); + break; + case Aind: + strcpy (buffer,"(An)"); + break; + case Aipi: + strcpy (buffer,"(An)+"); + break; + case Apdi: + strcpy (buffer,"-(An)"); + break; + case Ad16: + strcpy (buffer,"(d16,An)"); + break; + case Ad8r: + strcpy (buffer,"(d8,An,Xn)"); + break; + case PC16: + strcpy (buffer,"(d16,PC)"); + break; + case PC8r: + strcpy (buffer,"(d8,PC,Xn)"); + break; + case absw: + strcpy (buffer,"(xxx).W"); + break; + case absl: + strcpy (buffer,"(xxx).L"); + break; + case imm: + switch (size){ + case sz_byte: + strcpy (buffer,"#.B"); + break; + case sz_word: + strcpy (buffer,"#.W"); + break; + case sz_long: + strcpy (buffer,"#.L"); + break; + default: + break; + } + break; + case imm0: + strcpy (buffer,"#.B"); + break; + case imm1: + strcpy (buffer,"#.W"); + break; + case imm2: + strcpy (buffer,"#.L"); + break; + case immi: + strcpy (buffer,"#"); + break; + + default: + break; + } + return buffer; +} + +static char *outopcode (const char *name, int opcode) +{ + static char out[100]; + struct instr *ins; + + ins = &table68k[opcode]; + strcpy (out, name); + if (ins->smode == immi) + strcat (out, "Q"); + if (ins->size == sz_byte) + strcat (out,".B"); + if (ins->size == sz_word) + strcat (out,".W"); + if (ins->size == sz_long) + strcat (out,".L"); + strcat (out," "); + if (ins->suse) + strcat (out, decodeEA (ins->smode, ins->size)); + if (ins->duse) { + if (ins->suse) strcat (out,","); + strcat (out, decodeEA (ins->dmode, ins->size)); + } + return out; +} + + +static void generate_one_opcode(int rp, int noflags) { + int i; + uae_u16 smsk, dmsk; + int opcode = opcode_map[rp]; + int aborted = 0; + int have_srcreg = 0; + int have_dstreg = 0; + const char *name; + + if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level) + return; + + for (i = 0; lookuptab[i].name[0]; i++) { + if (table68k[opcode].mnemo == lookuptab[i].mnemo) + break; + } + + if (table68k[opcode].handler != -1) + return; + + switch (table68k[opcode].stype) { + case 0: + smsk = 7; + break; + case 1: + smsk = 255; + break; + case 2: + smsk = 15; + break; + case 3: + smsk = 7; + break; + case 4: + smsk = 7; + break; + case 5: + smsk = 63; + break; + case 6: + smsk = 255; + break; + case 7: + smsk = 3; + break; + default: + assert(0); + break; + } + dmsk = 7; + + next_cpu_level = -1; + if (table68k[opcode].suse && table68k[opcode].smode != imm + && table68k[opcode].smode != imm0 && table68k[opcode].smode != imm1 + && table68k[opcode].smode != imm2 && table68k[opcode].smode != absw + && table68k[opcode].smode != absl && table68k[opcode].smode != PC8r + && table68k[opcode].smode != PC16) { + have_srcreg = 1; + if (table68k[opcode].spos == -1) { + if (((int) table68k[opcode].sreg) >= 128) + comprintf("\tuae_s32 srcreg = (uae_s32)(uae_s8)%d;\n", + (int) table68k[opcode].sreg); + else + comprintf("\tuae_s32 srcreg = %d;\n", + (int) table68k[opcode].sreg); + } else { + char source[100]; + int pos = table68k[opcode].spos; + + 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"); + + if (pos) + sprintf(source, "((opcode >> %d) & %d)", pos, smsk); + else + sprintf(source, "(opcode & %d)", smsk); + + if (table68k[opcode].stype == 3) + comprintf("\tuae_s32 srcreg = imm8_table[%s];\n", source); + else if (table68k[opcode].stype == 1) + comprintf("\tuae_s32 srcreg = (uae_s32)(uae_s8)%s;\n", source); + else + comprintf("\tuae_s32 srcreg = %s;\n", source); + + comprintf("#endif\n"); + } + } + if (table68k[opcode].duse + /* Yes, the dmode can be imm, in case of LINK or DBcc */ + && table68k[opcode].dmode != imm && table68k[opcode].dmode != imm0 + && table68k[opcode].dmode != imm1 && table68k[opcode].dmode != imm2 + && table68k[opcode].dmode != absw + && table68k[opcode].dmode != absl) { + have_dstreg = 1; + if (table68k[opcode].dpos == -1) { + if (((int) table68k[opcode].dreg) >= 128) + comprintf("\tuae_s32 dstreg = (uae_s32)(uae_s8)%d;\n", + (int) table68k[opcode].dreg); + else + comprintf("\tuae_s32 dstreg = %d;\n", + (int) table68k[opcode].dreg); + } else { + int pos = table68k[opcode].dpos; + + 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"); + + if (pos) + comprintf("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", pos, + dmsk); + else + comprintf("\tuae_u32 dstreg = opcode & %d;\n", dmsk); + + comprintf("#endif\n"); + } + } + + if (have_srcreg && have_dstreg + && (table68k[opcode].dmode == Areg || table68k[opcode].dmode == Aind + || table68k[opcode].dmode == Aipi + || table68k[opcode].dmode == Apdi + || table68k[opcode].dmode == Ad16 + || table68k[opcode].dmode == Ad8r) + && (table68k[opcode].smode == Areg || table68k[opcode].smode == Aind + || table68k[opcode].smode == Aipi + || table68k[opcode].smode == Apdi + || table68k[opcode].smode == Ad16 + || table68k[opcode].smode == Ad8r)) { + comprintf("\tuae_u32 dodgy=(srcreg==(uae_s32)dstreg);\n"); + } else { + comprintf("\tuae_u32 dodgy=0;\n"); + } + comprintf("\tuae_u32 m68k_pc_offset_thisinst=m68k_pc_offset;\n"); + comprintf("\tm68k_pc_offset+=2;\n"); + + aborted = gen_opcode(opcode); + { + int flags = 0; + if (global_isjump) + flags |= 1; + if (long_opcode) + flags |= 2; + if (global_cmov) + flags |= 4; + if (global_isaddx) + flags |= 8; + if (global_iscjump) + flags |= 16; + if (global_fpu) + flags |= 32; + + comprintf("}\n"); + + name = lookuptab[i].name; + if (aborted) { + fprintf(stblfile, "{ NULL, 0x%08x, %d }, /* %s */\n", opcode, flags, name); + com_discard(); + } else { + const char *tbl = noflags ? "nf" : "ff"; + fprintf(stblfile, + "{ op_%x_%d_comp_%s, %d, 0x%08x }, /* %s */\n", + opcode, postfix, tbl, opcode, flags, name); + fprintf(headerfile, "extern compop_func op_%x_%d_comp_%s;\n", + opcode, postfix, tbl); + printf ("/* %s */\n", outopcode (name, opcode)); + printf( + "void REGPARAM2 op_%x_%d_comp_%s(uae_u32 opcode) /* %s */\n{\n", + opcode, postfix, tbl, name); + com_flush(); + } + } + opcode_next_clev[rp] = next_cpu_level; + opcode_last_postfix[rp] = postfix; +} + +static void 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 = 4 - i; + postfix = i; + + 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" + "#if !defined(PART_1) && !defined(PART_2) && " + "!defined(PART_3) && !defined(PART_4) && " + "!defined(PART_5) && !defined(PART_6) && " + "!defined(PART_7) && !defined(PART_8)" + "\n" + "#define PART_1 1\n" + "#define PART_2 1\n" + "#define PART_3 1\n" + "#define PART_4 1\n" + "#define PART_5 1\n" + "#define PART_6 1\n" + "#define PART_7 1\n" + "#define PART_8 1\n" + "#endif\n\n"); + + rp = 0; + for (j = 1; j <= 8; ++j) { + int k = (j * nr_cpuop_funcs) / 8; + printf("#ifdef PART_%d\n", j); + for (; rp < k; rp++) + generate_one_opcode(rp, noflags); + printf("#endif\n\n"); + } + + fprintf(stblfile, "{ 0, 65536, 0 }};\n"); + } + +} + +#if (defined(OS_cygwin) || defined(OS_mingw)) && defined(EXTENDED_SIGSEGV) +void cygwin_mingw_abort() +{ +#undef abort + abort(); +} +#endif + +int main(void) +{ + init_table68k(); + + opcode_map = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + opcode_last_postfix = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + opcode_next_clev = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + counts = (unsigned long *) malloc(65536 * sizeof(unsigned long)); + read_counts(); + + /* It would be a lot nicer to put all in one file (we'd also get rid of + * cputbl.h that way), but cpuopti can't cope. That could be fixed, but + * I don't dare to touch the 68k version. */ + + headerfile = fopen("comptbl.h", "wb"); + fprintf (headerfile, "" + "extern const struct comptbl op_smalltbl_0_comp_nf[];\n" + "extern const struct comptbl op_smalltbl_0_comp_ff[];\n" + ""); + + stblfile = fopen("compstbl.cpp", "wb"); + if (freopen("compemu.cpp", "wb", stdout) == NULL) + { + assert(0); + } + + generate_includes(stdout); + generate_includes(stblfile); + + printf("#include \"compiler/compemu.h\"\n"); + + noflags = 0; + generate_func(noflags); + + free(opcode_map); + free(opcode_last_postfix); + free(opcode_next_clev); + free(counts); + + opcode_map = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + opcode_last_postfix = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + opcode_next_clev = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + counts = (unsigned long *) malloc(65536 * sizeof(unsigned long)); + read_counts(); + noflags = 1; + generate_func(noflags); + + free(opcode_map); + free(opcode_last_postfix); + free(opcode_next_clev); + free(counts); + + free(table68k); + fclose(stblfile); + fclose(headerfile); + return 0; +} diff --git a/od-win32/sysconfig.h b/od-win32/sysconfig.h index 2cb29723..73089e8d 100644 --- a/od-win32/sysconfig.h +++ b/od-win32/sysconfig.h @@ -12,12 +12,17 @@ #define DRIVESOUND #define GFXFILTER +#if defined(_M_ARM64) || defined(_M_ARM64EC) +#define __arm__ +#define MSVC_LONG_DOUBLE +#else #define X86_MSVC_ASSEMBLY //#define OPTIMIZED_FLAGS #define MSVC_LONG_DOUBLE #ifndef __i386__ #define __i386__ #endif +#endif #define WINDOWS #define ZLIB_WINAPI #define PACKAGE_STRING "WinUAE" diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index fc44f54f..b4394bfd 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -328,7 +328,7 @@ int target_sleep_nanos(int nanos) return 0; } -uae_u64 spincount; +uae_s64 spincount; extern bool calculated_scanline; void target_spin(int total) @@ -338,9 +338,9 @@ void target_spin(int total) if (total > 10) total = 10; while (total-- >= 0) { - uae_u64 v1 = __rdtsc(); + uae_s64 v1 = read_processor_time_rdtsc(); v1 += spincount; - while (v1 > __rdtsc()); + while (v1 > read_processor_time_rdtsc()); } } diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index ae5bbc5e..87371e87 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -369,7 +369,7 @@ static int target_get_display_scanline2(int displayindex) return -13; } -extern uae_u64 spincount; +extern uae_s64 spincount; bool calculated_scanline = true; int target_get_display_scanline(int displayindex) @@ -384,18 +384,18 @@ int target_get_display_scanline(int displayindex) sl = -1; return sl; } else { - static uae_u64 lastrdtsc; + static uae_s64 lastrdtsc; static int lastvpos; if (spincount == 0 || currprefs.m68k_speed >= 0) { lastrdtsc = 0; lastvpos = target_get_display_scanline2(displayindex); return lastvpos; } - uae_u64 v = __rdtsc(); + uae_s64 v = read_processor_time_rdtsc(); if (lastrdtsc > v) return lastvpos; lastvpos = target_get_display_scanline2(displayindex); - lastrdtsc = __rdtsc() + spincount * 4; + lastrdtsc = read_processor_time_rdtsc() + spincount * 4; return lastvpos; } } diff --git a/support/time.cpp b/support/time.cpp index 8f83584d..f825ba6e 100644 --- a/support/time.cpp +++ b/support/time.cpp @@ -27,23 +27,13 @@ static frame_time_t read_processor_time_qpf(void) return t; } -static frame_time_t read_processor_time_rdtsc(void) +uae_s64 read_processor_time_rdtsc(void) { - uae_u32 foo = 0; -#if defined(X86_MSVC_ASSEMBLY) - uae_u32 bar; - __asm - { - rdtsc - mov foo, eax - mov bar, edx - } - /* very high speed CPU's RDTSC might overflow without this.. */ - frame_time_t out; - out = ((uae_u64)foo << 32) | bar; - out >>= 6; +#ifdef __arm__ + return read_processor_time_qpf(); +#else + return __rdtsc(); #endif - return foo; } uae_time_t uae_time(void) -- 2.47.3