frontend: update libpicofe, fix missed callbacks
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / assem_arm.c
index a7bdfbd..aabf1c2 100644 (file)
@@ -19,6 +19,7 @@
  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
+#include <strings.h> // ffs
 #define FLAGLESS
 #include "../gte.h"
 #undef FLAGLESS
 #include "pcnt.h"
 #include "arm_features.h"
 
+#ifdef TC_WRITE_OFFSET
+#error "not implemented"
+#endif
+
 #ifdef DRC_DBG
 #pragma GCC diagnostic ignored "-Wunused-function"
 #pragma GCC diagnostic ignored "-Wunused-variable"
@@ -81,31 +86,40 @@ void invalidate_addr_r9();
 void invalidate_addr_r10();
 void invalidate_addr_r12();
 
-const u_int invalidate_addr_reg[16] = {
-  (int)invalidate_addr_r0,
-  (int)invalidate_addr_r1,
-  (int)invalidate_addr_r2,
-  (int)invalidate_addr_r3,
-  (int)invalidate_addr_r4,
-  (int)invalidate_addr_r5,
-  (int)invalidate_addr_r6,
-  (int)invalidate_addr_r7,
-  (int)invalidate_addr_r8,
-  (int)invalidate_addr_r9,
-  (int)invalidate_addr_r10,
+const void *invalidate_addr_reg[16] = {
+  invalidate_addr_r0,
+  invalidate_addr_r1,
+  invalidate_addr_r2,
+  invalidate_addr_r3,
+  invalidate_addr_r4,
+  invalidate_addr_r5,
+  invalidate_addr_r6,
+  invalidate_addr_r7,
+  invalidate_addr_r8,
+  invalidate_addr_r9,
+  invalidate_addr_r10,
   0,
-  (int)invalidate_addr_r12,
+  invalidate_addr_r12,
   0,
   0,
-  0};
+  0
+};
 
 /* Linker */
 
+static void set_jump_target_far1(u_int *insn, void *target)
+{
+  u_int ni = *insn & 0xff000000;
+  ni |= (((u_int)target - (u_int)insn - 8u) << 6) >> 8;
+  assert((ni & 0x0e000000) == 0x0a000000);
+  *insn = ni;
+}
+
 static void set_jump_target(void *addr, void *target_)
 {
-  u_int target = (u_int)target_;
-  u_char *ptr = addr;
-  u_int *ptr2=(u_int *)ptr;
+  const u_int target = (u_int)target_;
+  const u_char *ptr = addr;
+  u_int *ptr2 = (u_int *)ptr;
   if(ptr[3]==0xe2) {
     assert((target-(u_int)ptr2-8)<1024);
     assert(((uintptr_t)addr&3)==0);
@@ -128,8 +142,7 @@ static void set_jump_target(void *addr, void *target_)
     else *ptr2=(0x7A000000)|(((target-(u_int)ptr2-8)<<6)>>8);
   }
   else {
-    assert((ptr[3]&0x0e)==0xa);
-    *ptr2=(*ptr2&0xFF000000)|(((target-(u_int)ptr2-8)<<6)>>8);
+    set_jump_target_far1(ptr2, target_);
   }
 }
 
@@ -188,20 +201,6 @@ static void *find_extjump_insn(void *stub)
   return *l_ptr;
 }
 
-// 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
-#if 0
-static void *get_pointer(void *stub)
-{
-  //printf("get_pointer(%x)\n",(int)stub);
-  int *i_ptr=find_extjump_insn(stub);
-  assert((*i_ptr&0x0f000000)==0x0a000000); // b
-  return (u_char *)i_ptr+((*i_ptr<<8)>>6)+8;
-}
-#endif
-
 // Allocate a specific ARM register.
 static void alloc_arm_reg(struct regstat *cur,int i,signed char reg,int hr)
 {
@@ -217,21 +216,31 @@ static void alloc_arm_reg(struct regstat *cur,int i,signed char reg,int hr)
     }
   }
 
-  cur->regmap[hr]=reg;
-  cur->dirty&=~(1<<hr);
-  cur->dirty|=dirty<<hr;
-  cur->isconst&=~(1<<hr);
+  assert(n == hr || cur->regmap[hr] < 0 || !((cur->noevict >> hr) & 1));
+  cur->regmap[hr] = reg;
+  cur->dirty &= ~(1 << hr);
+  cur->dirty |= dirty << hr;
+  cur->isconst &= ~(1u << hr);
+  cur->noevict |= 1u << hr;
 }
 
 // Alloc cycle count into dedicated register
