drc: starting arm64 support
authornotaz <notasas@gmail.com>
Tue, 2 Nov 2021 23:08:49 +0000 (23:08 +0000)
committernotaz <notasas@gmail.com>
Sun, 14 Nov 2021 00:05:06 +0000 (02:05 +0200)
mostly stubs only for now

12 files changed:
Makefile
libpcsxcore/new_dynarec/assem_arm.c
libpcsxcore/new_dynarec/assem_arm64.c [new file with mode: 0644]
libpcsxcore/new_dynarec/assem_arm64.h [new file with mode: 0644]
libpcsxcore/new_dynarec/emu_if.c
libpcsxcore/new_dynarec/emu_if.h
libpcsxcore/new_dynarec/linkage_arm.S
libpcsxcore/new_dynarec/linkage_arm64.S [new file with mode: 0644]
libpcsxcore/new_dynarec/new_dynarec.c
libpcsxcore/new_dynarec/new_dynarec.h
libpcsxcore/new_dynarec/new_dynarec_config.h
libpcsxcore/new_dynarec/pcsxmem.c

index f8d1dc1..3f4b87d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -56,8 +56,15 @@ libpcsxcore/psxbios.o: CFLAGS += -Wno-nonnull
 
 # dynarec
 ifeq "$(USE_DYNAREC)" "1"
-OBJS += libpcsxcore/new_dynarec/new_dynarec.o libpcsxcore/new_dynarec/linkage_arm.o
+OBJS += libpcsxcore/new_dynarec/new_dynarec.o
 OBJS += libpcsxcore/new_dynarec/pcsxmem.o
+ ifeq "$(ARCH)" "arm"
+ OBJS += libpcsxcore/new_dynarec/linkage_arm.o
+ else ifeq "$(ARCH)" "aarch64"
+ OBJS += libpcsxcore/new_dynarec/linkage_arm64.o
+ else
+ $(error no dynarec support for architecture $(ARCH))
+ endif
 else
 CFLAGS += -DDRC_DISABLE
 endif
index 4953faa..d0b1bd7 100644 (file)
@@ -55,7 +55,6 @@ extern int pcaddr;
 extern int pending_exception;
 extern int branch_target;
 extern uint64_t readmem_dword;
-extern void *dynarec_local;
 extern u_int mini_ht[32][2];
 
 void indirect_jump_indexed();
@@ -1141,6 +1140,11 @@ static void emit_jmpreg(u_int r)
   output_w32(0xe1a00000|rd_rn_rm(15,0,r));
 }
 
