DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/cpu/core_dynrec/risc_armv4le-o3.h
00001 /*
00002  *  Copyright (C) 2002-2020  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 
00021 /* ARMv4/ARMv7 (little endian) backend by M-HT (arm version) */
00022 
00023 
00024 // temporary registers
00025 #define temp1 HOST_ip
00026 #define temp2 HOST_v3
00027 #define temp3 HOST_v4
00028 
00029 // register that holds function return values
00030 #define FC_RETOP HOST_a1
00031 
00032 // register used for address calculations,
00033 #define FC_ADDR HOST_v1                 // has to be saved across calls, see DRC_PROTECT_ADDR_REG
00034 
00035 // register that holds the first parameter
00036 #define FC_OP1 HOST_a1
00037 
00038 // register that holds the second parameter
00039 #define FC_OP2 HOST_a2
00040 
00041 // special register that holds the third parameter for _R3 calls (byte accessible)
00042 #define FC_OP3 HOST_v2
00043 
00044 // register that holds byte-accessible temporary values
00045 #define FC_TMP_BA1 HOST_a1
00046 
00047 // register that holds byte-accessible temporary values
00048 #define FC_TMP_BA2 HOST_a2
00049 
00050 // temporary register for LEA
00051 #define TEMP_REG_DRC HOST_v2
00052 
00053 // used to hold the address of "cpu_regs" - preferably filled in function gen_run_code
00054 #define FC_REGS_ADDR HOST_v7
00055 
00056 // used to hold the address of "Segs" - preferably filled in function gen_run_code
00057 #define FC_SEGS_ADDR HOST_v8
00058 
00059 // used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code
00060 #define readdata_addr HOST_v5
00061 
00062 
00063 // helper macro
00064 #define ROTATE_SCALE(x) ( (x)?(32 - x):(0) )
00065 
00066 
00067 // instruction encodings
00068 
00069 // move
00070 // mov dst, #(imm ror rimm)             @       0 <= imm <= 255 &       rimm mod 2 = 0
00071 #define MOV_IMM(dst, imm, rimm) (0xe3a00000 + ((dst) << 12) + (imm) + ((rimm) << 7) )
00072 // mov dst, src, lsl #imm
00073 #define MOV_REG_LSL_IMM(dst, src, imm) (0xe1a00000 + ((dst) << 12) + (src) + ((imm) << 7) )
00074 // movs dst, src, lsl #imm
00075 #define MOVS_REG_LSL_IMM(dst, src, imm) (0xe1b00000 + ((dst) << 12) + (src) + ((imm) << 7) )
00076 // mov dst, src, lsr #imm
00077 #define MOV_REG_LSR_IMM(dst, src, imm) (0xe1a00020 + ((dst) << 12) + (src) + ((imm) << 7) )
00078 // mov dst, src, asr #imm
00079 #define MOV_REG_ASR_IMM(dst, src, imm) (0xe1a00040 + ((dst) << 12) + (src) + ((imm) << 7) )
00080 // mov dst, src, lsl rreg
00081 #define MOV_REG_LSL_REG(dst, src, rreg) (0xe1a00010 + ((dst) << 12) + (src) + ((rreg) << 8) )
00082 // mov dst, src, lsr rreg
00083 #define MOV_REG_LSR_REG(dst, src, rreg) (0xe1a00030 + ((dst) << 12) + (src) + ((rreg) << 8) )
00084 // mov dst, src, asr rreg
00085 #define MOV_REG_ASR_REG(dst, src, rreg) (0xe1a00050 + ((dst) << 12) + (src) + ((rreg) << 8) )
00086 // mov dst, src, ror rreg
00087 #define MOV_REG_ROR_REG(dst, src, rreg) (0xe1a00070 + ((dst) << 12) + (src) + ((rreg) << 8) )
00088 // mvn dst, #(imm ror rimm)             @       0 <= imm <= 255 &       rimm mod 2 = 0
00089 #define MVN_IMM(dst, imm, rimm) (0xe3e00000 + ((dst) << 12) + (imm) + ((rimm) << 7) )
00090 #if C_TARGETCPU == ARMV7LE
00091 // movw dst, #imm               @       0 <= imm <= 65535
00092 #define MOVW(dst, imm) (0xe3000000 + ((dst) << 12) + (((imm) & 0xf000) << 4) + ((imm) & 0x0fff) )
00093 // movt dst, #imm               @       0 <= imm <= 65535
00094 #define MOVT(dst, imm) (0xe3400000 + ((dst) << 12) + (((imm) & 0xf000) << 4) + ((imm) & 0x0fff) )
00095 #endif
00096 
00097 // arithmetic
00098 // add dst, src, #(imm ror rimm)                @       0 <= imm <= 255 &       rimm mod 2 = 0
00099 #define ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
00100 // add dst, src1, src2, lsl #imm
00101 #define ADD_REG_LSL_IMM(dst, src1, src2, imm) (0xe0800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
00102 // sub dst, src, #(imm ror rimm)                @       0 <= imm <= 255 &       rimm mod 2 = 0
00103 #define SUB_IMM(dst, src, imm, rimm) (0xe2400000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
00104 // sub dst, src1, src2, lsl #imm
00105 #define SUB_REG_LSL_IMM(dst, src1, src2, imm) (0xe0400000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
00106 // rsb dst, src, #(imm ror rimm)                @       0 <= imm <= 255 &       rimm mod 2 = 0
00107 #define RSB_IMM(dst, src, imm, rimm) (0xe2600000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
00108 // cmp src, #(imm ror rimm)             @       0 <= imm <= 255 &       rimm mod 2 = 0
00109 #define CMP_IMM(src, imm, rimm) (0xe3500000 + ((src) << 16) + (imm) + ((rimm) << 7) )
00110 // nop
00111 #if C_TARGETCPU == ARMV7LE
00112 #define NOP (0xe320f000)
00113 #else
00114 #define NOP MOV_REG_LSL_IMM(HOST_r0, HOST_r0, 0)
00115 #endif
00116 
00117 // logical
00118 // tst src, #(imm ror rimm)             @       0 <= imm <= 255 &       rimm mod 2 = 0
00119 #define TST_IMM(src, imm, rimm) (0xe3100000 + ((src) << 16) + (imm) + ((rimm) << 7) )
00120 // and dst, src, #(imm ror rimm)                @       0 <= imm <= 255 &       rimm mod 2 = 0
00121 #define AND_IMM(dst, src, imm, rimm) (0xe2000000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
00122 // and dst, src1, src2, lsl #imm
00123 #define AND_REG_LSL_IMM(dst, src1, src2, imm) (0xe0000000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
00124 // orr dst, src, #(imm ror rimm)                @       0 <= imm <= 255 &       rimm mod 2 = 0
00125 #define ORR_IMM(dst, src, imm, rimm) (0xe3800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
00126 // orr dst, src1, src2, lsl #imm
00127 #define ORR_REG_LSL_IMM(dst, src1, src2, imm) (0xe1800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
00128 // orr dst, src1, src2, lsr #imm
00129 #define ORR_REG_LSR_IMM(dst, src1, src2, imm) (0xe1800020 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
00130 // eor dst, src1, src2, lsl #imm
00131 #define EOR_REG_LSL_IMM(dst, src1, src2, imm) (0xe0200000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
00132 // bic dst, src, #(imm ror rimm)                @       0 <= imm <= 255 &       rimm mod 2 = 0
00133 #define BIC_IMM(dst, src, imm, rimm) (0xe3c00000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
00134 // bic dst, src1, src2, lsl #imm                @       0 <= imm <= 31
00135 #define BIC_REG_LSL_IMM(dst, src1, src2, imm) (0xe1c00000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
00136 
00137 // load
00138 // ldr reg, [addr, #imm]                @       0 <= imm < 4096
00139 #define LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) )
00140 // ldr reg, [addr, #-(imm)]             @       0 <= imm < 4096
00141 #define LDR_IMM_M(reg, addr, imm) (0xe5100000 + ((reg) << 12) + ((addr) << 16) + (imm) )
00142 // ldrh reg, [addr, #imm]               @       0 <= imm < 256
00143 #define LDRH_IMM(reg, addr, imm) (0xe1d000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
00144 // ldrh reg, [addr, #-(imm)]            @       0 <= imm < 256
00145 #define LDRH_IMM_M(reg, addr, imm) (0xe15000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
00146 // ldrb reg, [addr, #imm]               @       0 <= imm < 4096
00147 #define LDRB_IMM(reg, addr, imm) (0xe5d00000 + ((reg) << 12) + ((addr) << 16) + (imm) )
00148 // ldrb reg, [addr, #-(imm)]            @       0 <= imm < 4096
00149 #define LDRB_IMM_M(reg, addr, imm) (0xe5500000 + ((reg) << 12) + ((addr) << 16) + (imm) )
00150 // ldr reg, [addr1, addr2, lsl #imm]            @       0 <= imm < 31
00151 #define LDR_REG_LSL_IMM(reg, addr1, addr2, imm) (0xe7900000 + ((reg) << 12) + ((addr1) << 16) + (addr2) + ((imm) << 7) )
00152 
00153 // store
00154 // str reg, [addr, #imm]                @       0 <= imm < 4096
00155 #define STR_IMM(reg, addr, imm) (0xe5800000 + ((reg) << 12) + ((addr) << 16) + (imm) )
00156 // str reg, [addr, #-(imm)]             @       0 <= imm < 4096
00157 #define STR_IMM_M(reg, addr, imm) (0xe5000000 + ((reg) << 12) + ((addr) << 16) + (imm) )
00158 // strh reg, [addr, #imm]               @       0 <= imm < 256
00159 #define STRH_IMM(reg, addr, imm) (0xe1c000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
00160 // strh reg, [addr, #-(imm)]            @       0 <= imm < 256
00161 #define STRH_IMM_M(reg, addr, imm) (0xe14000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
00162 // strb reg, [addr, #imm]               @       0 <= imm < 4096
00163 #define STRB_IMM(reg, addr, imm) (0xe5c00000 + ((reg) << 12) + ((addr) << 16) + (imm) )
00164 // strb reg, [addr, #-(imm)]            @       0 <= imm < 4096
00165 #define STRB_IMM_M(reg, addr, imm) (0xe5400000 + ((reg) << 12) + ((addr) << 16) + (imm) )
00166 
00167 // branch
00168 // beq pc+imm           @       0 <= imm < 32M  &       imm mod 4 = 0
00169 #define BEQ_FWD(imm) (0x0a000000 + ((imm) >> 2) )
00170 // bne pc+imm           @       0 <= imm < 32M  &       imm mod 4 = 0
00171 #define BNE_FWD(imm) (0x1a000000 + ((imm) >> 2) )
00172 // ble pc+imm           @       0 <= imm < 32M  &       imm mod 4 = 0
00173 #define BLE_FWD(imm) (0xda000000 + ((imm) >> 2) )
00174 // b pc+imm             @       0 <= imm < 32M  &       imm mod 4 = 0
00175 #define B_FWD(imm) (0xea000000 + ((imm) >> 2) )
00176 // bx reg
00177 #define BX(reg) (0xe12fff10 + (reg) )
00178 #if C_TARGETCPU == ARMV7LE
00179 // blx reg
00180 #define BLX_REG(reg) (0xe12fff30 + (reg) )
00181 
00182 // extend
00183 // sxth dst, src, ror #rimm             @       rimm = 0 | 8 | 16 | 24
00184 #define SXTH(dst, src, rimm) (0xe6bf0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) )
00185 // sxtb dst, src, ror #rimm             @       rimm = 0 | 8 | 16 | 24
00186 #define SXTB(dst, src, rimm) (0xe6af0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) )
00187 // uxth dst, src, ror #rimm             @       rimm = 0 | 8 | 16 | 24
00188 #define UXTH(dst, src, rimm) (0xe6ff0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) )
00189 // uxtb dst, src, ror #rimm             @       rimm = 0 | 8 | 16 | 24
00190 #define UXTB(dst, src, rimm) (0xe6ef0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) )
00191 
00192 // bit field
00193 // bfi dst, src, #lsb, #width           @       lsb >= 0, width >= 1, lsb+width <= 32
00194 #define BFI(dst, src, lsb, width) (0xe7c00010 + ((dst) << 12) + (src) + ((lsb) << 7) + (((lsb) + (width) - 1) << 16) )
00195 // bfc dst, #lsb, #width                @       lsb >= 0, width >= 1, lsb+width <= 32
00196 #define BFC(dst, lsb, width) (0xe7c0001f + ((dst) << 12) + ((lsb) << 7) + (((lsb) + (width) - 1) << 16) )
00197 #endif
00198 
00199 
00200 // move a full register from reg_src to reg_dst
00201 static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
00202         if(reg_src == reg_dst) return;
00203         cache_addd( MOV_REG_LSL_IMM(reg_dst, reg_src, 0) );      // mov reg_dst, reg_src
00204 }
00205 
00206 // helper function
00207 static bool val_is_operand2(Bit32u value, Bit32u *val_shift) {
00208         Bit32u shift;
00209 
00210         if (GCC_UNLIKELY(value == 0)) {
00211                 *val_shift = 0;
00212                 return true;
00213         }
00214 
00215         shift = 0;
00216         while ((value & 3) == 0) {
00217                 value>>=2;
00218                 shift+=2;
00219         }
00220 
00221         if ((value >> 8) != 0) return false;
00222 
00223         *val_shift = shift;
00224         return true;
00225 }
00226 
00227 #if C_TARGETCPU != ARMV7LE
00228 // helper function
00229 static Bits get_imm_gen_len(Bit32u imm) {
00230         Bits ret;
00231         if (imm == 0) {
00232                 return 1;
00233         } else {
00234                 ret = 0;
00235                 while (imm) {
00236                         while ((imm & 3) == 0) {
00237                                 imm>>=2;
00238                         }
00239                         ret++;
00240                         imm>>=8;
00241                 }
00242                 return ret;
00243         }
00244 }
00245 
00246 // helper function
00247 static Bits get_min_imm_gen_len(Bit32u imm) {
00248         Bits num1, num2;
00249 
00250         num1 = get_imm_gen_len(imm);
00251         num2 = get_imm_gen_len(~imm);
00252 
00253         return (num1 <= num2)?num1:num2;
00254 }
00255 #endif
00256 
00257 // move a 32bit constant value into dest_reg
00258 static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
00259 #if C_TARGETCPU == ARMV7LE
00260         Bit32u scale;
00261 
00262         if ( val_is_operand2(imm, &scale) ) {
00263                 cache_addd( MOV_IMM(dest_reg, imm >> scale, ROTATE_SCALE(scale)) );      // mov dest_reg, #imm
00264         } else if ( val_is_operand2(~imm, &scale) ) {
00265                 cache_addd( MVN_IMM(dest_reg, (~imm) >> scale, ROTATE_SCALE(scale)) );      // mvn dest_reg, #~imm
00266         } else {
00267                 cache_addd( MOVW(dest_reg, imm & 0xffff) );      // movw dest_reg, #(imm & 0xffff)
00268 
00269                 if (imm >= 0x10000)
00270                 {
00271                         cache_addd( MOVT(dest_reg, imm >> 16) );      // movt dest_reg, #(imm >> 16)
00272                 }
00273         }
00274 #else
00275         Bit32u imm2, first, scale;
00276 
00277         scale = 0;
00278         first = 1;
00279         imm2 = ~imm;
00280 
00281         if (get_imm_gen_len(imm) <= get_imm_gen_len(imm2)) {
00282                 if (imm == 0) {
00283                         cache_addd( MOV_IMM(dest_reg, 0, 0) );      // mov dest_reg, #0
00284                 } else {
00285                         while (imm) {
00286                                 while ((imm & 3) == 0) {
00287                                         imm>>=2;
00288                                         scale+=2;
00289                                 }
00290                                 if (first) {
00291                                         cache_addd( MOV_IMM(dest_reg, imm & 0xff, ROTATE_SCALE(scale)) );      // mov dest_reg, #((imm & 0xff) << scale)
00292                                         first = 0;
00293                                 } else {
00294                                         cache_addd( ORR_IMM(dest_reg, dest_reg, imm & 0xff, ROTATE_SCALE(scale)) );      // orr dest_reg, dest_reg, #((imm & 0xff) << scale)
00295                                 }
00296                                 imm>>=8;
00297                                 scale+=8;
00298                         }
00299                 }
00300         } else {
00301                 if (imm2 == 0) {
00302                         cache_addd( MVN_IMM(dest_reg, 0, 0) );      // mvn dest_reg, #0
00303                 } else {
00304                         while (imm2) {
00305                                 while ((imm2 & 3) == 0) {
00306                                         imm2>>=2;
00307                                         scale+=2;
00308                                 }
00309                                 if (first) {
00310                                         cache_addd( MVN_IMM(dest_reg, imm2 & 0xff, ROTATE_SCALE(scale)) );      // mvn dest_reg, #((imm2 & 0xff) << scale)
00311                                         first = 0;
00312                                 } else {
00313                                         cache_addd( BIC_IMM(dest_reg, dest_reg, imm2 & 0xff, ROTATE_SCALE(scale)) );      // bic dest_reg, dest_reg, #((imm2 & 0xff) << scale)
00314                                 }
00315                                 imm2>>=8;
00316                                 scale+=8;
00317                         }
00318                 }
00319         }
00320 #endif
00321 }
00322 
00323 // helper function
00324 static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
00325         switch (size) {
00326                 case 4:
00327 #if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
00328                         if ((data & 3) == 0)
00329 #endif
00330                         {
00331                                 if ((data >= addr_data) && (data < addr_data + 4096)) {
00332                                         cache_addd( LDR_IMM(dest_reg, addr_reg, data - addr_data) );      // ldr dest_reg, [addr_reg, #(data - addr_data)]
00333                                         return true;
00334                                 } else if ((data < addr_data) && (data > addr_data - 4096)) {
00335                                         cache_addd( LDR_IMM_M(dest_reg, addr_reg, addr_data - data) );      // ldr dest_reg, [addr_reg, #-(addr_data - data)]
00336                                         return true;
00337                                 }
00338                         }
00339                         break;
00340                 case 2:
00341 #if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
00342                         if ((data & 1) == 0)
00343 #endif
00344                         {
00345                                 if ((data >= addr_data) && (data < addr_data + 256)) {
00346                                         cache_addd( LDRH_IMM(dest_reg, addr_reg, data - addr_data) );      // ldrh dest_reg, [addr_reg, #(data - addr_data)]
00347                                         return true;
00348                                 } else if ((data < addr_data) && (data > addr_data - 256)) {
00349                                         cache_addd( LDRH_IMM_M(dest_reg, addr_reg, addr_data - data) );      // ldrh dest_reg, [addr_reg, #-(addr_data - data)]
00350                                         return true;
00351                                 }
00352                         }
00353                         break;
00354                 case 1:
00355                         if ((data >= addr_data) && (data < addr_data + 4096)) {
00356                                 cache_addd( LDRB_IMM(dest_reg, addr_reg, data - addr_data) );      // ldrb dest_reg, [addr_reg, #(data - addr_data)]
00357                                 return true;
00358                         } else if ((data < addr_data) && (data > addr_data - 4096)) {
00359                                 cache_addd( LDRB_IMM_M(dest_reg, addr_reg, addr_data - data) );      // ldrb dest_reg, [addr_reg, #-(addr_data - data)]
00360                                 return true;
00361                         }
00362                 default:
00363                         break;
00364         }
00365         return false;
00366 }
00367 
00368 // helper function
00369 static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) {
00370         if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
00371         if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
00372         if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
00373         return false;
00374 }
00375 
00376 // helper function for gen_mov_word_to_reg
00377 static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) {
00378         // alignment....
00379         if (dword) {
00380 #if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
00381                 if ((Bit32u)data & 3) {
00382                         if ( ((Bit32u)data & 3) == 2 ) {
00383                                 cache_addd( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
00384                                 cache_addd( LDRH_IMM(temp2, data_reg, 2) );      // ldrh temp2, [data_reg, #2]
00385                                 cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 16) );      // orr dest_reg, dest_reg, temp2, lsl #16
00386                         } else {
00387                                 cache_addd( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
00388                                 cache_addd( LDRH_IMM(temp2, data_reg, 1) );      // ldrh temp2, [data_reg, #1]
00389                                 cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) );      // orr dest_reg, dest_reg, temp2, lsl #8
00390                                 cache_addd( LDRB_IMM(temp2, data_reg, 3) );      // ldrb temp2, [data_reg, #3]
00391                                 cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 24) );      // orr dest_reg, dest_reg, temp2, lsl #24
00392                         }
00393                 } else
00394 #endif
00395                 {
00396                         cache_addd( LDR_IMM(dest_reg, data_reg, 0) );      // ldr dest_reg, [data_reg]
00397                 }
00398         } else {
00399 #if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
00400                 if ((Bit32u)data & 1) {
00401                         cache_addd( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
00402                         cache_addd( LDRB_IMM(temp2, data_reg, 1) );      // ldrb temp2, [data_reg, #1]
00403                         cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) );      // orr dest_reg, dest_reg, temp2, lsl #8
00404                 } else
00405 #endif
00406                 {
00407                         cache_addd( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
00408                 }
00409         }
00410 }
00411 
00412 // move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
00413 // 16bit moves may destroy the upper 16bit of the destination register
00414 static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
00415         if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) {
00416                 gen_mov_dword_to_reg_imm(temp1, (Bit32u)data);
00417                 gen_mov_word_to_reg_helper(dest_reg, data, dword, temp1);
00418         }
00419 }
00420 
00421 // move a 16bit constant value into dest_reg
00422 // the upper 16bit of the destination register may be destroyed
00423 static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
00424         gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm);
00425 }
00426 
00427 // helper function
00428 static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
00429         switch (size) {
00430                 case 4:
00431 #if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
00432                         if ((data & 3) == 0)
00433 #endif
00434                         {
00435                                 if ((data >= addr_data) && (data < addr_data + 4096)) {
00436                                         cache_addd( STR_IMM(src_reg, addr_reg, data - addr_data) );      // str src_reg, [addr_reg, #(data - addr_data)]
00437                                         return true;
00438                                 } else if ((data < addr_data) && (data > addr_data - 4096)) {
00439                                         cache_addd( STR_IMM_M(src_reg, addr_reg, addr_data - data) );      // str src_reg, [addr_reg, #-(addr_data - data)]
00440                                         return true;
00441                                 }
00442                         }
00443                         break;
00444                 case 2:
00445 #if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
00446                         if ((data & 1) == 0)
00447 #endif
00448                         {
00449                                 if ((data >= addr_data) && (data < addr_data + 256)) {
00450                                         cache_addd( STRH_IMM(src_reg, addr_reg, data - addr_data) );      // strh src_reg, [addr_reg, #(data - addr_data)]
00451                                         return true;
00452                                 } else if ((data < addr_data) && (data > addr_data - 256)) {
00453                                         cache_addd( STRH_IMM_M(src_reg, addr_reg, addr_data - data) );      // strh src_reg, [addr_reg, #-(addr_data - data)]
00454                                         return true;
00455                                 }
00456                         }
00457                         break;
00458                 case 1:
00459                         if ((data >= addr_data) && (data < addr_data + 4096)) {
00460                                 cache_addd( STRB_IMM(src_reg, addr_reg, data - addr_data) );      // strb src_reg, [addr_reg, #(data - addr_data)]
00461                                 return true;
00462                         } else if ((data < addr_data) && (data > addr_data - 4096)) {
00463                                 cache_addd( STRB_IMM_M(src_reg, addr_reg, addr_data - data) );      // strb src_reg, [addr_reg, #-(addr_data - data)]
00464                                 return true;
00465                         }
00466                 default:
00467                         break;
00468         }
00469         return false;
00470 }
00471 
00472 // helper function
00473 static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) {
00474         if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
00475         if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
00476         if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
00477         return false;
00478 }
00479 
00480 // helper function for gen_mov_word_from_reg
00481 static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) {
00482         // alignment....
00483         if (dword) {
00484 #if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
00485                 if ((Bit32u)dest & 3) {
00486                         if ( ((Bit32u)dest & 3) == 2 ) {
00487                                 cache_addd( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
00488                                 cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 16) );      // mov temp2, src_reg, lsr #16
00489                                 cache_addd( STRH_IMM(temp2, data_reg, 2) );      // strh temp2, [data_reg, #2]
00490                         } else {
00491                                 cache_addd( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
00492                                 cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) );      // mov temp2, src_reg, lsr #8
00493                                 cache_addd( STRH_IMM(temp2, data_reg, 1) );      // strh temp2, [data_reg, #1]
00494                                 cache_addd( MOV_REG_LSR_IMM(temp2, temp2, 16) );      // mov temp2, temp2, lsr #16
00495                                 cache_addd( STRB_IMM(temp2, data_reg, 3) );      // strb temp2, [data_reg, #3]
00496                         }
00497                 } else
00498 #endif
00499                 {
00500                         cache_addd( STR_IMM(src_reg, data_reg, 0) );      // str src_reg, [data_reg]
00501                 }
00502         } else {
00503 #if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
00504                 if ((Bit32u)dest & 1) {
00505                         cache_addd( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
00506                         cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) );      // mov temp2, src_reg, lsr #8
00507                         cache_addd( STRB_IMM(temp2, data_reg, 1) );      // strb temp2, [data_reg, #1]
00508                 } else
00509 #endif
00510                 {
00511                         cache_addd( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
00512                 }
00513         }
00514 }
00515 
00516 // move 32bit (dword==true) or 16bit (dword==false) of a register into memory
00517 static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
00518         if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) {
00519                 gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
00520                 gen_mov_word_from_reg_helper(src_reg, dest, dword, temp1);
00521         }
00522 }
00523 
00524 // move an 8bit value from memory into dest_reg
00525 // the upper 24bit of the destination register can be destroyed
00526 // this function does not use FC_OP1/FC_OP2 as dest_reg as these
00527 // registers might not be directly byte-accessible on some architectures
00528 static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
00529         if (!gen_mov_memval_to_reg(dest_reg, data, 1)) {
00530                 gen_mov_dword_to_reg_imm(temp1, (Bit32u)data);
00531                 cache_addd( LDRB_IMM(dest_reg, temp1, 0) );      // ldrb dest_reg, [temp1]
00532         }
00533 }
00534 
00535 // move an 8bit value from memory into dest_reg
00536 // the upper 24bit of the destination register can be destroyed
00537 // this function can use FC_OP1/FC_OP2 as dest_reg which are
00538 // not directly byte-accessible on some architectures
00539 static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
00540         gen_mov_byte_to_reg_low(dest_reg, data);
00541 }
00542 
00543 // move an 8bit constant value into dest_reg
00544 // the upper 24bit of the destination register can be destroyed
00545 // this function does not use FC_OP1/FC_OP2 as dest_reg as these
00546 // registers might not be directly byte-accessible on some architectures
00547 static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
00548         cache_addd( MOV_IMM(dest_reg, imm, 0) );      // mov dest_reg, #(imm)
00549 }
00550 
00551 // move an 8bit constant value into dest_reg
00552 // the upper 24bit of the destination register can be destroyed
00553 // this function can use FC_OP1/FC_OP2 as dest_reg which are
00554 // not directly byte-accessible on some architectures
00555 static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
00556         gen_mov_byte_to_reg_low_imm(dest_reg, imm);
00557 }
00558 
00559 // move the lowest 8bit of a register into memory
00560 static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
00561         if (!gen_mov_memval_from_reg(src_reg, dest, 1)) {
00562                 gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
00563                 cache_addd( STRB_IMM(src_reg, temp1, 0) );      // strb src_reg, [temp1]
00564         }
00565 }
00566 
00567 
00568 
00569 // convert an 8bit word to a 32bit dword
00570 // the register is zero-extended (sign==false) or sign-extended (sign==true)
00571 static void gen_extend_byte(bool sign,HostReg reg) {
00572         if (sign) {
00573 #if C_TARGETCPU == ARMV7LE
00574                 cache_addd( SXTB(reg, reg, 0) );      // sxtb reg, reg
00575 #else
00576                 cache_addd( MOV_REG_LSL_IMM(reg, reg, 24) );      // mov reg, reg, lsl #24
00577                 cache_addd( MOV_REG_ASR_IMM(reg, reg, 24) );      // mov reg, reg, asr #24
00578 #endif
00579         } else {
00580 #if C_TARGETCPU == ARMV7LE
00581                 cache_addd( UXTB(reg, reg, 0) );      // uxtb reg, reg
00582 #else
00583                 cache_addd( AND_IMM(reg, reg, 0xff, 0) );      // and reg, reg, #0xff
00584 #endif
00585         }
00586 }
00587 
00588 // convert a 16bit word to a 32bit dword
00589 // the register is zero-extended (sign==false) or sign-extended (sign==true)
00590 static void gen_extend_word(bool sign,HostReg reg) {
00591         if (sign) {
00592 #if C_TARGETCPU == ARMV7LE
00593                 cache_addd( SXTH(reg, reg, 0) );      // sxth reg, reg
00594 #else
00595                 cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) );      // mov reg, reg, lsl #16
00596                 cache_addd( MOV_REG_ASR_IMM(reg, reg, 16) );      // mov reg, reg, asr #16
00597 #endif
00598         } else {
00599 #if C_TARGETCPU == ARMV7LE
00600                 cache_addd( UXTH(reg, reg, 0) );      // uxth reg, reg
00601 #else
00602                 cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) );      // mov reg, reg, lsl #16
00603                 cache_addd( MOV_REG_LSR_IMM(reg, reg, 16) );      // mov reg, reg, lsr #16
00604 #endif
00605         }
00606 }
00607 
00608 // add a 32bit value from memory to a full register
00609 static void gen_add(HostReg reg,void* op) {
00610         gen_mov_word_to_reg(temp3, op, 1);
00611         cache_addd( ADD_REG_LSL_IMM(reg, reg, temp3, 0) );      // add reg, reg, temp3
00612 }
00613 
00614 // add a 32bit constant value to a full register
00615 static void gen_add_imm(HostReg reg,Bit32u imm) {
00616         Bit32u imm2, scale;
00617 
00618         if(!imm) return;
00619 
00620         imm2 = (Bit32u) (-((Bit32s)imm));
00621 
00622         if ( val_is_operand2(imm, &scale) ) {
00623                 cache_addd( ADD_IMM(reg, reg, imm >> scale, ROTATE_SCALE(scale)) );      // add reg, reg, #imm
00624         } else if ( val_is_operand2(imm2, &scale) ) {
00625                 cache_addd( SUB_IMM(reg, reg, imm2 >> scale, ROTATE_SCALE(scale)) );      // sub reg, reg, #(-imm)
00626 #if C_TARGETCPU == ARMV7LE
00627         } else if (imm2 < 0x10000) {
00628                 cache_addd( MOVW(temp2, imm2) );      // movw temp2, #(-imm)
00629                 cache_addd( SUB_REG_LSL_IMM(reg, reg, temp2, 0) );      // sub reg, reg, temp2
00630 #endif
00631         } else {
00632 #if C_TARGETCPU != ARMV7LE
00633                 if (get_min_imm_gen_len(imm) <= get_min_imm_gen_len(imm2)) {
00634 #endif
00635                         gen_mov_dword_to_reg_imm(temp2, imm);
00636                         cache_addd( ADD_REG_LSL_IMM(reg, reg, temp2, 0) );      // add reg, reg, temp2
00637 #if C_TARGETCPU != ARMV7LE
00638                 } else {
00639                         gen_mov_dword_to_reg_imm(temp2, imm2);
00640                         cache_addd( SUB_REG_LSL_IMM(reg, reg, temp2, 0) );      // sub reg, reg, temp2
00641                 }
00642 #endif
00643         }
00644 }
00645 
00646 // and a 32bit constant value with a full register
00647 static void gen_and_imm(HostReg reg,Bit32u imm) {
00648         Bit32u imm2, scale;
00649 
00650         imm2 = ~imm;
00651         if(!imm2) return;
00652 
00653         if (!imm) {
00654                 cache_addd( MOV_IMM(reg, 0, 0) );      // mov reg, #0
00655         } else if ( val_is_operand2(imm, &scale) ) {
00656                 cache_addd( AND_IMM(reg, reg, imm >> scale, ROTATE_SCALE(scale)) );      // and reg, reg, #imm
00657         } else if ( val_is_operand2(imm2, &scale) ) {
00658                 cache_addd( BIC_IMM(reg, reg, imm2 >> scale, ROTATE_SCALE(scale)) );      // bic reg, reg, #(~imm)
00659 #if C_TARGETCPU == ARMV7LE
00660         } else if (imm2 < 0x10000) {
00661                 cache_addd( MOVW(temp2, imm2) );      // movw temp2, #(~imm)
00662                 cache_addd( BIC_REG_LSL_IMM(reg, reg, temp2, 0) );      // bic reg, reg, temp2
00663 #endif
00664         } else {
00665                 gen_mov_dword_to_reg_imm(temp2, imm);
00666                 cache_addd( AND_REG_LSL_IMM(reg, reg, temp2, 0) );      // and reg, reg, temp2
00667         }
00668 }
00669 
00670 
00671 // move a 32bit constant value into memory
00672 static void gen_mov_direct_dword(void* dest,Bit32u imm) {
00673         gen_mov_dword_to_reg_imm(temp3, imm);
00674         gen_mov_word_from_reg(temp3, dest, 1);
00675 }
00676 
00677 // move an address into memory
00678 static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
00679         gen_mov_direct_dword(dest,(Bit32u)imm);
00680 }
00681 
00682 // add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
00683 static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
00684         if (!dword) imm &= 0xffff;
00685         if(!imm) return;
00686 
00687         if (!gen_mov_memval_to_reg(temp3, dest, (dword)?4:2)) {
00688                 gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
00689                 gen_mov_word_to_reg_helper(temp3, dest, dword, temp1);
00690         }
00691         gen_add_imm(temp3, imm);
00692         if (!gen_mov_memval_from_reg(temp3, dest, (dword)?4:2)) {
00693                 gen_mov_word_from_reg_helper(temp3, dest, dword, temp1);
00694         }
00695 }
00696 
00697 // add an 8bit constant value to a dword memory value
00698 static void gen_add_direct_byte(void* dest,Bit8s imm) {
00699         gen_add_direct_word(dest, (Bit32s)imm, 1);
00700 }
00701 
00702 // subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
00703 static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
00704         Bit32u imm2, scale;
00705 
00706         if (!dword) imm &= 0xffff;
00707         if(!imm) return;
00708 
00709         if (!gen_mov_memval_to_reg(temp3, dest, (dword)?4:2)) {
00710                 gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
00711                 gen_mov_word_to_reg_helper(temp3, dest, dword, temp1);
00712         }
00713 
00714         imm2 = (Bit32u) (-((Bit32s)imm));
00715 
00716         if ( val_is_operand2(imm, &scale) ) {
00717                 cache_addd( SUB_IMM(temp3, temp3, imm >> scale, ROTATE_SCALE(scale)) );      // sub temp3, temp3, #imm
00718         } else if ( val_is_operand2(imm2, &scale) ) {
00719                 cache_addd( ADD_IMM(temp3, temp3, imm2 >> scale, ROTATE_SCALE(scale)) );      // add temp3, temp3, #(-imm)
00720 #if C_TARGETCPU == ARMV7LE
00721         } else if (imm2 < 0x10000) {
00722                 cache_addd( MOVW(temp2, imm2) );      // movw temp2, #(-imm)
00723                 cache_addd( ADD_REG_LSL_IMM(temp3, temp3, temp2, 0) );      // add temp3, temp3, temp2
00724 #endif
00725         } else {
00726 #if C_TARGETCPU != ARMV7LE
00727                 if (get_min_imm_gen_len(imm) <= get_min_imm_gen_len(imm2)) {
00728 #endif
00729                         gen_mov_dword_to_reg_imm(temp2, imm);
00730                         cache_addd( SUB_REG_LSL_IMM(temp3, temp3, temp2, 0) );      // sub temp3, temp3, temp2
00731 #if C_TARGETCPU != ARMV7LE
00732                 } else {
00733                         gen_mov_dword_to_reg_imm(temp2, imm2);
00734                         cache_addd( ADD_REG_LSL_IMM(temp3, temp3, temp2, 0) );      // add temp3, temp3, temp2
00735                 }
00736 #endif
00737         }
00738 
00739         if (!gen_mov_memval_from_reg(temp3, dest, (dword)?4:2)) {
00740                 gen_mov_word_from_reg_helper(temp3, dest, dword, temp1);
00741         }
00742 }
00743 
00744 // subtract an 8bit constant value from a dword memory value
00745 static void gen_sub_direct_byte(void* dest,Bit8s imm) {
00746         gen_sub_direct_word(dest, (Bit32s)imm, 1);
00747 }
00748 
00749 // effective address calculation, destination is dest_reg
00750 // scale_reg is scaled by scale (scale_reg*(2^scale)) and
00751 // added to dest_reg, then the immediate value is added
00752 static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
00753         cache_addd( ADD_REG_LSL_IMM(dest_reg, dest_reg, scale_reg, scale) );      // add dest_reg, dest_reg, scale_reg, lsl #(scale)
00754         gen_add_imm(dest_reg, imm);
00755 }
00756 
00757 // effective address calculation, destination is dest_reg
00758 // dest_reg is scaled by scale (dest_reg*(2^scale)),
00759 // then the immediate value is added
00760 static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
00761         if (scale) {
00762                 cache_addd( MOV_REG_LSL_IMM(dest_reg, dest_reg, scale) );      // mov dest_reg, dest_reg, lsl #(scale)
00763         }
00764         gen_add_imm(dest_reg, imm);
00765 }
00766 
00767 // generate a call to a parameterless function
00768 template <typename T> static void INLINE gen_call_function_raw(const T func) {
00769 #if C_TARGETCPU == ARMV7LE
00770         cache_addd( MOVW(temp1, ((Bit32u)func) & 0xffff) );      // movw temp1, #(func & 0xffff)
00771         cache_addd( MOVT(temp1, ((Bit32u)func) >> 16) );      // movt temp1, #(func >> 16)
00772         cache_addd( BLX_REG(temp1) );      // blx temp1
00773 #else
00774         cache_addd( LDR_IMM(temp1, HOST_pc, 4) );      // ldr temp1, [pc, #4]
00775         cache_addd( ADD_IMM(HOST_lr, HOST_pc, 4, 0) );      // add lr, pc, #4
00776         cache_addd( BX(temp1) );      // bx temp1
00777         cache_addd((Bit32u)func);      // .int func
00778 #endif
00779 }
00780 
00781 // generate a call to a function with paramcount parameters
00782 // note: the parameters are loaded in the architecture specific way
00783 // using the gen_load_param_ functions below
00784 template <typename T> static Bit32u INLINE gen_call_function_setup(const T func,Bitu paramcount,bool fastcall=false) {
00785         Bit32u proc_addr = (Bit32u)cache.pos;
00786         gen_call_function_raw(func);
00787         return proc_addr;
00788 }
00789 
00790 #if (1)
00791 // max of 4 parameters in a1-a4
00792 
00793 // load an immediate value as param'th function parameter
00794 static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
00795         gen_mov_dword_to_reg_imm(param, imm);
00796 }
00797 
00798 // load an address as param'th function parameter
00799 static void INLINE gen_load_param_addr(Bitu addr,Bitu param) {
00800         gen_mov_dword_to_reg_imm(param, addr);
00801 }
00802 
00803 // load a host-register as param'th function parameter
00804 static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
00805         gen_mov_regs(param, reg);
00806 }
00807 
00808 // load a value from memory as param'th function parameter
00809 static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
00810         gen_mov_word_to_reg(param, (void *)mem, 1);
00811 }
00812 #else
00813         other arm abis
00814 #endif
00815 
00816 // jump to an address pointed at by ptr, offset is in imm
00817 static void gen_jmp_ptr(void * ptr,Bits imm=0) {
00818 //      Bit32u scale; // unused
00819 
00820         gen_mov_word_to_reg(temp3, ptr, 1);
00821 
00822 #if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
00823 // (*ptr) should be word aligned
00824         if ((imm & 0x03) == 0) {
00825 #endif
00826                 if ((imm >= 0) && (imm < 4096)) {
00827                         cache_addd( LDR_IMM(temp1, temp3, imm) );      // ldr temp1, [temp3, #imm]
00828                 } else {
00829                         gen_mov_dword_to_reg_imm(temp2, imm);
00830                         cache_addd( LDR_REG_LSL_IMM(temp1, temp3, temp2, 0) );      // ldr temp1, [temp3, temp2]
00831                 }
00832 #if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
00833         } else {
00834                 gen_add_imm(temp3, imm);
00835 
00836                 cache_addd( LDRB_IMM(temp1, temp3, 0) );      // ldrb temp1, [temp3]
00837                 cache_addd( LDRB_IMM(temp2, temp3, 1) );      // ldrb temp2, [temp3, #1]
00838                 cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 8) );      // orr temp1, temp1, temp2, lsl #8
00839                 cache_addd( LDRB_IMM(temp2, temp3, 2) );      // ldrb temp2, [temp3, #2]
00840                 cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 16) );      // orr temp1, temp1, temp2, lsl #16
00841                 cache_addd( LDRB_IMM(temp2, temp3, 3) );      // ldrb temp2, [temp3, #3]
00842                 cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 24) );      // orr temp1, temp1, temp2, lsl #24
00843         }
00844 #endif
00845 
00846         cache_addd( BX(temp1) );      // bx temp1
00847 }
00848 
00849 // short conditional jump (+-127 bytes) if register is zero
00850 // the destination is set by gen_fill_branch() later
00851 static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) {
00852         if (dword) {
00853                 cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
00854         } else {
00855                 cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) );      // movs temp1, reg, lsl #16
00856         }
00857         cache_addd( BEQ_FWD(0) );      // beq j
00858         return ((Bit32u)cache.pos-4);
00859 }
00860 
00861 // short conditional jump (+-127 bytes) if register is nonzero
00862 // the destination is set by gen_fill_branch() later
00863 static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) {
00864         if (dword) {
00865                 cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
00866         } else {
00867                 cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) );      // movs temp1, reg, lsl #16
00868         }
00869         cache_addd( BNE_FWD(0) );      // bne j
00870         return ((Bit32u)cache.pos-4);
00871 }
00872 
00873 // calculate relative offset and fill it into the location pointed to by data
00874 static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) {
00875 #if C_DEBUG
00876         Bits len=(Bit32u)cache.pos-(data+8);
00877         if (len<0) len=-len;
00878         if (len>0x02000000) LOG_MSG("Big jump %d",len);
00879 #endif
00880         *(Bit32u*)data=( (*(Bit32u*)data) & 0xff000000 ) | ( ( ((Bit32u)cache.pos - (data+8)) >> 2 ) & 0x00ffffff );
00881 }
00882 
00883 // conditional jump if register is nonzero
00884 // for isdword==true the 32bit of the register are tested
00885 // for isdword==false the lowest 8bit of the register are tested
00886 static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
00887         if (isdword) {
00888                 cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
00889         } else {
00890                 cache_addd( TST_IMM(reg, 0xff, 0) );      // tst reg, #0xff
00891         }
00892         cache_addd( BNE_FWD(0) );      // bne j
00893         return ((Bit32u)cache.pos-4);
00894 }
00895 
00896 // compare 32bit-register against zero and jump if value less/equal than zero
00897 static Bit32u gen_create_branch_long_leqzero(HostReg reg) {
00898         cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
00899         cache_addd( BLE_FWD(0) );      // ble j
00900         return ((Bit32u)cache.pos-4);
00901 }
00902 
00903 // calculate long relative offset and fill it into the location pointed to by data
00904 static void INLINE gen_fill_branch_long(Bit32u data) {
00905         *(Bit32u*)data=( (*(Bit32u*)data) & 0xff000000 ) | ( ( ((Bit32u)cache.pos - (data+8)) >> 2 ) & 0x00ffffff );
00906 }
00907 
00908 static void gen_run_code(void) {
00909 #if C_TARGETCPU == ARMV7LE
00910         cache_addd(0xe92d4df0);                 // stmfd sp!, {v1-v5,v7,v8,lr}
00911 
00912         cache_addd( MOVW(FC_SEGS_ADDR, ((Bit32u)&Segs) & 0xffff) );      // movw FC_SEGS_ADDR, #(&Segs & 0xffff)
00913         cache_addd( MOVT(FC_SEGS_ADDR, ((Bit32u)&Segs) >> 16) );      // movt FC_SEGS_ADDR, #(&Segs >> 16)
00914 
00915         cache_addd( MOVW(FC_REGS_ADDR, ((Bit32u)&cpu_regs) & 0xffff) );      // movw FC_REGS_ADDR, #(&cpu_regs & 0xffff)
00916         cache_addd( MOVT(FC_REGS_ADDR, ((Bit32u)&cpu_regs) >> 16) );      // movt FC_REGS_ADDR, #(&cpu_regs >> 16)
00917 
00918         cache_addd( MOVW(readdata_addr, ((Bitu)&core_dynrec.readdata) & 0xffff) );      // movw readdata_addr, #(&core_dynrec.readdata & 0xffff)
00919         cache_addd( MOVT(readdata_addr, ((Bitu)&core_dynrec.readdata) >> 16) );      // movt readdata_addr, #(&core_dynrec.readdata >> 16)
00920 
00921         cache_addd( BX(HOST_r0) );                      // bx r0
00922 #else
00923         Bit8u *pos1, *pos2, *pos3;
00924 
00925         cache_addd(0xe92d4df0);                 // stmfd sp!, {v1-v5,v7,v8,lr}
00926 
00927         pos1 = cache.pos;
00928         cache_addd( 0 );
00929         pos2 = cache.pos;
00930         cache_addd( 0 );
00931         pos3 = cache.pos;
00932         cache_addd( 0 );
00933 
00934         cache_addd( BX(HOST_r0) );                      // bx r0
00935 
00936         // align cache.pos to 32 bytes
00937         if ((((Bitu)cache.pos) & 0x1f) != 0) {
00938                 cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
00939         }
00940 
00941         *(Bit32u*)pos1 = LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8));      // ldr FC_SEGS_ADDR, [pc, #(&Segs)]
00942         cache_addd((Bit32u)&Segs);      // address of "Segs"
00943 
00944         *(Bit32u*)pos2 = LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8));      // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)]
00945         cache_addd((Bit32u)&cpu_regs);  // address of "cpu_regs"
00946 
00947         *(Bit32u*)pos3 = LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8));      // ldr readdata_addr, [pc, #(&core_dynrec.readdata)]
00948         cache_addd((Bit32u)&core_dynrec.readdata);  // address of "core_dynrec.readdata"
00949 
00950         // align cache.pos to 32 bytes
00951         if ((((Bitu)cache.pos) & 0x1f) != 0) {
00952                 cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
00953         }
00954 #endif
00955 }
00956 
00957 // return from a function
00958 static void gen_return_function(void) {
00959         cache_addd(0xe8bd8df0);                 // ldmfd sp!, {v1-v5,v7,v8,pc}
00960 }
00961 
00962 #ifdef DRC_FLAGS_INVALIDATION
00963 
00964 // called when a call to a function can be replaced by a
00965 // call to a simpler function
00966 static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
00967 #ifdef DRC_FLAGS_INVALIDATION_DCODE
00968         // try to avoid function calls but rather directly fill in code
00969         switch (flags_type) {
00970                 case t_ADDb:
00971                 case t_ADDw:
00972                 case t_ADDd:
00973                         *(Bit32u*)pos=NOP;                                      // nop
00974                         *(Bit32u*)(pos+4)=NOP;                          // nop
00975                         *(Bit32u*)(pos+8)=ADD_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);       // add FC_RETOP, a1, a2
00976 #if C_TARGETCPU != ARMV7LE
00977                         *(Bit32u*)(pos+12)=NOP;                         // nop
00978 #endif
00979                         break;
00980                 case t_ORb:
00981                 case t_ORw:
00982                 case t_ORd:
00983                         *(Bit32u*)pos=NOP;                                      // nop
00984                         *(Bit32u*)(pos+4)=NOP;                          // nop
00985                         *(Bit32u*)(pos+8)=ORR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);       // orr FC_RETOP, a1, a2
00986 #if C_TARGETCPU != ARMV7LE
00987                         *(Bit32u*)(pos+12)=NOP;                         // nop
00988 #endif
00989                         break;
00990                 case t_ANDb:
00991                 case t_ANDw:
00992                 case t_ANDd:
00993                         *(Bit32u*)pos=NOP;                                      // nop
00994                         *(Bit32u*)(pos+4)=NOP;                          // nop
00995                         *(Bit32u*)(pos+8)=AND_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);       // and FC_RETOP, a1, a2
00996 #if C_TARGETCPU != ARMV7LE
00997                         *(Bit32u*)(pos+12)=NOP;                         // nop
00998 #endif
00999                         break;
01000                 case t_SUBb:
01001                 case t_SUBw:
01002                 case t_SUBd:
01003                         *(Bit32u*)pos=NOP;                                      // nop
01004                         *(Bit32u*)(pos+4)=NOP;                          // nop
01005                         *(Bit32u*)(pos+8)=SUB_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);       // sub FC_RETOP, a1, a2
01006 #if C_TARGETCPU != ARMV7LE
01007                         *(Bit32u*)(pos+12)=NOP;                         // nop
01008 #endif
01009                         break;
01010                 case t_XORb:
01011                 case t_XORw:
01012                 case t_XORd:
01013                         *(Bit32u*)pos=NOP;                                      // nop
01014                         *(Bit32u*)(pos+4)=NOP;                          // nop
01015                         *(Bit32u*)(pos+8)=EOR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);       // eor FC_RETOP, a1, a2
01016 #if C_TARGETCPU != ARMV7LE
01017                         *(Bit32u*)(pos+12)=NOP;                         // nop
01018 #endif
01019                         break;
01020                 case t_CMPb:
01021                 case t_CMPw:
01022                 case t_CMPd:
01023                 case t_TESTb:
01024                 case t_TESTw:
01025                 case t_TESTd:
01026                         *(Bit32u*)pos=NOP;                                      // nop
01027                         *(Bit32u*)(pos+4)=NOP;                          // nop
01028                         *(Bit32u*)(pos+8)=NOP;                          // nop
01029 #if C_TARGETCPU != ARMV7LE
01030                         *(Bit32u*)(pos+12)=NOP;                         // nop
01031 #endif
01032                         break;
01033                 case t_INCb:
01034                 case t_INCw:
01035                 case t_INCd:
01036                         *(Bit32u*)pos=NOP;                                      // nop
01037                         *(Bit32u*)(pos+4)=NOP;                          // nop
01038                         *(Bit32u*)(pos+8)=ADD_IMM(FC_RETOP, HOST_a1, 1, 0);     // add FC_RETOP, a1, #1
01039 #if C_TARGETCPU != ARMV7LE
01040                         *(Bit32u*)(pos+12)=NOP;                         // nop
01041 #endif
01042                         break;
01043                 case t_DECb:
01044                 case t_DECw:
01045                 case t_DECd:
01046                         *(Bit32u*)pos=NOP;                                      // nop
01047                         *(Bit32u*)(pos+4)=NOP;                          // nop
01048                         *(Bit32u*)(pos+8)=SUB_IMM(FC_RETOP, HOST_a1, 1, 0);     // sub FC_RETOP, a1, #1
01049 #if C_TARGETCPU != ARMV7LE
01050                         *(Bit32u*)(pos+12)=NOP;                         // nop
01051 #endif
01052                         break;
01053                 case t_SHLb:
01054                 case t_SHLw:
01055                 case t_SHLd:
01056                         *(Bit32u*)pos=NOP;                                      // nop
01057                         *(Bit32u*)(pos+4)=NOP;                          // nop
01058                         *(Bit32u*)(pos+8)=MOV_REG_LSL_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, lsl a2
01059 #if C_TARGETCPU != ARMV7LE
01060                         *(Bit32u*)(pos+12)=NOP;                         // nop
01061 #endif
01062                         break;
01063                 case t_SHRb:
01064                         *(Bit32u*)pos=NOP;                                      // nop
01065 #if C_TARGETCPU == ARMV7LE
01066                         *(Bit32u*)(pos+4)=BFC(HOST_a1, 8, 24);  // bfc a1, 8, 24
01067                         *(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, lsr a2
01068 #else
01069                         *(Bit32u*)(pos+4)=NOP;                          // nop
01070                         *(Bit32u*)(pos+8)=AND_IMM(FC_RETOP, HOST_a1, 0xff, 0);                          // and FC_RETOP, a1, #0xff
01071                         *(Bit32u*)(pos+12)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2);        // mov FC_RETOP, FC_RETOP, lsr a2
01072 #endif
01073                         break;
01074                 case t_SHRw:
01075                         *(Bit32u*)pos=NOP;                                      // nop
01076 #if C_TARGETCPU == ARMV7LE
01077                         *(Bit32u*)(pos+4)=BFC(HOST_a1, 16, 16); // bfc a1, 16, 16
01078                         *(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, lsr a2
01079 #else
01080                         *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                       // mov FC_RETOP, a1, lsl #16
01081                         *(Bit32u*)(pos+8)=MOV_REG_LSR_IMM(FC_RETOP, FC_RETOP, 16);                      // mov FC_RETOP, FC_RETOP, lsr #16
01082                         *(Bit32u*)(pos+12)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2);        // mov FC_RETOP, FC_RETOP, lsr a2
01083 #endif
01084                         break;
01085                 case t_SHRd:
01086                         *(Bit32u*)pos=NOP;                                      // nop
01087                         *(Bit32u*)(pos+4)=NOP;                          // nop
01088                         *(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, lsr a2
01089 #if C_TARGETCPU != ARMV7LE
01090                         *(Bit32u*)(pos+12)=NOP;                         // nop
01091 #endif
01092                         break;
01093                 case t_SARb:
01094                         *(Bit32u*)pos=NOP;                                      // nop
01095 #if C_TARGETCPU == ARMV7LE
01096                         *(Bit32u*)(pos+4)=SXTB(FC_RETOP, HOST_a1, 0);                                   // sxtb FC_RETOP, a1
01097                         *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2
01098 #else
01099                         *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24);                       // mov FC_RETOP, a1, lsl #24
01100                         *(Bit32u*)(pos+8)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 24);                      // mov FC_RETOP, FC_RETOP, asr #24
01101                         *(Bit32u*)(pos+12)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2);        // mov FC_RETOP, FC_RETOP, asr a2
01102 #endif
01103                         break;
01104                 case t_SARw:
01105                         *(Bit32u*)pos=NOP;                                      // nop
01106 #if C_TARGETCPU == ARMV7LE
01107                         *(Bit32u*)(pos+4)=SXTH(FC_RETOP, HOST_a1, 0);                                   // sxth FC_RETOP, a1
01108                         *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2
01109 #else
01110                         *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                       // mov FC_RETOP, a1, lsl #16
01111                         *(Bit32u*)(pos+8)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 16);                      // mov FC_RETOP, FC_RETOP, asr #16
01112                         *(Bit32u*)(pos+12)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2);        // mov FC_RETOP, FC_RETOP, asr a2
01113 #endif
01114                         break;
01115                 case t_SARd:
01116                         *(Bit32u*)pos=NOP;                                      // nop
01117                         *(Bit32u*)(pos+4)=NOP;                          // nop
01118                         *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, asr a2
01119 #if C_TARGETCPU != ARMV7LE
01120                         *(Bit32u*)(pos+12)=NOP;                         // nop
01121 #endif
01122                         break;
01123                 case t_RORb:
01124 #if C_TARGETCPU == ARMV7LE
01125                         *(Bit32u*)pos=BFI(HOST_a1, HOST_a1, 8, 8);                                              // bfi a1, a1, 8, 8
01126                         *(Bit32u*)(pos+4)=BFI(HOST_a1, HOST_a1, 16, 16);                                // bfi a1, a1, 16, 16
01127                         *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, ror a2
01128 #else
01129                         *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24);                                   // mov FC_RETOP, a1, lsl #24
01130                         *(Bit32u*)(pos+4)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 8);             // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #8
01131                         *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16);    // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
01132                         *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2);                // mov FC_RETOP, FC_RETOP, ror a2
01133 #endif
01134                         break;
01135                 case t_RORw:
01136                         *(Bit32u*)pos=NOP;                                      // nop
01137 #if C_TARGETCPU == ARMV7LE
01138                         *(Bit32u*)(pos+4)=BFI(HOST_a1, HOST_a1, 16, 16);                                // bfi a1, a1, 16, 16
01139                         *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, ror a2
01140 #else
01141                         *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                               // mov FC_RETOP, a1, lsl #16
01142                         *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16);    // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
01143                         *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2);                // mov FC_RETOP, FC_RETOP, ror a2
01144 #endif
01145                         break;
01146                 case t_RORd:
01147                         *(Bit32u*)pos=NOP;                                      // nop
01148                         *(Bit32u*)(pos+4)=NOP;                          // nop
01149                         *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, ror a2
01150 #if C_TARGETCPU != ARMV7LE
01151                         *(Bit32u*)(pos+12)=NOP;                         // nop
01152 #endif
01153                         break;
01154                 case t_ROLw:
01155 #if C_TARGETCPU == ARMV7LE
01156                         *(Bit32u*)pos=BFI(HOST_a1, HOST_a1, 16, 16);                                    // bfi a1, a1, 16, 16
01157                         *(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0);                             // rsb a2, a2, #32
01158                         *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, ror a2
01159 #else
01160                         *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                                   // mov FC_RETOP, a1, lsl #16
01161                         *(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0);                                             // rsb a2, a2, #32
01162                         *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16);    // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
01163                         *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2);                // mov FC_RETOP, FC_RETOP, ror a2
01164 #endif
01165                         break;
01166                 case t_ROLd:
01167                         *(Bit32u*)pos=NOP;                                      // nop
01168 #if C_TARGETCPU == ARMV7LE
01169                         *(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0);                             // rsb a2, a2, #32
01170                         *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, ror a2
01171 #else
01172                         *(Bit32u*)(pos+4)=NOP;                          // nop
01173                         *(Bit32u*)(pos+8)=RSB_IMM(HOST_a2, HOST_a2, 32, 0);                             // rsb a2, a2, #32
01174                         *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2
01175 #endif
01176                         break;
01177                 case t_NEGb:
01178                 case t_NEGw:
01179                 case t_NEGd:
01180                         *(Bit32u*)pos=NOP;                                      // nop
01181                         *(Bit32u*)(pos+4)=NOP;                          // nop
01182                         *(Bit32u*)(pos+8)=RSB_IMM(FC_RETOP, HOST_a1, 0, 0);     // rsb FC_RETOP, a1, #0
01183 #if C_TARGETCPU != ARMV7LE
01184                         *(Bit32u*)(pos+12)=NOP;                         // nop
01185 #endif
01186                         break;
01187                 default:
01188 #if C_TARGETCPU == ARMV7LE
01189                         *(Bit32u*)pos=MOVW(temp1, ((Bit32u)fct_ptr) & 0xffff);      // movw temp1, #(fct_ptr & 0xffff)
01190                         *(Bit32u*)(pos+4)=MOVT(temp1, ((Bit32u)fct_ptr) >> 16);      // movt temp1, #(fct_ptr >> 16)
01191 #else
01192                         *(Bit32u*)(pos+12)=(Bit32u)fct_ptr;             // simple_func
01193 #endif
01194                         break;
01195 
01196         }
01197 #else
01198 #if C_TARGETCPU == ARMV7LE
01199         *(Bit32u*)pos=MOVW(temp1, ((Bit32u)fct_ptr) & 0xffff);      // movw temp1, #(fct_ptr & 0xffff)
01200         *(Bit32u*)(pos+4)=MOVT(temp1, ((Bit32u)fct_ptr) >> 16);      // movt temp1, #(fct_ptr >> 16)
01201 #else
01202         *(Bit32u*)(pos+12)=(Bit32u)fct_ptr;             // simple_func
01203 #endif
01204 #endif
01205 }
01206 #endif
01207 
01208 static void cache_block_before_close(void) { }
01209 
01210 #ifdef DRC_USE_SEGS_ADDR
01211 
01212 // mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero)
01213 // 16bit moves may destroy the upper 16bit of the destination register
01214 static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) {
01215         cache_addd( LDRH_IMM(dest_reg, FC_SEGS_ADDR, index) );      // ldrh dest_reg, [FC_SEGS_ADDR, #index]
01216 }
01217 
01218 // mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero)
01219 static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) {
01220         cache_addd( LDR_IMM(dest_reg, FC_SEGS_ADDR, index) );      // ldr dest_reg, [FC_SEGS_ADDR, #index]
01221 }
01222 
01223 // add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero)
01224 static void gen_add_seg32_to_reg(HostReg reg,Bitu index) {
01225         cache_addd( LDR_IMM(temp1, FC_SEGS_ADDR, index) );      // ldr temp1, [FC_SEGS_ADDR, #index]
01226         cache_addd( ADD_REG_LSL_IMM(reg, reg, temp1, 0) );      // add reg, reg, temp1
01227 }
01228 
01229 #endif
01230 
01231 #ifdef DRC_USE_REGS_ADDR
01232 
01233 // mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero)
01234 // 16bit moves may destroy the upper 16bit of the destination register
01235 static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) {
01236         cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrh dest_reg, [FC_REGS_ADDR, #index]
01237 }
01238 
01239 // mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero)
01240 static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) {
01241         cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldr dest_reg, [FC_REGS_ADDR, #index]
01242 }
01243 
01244 // move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
01245 // 16bit moves may destroy the upper 16bit of the destination register
01246 static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) {
01247         if (dword) {
01248                 cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldr dest_reg, [FC_REGS_ADDR, #index]
01249         } else {
01250                 cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrh dest_reg, [FC_REGS_ADDR, #index]
01251         }
01252 }
01253 
01254 // move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
01255 // the upper 24bit of the destination register can be destroyed
01256 // this function does not use FC_OP1/FC_OP2 as dest_reg as these
01257 // registers might not be directly byte-accessible on some architectures
01258 static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) {
01259         cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrb dest_reg, [FC_REGS_ADDR, #index]
01260 }
01261 
01262 // move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
01263 // the upper 24bit of the destination register can be destroyed
01264 // this function can use FC_OP1/FC_OP2 as dest_reg which are
01265 // not directly byte-accessible on some architectures
01266 static void gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) {
01267         cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrb dest_reg, [FC_REGS_ADDR, #index]
01268 }
01269 
01270 
01271 // add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero)
01272 static void gen_add_regval32_to_reg(HostReg reg,Bitu index) {
01273         cache_addd( LDR_IMM(temp2, FC_REGS_ADDR, index) );      // ldr temp2, [FC_REGS_ADDR, #index]
01274         cache_addd( ADD_REG_LSL_IMM(reg, reg, temp2, 0) );      // add reg, reg, temp2
01275 }
01276 
01277 
01278 // move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero)
01279 static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) {
01280         cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) );      // strh src_reg, [FC_REGS_ADDR, #index]
01281 }
01282 
01283 // move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero)
01284 static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) {
01285         cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) );      // str src_reg, [FC_REGS_ADDR, #index]
01286 }
01287 
01288 // move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
01289 static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) {
01290         if (dword) {
01291                 cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) );      // str src_reg, [FC_REGS_ADDR, #index]
01292         } else {
01293                 cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) );      // strh src_reg, [FC_REGS_ADDR, #index]
01294         }
01295 }
01296 
01297 // move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR
01298 static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) {
01299         cache_addd( STRB_IMM(src_reg, FC_REGS_ADDR, index) );      // strb src_reg, [FC_REGS_ADDR, #index]
01300 }
01301 
01302 #endif