-static void alloc_cc(struct regstat *cur,int i)
+static void alloc_cc(struct regstat *cur, int i)
 {
-  alloc_arm_reg(cur,i,CCREG,HOST_CCREG);
+  alloc_arm_reg(cur, i, CCREG, HOST_CCREG);
+}
+
+static void alloc_cc_optional(struct regstat *cur, int i)
+{
+  if (cur->regmap[HOST_CCREG] < 0) {
+    alloc_arm_reg(cur, i, CCREG, HOST_CCREG);
+    cur->noevict &= ~(1u << HOST_CCREG);
+  }
 }
 
 /* Assembler */
 
-static unused char regname[16][4] = {
+static attr_unused char regname[16][4] = {
  "r0",
  "r1",
  "r2",
@@ -307,7 +316,7 @@ static u_int genjmp(u_int addr)
   return ((u_int)offset>>2)&0xffffff;
 }
 
-static unused void emit_breakpoint(void)
+static attr_unused void emit_breakpoint(void)
 {
   assem_debug("bkpt #0\n");
   //output_w32(0xe1200070);
@@ -459,15 +468,15 @@ static void emit_loadreg(int r, int hr)
 static void emit_storereg(int r, int hr)
 {
   assert(hr != EXCLUDE_REG);
-  int addr = (int)&psxRegs.GPR.r[r];
+  void *addr;
   switch (r) {
   //case HIREG: addr = &hi; break;
   //case LOREG: addr = &lo; break;
-  case CCREG: addr = (int)&cycle_count; break;
-  default: assert(r < 34); break;
+  case CCREG: addr = &cycle_count; break;
+  default: assert(r < 34u); addr = &psxRegs.GPR.r[r]; break;
   }
-  u_int offset = addr-(u_int)&dynarec_local;
-  assert(offset<4096);
+  uintptr_t offset = (char *)addr - (char *)&dynarec_local;
+  assert(offset < 4096u);
   assem_debug("str %s,fp+%d # r%d\n",regname[hr],offset,r);
   output_w32(0xe5800000|rd_rn_rm(hr,FP,0)|offset);
 }
@@ -719,7 +728,7 @@ static void emit_lsls_imm(int rs,int imm,int rt)
   output_w32(0xe1b00000|rd_rn_rm(rt,0,rs)|(imm<<7));
 }
 
-static unused void emit_lslpls_imm(int rs,int imm,int rt)
+static attr_unused void emit_lslpls_imm(int rs,int imm,int rt)
 {
   assert(imm>0);
   assert(imm<32);
@@ -801,7 +810,7 @@ static void emit_sar(u_int rs,u_int shift,u_int rt)
   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x50|(shift<<8));
 }
 
-static unused void emit_orrshl(u_int rs,u_int shift,u_int rt)
+static attr_unused void emit_orrshl(u_int rs,u_int shift,u_int rt)
 {
   assert(rs<16);
   assert(rt<16);
@@ -810,7 +819,7 @@ static unused void emit_orrshl(u_int rs,u_int shift,u_int rt)
   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs)|0x10|(shift<<8));
 }
 
-static unused void emit_orrshr(u_int rs,u_int shift,u_int rt)
+static attr_unused void emit_orrshr(u_int rs,u_int shift,u_int rt)
 {
   assert(rs<16);
   assert(rt<16);
@@ -881,7 +890,7 @@ static void emit_cmovs_imm(int imm,int rt)
   output_w32(0x43a00000|rd_rn_rm(rt,0,0)|armval);
 }
 