+static void emit_ret(void)
+{
+  emit_jmpreg(14);
+}
+
 static void emit_readword_indexed(int offset, int rs, int rt)
 {
   assert(offset>-4096&&offset<4096);
diff --git a/libpcsxcore/new_dynarec/assem_arm64.c b/libpcsxcore/new_dynarec/assem_arm64.c
new file mode 100644 (file)
index 0000000..f9c837e
--- /dev/null
@@ -0,0 +1,1158 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus/PCSX - assem_arm64.c                                      *
+ *   Copyright (C) 2009-2011 Ari64                                         *
+ *   Copyright (C) 2010-2021 notaz                                         *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "arm_features.h"
+
+#if   defined(BASE_ADDR_FIXED)
+#elif defined(BASE_ADDR_DYNAMIC)
+u_char *translation_cache;
+#else
+u_char translation_cache[1 << TARGET_SIZE_2] __attribute__((aligned(4096)));
+#endif
+
+#define CALLER_SAVE_REGS 0x0007ffff
+
+#define unused __attribute__((unused))
+
+extern int cycle_count;
+extern int last_count;
+extern int pcaddr;
+extern int pending_exception;
+extern int branch_target;
+extern u_int mini_ht[32][2];
+
+static u_int needs_clear_cache[1<<(TARGET_SIZE_2-17)];
+
+//void indirect_jump_indexed();
+//void indirect_jump();
+void do_interrupt();
+//void jump_vaddr_r0();
+
+void * const jump_vaddr_reg[32];
+
+/* Linker */
+
+static void set_jump_target(void *addr, void *target_)
+{
+  assert(0);
+}
+
+// from a pointer to external jump stub (which was produced by emit_extjump2)
+// find where the jumping insn is
+static void *find_extjump_insn(void *stub)
+{
+  assert(0);
+  return NULL;
+}
+
+// find where external branch is liked to using addr of it's stub:
+// get address that insn one after stub loads (dyna_linker arg1),
+// treat it as a pointer to branch insn,
+// return addr where that branch jumps to
+static void *get_pointer(void *stub)
+{
+  //printf("get_pointer(%x)\n",(int)stub);
+  assert(0);
+  return NULL;
+}
+
+// Find the "clean" entry point from a "dirty" entry point
+// by skipping past the call to verify_code
+static void *get_clean_addr(void *addr)
+{
+  assert(0);
+  return NULL;
+}
+
+static int verify_dirty(u_int *ptr)
+{
+  assert(0);
+  return 0;
+}
+
+// This doesn't necessarily find all clean entry points, just
+// guarantees that it's not dirty
+static int isclean(void *addr)
+{
+  assert(0);
+  return 0;
+}
+
+// get source that block at addr was compiled from (host pointers)
+static void get_bounds(void *addr, u_char **start, u_char **end)
+{
+  assert(0);
+}
+
+// Allocate a specific ARM register.
+static void alloc_arm_reg(struct regstat *cur,int i,signed char reg,int hr)
+{
+  int n;
+  int dirty=0;
+
+  // see if it's already allocated (and dealloc it)
+  for(n=0;n<HOST_REGS;n++)
+  {
+    if(n!=EXCLUDE_REG&&cur->regmap[n]==reg) {
+      dirty=(cur->dirty>>n)&1;
+      cur->regmap[n]=-1;
+    }
+  }
+
+  cur->regmap[hr]=reg;
+  cur->dirty&=~(1<<hr);
+  cur->dirty|=dirty<<hr;
+  cur->isconst&=~(1<<hr);
+}
+
+// Alloc cycle count into dedicated register
+static void alloc_cc(struct regstat *cur,int i)
+{
+  alloc_arm_reg(cur,i,CCREG,HOST_CCREG);
+}
+
+/* Special alloc */
+
+
+/* Assembler */
+
+static unused const char *regname[32] = {
+  "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6", "r7",
+  "r8",  "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+ "ip0", "ip1", "r18", "r19", "r20", "r21", "r22", "r23"
+ "r24", "r25", "r26", "r27", "r28",  "fp",  "lr",  "sp"
+};
+
+#pragma GCC diagnostic ignored "-Wunused-function"
+static void output_w32(u_int word)
+{
+  *((u_int *)out) = word;
+  out += 4;
+}
+
+static u_int rm_rn_rd(u_int rm, u_int rn, u_int rd)
+{
+  assert(rm < 31);
+  assert(rn < 31);
+  assert(rd < 31);
+  return (rm << 16) | (rn << 5) | rd;
+}
+
+static u_int imm16_rd(u_int imm16, u_int rd)
+{
+  assert(imm16 < 0x10000);
+  assert(rd < 31);
+  return (imm16 << 5) | rd;
+}
+
+static u_int genjmp(u_char *addr)
+{
+  intptr_t offset = addr - out;
+  if (offset < -134217728 || offset > 134217727) {
+    if ((uintptr_t)addr > 2) {
+      SysPrintf("%s: out of range: %08x\n", __func__, offset);
+      exit(1);
+    }
+    return 0;
+  }
+  return ((u_int)offset >> 2) & 0x01ffffff;
+}
+
+static u_int genjmpcc(u_char *addr)
+{
+  intptr_t offset = addr - out;
+  if (offset < -1048576 || offset > 1048572) {
+    if ((uintptr_t)addr > 2) {
+      SysPrintf("%s: out of range: %08x\n", __func__, offset);
+      exit(1);
+    }
+    return 0;
+  }
+  return ((u_int)offset >> 2) & 0xfffff;
+}
+
+static void emit_mov(u_int rs, u_int rt)
+{
+  assem_debug("mov %s,%s\n",regname[rt],regname[rs]);
+  assert(0);
+}
+
+static void emit_movs(u_int rs, u_int rt)
+{
+  assem_debug("mov %s,%s\n",regname[rt],regname[rs]);
+  assert(0);
+}
+
+static void emit_add(u_int rs1,u_int rs2,u_int rt)
+{
+  assem_debug("add %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_sbc(u_int rs1,u_int rs2,u_int rt)
+{
+  assem_debug("sbc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_neg(u_int rs, u_int rt)
+{
+  assem_debug("rsb %s,%s,#0\n",regname[rt],regname[rs]);
+  assert(0);
+}
+
+static void emit_negs(u_int rs, u_int rt)
+{
+  assem_debug("rsbs %s,%s,#0\n",regname[rt],regname[rs]);
+  assert(0);
+}
+
+static void emit_sub(u_int rs1,u_int rs2,u_int rt)
+{
+  assem_debug("sub %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_subs(u_int rs1,u_int rs2,u_int rt)
+{
+  assem_debug("subs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_zeroreg(u_int rt)
+{
+  assem_debug("mov %s,#0\n",regname[rt]);
+  assert(0);
+}
+
+static void emit_movw(u_int imm,u_int rt)
+{
+  assert(imm<65536);
+  assem_debug("movw %s,#%d (0x%x)\n",regname[rt],imm,imm);
+  assert(0);
+}
+
+static void emit_movt(u_int imm,u_int rt)
+{
+  assem_debug("movt %s,#%d (0x%x)\n",regname[rt],imm&0xffff0000,imm&0xffff0000);
+  assert(0);
+}
+
+static void emit_movimm(u_int imm, u_int rt)
+{
+  assem_debug("mov %s,#%x\n", regname[rt], imm);
+  if      ((imm & 0xffff0000) == 0)
+    output_w32(0x52800000 | imm16_rd(imm, rt));
+  else if ((imm & 0xffff0000) == 0xffff0000)
+    assert(0);
+  else {
+    output_w32(0x52800000 | imm16_rd(imm & 0xffff, rt));
+    output_w32(0x72a00000 | imm16_rd(imm >> 16, rt));
+  }
+}
+
+static void emit_loadreg(u_int r, u_int hr)
+{
+  assert(r < 64);
+  if (r == 0)
+    emit_zeroreg(hr);
+  else {
+    void *addr = &reg[r];
+    switch (r) {
+    case HIREG: addr = &hi; break;
+    case LOREG: addr = &lo; break;
+    case CCREG: addr = &cycle_count; break;
+    case CSREG: addr = &Status; break;
+    case INVCP: addr = &invc_ptr; break;
+    default: assert(r < 32); break;
+    }
+    uintptr_t offset = (u_char *)addr - (u_char *)&dynarec_local;
+    assert(offset < 4096);
+    assem_debug("ldr %s,fp+%lx\n", regname[hr], offset);
+    assert(0);
+  }
+}
+
+static void emit_storereg(u_int r, int hr)
+{
+  assert(r < 64);
+  void *addr = &reg[r];
+  switch (r) {
+  case HIREG: addr = &hi; break;
+  case LOREG: addr = &lo; break;
+  case CCREG: addr = &cycle_count; break;
+  default: assert(r < 32); break;
+  }
+  uintptr_t offset = (u_char *)addr - (u_char *)&dynarec_local;
+  assert(offset < 4096);
+  assem_debug("str %s,fp+%lx\n", regname[hr], offset);
+  assert(0);
+}
+
+static void emit_test(u_int rs, u_int rt)
+{
+  assem_debug("tst %s,%s\n",regname[rs],regname[rt]);
+  assert(0);
+}
+
+static void emit_testimm(u_int rs,int imm)
+{
+  assem_debug("tst %s,#%d\n",regname[rs],imm);
+  assert(0);
+}
+
+static void emit_testeqimm(u_int rs,int imm)
+{
+  assem_debug("tsteq %s,$%d\n",regname[rs],imm);
+  assert(0);
+}
+
+static void emit_not(u_int rs,u_int rt)
+{
+  assem_debug("mvn %s,%s\n",regname[rt],regname[rs]);
+  assert(0);
+}
+
+static void emit_mvnmi(u_int rs,u_int rt)
+{
+  assem_debug("mvnmi %s,%s\n",regname[rt],regname[rs]);
+  assert(0);
+}
+
+static void emit_and(u_int rs1,u_int rs2,u_int rt)
+{
+  assem_debug("and %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_or(u_int rs1,u_int rs2,u_int rt)
+{
+  assem_debug("orr %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_orrshl_imm(u_int rs,u_int imm,u_int rt)
+{
+  assert(rs < 31);
+  assert(rt < 31);
+  assert(imm < 32);
+  assem_debug("orr %s,%s,%s,lsl #%d\n",regname[rt],regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static void emit_orrshr_imm(u_int rs,u_int imm,u_int rt)
+{
+  assert(rs < 31);
+  assert(rt < 31);
+  assert(imm < 32);
+  assem_debug("orr %s,%s,%s,lsr #%d\n",regname[rt],regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static void emit_or_and_set_flags(u_int rs1,u_int rs2,u_int rt)
+{
+  assem_debug("orrs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_xor(u_int rs1,u_int rs2,u_int rt)
+{
+  assem_debug("eor %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_addimm(u_int rs, uintptr_t imm, u_int rt)
+{
+  assert(rs < 31);
+  assert(rt < 31);
+  assert(0);
+}
+
+static void emit_addimm_and_set_flags(int imm, u_int rt)
+{
+  assert(0);
+}
+
+static void emit_addimm_no_flags(u_int imm,u_int rt)
+{
+  emit_addimm(rt,imm,rt);
+}
+
+static void emit_addnop(u_int r)
+{
+  assert(r<16);
+  assem_debug("add %s,%s,#0 (nop)\n",regname[r],regname[r]);
+  assert(0);
+}
+
+static void emit_adcimm(u_int rs,int imm,u_int rt)
+{
+  assem_debug("adc %s,%s,#%d\n",regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static void emit_rscimm(u_int rs,int imm,u_int rt)
+{
+  assem_debug("rsc %s,%s,#%d\n",regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static void emit_addimm64_32(u_int rsh,u_int rsl,int imm,u_int rth,u_int rtl)
+{
+  assert(0);
+}
+
+static void emit_andimm(u_int rs,int imm,u_int rt)
+{
+  assert(0);
+}
+
+static void emit_orimm(u_int rs,int imm,u_int rt)
+{
+  assert(0);
+}
+
+static void emit_xorimm(u_int rs,int imm,u_int rt)
+{
+  assert(0);
+}
+
+static void emit_shlimm(u_int rs,u_int imm,u_int rt)
+{
+  assert(imm>0);
+  assert(imm<32);
+  assem_debug("lsl %s,%s,#%d\n",regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static void emit_lsls_imm(u_int rs,int imm,u_int rt)
+{
+  assert(imm>0);
+  assert(imm<32);
+  assem_debug("lsls %s,%s,#%d\n",regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static unused void emit_lslpls_imm(u_int rs,int imm,u_int rt)
+{
+  assert(imm>0);
+  assert(imm<32);
+  assem_debug("lslpls %s,%s,#%d\n",regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static void emit_shrimm(u_int rs,u_int imm,u_int rt)
+{
+  assert(imm>0);
+  assert(imm<32);
+  assem_debug("lsr %s,%s,#%d\n",regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static void emit_sarimm(u_int rs,u_int imm,u_int rt)
+{
+  assert(imm>0);
+  assert(imm<32);
+  assem_debug("asr %s,%s,#%d\n",regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static void emit_rorimm(u_int rs,u_int imm,u_int rt)
+{
+  assert(imm>0);
+  assert(imm<32);
+  assem_debug("ror %s,%s,#%d\n",regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static void emit_signextend16(u_int rs, u_int rt)
+{
+  assem_debug("sxth %s,%s\n", regname[rt], regname[rs]);
+  assert(0);
+}
+
+static void emit_shl(u_int rs,u_int shift,u_int rt)
+{
+  assert(rs < 31);
+  assert(rt < 31);
+  assert(shift < 16);
+  assert(0);
+}
+
+static void emit_shr(u_int rs,u_int shift,u_int rt)
+{
+  assert(rs < 31);
+  assert(rt < 31);
+  assert(shift<16);
+  assem_debug("lsr %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
+  assert(0);
+}
+
+static void emit_sar(u_int rs,u_int shift,u_int rt)
+{
+  assert(rs < 31);
+  assert(rt < 31);
+  assert(shift<16);
+  assem_debug("asr %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
+  assert(0);
+}
+
+static void emit_orrshl(u_int rs,u_int shift,u_int rt)
+{
+  assert(rs < 31);
+  assert(rt < 31);
+  assert(shift<16);
+  assem_debug("orr %s,%s,%s,lsl %s\n",regname[rt],regname[rt],regname[rs],regname[shift]);
+  assert(0);
+}
+
+static void emit_orrshr(u_int rs,u_int shift,u_int rt)
+{
+  assert(rs < 31);
+  assert(rt < 31);
+  assert(shift<16);
+  assem_debug("orr %s,%s,%s,lsr %s\n",regname[rt],regname[rt],regname[rs],regname[shift]);
+  assert(0);
+}
+
+static void emit_cmpimm(u_int rs,int imm)
+{
+  assert(0);
+}
+
+static void emit_cmovne_imm(int imm,u_int rt)
+{
+  assem_debug("movne %s,#%d\n",regname[rt],imm);
+  assert(0);
+}
+
+static void emit_cmovl_imm(int imm,u_int rt)
+{
+  assem_debug("movlt %s,#%d\n",regname[rt],imm);
+  assert(0);
+}
+
+static void emit_cmovb_imm(int imm,u_int rt)
+{
+  assem_debug("movcc %s,#%d\n",regname[rt],imm);
+  assert(0);
+}
+
+static void emit_cmovs_imm(int imm,u_int rt)
+{
+  assem_debug("movmi %s,#%d\n",regname[rt],imm);
+  assert(0);
+}
+
+static void emit_cmovne_reg(u_int rs,u_int rt)
+{
+  assem_debug("movne %s,%s\n",regname[rt],regname[rs]);
+  assert(0);
+}
+
+static void emit_cmovl_reg(u_int rs,u_int rt)
+{
+  assem_debug("movlt %s,%s\n",regname[rt],regname[rs]);
+  assert(0);
+}
+
+static void emit_cmovs_reg(u_int rs,u_int rt)
+{
+  assem_debug("movmi %s,%s\n",regname[rt],regname[rs]);
+  assert(0);
+}
+
+static void emit_slti32(u_int rs,int imm,u_int rt)
+{
+  if(rs!=rt) emit_zeroreg(rt);
+  emit_cmpimm(rs,imm);
+  if(rs==rt) emit_movimm(0,rt);
+  emit_cmovl_imm(1,rt);
+}
+
+static void emit_sltiu32(u_int rs,int imm,u_int rt)
+{
+  if(rs!=rt) emit_zeroreg(rt);
+  emit_cmpimm(rs,imm);
+  if(rs==rt) emit_movimm(0,rt);
+  emit_cmovb_imm(1,rt);
+}
+
+static void emit_cmp(u_int rs,u_int rt)
+{
+  assem_debug("cmp %s,%s\n",regname[rs],regname[rt]);
+  assert(0);
+}
+
+static void emit_set_gz32(u_int rs, u_int rt)
+{
+  //assem_debug("set_gz32\n");
+  emit_cmpimm(rs,1);
+  emit_movimm(1,rt);
+  emit_cmovl_imm(0,rt);
+}
+
+static void emit_set_nz32(u_int rs, u_int rt)
+{
+  //assem_debug("set_nz32\n");
+  assert(0);
+}
+
+static void emit_set_if_less32(u_int rs1, u_int rs2, u_int rt)
+{
+  //assem_debug("set if less (%%%s,%%%s),%%%s\n",regname[rs1],regname[rs2],regname[rt]);
+  if(rs1!=rt&&rs2!=rt) emit_zeroreg(rt);
+  emit_cmp(rs1,rs2);
+  if(rs1==rt||rs2==rt) emit_movimm(0,rt);
+  emit_cmovl_imm(1,rt);
+}
+
+static void emit_set_if_carry32(u_int rs1, u_int rs2, u_int rt)
+{
+  //assem_debug("set if carry (%%%s,%%%s),%%%s\n",regname[rs1],regname[rs2],regname[rt]);
+  if(rs1!=rt&&rs2!=rt) emit_zeroreg(rt);
+  emit_cmp(rs1,rs2);
+  if(rs1==rt||rs2==rt) emit_movimm(0,rt);
+  emit_cmovb_imm(1,rt);
+}
+
+#pragma GCC diagnostic ignored "-Wunused-variable"
+static void emit_call(const void *a_)
+{
+  uintptr_t a = (uintptr_t)a_;
+  assem_debug("bl %p (%p+%lx)%s\n", a_, out, (u_char *)a_ - out, func_name(a));
+  assert(0);
+}
+
+static void emit_jmp(const void *a_)
+{
+  uintptr_t a = (uintptr_t)a_;
+  assem_debug("b %p (%p+%lx)%s\n", a_, out, (u_char *)a_ - out, func_name(a));
+  assert(0);
+}
+
+static void emit_jne(const void *a_)
+{
+  uintptr_t a = (uintptr_t)a_;
+  assem_debug("bne %p\n", a_);
+  assert(0);
+}
+
+static void emit_jeq(int a)
+{
+  assem_debug("beq %x\n",a);
+  assert(0);
+}
+
+static void emit_js(int a)
+{
+  assem_debug("bmi %x\n",a);
+  assert(0);
+}
+
+static void emit_jns(int a)
+{
+  assem_debug("bpl %x\n",a);
+  assert(0);
+}
+
+static void emit_jl(int a)
+{
+  assem_debug("blt %x\n",a);
+  assert(0);
+}
+
+static void emit_jge(int a)
+{
+  assem_debug("bge %x\n",a);
+  assert(0);
+}
+
+static void emit_jno(int a)
+{
+  assem_debug("bvc %x\n",a);
+  assert(0);
+}
+
+static void emit_jc(int a)
+{
+  assem_debug("bcs %x\n",a);
+  assert(0);
+}
+
+static void emit_jcc(void *a_)
+{
+  uintptr_t a = (uintptr_t)a_;
+  assem_debug("bcc %p\n", a_);
+  assert(0);
+}
+
+static void emit_callreg(u_int r)
+{
+  assert(r < 31);
+  assem_debug("blx %s\n", regname[r]);
+  assert(0);
+}
+
+static void emit_jmpreg(u_int r)
+{
+  assem_debug("mov pc,%s\n",regname[r]);
+  assert(0);
+}
+
+static void emit_retreg(u_int r)
+{
+  assem_debug("ret %s\n", r == LR ? "" : regname[r]);
+  output_w32(0xd65f0000 | rm_rn_rd(0, r, 0));
+}
+
+static void emit_ret(void)
+{
+  emit_retreg(LR);
+}
+
+static void emit_readword_indexed(int offset, u_int rs, u_int rt)
+{
+  assem_debug("ldr %s,%s+%d\n",regname[rt],regname[rs],offset);
+  assert(0);
+}
+
+static void emit_readword_dualindexedx4(u_int rs1, u_int rs2, u_int rt)
+{
+  assem_debug("ldr %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_ldrcc_dualindexed(u_int rs1, u_int rs2, u_int rt)
+{
+  assem_debug("ldrcc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_ldrccb_dualindexed(u_int rs1, u_int rs2, u_int rt)
+{
+  assem_debug("ldrccb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_ldrccsb_dualindexed(u_int rs1, u_int rs2, u_int rt)
+{
+  assem_debug("ldrccsb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_ldrcch_dualindexed(u_int rs1, u_int rs2, u_int rt)
+{
+  assem_debug("ldrcch %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_ldrccsh_dualindexed(u_int rs1, u_int rs2, u_int rt)
+{
+  assem_debug("ldrccsh %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_movsbl_indexed(int offset, u_int rs, u_int rt)
+{
+  assem_debug("ldrsb %s,%s+%d\n",regname[rt],regname[rs],offset);
+  assert(0);
+}
+
+static void emit_movswl_indexed(int offset, u_int rs, u_int rt)
+{
+  assem_debug("ldrsh %s,%s+%d\n",regname[rt],regname[rs],offset);
+  assert(0);
+}
+
+static void emit_movzbl_indexed(int offset, u_int rs, u_int rt)
+{
+  assem_debug("ldrb %s,%s+%d\n",regname[rt],regname[rs],offset);
+  assert(0);
+}
+
+static void emit_movzwl_indexed(int offset, u_int rs, u_int rt)
+{
+  assem_debug("ldrh %s,%s+%d\n",regname[rt],regname[rs],offset);
+  assert(0);
+}
+
+static void emit_ldrd(int offset, u_int rs, u_int rt)
+{
+  assem_debug("ldrd %s,%s+%d\n",regname[rt],regname[rs],offset);
+  assert(0);
+}
+
+static void emit_readword(void *addr, u_int rt)
+{
+  uintptr_t offset = (u_char *)addr - (u_char *)&dynarec_local;
+  assert(offset<4096);
+  assem_debug("ldr %s,fp+%lx\n", regname[rt], offset);
+  assert(0);
+}
+
+static void emit_writeword_indexed(u_int rt, int offset, u_int rs)
+{
+  assert(offset>-4096&&offset<4096);
+  assem_debug("str %s,%s+%x\n",regname[rt],regname[rs],offset);
+  assert(0);
+}
+
+static void emit_writehword_indexed(u_int rt, int offset, u_int rs)
+{
+  assert(offset>-256&&offset<256);
+  assem_debug("strh %s,%s+%d\n",regname[rt],regname[rs],offset);
+  assert(0);
+}
+
+static void emit_writebyte_indexed(u_int rt, int offset, u_int rs)
+{
+  assert(offset>-4096&&offset<4096);
+  assem_debug("strb %s,%s+%d\n",regname[rt],regname[rs],offset);
+  assert(0);
+}
+
+static void emit_strcc_dualindexed(u_int rs1, u_int rs2, u_int rt)
+{
+  assem_debug("strcc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_strccb_dualindexed(u_int rs1, u_int rs2, u_int rt)
+{
+  assem_debug("strccb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_strcch_dualindexed(u_int rs1, u_int rs2, u_int rt)
+{
+  assem_debug("strcch %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  assert(0);
+}
+
+static void emit_writeword(u_int rt, void *addr)
+{
+  uintptr_t offset = (u_char *)addr - (u_char *)&dynarec_local;
+  assert(offset<4096);
+  assem_debug("str %s,fp+%lx\n", regname[rt], offset);
+  assert(0);
+}
+
+static void emit_umull(u_int rs1, u_int rs2, u_int hi, u_int lo)
+{
+  assem_debug("umull %s, %s, %s, %s\n",regname[lo],regname[hi],regname[rs1],regname[rs2]);
+  assert(rs1<16);
+  assert(rs2<16);
+  assert(hi<16);
+  assert(lo<16);
+  assert(0);
+}
+
+static void emit_smull(u_int rs1, u_int rs2, u_int hi, u_int lo)
+{
+  assem_debug("smull %s, %s, %s, %s\n",regname[lo],regname[hi],regname[rs1],regname[rs2]);
+  assert(rs1<16);
+  assert(rs2<16);
+  assert(hi<16);
+  assert(lo<16);
+  assert(0);
+}
+
+static void emit_clz(u_int rs,u_int rt)
+{
+  assem_debug("clz %s,%s\n",regname[rt],regname[rs]);
+  assert(0);
+}
+
+// Load 2 immediates optimizing for small code size
+static void emit_mov2imm_compact(int imm1,u_int rt1,int imm2,u_int rt2)
+{
+  assert(0);
+}
+
+// Conditionally select one of two immediates, optimizing for small code size
+// This will only be called if HAVE_CMOV_IMM is defined
+static void emit_cmov2imm_e_ne_compact(int imm1,int imm2,u_int rt)
+{
+  assert(0);
+}
+
+// special case for checking invalid_code
+static void emit_cmpmem_indexedsr12_reg(int base,u_int r,int imm)
+{
+  assert(imm<128&&imm>=0);
+  assert(r>=0&&r<16);
+  assem_debug("ldrb lr,%s,%s lsr #12\n",regname[base],regname[r]);
+  assert(0);
+}
+
+// Used to preload hash table entries
+static unused void emit_prefetchreg(u_int r)
+{
+  assem_debug("pld %s\n",regname[r]);
+  assert(0);
+}
+
+// Special case for mini_ht
+static void emit_ldreq_indexed(u_int rs, u_int offset, u_int rt)
+{
+  assert(offset<4096);
+  assem_debug("ldreq %s,[%s, #%d]\n",regname[rt],regname[rs],offset);
+  assert(0);
+}
+
+static void emit_orrne_imm(u_int rs,int imm,u_int rt)
+{
+  assem_debug("orrne %s,%s,#%d\n",regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static void emit_andne_imm(u_int rs,int imm,u_int rt)
+{
+  assem_debug("andne %s,%s,#%d\n",regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static unused void emit_addpl_imm(u_int rs,int imm,u_int rt)
+{
+  assem_debug("addpl %s,%s,#%d\n",regname[rt],regname[rs],imm);
+  assert(0);
+}
+
+static void save_regs_all(u_int reglist)
+{
+  if(!reglist) return;
+  assert(0);
+}
+
+static void restore_regs_all(u_int reglist)
+{
+  if(!reglist) return;
+  assert(0);
+}
+
+// Save registers before function call
+static void save_regs(u_int reglist)
+{
+  reglist &= CALLER_SAVE_REGS; // only save the caller-save registers
+  save_regs_all(reglist);
+}
+
+// Restore registers after function call
+static void restore_regs(u_int reglist)
+{
+  reglist &= CALLER_SAVE_REGS;
+  restore_regs_all(reglist);
+}
+
+/* Stubs/epilogue */
+
+static void literal_pool(int n)
+{
+  (void)literals;
+}
+
+static void literal_pool_jumpover(int n)
+{
+}
+
+static void emit_extjump2(u_char *addr, int target, void *linker)
+{
+  assert(0);
+}
+
+static void emit_extjump(void *addr, int target)
+{
+  emit_extjump2(addr, target, dyna_linker);
+}
+
+static void emit_extjump_ds(void *addr, int target)
+{
+  emit_extjump2(addr, target, dyna_linker_ds);
+}
+
+// put rt_val into rt, potentially making use of rs with value rs_val
+static void emit_movimm_from(u_int rs_val,u_int rs,u_int rt_val,u_int rt)
+{
+  assert(0);
+}
+
+// return 1 if above function can do it's job cheaply
+static int is_similar_value(u_int v1,u_int v2)
+{
+  assert(0);
+  return 0;
+}
+
+//#include "pcsxmem.h"
+//#include "pcsxmem_inline.c"
+
+static void do_readstub(int n)
+{
+  assem_debug("do_readstub %x\n",start+stubs[n].a*4);
+  assert(0);
+}
+
+static void inline_readstub(enum stub_type type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
+{
+  assert(0);
+}
+
+static void do_writestub(int n)
+{
+  assem_debug("do_writestub %x\n",start+stubs[n].a*4);
+  assert(0);
+}
+
+static void inline_writestub(enum stub_type type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
+{
+  assert(0);
+}
+
+static void do_unalignedwritestub(int n)
+{
+  assem_debug("do_unalignedwritestub %x\n",start+stubs[n].a*4);
+  assert(0);
+}
+
+static void do_invstub(int n)
+{
+  assert(0);
+}
+
+void *do_dirty_stub(int i)
+{
+  assem_debug("do_dirty_stub %x\n",start+i*4);
+  // Careful about the code output here, verify_dirty needs to parse it.
+  assert(0);
+  load_regs_entry(i);
+  return NULL;
+}
+
+static void do_dirty_stub_ds()
+{
+  // Careful about the code output here, verify_dirty needs to parse it.
+  assert(0);
+}
+
+/* Special assem */
+
+#define shift_assemble shift_assemble_arm64
+
+static void shift_assemble_arm64(int i,struct regstat *i_regs)
+{
+  assert(0);
+}
+#define loadlr_assemble loadlr_assemble_arm64
+
+static void loadlr_assemble_arm64(int i,struct regstat *i_regs)
+{
+  assert(0);
+}
+
+static void c2op_assemble(int i,struct regstat *i_regs)
+{
+  assert(0);
+}
+
+static void multdiv_assemble_arm64(int i,struct regstat *i_regs)
+{
+  assert(0);
+}
+#define multdiv_assemble multdiv_assemble_arm64
+
+static void do_preload_rhash(u_int r) {
+  // Don't need this for ARM.  On x86, this puts the value 0xf8 into the
+  // register.  On ARM the hash can be done with a single instruction (below)
+}
+
+static void do_preload_rhtbl(u_int ht) {
+  emit_addimm(FP, (u_char *)&mini_ht - (u_char *)&dynarec_local, ht);
+}
+
+static void do_rhash(u_int rs,u_int rh) {
+  emit_andimm(rs, 0xf8, rh);
+}
+
+static void do_miniht_load(int ht,u_int rh) {
+  assem_debug("ldr %s,[%s,%s]!\n",regname[rh],regname[ht],regname[rh]);
+  assert(0);
+}
+
+static void do_miniht_jump(u_int rs,u_int rh,int ht) {
+  emit_cmp(rh,rs);
+  emit_ldreq_indexed(ht,4,15);
+  //emit_jmp(jump_vaddr_reg[rs]);
+  assert(0);
+}
+
+static void do_miniht_insert(u_int return_address,u_int rt,int temp) {
+  assert(0);
+}
+
+static void mark_clear_cache(void *target)
+{
+  u_long offset = (u_char *)target - translation_cache;
+  u_int mask = 1u << ((offset >> 12) & 31);
+  if (!(needs_clear_cache[offset >> 17] & mask)) {
+    char *start = (char *)((u_long)target & ~4095ul);
+    start_tcache_write(start, start + 4096);
+    needs_clear_cache[offset >> 17] |= mask;
+  }
+}
+
+// Clearing the cache is rather slow on ARM Linux, so mark the areas
+// that need to be cleared, and then only clear these areas once.
+static void do_clear_cache()
+{
+  int i,j;
+  for (i=0;i<(1<<(TARGET_SIZE_2-17));i++)
+  {
+    u_int bitmap=needs_clear_cache[i];
+    if(bitmap) {
+      u_char *start, *end;
+      for(j=0;j<32;j++)
+      {
+        if(bitmap&(1<<j)) {
+          start=translation_cache+i*131072+j*4096;
+          end=start+4095;
+          j++;
+          while(j<32) {
+            if(bitmap&(1<<j)) {
+              end+=4096;
+              j++;
+            }else{
+              end_tcache_write(start, end);
+              break;
+            }
+          }
+        }
+      }
+      needs_clear_cache[i]=0;
+    }
+  }
+}
+
+// CPU-architecture-specific initialization
+static void arch_init() {
+}
+
+// vim:shiftwidth=2:expandtab
diff --git a/libpcsxcore/new_dynarec/assem_arm64.h b/libpcsxcore/new_dynarec/assem_arm64.h
new file mode 100644 (file)
index 0000000..8ba17ed
--- /dev/null
@@ -0,0 +1,46 @@
+#define HOST_REGS 29
+#define HOST_BTREG 27
+#define EXCLUDE_REG -1
+
+#define HOST_IMM8 1
+#define HAVE_CMOV_IMM 1
+#define RAM_SIZE 0x200000
+
+//#define REG_SHIFT 2
+
+/* calling convention:
+   r0 -r17: caller-save
+   r19-r29: callee-save */
+
+#define ARG1_REG 0
+#define ARG2_REG 1
+#define ARG3_REG 2
+#define ARG4_REG 3
+
+#define LR 30
+#define HOST_TEMPREG LR
+
+// Note: FP is set to &dynarec_local when executing generated code.
+// Thus the local variables are actually global and not on the stack.
+#define FP 29
+#define rFP x29
+
+#define HOST_CCREG 28
+#define rCC w28
+
+#ifndef __ASSEMBLER__
+
+extern char *invc_ptr;
+
+#define TARGET_SIZE_2 24 // 2^24 = 16 megabytes
+
+// Code generator target address
+#if defined(BASE_ADDR_DYNAMIC)
+  // for platforms that can't just use .bss buffer (are there any on arm64?)
+  extern u_char *translation_cache;
+#else
+  // using a static buffer in .bss
+  extern u_char translation_cache[1 << TARGET_SIZE_2];
+#endif
+
+#endif // !__ASSEMBLY__
index 2c82f58..62b9176 100644 (file)
@@ -362,7 +362,7 @@ static void ari64_execute_until()
        evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
                psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
 
-       new_dyna_start();
+       new_dyna_start(dynarec_local);
 
        evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
                psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
@@ -446,7 +446,7 @@ unsigned char *out;
 void *mem_rtab;
 void *scratch_buf_ptr;
 void new_dynarec_init() {}
-void new_dyna_start() {}
+void new_dyna_start(void *context) {}
 void new_dynarec_cleanup() {}
 void new_dynarec_clear_full() {}
 void invalidate_all_pages() {}
index c18a644..5783ad3 100644 (file)
@@ -7,6 +7,8 @@ extern char invalid_code[0x100000];
 #define EAX 0
 #define ECX 1
 
+extern int dynarec_local[];
+
 /* same as psxRegs */
 extern int reg[];
 
index 5f2b6ee..84a0178 100644 (file)
@@ -655,7 +655,7 @@ invalidate_addr_call:
 FUNCTION(new_dyna_start):
        /* ip is stored to conform EABI alignment */
        stmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
-       load_varadr fp, dynarec_local
+       mov     fp, r0 /* dynarec_local */
        ldr     r0, [fp, #LO_pcaddr]
        bl      get_addr_ht
        ldr     r1, [fp, #LO_next_interupt]
diff --git a/libpcsxcore/new_dynarec/linkage_arm64.S b/libpcsxcore/new_dynarec/linkage_arm64.S
new file mode 100644 (file)
index 0000000..1220787
--- /dev/null
@@ -0,0 +1,267 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   linkage_arm.s for PCSX                                                *
+ *   Copyright (C) 2009-2011 Ari64                                         *
+ *   Copyright (C) 2021 notaz                                              *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "arm_features.h"
+#include "new_dynarec_config.h"
+#include "assem_arm64.h"
+#include "linkage_offsets.h"
+
+.bss
+       .align  4
+       .global dynarec_local
+       .type   dynarec_local, %object
+       .size   dynarec_local, LO_dynarec_local_size
+dynarec_local:
+       .space  LO_dynarec_local_size
+
+#define DRC_VAR_(name, vname, size_) \
+       vname = dynarec_local + LO_##name; \
+       .global vname; \
+       .type   vname, %object; \
+       .size   vname, size_
+
+#define DRC_VAR(name, size_) \
+       DRC_VAR_(name, ESYM(name), size_)
+
+DRC_VAR(next_interupt, 4)
+DRC_VAR(cycle_count, 4)
+DRC_VAR(last_count, 4)
+DRC_VAR(pending_exception, 4)
+DRC_VAR(stop, 4)
+DRC_VAR(invc_ptr, 4)
+DRC_VAR(address, 4)
+DRC_VAR(psxRegs, LO_psxRegs_end - LO_psxRegs)
+
+/* psxRegs */
+DRC_VAR(reg, 128)
+DRC_VAR(lo, 4)
+DRC_VAR(hi, 4)
+DRC_VAR(reg_cop0, 128)
+DRC_VAR(reg_cop2d, 128)
+DRC_VAR(reg_cop2c, 128)
+DRC_VAR(pcaddr, 4)
+#DRC_VAR(code, 4)
+#DRC_VAR(cycle, 4)
+#DRC_VAR(interrupt, 4)
+#DRC_VAR(intCycle, 256)
+
+DRC_VAR(rcnts, 7*4*4)
+DRC_VAR(mem_rtab, 4)
+DRC_VAR(mem_wtab, 4)
+DRC_VAR(psxH_ptr, 4)
+DRC_VAR(zeromem_ptr, 4)
+DRC_VAR(inv_code_start, 4)
+DRC_VAR(inv_code_end, 4)
+DRC_VAR(branch_target, 4)
+DRC_VAR(scratch_buf_ptr, 4)
+#DRC_VAR(align0, 12) /* unused/alignment */
+DRC_VAR(mini_ht, 256)
+DRC_VAR(restore_candidate, 512)
+
+
+       .text
+       .align  2
+
+/* r0 = virtual target address */
+/* r1 = instruction to patch */
+.macro dyna_linker_main
+       /* XXX: should be able to do better than this... */
+       bl      get_addr_ht
+       br      x0
+.endm
+
+
+FUNCTION(dyna_linker):
+       /* r0 = virtual target address */
+       /* r1 = instruction to patch */
+       dyna_linker_main
+       .size   dyna_linker, .-dyna_linker
+
+FUNCTION(exec_pagefault):
+       /* r0 = instruction pointer */
+       /* r1 = fault address */
+       /* r2 = cause */
+       bl      abort
+       .size   exec_pagefault, .-exec_pagefault
+
+/* Special dynamic linker for the case where a page fault
+   may occur in a branch delay slot */
+FUNCTION(dyna_linker_ds):
+       /* r0 = virtual target address */
+       /* r1 = instruction to patch */
+       dyna_linker_main
+       .size   dyna_linker_ds, .-dyna_linker_ds
+
+       .align  2
+
+FUNCTION(jump_vaddr):
+       bl      abort
+       .size   jump_vaddr, .-jump_vaddr
+
+       .align  2
+
+FUNCTION(verify_code_ds):
+       bl      abort
+FUNCTION(verify_code_vm):
+FUNCTION(verify_code):
+       /* r1 = source */
+       /* r2 = target */
+       /* r3 = length */
+       bl      abort
+       .size   verify_code, .-verify_code
+       .size   verify_code_vm, .-verify_code_vm
+
+       .align  2
+FUNCTION(cc_interrupt):
+       bl      abort
+       .size   cc_interrupt, .-cc_interrupt
+
+       .align  2
+FUNCTION(do_interrupt):
+       bl      abort
+       .size   do_interrupt, .-do_interrupt
+
+       .align  2
+FUNCTION(fp_exception):
+       mov     w2, #0x10000000
+0:
+       ldr     w1, [fp, #LO_reg_cop0+48] /* Status */
+       mov     w3, #0x80000000
+       str     w0, [fp, #LO_reg_cop0+56] /* EPC */
+       orr     w1, w1, #2
+       add     w2, w2, #0x2c
+       str     w1, [fp, #LO_reg_cop0+48] /* Status */
+       str     w2, [fp, #LO_reg_cop0+52] /* Cause */
+       add     w0, w3, #0x80
+       bl      get_addr_ht
+       br      x0
+       .size   fp_exception, .-fp_exception
+       .align  2
+FUNCTION(fp_exception_ds):
+       mov     w2, #0x90000000 /* Set high bit if delay slot */
+       b       0b
+       .size   fp_exception_ds, .-fp_exception_ds
+
+       .align  2
+FUNCTION(jump_syscall):
+       ldr     w1, [fp, #LO_reg_cop0+48] /* Status */
+       mov     w3, #0x80000000
+       str     w0, [fp, #LO_reg_cop0+56] /* EPC */
+       orr     w1, w1, #2
+       mov     w2, #0x20
+       str     w1, [fp, #LO_reg_cop0+48] /* Status */
+       str     w2, [fp, #LO_reg_cop0+52] /* Cause */
+       add     w0, w3, #0x80
+       bl      get_addr_ht
+       br      x0
+       .size   jump_syscall, .-jump_syscall
+       .align  2
+
+       .align  2
+FUNCTION(jump_syscall_hle):
+       bl      abort
+
+       /* note: psxException might do recursive recompiler call from it's HLE code,
+        * so be ready for this */
+pcsx_return:
+       bl      abort // w10
+       ldr     w1, [fp, #LO_next_interupt]
+       ldr     w10, [fp, #LO_cycle]
+       ldr     w0, [fp, #LO_pcaddr]
+       sub     w10, w10, w1
+       str     w1, [fp, #LO_last_count]
+       bl      get_addr_ht
+       br      x0
+       .size   jump_syscall_hle, .-jump_syscall_hle
+
+       .align  2
+FUNCTION(jump_hlecall):
+       bl      abort
+       .size   jump_hlecall, .-jump_hlecall
+
+       .align  2
+FUNCTION(jump_intcall):
+       bl      abort
+       .size   jump_intcall, .-jump_intcall
+
+       .align  2
+FUNCTION(new_dyna_start):
+       stp     x29, x30, [sp, #-96]!   // must be aligned by 16
+       ldr     w1,  [x0, #LO_next_interupt]
+       ldr     w2,  [x0, #LO_cycle]
+       stp     x19, x20, [sp, #16*1]
+       stp     x21, x22, [sp, #16*2]
+       stp     x23, x24, [sp, #16*3]
+       stp     x25, x26, [sp, #16*4]
+       stp     x27, x28, [sp, #16*5]
+       mov     rFP, x0
+       ldr     w0,  [rFP, #LO_pcaddr]
+       str     w1,  [rFP, #LO_last_count]
+       sub     rCC, w2, w1
+       bl      get_addr_ht
+       br      x0
+       .size   new_dyna_start, .-new_dyna_start
+
+       .align  2
+FUNCTION(new_dyna_leave):
+       ldr     w0,  [rFP, #LO_last_count]
+       add     rCC, rCC, w0
+       str     rCC, [rFP, #LO_cycle]
+       ldp     x19, x20, [sp, #16*1]
+       ldp     x21, x22, [sp, #16*2]
+       ldp     x23, x24, [sp, #16*3]
+       ldp     x25, x26, [sp, #16*4]
+       ldp     x27, x28, [sp, #16*5]
+       ldp     x29, x30, [sp], #96
+       ret
+       .size   new_dyna_leave, .-new_dyna_leave
+
+/* --------------------------------------- */
+
+.align 2
+
+FUNCTION(jump_handler_read8):
+       bl      abort
+
+FUNCTION(jump_handler_read16):
+       bl      abort
+
+FUNCTION(jump_handler_read32):
+       bl      abort
+
+FUNCTION(jump_handler_write8):
+       bl      abort
+
+FUNCTION(jump_handler_write16):
+       bl      abort
+
+FUNCTION(jump_handler_write32):
+       bl      abort
+
+FUNCTION(jump_handler_write_h):
+       bl      abort
+
+FUNCTION(jump_handle_swl):
+       bl      abort
+
+FUNCTION(jump_handle_swr):
+       bl      abort
+
index 987892f..0809a4a 100644 (file)
@@ -57,6 +57,9 @@ static int sceBlock;
 #ifdef __arm__
 #include "assem_arm.h"
 #endif
+#ifdef __aarch64__
+#include "assem_arm64.h"
+#endif
 
 #define MAXBLOCK 4096
 #define MAX_OUTPUT_BLOCK_SIZE 262144
@@ -338,6 +341,8 @@ static void end_tcache_write(void *start, void *end)
   __clear_cache(start, end);
   #endif
   (void)len;
+#else
+  __clear_cache(start, end);
 #endif
 
   mprotect_w_x(start, end, 1);
@@ -834,6 +839,9 @@ static const char *func_name(intptr_t a)
 #ifdef __arm__
 #include "assem_arm.c"
 #endif
+#ifdef __aarch64__
+#include "assem_arm64.c"
+#endif
 
 // Add virtual address mapping to linked list
 void ll_add(struct ll_entry **head,int vaddr,void *addr)
@@ -1015,7 +1023,7 @@ static void invalidate_block_range(u_int block, u_int first, u_int last)
   for(first=page+1;first<last;first++) {
     invalidate_page(first);
   }
-  #ifdef __arm__
+  #if defined(__arm__) || defined(__aarch64__)
     do_clear_cache();
   #endif
 
@@ -3112,7 +3120,7 @@ static void cop2_put_dreg(u_int copr,signed char sl,signed char temp)
     case 30:
       emit_movs(sl,temp);
       emit_mvnmi(temp,temp);
-#ifdef HAVE_ARMV5
+#if defined(HAVE_ARMV5) || defined(__aarch64__)
       emit_clz(temp,temp);
 #else
       emit_movs(temp,HOST_TEMPREG);
@@ -4193,7 +4201,7 @@ void do_cc(int i,signed char i_regmap[],int *adj,int addr,int taken,int invert)
 static void do_ccstub(int n)
 {
   literal_pool(256);
-  assem_debug("do_ccstub %x\n",start+stubs[n].b*4);
+  assem_debug("do_ccstub %lx\n",start+stubs[n].b*4);
   set_jump_target(stubs[n].addr, out);
   int i=stubs[n].b;
   if(stubs[n].d==NULLDS) {
@@ -6183,25 +6191,32 @@ static void disassemble_inst(int i) {}
 
 #define DRC_TEST_VAL 0x74657374
 
-static int new_dynarec_test(void)
+static void new_dynarec_test(void)
 {
-  int (*testfunc)(void) = (void *)out;
+  int (*testfunc)(void);
   void *beginning;
-  int ret;
+  int ret[2];
+  size_t i;
 
-  beginning = start_block();
-  emit_movimm(DRC_TEST_VAL,0); // test
-  emit_jmpreg(14);
-  literal_pool(0);
-  end_block(beginning);
-  SysPrintf("testing if we can run recompiled code..\n");
-  ret = testfunc();
-  if (ret == DRC_TEST_VAL)
+  SysPrintf("testing if we can run recompiled code...\n");
+  ((volatile u_int *)out)[0]++; // make cache dirty
+
+  for (i = 0; i < ARRAY_SIZE(ret); i++) {
+    out = translation_cache;
+    beginning = start_block();
+    emit_movimm(DRC_TEST_VAL + i, 0); // test
+    emit_ret();
+    literal_pool(0);
+    end_block(beginning);
+    testfunc = beginning;
+    ret[i] = testfunc();
+  }
+
+  if (ret[0] == DRC_TEST_VAL && ret[1] == DRC_TEST_VAL + 1)
     SysPrintf("test passed.\n");
   else
-    SysPrintf("test failed: %08x\n", ret);
+    SysPrintf("test failed, will likely crash soon (r=%08x %08x)\n", ret[0], ret[1]);
   out = translation_cache;
-  return ret == DRC_TEST_VAL;
 }
 
 // clear the state completely, instead of just marking
@@ -6645,7 +6660,7 @@ int new_recompile_block(int addr)
 #endif
       case 0x12: strcpy(insn[i],"COP2"); type=NI;
         op2=(source[i]>>21)&0x1f;
-        //if (op2 & 0x10) {
+        //if (op2 & 0x10)
         if (source[i]&0x3f) { // use this hack to support old savestates with patched gte insns
           if (gte_handlers[source[i]&0x3f]!=NULL) {
             if (gte_regnames[source[i]&0x3f]!=NULL)
@@ -8893,7 +8908,7 @@ int new_recompile_block(int addr)
         break;
       case 3:
         // Clear jump_out
-        #ifdef __arm__
+        #if defined(__arm__) || defined(__aarch64__)
         if((expirep&2047)==0)
           do_clear_cache();
         #endif
index ddc84a5..1bec5e1 100644 (file)
@@ -14,7 +14,7 @@ extern int new_dynarec_hacks;
 void new_dynarec_init();
 void new_dynarec_cleanup();
 void new_dynarec_clear_full();
-void new_dyna_start();
+void new_dyna_start(void *context);
 int  new_dynarec_save_blocks(void *save, int size);
 void new_dynarec_load_blocks(const void *save, int size);
 
index fbd08ac..321bfbf 100644 (file)
@@ -1,6 +1,8 @@
 
-
+#ifdef __arm__
 #define CORTEX_A8_BRANCH_PREDICTION_HACK 1
+#endif
+
 #define USE_MINI_HT 1
 //#define REG_PREFETCH 1
 
index 9376ff4..bb471b6 100644 (file)
 //#define memprintf printf
 #define memprintf(...)
 
-static u32 *mem_readtab;
-static u32 *mem_writetab;
-static u32 mem_iortab[(1+2+4) * 0x1000 / 4];
-static u32 mem_iowtab[(1+2+4) * 0x1000 / 4];
-static u32 mem_ffwtab[(1+2+4) * 0x1000 / 4];
-//static u32 mem_unmrtab[(1+2+4) * 0x1000 / 4];
-static u32 mem_unmwtab[(1+2+4) * 0x1000 / 4];
-
-// When this is called in a loop, and 'h' is a function pointer, clang will crash.
+static uintptr_t *mem_readtab;
+static uintptr_t *mem_writetab;
+static uintptr_t mem_iortab[(1+2+4) * 0x1000 / 4];
+static uintptr_t mem_iowtab[(1+2+4) * 0x1000 / 4];
+static uintptr_t mem_ffwtab[(1+2+4) * 0x1000 / 4];
+//static uintptr_t mem_unmrtab[(1+2+4) * 0x1000 / 4];
+static uintptr_t mem_unmwtab[(1+2+4) * 0x1000 / 4];
+
+static
 #ifdef __clang__
-static __attribute__ ((noinline)) void map_item(u32 *out, const void *h, u32 flag)
-#else
-static void map_item(u32 *out, const void *h, u32 flag)
+// When this is called in a loop, and 'h' is a function pointer, clang will crash.
+__attribute__ ((noinline))
 #endif
+void map_item(uintptr_t *out, const void *h, uintptr_t flag)
 {
-       u32 hv = (u32)h;
+       uintptr_t hv = (uintptr_t)h;
        if (hv & 1) {
                SysPrintf("FATAL: %p has LSB set\n", h);
                abort();
        }
-       *out = (hv >> 1) | (flag << 31);
+       *out = (hv >> 1) | (flag << (sizeof(hv) * 8 - 1));
 }
 
 // size must be power of 2, at least 4k
@@ -90,7 +90,7 @@ static void io_write_sio32(u32 value)
        sioWrite8((unsigned char)(value >> 24));
 }
 
-#ifndef DRC_DBG
+#if !defined(DRC_DBG) && defined(__arm__)
 
 static void map_rcnt_rcount0(u32 mode)
 {
@@ -306,7 +306,7 @@ void new_dyna_pcsx_mem_init(void)
        int i;
 
        // have to map these further to keep tcache close to .text
-       mem_readtab = psxMap(0x08000000, 0x200000 * 4, 0, MAP_TAG_LUTS);
+       mem_readtab = psxMap(0x08000000, 0x200000 * sizeof(mem_readtab[0]), 0, MAP_TAG_LUTS);
        if (mem_readtab == NULL) {
                SysPrintf("failed to map mem tables\n");
                exit(1);