mirror of
https://github.com/libretro/hatari.git
synced 2026-11-07 10:36:00 -10:00
Port Amiberry ARM64 and x86-64 JIT fixes (not used in Hatari) (from WinUAE 6.1.0 beta6+ 2026/05/19)
This commit is contained in:
1 parent
f0ebac5296
commit
80729679a8
34 files changed
+208837
-222
No files matched your search
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,493 @@
|
||||
/*
|
||||
* compiler/codegen_armA64.h - AARCH64 code generator
|
||||
*
|
||||
* Copyright (c) 2019 TomB
|
||||
*
|
||||
* This file is part of the UAE4ARM project.
|
||||
*
|
||||
* JIT compiler m68k -> ARMv8.1
|
||||
*
|
||||
* Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer
|
||||
* This file is derived from CCG, copyright 1999-2003 Ian Piumarta
|
||||
*
|
||||
* 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_ASMA64_H
|
||||
#define ARM_ASMA64_H
|
||||
|
||||
|
||||
/* CPSR flags */
|
||||
|
||||
#define ARM_N_FLAG 0x80000000
|
||||
#define ARM_Z_FLAG 0x40000000
|
||||
#define ARM_C_FLAG 0x20000000
|
||||
#define ARM_V_FLAG 0x10000000
|
||||
#define ARM_CV_FLAGS (ARM_C_FLAG|ARM_V_FLAG)
|
||||
|
||||
|
||||
#define _W(c) emit_long(c)
|
||||
|
||||
|
||||
#define MIN_EL0 0b011
|
||||
|
||||
#define EX_UXTB 0b000
|
||||
#define EX_UXTH 0b001
|
||||
#define EX_UXTW 0b010
|
||||
#define EX_UXTX 0b011
|
||||
#define EX_SXTB 0b100
|
||||
#define EX_SXTH 0b101
|
||||
#define EX_SXTW 0b110
|
||||
#define EX_SXTX 0b111
|
||||
|
||||
#define immEncode(N,immr,imms) (N << 22) | (immr << 16) | (imms << 10)
|
||||
|
||||
|
||||
/* read/write flags */
|
||||
// move from sysreg
|
||||
#define MRS_NZCV_x(Xt) _W((0b1101010100111 << 19) | (MIN_EL0 << 16) | (0b0100 << 12) | (0b0010 << 8) | (0b000 << 5) | (Xt))
|
||||
#define MRS_FPCR_x(Xt) _W((0b1101010100111 << 19) | (MIN_EL0 << 16) | (0b0100 << 12) | (0b0100 << 8) | (0b000 << 5) | (Xt))
|
||||
// move to sysreg
|
||||
#define MSR_NZCV_x(Xt) _W((0b1101010100011 << 19) | (MIN_EL0 << 16) | (0b0100 << 12) | (0b0010 << 8) | (0b000 << 5) | (Xt))
|
||||
#define MSR_FPCR_x(Xt) _W((0b1101010100011 << 19) | (MIN_EL0 << 16) | (0b0100 << 12) | (0b0100 << 8) | (0b000 << 5) | (Xt))
|
||||
|
||||
|
||||
/*----------------------------------------
|
||||
* branch instructions
|
||||
*----------------------------------------*/
|
||||
// i is the number of instructions, i.e. 4 bytes
|
||||
#define B_i(i) _W((0b000101 << 26) | ((i) & 0x03ffffff))
|
||||
#define BL_i(i) _W((0b100101 << 26) | ((i) & 0x03ffffff))
|
||||
#define BLR_x(Xn) _W((0b11010110001 << 21) | (0b11111 << 16) | (0 << 10) | ((Xn) << 5) | 0)
|
||||
#define BR_x(Xn) _W((0b11010110000 << 21) | (0b11111 << 16) | (0 << 10) | ((Xn) << 5) | 0)
|
||||
|
||||
#define CC_B_i(cc,i) _W((0b01010100 << 24) | (((i) & 0x0007ffff) << 5) | (cc))
|
||||
#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 RET _W((0b11010110010 << 21) | (0b11111 << 16) | (0 << 10) | ((30) << 5) | (0))
|
||||
|
||||
/* compare and branch */
|
||||
// these instructions do not affect condition flags
|
||||
#define CBNZ_wi(Wt,i) _W((0b00110101 << 24) | (((i) & 0x0007ffff) << 5) | (Wt))
|
||||
#define CBNZ_xi(Xt,i) _W((0b10110101 << 24) | (((i) & 0x0007ffff) << 5) | (Xt))
|
||||
#define CBZ_wi(Wt,i) _W((0b00110100 << 24) | (((i) & 0x0007ffff) << 5) | (Wt))
|
||||
#define CBZ_xi(Xt,i) _W((0b10110100 << 24) | (((i) & 0x0007ffff) << 5) | (Xt))
|
||||
|
||||
/* test bit and branch */
|
||||
// these instructions do not affect condition flags
|
||||
#define TBNZ_xii(Xt,bit,i) _W(((((bit) & 0x20) >> 5) << 31) | (0b0110111 << 24) | (((bit) & 0x1f) << 19) | ((((i)) % 0x3fff) << 5) | (Xt))
|
||||
#define TBNZ_wii(Wt,bit,i) _W((0 << 31) | (0b0110111 << 24) | (((bit) & 0x1f) << 19) | ((((i)) % 0x3fff) << 5) | (Wt))
|
||||
#define TBZ_xii(Xt,bit,i) _W(((((bit) & 0x20) >> 5) << 31) | (0b0110110 << 24) | (((bit) & 0x1f) << 19) | ((((i)) % 0x3fff) << 5) | (Xt))
|
||||
#define TBZ_wii(Wt,bit,i) _W((0 << 31) | (0b0110110 << 24) | (((bit) & 0x1f) << 19) | ((((i)) % 0x3fff) << 5) | (Wt))
|
||||
|
||||
|
||||
/*----------------------------------------
|
||||
* load/store registers
|
||||
*---------------------------------------- */
|
||||
// i is number of bytes
|
||||
#define LDP_wwXi(Wt1,Wt2,Xn,i) _W((0b0010100101 << 22) | ((((i)/4) & 0x7f) << 15) | ((Wt2) << 10) | ((Xn) << 5) | (Wt1))
|
||||
#define LDP_xxXi(Xt1,Xt2,Xn,i) _W((0b1010100101 << 22) | ((((i)/8) & 0x7f) << 15) | ((Xt2) << 10) | ((Xn) << 5) | (Xt1))
|
||||
#define LDP_xxXpost(Xt1,Xt2,Xn,i) _W((0b1010100011 << 22) | ((((i)/8) & 0x7f) << 15) | ((Xt2) << 10) | ((Xn) << 5) | (Xt1))
|
||||
#define LDR_wXi(Wt,Xn,i) _W((0b1011100101 << 22) | ((((i)/4) & 0xfff) << 10) | ((Xn) << 5) | (Wt))
|
||||
#define LDR_xXi(Xt,Xn,i) _W((0b1111100101 << 22) | ((((i)/8) & 0xfff) << 10) | ((Xn) << 5) | (Xt))
|
||||
#define LDR_xXpost(Xt,Xn,i) _W((0b11111000010 << 21) | (((i) & 0x1ff) << 12) | (0b01 << 10) | ((Xn) << 5) | (Xt))
|
||||
#define LDR_wPCi(Wt,i) _W((0b00011000 << 24) | ((((i)/4) & 0x7ffff) << 5) | (Wt))
|
||||
#define LDR_xPCi(Xt,i) _W((0b01011000 << 24) | ((((i)/4) & 0x7ffff) << 5) | (Xt))
|
||||
/* JIT direct memory helpers pass (addr_reg, R_MEMSTART).
|
||||
* Use UXTW to zero-extend 32-bit M68k addresses to 64-bit host offsets.
|
||||
* SXTW was used historically when natmem lived at 0x80000000, but sign-extending
|
||||
* addresses with bit 31 set wraps BELOW natmem on platforms where natmem > 2GB
|
||||
* (e.g., macOS ARM64 at 0x300000000), causing SIGBUS. */
|
||||
#define LDR_wXx(Wt,Xn,Xm) _W((0b10111000011 << 21) | ((Xn) << 16) | (EX_UXTW << 13) | (0 << 12) | (0b10 << 10) | ((Xm) << 5) | (Wt))
|
||||
#define LDR_xXx(Xt,Xn,Xm) _W((0b11111000011 << 21) | ((Xm) << 16) | (0b011 << 13) | (0 << 12) | (0b10 << 10) | ((Xn) << 5) | (Xt))
|
||||
// i=0 no shift, i=1 LSL 2 (W) or LSL 3 (X)
|
||||
#define LDR_wXxLSLi(Wt,Xn,Xm,i) _W((0b10111000011 << 21) | ((Xm) << 16) | (0b011 << 13) | (((i)&1) << 12) | (0b10 << 10) | ((Xn) << 5) | (Wt))
|
||||
#define LDR_xXxLSLi(Xt,Xn,Xm,i) _W((0b11111000011 << 21) | ((Xm) << 16) | (0b011 << 13) | (((i)&1) << 12) | (0b10 << 10) | ((Xn) << 5) | (Xt))
|
||||
#define LDRB_wXi(Wt,Xn,i) _W((0b0011100101 << 22) | (((i) & 0xfff) << 10) | ((Xn) << 5) | (Wt))
|
||||
#define LDRB_wXx(Wt,Xn,Xm) _W((0b00111000011 << 21) | ((Xn) << 16) | (EX_UXTW << 13) | (0 << 12) | (0b10 << 10) | ((Xm) << 5) | (Wt))
|
||||
#define LDRH_wXi(Wt,Xn,i) _W((0b0111100101 << 22) | ((((i)/2) &0xfff) << 10) | ((Xn) << 5) | (Wt))
|
||||
#define LDRH_wXx(Wt,Xn,Xm) _W((0b01111000011 << 21) | ((Xn) << 16) | (EX_UXTW << 13) | (0 << 12) | (0b10 << 10) | ((Xm) << 5) | (Wt))
|
||||
|
||||
#define STP_wwXi(Wt1,Wt2,Xn,i) _W((0b0010100100 << 22) | ((((i)/4) & 0x7f) << 15) | ((Wt2) << 10) | ((Xn) << 5) | (Wt1))
|
||||
#define STP_xxXi(Xt1,Xt2,Xn,i) _W((0b1010100100 << 22) | ((((i)/8) & 0x7f) << 15) | ((Xt2) << 10) | ((Xn) << 5) | (Xt1))
|
||||
#define STP_xxXpre(Xt1,Xt2,Xn,i) _W((0b1010100110 << 22) | ((((i)/8) & 0x7f) << 15) | ((Xt2) << 10) | ((Xn) << 5) | (Xt1))
|
||||
#define STR_wXi(Wt,Xn,i) _W((0b1011100100 << 22) | ((((i)/4) & 0xfff) << 10) | ((Xn) << 5) | (Wt))
|
||||
#define STR_xXi(Xt,Xn,i) _W((0b1111100100 << 22) | ((((i)/8) & 0xfff) << 10) | ((Xn) << 5) | (Xt))
|
||||
#define STR_xXpre(Xt,Xn,i) _W((0b11111000000 << 21) | (((i) & 0x1ff) << 12) | (0b11 << 10) | ((Xn) << 5) | (Xt))
|
||||
#define STR_wXx(Wt,Xn,Xm) _W((0b10111000001 << 21) | ((Xn) << 16) | (EX_UXTW << 13) | (0 << 12) | (0b10 << 10) | ((Xm) << 5) | (Wt))
|
||||
#define STR_xXx(Xt,Xn,Xm) _W((0b11111000001 << 21) | ((Xm) << 16) | (0b011 << 13) | (0 << 12) | (0b10 << 10) | ((Xn) << 5) | (Xt))
|
||||
// i=0 no shift, i=1 LSL 2 (W) or LSL 3 (X)
|
||||
#define STR_wXxLSLi(Wt,Xn,Xm,i) _W((0b10111000001 << 21) | ((Xm) << 16) | (0b011 << 13) | (((i)&1) << 12) | (0b10 << 10) | ((Xn) << 5) | (Wt))
|
||||
#define STRB_wXi(Wt,Xn,i) _W((0b0011100100 << 22) | (((i) & 0xfff) << 10) | ((Xn) << 5) | (Wt))
|
||||
#define STRB_wXx(Wt,Xn,Xm) _W((0b00111000001 << 21) | ((Xn) << 16) | (EX_UXTW << 13) | (0 << 12) | (0b10 << 10) | ((Xm) << 5) | (Wt))
|
||||
#define STRH_wXi(Wt,Xn,i) _W((0b0111100100 << 22) | ((((i)/2) &0xfff) << 10) | ((Xn) << 5) | (Wt))
|
||||
#define STRH_wXx(Wt,Xn,Xm) _W((0b01111000001 << 21) | ((Xn) << 16) | (EX_UXTW << 13) | (0 << 12) | (0b10 << 10) | ((Xm) << 5) | (Wt))
|
||||
|
||||
#define STUR_wXi(Wt,Xn,i) _W((0b10111000000 << 21) | ((i & 0x1ff) << 12) | ((Xn) << 5) | (Wt))
|
||||
#define STURH_wXi(Wt,Xn,i) _W((0b01111000000 << 21) | ((i & 0x1ff) << 12) | ((Xn) << 5) | (Wt))
|
||||
|
||||
/*----------------------------------------
|
||||
* move immediate/register
|
||||
*----------------------------------------*/
|
||||
#define MOV_wi(Wd,i16) _W((0b01010010100 << 21) | (((i16) & 0xffff) << 5) | (Wd))
|
||||
#define MOV_xi(Xd,i16) _W((0b11010010100 << 21) | (((i16) & 0xffff) << 5) | (Xd))
|
||||
// sh in bits (multiple of 16)
|
||||
#define MOV_wish(Wd,i16,sh) _W((0b010100101 << 23) | (((sh)/16) << 21) | (((i16) & 0xffff) << 5) | (Wd))
|
||||
#define MOV_xish(Xd,i16,sh) _W((0b110100101 << 23) | (((sh)/16) << 21) | (((i16) & 0xffff) << 5) | (Xd))
|
||||
#define MOV_ww(Wd,Wm) _W((0b00101010000 << 21) | ((Wm) << 16) | (0 << 10) | (0b11111 << 5) | (Wd))
|
||||
#define MOV_xx(Xd,Xm) _W((0b10101010000 << 21) | ((Xm) << 16) | (0 << 10) | (0b11111 << 5) | (Xd))
|
||||
#define MOVK_wi(Wd,i16) _W((0b01110010100 << 21) | (((i16) & 0xffff) << 5) | (Wd))
|
||||
#define MOVK_xi(Xd,i16) _W((0b11110010100 << 21) | (((i16) & 0xffff) << 5) | (Xd))
|
||||
#define MOVK_wish(Wd,i16,sh) _W((0b011100101 << 23) | (((sh)/16) << 21) | (((i16) & 0xffff) << 5) | (Wd))
|
||||
#define MOVK_xish(Xd,i16,sh) _W((0b111100101 << 23) | (((sh)/16) << 21) | (((i16) & 0xffff) << 5) | (Xd))
|
||||
#define MOVN_wi(Wd,i16) _W((0b00010010100 << 21) | (((i16) & 0xffff) << 5) | (Wd))
|
||||
#define MOVN_xi(Xd,i16) _W((0b10010010100 << 21) | (((i16) & 0xffff) << 5) | (Xd))
|
||||
#define MOVN_wish(Wd,i16,sh) _W((0b000100101 << 23) | (((sh)/16) << 21) | (((i16) & 0xffff) << 5) | (Wd))
|
||||
#define MOVN_xish(Xd,i16,sh) _W((0b100100101 << 23) | (((sh)/16) << 21) | (((i16) & 0xffff) << 5) | (Xd))
|
||||
#define MVN_ww(Wd,Wm) _W((0b00101010001 << 21) | ((Wm) << 16) | (0 << 10) | (0b11111 << 5) | (Wd))
|
||||
#define MVN_xx(Xd,Xm) _W((0b10101010001 << 21) | ((Xm) << 16) | (0 << 10) | (0b11111 << 5) | (Xd))
|
||||
|
||||
|
||||
/*----------------------------------------
|
||||
* arithmetic
|
||||
*----------------------------------------*/
|
||||
/* ADD */
|
||||
#define ADC_www(Wd,Wn,Wm) _W((0b00011010000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ADC_xxx(Xd,Xn,Xm) _W((0b10011010000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ADCS_www(Wd,Wn,Wm) _W((0b00111010000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ADCS_xxx(Xd,Xn,Xm) _W((0b10111010000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ADD_wwwEX(Wd,Wn,Wm,ex) _W((0b00001011001 << 21) | ((Wm) << 16) | ((ex) << 13) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ADD_xxwEX(Xd,Xn,Wm,ex) _W((0b10001011001 << 21) | ((Wm) << 16) | ((ex) << 13) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ADD_wwi(Wd,Wn,i12) _W((0b0001000100 << 22) | (((i12) & 0xfff) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ADD_xxi(Xd,Xn,i12) _W((0b1001000100 << 22) | (((i12) & 0xfff) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ADD_www(Wd,Wn,Wm) _W((0b00001011000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ADD_xxx(Xd,Xn,Xm) _W((0b10001011000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ADD_wwwLSLi(Wd,Wn,Wm,i) _W((0b00001011000 << 21) | ((Wm) << 16) | (((i) & 0x1f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ADD_xxxLSLi(Xd,Xn,Xm,i) _W((0b10001011000 << 21) | ((Xm) << 16) | (((i) & 0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ADDS_wwi(Wd,Wn,i12) _W((0b0011000100 << 22) | (((i12) & 0xfff) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ADDS_xxi(Xd,Xn,i12) _W((0b1011000100 << 22) | (((i12) & 0xfff) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ADDS_www(Wd,Wn,Wm) _W((0b00101011000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ADDS_xxx(Xd,Xn,Xm) _W((0b10101011000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ADDS_wwwLSLi(Wd,Wn,Wm,i) _W((0b00101011000 << 21) | ((Wm) << 16) | (((i) & 0x1f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ADDS_xxxLSLi(Xd,Xn,Xm,i) _W((0b10101011000 << 21) | ((Xm) << 16) | (((i) & 0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
/* compare */
|
||||
#define CMP_wi(Wn,i12) _W((0b0111000100 << 22) | (((i12) & 0xfff) << 10) | ((Wn) << 5) | (0b11111))
|
||||
#define CMP_xi(Xn,i12) _W((0b1111000100 << 22) | (((i12) & 0xfff) << 10) | ((Xn) << 5) | (0b11111))
|
||||
#define CMP_ww(Wn,Wm) _W((0b01101011000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (0b11111))
|
||||
#define CMP_xx(Xn,Xm) _W((0b11101011000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (0b11111))
|
||||
#define CMP_wwLSLi(Wn,Wm,i) _W((0b01101011000 << 21) | ((Wm) << 16) | (((i) & 0x1f) << 10) | ((Wn) << 5) | (0b11111))
|
||||
#define CMP_xxLSLi(Xn,Xm,i) _W((0b11101011000 << 21) | ((Xm) << 16) | (((i) & 0x3f) << 10) | ((Xn) << 5) | (0b11111))
|
||||
#define CMP_wwEX(Wn,Wm,ex) _W((0b01101011001 << 21) | ((Wm) << 16) | ((ex) << 13) | (0 << 10) | ((Wn) << 5) | (0b11111))
|
||||
|
||||
/* MUL */
|
||||
#define MUL_www(Wd,Wn,Wm) _W((0b00011011000 << 21) | ((Wm) << 16) | (0b011111 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define MUL_xxx(Xd,Xn,Xm) _W((0b10011011000 << 21) | ((Xm) << 16) | (0b011111 << 10) | ((Xn) << 5) | (Xd))
|
||||
// Xd = (Xn*Xm)[127...64]
|
||||
#define SMULH_xxx(Xd,Xn,Xm) _W((0b10011011010 << 21) | ((Xm) << 16) | (0b011111 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define UMULH_xxx(Xd,Xn,Xm) _W((0b10011011110 << 21) | ((Xm) << 16) | (0b011111 << 10) | ((Xn) << 5) | (Xd))
|
||||
// Xd = (Wn*Wm)[63...0]
|
||||
#define SMULL_xww(Xd,Wn,Wm) _W((0b10011011001 << 21) | ((Wm) << 16) | (0b011111 << 10) | ((Wn) << 5) | (Xd))
|
||||
#define UMULL_xww(Xd,Wn,Wm) _W((0b10011011101 << 21) | ((Wm) << 16) | (0b011111 << 10) | ((Wn) << 5) | (Xd))
|
||||
|
||||
/* multiply sub */
|
||||
// Wd = Wa - (Wn * Wm)
|
||||
#define MSUB_wwww(Wd,Wn,Wm,Wa) _W((0b00011011000 << 21) | ((Wm) << 16) | (1 << 15) | ((Wa) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define MSUB_xxxx(Xd,Xn,Xm,Xa) _W((0b10011011000 << 21) | ((Xm) << 16) | (1 << 15) | ((Xa) << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
/* DIV */
|
||||
// Wd = Wn / Wm
|
||||
#define SDIV_www(Wd,Wn,Wm) _W((0b00011010110 << 21) | ((Wm) << 16) | (0b000011 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SDIV_xxx(Xd,Xn,Xm) _W((0b10011010110 << 21) | ((Xm) << 16) | (0b000011 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define UDIV_www(Wd,Wn,Wm) _W((0b00011010110 << 21) | ((Wm) << 16) | (0b000010 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define UDIV_xxx(Xd,Xn,Xm) _W((0b10011010110 << 21) | ((Xm) << 16) | (0b000010 << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
/* NEG */
|
||||
#define NEG_ww(Wd,Wm) _W((0b01001011000 << 21) | ((Wm) << 16) | (0 << 10) | (0b11111 << 5) | (Wd))
|
||||
#define NEG_xx(Xd,Xm) _W((0b11001011000 << 21) | ((Xm) << 16) | (0 << 10) | (0b11111 << 5) | (Xd))
|
||||
#define NEGS_ww(Wd,Wm) _W((0b01101011000 << 21) | ((Wm) << 16) | (0 << 10) | (0b11111 << 5) | (Wd))
|
||||
#define NEGS_xx(Xd,Xm) _W((0b11101011000 << 21) | ((Xm) << 16) | (0 << 10) | (0b11111 << 5) | (Xd))
|
||||
#define NGC_ww(Wd,Wm) _W((0b01011010000 << 21) | ((Wm) << 16) | (0 << 10) | (0b11111 << 5) | (Wd))
|
||||
#define NGC_xx(Xd,Xm) _W((0b11011010000 << 21) | ((Xm) << 16) | (0 << 10) | (0b11111 << 5) | (Xd))
|
||||
#define NGCS_ww(Wd,Wm) _W((0b01111010000 << 21) | ((Wm) << 16) | (0 << 10) | (0b11111 << 5) | (Wd))
|
||||
#define NGCS_xx(Xd,Xm) _W((0b11111010000 << 21) | ((Xm) << 16) | (0 << 10) | (0b11111 << 5) | (Xd))
|
||||
|
||||
/* SUB */
|
||||
// Wd = Wn - Wm
|
||||
#define SBC_www(Wd,Wn,Wm) _W((0b01011010000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SBC_xxx(Xd,Xn,Xm) _W((0b11011010000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define SBCS_www(Wd,Wn,Wm) _W((0b01111010000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SBCS_xxx(Xd,Xn,Xm) _W((0b11111010000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define SUB_wwi(Wd,Wn,i12) _W((0b0101000100 << 22) | (((i12) & 0xfff) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SUB_xxi(Xd,Xn,i12) _W((0b1101000100 << 22) | (((i12) & 0xfff) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define SUB_www(Wd,Wn,Wm) _W((0b01001011000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SUB_xxx(Xd,Xn,Xm) _W((0b11001011000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define SUB_wwwEX(Wd,Wn,Wm,ex) _W((0b11001011001 << 21) | ((Wm) << 16) | ((ex) << 13) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SUBS_wwi(Wd,Wn,i12) _W((0b0111000100 << 22) | (((i12) & 0xfff) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SUBS_xxi(Xd,Xn,i12) _W((0b1111000100 << 22) | (((i12) & 0xfff) << 10) | ((Xn) << 5) | (Xd))
|
||||
// sh: 0 - no shift, 1 - LSL 12
|
||||
#define SUBS_wwish(Wd,Wn,i12,sh) _W((0b011100010 << 23) | (((sh) & 1) << 22) | (((i12) & 0xfff) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SUBS_xxish(Xd,Xn,i12,sh) _W((0b111100010 << 23) | (((sh) & 1) << 22) | (((i12) & 0xfff) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define SUBS_www(Wd,Wn,Wm) _W((0b01101011000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SUBS_xxx(Xd,Xn,Xm) _W((0b11101011000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define SUBS_wwwLSLi(Wd,Wn,Wm,i) _W((0b01101011000 << 21) | ((Wm) << 16) | (((i) & 0x1f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SUBS_xxxLSLi(Xd,Xn,Xm,i) _W((0b11101011000 << 21) | ((Xm) << 16) | (((i) & 0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
/* signed extend */
|
||||
#define SBFM_wwii(Wd,Wn,immr,imms) _W((0b0001001100 << 22) | ((immr) << 16) | ((imms) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SBFM_xxii(Xd,Xn,immr,imms) _W((0b1001001101 << 22) | ((immr) << 16) | ((imms) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define SXTB_ww(Wd,Wn) SBFM_wwii(Wd,Wn,0,7)
|
||||
#define SXTB_xx(Xd,Xn) SBFM_xxii(Xd,Xn,0,7)
|
||||
#define SXTH_ww(Wd,Wn) SBFM_wwii(Wd,Wn,0,15)
|
||||
#define SXTH_xx(Xd,Xn) SBFM_xxii(Xd,Xn,0,15)
|
||||
#define SXTW_xw(Xd,Wn) SBFM_xxii(Xd,Wn,0,31)
|
||||
|
||||
/* unsigned extend */
|
||||
#define UBFM_wwii(Wd,Wn,immr,imms) _W((0b0101001100 << 22) | ((immr) << 16) | ((imms) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define UBFM_xxii(Xd,Xn,immr,imms) _W((0b1101001101 << 22) | ((immr) << 16) | ((imms) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define UXTB_ww(Wd,Wn) UBFM_wwii(Wd,Wn,0,7)
|
||||
#define UXTB_xx(Xd,Xn) UBFM_xxii(Xd,Xn,0,7)
|
||||
#define UXTH_ww(Wd,Wn) UBFM_wwii(Wd,Wn,0,15)
|
||||
#define UXTH_xx(Xd,Xn) UBFM_xxii(Xd,Xn,0,15)
|
||||
|
||||
|
||||
/*----------------------------------------
|
||||
* logical
|
||||
*----------------------------------------*/
|
||||
/* AND */
|
||||
#define AND_www(Wd,Wn,Wm) _W((0b00001010000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define AND_xxx(Xd,Xn,Xm) _W((0b10001010000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define AND_xx1f(Xd,Xn) _W((0b100100100 << 23) | immEncode(1,0b000000,0b000100) | ((Xn) << 5) | (Xd))
|
||||
#define AND_ww3f(Wd,Wn) _W((0b000100100 << 23) | immEncode(0,0b000000,0b000101) | ((Wn) << 5) | (Wd))
|
||||
#define AND_ww1f(Wd,Wn) _W((0b000100100 << 23) | immEncode(0,0b000000,0b000100) | ((Wn) << 5) | (Wd))
|
||||
#define ANDS_www(Wd,Wn,Wm) _W((0b01101010000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ANDS_xxx(Xd,Xn,Xm) _W((0b11101010000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ANDS_xx7fff(Xd,Xn) _W((0b111100100 << 23) | immEncode(1,0b000000,0b001110) | ((Xn) << 5) | (Xd))
|
||||
#define ANDS_xx1f(Xd,Xn) _W((0b111100100 << 23) | immEncode(1,0b000000,0b000100) | ((Xn) << 5) | (Xd))
|
||||
#define ANDS_ww7f(Wd,Wn) _W((0b011100100 << 23) | immEncode(0,0b000000,0b000110) | ((Wn) << 5) | (Wd))
|
||||
#define ANDS_ww3f(Wd,Wn) _W((0b011100100 << 23) | immEncode(0,0b000000,0b000101) | ((Wn) << 5) | (Wd))
|
||||
#define ANDS_ww1f(Wd,Wn) _W((0b011100100 << 23) | immEncode(0,0b000000,0b000100) | ((Wn) << 5) | (Wd))
|
||||
|
||||
/* EOR */
|
||||
#define EOR_www(Wd,Wn,Wm) _W((0b01001010000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define EOR_xxx(Xd,Xn,Xm) _W((0b11001010000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define EOR_wwwLSLi(Wd,Wn,Wm,i) _W((0b01001010000 << 21) | ((Wm) << 16) | (((i) & 0x1f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define EOR_xxxLSLi(Xd,Xn,Xm,i) _W((0b11001010000 << 21) | ((Xm) << 16) | (((i) & 0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
/* ORR */
|
||||
#define ORR_www(Wd,Wn,Wm) _W((0b00101010000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ORR_xxx(Xd,Xn,Xm) _W((0b10101010000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ORR_wwwLSLi(Wd,Wn,Wm,i) _W((0b00101010000 << 21) | ((Wm) << 16) | (((i) & 0x1f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ORR_xxxLSLi(Xd,Xn,Xm,i) _W((0b10101010000 << 21) | ((Xm) << 16) | (((i) & 0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ORR_wwwLSRi(Wd,Wn,Wm,i) _W((0b00101010010 << 21) | ((Wm) << 16) | (((i) & 0x1f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ORR_xxxLSRi(Xd,Xn,Xm,i) _W((0b10101010010 << 21) | ((Xm) << 16) | (((i) & 0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
/* TST */
|
||||
#define TST_ww(Wn,Wm) _W((0b01101010000 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (0b11111))
|
||||
#define TST_xx(Xn,Xm) _W((0b11101010000 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (0b11111))
|
||||
|
||||
|
||||
/*----------------------------------------
|
||||
* shift
|
||||
*----------------------------------------*/
|
||||
#define ASR_www(Wd,Wn,Wm) _W((0b00011010110 << 21) | ((Wm) << 16) | (0b001010 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ASR_xxx(Xd,Xn,Xm) _W((0b10011010110 << 21) | ((Xm) << 16) | (0b001010 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ASR_wwi(Wd,Wn,i) _W((0b0001001100 << 22) | (((i) & 0x1f) << 16) | (0b011111 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ASR_xxi(Xd,Xn,i) _W((0b1001001101 << 22) | (((i) & 0x3f) << 16) | (0b111111 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define LSL_www(Wd,Wn,Wm) _W((0b00011010110 << 21) | ((Wm) << 16) | (0b001000 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define LSL_xxx(Xd,Xn,Xm) _W((0b10011010110 << 21) | ((Xm) << 16) | (0b001000 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define LSL_wwi(Wd,Wn,i) _W((0b0101001100 << 22) | (((32-(i)) & 0x1f) << 16) | (((31-(i)) & 0x1f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define LSL_xxi(Xd,Xn,i) _W((0b1101001101 << 22) | (((64-(i)) & 0x3f) << 16) | (((63-(i)) & 0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define LSR_www(Wd,Wn,Wm) _W((0b00011010110 << 21) | ((Wm) << 16) | (0b001001 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define LSR_xxx(Xd,Xn,Xm) _W((0b10011010110 << 21) | ((Xm) << 16) | (0b001001 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define LSR_wwi(Wd,Wn,i) _W((0b0101001100 << 22) | (((i) & 0x1f) << 16) | (0b011111 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define LSR_xxi(Xd,Xn,i) _W((0b1101001101 << 22) | (((i) & 0x3f) << 16) | (0b111111 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define ROR_wwi(Wd,Ws,i) _W((0b00010011100 << 21) | ((Ws) << 16) | (((i) & 0x1f) << 10) | ((Ws) << 5) | (Wd))
|
||||
#define ROR_xxi(Xd,Xs,i) _W((0b10010011110 << 21) | ((Xs) << 16) | (((i) & 0x3f) << 10) | ((Xs) << 5) | (Xd))
|
||||
#define ROR_www(Wd,Wn,Wm) _W((0b00011010110 << 21) | ((Wm) << 16) | (0b001011 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define ROR_xxx(Xd,Xn,Xm) _W((0b10011010110 << 21) | ((Xm) << 16) | (0b001011 << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
|
||||
/*----------------------------------------
|
||||
* bit ops
|
||||
*----------------------------------------*/
|
||||
/* extract */
|
||||
// Wd[31...0] = Wn[31-lsb...0]Wm[31...lsb]
|
||||
// Xd[63...0] = Xn[63-lsb...0]Xm[63...lsb]
|
||||
#define EXTR_wwwi(Wd,Wn,Wm,lsb) _W((0b00010011100 << 21) | ((Wm) << 16) | (((lsb) & 0x1f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define EXTR_xxxi(Xd,Xn,Xm,lsb) _W((0b10010011110 << 21) | ((Xm) << 16) | (((lsb) & 0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
/* bitfield */
|
||||
// dst[lsb+width-1...lsb] = src[width-1...0]
|
||||
#define BFI_wwii(Wd,Wn,lsb,width) _W((0b0011001100 << 22) | (((32-(lsb))&0x1f) << 16) | ((((width)-1)&0x1f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define BFI_xxii(Xd,Xn,lsb,width) _W((0b1011001101 << 22) | (((64-(lsb))&0x3f) << 16) | ((((width)-1)&0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define SBFIZ_wwii(Wd,Wn,lsb,width) _W((0b0001001100 << 22) | (((32-(lsb))&0x1f) << 16) | ((((width)-1)&0x1f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SBFIZ_xxii(Xd,Xn,lsb,width) _W((0b1001001101 << 22) | (((64-(lsb))&0x3f) << 16) | ((((width)-1)&0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define UBFIZ_wwii(Wd,Wn,lsb,width) _W((0b0101001100 << 22) | (((32-(lsb))&0x1f) << 16) | ((((width)-1)&0x1f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define UBFIZ_xxii(Xd,Xn,lsb,width) _W((0b1101001101 << 22) | (((64-(lsb))&0x3f) << 16) | ((((width)-1)&0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
// dst[width-1...0] = src[lsb+width-1...lsb]
|
||||
#define BFXIL_wwii(Wd,Wn,lsb,width) _W((0b0011001100 << 22) | (((lsb)&0x1f) << 16) | ((((lsb)+(width)-1)&0x3f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define BFXIL_xxii(Xd,Xn,lsb,width) _W((0b1011001101 << 22) | (((lsb)&0x3f) << 16) | ((((lsb)+(width)-1)&0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define SBFX_wwii(Wd,Wn,lsb,width) _W((0b0001001100 << 22) | (((lsb)&0x1f) << 16) | ((((lsb)+(width)-1)&0x3f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define SBFX_xxii(Xd,Xn,lsb,width) _W((0b1001001101 << 22) | (((lsb)&0x3f) << 16) | ((((lsb)+(width)-1)&0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
#define UBFX_wwii(Wd,Wn,lsb,width) _W((0b0101001100 << 22) | (((lsb)&0x1f) << 16) | ((((lsb)+(width)-1)&0x3f) << 10) | ((Wn) << 5) | (Wd))
|
||||
#define UBFX_xxii(Xd,Xn,lsb,width) _W((0b1101001101 << 22) | (((lsb)&0x3f) << 16) | ((((lsb)+(width)-1)&0x3f) << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
#define BIC_www(Wd,Wn,Wm) _W((0b00001010001 << 21) | ((Wm) << 16) | (0 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define BIC_xxx(Xd,Xn,Xm) _W((0b10001010001 << 21) | ((Xm) << 16) | (0 << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
/* reverse */
|
||||
#define REV_ww(Wd,Wn) _W((0b01011010110 << 21) | (0b00000 << 16) | (0b000010 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define REV_xx(Xd,Xn) _W((0b11011010110 << 21) | (0b00000 << 16) | (0b000011 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define REV16_ww(Wd,Wn) _W((0b01011010110 << 21) | (0b00000 << 16) | (0b000001 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define REV16_xx(Xd,Xn) _W((0b11011010110 << 21) | (0b00000 << 16) | (0b000001 << 10) | ((Xn) << 5) | (Xd))
|
||||
#define REV32_xx(Xd,Xn) _W((0b11011010110 << 21) | (0b00000 << 16) | (0b000010 << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
#define CLS_ww(Wd,Wn) _W((0b01011010110 << 21) | (0b00000000101 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define CLZ_ww(Wd,Wn) _W((0b01011010110 << 21) | (0b00000000100 << 10) | ((Wn) << 5) | (Wd))
|
||||
|
||||
|
||||
/*----------------------------------------
|
||||
* conditional ops
|
||||
*----------------------------------------*/
|
||||
/* conditional compare */
|
||||
#define CCMP_wwfc(Wn,Wm,nzcv,cond) _W((0b01111010010 << 21) | ((Wm) << 16) | ((cond) << 12) | (0b00 << 10) | ((Wn) << 5) | (nzcv))
|
||||
#define CCMP_xxfc(Xn,Xm,nzcv,cond) _W((0b11111010010 << 21) | ((Xm) << 16) | ((cond) << 12) | (0b00 << 10) | ((Xn) << 5) | (nzcv))
|
||||
|
||||
/* conditional select */
|
||||
#define CSEL_wwwc(Wd,Wn,Wm,cond) _W((0b00011010100 << 21) | ((Wm) << 16) | ((cond) << 12) | (0b00 << 10) | ((Wn) << 5) | (Wd))
|
||||
#define CSEL_xxxc(Xd,Xn,Xm,cond) _W((0b10011010100 << 21) | ((Xm) << 16) | ((cond) << 12) | (0b00 << 10) | ((Xn) << 5) | (Xd))
|
||||
|
||||
/* conditional set */
|
||||
#define CSET_wc(Wd,cond) _W((0b00011010100 << 21) | (0b11111 << 16) | ((cond^1) << 12) | (0b01 << 10) | (0b11111 << 5) | (Wd))
|
||||
#define CSET_xc(Xd,cond) _W((0b10011010100 << 21) | (0b11111 << 16) | ((cond^1) << 12) | (0b01 << 10) | (0b11111 << 5) | (Xd))
|
||||
|
||||
/* conditional set mask */
|
||||
#define CSETM_wc(Wd,cond) _W((0b01011010100 << 21) | (0b11111 << 16) | ((cond^1) << 12) | (0b00 << 10) | (0b11111 << 5) | (Wd))
|
||||
#define CSETM_xc(Xd,cond) _W((0b11011010100 << 21) | (0b11111 << 16) | ((cond^1) << 12) | (0b00 << 10) | (0b11111 << 5) | (Xd))
|
||||
|
||||
|
||||
/*----------------------------------------
|
||||
* some special defines
|
||||
*----------------------------------------*/
|
||||
// immediate encoding for flags:
|
||||
// N N=1 immr=100001 imms=000000
|
||||
// Z N=1 immr=100010 imms=000000
|
||||
// C N=1 immr=100011 imms=000000
|
||||
// V N=1 immr=100100 imms=000000
|
||||
// ~N N=1 immr=100000 imms=111110
|
||||
// ~Z N=1 immr=100001 imms=111110
|
||||
// ~C N=1 immr=100010 imms=111110
|
||||
// ~V N=1 immr=100011 imms=111110
|
||||
#define immNflag immEncode(1, 0b100001, 0b000000)
|
||||
#define immZflag immEncode(1, 0b100010, 0b000000)
|
||||
#define immCflag immEncode(1, 0b100011, 0b000000)
|
||||
#define immVflag immEncode(1, 0b100100, 0b000000)
|
||||
|
||||
#define immNflagInv immEncode(1, 0b100000, 0b111110)
|
||||
#define immZflagInv immEncode(1, 0b100001, 0b111110)
|
||||
#define immCflagInv immEncode(1, 0b100010, 0b111110)
|
||||
#define immVflagInv immEncode(1, 0b100011, 0b111110)
|
||||
|
||||
#define immOP_EOR (0b110100100 << 23)
|
||||
#define immOP_AND (0b100100100 << 23)
|
||||
#define immOP_ORR (0b101100100 << 23)
|
||||
|
||||
// R_MEMSTART is in 32bit address space and never 0, so CCMN(R_MEMSTART, #0, #0, #<any cond>) will always clear NZCV
|
||||
#define CLEAR_NZCV() _W((0b10111010010 << 21) | (0 << 16) | (NATIVE_CC_EQ << 12) | (0b10 << 10) | (R_MEMSTART << 5) | (0))
|
||||
|
||||
#define EOR_xxCflag(Xd,Xn) _W(immCflag | immOP_EOR | ((Xn) << 5) | (Xd))
|
||||
#define CLEAR_xxZflag(Xd,Xn) _W(immZflagInv | immOP_AND | ((Xn) << 5) | (Xd))
|
||||
#define CLEAR_xxCflag(Xd,Xn) _W(immCflagInv | immOP_AND | ((Xn) << 5) | (Xd))
|
||||
#define SET_xxZflag(Xd,Xn) _W(immZflag | immOP_ORR | ((Xn) << 5) | (Xd))
|
||||
#define SET_xxVflag(Xd,Xn) _W(immVflag | immOP_ORR | ((Xn) << 5) | (Xd))
|
||||
#define SET_xxCflag(Xd,Xn) _W(immCflag | immOP_ORR | ((Xn) << 5) | (Xd))
|
||||
|
||||
#define EOR_xxbit(Xd,Xn,bit) _W(immOP_EOR | immEncode(1, ((-(bit)) & 0x3f), 0b000000) | ((Xn) << 5) | (Xd))
|
||||
#define CLEAR_xxbit(Xd,Xn,bit) _W(immOP_AND | immEncode(1, ((-((bit)+1)) & 0x3f), 0b111110) | ((Xn) << 5) | (Xd))
|
||||
#define SET_xxbit(Xd,Xn,bit) _W(immOP_ORR | immEncode(1, ((-(bit)) & 0x3f), 0b000000) | ((Xn) << 5) | (Xd))
|
||||
|
||||
#define CLEAR_LOW4_xx(Xd,Xn) _W(immOP_AND | immEncode(1, 0b111100, 0b111011) | ((Xn) << 5) | (Xd))
|
||||
#define CLEAR_LOW8_xx(Xd,Xn) _W(immOP_AND | immEncode(1, 0b111000, 0b110111) | ((Xn) << 5) | (Xd))
|
||||
#define CLEAR_LOW16_xx(Xd,Xn) _W(immOP_AND | immEncode(1, 0b110000, 0b101111) | ((Xn) << 5) | (Xd))
|
||||
|
||||
#define SET_LOW8_xx(Xd,Xn) _W(immOP_ORR | immEncode(1, 0b000000, 0b000111) | ((Xn) << 5) | (Xd))
|
||||
|
||||
// Floatingpoint
|
||||
|
||||
#define LDR_dXi(Dt,Xn,i) _W((0b1111110101 << 22) | (((i)/8) << 10) | ((Xn) << 5) | (Dt))
|
||||
#define LDR_sXi(St,Xn,i) _W((0b1011110101 << 22) | (((i)/4) << 10) | ((Xn) << 5) | (St))
|
||||
#define LDR_dXx(Dt,Xn,Xm) _W((0b11111100011 << 21) | ((Xm) << 16) | (0b011010 << 10) | ((Xn) << 5) | (Dt))
|
||||
|
||||
#define STR_dXi(Dt,Xn,i) _W((0b1111110100 << 22) | (((i)/8) << 10) | ((Xn) << 5) | (Dt))
|
||||
#define STR_sXi(St,Xn,i) _W((0b1011110100 << 22) | (((i)/4) << 10) | ((Xn) << 5) | (St))
|
||||
#define STR_dXx(Dt,Xn,Xm) _W((0b11111100001 << 21) | ((Xm) << 16) | (0b011010 << 10) | ((Xn) << 5) | (Dt))
|
||||
#define FMOV_dd(Dd,Dn) _W((0b00011110011 << 21) | (0b00000010000 << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FMOV_ss(Sd,Sn) _W((0b00011110001 << 21) | (0b00000010000 << 10) | ((Sn) << 5) | (Sd))
|
||||
#define FMOV_dx(Dd,Xn) _W((0b10011110011 << 21) | (0b00111000000 << 10) | ((Xn) << 5) | (Dd))
|
||||
#define FMOV_xd(Xd,Dn) _W((0b10011110011 << 21) | (0b00110000000 << 10) | ((Dn) << 5) | (Xd))
|
||||
#define FMOV_sw(Sd,Wn) _W((0b00011110001 << 21) | (0b00111000000 << 10) | ((Wn) << 5) | (Sd))
|
||||
#define FMOV_ws(Wd,Sn) _W((0b00011110001 << 21) | (0b00110000000 << 10) | ((Sn) << 5) | (Wd))
|
||||
#define FMOV_di(Dd,i) _W((0b00011110011 << 21) | ((i) << 13) | (0b10000000 << 5) | (Dd))
|
||||
#define FMOV_si(Sd,i) _W((0b00011110001 << 21) | ((i) << 13) | (0b10000000 << 5) | (Sd))
|
||||
#define MOVI_di(Dd,i) _W((0b0010111100000 << 19) | ((((i) >> 5) & 0x7) << 16) | (0b111001 << 10) | (((i) & 0x1f) << 5) | (Dd))
|
||||
#define FCVT_ds(Dd,Sn) _W((0b00011110001 << 21) | (0b00010110000 << 10) | ((Sn) << 5) | (Dd))
|
||||
#define FCVT_sd(Sd,Dn) _W((0b00011110011 << 21) | (0b00010010000 << 10) | ((Dn) << 5) | (Sd))
|
||||
#define FRINTA_dd(Dd,Dn) _W((0b00011110011 << 21) | (0b00110010000 << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FRINTI_dd(Dd,Dn) _W((0b00011110011 << 21) | (0b00111110000 << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FRINTZ_dd(Dd,Dn) _W((0b00011110011 << 21) | (0b00101110000 << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FCVTAS_wd(Wd,Dn) _W((0b00011110011 << 21) | (0b00100000000 << 10) | ((Dn) << 5) | (Wd))
|
||||
#define FCVTAS_xd(Xd,Dn) _W((0b10011110011 << 21) | (0b00100000000 << 10) | ((Dn) << 5) | (Xd))
|
||||
#define FCVTZS_xd(Xd,Dn) _W((0b10011110011 << 21) | (0b11000000000 << 10) | ((Dn) << 5) | (Xd))
|
||||
#define SCVTF_dw(Dd,Wn) _W((0b00011110011 << 21) | (0b00010000000 << 10) | ((Wn) << 5) | (Dd))
|
||||
#define SCVTF_sw(Sd,Wn) _W((0b00011110001 << 21) | (0b00010000000 << 10) | ((Wn) << 5) | (Sd))
|
||||
#define SCVTF_dx(Dd,Xn) _W((0b10011110011 << 21) | (0b00010000000 << 10) | ((Xn) << 5) | (Dd))
|
||||
|
||||
#define FABS_dd(Dd,Dn) _W((0b00011110011 << 21) | (0b00000110000 << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FABS_ss(Sd,Sn) _W((0b00011110001 << 21) | (0b00000110000 << 10) | ((Sn) << 5) | (Sd))
|
||||
#define FADD_ddd(Dd,Dn,Dm) _W((0b00011110011 << 21) | ((Dm) << 16) | (0b001010 << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FADD_sss(Sd,Sn,Sm) _W((0b00011110001 << 21) | ((Sm) << 16) | (0b001010 << 10) | ((Sn) << 5) | (Sd))
|
||||
#define FCMP_dd(Dn,Dm) _W((0b00011110011 << 21) | ((Dm) << 16) | (0b001000 << 10) | ((Dn) << 5) | (0b00000))
|
||||
#define FCMP_d0(Dn) _W((0b00011110011 << 21) | (0 << 16) | (0b001000 << 10) | ((Dn) << 5) | (0b01000))
|
||||
#define FCMP_ss(Sn,Sm) _W((0b00011110001 << 21) | ((Sm) << 16) | (0b001000 << 10) | ((Sn) << 5) | (0b00000))
|
||||
#define FDIV_ddd(Dd,Dn,Dm) _W((0b00011110011 << 21) | ((Dm) << 16) | (0b000110 << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FDIV_sss(Sd,Sn,Sm) _W((0b00011110001 << 21) | ((Sm) << 16) | (0b000110 << 10) | ((Sn) << 5) | (Sd))
|
||||
#define FMUL_ddd(Dd,Dn,Dm) _W((0b00011110011 << 21) | ((Dm) << 16) | (0b000010 << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FMUL_sss(Sd,Sn,Sm) _W((0b00011110001 << 21) | ((Sm) << 16) | (0b000010 << 10) | ((Sn) << 5) | (Sd))
|
||||
#define FMSUB_dddd(Dd,Dn,Dm,Da) _W((0b00011111010 << 21) | ((Dm) << 16) | (1 << 15) | ((Da) << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FNEG_dd(Dd,Dn) _W((0b00011110011 << 21) | (0b00001010000 << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FNEG_ss(Sd,Sn) _W((0b00011110001 << 21) | (0b00001010000 << 10) | ((Sn) << 5) | (Sd))
|
||||
#define FSQRT_dd(Dd,Dn) _W((0b00011110011 << 21) | (0b00001110000 << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FSQRT_ss(Sd,Sn) _W((0b00011110001 << 21) | (0b00001110000 << 10) | ((Sn) << 5) | (Sd))
|
||||
#define FSUB_ddd(Dd,Dn,Dm) _W((0b00011110011 << 21) | ((Dm) << 16) | (0b001110 << 10) | ((Dn) << 5) | (Dd))
|
||||
#define FSUB_sss(Sd,Sn,Sm) _W((0b00011110001 << 21) | ((Sm) << 16) | (0b001110 << 10) | ((Sn) << 5) | (Sd))
|
||||
|
||||
#define REV64_dd(Vd,Vn) _W((0b0000111000 << 22) | (0b100000000010 << 10) | ((Vn) << 5) | (Vd))
|
||||
|
||||
#endif /* ARM_ASMA64_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* compiler/compemu.h - Public interface and definitions
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik 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 -> IA-32 and AMD64
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* ARAnyM 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.
|
||||
*
|
||||
* ARAnyM 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 ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef COMPEMU_H
|
||||
#define COMPEMU_H
|
||||
|
||||
#include "sysconfig.h"
|
||||
#include "newcpu.h"
|
||||
|
||||
#ifdef UAE
|
||||
#ifdef CPU_64_BIT
|
||||
typedef uae_u64 uintptr;
|
||||
typedef uae_s64 intptr;
|
||||
#else
|
||||
typedef uae_u32 uintptr;
|
||||
#endif
|
||||
/* FIXME: cpummu.cpp also checks for USE_JIT, possibly others */
|
||||
#define USE_JIT
|
||||
#endif
|
||||
|
||||
#define JITPTR (uintptr)
|
||||
|
||||
/* Now that we do block chaining, and also have linked lists on each tag,
|
||||
TAGMASK can be much smaller and still do its job. Saves several megs
|
||||
of memory! */
|
||||
#define TAGMASK 0x0000ffff
|
||||
#define TAGSIZE (TAGMASK+1)
|
||||
#define MAXRUN 1024
|
||||
#define cacheline(x) (((uintptr)x)&TAGMASK)
|
||||
|
||||
extern uae_u8* start_pc_p;
|
||||
extern uae_u32 start_pc;
|
||||
|
||||
struct blockinfo_t;
|
||||
|
||||
typedef struct {
|
||||
uae_u16* location;
|
||||
uae_u8 specmem;
|
||||
} cpu_history;
|
||||
|
||||
typedef union {
|
||||
cpuop_func* handler;
|
||||
struct blockinfo_t* bi;
|
||||
} cacheline;
|
||||
|
||||
#define USE_F_ALIAS 1
|
||||
#define USE_OFFSET 1
|
||||
#define COMP_DEBUG 1
|
||||
|
||||
#if COMP_DEBUG
|
||||
#define Dif(x) if (x)
|
||||
#else
|
||||
#define Dif(x) if (0)
|
||||
#endif
|
||||
|
||||
#define SCALE 2
|
||||
#define MAXCYCLES (1000 * CYCLE_UNIT)
|
||||
|
||||
#define BYTES_PER_INST 10240 /* paranoid ;-) */
|
||||
#if defined(CPU_arm)
|
||||
#define LONGEST_68K_INST 256 /* The number of bytes the longest possible
|
||||
68k instruction takes */
|
||||
#else
|
||||
#define LONGEST_68K_INST 16 /* The number of bytes the longest possible
|
||||
68k instruction takes */
|
||||
#endif
|
||||
#define MAX_CHECKSUM_LEN 2048 /* The maximum size we calculate checksums
|
||||
for. Anything larger will be flushed
|
||||
unconditionally even with SOFT_FLUSH */
|
||||
#define MAX_HOLD_BI 3 /* One for the current block, and up to two
|
||||
for jump targets */
|
||||
|
||||
#if 1
|
||||
// gb-- my format from readcpu.cpp is not the same
|
||||
#define FLAG_X 0x0010
|
||||
#define FLAG_N 0x0008
|
||||
#define FLAG_Z 0x0004
|
||||
#define FLAG_V 0x0002
|
||||
#define FLAG_C 0x0001
|
||||
#else
|
||||
#define FLAG_C 0x0010
|
||||
#define FLAG_V 0x0008
|
||||
#define FLAG_Z 0x0004
|
||||
#define FLAG_N 0x0002
|
||||
#define FLAG_X 0x0001
|
||||
#endif
|
||||
#define FLAG_CZNV (FLAG_C | FLAG_Z | FLAG_N | FLAG_V)
|
||||
#define FLAG_ALL (FLAG_C | FLAG_Z | FLAG_N | FLAG_V | FLAG_X)
|
||||
#define FLAG_ZNV (FLAG_Z | FLAG_N | FLAG_V)
|
||||
|
||||
#if defined(CPU_arm) && !defined(ARMV6T2) && !defined(CPU_AARCH64)
|
||||
#define USE_DATA_BUFFER
|
||||
#elif defined(CPU_AARCH64)
|
||||
#define N_REGS 18 /* really 32, but 29 to 31 are FP, LR, SP; 18 has special meaning; 27 holds memstart and 28 holds regs-struct */
|
||||
#else
|
||||
#define N_REGS 11 /* really 16, but 13 to 15 are SP, LR, PC; 11 holds memstart and 12 is scratch register */
|
||||
#endif
|
||||
|
||||
#define N_FREGS 16 // We use 10 regs: 6 - FP_RESULT, 7 - SCRATCH, 8-15 - Amiga regs FP0-FP7
|
||||
|
||||
/* Functions exposed to newcpu, or to what was moved from newcpu.c to
|
||||
* compemu_support.c */
|
||||
extern void compiler_init(void);
|
||||
extern void compiler_exit(void);
|
||||
extern void build_comp(void);
|
||||
extern void set_cache_state(int enabled);
|
||||
#ifdef JIT
|
||||
extern void (*flush_icache)(int);
|
||||
#endif
|
||||
extern void alloc_cache(void);
|
||||
extern void compile_block(cpu_history* pc_hist, int blocklen, int totcyles);
|
||||
extern int check_for_cache_miss(void);
|
||||
|
||||
#define scaled_cycles(x) (currprefs.m68k_speed<0?(((x)/SCALE)?(((x)/SCALE<MAXCYCLES?((x)/SCALE):MAXCYCLES)):1):(x))
|
||||
|
||||
/* JIT FPU compilation */
|
||||
extern void comp_fpp_opp (uae_u32 opcode, uae_u16 extra);
|
||||
extern void comp_fbcc_opp (uae_u32 opcode);
|
||||
extern void comp_fscc_opp (uae_u32 opcode, uae_u16 extra);
|
||||
|
||||
extern uae_u32 needed_flags;
|
||||
extern uae_u8* comp_pc_p;
|
||||
extern void* pushall_call_handler;
|
||||
|
||||
#define VREGS 22
|
||||
#define VFREGS 10
|
||||
|
||||
#define INMEM 1
|
||||
#define CLEAN 2
|
||||
#define DIRTY 3
|
||||
#define UNDEF 4
|
||||
#define ISCONST 5
|
||||
|
||||
typedef struct {
|
||||
uae_u32* mem;
|
||||
uintptr val; /* Must be pointer-width: PC_P holds a host pointer (64-bit on ARM64) */
|
||||
uae_u8 status;
|
||||
uae_s8 realreg; /* gb-- realreg can hold -1 */
|
||||
uae_u8 realind; /* The index in the holds[] array */
|
||||
uae_u8 needflush;
|
||||
} reg_status;
|
||||
|
||||
typedef struct {
|
||||
uae_u32* mem;
|
||||
uae_u8 status;
|
||||
uae_s8 realreg; /* gb-- realreg can hold -1 */
|
||||
uae_u8 needflush;
|
||||
} freg_status;
|
||||
|
||||
typedef struct {
|
||||
uae_u8 use_flags;
|
||||
uae_u8 set_flags;
|
||||
uae_u8 is_addx;
|
||||
uae_u8 cflow;
|
||||
} op_properties;
|
||||
|
||||
extern op_properties prop[65536];
|
||||
|
||||
STATIC_INLINE int end_block(uae_u16 opcode)
|
||||
{
|
||||
return (prop[opcode].cflow & fl_end_block);
|
||||
}
|
||||
|
||||
#define SP_REG 15
|
||||
#define PC_P 16
|
||||
#define FLAGX 17
|
||||
#define FLAGTMP 18
|
||||
|
||||
#define S1 19
|
||||
#define S2 20
|
||||
#define S3 21
|
||||
#define SCRATCH_REGS 3
|
||||
|
||||
#define FP_RESULT 8
|
||||
#define FS1 9
|
||||
|
||||
#define SCRATCH_F64_1 1
|
||||
#define SCRATCH_F64_2 2
|
||||
#define SCRATCH_F64_3 3
|
||||
#define SCRATCH_F64_4 4
|
||||
#define SCRATCH_F32_1 2
|
||||
#define SCRATCH_F32_2 4
|
||||
#define SCRATCH_F32_3 6
|
||||
#define SCRATCH_F32_4 8
|
||||
|
||||
typedef struct {
|
||||
uae_u32 touched;
|
||||
uae_s8 holds[VREGS];
|
||||
uae_u8 nholds;
|
||||
uae_u8 locked;
|
||||
} n_status;
|
||||
|
||||
typedef struct {
|
||||
uae_s8 holds;
|
||||
uae_u8 nholds;
|
||||
} fn_status;
|
||||
|
||||
/* For flag handling */
|
||||
#define NADA 1
|
||||
#define TRASH 2
|
||||
#define VALID 3
|
||||
|
||||
/* needflush values */
|
||||
#define NF_SCRATCH 0
|
||||
#define NF_TOMEM 1
|
||||
#define NF_HANDLER 2
|
||||
|
||||
typedef struct {
|
||||
/* Integer part */
|
||||
reg_status state[VREGS];
|
||||
n_status nat[N_REGS];
|
||||
uae_u32 flags_on_stack;
|
||||
uae_u32 flags_in_flags;
|
||||
uae_u32 flags_are_important;
|
||||
uae_u32 scratch_in_use[SCRATCH_REGS];
|
||||
/* FPU part */
|
||||
freg_status fate[VFREGS];
|
||||
fn_status fat[N_FREGS];
|
||||
} bigstate;
|
||||
|
||||
typedef struct {
|
||||
/* Integer part */
|
||||
uae_s8 virt[VREGS];
|
||||
uae_s8 nat[N_REGS];
|
||||
} smallstate;
|
||||
|
||||
#define IM8 uae_s32
|
||||
#define IM16 uae_s32
|
||||
#define IM32 uae_s32
|
||||
#define IMPTR uintptr
|
||||
#define RR1 uae_u32
|
||||
#define RR2 uae_u32
|
||||
#define RR4 uae_u32
|
||||
#define W1 uae_u32
|
||||
#define W2 uae_u32
|
||||
#define W4 uae_u32
|
||||
#define RW1 uae_u32
|
||||
#define RW2 uae_u32
|
||||
#define RW4 uae_u32
|
||||
#define MEMR uintptr
|
||||
#define MEMW uintptr
|
||||
#define MEMRW uintptr
|
||||
|
||||
#define FW uae_u32
|
||||
#define FR uae_u32
|
||||
#define FRW uae_u32
|
||||
|
||||
#define MIDFUNC(nargs,func,args) void func args
|
||||
#define MENDFUNC(nargs,func,args)
|
||||
#define COMPCALL(func) func
|
||||
|
||||
#define LOWFUNC(flags,mem,nargs,func,args) STATIC_INLINE void func args
|
||||
#define LENDFUNC(flags,mem,nargs,func,args)
|
||||
|
||||
/* What we expose to the outside */
|
||||
#define DECLARE_MIDFUNC(func) extern void func
|
||||
|
||||
#if defined(CPU_arm)
|
||||
#include "compemu_midfunc_arm.h"
|
||||
#include "compemu_midfunc_arm2.h"
|
||||
#endif
|
||||
|
||||
#undef DECLARE_MIDFUNC
|
||||
|
||||
extern int failure;
|
||||
#define FAIL(x) do { failure|=x; } while (0)
|
||||
|
||||
/* Convenience functions exposed to gencomp */
|
||||
extern uae_u32 m68k_pc_offset;
|
||||
/* address and dest are virtual register numbers */
|
||||
extern void readbyte(int address, int dest);
|
||||
extern void readword(int address, int dest);
|
||||
extern void readlong(int address, int dest);
|
||||
extern void writebyte(int address, int source);
|
||||
extern void writeword(int address, int source);
|
||||
extern void writelong(int address, int source);
|
||||
extern void writeword_clobber(int address, int source);
|
||||
extern void writelong_clobber(int address, int source);
|
||||
extern void get_n_addr(int address, int dest);
|
||||
extern void get_n_addr_jmp(int address, int dest);
|
||||
extern void calc_disp_ea_020(int base, uae_u32 dp, int target);
|
||||
#define SYNC_PC_OFFSET 124
|
||||
extern void sync_m68k_pc(void);
|
||||
extern uintptr get_const(int r);
|
||||
extern uae_u8* compemu_host_pc_from_const(uintptr pc_const);
|
||||
extern void register_branch(uintptr not_taken, uintptr taken, uae_u8 cond);
|
||||
extern void register_possible_exception(void);
|
||||
|
||||
#define comp_get_ibyte(o) do_get_mem_byte((uae_u8 *)(comp_pc_p + (o) + 1))
|
||||
#define comp_get_iword(o) do_get_mem_word((uae_u16 *)(comp_pc_p + (o)))
|
||||
#define comp_get_ilong(o) do_get_mem_long((uae_u32 *)(comp_pc_p + (o)))
|
||||
|
||||
extern int alloc_scratch(void);
|
||||
extern void release_scratch(int i);
|
||||
|
||||
struct blockinfo_t;
|
||||
|
||||
typedef struct dep_t {
|
||||
uae_u32* jmp_off;
|
||||
struct blockinfo_t* target;
|
||||
struct blockinfo_t* source;
|
||||
struct dep_t** prev_p;
|
||||
struct dep_t* next;
|
||||
} dependency;
|
||||
|
||||
typedef struct checksum_info_t {
|
||||
uae_u8 *start_p;
|
||||
uae_u32 length;
|
||||
struct checksum_info_t *next;
|
||||
} checksum_info;
|
||||
|
||||
typedef struct blockinfo_t {
|
||||
uae_s32 count;
|
||||
cpuop_func* direct_handler_to_use;
|
||||
cpuop_func* handler_to_use;
|
||||
/* The direct handler does not check for the correct address */
|
||||
|
||||
cpuop_func* handler;
|
||||
cpuop_func* direct_handler;
|
||||
|
||||
cpuop_func* direct_pen;
|
||||
cpuop_func* direct_pcc;
|
||||
|
||||
uae_u8* nexthandler;
|
||||
uae_u8* pc_p;
|
||||
|
||||
uae_u32 c1;
|
||||
uae_u32 c2;
|
||||
checksum_info *csi;
|
||||
|
||||
struct blockinfo_t* next_same_cl;
|
||||
struct blockinfo_t** prev_same_cl_p;
|
||||
struct blockinfo_t* next;
|
||||
struct blockinfo_t** prev_p;
|
||||
|
||||
uae_u8 optlevel;
|
||||
uae_u8 needed_flags;
|
||||
uae_u8 status;
|
||||
|
||||
dependency dep[2]; /* Holds things we depend on */
|
||||
dependency* deplist; /* List of things that depend on this */
|
||||
} blockinfo;
|
||||
|
||||
#define BI_INVALID 0
|
||||
#define BI_ACTIVE 1
|
||||
#define BI_NEED_RECOMP 2
|
||||
#define BI_NEED_CHECK 3
|
||||
#define BI_CHECKING 4
|
||||
#define BI_COMPILING 5
|
||||
#define BI_FINALIZING 6
|
||||
|
||||
extern const int POPALLSPACE_SIZE;
|
||||
|
||||
void execute_normal(void);
|
||||
void exec_nostats(void);
|
||||
void do_nothing(void);
|
||||
void execute_exception(uae_u32 cycles);
|
||||
|
||||
typedef fptype fpu_register;
|
||||
|
||||
/* Flags for Bernie during development/debugging. Should go away eventually */
|
||||
#define DISTRUST_CONSISTENT_MEM 0
|
||||
|
||||
void jit_abort(const TCHAR *format,...);
|
||||
|
||||
#ifdef CPU_64_BIT
|
||||
static inline uae_u32 check_uae_p32(uintptr address, const char* file, int line)
|
||||
{
|
||||
if (address > (uintptr_t)0xffffffff) {
|
||||
#if !defined(CPU_AARCH64)
|
||||
jit_abort("JIT: 64-bit pointer (0x%llx) at %s:%d (fatal)",
|
||||
(unsigned long long)address, file, line);
|
||||
#endif
|
||||
}
|
||||
return (uae_u32)address;
|
||||
}
|
||||
#define uae_p32(x) (check_uae_p32((uintptr)(x), __FILE__, __LINE__))
|
||||
#else
|
||||
#define uae_p32(x) ((uae_u32)(x))
|
||||
#endif
|
||||
|
||||
#endif /* COMPEMU_H */
|
||||
@@ -0,0 +1,973 @@
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68881 emulation
|
||||
*
|
||||
* Copyright 1996 Herman ten Brugge
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
* Modified 2005 Peter Keunecke
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include "options.h"
|
||||
#include "memory.h"
|
||||
#include "newcpu.h"
|
||||
#include "compemu_arm.h"
|
||||
#include "flags_arm.h"
|
||||
|
||||
#if defined(USE_JIT_FPU)
|
||||
|
||||
extern void fp_to_exten(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3);
|
||||
|
||||
static const int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
|
||||
static const int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
|
||||
|
||||
/* return the required floating point precision or -1 for failure, 0=E, 1=S, 2=D */
|
||||
STATIC_INLINE int comp_fp_get (uae_u32 opcode, uae_u16 extra, int treg)
|
||||
{
|
||||
int reg = opcode & 7;
|
||||
int mode = (opcode >> 3) & 7;
|
||||
int size = (extra >> 10) & 7;
|
||||
|
||||
if (size == 3 || size == 7) /* 3 = packed decimal, 7 is not defined */
|
||||
return -1;
|
||||
switch (mode) {
|
||||
case 0: /* Dn */
|
||||
switch (size) {
|
||||
case 0: /* Long */
|
||||
fmov_l_rr (treg, reg);
|
||||
return 2;
|
||||
case 1: /* Single */
|
||||
fmov_s_rr (treg, reg);
|
||||
return 1;
|
||||
case 4: /* Word */
|
||||
fmov_w_rr (treg, reg);
|
||||
return 1;
|
||||
case 6: /* Byte */
|
||||
fmov_b_rr (treg, reg);
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
case 1: /* An, invalid mode */
|
||||
return -1;
|
||||
case 2: /* (An) */
|
||||
mov_l_rr (S1, reg + 8);
|
||||
break;
|
||||
case 3: /* (An)+ */
|
||||
mov_l_rr (S1, reg + 8);
|
||||
arm_ADD_l_ri8(reg + 8, (reg == 7 ? sz2[size] : sz1[size]));
|
||||
break;
|
||||
case 4: /* -(An) */
|
||||
arm_SUB_l_ri8(reg + 8, (reg == 7 ? sz2[size] : sz1[size]));
|
||||
mov_l_rr (S1, reg + 8);
|
||||
break;
|
||||
case 5: /* (d16,An) */
|
||||
{
|
||||
uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_rr (S1, reg + 8);
|
||||
lea_l_brr (S1, S1, off);
|
||||
break;
|
||||
}
|
||||
case 6: /* (d8,An,Xn) or (bd,An,Xn) or ([bd,An,Xn],od) or ([bd,An],Xn,od) */
|
||||
{
|
||||
uae_u32 dp = comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
calc_disp_ea_020 (reg + 8, dp, S1);
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
switch (reg) {
|
||||
case 0: /* (xxx).W */
|
||||
{
|
||||
uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_ri (S1, off);
|
||||
break;
|
||||
}
|
||||
case 1: /* (xxx).L */
|
||||
{
|
||||
uae_u32 off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
mov_l_ri (S1, off);
|
||||
break;
|
||||
}
|
||||
case 2: /* (d16,PC) */
|
||||
{
|
||||
uae_u32 address = start_pc + ((uae_char*) comp_pc_p - (uae_char*) start_pc_p) + m68k_pc_offset;
|
||||
uae_s32 PC16off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_ri (S1, address + PC16off);
|
||||
break;
|
||||
}
|
||||
case 3: /* (d8,PC,Xn) or (bd,PC,Xn) or ([bd,PC,Xn],od) or ([bd,PC],Xn,od) */
|
||||
return -1; /* rarely used, fallback to non-JIT */
|
||||
case 4: /* # < data >; Constants should be converted just once by the JIT */
|
||||
m68k_pc_offset += sz2[size];
|
||||
switch (size) {
|
||||
case 0:
|
||||
{
|
||||
uae_s32 li = comp_get_ilong(m68k_pc_offset - 4);
|
||||
float si = (float)li;
|
||||
|
||||
if (li == (int)si) {
|
||||
//write_log ("converted immediate LONG constant to SINGLE\n");
|
||||
fmov_s_ri(treg, *(uae_u32 *)&si);
|
||||
return 1;
|
||||
}
|
||||
//write_log ("immediate LONG constant\n");
|
||||
fmov_l_ri(treg, *(uae_u32 *)&li);
|
||||
return 2;
|
||||
}
|
||||
case 1:
|
||||
//write_log (_T("immediate SINGLE constant\n"));
|
||||
fmov_s_ri(treg, comp_get_ilong(m68k_pc_offset - 4));
|
||||
return 1;
|
||||
case 2:
|
||||
{
|
||||
//write_log (_T("immediate LONG DOUBLE constant\n"));
|
||||
uae_u32 wrd1, wrd2, wrd3;
|
||||
fpdata tmp;
|
||||
wrd3 = comp_get_ilong(m68k_pc_offset - 4);
|
||||
wrd2 = comp_get_ilong(m68k_pc_offset - 8);
|
||||
wrd1 = comp_get_iword(m68k_pc_offset - 12) << 16;
|
||||
fp_to_exten(&tmp, wrd1, wrd2, wrd3);
|
||||
mov_l_ri(S1, ((uae_u32*)&tmp)[0]);
|
||||
mov_l_ri(S2, ((uae_u32*)&tmp)[1]);
|
||||
fmov_d_rrr (treg, S1, S2);
|
||||
return 0;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
float si = (float)(uae_s16)comp_get_iword(m68k_pc_offset-2);
|
||||
|
||||
//write_log (_T("converted immediate WORD constant %f to SINGLE\n"), si);
|
||||
fmov_s_ri(treg, *(uae_u32 *)&si);
|
||||
return 1;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
//write_log (_T("immediate DOUBLE constant\n"));
|
||||
mov_l_ri(S1, comp_get_ilong(m68k_pc_offset - 4));
|
||||
mov_l_ri(S2, comp_get_ilong(m68k_pc_offset - 8));
|
||||
fmov_d_rrr (treg, S1, S2);
|
||||
return 2;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
float si = (float)(uae_s8)comp_get_ibyte(m68k_pc_offset - 2);
|
||||
|
||||
//write_log (_T("converted immediate BYTE constant to SINGLE\n"));
|
||||
fmov_s_ri(treg, *(uae_u32 *)&si);
|
||||
return 1;
|
||||
}
|
||||
default: /* never reached */
|
||||
return -1;
|
||||
}
|
||||
default: /* never reached */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case 0: /* Long */
|
||||
readlong (S1, S2);
|
||||
fmov_l_rr (treg, S2);
|
||||
return 2;
|
||||
case 1: /* Single */
|
||||
readlong (S1, S2);
|
||||
fmov_s_rr (treg, S2);
|
||||
return 1;
|
||||
case 2: /* Long Double */
|
||||
fp_to_exten_rm (treg, S1);
|
||||
return 0;
|
||||
case 4: /* Word */
|
||||
readword (S1, S2);
|
||||
fmov_w_rr (treg, S2);
|
||||
return 1;
|
||||
case 5: /* Double */
|
||||
fp_to_double_rm (treg, S1);
|
||||
return 2;
|
||||
case 6: /* Byte */
|
||||
readbyte (S1, S2);
|
||||
fmov_b_rr (treg, S2);
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* return of -1 means failure, >=0 means OK */
|
||||
STATIC_INLINE int comp_fp_put (uae_u32 opcode, uae_u16 extra)
|
||||
{
|
||||
int reg = opcode & 7;
|
||||
int sreg = (extra >> 7) & 7;
|
||||
int mode = (opcode >> 3) & 7;
|
||||
int size = (extra >> 10) & 7;
|
||||
|
||||
if (size == 3 || size == 7) /* 3 = packed decimal, 7 is not defined */
|
||||
return -1;
|
||||
switch (mode) {
|
||||
case 0: /* Dn */
|
||||
switch (size) {
|
||||
case 0: /* FMOVE.L FPx, Dn */
|
||||
fmov_to_l_rr(reg, sreg);
|
||||
return 0;
|
||||
case 1: /* FMOVE.S FPx, Dn */
|
||||
fmov_to_s_rr(reg, sreg);
|
||||
return 0;
|
||||
case 4: /* FMOVE.W FPx, Dn */
|
||||
fmov_to_w_rr(reg, sreg);
|
||||
return 0;
|
||||
case 6: /* FMOVE.B FPx, Dn */
|
||||
fmov_to_b_rr(reg, sreg);
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
case 1: /* An, invalid mode */
|
||||
return -1;
|
||||
case 2: /* (An) */
|
||||
mov_l_rr (S1, reg + 8);
|
||||
break;
|
||||
case 3: /* (An)+ */
|
||||
mov_l_rr (S1, reg + 8);
|
||||
arm_ADD_l_ri8(reg + 8, (reg == 7 ? sz2[size] : sz1[size]));
|
||||
break;
|
||||
case 4: /* -(An) */
|
||||
arm_SUB_l_ri8(reg + 8, (reg == 7 ? sz2[size] : sz1[size]));
|
||||
mov_l_rr (S1, reg + 8);
|
||||
break;
|
||||
case 5: /* (d16,An) */
|
||||
{
|
||||
uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_rr (S1, reg + 8);
|
||||
arm_ADD_l_ri (S1, off);
|
||||
break;
|
||||
}
|
||||
case 6: /* (d8,An,Xn) or (bd,An,Xn) or ([bd,An,Xn],od) or ([bd,An],Xn,od) */
|
||||
{
|
||||
uae_u32 dp = comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
calc_disp_ea_020 (reg + 8, dp, S1);
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
switch (reg) {
|
||||
case 0: /* (xxx).W */
|
||||
{
|
||||
uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_ri (S1, off);
|
||||
break;
|
||||
}
|
||||
case 1: /* (xxx).L */
|
||||
{
|
||||
uae_u32 off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
mov_l_ri (S1, off);
|
||||
break;
|
||||
}
|
||||
default: /* All other modes are not allowed for FPx to <EA> */
|
||||
write_log (_T ("JIT FMOVE FPx,<EA> Mode is not allowed %04x %04x\n"), opcode, extra);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
switch (size) {
|
||||
case 0: /* Long */
|
||||
fmov_to_l_rr(S2, sreg);
|
||||
writelong_clobber (S1, S2);
|
||||
return 0;
|
||||
case 1: /* Single */
|
||||
fmov_to_s_rr(S2, sreg);
|
||||
writelong_clobber (S1, S2);
|
||||
return 0;
|
||||
case 2:/* Long Double */
|
||||
fp_from_exten_mr (S1, sreg);
|
||||
return 0;
|
||||
case 4: /* Word */
|
||||
fmov_to_w_rr(S2, sreg);
|
||||
writeword_clobber (S1, S2);
|
||||
return 0;
|
||||
case 5: /* Double */
|
||||
fp_from_double_mr(S1, sreg);
|
||||
return 0;
|
||||
case 6: /* Byte */
|
||||
fmov_to_b_rr(S2, sreg);
|
||||
writebyte (S1, S2);
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* return -1 for failure, or register number for success */
|
||||
STATIC_INLINE int comp_fp_adr (uae_u32 opcode)
|
||||
{
|
||||
uae_s32 off;
|
||||
int mode = (opcode >> 3) & 7;
|
||||
int reg = opcode & 7;
|
||||
|
||||
switch (mode) {
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
mov_l_rr (S1, 8 + reg);
|
||||
return S1;
|
||||
case 5:
|
||||
off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_rr (S1, 8 + reg);
|
||||
arm_ADD_l_ri (S1, off);
|
||||
return S1;
|
||||
case 7:
|
||||
switch (reg) {
|
||||
case 0:
|
||||
off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_ri (S1, off);
|
||||
return S1;
|
||||
case 1:
|
||||
off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
mov_l_ri (S1, off);
|
||||
return S1;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void comp_fscc_opp (uae_u32 opcode, uae_u16 extra)
|
||||
{
|
||||
int reg;
|
||||
|
||||
if (!currprefs.compfpu) {
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (extra & 0x20) { /* only cc from 00 to 1f are defined */
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
if ((opcode & 0x38) != 0) { /* We can only do to integer register */
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
|
||||
fflags_into_flags ();
|
||||
reg = (opcode & 7);
|
||||
|
||||
if (!(opcode & 0x38)) {
|
||||
switch (extra & 0x0f) { /* according to fpp.c, the 0x10 bit is ignored */
|
||||
case 0: fp_fscc_ri(reg, NATIVE_CC_F_NEVER); break;
|
||||
case 1: fp_fscc_ri(reg, NATIVE_CC_EQ); break;
|
||||
case 2: fp_fscc_ri(reg, NATIVE_CC_F_OGT); break;
|
||||
case 3: fp_fscc_ri(reg, NATIVE_CC_F_OGE); break;
|
||||
case 4: fp_fscc_ri(reg, NATIVE_CC_F_OLT); break;
|
||||
case 5: fp_fscc_ri(reg, NATIVE_CC_F_OLE); break;
|
||||
case 6: fp_fscc_ri(reg, NATIVE_CC_F_OGL); break;
|
||||
case 7: fp_fscc_ri(reg, NATIVE_CC_F_OR); break;
|
||||
case 8: fp_fscc_ri(reg, NATIVE_CC_F_UN); break;
|
||||
case 9: fp_fscc_ri(reg, NATIVE_CC_F_UEQ); break;
|
||||
case 10: fp_fscc_ri(reg, NATIVE_CC_F_UGT); break;
|
||||
case 11: fp_fscc_ri(reg, NATIVE_CC_F_UGE); break;
|
||||
case 12: fp_fscc_ri(reg, NATIVE_CC_F_ULT); break;
|
||||
case 13: fp_fscc_ri(reg, NATIVE_CC_F_ULE); break;
|
||||
case 14: fp_fscc_ri(reg, NATIVE_CC_NE); break;
|
||||
case 15: fp_fscc_ri(reg, NATIVE_CC_AL); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void comp_fbcc_opp (uae_u32 opcode)
|
||||
{
|
||||
uae_u32 start_68k_offset = m68k_pc_offset;
|
||||
uae_s32 off;
|
||||
uintptr v1, v2;
|
||||
int cc;
|
||||
|
||||
if (!currprefs.compfpu) {
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (opcode & 0x20) { /* only cc from 00 to 1f are defined */
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
if (!(opcode & 0x40)) {
|
||||
off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
}
|
||||
else {
|
||||
off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
}
|
||||
|
||||
/* according to fpp.c, the 0x10 bit is ignored
|
||||
(it handles exception handling, which we don't
|
||||
do, anyway ;-) */
|
||||
cc = opcode & 0x0f;
|
||||
if(cc == 0)
|
||||
return; /* jump never */
|
||||
|
||||
/* ARM64 fix: split the branch target computation so that the
|
||||
* displacement and the host pointer addition are separate.
|
||||
* On 32-bit, mov_l_ri folds everything into a single value,
|
||||
* but on 64-bit, set_const masks non-PC_P registers to 32 bits,
|
||||
* truncating the host pointer. Match the pattern used by the
|
||||
* integer Bcc handlers: load signed displacement first, then
|
||||
* add the 64-bit comp_pc_p via arm_ADD_l_ri. */
|
||||
{
|
||||
uae_s32 displacement = off - (uae_s32)(m68k_pc_offset - start_68k_offset);
|
||||
mov_l_ri(S1, (uae_s32)displacement);
|
||||
arm_ADD_l_ri(S1, (uintptr)comp_pc_p);
|
||||
}
|
||||
mov_l_ri(PC_P, (uintptr) comp_pc_p);
|
||||
|
||||
/* Now they are both constant. Fold in m68k_pc_offset */
|
||||
arm_ADD_l_ri (S1, m68k_pc_offset);
|
||||
arm_ADD_l_ri (PC_P, m68k_pc_offset);
|
||||
m68k_pc_offset = 0;
|
||||
|
||||
v1 = get_const (PC_P);
|
||||
v2 = get_const (S1);
|
||||
fflags_into_flags ();
|
||||
|
||||
switch (cc) {
|
||||
case 1: register_branch (v1, v2, NATIVE_CC_EQ); break;
|
||||
case 2: register_branch (v1, v2, NATIVE_CC_F_OGT); break;
|
||||
case 3: register_branch (v1, v2, NATIVE_CC_F_OGE); break;
|
||||
case 4: register_branch (v1, v2, NATIVE_CC_F_OLT); break;
|
||||
case 5: register_branch (v1, v2, NATIVE_CC_F_OLE); break;
|
||||
case 6: register_branch (v1, v2, NATIVE_CC_F_OGL); break;
|
||||
case 7: register_branch (v1, v2, NATIVE_CC_F_OR); break;
|
||||
case 8: register_branch (v1, v2, NATIVE_CC_F_UN); break;
|
||||
case 9: register_branch (v1, v2, NATIVE_CC_F_UEQ); break;
|
||||
case 10: register_branch (v1, v2, NATIVE_CC_F_UGT); break;
|
||||
case 11: register_branch (v1, v2, NATIVE_CC_F_UGE); break;
|
||||
case 12: register_branch (v1, v2, NATIVE_CC_F_ULT); break;
|
||||
case 13: register_branch (v1, v2, NATIVE_CC_F_ULE); break;
|
||||
case 14: register_branch (v1, v2, NATIVE_CC_NE); break;
|
||||
case 15: register_branch (v2, v2, NATIVE_CC_AL); break;
|
||||
}
|
||||
}
|
||||
|
||||
static uae_u32 dhex_pi[] ={0x54442D18, 0x400921FB};
|
||||
static uae_u32 dhex_exp_1[] ={0x8B145769, 0x4005BF0A};
|
||||
static uae_u32 dhex_l2_e[] ={0x652B82FE, 0x3FF71547};
|
||||
static uae_u32 dhex_ln_2[] ={0xFEFA39EF, 0x3FE62E42};
|
||||
static uae_u32 dhex_ln_10[] ={0xBBB55516, 0x40026BB1};
|
||||
static uae_u32 dhex_l10_2[] ={0x509F79FF, 0x3FD34413};
|
||||
static uae_u32 dhex_l10_e[] ={0x1526E50E, 0x3FDBCB7B};
|
||||
static uae_u32 dhex_1e16[] ={0x37E08000, 0x4341C379};
|
||||
static uae_u32 dhex_1e32[] ={0xB5056E17, 0x4693B8B5};
|
||||
static uae_u32 dhex_1e64[] ={0xE93FF9F5, 0x4D384F03};
|
||||
static uae_u32 dhex_1e128[] ={0xF9301D32, 0x5A827748};
|
||||
static uae_u32 dhex_1e256[] ={0x7F73BF3C, 0x75154FDD};
|
||||
static double fp_1e8;
|
||||
|
||||
void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
|
||||
{
|
||||
int reg;
|
||||
int sreg, prec = 0;
|
||||
int dreg = (extra >> 7) & 7;
|
||||
int source = (extra >> 13) & 7;
|
||||
int opmode = extra & 0x7f;
|
||||
|
||||
if (special_mem) {
|
||||
FAIL(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!currprefs.compfpu) {
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
switch (source) {
|
||||
case 3: /* FMOVE FPx, <EA> */
|
||||
if (comp_fp_put (opcode, extra) < 0)
|
||||
FAIL (1);
|
||||
return;
|
||||
case 4: /* FMOVE.L <EA>, ControlReg */
|
||||
if ((opcode & 0x38) == 0) {
|
||||
// Dn
|
||||
// Only single selected control register is allowed
|
||||
// All control register bits unset = FPIAR
|
||||
uae_u16 bits = extra & (0x1000 | 0x0800 | 0x0400);
|
||||
if (bits && bits != 0x1000 && bits != 0x0800 && bits != 0x400) {
|
||||
FAIL(1);
|
||||
return;
|
||||
}
|
||||
if (extra & 0x1000) { /* FPCR */
|
||||
FAIL (1);
|
||||
}
|
||||
if (extra & 0x0800) { /* FPSR */
|
||||
FAIL (1);
|
||||
}
|
||||
if ((extra & 0x0400) || !bits) /* FPIAR */
|
||||
mov_l_mr ((uintptr)®s.fpiar, opcode & 15);
|
||||
return;
|
||||
} else if ((opcode & 0x38) == 0x08) {
|
||||
// An
|
||||
// Only FPIAR can be moved to/from address register
|
||||
// All bits unset = FPIAR
|
||||
uae_u16 bits = extra & (0x1000 | 0x0800 | 0x0400);
|
||||
if (bits && bits != 0x0400) {
|
||||
FAIL(1);
|
||||
return;
|
||||
}
|
||||
mov_l_mr ((uintptr)®s.fpiar, opcode & 15);
|
||||
return;
|
||||
}
|
||||
else if ((opcode & 0x3f) == 0x3c) {
|
||||
if (extra & 0x1000) { /* FPCR */
|
||||
FAIL(1);
|
||||
return;
|
||||
}
|
||||
if (extra & 0x0800) { /* FPSR */
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
if (extra & 0x0400) { /* FPIAR */
|
||||
uae_u32 val = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
mov_l_mi ((uintptr)®s.fpiar, val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
FAIL (1);
|
||||
return;
|
||||
case 5: /* FMOVE.L ControlReg, <EA> */
|
||||
if ((opcode & 0x38) == 0) {
|
||||
// Dn
|
||||
// Only single selected control register is allowed
|
||||
// All control register bits unset = FPIAR
|
||||
uae_u16 bits = extra & (0x1000 | 0x0800 | 0x0400);
|
||||
if (bits && bits != 0x1000 && bits != 0x0800 && bits != 0x400) {
|
||||
FAIL(1);
|
||||
return;
|
||||
}
|
||||
if (extra & 0x1000) /* FPCR */
|
||||
mov_l_rm (opcode & 15, (uintptr)®s.fpcr);
|
||||
if (extra & 0x0800) { /* FPSR */
|
||||
FAIL (1);
|
||||
}
|
||||
if ((extra & 0x0400) || !bits) /* FPIAR */
|
||||
mov_l_rm (opcode & 15, (uintptr)®s.fpiar);
|
||||
return;
|
||||
} else if ((opcode & 0x38) == 0x08) {
|
||||
// An
|
||||
// Only FPIAR can be moved to/from address register
|
||||
// All bits unset = FPIAR
|
||||
uae_u16 bits = extra & (0x1000 | 0x0800 | 0x0400);
|
||||
if (bits && bits != 0x0400) {
|
||||
FAIL(1);
|
||||
return;
|
||||
}
|
||||
mov_l_rm (opcode & 15, (uintptr)®s.fpiar);
|
||||
return;
|
||||
}
|
||||
FAIL (1);
|
||||
return;
|
||||
case 6:
|
||||
case 7:
|
||||
{
|
||||
uae_u32 list = 0;
|
||||
int incr = 0;
|
||||
if (extra & 0x2000) {
|
||||
int ad;
|
||||
|
||||
/* FMOVEM FPP->memory */
|
||||
switch ((extra >> 11) & 3) { /* Get out early if failure */
|
||||
case 0:
|
||||
case 2:
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
default:
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
ad = comp_fp_adr (opcode);
|
||||
if (ad < 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
return;
|
||||
}
|
||||
switch ((extra >> 11) & 3) {
|
||||
case 0: /* static pred */
|
||||
list = extra & 0xff;
|
||||
incr = -1;
|
||||
break;
|
||||
case 2: /* static postinc */
|
||||
list = extra & 0xff;
|
||||
incr = 1;
|
||||
break;
|
||||
case 1: /* dynamic pred */
|
||||
case 3: /* dynamic postinc */
|
||||
abort ();
|
||||
}
|
||||
if (incr < 0) { /* Predecrement */
|
||||
for (reg = 7; reg >= 0; reg--) {
|
||||
if (list & 0x80) {
|
||||
sub_l_ri (ad, 12);
|
||||
fp_from_exten_mr (ad, reg);
|
||||
}
|
||||
list <<= 1;
|
||||
}
|
||||
} else { /* Postincrement */
|
||||
for (reg = 0; reg <= 7; reg++) {
|
||||
if (list & 0x80) {
|
||||
fp_from_exten_mr (ad, reg);
|
||||
arm_ADD_l_ri (ad, 12);
|
||||
}
|
||||
list <<= 1;
|
||||
}
|
||||
}
|
||||
if ((opcode & 0x38) == 0x18)
|
||||
mov_l_rr ((opcode & 7) + 8, ad);
|
||||
if ((opcode & 0x38) == 0x20)
|
||||
mov_l_rr ((opcode & 7) + 8, ad);
|
||||
} else {
|
||||
/* FMOVEM memory->FPP */
|
||||
int ad;
|
||||
switch ((extra >> 11) & 3) { /* Get out early if failure */
|
||||
case 0:
|
||||
case 2:
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
default:
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
ad = comp_fp_adr (opcode);
|
||||
if (ad < 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
return;
|
||||
}
|
||||
switch ((extra >> 11) & 3) {
|
||||
case 0: /* static pred */
|
||||
list = extra & 0xff;
|
||||
incr = -1;
|
||||
break;
|
||||
case 2: /* static postinc */
|
||||
list = extra & 0xff;
|
||||
incr = 1;
|
||||
break;
|
||||
case 1: /* dynamic pred */
|
||||
case 3: /* dynamic postinc */
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (incr < 0) {
|
||||
// not reached
|
||||
for (reg = 7; reg >= 0; reg--) {
|
||||
if (list & 0x80) {
|
||||
sub_l_ri (ad, 12);
|
||||
fp_to_exten_rm(reg, ad);
|
||||
}
|
||||
list <<= 1;
|
||||
}
|
||||
} else {
|
||||
for (reg = 0; reg <= 7; reg++) {
|
||||
if (list & 0x80) {
|
||||
fp_to_exten_rm(reg, ad);
|
||||
arm_ADD_l_ri (ad, 12);
|
||||
}
|
||||
list <<= 1;
|
||||
}
|
||||
}
|
||||
if ((opcode & 0x38) == 0x18)
|
||||
mov_l_rr ((opcode & 7) + 8, ad);
|
||||
if ((opcode & 0x38) == 0x20)
|
||||
mov_l_rr ((opcode & 7) + 8, ad);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 2: /* from <EA> to FPx */
|
||||
dont_care_fflags ();
|
||||
if ((extra & 0xfc00) == 0x5c00) { /* FMOVECR */
|
||||
//write_log (_T("JIT FMOVECR %x\n"), opmode);
|
||||
switch (opmode) {
|
||||
case 0x00:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_pi);
|
||||
break;
|
||||
case 0x0b:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_l10_2);
|
||||
break;
|
||||
case 0x0c:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_exp_1);
|
||||
break;
|
||||
case 0x0d:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_l2_e);
|
||||
break;
|
||||
case 0x0e:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_l10_e);
|
||||
break;
|
||||
case 0x0f:
|
||||
fmov_d_ri_0 (dreg);
|
||||
break;
|
||||
case 0x30:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_ln_2);
|
||||
break;
|
||||
case 0x31:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_ln_10);
|
||||
break;
|
||||
case 0x32:
|
||||
fmov_d_ri_1 (dreg);
|
||||
break;
|
||||
case 0x33:
|
||||
fmov_d_ri_10 (dreg);
|
||||
break;
|
||||
case 0x34:
|
||||
fmov_d_ri_100 (dreg);
|
||||
break;
|
||||
case 0x35:
|
||||
fmov_l_ri (dreg, 10000);
|
||||
break;
|
||||
case 0x36:
|
||||
fmov_rm (dreg, (uintptr)&fp_1e8);
|
||||
break;
|
||||
case 0x37:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_1e16);
|
||||
break;
|
||||
case 0x38:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_1e32);
|
||||
break;
|
||||
case 0x39:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_1e64);
|
||||
break;
|
||||
case 0x3a:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_1e128);
|
||||
break;
|
||||
case 0x3b:
|
||||
fmov_d_rm (dreg, (uintptr)&dhex_1e256);
|
||||
break;
|
||||
default:
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
fmov_rr (FP_RESULT, dreg);
|
||||
return;
|
||||
}
|
||||
if (opmode & 0x20) /* two operands, so we need a scratch reg */
|
||||
sreg = FS1;
|
||||
else /* one operand only, thus we can load the argument into dreg */
|
||||
sreg = dreg;
|
||||
if(opmode >= 0x30 && opmode <= 0x37) {
|
||||
// get out early for unsupported ops
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
if ((prec = comp_fp_get (opcode, extra, sreg)) < 0) {
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
if (!opmode) { /* FMOVE <EA>,FPx */
|
||||
fmov_rr (FP_RESULT, dreg);
|
||||
return;
|
||||
}
|
||||
/* no break here for <EA> to dreg */
|
||||
case 0: /* directly from sreg to dreg */
|
||||
if (!source) { /* no <EA> */
|
||||
dont_care_fflags ();
|
||||
sreg = (extra >> 10) & 7;
|
||||
}
|
||||
switch (opmode) {
|
||||
case 0x00: /* FMOVE */
|
||||
fmov_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x01: /* FINT */
|
||||
frndint_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x02: /* FSINH */
|
||||
ffunc_rr (sinh, dreg, sreg);
|
||||
break;
|
||||
case 0x03: /* FINTRZ */
|
||||
frndintz_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x04: /* FSQRT */
|
||||
fsqrt_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x06: /* FLOGNP1 */
|
||||
ffunc_rr (log1p, dreg, sreg);
|
||||
break;
|
||||
case 0x08: /* FETOXM1 */
|
||||
ffunc_rr (expm1, dreg, sreg);
|
||||
break;
|
||||
case 0x09: /* FTANH */
|
||||
ffunc_rr (tanh, dreg, sreg);
|
||||
break;
|
||||
case 0x0a: /* FATAN */
|
||||
ffunc_rr (atan, dreg, sreg);
|
||||
break;
|
||||
case 0x0c: /* FASIN */
|
||||
ffunc_rr (asin, dreg, sreg);
|
||||
break;
|
||||
case 0x0d: /* FATANH */
|
||||
ffunc_rr (atanh, dreg, sreg);
|
||||
break;
|
||||
case 0x0e: /* FSIN */
|
||||
ffunc_rr (sin, dreg, sreg);
|
||||
break;
|
||||
case 0x0f: /* FTAN */
|
||||
ffunc_rr (tan, dreg, sreg);
|
||||
break;
|
||||
case 0x10: /* FETOX */
|
||||
ffunc_rr (exp, dreg, sreg);
|
||||
break;
|
||||
case 0x11: /* FTWOTOX */
|
||||
fpowx_rr (2, dreg, sreg);
|
||||
break;
|
||||
case 0x12: /* FTENTOX */
|
||||
fpowx_rr (10, dreg, sreg);
|
||||
break;
|
||||
case 0x14: /* FLOGN */
|
||||
ffunc_rr (log, dreg, sreg);
|
||||
break;
|
||||
case 0x15: /* FLOG10 */
|
||||
ffunc_rr (log10, dreg, sreg);
|
||||
break;
|
||||
case 0x16: /* FLOG2 */
|
||||
ffunc_rr (log2, dreg, sreg);
|
||||
break;
|
||||
case 0x18: /* FABS */
|
||||
fabs_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x19: /* FCOSH */
|
||||
ffunc_rr (cosh, dreg, sreg);
|
||||
break;
|
||||
case 0x1a: /* FNEG */
|
||||
fneg_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x1c: /* FACOS */
|
||||
ffunc_rr (acos, dreg, sreg);
|
||||
break;
|
||||
case 0x1d: /* FCOS */
|
||||
ffunc_rr (cos, dreg, sreg);
|
||||
break;
|
||||
case 0x20: /* FDIV */
|
||||
fdiv_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x21: /* FMOD */
|
||||
fmod_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x22: /* FADD */
|
||||
fadd_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x23: /* FMUL */
|
||||
fmul_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x24: /* FSGLDIV */
|
||||
fsgldiv_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x60: /* FSDIV */
|
||||
fdiv_rr (dreg, sreg);
|
||||
if (!currprefs.fpu_strict) /* faster, but less strict rounding */
|
||||
break;
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x25: /* FREM */
|
||||
frem1_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x27: /* FSGLMUL */
|
||||
fsglmul_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x63: /* FSMUL */
|
||||
fmul_rr (dreg, sreg);
|
||||
if (!currprefs.fpu_strict) /* faster, but less strict rounding */
|
||||
break;
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x28: /* FSUB */
|
||||
fsub_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x30: /* FSINCOS */
|
||||
case 0x31:
|
||||
case 0x32:
|
||||
case 0x33:
|
||||
case 0x34:
|
||||
case 0x35:
|
||||
case 0x36:
|
||||
case 0x37:
|
||||
FAIL (1);
|
||||
return;
|
||||
case 0x38: /* FCMP */
|
||||
fmov_rr (FP_RESULT, dreg);
|
||||
fsub_rr (FP_RESULT, sreg);
|
||||
return;
|
||||
case 0x3a: /* FTST */
|
||||
fmov_rr (FP_RESULT, sreg);
|
||||
return;
|
||||
case 0x40: /* FSMOVE */
|
||||
if (prec == 1 || !currprefs.fpu_strict) {
|
||||
if (sreg != dreg) /* no <EA> */
|
||||
fmov_rr (dreg, sreg);
|
||||
}
|
||||
else {
|
||||
fmovs_rr (dreg, sreg);
|
||||
}
|
||||
break;
|
||||
case 0x44: /* FDMOVE */
|
||||
if (sreg != dreg) /* no <EA> */
|
||||
fmov_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x41: /* FSSQRT */
|
||||
fsqrt_rr (dreg, sreg);
|
||||
if (!currprefs.fpu_strict) /* faster, but less strict rounding */
|
||||
break;
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x45: /* FDSQRT */
|
||||
fsqrt_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x58: /* FSABS */
|
||||
fabs_rr (dreg, sreg);
|
||||
if (prec != 1 && currprefs.fpu_strict)
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x5a: /* FSNEG */
|
||||
fneg_rr (dreg, sreg);
|
||||
if (prec != 1 && currprefs.fpu_strict)
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x5c: /* FDABS */
|
||||
fabs_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x5e: /* FDNEG */
|
||||
fneg_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x62: /* FSADD */
|
||||
fadd_rr (dreg, sreg);
|
||||
if (!currprefs.fpu_strict) /* faster, but less strict rounding */
|
||||
break;
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x64: /* FDDIV */
|
||||
fdiv_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x66: /* FDADD */
|
||||
fadd_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x67: /* FDMUL */
|
||||
fmul_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x68: /* FSSUB */
|
||||
fsub_rr (dreg, sreg);
|
||||
if (!currprefs.fpu_strict) /* faster, but less strict rounding */
|
||||
break;
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x6c: /* FDSUB */
|
||||
fsub_rr (dreg, sreg);
|
||||
break;
|
||||
default:
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
fmov_rr (FP_RESULT, dreg);
|
||||
return;
|
||||
default:
|
||||
write_log (_T ("Unsupported JIT-FPU instruction: 0x%04x %04x\n"), opcode, extra);
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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_ldiv8(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(arm_ADD_l_ri(RW4 d, IMPTR i));
|
||||
DECLARE_MIDFUNC(arm_ADD_l_ri8(RW4 d, IM8 i));
|
||||
DECLARE_MIDFUNC(arm_SUB_l_ri8(RW4 d, IM8 i));
|
||||
|
||||
// Emulated midfunc
|
||||
DECLARE_MIDFUNC(disp_ea20_target_add(RW4 target, RR4 reg, IM8 shift, IM8 extend));
|
||||
DECLARE_MIDFUNC(disp_ea20_target_mov(W4 target, RR4 reg, IM8 shift, IM8 extend));
|
||||
|
||||
DECLARE_MIDFUNC(mov_l_mi(IMPTR d, IMPTR 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(lea_l_brr(W4 d, RR4 s, IM32 offset));
|
||||
DECLARE_MIDFUNC(lea_l_brr_indexed(W4 d, RR4 s, RR4 index, IM8 factor, IM8 offset));
|
||||
DECLARE_MIDFUNC(lea_l_rr_indexed(W4 d, RR4 s, RR4 index, IM8 factor));
|
||||
DECLARE_MIDFUNC(mov_l_rr(W4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(mov_l_mr(IMPTR d, RR4 s));
|
||||
DECLARE_MIDFUNC(mov_l_rm(W4 d, IMPTR s));
|
||||
DECLARE_MIDFUNC(mov_l_ri(W4 d, IMPTR s));
|
||||
DECLARE_MIDFUNC(mov_b_ri(W1 d, IM8 s));
|
||||
DECLARE_MIDFUNC(sub_l_ri(RW4 d, IM8 i));
|
||||
DECLARE_MIDFUNC(sub_w_ri(RW2 d, IM8 i));
|
||||
DECLARE_MIDFUNC(live_flags(void));
|
||||
DECLARE_MIDFUNC(dont_care_flags(void));
|
||||
DECLARE_MIDFUNC(make_flags_live(void));
|
||||
DECLARE_MIDFUNC(forget_about(W4 r));
|
||||
|
||||
DECLARE_MIDFUNC(f_forget_about(FW r));
|
||||
DECLARE_MIDFUNC(dont_care_fflags(void));
|
||||
DECLARE_MIDFUNC(fmov_rr(FW d, FR s));
|
||||
|
||||
DECLARE_MIDFUNC(fmov_l_rr(FW d, RR4 s));
|
||||
DECLARE_MIDFUNC(fmov_s_rr(FW d, RR4 s));
|
||||
DECLARE_MIDFUNC(fmov_w_rr(FW d, RR2 s));
|
||||
DECLARE_MIDFUNC(fmov_b_rr(FW d, RR1 s));
|
||||
DECLARE_MIDFUNC(fmov_d_rrr(FW d, RR4 s1, RR4 s2));
|
||||
DECLARE_MIDFUNC(fmov_l_ri(FW d, IM32 i));
|
||||
DECLARE_MIDFUNC(fmov_s_ri(FW d, IM32 i));
|
||||
DECLARE_MIDFUNC(fmov_to_l_rr(W4 d, FR s));
|
||||
DECLARE_MIDFUNC(fmov_to_s_rr(W4 d, FR s));
|
||||
DECLARE_MIDFUNC(fmov_to_w_rr(W4 d, FR s));
|
||||
DECLARE_MIDFUNC(fmov_to_b_rr(W4 d, FR s));
|
||||
DECLARE_MIDFUNC(fmov_d_ri_0(FW d));
|
||||
DECLARE_MIDFUNC(fmov_d_ri_1(FW d));
|
||||
DECLARE_MIDFUNC(fmov_d_ri_10(FW d));
|
||||
DECLARE_MIDFUNC(fmov_d_ri_100(FW d));
|
||||
DECLARE_MIDFUNC(fmov_d_rm(FW r, MEMR m));
|
||||
DECLARE_MIDFUNC(fmovs_rm(FW r, MEMR m));
|
||||
DECLARE_MIDFUNC(fmov_rm(FW r, MEMR m));
|
||||
DECLARE_MIDFUNC(fmov_to_d_rrr(W4 d1, W4 d2, FR s));
|
||||
DECLARE_MIDFUNC(fsqrt_rr(FW d, FR s));
|
||||
DECLARE_MIDFUNC(fabs_rr(FW d, FR s));
|
||||
DECLARE_MIDFUNC(fneg_rr(FW d, FR s));
|
||||
DECLARE_MIDFUNC(fdiv_rr(FRW d, FR s));
|
||||
DECLARE_MIDFUNC(fadd_rr(FRW d, FR s));
|
||||
DECLARE_MIDFUNC(fmul_rr(FRW d, FR s));
|
||||
DECLARE_MIDFUNC(fsub_rr(FRW d, FR s));
|
||||
DECLARE_MIDFUNC(frndint_rr(FW d, FR s));
|
||||
DECLARE_MIDFUNC(frndintz_rr(FW d, FR s));
|
||||
DECLARE_MIDFUNC(fmod_rr(FRW d, FR s));
|
||||
DECLARE_MIDFUNC(fsgldiv_rr(FRW d, FR s));
|
||||
DECLARE_MIDFUNC(fcuts_r(FRW r));
|
||||
DECLARE_MIDFUNC(frem1_rr(FRW d, FR s));
|
||||
DECLARE_MIDFUNC(fsglmul_rr(FRW d, FR s));
|
||||
DECLARE_MIDFUNC(fmovs_rr(FW d, FR s));
|
||||
DECLARE_MIDFUNC(ffunc_rr(double (*func)(double), FW d, FR s));
|
||||
DECLARE_MIDFUNC(fsincos_rr(FW d, FW c, FR s));
|
||||
DECLARE_MIDFUNC(fpowx_rr(uae_u32 x, FW d, FR s));
|
||||
DECLARE_MIDFUNC(fflags_into_flags());
|
||||
DECLARE_MIDFUNC(fp_from_exten_mr(RR4 adr, FR s));
|
||||
DECLARE_MIDFUNC(fp_to_exten_rm(FW d, RR4 adr));
|
||||
DECLARE_MIDFUNC(fp_from_double_mr(RR4 adr, FR s));
|
||||
DECLARE_MIDFUNC(fp_to_double_rm(FW d, RR4 adr));
|
||||
DECLARE_MIDFUNC(fp_fscc_ri(RW4, int cc));
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,468 @@
|
||||
/*
|
||||
* 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[];
|
||||
|
||||
// ADD
|
||||
DECLARE_MIDFUNC(jnf_ADD_im8(W4 d, RR4 s, IM8 v));
|
||||
DECLARE_MIDFUNC(jnf_ADD_b_imm(RW1 d, IM8 v));
|
||||
DECLARE_MIDFUNC(jnf_ADD_w_imm(RW2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jnf_ADD_l_imm(RW4 d, IM32 v));
|
||||
DECLARE_MIDFUNC(jnf_ADD_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jnf_ADD_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jnf_ADD_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_ADD_b_imm(RW1 d, IM8 v));
|
||||
DECLARE_MIDFUNC(jff_ADD_w_imm(RW2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jff_ADD_l_imm(RW4 d, IM32 v));
|
||||
DECLARE_MIDFUNC(jff_ADD_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jff_ADD_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jff_ADD_l(RW4 d, RR4 s));
|
||||
|
||||
// ADDA
|
||||
DECLARE_MIDFUNC(jnf_ADDA_w(RW4 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jnf_ADDA_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jnf_ADDA_w_imm(RW4 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jnf_ADDA_l_imm(RW4 d, IM32 v));
|
||||
|
||||
// ADDX
|
||||
DECLARE_MIDFUNC(jnf_ADDX_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jnf_ADDX_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jnf_ADDX_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_ADDX_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jff_ADDX_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jff_ADDX_l(RW4 d, RR4 s));
|
||||
|
||||
// ANDSR
|
||||
DECLARE_MIDFUNC(jff_ANDSR(IM32 s, IM8 x));
|
||||
|
||||
// AND
|
||||
DECLARE_MIDFUNC(jnf_AND_b_imm(RW1 d, IM8 v));
|
||||
DECLARE_MIDFUNC(jnf_AND_w_imm(RW2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jnf_AND_l_imm(RW4 d, IM32 v));
|
||||
DECLARE_MIDFUNC(jnf_AND_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jnf_AND_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jnf_AND_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_AND_b_imm(RW1 d, IM8 v));
|
||||
DECLARE_MIDFUNC(jff_AND_w_imm(RW2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jff_AND_l_imm(RW4 d, IM32 v));
|
||||
DECLARE_MIDFUNC(jff_AND_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jff_AND_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jff_AND_l(RW4 d, RR4 s));
|
||||
|
||||
// ASL
|
||||
DECLARE_MIDFUNC(jff_ASL_b_imm(RW1 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_ASL_w_imm(RW2 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_ASL_l_imm(RW4 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_ASL_b_reg(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ASL_w_reg(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ASL_l_reg(RW4 d, RR4 i));
|
||||
|
||||
// ASLW
|
||||
DECLARE_MIDFUNC(jff_ASLW(RW2 d));
|
||||
DECLARE_MIDFUNC(jnf_ASLW(RW2 d));
|
||||
|
||||
// ASR
|
||||
DECLARE_MIDFUNC(jnf_ASR_b_imm(RW1 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_ASR_w_imm(RW2 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_ASR_l_imm(RW4 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_ASR_b_imm(RW1 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_ASR_w_imm(RW2 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_ASR_l_imm(RW4 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_ASR_b_reg(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_ASR_w_reg(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_ASR_l_reg(RW4 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ASR_b_reg(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ASR_w_reg(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ASR_l_reg(RW4 d, RR4 i));
|
||||
|
||||
// ASRW
|
||||
DECLARE_MIDFUNC(jff_ASRW(RW2 d));
|
||||
DECLARE_MIDFUNC(jnf_ASRW(RW2 d));
|
||||
|
||||
// BCHG
|
||||
DECLARE_MIDFUNC(jnf_BCHG_b_imm(RW1 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jnf_BCHG_l_imm(RW4 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jff_BCHG_b_imm(RW1 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jff_BCHG_l_imm(RW4 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jnf_BCHG_b(RW1 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jnf_BCHG_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_BCHG_b(RW1 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_BCHG_l(RW4 d, RR4 s));
|
||||
|
||||
// BCLR
|
||||
DECLARE_MIDFUNC(jnf_BCLR_b_imm(RW1 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jnf_BCLR_l_imm(RW4 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jnf_BCLR_b(RW1 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jnf_BCLR_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_BCLR_b_imm(RW1 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jff_BCLR_l_imm(RW4 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jff_BCLR_b(RW1 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_BCLR_l(RW4 d, RR4 s));
|
||||
|
||||
// BFINS
|
||||
DECLARE_MIDFUNC(jnf_BFINS_ii(RW4 d, RR4 s, IM8 offs, IM8 width));
|
||||
DECLARE_MIDFUNC(jff_BFINS_ii(RW4 d, RR4 s, IM8 offs, IM8 width));
|
||||
DECLARE_MIDFUNC(jnf_BFINS2_ii(RW4 d, RW4 d2, RR4 s, IM8 offs, IM8 width));
|
||||
DECLARE_MIDFUNC(jff_BFINS2_ii(RW4 d, RW4 d2, RR4 s, IM8 offs, IM8 width));
|
||||
DECLARE_MIDFUNC(jnf_BFINS_di(RW4 d, RR4 s, RR4 offs, IM8 width));
|
||||
DECLARE_MIDFUNC(jff_BFINS_di(RW4 d, RR4 s, RR4 offs, IM8 width));
|
||||
DECLARE_MIDFUNC(jnf_BFINS2_di(RW4 d, RW4 d2, RR4 s, RR4 offs, IM8 width));
|
||||
DECLARE_MIDFUNC(jff_BFINS2_di(RW4 d, RW4 d2, RR4 s, RR4 offs, IM8 width));
|
||||
DECLARE_MIDFUNC(jnf_BFINS_id(RW4 d, RR4 s, IM8 offs, RR4 width));
|
||||
DECLARE_MIDFUNC(jff_BFINS_id(RW4 d, RR4 s, IM8 offs, RR4 width));
|
||||
DECLARE_MIDFUNC(jnf_BFINS2_id(RW4 d, RW4 d2, RR4 s, IM8 offs, RR4 width));
|
||||
DECLARE_MIDFUNC(jff_BFINS2_id(RW4 d, RW4 d2, RR4 s, IM8 offs, RR4 width));
|
||||
DECLARE_MIDFUNC(jnf_BFINS_dd(RW4 d, RR4 s, RR4 offs, RR4 width));
|
||||
DECLARE_MIDFUNC(jff_BFINS_dd(RW4 d, RR4 s, RR4 offs, RR4 width));
|
||||
DECLARE_MIDFUNC(jnf_BFINS2_dd(RW4 d, RW4 d2, RR4 s, RR4 offs, RR4 width));
|
||||
DECLARE_MIDFUNC(jff_BFINS2_dd(RW4 d, RW4 d2, RR4 s, RR4 offs, RR4 width));
|
||||
|
||||
// BSET
|
||||
DECLARE_MIDFUNC(jnf_BSET_b_imm(RW1 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jnf_BSET_l_imm(RW4 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jnf_BSET_b(RW1 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jnf_BSET_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_BSET_b_imm(RW1 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jff_BSET_l_imm(RW4 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jff_BSET_b(RW1 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_BSET_l(RW4 d, RR4 s));
|
||||
|
||||
// BTST
|
||||
DECLARE_MIDFUNC(jff_BTST_b_imm(RR1 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jff_BTST_l_imm(RR4 d, IM8 s));
|
||||
DECLARE_MIDFUNC(jff_BTST_b(RR1 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_BTST_l(RR4 d, RR4 s));
|
||||
|
||||
// CLR
|
||||
DECLARE_MIDFUNC (jnf_CLR_b(W1 d));
|
||||
DECLARE_MIDFUNC (jnf_CLR_w(W2 d));
|
||||
DECLARE_MIDFUNC (jnf_CLR_l(W4 d));
|
||||
DECLARE_MIDFUNC (jff_CLR_b(W1 d));
|
||||
DECLARE_MIDFUNC (jff_CLR_w(W2 d));
|
||||
DECLARE_MIDFUNC (jff_CLR_l(W4 d));
|
||||
|
||||
// CMP
|
||||
DECLARE_MIDFUNC(jff_CMP_b_imm(RR1 d, IM8 v));
|
||||
DECLARE_MIDFUNC(jff_CMP_w_imm(RR2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jff_CMP_l_imm(RR4 d, IM32 v));
|
||||
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_w_imm(RR2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jff_CMPA_l_imm(RR4 d, IM32 v));
|
||||
DECLARE_MIDFUNC(jff_CMPA_w(RR2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jff_CMPA_l(RR4 d, RR4 s));
|
||||
|
||||
// DBCC
|
||||
DECLARE_MIDFUNC(jff_DBCC(RW4 d, IM8 cc));
|
||||
|
||||
// DIVU
|
||||
DECLARE_MIDFUNC(jnf_DIVU(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_DIVU(RW4 d, RR4 s));
|
||||
|
||||
// DIVS
|
||||
DECLARE_MIDFUNC(jnf_DIVS(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_DIVS(RW4 d, RR4 s));
|
||||
|
||||
// DIVL
|
||||
DECLARE_MIDFUNC(jnf_DIVLU32(RW4 d, RR4 s1, W4 rem));
|
||||
DECLARE_MIDFUNC(jff_DIVLU32(RW4 d, RR4 s1, W4 rem));
|
||||
DECLARE_MIDFUNC(jnf_DIVLS32(RW4 d, RR4 s1, W4 rem));
|
||||
DECLARE_MIDFUNC(jff_DIVLS32(RW4 d, RR4 s1, W4 rem));
|
||||
|
||||
// EOR
|
||||
DECLARE_MIDFUNC(jnf_EOR_b_imm(RW1 d, IM8 v));
|
||||
DECLARE_MIDFUNC(jnf_EOR_w_imm(RW2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jnf_EOR_l_imm(RW4 d, IM32 v));
|
||||
DECLARE_MIDFUNC(jnf_EOR_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jnf_EOR_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jnf_EOR_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_EOR_b_imm(RW1 d, IM8 v));
|
||||
DECLARE_MIDFUNC(jff_EOR_w_imm(RW2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jff_EOR_l_imm(RW4 d, IM32 v));
|
||||
DECLARE_MIDFUNC(jff_EOR_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jff_EOR_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jff_EOR_l(RW4 d, RR4 s));
|
||||
|
||||
// EORSR
|
||||
DECLARE_MIDFUNC(jff_EORSR(IM32 s, IM8 x));
|
||||
|
||||
// EXT
|
||||
DECLARE_MIDFUNC(jnf_EXT_b(RW4 d));
|
||||
DECLARE_MIDFUNC(jnf_EXT_w(RW4 d));
|
||||
DECLARE_MIDFUNC(jnf_EXT_l(RW4 d));
|
||||
DECLARE_MIDFUNC(jff_EXT_b(RW4 d));
|
||||
DECLARE_MIDFUNC(jff_EXT_w(RW4 d));
|
||||
DECLARE_MIDFUNC(jff_EXT_l(RW4 d));
|
||||
|
||||
// LSL
|
||||
DECLARE_MIDFUNC(jnf_LSL_b_imm(RW1 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_LSL_w_imm(RW2 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_LSL_l_imm(RW4 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_LSL_b_reg(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_LSL_w_reg(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_LSL_l_reg(RW4 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_LSL_b_imm(RW1 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_LSL_w_imm(RW2 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_LSL_l_imm(RW4 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_LSL_b_reg(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_LSL_w_reg(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_LSL_l_reg(RW4 d, RR4 i));
|
||||
|
||||
// LSLW
|
||||
DECLARE_MIDFUNC(jff_LSLW(RW2 d));
|
||||
DECLARE_MIDFUNC(jnf_LSLW(RW2 d));
|
||||
|
||||
// LSR
|
||||
DECLARE_MIDFUNC(jnf_LSR_b_imm(RW1 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_LSR_w_imm(RW2 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_LSR_l_imm(RW4 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_LSR_b_imm(RW1 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_LSR_w_imm(RW2 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_LSR_l_imm(RW4 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_LSR_b_reg(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_LSR_w_reg(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_LSR_l_reg(RW4 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_LSR_b_reg(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_LSR_w_reg(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_LSR_l_reg(RW4 d, RR4 i));
|
||||
|
||||
// LSRW
|
||||
DECLARE_MIDFUNC(jff_LSRW(RW2 d));
|
||||
DECLARE_MIDFUNC(jnf_LSRW(RW2 d));
|
||||
|
||||
// MOVE
|
||||
DECLARE_MIDFUNC(jnf_MOVE_b_imm(W4 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_MOVE_w_imm(W4 d, IM16 i));
|
||||
DECLARE_MIDFUNC(jnf_MOVE_b(W4 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jnf_MOVE_w(W4 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jnf_MOVE_l(W4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_MOVE_b_imm(W4 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_MOVE_w_imm(W4 d, IM16 i));
|
||||
DECLARE_MIDFUNC(jff_MOVE_l_imm(W4 d, IM32 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));
|
||||
|
||||
// MVMEL
|
||||
DECLARE_MIDFUNC(jnf_MVMEL_w(W4 d, RR4 s, IM8 offset));
|
||||
DECLARE_MIDFUNC(jnf_MVMEL_l(W4 d, RR4 s, IM8 offset));
|
||||
|
||||
// MVMLE
|
||||
DECLARE_MIDFUNC(jnf_MVMLE_w(RR4 d, RR4 s, IM8 offset));
|
||||
DECLARE_MIDFUNC(jnf_MVMLE_l(RR4 d, RR4 s, IM8 offset));
|
||||
|
||||
// MOVE16
|
||||
DECLARE_MIDFUNC(jnf_MOVE16(RR4 d, RR4 s));
|
||||
|
||||
// MOVEA
|
||||
DECLARE_MIDFUNC(jnf_MOVEA_w_imm(W4 d, IM16 v));
|
||||
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_b(RW1 d));
|
||||
DECLARE_MIDFUNC(jnf_NEG_w(RW2 d));
|
||||
DECLARE_MIDFUNC(jnf_NEG_l(RW4 d));
|
||||
DECLARE_MIDFUNC(jff_NEG_b(RW1 d));
|
||||
DECLARE_MIDFUNC(jff_NEG_w(RW2 d));
|
||||
DECLARE_MIDFUNC(jff_NEG_l(RW4 d));
|
||||
|
||||
// NEGX
|
||||
DECLARE_MIDFUNC(jnf_NEGX_b(RW1 d));
|
||||
DECLARE_MIDFUNC(jnf_NEGX_w(RW2 d));
|
||||
DECLARE_MIDFUNC(jnf_NEGX_l(RW4 d));
|
||||
DECLARE_MIDFUNC(jff_NEGX_b(RW1 d));
|
||||
DECLARE_MIDFUNC(jff_NEGX_w(RW2 d));
|
||||
DECLARE_MIDFUNC(jff_NEGX_l(RW4 d));
|
||||
|
||||
// NOT
|
||||
DECLARE_MIDFUNC(jnf_NOT_b(RW1 d));
|
||||
DECLARE_MIDFUNC(jnf_NOT_w(RW2 d));
|
||||
DECLARE_MIDFUNC(jnf_NOT_l(RW4 d));
|
||||
DECLARE_MIDFUNC(jff_NOT_b(RW1 d));
|
||||
DECLARE_MIDFUNC(jff_NOT_w(RW2 d));
|
||||
DECLARE_MIDFUNC(jff_NOT_l(RW4 d));
|
||||
|
||||
// OR
|
||||
DECLARE_MIDFUNC(jnf_OR_b_imm(RW1 d, IM8 v));
|
||||
DECLARE_MIDFUNC(jnf_OR_w_imm(RW2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jnf_OR_l_imm(RW4 d, IM32 v));
|
||||
DECLARE_MIDFUNC(jnf_OR_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jnf_OR_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jnf_OR_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_OR_b_imm(RW1 d, IM8 v));
|
||||
DECLARE_MIDFUNC(jff_OR_w_imm(RW2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jff_OR_l_imm(RW4 d, IM32 v));
|
||||
DECLARE_MIDFUNC(jff_OR_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jff_OR_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jff_OR_l(RW4 d, RR4 s));
|
||||
|
||||
// ORSR
|
||||
DECLARE_MIDFUNC(jff_ORSR(IM32 s, IM8 x));
|
||||
|
||||
// ROL
|
||||
DECLARE_MIDFUNC(jnf_ROL_b_imm(RW1 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_ROL_w_imm(RW2 d, IM16 i));
|
||||
DECLARE_MIDFUNC(jnf_ROL_l_imm(RW4 d, IM32 i));
|
||||
DECLARE_MIDFUNC(jnf_ROL_b(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_ROL_w(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_ROL_l(RW4 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROL_b_imm(RW1 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_ROL_w_imm(RW2 d, IM16 i));
|
||||
DECLARE_MIDFUNC(jff_ROL_l_imm(RW4 d, IM32 i));
|
||||
DECLARE_MIDFUNC(jff_ROL_b(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROL_w(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROL_l(RW4 d, RR4 i));
|
||||
|
||||
// ROLW
|
||||
DECLARE_MIDFUNC(jff_ROLW(RW2 d));
|
||||
DECLARE_MIDFUNC(jnf_ROLW(RW2 d));
|
||||
|
||||
// RORW
|
||||
DECLARE_MIDFUNC(jff_RORW(RW2 d));
|
||||
DECLARE_MIDFUNC(jnf_RORW(RW2 d));
|
||||
|
||||
// ROXL
|
||||
DECLARE_MIDFUNC(jnf_ROXL_b(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_ROXL_w(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_ROXL_l(RW4 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROXL_b(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROXL_w(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROXL_l(RW4 d, RR4 i));
|
||||
|
||||
// ROR
|
||||
DECLARE_MIDFUNC(jnf_ROR_b_imm(RW1 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jnf_ROR_w_imm(RW2 d, IM16 i));
|
||||
DECLARE_MIDFUNC(jnf_ROR_l_imm(RW4 d, IM32 i));
|
||||
DECLARE_MIDFUNC(jnf_ROR_b(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_ROR_w(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_ROR_l(RW4 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROR_b_imm(RW1 d, IM8 i));
|
||||
DECLARE_MIDFUNC(jff_ROR_w_imm(RW2 d, IM16 i));
|
||||
DECLARE_MIDFUNC(jff_ROR_l_imm(RW4 d, IM32 i));
|
||||
DECLARE_MIDFUNC(jff_ROR_b(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROR_w(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROR_l(RW4 d, RR4 i));
|
||||
|
||||
// ROXR
|
||||
DECLARE_MIDFUNC(jnf_ROXR_b(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_ROXR_w(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jnf_ROXR_l(RW4 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROXR_b(RW1 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROXR_w(RW2 d, RR4 i));
|
||||
DECLARE_MIDFUNC(jff_ROXR_l(RW4 d, RR4 i));
|
||||
|
||||
// Scc
|
||||
DECLARE_MIDFUNC(jnf_SCC(W1 d, IM8 cc));
|
||||
|
||||
// SUB
|
||||
DECLARE_MIDFUNC(jnf_SUB_b_imm(RW1 d, IM8 v));
|
||||
DECLARE_MIDFUNC(jnf_SUB_w_imm(RW2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jnf_SUB_l_imm(RW4 d, IM32 v));
|
||||
DECLARE_MIDFUNC(jnf_SUB_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jnf_SUB_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jnf_SUB_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_SUB_b_imm(RW1 d, IM8 v));
|
||||
DECLARE_MIDFUNC(jff_SUB_w_imm(RW2 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jff_SUB_l_imm(RW4 d, IM32 v));
|
||||
DECLARE_MIDFUNC(jff_SUB_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jff_SUB_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jff_SUB_l(RW4 d, RR4 s));
|
||||
|
||||
// SUBA
|
||||
DECLARE_MIDFUNC(jnf_SUBA_w(RW4 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jnf_SUBA_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jnf_SUBA_w_imm(RW4 d, IM16 v));
|
||||
DECLARE_MIDFUNC(jnf_SUBA_l_imm(RW4 d, IM32 v));
|
||||
|
||||
// SUBX
|
||||
DECLARE_MIDFUNC(jnf_SUBX_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jnf_SUBX_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jnf_SUBX_l(RW4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(jff_SUBX_b(RW1 d, RR1 s));
|
||||
DECLARE_MIDFUNC(jff_SUBX_w(RW2 d, RR2 s));
|
||||
DECLARE_MIDFUNC(jff_SUBX_l(RW4 d, RR4 s));
|
||||
|
||||
// SWAP
|
||||
DECLARE_MIDFUNC (jnf_SWAP(RW4 d));
|
||||
DECLARE_MIDFUNC (jff_SWAP(RW4 d));
|
||||
|
||||
// TST
|
||||
DECLARE_MIDFUNC (jff_TST_b_imm(IM8 v));
|
||||
DECLARE_MIDFUNC (jff_TST_w_imm(IM16 v));
|
||||
DECLARE_MIDFUNC (jff_TST_l_imm(IM32 v));
|
||||
DECLARE_MIDFUNC (jff_TST_b(RR1 s));
|
||||
DECLARE_MIDFUNC (jff_TST_w(RR2 s));
|
||||
DECLARE_MIDFUNC (jff_TST_l(RR4 s));
|
||||
|
||||
// Memory access functions
|
||||
DECLARE_MIDFUNC(jnf_MEM_WRITE_OFF_b(RR4 adr, RR4 b));
|
||||
DECLARE_MIDFUNC(jnf_MEM_WRITE_OFF_w(RR4 adr, RR4 w));
|
||||
DECLARE_MIDFUNC(jnf_MEM_WRITE_OFF_l(RR4 adr, RR4 l));
|
||||
DECLARE_MIDFUNC(jnf_MEM_WRITE24_OFF_b(RR4 adr, RR4 b));
|
||||
DECLARE_MIDFUNC(jnf_MEM_WRITE24_OFF_w(RR4 adr, RR4 w));
|
||||
DECLARE_MIDFUNC(jnf_MEM_WRITE24_OFF_l(RR4 adr, RR4 l));
|
||||
|
||||
DECLARE_MIDFUNC(jnf_MEM_READ_OFF_b(W4 d, RR4 adr));
|
||||
DECLARE_MIDFUNC(jnf_MEM_READ_OFF_w(W4 d, RR4 adr));
|
||||
DECLARE_MIDFUNC(jnf_MEM_READ_OFF_l(W4 d, RR4 adr));
|
||||
DECLARE_MIDFUNC(jnf_MEM_READ24_OFF_b(W4 d, RR4 adr));
|
||||
DECLARE_MIDFUNC(jnf_MEM_READ24_OFF_w(W4 d, RR4 adr));
|
||||
DECLARE_MIDFUNC(jnf_MEM_READ24_OFF_l(W4 d, RR4 adr));
|
||||
|
||||
DECLARE_MIDFUNC(jnf_MEM_GETADR_OFF(W4 d, RR4 adr));
|
||||
DECLARE_MIDFUNC(jnf_MEM_GETADR24_OFF(W4 d, RR4 adr));
|
||||
DECLARE_MIDFUNC(jnf_MEM_GETADR_JMP_OFF(W4 d, RR4 adr));
|
||||
|
||||
DECLARE_MIDFUNC(jnf_MEM_READMEMBANK(W4 dest, RR4 adr, IM8 offset));
|
||||
DECLARE_MIDFUNC(jnf_MEM_WRITEMEMBANK(RR4 adr, RR4 source, IM8 offset));
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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,
|
||||
|
||||
// For FBcc, we need some pseudo condition codes
|
||||
NATIVE_CC_F_OGT = 16 + 2,
|
||||
NATIVE_CC_F_OGE = 16 + 3,
|
||||
NATIVE_CC_F_OLT = 16 + 4,
|
||||
NATIVE_CC_F_OLE = 16 + 5,
|
||||
NATIVE_CC_F_OGL = 16 + 6,
|
||||
NATIVE_CC_F_OR = 16 + 7,
|
||||
NATIVE_CC_F_UN = 16 + 8,
|
||||
NATIVE_CC_F_UEQ = 16 + 9,
|
||||
NATIVE_CC_F_UGT = 16 + 10,
|
||||
NATIVE_CC_F_UGE = 16 + 11,
|
||||
NATIVE_CC_F_ULT = 16 + 12,
|
||||
NATIVE_CC_F_ULE = 16 + 13,
|
||||
NATIVE_CC_F_NEVER = 32
|
||||
};
|
||||
|
||||
#endif /* NATIVE_FLAGS_ARM_H */
|
||||
File diff suppressed because it is too large.
Load diff
+239
-36
@@ -59,6 +59,9 @@
|
||||
#define R13_INDEX 13
|
||||
#define R14_INDEX 14
|
||||
#define R15_INDEX 15
|
||||
/* Dedicated register holding natmem_offset, analogous to ARM64's R27 (R_MEMSTART).
|
||||
Used in [R_MEMSTART + m68k_addr] addressing to avoid disp32 sign-extension. */
|
||||
#define R_MEMSTART R15_INDEX
|
||||
#endif
|
||||
/* XXX this has to match X86_Reg8H_Base + 4 */
|
||||
#define AH_INDEX (0x10+4+EAX_INDEX)
|
||||
@@ -111,12 +114,12 @@
|
||||
* since r/m bits 100 implies SIB byte. Simplest fix is to not use these
|
||||
* registers. Also note that these registers are listed in the freescratch
|
||||
* function as well. */
|
||||
uae_s8 always_used[] = { ESP_INDEX, R12_INDEX, -1 };
|
||||
uae_s8 always_used[] = { ESP_INDEX, R12_INDEX, R_MEMSTART, -1 };
|
||||
#else
|
||||
uae_s8 always_used[] = { ESP_INDEX, -1 };
|
||||
#endif
|
||||
uae_s8 can_byte[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1};
|
||||
uae_s8 can_word[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1};
|
||||
uae_s8 can_byte[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,-1};
|
||||
uae_s8 can_word[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,-1};
|
||||
#else
|
||||
uae_s8 always_used[] = { ESP_INDEX, -1 };
|
||||
uae_s8 can_byte[]={0,1,2,3,-1};
|
||||
@@ -198,10 +201,19 @@ static const uae_u8 need_to_preserve[]={0,0,0,1,0,1,1,1};
|
||||
|
||||
#if defined(CPU_x86_64)
|
||||
#define X86_TARGET_64BIT 1
|
||||
/* The address override prefix causes a 5 cycles penalty on Intel Core
|
||||
processors. Another solution would be to decompose the load in an LEA,
|
||||
MOV (to zero-extend), MOV (from memory): is it better? */
|
||||
#define ADDR32 x86_emit_byte(0x67),
|
||||
/* ADDR32 removed: the address override prefix (0x67) caused a 5-cycle penalty
|
||||
on Intel Core processors and forced 32-bit addressing. With the JIT now
|
||||
64-bit pointer-clean, we use the default 64-bit addressing mode which
|
||||
allows RIP-relative access (via _r_X macro) for addresses within 2GB
|
||||
of the JIT code. This is both faster and supports natmem above 4GB.
|
||||
FreeBSD exception: JIT cache is placed by ASLR mmap so RIP-relative
|
||||
encoding of raw 32-bit addresses is incorrect. Restore 0x67 prefix to
|
||||
force 32-bit absolute addressing. The 5-cycle penalty is acceptable. */
|
||||
#if defined(__FreeBSD__)
|
||||
#define ADDR32 x86_emit_byte(0x67),
|
||||
#else
|
||||
#define ADDR32
|
||||
#endif
|
||||
#else
|
||||
#define ADDR32
|
||||
#endif
|
||||
@@ -703,31 +715,74 @@ LOWFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index,
|
||||
ADDR32 MOVBmr(base, baser, index, factor, d);
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor))
|
||||
LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, MEMR base, R4 index, IMM factor))
|
||||
{
|
||||
ADDR32 MOVLmr(base, X86_NOREG, index, factor, d);
|
||||
#if X86_TARGET_64BIT
|
||||
/* x86-64: [disp32 + index*scale] can't reach addresses above +/-2GB.
|
||||
Load 64-bit base into a scratch, then read from [scratch + index*factor].
|
||||
All callers read pointer arrays (baseaddr[], mem_banks[], cache_tags[]),
|
||||
so use MOVQmr (64-bit load) to get the full pointer width.
|
||||
If d == index, we must use a DIFFERENT scratch register so MOVQir
|
||||
doesn't destroy the index value.
|
||||
Compare _rR() to get 4-bit hardware register number regardless of
|
||||
register class (X86_EAX=0x40 and X86_RAX=0x50 are the same register). */
|
||||
if (d == index) {
|
||||
int scratch = (_rR(d) == 0) ? X86_RCX : X86_RAX;
|
||||
PUSHQr(scratch);
|
||||
MOVQir(base, scratch);
|
||||
MOVQmr(0, scratch, index, factor, d);
|
||||
POPQr(scratch);
|
||||
} else {
|
||||
MOVQir(base, d);
|
||||
MOVQmr(0, d, index, factor, d);
|
||||
}
|
||||
#else
|
||||
MOVLmr(base, X86_NOREG, index, factor, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond))
|
||||
LOWFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, MEMR base, R4 index, IMM factor, IMM cond))
|
||||
{
|
||||
#if X86_TARGET_64BIT
|
||||
/* x86-64: [disp32 + index*scale] can't reach 64-bit addresses.
|
||||
Emulate CMOV as: JCC_not skip; MOV d,[base+index*factor]; skip:
|
||||
If d == index, use a scratch register to hold the base (preserved
|
||||
via PUSH/POP) to avoid overwriting the index value. */
|
||||
{
|
||||
uae_s8 *target_p = (uae_s8 *)x86_get_target() + 1;
|
||||
JCCSii(cond^1, 0);
|
||||
if (d == index) {
|
||||
int scratch = (_rR(d) == 0) ? X86_RCX : X86_RAX;
|
||||
PUSHQr(scratch);
|
||||
MOVQir(base, scratch);
|
||||
MOVQmr(0, scratch, index, factor, d);
|
||||
POPQr(scratch);
|
||||
} else {
|
||||
MOVQir(base, d);
|
||||
MOVQmr(0, d, index, factor, d);
|
||||
}
|
||||
*target_p = (uae_s8)(JITPTR x86_get_target() - (JITPTR target_p + 1));
|
||||
}
|
||||
#else
|
||||
if (have_cmov)
|
||||
ADDR32 CMOVLmr(cond, base, X86_NOREG, index, factor, d);
|
||||
CMOVLmr(cond, base, X86_NOREG, index, factor, d);
|
||||
else { /* replacement using branch and mov */
|
||||
uae_s8 *target_p = (uae_s8 *)x86_get_target() + 1;
|
||||
JCCSii(cond^1, 0);
|
||||
ADDR32 MOVLmr(base, X86_NOREG, index, factor, d);
|
||||
MOVLmr(base, X86_NOREG, index, factor, d);
|
||||
*target_p = JITPTR x86_get_target() - (JITPTR target_p + 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond))
|
||||
LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, MEMR mem, IMM cond))
|
||||
{
|
||||
if (have_cmov)
|
||||
CMOVLmr(cond, mem, X86_NOREG, X86_NOREG, 1, d);
|
||||
else { /* replacement using branch and mov */
|
||||
uae_s8 *target_p = (uae_s8 *)x86_get_target() + 1;
|
||||
JCCSii(cond^1, 0);
|
||||
ADDR32 MOVLmr(mem, X86_NOREG, X86_NOREG, 1, d);
|
||||
MOVLmr(mem, X86_NOREG, X86_NOREG, 1, d);
|
||||
*target_p = JITPTR x86_get_target() - (JITPTR target_p + 1);
|
||||
}
|
||||
}
|
||||
@@ -737,6 +792,15 @@ LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset))
|
||||
ADDR32 MOVLmr(offset, s, X86_NOREG, 1, d);
|
||||
}
|
||||
|
||||
#if X86_TARGET_64BIT
|
||||
/* 64-bit register-relative load: d = *(uint64_t*)(s + offset).
|
||||
Used for reading pointer-sized values (e.g., function pointers from addrbank). */
|
||||
static inline void raw_mov_q_rR(int d, int s, int offset)
|
||||
{
|
||||
MOVQmr(offset, s, X86_NOREG, 1, d);
|
||||
}
|
||||
#endif
|
||||
|
||||
LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset))
|
||||
{
|
||||
ADDR32 MOVWmr(offset, s, X86_NOREG, 1, d);
|
||||
@@ -749,17 +813,52 @@ LOWFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset))
|
||||
|
||||
LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset))
|
||||
{
|
||||
#if X86_TARGET_64BIT
|
||||
/* Use LEA+MOV to ensure M68K 32-bit address wrapping.
|
||||
x86-64 [base + index + disp32] computes in 64-bit, so when the
|
||||
M68K register + displacement wraps past 32 bits, the host address
|
||||
is 4GB off. LEA r32,[r64+disp32] truncates to 32 bits (zeroing
|
||||
the upper half), giving the correct M68K effective address.
|
||||
Skip the LEA when offset==0 - the register already holds the
|
||||
full M68K address and no wrapping is possible. */
|
||||
if (offset != 0) {
|
||||
LEALmr(offset, s, X86_NOREG, 1, d);
|
||||
MOVLmr(0, R_MEMSTART, d, 1, d);
|
||||
} else {
|
||||
MOVLmr(0, R_MEMSTART, s, 1, d);
|
||||
}
|
||||
#else
|
||||
ADDR32 MOVLmr(offset, s, X86_NOREG, 1, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset))
|
||||
{
|
||||
#if X86_TARGET_64BIT
|
||||
/* See raw_mov_l_brR for the LEA+MOV rationale. */
|
||||
if (offset != 0) {
|
||||
LEALmr(offset, s, X86_NOREG, 1, d);
|
||||
MOVWmr(0, R_MEMSTART, d, 1, d);
|
||||
} else {
|
||||
MOVWmr(0, R_MEMSTART, s, 1, d);
|
||||
}
|
||||
#else
|
||||
ADDR32 MOVWmr(offset, s, X86_NOREG, 1, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset))
|
||||
{
|
||||
#if X86_TARGET_64BIT
|
||||
if (offset != 0) {
|
||||
LEALmr(offset, s, X86_NOREG, 1, d);
|
||||
MOVBmr(0, R_MEMSTART, d, 1, d);
|
||||
} else {
|
||||
MOVBmr(0, R_MEMSTART, s, 1, d);
|
||||
}
|
||||
#else
|
||||
ADDR32 MOVBmr(offset, s, X86_NOREG, 1, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset))
|
||||
@@ -794,7 +893,13 @@ LOWFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset))
|
||||
|
||||
LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset))
|
||||
{
|
||||
ADDR32 LEALmr(offset, s, X86_NOREG, 1, d);
|
||||
/* On x86-64 without ADDR32: LEA r32, [r64 + disp32_signext].
|
||||
The 32-bit operand size truncates the result correctly even when
|
||||
disp32 sign-extends (e.g. MEMBaseDiff=0x80000000 -> -2GB + addr
|
||||
wraps around in 64-bit, but 32-bit truncation gives correct result).
|
||||
This works for both natmem translation (MEMBaseDiff offset) and
|
||||
general register arithmetic (small offsets like 2, 4, -2, -4). */
|
||||
LEALmr(offset, s, X86_NOREG, 1, d);
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset))
|
||||
@@ -814,17 +919,30 @@ LOWFUNC(NONE,NONE,4,raw_lea_l_r_scaled,(W4 d, R4 index, IMM factor))
|
||||
|
||||
LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset))
|
||||
{
|
||||
#if X86_TARGET_64BIT
|
||||
/* Use [R_MEMSTART + d + offset] - see raw_mov_l_brR comment. */
|
||||
MOVLrm(s, offset, R_MEMSTART, d, 1);
|
||||
#else
|
||||
ADDR32 MOVLrm(s, offset, d, X86_NOREG, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset))
|
||||
{
|
||||
#if X86_TARGET_64BIT
|
||||
MOVWrm(s, offset, R_MEMSTART, d, 1);
|
||||
#else
|
||||
ADDR32 MOVWrm(s, offset, d, X86_NOREG, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset))
|
||||
{
|
||||
#if X86_TARGET_64BIT
|
||||
MOVBrm(s, offset, R_MEMSTART, d, 1);
|
||||
#else
|
||||
ADDR32 MOVBrm(s, offset, d, X86_NOREG, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r))
|
||||
@@ -842,27 +960,27 @@ LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s))
|
||||
MOVLrr(s, d);
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s))
|
||||
LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(MEMW d, R4 s))
|
||||
{
|
||||
ADDR32 MOVLrm(s, d, X86_NOREG, X86_NOREG, 1);
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s))
|
||||
LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(MEMW d, R2 s))
|
||||
{
|
||||
ADDR32 MOVWrm(s, d, X86_NOREG, X86_NOREG, 1);
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s))
|
||||
LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, MEMR s))
|
||||
{
|
||||
ADDR32 MOVWmr(s, X86_NOREG, X86_NOREG, 1, d);
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s))
|
||||
LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(MEMW d, R1 s))
|
||||
{
|
||||
ADDR32 MOVBrm(s, d, X86_NOREG, X86_NOREG, 1);
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s))
|
||||
LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, MEMR s))
|
||||
{
|
||||
ADDR32 MOVBmr(s, X86_NOREG, X86_NOREG, 1, d);
|
||||
}
|
||||
@@ -872,6 +990,40 @@ LOWFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s))
|
||||
MOVLir(s, d);
|
||||
}
|
||||
|
||||
#if X86_TARGET_64BIT
|
||||
/* 64-bit immediate -> register (movabs r64, imm64).
|
||||
Used for PC_P which holds a 64-bit host pointer. */
|
||||
LOWFUNC(NONE,NONE,2,raw_mov_q_ri,(W4 d, uintptr s))
|
||||
{
|
||||
MOVQir(s, d);
|
||||
}
|
||||
|
||||
/* 64-bit value -> memory via scratch register.
|
||||
x86_64 has no MOV [mem], imm64 instruction, so we use
|
||||
movabs rax, imm64; then store via RIP-relative or register-indirect. */
|
||||
static inline void raw_mov_q_mi(uintptr d, uintptr s)
|
||||
{
|
||||
MOVQir(s, X86_RAX); /* movabs rax, imm64 (value to store) */
|
||||
/* Let _r_X handle RIP-relative vs fallback automatically.
|
||||
_r_X sees d as uintptr, computes RIP-relative if within +/-2GB. */
|
||||
MOVQrm(X86_RAX, d, X86_NOREG, X86_NOREG, 1); /* mov [d], rax */
|
||||
}
|
||||
|
||||
/* 64-bit load from memory -> register.
|
||||
Used for reloading PC_P from its home slot. */
|
||||
static inline void raw_mov_q_rm(int d, uintptr s)
|
||||
{
|
||||
MOVQmr(s, X86_NOREG, X86_NOREG, 1, d); /* mov d, [s] via RIP-relative */
|
||||
}
|
||||
|
||||
/* 64-bit store from register -> memory.
|
||||
Used for flushing PC_P from hardware register to its home slot. */
|
||||
static inline void raw_mov_q_mr(uintptr d, int s)
|
||||
{
|
||||
MOVQrm(s, d, X86_NOREG, X86_NOREG, 1); /* mov [d], s via RIP-relative */
|
||||
}
|
||||
#endif
|
||||
|
||||
LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s))
|
||||
{
|
||||
MOVWir(s, d);
|
||||
@@ -887,17 +1039,17 @@ LOWFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s))
|
||||
ADDR32 ADCLim(s, d, X86_NOREG, X86_NOREG, 1);
|
||||
}
|
||||
|
||||
LOWFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s))
|
||||
LOWFUNC(WRITE,RMW,2,raw_add_l_mi,(MEMRW d, IMM s))
|
||||
{
|
||||
ADDR32 ADDLim(s, d, X86_NOREG, X86_NOREG, 1);
|
||||
}
|
||||
|
||||
LOWFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s))
|
||||
LOWFUNC(WRITE,RMW,2,raw_add_w_mi,(MEMRW d, IMM s))
|
||||
{
|
||||
ADDR32 ADDWim(s, d, X86_NOREG, X86_NOREG, 1);
|
||||
}
|
||||
|
||||
LOWFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s))
|
||||
LOWFUNC(WRITE,RMW,2,raw_add_b_mi,(MEMRW d, IMM s))
|
||||
{
|
||||
ADDR32 ADDBim(s, d, X86_NOREG, X86_NOREG, 1);
|
||||
}
|
||||
@@ -922,7 +1074,7 @@ LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s))
|
||||
TESTBrr(s, d);
|
||||
}
|
||||
|
||||
LOWFUNC(WRITE,READ,2,raw_test_b_mi,(IMM d, IMM s))
|
||||
LOWFUNC(WRITE,READ,2,raw_test_b_mi,(MEMR d, IMM s))
|
||||
{
|
||||
ADDR32 TESTBim(s, d, X86_NOREG, X86_NOREG, 1);
|
||||
}
|
||||
@@ -1122,6 +1274,15 @@ LOWFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s))
|
||||
ADDR32 CMPLim(s, d, X86_NOREG, X86_NOREG, 1);
|
||||
}
|
||||
|
||||
#if X86_TARGET_64BIT
|
||||
/* CMP [mem64], r64 - compare 8-byte memory value against 64-bit register.
|
||||
Sets flags from [mem] - reg. */
|
||||
static inline void raw_cmp_q_mr(uintptr mem, R4 r)
|
||||
{
|
||||
CMPQrm(r, mem, X86_NOREG, X86_NOREG, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
LOWFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2))
|
||||
{
|
||||
XCHGLrr(r2, r1);
|
||||
@@ -1168,28 +1329,58 @@ static inline void raw_jmp_r(R4 r)
|
||||
JMPsr(r);
|
||||
}
|
||||
|
||||
static inline void raw_jmp_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m)
|
||||
static inline void raw_jmp_m_indexed(uintptr base, uae_u32 r, uae_u32 m)
|
||||
{
|
||||
ADDR32 JMPsm(base, X86_NOREG, r, m);
|
||||
#if X86_TARGET_64BIT
|
||||
/* x86-64: load 64-bit base into RAX, then JMP [RAX + r*m].
|
||||
Caller must ensure r != EAX_INDEX (currently always true:
|
||||
r = REG_PC_TMP = ECX_INDEX). */
|
||||
MOVQir(base, X86_RAX);
|
||||
JMPsm(0, X86_RAX, r, m);
|
||||
#else
|
||||
JMPsm(base, X86_NOREG, r, m);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void raw_jmp_m(uae_u32 base)
|
||||
static inline void raw_jmp_m(uintptr base)
|
||||
{
|
||||
#if X86_TARGET_64BIT
|
||||
/* x86-64: load 64-bit address into RAX, then JMP [RAX] */
|
||||
MOVQir(base, X86_RAX);
|
||||
JMPsm(0, X86_RAX, X86_NOREG, 1);
|
||||
#else
|
||||
emit_byte(0xff);
|
||||
emit_byte(0x25);
|
||||
emit_long(base);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if X86_TARGET_64BIT
|
||||
static inline void raw_call(uintptr t)
|
||||
{
|
||||
/* 64-bit: load target into scratch register, call via register */
|
||||
MOVQir(t, X86_RAX);
|
||||
CALLsr(X86_RAX);
|
||||
}
|
||||
|
||||
static inline void raw_jmp(uintptr t)
|
||||
{
|
||||
/* 64-bit: load target into scratch register, jump via register */
|
||||
MOVQir(t, X86_RAX);
|
||||
JMPsr(X86_RAX);
|
||||
}
|
||||
#else
|
||||
static inline void raw_call(uae_u32 t)
|
||||
{
|
||||
ADDR32 CALLm(t);
|
||||
CALLm(t);
|
||||
}
|
||||
|
||||
static inline void raw_jmp(uae_u32 t)
|
||||
{
|
||||
ADDR32 JMPm(t);
|
||||
JMPm(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void raw_jcc_l_oponly(int cc)
|
||||
{
|
||||
@@ -1207,22 +1398,22 @@ static inline void raw_jnz_l_oponly(void)
|
||||
raw_jcc_l_oponly(NATIVE_CC_NE);
|
||||
}
|
||||
|
||||
static inline void raw_jl(uae_u32 t)
|
||||
static inline void raw_jl(uintptr t)
|
||||
{
|
||||
raw_jcc_l_oponly(NATIVE_CC_LT);
|
||||
emit_long(t-(uae_u32)JITPTR target-4);
|
||||
emit_long((uae_u32)(t-(uintptr)target-4));
|
||||
}
|
||||
|
||||
static inline void raw_jz(uae_u32 t)
|
||||
static inline void raw_jz(uintptr t)
|
||||
{
|
||||
raw_jz_l_oponly();
|
||||
emit_long(t-(uae_u32)JITPTR target-4);
|
||||
emit_long((uae_u32)(t-(uintptr)target-4));
|
||||
}
|
||||
|
||||
static inline void raw_jnz(uae_u32 t)
|
||||
static inline void raw_jnz(uintptr t)
|
||||
{
|
||||
raw_jnz_l_oponly();
|
||||
emit_long(t-(uae_u32)JITPTR target-4);
|
||||
emit_long((uae_u32)(t-(uintptr)target-4));
|
||||
}
|
||||
|
||||
static inline void raw_jcc_b_oponly(int cc)
|
||||
@@ -2232,12 +2423,24 @@ LOWFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s))
|
||||
}
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base))
|
||||
LOWFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, MEMR base))
|
||||
{
|
||||
#if X86_TARGET_64BIT
|
||||
/* x86-64: [index + disp32] can't reach 64-bit addresses.
|
||||
Load base into RAX, use FLDCW [RAX + index*1] via SIB encoding. */
|
||||
MOVQir(base, X86_RAX);
|
||||
x86_64_prefix(false, false, NULL, &index, NULL);
|
||||
emit_byte(0xd9);
|
||||
/* ModRM: mod=00, reg=5 (FLDCW), rm=100 (SIB follows) */
|
||||
emit_byte(0x2c);
|
||||
/* SIB: scale=00 (x1), index=index_reg, base=RAX (000) */
|
||||
emit_byte((_r(index) << 3) | 0x00);
|
||||
#else
|
||||
x86_64_prefix(true, false, NULL, NULL, &index);
|
||||
emit_byte(0xd9);
|
||||
emit_byte(0xa8 + index);
|
||||
emit_long(base);
|
||||
#endif
|
||||
}
|
||||
|
||||
LOWFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s))
|
||||
|
||||
@@ -1627,6 +1627,7 @@ enum {
|
||||
/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */
|
||||
|
||||
#define LEALmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _O_r_X (0x8d ,_r4(RD) ,MD,MB,MI,MS ))
|
||||
#define LEAQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _O_r_X (0x8d ,_r8(RD) ,MD,MB,MI,MS ))
|
||||
|
||||
#define BSWAPLr(R) (_REXLrr(0, R), _OOr (0x0fc8,_r4(R) ))
|
||||
#define BSWAPQr(R) (_REXQrr(0, R), _OOr (0x0fc8,_r8(R) ))
|
||||
|
||||
+103738
File diff suppressed because it is too large.
Load diff
+27
-31
@@ -1,3 +1,6 @@
|
||||
#if defined(CPU_AARCH64)
|
||||
#include "arm/compemu_arm.h"
|
||||
#else
|
||||
/*
|
||||
* compiler/compemu.h - Public interface and definitions
|
||||
*
|
||||
@@ -46,10 +49,14 @@ typedef uae_u32 uintptr;
|
||||
#define USE_JIT
|
||||
#endif
|
||||
|
||||
#define JITPTR (uae_u32)(uintptr)
|
||||
#define JITPTR (uintptr)
|
||||
|
||||
#ifdef USE_JIT
|
||||
|
||||
/* Allocate memory near the JIT cache / .data segment for RIP-relative access.
|
||||
* options=0 uses anchor-based allocation; options=1 forces low 2GB (MAP_32BIT). */
|
||||
extern void *jit_vm_acquire(uae_u32 size, int options = 0);
|
||||
|
||||
#ifdef JIT_DEBUG
|
||||
/* dump some information (m68k block, x86 block addresses) about the compiler state */
|
||||
extern void compiler_dumpstate(void);
|
||||
@@ -86,7 +93,7 @@ union cacheline {
|
||||
#error implementation in progress
|
||||
#endif
|
||||
|
||||
/* (gb) When on, this option can save save up to 30% compilation time
|
||||
/* (gb) When on, this option can save up to 30% compilation time
|
||||
* when many lazy flushes occur (e.g. apps in MacOS 8.x).
|
||||
*/
|
||||
#define USE_SEPARATE_BIA 1
|
||||
@@ -97,7 +104,7 @@ union cacheline {
|
||||
/* Use code inlining, aka follow-up of constant jumps */
|
||||
#define USE_INLINING 1
|
||||
|
||||
/* Inlining requires the chained checksuming information */
|
||||
/* Inlining requires the chained checksum information */
|
||||
#if USE_INLINING
|
||||
#undef USE_CHECKSUM_INFO
|
||||
#define USE_CHECKSUM_INFO 1
|
||||
@@ -176,6 +183,9 @@ extern void (*flush_icache)(int);
|
||||
#endif
|
||||
extern void alloc_cache(void);
|
||||
extern int check_for_cache_miss(void);
|
||||
#ifdef UAE
|
||||
extern void disable_jit_on_runtime_alloc_failure(const char *what);
|
||||
#endif
|
||||
|
||||
/* JIT FPU compilation */
|
||||
struct jit_disable_opcodes {
|
||||
@@ -253,7 +263,7 @@ extern void* pushall_call_handler;
|
||||
|
||||
typedef struct {
|
||||
uae_u32* mem;
|
||||
uae_u32 val;
|
||||
uintptr val; /* Must be pointer-width: PC_P holds a host pointer (64-bit on x86_64) */
|
||||
uae_u8 is_swapped;
|
||||
uae_u8 status;
|
||||
uae_s8 realreg; /* gb-- realreg can hold -1 */
|
||||
@@ -348,6 +358,7 @@ typedef struct {
|
||||
extern int touchcnt;
|
||||
|
||||
#define IMM uae_s32
|
||||
#define IMPTR uintptr
|
||||
#define RR1 uae_u32
|
||||
#define RR2 uae_u32
|
||||
#define RR4 uae_u32
|
||||
@@ -363,9 +374,9 @@ extern int touchcnt;
|
||||
#define RW1 uae_u32
|
||||
#define RW2 uae_u32
|
||||
#define RW4 uae_u32
|
||||
#define MEMR uae_u32
|
||||
#define MEMW uae_u32
|
||||
#define MEMRW uae_u32
|
||||
#define MEMR uintptr
|
||||
#define MEMW uintptr
|
||||
#define MEMRW uintptr
|
||||
#define MEMPTR uintptr
|
||||
#define MEMPTRR MEMPTR
|
||||
#define MEMPTRW MEMPTR
|
||||
@@ -383,15 +394,6 @@ extern int touchcnt;
|
||||
/* What we expose to the outside */
|
||||
#define DECLARE_MIDFUNC(func) extern void func
|
||||
|
||||
#if defined(CPU_arm)
|
||||
|
||||
#include "compemu_midfunc_arm.h"
|
||||
|
||||
#if defined(USE_JIT2)
|
||||
#include "compemu_midfunc_arm2.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CPU_i386) || defined(CPU_x86_64)
|
||||
#include "compemu_midfunc_x86.h"
|
||||
#endif
|
||||
@@ -419,9 +421,9 @@ extern void set_zero(int r, int tmp);
|
||||
extern int kill_rodent(int r);
|
||||
#define SYNC_PC_OFFSET 100
|
||||
extern void sync_m68k_pc(void);
|
||||
extern uae_u32 get_const(int r);
|
||||
extern uintptr get_const(int r);
|
||||
extern int is_const(int r);
|
||||
extern void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond);
|
||||
extern void register_branch(uintptr not_taken, uintptr taken, uae_u8 cond);
|
||||
void compemu_make_sr(int sr, int tmp);
|
||||
void compemu_enter_super(int sr);
|
||||
void compemu_exc_make_frame(int format, int sr, int currpc, int nr, int tmp);
|
||||
@@ -569,18 +571,12 @@ void jit_abort(const char *format,...) __attribute__((format(printf, 1, 2))) __a
|
||||
|
||||
#endif /* UAE */
|
||||
|
||||
#ifdef CPU_64_BIT
|
||||
static inline uae_u32 check_uae_p32(uintptr address, const char *file, int line)
|
||||
{
|
||||
if (address > (uintptr_t) 0xffffffff) {
|
||||
jit_abort("JIT: 64-bit pointer (0x%llx) at %s:%d (fatal)",
|
||||
(unsigned long long)address, file, line);
|
||||
}
|
||||
return (uae_u32) address;
|
||||
}
|
||||
#define uae_p32(x) (check_uae_p32((uintptr)(x), __FILE__, __LINE__))
|
||||
#else
|
||||
#define uae_p32(x) ((uae_u32)(x))
|
||||
#endif
|
||||
/* x86_64 JIT is now 64-bit pointer-clean. uae_p32() is no longer needed
|
||||
for pointer truncation. It now passes through the full uintptr value.
|
||||
The debug check remains to catch any leftover code that still assumes
|
||||
32-bit pointers where it shouldn't. */
|
||||
#define uae_p32(x) ((uintptr)(x))
|
||||
|
||||
#endif /* COMPEMU_H */
|
||||
|
||||
#endif /* CPU_AARCH64 */
|
||||
@@ -1,3 +1,6 @@
|
||||
#if defined(CPU_AARCH64)
|
||||
#include "arm/compemu_fpp_arm.cpp"
|
||||
#else
|
||||
/*
|
||||
* compiler/compemu_fpp.cpp - Dynamic translation of FPU instructions
|
||||
*
|
||||
@@ -54,7 +57,7 @@
|
||||
//#include "fpu/exceptions.h"
|
||||
//#include "fpu/rounding.h"
|
||||
|
||||
#define DEBUG 0
|
||||
//#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
struct jit_disable_opcodes jit_disable;
|
||||
@@ -616,6 +619,11 @@ void comp_fscc_opp(uae_u32 opcode, uae_u16 extra)
|
||||
{
|
||||
int reg;
|
||||
|
||||
if (!currprefs.compfpu)
|
||||
{
|
||||
FAIL(1);
|
||||
return;
|
||||
}
|
||||
if (jit_disable.fscc)
|
||||
{
|
||||
FAIL(1);
|
||||
@@ -730,14 +738,16 @@ void comp_ftrapcc_opp (uae_u32 /* opcode */, uaecptr /* oldpc */)
|
||||
void comp_fbcc_opp(uae_u32 opcode)
|
||||
{
|
||||
uae_u32 start_68k_offset = m68k_pc_offset;
|
||||
uae_u32 off;
|
||||
uae_u32 v1;
|
||||
uae_u32 v2;
|
||||
uae_s32 off;
|
||||
uintptr v1;
|
||||
uintptr v2;
|
||||
int cc;
|
||||
|
||||
// comp_pc_p is expected to be bound to 32-bit addresses
|
||||
assert((uintptr) comp_pc_p <= 0xffffffffUL);
|
||||
|
||||
if (!currprefs.compfpu)
|
||||
{
|
||||
FAIL(1);
|
||||
return;
|
||||
}
|
||||
if (jit_disable.fbcc)
|
||||
{
|
||||
FAIL(1);
|
||||
@@ -753,9 +763,16 @@ void comp_fbcc_opp(uae_u32 opcode)
|
||||
off = (uae_s32) (uae_s16) comp_get_iword((m68k_pc_offset += 2) - 2);
|
||||
} else
|
||||
{
|
||||
off = comp_get_ilong((m68k_pc_offset += 4) - 4);
|
||||
off = (uae_s32) comp_get_ilong((m68k_pc_offset += 4) - 4);
|
||||
}
|
||||
/* Match the ARM64 FBcc fix: keep the signed displacement separate
|
||||
* from the 64-bit host pointer so non-PC_P set_const paths do not
|
||||
* lose pointer width or zero-extend backward branches. */
|
||||
{
|
||||
uae_s32 displacement = off - (uae_s32)(m68k_pc_offset - start_68k_offset);
|
||||
mov_l_ri(S1, (uintptr)(uae_s32)displacement);
|
||||
add_l_ri(S1, (uintptr)comp_pc_p);
|
||||
}
|
||||
mov_l_ri(S1, JITPTR (comp_pc_p + off - (m68k_pc_offset - start_68k_offset)));
|
||||
mov_l_ri(PC_P, JITPTR comp_pc_p);
|
||||
|
||||
/* Now they are both constant. Might as well fold in m68k_pc_offset */
|
||||
@@ -1112,6 +1129,16 @@ void comp_fpp_opp(uae_u32 opcode, uae_u16 extra)
|
||||
int reg;
|
||||
int src;
|
||||
|
||||
if (special_mem)
|
||||
{
|
||||
FAIL(1);
|
||||
return;
|
||||
}
|
||||
if (!currprefs.compfpu)
|
||||
{
|
||||
FAIL(1);
|
||||
return;
|
||||
}
|
||||
switch ((extra >> 13) & 0x7)
|
||||
{
|
||||
case 1: /* illegal */
|
||||
@@ -2113,3 +2140,5 @@ void comp_fpp_opp(uae_u32 opcode, uae_u16 extra)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CPU_AARCH64 */
|
||||
@@ -342,7 +342,7 @@ MIDFUNC(2,bts_l_rr,(RW4 r, RR4 b))
|
||||
unlock2(b);
|
||||
}
|
||||
|
||||
MIDFUNC(2,mov_l_rm,(W4 d, IMM s))
|
||||
MIDFUNC(2,mov_l_rm,(W4 d, MEMR s))
|
||||
{
|
||||
CLOBBER_MOV;
|
||||
d=writereg(d,4);
|
||||
@@ -359,25 +359,25 @@ MIDFUNC(1,call_r,(RR4 r)) /* Clobbering is implicit */
|
||||
unlock2(r);
|
||||
}
|
||||
|
||||
MIDFUNC(2,sub_l_mi,(IMM d, IMM s))
|
||||
MIDFUNC(2,sub_l_mi,(MEMRW d, IMM s))
|
||||
{
|
||||
CLOBBER_SUB;
|
||||
raw_sub_l_mi(d,s) ;
|
||||
}
|
||||
|
||||
MIDFUNC(2,mov_l_mi,(IMM d, IMM s))
|
||||
MIDFUNC(2,mov_l_mi,(MEMW d, IMM s))
|
||||
{
|
||||
CLOBBER_MOV;
|
||||
raw_mov_l_mi(d,s) ;
|
||||
}
|
||||
|
||||
MIDFUNC(2,mov_w_mi,(IMM d, IMM s))
|
||||
MIDFUNC(2,mov_w_mi,(MEMW d, IMM s))
|
||||
{
|
||||
CLOBBER_MOV;
|
||||
raw_mov_w_mi(d,s) ;
|
||||
}
|
||||
|
||||
MIDFUNC(2,mov_b_mi,(IMM d, IMM s))
|
||||
MIDFUNC(2,mov_b_mi,(MEMW d, IMM s))
|
||||
{
|
||||
CLOBBER_MOV;
|
||||
raw_mov_b_mi(d,s) ;
|
||||
@@ -821,17 +821,24 @@ MIDFUNC(2,setcc_m,(IMM d, IMM cc))
|
||||
|
||||
MIDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc))
|
||||
{
|
||||
int dreg=d;
|
||||
int sreg=s;
|
||||
if (d==s)
|
||||
return;
|
||||
CLOBBER_CMOV;
|
||||
s=readreg(s,4);
|
||||
d=rmw(d,4,4);
|
||||
#if X86_TARGET_64BIT
|
||||
if (dreg == PC_P || sreg == PC_P) {
|
||||
CMOVQrr(cc,s,d);
|
||||
} else
|
||||
#endif
|
||||
raw_cmov_l_rr(d,s,cc);
|
||||
unlock2(s);
|
||||
unlock2(d);
|
||||
}
|
||||
|
||||
MIDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc))
|
||||
MIDFUNC(3,cmov_l_rm,(RW4 d, MEMR s, IMM cc))
|
||||
{
|
||||
CLOBBER_CMOV;
|
||||
d=rmw(d,4,4);
|
||||
@@ -1288,7 +1295,7 @@ MIDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, RR4 baser, RR4 index, IMM factor))
|
||||
}
|
||||
|
||||
/* Read a long from base+factor*index */
|
||||
MIDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor))
|
||||
MIDFUNC(4,mov_l_rm_indexed,(W4 d, MEMR base, RR4 index, IMM factor))
|
||||
{
|
||||
int indexreg=index;
|
||||
|
||||
@@ -1310,10 +1317,15 @@ MIDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor))
|
||||
/* 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 !X86_TARGET_64BIT
|
||||
/* On x86-64, s may hold a natmem-translated address (via get_n_addr)
|
||||
that is unreachable via RIP-relative encoding. Use register-indirect
|
||||
path instead. */
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_l_rm)(d,live.state[s].val+offset);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CLOBBER_MOV;
|
||||
s=readreg(s,4);
|
||||
d=writereg(d,4);
|
||||
@@ -1323,13 +1335,30 @@ MIDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset))
|
||||
unlock2(s);
|
||||
}
|
||||
|
||||
#if X86_TARGET_64BIT
|
||||
/* read a 64-bit (pointer-width) value at the address contained in s+offset and store in d.
|
||||
Used for reading function pointers from addrbank structs on x86-64. */
|
||||
MIDFUNC(3,mov_q_rR,(W4 d, RR4 s, IMM offset))
|
||||
{
|
||||
CLOBBER_MOV;
|
||||
s=readreg(s,4);
|
||||
d=writereg(d,4);
|
||||
|
||||
raw_mov_q_rR(d,s,offset);
|
||||
unlock2(d);
|
||||
unlock2(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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 !X86_TARGET_64BIT
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_w_rm)(d,live.state[s].val+offset);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CLOBBER_MOV;
|
||||
s=readreg(s,4);
|
||||
d=writereg(d,2);
|
||||
@@ -1342,10 +1371,12 @@ MIDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset))
|
||||
/* read the word at the address contained in s+offset and store in d */
|
||||
MIDFUNC(3,mov_b_rR,(W1 d, RR4 s, IMM offset))
|
||||
{
|
||||
#if !X86_TARGET_64BIT
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_b_rm)(d,live.state[s].val+offset);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CLOBBER_MOV;
|
||||
s=readreg(s,4);
|
||||
d=writereg(d,1);
|
||||
@@ -1356,57 +1387,81 @@ MIDFUNC(3,mov_b_rR,(W1 d, RR4 s, IMM offset))
|
||||
}
|
||||
|
||||
/* 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))
|
||||
MIDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMPTR offset))
|
||||
{
|
||||
int sreg=s;
|
||||
#if !X86_TARGET_64BIT
|
||||
/* On x86-64, natmem addresses are unreachable via RIP-relative encoding
|
||||
(natmem at ~0x80000000 is far from JIT code at ~0x7FFxxxxxxxxx).
|
||||
Skip the isconst shortcut; the normal path uses [R_MEMSTART + reg]. */
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_l_rm)(d,live.state[s].val+offset);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CLOBBER_MOV;
|
||||
s=readreg_offset(s,4);
|
||||
#if X86_TARGET_64BIT
|
||||
/* R_MEMSTART already holds natmem_offset, so strip only MEMBaseDiff
|
||||
while preserving the caller's displacement (for example vector
|
||||
offsets such as MEMBaseDiff + trapno * 4). */
|
||||
offset=offset - MEMBaseDiff + get_offset(sreg);
|
||||
#else
|
||||
offset+=get_offset(sreg);
|
||||
#endif
|
||||
d=writereg(d,4);
|
||||
|
||||
raw_mov_l_brR(d,s,offset);
|
||||
raw_mov_l_brR(d,s,(IMM)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))
|
||||
MIDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMPTR offset))
|
||||
{
|
||||
int sreg=s;
|
||||
#if !X86_TARGET_64BIT
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_w_rm)(d,live.state[s].val+offset);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CLOBBER_MOV;
|
||||
remove_offset(d,-1);
|
||||
s=readreg_offset(s,4);
|
||||
#if X86_TARGET_64BIT
|
||||
offset=offset - MEMBaseDiff + get_offset(sreg);
|
||||
#else
|
||||
offset+=get_offset(sreg);
|
||||
#endif
|
||||
d=writereg(d,2);
|
||||
|
||||
raw_mov_w_brR(d,s,offset);
|
||||
raw_mov_w_brR(d,s,(IMM)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))
|
||||
MIDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMPTR offset))
|
||||
{
|
||||
int sreg=s;
|
||||
#if !X86_TARGET_64BIT
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_b_rm)(d,live.state[s].val+offset);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CLOBBER_MOV;
|
||||
remove_offset(d,-1);
|
||||
s=readreg_offset(s,4);
|
||||
#if X86_TARGET_64BIT
|
||||
offset=offset - MEMBaseDiff + get_offset(sreg);
|
||||
#else
|
||||
offset+=get_offset(sreg);
|
||||
#endif
|
||||
d=writereg(d,1);
|
||||
|
||||
raw_mov_b_brR(d,s,offset);
|
||||
raw_mov_b_brR(d,s,(IMM)offset);
|
||||
unlock2(d);
|
||||
unlock2(s);
|
||||
}
|
||||
@@ -1414,10 +1469,12 @@ MIDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset))
|
||||
MIDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset))
|
||||
{
|
||||
int dreg=d;
|
||||
#if !X86_TARGET_64BIT
|
||||
if (isconst(d)) {
|
||||
COMPCALL(mov_l_mi)(live.state[d].val+offset,i);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CLOBBER_MOV;
|
||||
d=readreg_offset(d,4);
|
||||
@@ -1429,10 +1486,12 @@ MIDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset))
|
||||
MIDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset))
|
||||
{
|
||||
int dreg=d;
|
||||
#if !X86_TARGET_64BIT
|
||||
if (isconst(d)) {
|
||||
COMPCALL(mov_w_mi)(live.state[d].val+offset,i);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CLOBBER_MOV;
|
||||
d=readreg_offset(d,4);
|
||||
@@ -1444,10 +1503,12 @@ MIDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset))
|
||||
MIDFUNC(3,mov_b_Ri,(RR4 d, IMM i, IMM offset))
|
||||
{
|
||||
int dreg=d;
|
||||
#if !X86_TARGET_64BIT
|
||||
if (isconst(d)) {
|
||||
COMPCALL(mov_b_mi)(live.state[d].val+offset,i);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CLOBBER_MOV;
|
||||
d=readreg_offset(d,4);
|
||||
@@ -1459,10 +1520,15 @@ MIDFUNC(3,mov_b_Ri,(RR4 d, IMM i, IMM offset))
|
||||
/* Warning! OFFSET is byte sized only! */
|
||||
MIDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset))
|
||||
{
|
||||
#if !X86_TARGET_64BIT
|
||||
/* On x86-64, d may hold a natmem-translated address (via get_n_addr)
|
||||
that is unreachable via RIP-relative encoding. Use register-indirect
|
||||
path instead. */
|
||||
if (isconst(d)) {
|
||||
COMPCALL(mov_l_mr)(live.state[d].val+offset,s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_l_Ri)(d,live.state[s].val,offset);
|
||||
return;
|
||||
@@ -1479,10 +1545,12 @@ MIDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset))
|
||||
|
||||
MIDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset))
|
||||
{
|
||||
#if !X86_TARGET_64BIT
|
||||
if (isconst(d)) {
|
||||
COMPCALL(mov_w_mr)(live.state[d].val+offset,s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_w_Ri)(d,(uae_u16)live.state[s].val,offset);
|
||||
return;
|
||||
@@ -1498,10 +1566,12 @@ MIDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset))
|
||||
|
||||
MIDFUNC(3,mov_b_Rr,(RR4 d, RR1 s, IMM offset))
|
||||
{
|
||||
#if !X86_TARGET_64BIT
|
||||
if (isconst(d)) {
|
||||
COMPCALL(mov_b_mr)(live.state[d].val+offset,s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_b_Ri)(d,(uae_u8)live.state[s].val,offset);
|
||||
return;
|
||||
@@ -1566,56 +1636,74 @@ MIDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor))
|
||||
}
|
||||
|
||||
/* write d to the long at the address contained in s+offset */
|
||||
MIDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset))
|
||||
MIDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMPTR offset))
|
||||
{
|
||||
int dreg=d;
|
||||
#if !X86_TARGET_64BIT
|
||||
if (isconst(d)) {
|
||||
COMPCALL(mov_l_mr)(live.state[d].val+offset,s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CLOBBER_MOV;
|
||||
s=readreg(s,4);
|
||||
d=readreg_offset(d,4);
|
||||
#if X86_TARGET_64BIT
|
||||
offset=offset - MEMBaseDiff + get_offset(dreg);
|
||||
#else
|
||||
offset+=get_offset(dreg);
|
||||
#endif
|
||||
|
||||
raw_mov_l_bRr(d,s,offset);
|
||||
raw_mov_l_bRr(d,s,(IMM)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))
|
||||
MIDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMPTR offset))
|
||||
{
|
||||
int dreg=d;
|
||||
|
||||
#if !X86_TARGET_64BIT
|
||||
if (isconst(d)) {
|
||||
COMPCALL(mov_w_mr)(live.state[d].val+offset,s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CLOBBER_MOV;
|
||||
s=readreg(s,2);
|
||||
d=readreg_offset(d,4);
|
||||
#if X86_TARGET_64BIT
|
||||
offset=offset - MEMBaseDiff + get_offset(dreg);
|
||||
#else
|
||||
offset+=get_offset(dreg);
|
||||
raw_mov_w_bRr(d,s,offset);
|
||||
#endif
|
||||
raw_mov_w_bRr(d,s,(IMM)offset);
|
||||
unlock2(d);
|
||||
unlock2(s);
|
||||
}
|
||||
|
||||
MIDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset))
|
||||
MIDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMPTR offset))
|
||||
{
|
||||
int dreg=d;
|
||||
#if !X86_TARGET_64BIT
|
||||
if (isconst(d)) {
|
||||
COMPCALL(mov_b_mr)(live.state[d].val+offset,s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CLOBBER_MOV;
|
||||
s=readreg(s,1);
|
||||
d=readreg_offset(d,4);
|
||||
#if X86_TARGET_64BIT
|
||||
offset=offset - MEMBaseDiff + get_offset(dreg);
|
||||
#else
|
||||
offset+=get_offset(dreg);
|
||||
raw_mov_b_bRr(d,s,offset);
|
||||
#endif
|
||||
raw_mov_b_bRr(d,s,(IMM)offset);
|
||||
unlock2(d);
|
||||
unlock2(s);
|
||||
}
|
||||
@@ -1660,9 +1748,29 @@ MIDFUNC(2,mov_l_rr,(W4 d, RR4 s))
|
||||
return;
|
||||
}
|
||||
if (isconst(s)) {
|
||||
#if X86_TARGET_64BIT
|
||||
if (s == PC_P) {
|
||||
CLOBBER_MOV;
|
||||
d=writereg(d,4);
|
||||
raw_mov_q_ri(d,live.state[s].val);
|
||||
unlock2(d);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
COMPCALL(mov_l_ri)(d,live.state[s].val);
|
||||
return;
|
||||
}
|
||||
#if X86_TARGET_64BIT
|
||||
if (d == PC_P || s == PC_P) {
|
||||
CLOBBER_MOV;
|
||||
s=readreg(s,4);
|
||||
d=writereg(d,4);
|
||||
MOVQrr(s,d);
|
||||
unlock2(d);
|
||||
unlock2(s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
olds=s;
|
||||
disassociate(d);
|
||||
s=readreg_offset(s,4);
|
||||
@@ -1680,8 +1788,22 @@ MIDFUNC(2,mov_l_rr,(W4 d, RR4 s))
|
||||
unlock2(s);
|
||||
}
|
||||
|
||||
MIDFUNC(2,mov_l_mr,(IMM d, RR4 s))
|
||||
MIDFUNC(2,mov_l_mr,(MEMW d, RR4 s))
|
||||
{
|
||||
#if X86_TARGET_64BIT
|
||||
if (s == PC_P) {
|
||||
/* PC_P holds a 64-bit host pointer and needs allocator-aware scratch use. */
|
||||
if (isconst(s)) {
|
||||
store_const_q_mi(d, live.state[s].val);
|
||||
} else {
|
||||
CLOBBER_MOV;
|
||||
s=readreg(s,4);
|
||||
raw_mov_q_mr(d, s);
|
||||
unlock2(s);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_l_mi)(d,live.state[s].val);
|
||||
return;
|
||||
@@ -1694,7 +1816,7 @@ MIDFUNC(2,mov_l_mr,(IMM d, RR4 s))
|
||||
}
|
||||
|
||||
|
||||
MIDFUNC(2,mov_w_mr,(IMM d, RR2 s))
|
||||
MIDFUNC(2,mov_w_mr,(MEMW d, RR2 s))
|
||||
{
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_w_mi)(d,(uae_u16)live.state[s].val);
|
||||
@@ -1707,7 +1829,7 @@ MIDFUNC(2,mov_w_mr,(IMM d, RR2 s))
|
||||
unlock2(s);
|
||||
}
|
||||
|
||||
MIDFUNC(2,mov_w_rm,(W2 d, IMM s))
|
||||
MIDFUNC(2,mov_w_rm,(W2 d, MEMR s))
|
||||
{
|
||||
CLOBBER_MOV;
|
||||
d=writereg(d,2);
|
||||
@@ -1716,7 +1838,7 @@ MIDFUNC(2,mov_w_rm,(W2 d, IMM s))
|
||||
unlock2(d);
|
||||
}
|
||||
|
||||
MIDFUNC(2,mov_b_mr,(IMM d, RR1 s))
|
||||
MIDFUNC(2,mov_b_mr,(MEMW d, RR1 s))
|
||||
{
|
||||
if (isconst(s)) {
|
||||
COMPCALL(mov_b_mi)(d,(uae_u8)live.state[s].val);
|
||||
@@ -1730,7 +1852,7 @@ MIDFUNC(2,mov_b_mr,(IMM d, RR1 s))
|
||||
unlock2(s);
|
||||
}
|
||||
|
||||
MIDFUNC(2,mov_b_rm,(W1 d, IMM s))
|
||||
MIDFUNC(2,mov_b_rm,(W1 d, MEMR s))
|
||||
{
|
||||
CLOBBER_MOV;
|
||||
d=writereg(d,1);
|
||||
@@ -1739,7 +1861,7 @@ MIDFUNC(2,mov_b_rm,(W1 d, IMM s))
|
||||
unlock2(d);
|
||||
}
|
||||
|
||||
MIDFUNC(2,mov_l_ri,(W4 d, IMM s))
|
||||
MIDFUNC(2,mov_l_ri,(W4 d, IMPTR s))
|
||||
{
|
||||
set_const(d,s);
|
||||
return;
|
||||
@@ -1763,19 +1885,19 @@ MIDFUNC(2,mov_b_ri,(W1 d, IMM s))
|
||||
unlock2(d);
|
||||
}
|
||||
|
||||
MIDFUNC(2,add_l_mi,(IMM d, IMM s))
|
||||
MIDFUNC(2,add_l_mi,(MEMRW d, IMM s))
|
||||
{
|
||||
CLOBBER_ADD;
|
||||
raw_add_l_mi(d,s);
|
||||
}
|
||||
|
||||
MIDFUNC(2,add_w_mi,(IMM d, IMM s))
|
||||
MIDFUNC(2,add_w_mi,(MEMRW d, IMM s))
|
||||
{
|
||||
CLOBBER_ADD;
|
||||
raw_add_w_mi(d,s);
|
||||
}
|
||||
|
||||
MIDFUNC(2,add_b_mi,(IMM d, IMM s))
|
||||
MIDFUNC(2,add_b_mi,(MEMRW d, IMM s))
|
||||
{
|
||||
CLOBBER_ADD;
|
||||
raw_add_b_mi(d,s);
|
||||
@@ -1823,7 +1945,7 @@ MIDFUNC(2,test_b_rr,(RR1 d, RR1 s))
|
||||
unlock2(s);
|
||||
}
|
||||
|
||||
MIDFUNC(2,test_b_mi,(IMM d, IMM s))
|
||||
MIDFUNC(2,test_b_mi,(MEMR d, IMM s))
|
||||
{
|
||||
CLOBBER_TEST;
|
||||
raw_test_b_mi(d,s);
|
||||
@@ -1972,6 +2094,7 @@ MIDFUNC(2,adc_b,(RW1 d, RR1 s))
|
||||
|
||||
MIDFUNC(2,add_l,(RW4 d, RR4 s))
|
||||
{
|
||||
int dreg=d;
|
||||
if (isconst(s)) {
|
||||
COMPCALL(add_l_ri)(d,live.state[s].val);
|
||||
return;
|
||||
@@ -1981,6 +2104,14 @@ MIDFUNC(2,add_l,(RW4 d, RR4 s))
|
||||
s=readreg(s,4);
|
||||
d=rmw(d,4,4);
|
||||
|
||||
#if X86_TARGET_64BIT
|
||||
if (dreg == PC_P) {
|
||||
const int scratch = get_unlocked_scratch_nreg_excluding(d, s);
|
||||
free_nreg(scratch);
|
||||
raw_sign_extend_32_rr(scratch,s);
|
||||
ADDQrr(scratch,d);
|
||||
} else
|
||||
#endif
|
||||
raw_add_l(d,s);
|
||||
|
||||
unlock2(d);
|
||||
@@ -2066,23 +2197,56 @@ MIDFUNC(2,sub_b_ri,(RW1 d, IMM i))
|
||||
unlock2(d);
|
||||
}
|
||||
|
||||
MIDFUNC(2,add_l_ri,(RW4 d, IMM i))
|
||||
#if X86_TARGET_64BIT
|
||||
static inline uintptr sign_extend_pc_disp(uintptr i)
|
||||
{
|
||||
if (i <= static_cast<uintptr>(0xffffffffULL) && (i & static_cast<uintptr>(0x80000000ULL)))
|
||||
return static_cast<uintptr>(static_cast<uae_s64>(static_cast<uae_s32>(i)));
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
MIDFUNC(2,add_l_ri,(RW4 d, IMPTR i))
|
||||
{
|
||||
int dreg=d;
|
||||
if (!i && !needflags)
|
||||
return;
|
||||
if (isconst(d) && !needflags) {
|
||||
live.state[d].val+=i;
|
||||
#if X86_TARGET_64BIT
|
||||
if (d == PC_P) {
|
||||
live.state[d].val += sign_extend_pc_disp(static_cast<uintptr>(i));
|
||||
} else if (i > static_cast<IMPTR>(0xffffffffULL) ||
|
||||
live.state[d].val > static_cast<uintptr>(0xffffffffULL)) {
|
||||
uintptr val = live.state[d].val;
|
||||
if (val <= static_cast<uintptr>(0xffffffffULL) &&
|
||||
i > static_cast<IMPTR>(0xffffffffULL)) {
|
||||
val = static_cast<uintptr>(static_cast<uae_s64>(static_cast<uae_s32>(val)));
|
||||
}
|
||||
live.state[d].val = val + i;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
live.state[d].val=static_cast<uae_u32>(live.state[d].val + i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#if USE_OFFSET
|
||||
if (!needflags) {
|
||||
add_offset(d,i);
|
||||
add_offset(d,(uintptr)i);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CLOBBER_ADD;
|
||||
d=rmw(d,4,4);
|
||||
raw_add_l_ri(d,i);
|
||||
#if X86_TARGET_64BIT
|
||||
if (dreg == PC_P) {
|
||||
x86_add_q_ri_ptr(d, sign_extend_pc_disp(static_cast<uintptr>(i)));
|
||||
} else if (i > static_cast<IMPTR>(0xffffffffULL)) {
|
||||
raw_sign_extend_32_rr(d,d);
|
||||
x86_add_q_ri_ptr(d, static_cast<uintptr>(i));
|
||||
} else
|
||||
#endif
|
||||
raw_add_l_ri(d,(IMM)i);
|
||||
unlock2(d);
|
||||
}
|
||||
|
||||
@@ -2516,7 +2680,7 @@ MIDFUNC(2,fmov_rr,(FW d, FR s))
|
||||
#endif
|
||||
}
|
||||
|
||||
MIDFUNC(2,fldcw_m_indexed,(RR4 index, IMM base))
|
||||
MIDFUNC(2,fldcw_m_indexed,(RR4 index, MEMR base))
|
||||
{
|
||||
index=readreg(index,4);
|
||||
|
||||
|
||||
@@ -39,12 +39,12 @@ DECLARE_MIDFUNC(bts_l_ri(RW4 r, IMM i));
|
||||
DECLARE_MIDFUNC(bts_l_rr(RW4 r, RR4 b));
|
||||
DECLARE_MIDFUNC(btr_l_ri(RW4 r, IMM i));
|
||||
DECLARE_MIDFUNC(btr_l_rr(RW4 r, RR4 b));
|
||||
DECLARE_MIDFUNC(mov_l_rm(W4 d, IMM s));
|
||||
DECLARE_MIDFUNC(mov_l_rm(W4 d, MEMR s));
|
||||
DECLARE_MIDFUNC(call_r(RR4 r));
|
||||
DECLARE_MIDFUNC(sub_l_mi(IMM d, IMM s));
|
||||
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(sub_l_mi(MEMRW d, IMM s));
|
||||
DECLARE_MIDFUNC(mov_l_mi(MEMW d, IMM s));
|
||||
DECLARE_MIDFUNC(mov_w_mi(MEMW d, IMM s));
|
||||
DECLARE_MIDFUNC(mov_b_mi(MEMW 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_ri(RW4 r, IMM i));
|
||||
@@ -78,7 +78,7 @@ 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(cmov_l_rm(RW4 d, IMM s, IMM cc));
|
||||
DECLARE_MIDFUNC(cmov_l_rm(RW4 d, MEMR s, IMM cc));
|
||||
DECLARE_MIDFUNC(bsf_l_rr(W4 d, RR4 s));
|
||||
DECLARE_MIDFUNC(pop_m(IMM d));
|
||||
DECLARE_MIDFUNC(push_m(IMM d));
|
||||
@@ -111,13 +111,16 @@ DECLARE_MIDFUNC(mov_b_bmrr_indexed(IMM base, RR4 baser, RR4 index, IMM factor, R
|
||||
DECLARE_MIDFUNC(mov_l_brrm_indexed(W4 d, IMM base, RR4 baser, RR4 index, IMM factor));
|
||||
DECLARE_MIDFUNC(mov_w_brrm_indexed(W2 d, IMM base, RR4 baser, RR4 index, IMM factor));
|
||||
DECLARE_MIDFUNC(mov_b_brrm_indexed(W1 d, IMM base, RR4 baser, RR4 index, IMM factor));
|
||||
DECLARE_MIDFUNC(mov_l_rm_indexed(W4 d, IMM base, RR4 index, IMM factor));
|
||||
DECLARE_MIDFUNC(mov_l_rm_indexed(W4 d, MEMR base, RR4 index, IMM factor));
|
||||
DECLARE_MIDFUNC(mov_l_rR(W4 d, RR4 s, IMM offset));
|
||||
#if X86_TARGET_64BIT
|
||||
DECLARE_MIDFUNC(mov_q_rR(W4 d, RR4 s, IMM offset));
|
||||
#endif
|
||||
DECLARE_MIDFUNC(mov_w_rR(W2 d, RR4 s, IMM offset));
|
||||
DECLARE_MIDFUNC(mov_b_rR(W1 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_brR(W4 d, RR4 s, IMPTR offset));
|
||||
DECLARE_MIDFUNC(mov_w_brR(W2 d, RR4 s, IMPTR offset));
|
||||
DECLARE_MIDFUNC(mov_b_brR(W1 d, RR4 s, IMPTR 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_b_Ri(RR4 d, IMM i, IMM offset));
|
||||
@@ -127,28 +130,28 @@ DECLARE_MIDFUNC(mov_b_Rr(RR4 d, RR1 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(mov_l_bRr(RR4 d, RR4 s, IMPTR offset));
|
||||
DECLARE_MIDFUNC(mov_w_bRr(RR4 d, RR2 s, IMPTR offset));
|
||||
DECLARE_MIDFUNC(mov_b_bRr(RR4 d, RR1 s, IMPTR 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_l_mr(MEMW d, RR4 s));
|
||||
DECLARE_MIDFUNC(mov_w_mr(MEMW d, RR2 s));
|
||||
DECLARE_MIDFUNC(mov_w_rm(W2 d, MEMR s));
|
||||
DECLARE_MIDFUNC(mov_b_mr(MEMW d, RR1 s));
|
||||
DECLARE_MIDFUNC(mov_b_rm(W1 d, MEMR s));
|
||||
DECLARE_MIDFUNC(mov_l_ri(W4 d, IMPTR s));
|
||||
DECLARE_MIDFUNC(mov_w_ri(W2 d, IMM s));
|
||||
DECLARE_MIDFUNC(mov_b_ri(W1 d, IMM s));
|
||||
DECLARE_MIDFUNC(add_l_mi(IMM d, IMM s));
|
||||
DECLARE_MIDFUNC(add_w_mi(IMM d, IMM s));
|
||||
DECLARE_MIDFUNC(add_b_mi(IMM d, IMM s));
|
||||
DECLARE_MIDFUNC(add_l_mi(MEMRW d, IMM s));
|
||||
DECLARE_MIDFUNC(add_w_mi(MEMRW d, IMM s));
|
||||
DECLARE_MIDFUNC(add_b_mi(MEMRW 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(test_b_mi(IMM d, IMM s));
|
||||
DECLARE_MIDFUNC(test_b_mi(MEMR d, IMM 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));
|
||||
@@ -167,7 +170,7 @@ 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_l_ri(RW4 d, IMPTR 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));
|
||||
@@ -217,7 +220,7 @@ DECLARE_MIDFUNC(fcut_r(FRW r));
|
||||
DECLARE_MIDFUNC(fmov_ext_mr(MEMPTRW m, FR r));
|
||||
DECLARE_MIDFUNC(fmov_ext_rm(FW r, MEMPTRR m));
|
||||
DECLARE_MIDFUNC(fmov_rr(FW d, FR s));
|
||||
DECLARE_MIDFUNC(fldcw_m_indexed(RR4 index, IMM base));
|
||||
DECLARE_MIDFUNC(fldcw_m_indexed(RR4 index, MEMR base));
|
||||
DECLARE_MIDFUNC(ftst_r(FR r));
|
||||
DECLARE_MIDFUNC(dont_care_fflags(void));
|
||||
DECLARE_MIDFUNC(fsqrt_rr(FW d, FR s));
|
||||
|
||||
+1113
-84
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -80,6 +80,7 @@ int candirect = -1;
|
||||
int special_mem, special_mem_default;
|
||||
/* do not use get_n_addr */
|
||||
int jit_n_addr_unsafe;
|
||||
int jit_n_addr_bank_unsafe;
|
||||
#endif
|
||||
|
||||
#ifdef NATMEM_OFFSET
|
||||
@@ -1910,7 +1911,12 @@ static void map_banks2 (addrbank *bank, int start, int size, int realsize, int q
|
||||
|
||||
#ifdef JIT
|
||||
if ((bank->jit_read_flag | bank->jit_write_flag) & S_N_ADDR) {
|
||||
if (!jit_n_addr_bank_unsafe) {
|
||||
write_log(_T("JIT: jit_n_addr_unsafe enabled by bank '%s' at %08x (r=%d w=%d)\n"),
|
||||
bank->name ? bank->name : _T("<unnamed>"), start << 16, bank->jit_read_flag, bank->jit_write_flag);
|
||||
}
|
||||
jit_n_addr_unsafe = 1;
|
||||
jit_n_addr_bank_unsafe = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ extern void memory_reset(void);
|
||||
extern int special_mem;
|
||||
extern int special_mem_default;
|
||||
extern int jit_n_addr_unsafe;
|
||||
extern int jit_n_addr_bank_unsafe;
|
||||
#endif
|
||||
|
||||
#define S_READ 1
|
||||
|
||||
@@ -6082,6 +6082,14 @@ void execute_normal(void)
|
||||
/* Take note: This is the do-it-normal loop */
|
||||
r->opcode = get_jit_opcode();
|
||||
|
||||
#if defined(JIT) && defined(CPU_x86_64)
|
||||
/* High x86-64 natmem uses jit_n_addr_unsafe for pointer-clean
|
||||
* codegen decisions. Keep pc_hist.specmem reserved for real
|
||||
* special-bank flags. */
|
||||
if (jit_n_addr_unsafe && !jit_n_addr_bank_unsafe) {
|
||||
special_mem = 0;
|
||||
} else
|
||||
#endif
|
||||
special_mem = special_mem_default;
|
||||
pc_hist[blocklen].location = (uae_u16*)r->pc_p;
|
||||
|
||||
|
||||
@@ -39,10 +39,8 @@
|
||||
|
||||
#ifndef UAE_MINI
|
||||
|
||||
#if !defined(_M_ARM64) && !defined(_M_ARM64EC) && !defined(__aarch64__)
|
||||
//#define JIT /* JIT compiler support */
|
||||
//#define USE_JIT_FPU
|
||||
#endif
|
||||
|
||||
#define DEBUGGER
|
||||
//#define GDBSERVER
|
||||
|
||||
+2
-1
@@ -50,7 +50,8 @@ using namespace std;
|
||||
#define UAE
|
||||
#endif
|
||||
|
||||
#if defined(_M_ARM64) || defined(_M_ARM64EC) || defined(__aarch64__)
|
||||
#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
|
||||
#define CPU_AARCH64 1
|
||||
#define CPU_arm 1
|
||||
#define ARM_ASSEMBLY 1
|
||||
#define CPU_64_BIT 1
|
||||
|
||||
Reference in new issue
Block a user