-static unused void emit_cmovne_reg(int rs,int rt)
+static attr_unused void emit_cmovne_reg(int rs,int rt)
 {
   assem_debug("movne %s,%s\n",regname[rt],regname[rs]);
   output_w32(0x11a00000|rd_rn_rm(rt,0,rs));
@@ -976,7 +985,7 @@ static int can_jump_or_call(const void *a)
 static void emit_call(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("bl %x (%x+%x)%s\n",a,(int)out,a-(int)out-8,func_name(a_));
+  assem_debug("bl %p%s\n", log_addr(a), func_name(a_));
   u_int offset=genjmp(a);
   output_w32(0xeb000000|offset);
 }
@@ -984,7 +993,7 @@ static void emit_call(const void *a_)
 static void emit_jmp(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("b %x (%x+%x)%s\n",a,(int)out,a-(int)out-8,func_name(a_));
+  assem_debug("b %p%s\n", log_addr(a_), func_name(a_));
   u_int offset=genjmp(a);
   output_w32(0xea000000|offset);
 }
@@ -992,7 +1001,7 @@ static void emit_jmp(const void *a_)
 static void emit_jne(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("bne %x\n",a);
+  assem_debug("bne %p\n", log_addr(a_));
   u_int offset=genjmp(a);
   output_w32(0x1a000000|offset);
 }
@@ -1000,7 +1009,7 @@ static void emit_jne(const void *a_)
 static void emit_jeq(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("beq %x\n",a);
+  assem_debug("beq %p\n", log_addr(a_));
   u_int offset=genjmp(a);
   output_w32(0x0a000000|offset);
 }
@@ -1008,7 +1017,7 @@ static void emit_jeq(const void *a_)
 static void emit_js(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("bmi %x\n",a);
+  assem_debug("bmi %p\n", log_addr(a_));
   u_int offset=genjmp(a);
   output_w32(0x4a000000|offset);
 }
@@ -1016,7 +1025,7 @@ static void emit_js(const void *a_)
 static void emit_jns(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("bpl %x\n",a);
+  assem_debug("bpl %p\n", log_addr(a_));
   u_int offset=genjmp(a);
   output_w32(0x5a000000|offset);
 }
@@ -1024,7 +1033,7 @@ static void emit_jns(const void *a_)
 static void emit_jl(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("blt %x\n",a);
+  assem_debug("blt %p\n", log_addr(a_));
   u_int offset=genjmp(a);
   output_w32(0xba000000|offset);
 }
@@ -1032,7 +1041,7 @@ static void emit_jl(const void *a_)
 static void emit_jge(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("bge %x\n",a);
+  assem_debug("bge %p\n", log_addr(a_));
   u_int offset=genjmp(a);
   output_w32(0xaa000000|offset);
 }
@@ -1040,7 +1049,7 @@ static void emit_jge(const void *a_)
 static void emit_jo(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("bvs %x\n",a);
+  assem_debug("bvs %p\n", log_addr(a_));
   u_int offset=genjmp(a);
   output_w32(0x6a000000|offset);
 }
@@ -1048,7 +1057,7 @@ static void emit_jo(const void *a_)
 static void emit_jno(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("bvc %x\n",a);
+  assem_debug("bvc %p\n", log_addr(a_));
   u_int offset=genjmp(a);
   output_w32(0x7a000000|offset);
 }
@@ -1056,7 +1065,7 @@ static void emit_jno(const void *a_)
 static void emit_jc(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("bcs %x\n",a);
+  assem_debug("bcs %p\n", log_addr(a_));
   u_int offset=genjmp(a);
   output_w32(0x2a000000|offset);
 }
@@ -1064,7 +1073,7 @@ static void emit_jc(const void *a_)
 static void emit_jcc(const void *a_)
 {
   int a = (int)a_;
-  assem_debug("bcc %x\n",a);
+  assem_debug("bcc %p\n", log_addr(a_));
   u_int offset=genjmp(a);
   output_w32(0x3a000000|offset);
 }
@@ -1078,7 +1087,7 @@ static void *emit_cbz(int rs, const void *a)
   return ret;
 }
 
-static unused void emit_callreg(u_int r)
+static attr_unused void emit_callreg(u_int r)
 {
   assert(r<15);
   assem_debug("blx %s\n",regname[r]);
@@ -1393,7 +1402,7 @@ static void emit_teq(int rs, int rt)
   output_w32(0xe1300000|rd_rn_rm(0,rs,rt));
 }
 
-static unused void emit_rsbimm(int rs, int imm, int rt)
+static attr_unused void emit_rsbimm(int rs, int imm, int rt)
 {
   u_int armval;
   genimm_checked(imm,&armval);
@@ -1443,15 +1452,16 @@ static void emit_ldrb_indexedsr12_reg(int base, int r, int rt)
   output_w32(0xe7d00000|rd_rn_rm(rt,base,r)|0x620);
 }
 
-static void emit_callne(int a)
+static void emit_callne(const void *a_)
 {
-  assem_debug("blne %x\n",a);
+  int a = (int)a_;
+  assem_debug("blne %p\n", log_addr(a_));
   u_int offset=genjmp(a);
   output_w32(0x1b000000|offset);
 }
 
 // Used to preload hash table entries
-static unused void emit_prefetchreg(int r)
+static attr_unused void emit_prefetchreg(int r)
 {
   assem_debug("pld %s\n",regname[r]);
   output_w32(0xf5d0f000|rd_rn_rm(0,r,0));
@@ -1473,7 +1483,7 @@ static void emit_orrne_imm(int rs,int imm,int rt)
   output_w32(0x13800000|rd_rn_rm(rt,rs,0)|armval);
 }
 
-static unused void emit_addpl_imm(int rs,int imm,int rt)
+static attr_unused void emit_addpl_imm(int rs,int imm,int rt)
 {
   u_int armval;
   genimm_checked(imm,&armval);
@@ -1481,10 +1491,11 @@ static unused void emit_addpl_imm(int rs,int imm,int rt)
   output_w32(0x52800000|rd_rn_rm(rt,rs,0)|armval);
 }
 
-static void emit_jno_unlikely(int a)
+static void emit_jno_unlikely(void *a_)
 {
-  //emit_jno(a);
-  assem_debug("addvc pc,pc,#? (%x)\n",/*a-(int)out-8,*/a);
+  //emit_jno(a_);
+  assert(a_ == NULL);
+  assem_debug("addvc pc,pc,#? (%p)\n", /*a-(int)out-8,*/ log_addr(a_));
   output_w32(0x72800000|rd_rn_rm(15,15,0));
 }
 
@@ -1572,7 +1583,7 @@ static void literal_pool_jumpover(int n)
   set_jump_target(jaddr, out);
 }
 
-// parsed by get_pointer, find_extjump_insn
+// parsed by find_extjump_insn, check_extjump2
 static void emit_extjump(u_char *addr, u_int target)
 {
   u_char *ptr=(u_char *)addr;
@@ -1654,7 +1665,7 @@ static void mov_loadtype_adj(enum stub_type type,int rs,int rt)
 
 static void do_readstub(int n)
 {
-  assem_debug("do_readstub %x\n",start+stubs[n].a*4);
+  assem_debug("do_readstub %p\n", log_addr(start + stubs[n].a*4));
   literal_pool(256);
   set_jump_target(stubs[n].addr, out);
   enum stub_type type=stubs[n].type;
@@ -1724,6 +1735,14 @@ static void do_readstub(int n)
     emit_loadreg(CCREG,2);
   emit_addimm(cc<0?2:cc,(int)stubs[n].d,2);
   emit_far_call(handler);
+#if 0
+  if (type == LOADW_STUB) {
+    // new cycle_count returned in r2
+    emit_addimm(2, -(int)stubs[n].d, cc<0?2:cc);
+    if (cc < 0)
+      emit_storereg(CCREG, 2);
+  }
+#endif
   if(dops[i].itype==C2LS||(rt>=0&&dops[i].rt1!=0)) {
     mov_loadtype_adj(type,0,rt);
   }
@@ -1794,6 +1813,14 @@ static void inline_readstub(enum stub_type type, int i, u_int addr,
 
   emit_far_call(handler);
 
+#if 0
+  if (type == LOADW_STUB) {
+    // new cycle_count returned in r2
+    emit_addimm(2, -adj, cc<0?2:cc);
+    if (cc < 0)
+      emit_storereg(CCREG, 2);
+  }
+#endif
   if(rt>=0&&dops[i].rt1!=0) {
     switch(type) {
       case LOADB_STUB:  emit_signextend8(0,rt); break;
@@ -1809,7 +1836,7 @@ static void inline_readstub(enum stub_type type, int i, u_int addr,
 
 static void do_writestub(int n)
 {
-  assem_debug("do_writestub %x\n",start+stubs[n].a*4);
+  assem_debug("do_writestub %p\n", log_addr(start + stubs[n].a*4));
   literal_pool(256);
   set_jump_target(stubs[n].addr, out);
   enum stub_type type=stubs[n].type;
@@ -1877,9 +1904,9 @@ static void do_writestub(int n)
   if(cc<0)
     emit_loadreg(CCREG,2);
   emit_addimm(cc<0?2:cc,(int)stubs[n].d,2);
-  // returns new cycle_count
   emit_far_call(handler);
-  emit_addimm(0,-(int)stubs[n].d,cc<0?2:cc);
+  // new cycle_count returned in r2
+  emit_addimm(2,-(int)stubs[n].d,cc<0?2:cc);
   if(cc<0)
     emit_storereg(CCREG,2);
   if(restore_jump)
@@ -1917,9 +1944,9 @@ static void inline_writestub(enum stub_type type, int i, u_int addr,
     emit_loadreg(CCREG,2);
   emit_addimm(cc<0?2:cc,adj,2);
   emit_movimm((u_int)handler,3);
-  // returns new cycle_count
   emit_far_call(jump_handler_write_h);
-  emit_addimm(0,-adj,cc<0?2:cc);
+  // new cycle_count returned in r2
+  emit_addimm(2,-adj,cc<0?2:cc);
   if(cc<0)
     emit_storereg(CCREG,2);
   restore_regs(reglist);