f9c837edae96bf89f5a5a7d43e8d71cc9bc8fac4
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / assem_arm64.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   Mupen64plus/PCSX - assem_arm64.c                                      *
3  *   Copyright (C) 2009-2011 Ari64                                         *
4  *   Copyright (C) 2010-2021 notaz                                         *
5  *                                                                         *
6  *   This program is free software; you can redistribute it and/or modify  *
7  *   it under the terms of the GNU General Public License as published by  *
8  *   the Free Software Foundation; either version 2 of the License, or     *
9  *   (at your option) any later version.                                   *
10  *                                                                         *
11  *   This program is distributed in the hope that it will be useful,       *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14  *   GNU General Public License for more details.                          *
15  *                                                                         *
16  *   You should have received a copy of the GNU General Public License     *
17  *   along with this program; if not, write to the                         *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
20  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22 #include "arm_features.h"
23
24 #if   defined(BASE_ADDR_FIXED)
25 #elif defined(BASE_ADDR_DYNAMIC)
26 u_char *translation_cache;
27 #else
28 u_char translation_cache[1 << TARGET_SIZE_2] __attribute__((aligned(4096)));
29 #endif
30
31 #define CALLER_SAVE_REGS 0x0007ffff
32
33 #define unused __attribute__((unused))
34
35 extern int cycle_count;
36 extern int last_count;
37 extern int pcaddr;
38 extern int pending_exception;
39 extern int branch_target;
40 extern u_int mini_ht[32][2];
41
42 static u_int needs_clear_cache[1<<(TARGET_SIZE_2-17)];
43
44 //void indirect_jump_indexed();
45 //void indirect_jump();
46 void do_interrupt();
47 //void jump_vaddr_r0();
48
49 void * const jump_vaddr_reg[32];
50
51 /* Linker */
52
53 static void set_jump_target(void *addr, void *target_)
54 {
55   assert(0);
56 }
57
58 // from a pointer to external jump stub (which was produced by emit_extjump2)
59 // find where the jumping insn is
60 static void *find_extjump_insn(void *stub)
61 {
62   assert(0);
63   return NULL;
64 }
65
66 // find where external branch is liked to using addr of it's stub:
67 // get address that insn one after stub loads (dyna_linker arg1),
68 // treat it as a pointer to branch insn,
69 // return addr where that branch jumps to
70 static void *get_pointer(void *stub)
71 {
72   //printf("get_pointer(%x)\n",(int)stub);
73   assert(0);
74   return NULL;
75 }
76
77 // Find the "clean" entry point from a "dirty" entry point
78 // by skipping past the call to verify_code
79 static void *get_clean_addr(void *addr)
80 {
81   assert(0);
82   return NULL;
83 }
84
85 static int verify_dirty(u_int *ptr)
86 {
87   assert(0);
88   return 0;
89 }
90
91 // This doesn't necessarily find all clean entry points, just
92 // guarantees that it's not dirty
93 static int isclean(void *addr)
94 {
95   assert(0);
96   return 0;
97 }
98
99 // get source that block at addr was compiled from (host pointers)
100 static void get_bounds(void *addr, u_char **start, u_char **end)
101 {
102   assert(0);
103 }
104
105 // Allocate a specific ARM register.
106 static void alloc_arm_reg(struct regstat *cur,int i,signed char reg,int hr)
107 {
108   int n;
109   int dirty=0;
110
111   // see if it's already allocated (and dealloc it)
112   for(n=0;n<HOST_REGS;n++)
113   {
114     if(n!=EXCLUDE_REG&&cur->regmap[n]==reg) {
115       dirty=(cur->dirty>>n)&1;
116       cur->regmap[n]=-1;
117     }
118   }
119
120   cur->regmap[hr]=reg;
121   cur->dirty&=~(1<<hr);
122   cur->dirty|=dirty<<hr;
123   cur->isconst&=~(1<<hr);
124 }
125
126 // Alloc cycle count into dedicated register
127 static void alloc_cc(struct regstat *cur,int i)
128 {
129   alloc_arm_reg(cur,i,CCREG,HOST_CCREG);
130 }
131
132 /* Special alloc */
133
134
135 /* Assembler */
136
137 static unused const char *regname[32] = {
138   "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6", "r7",
139   "r8",  "r9", "r10", "r11", "r12", "r13", "r14", "r15"
140  "ip0", "ip1", "r18", "r19", "r20", "r21", "r22", "r23"
141  "r24", "r25", "r26", "r27", "r28",  "fp",  "lr",  "sp"
142 };
143
144 #pragma GCC diagnostic ignored "-Wunused-function"
145 static void output_w32(u_int word)
146 {
147   *((u_int *)out) = word;
148   out += 4;
149 }
150
151 static u_int rm_rn_rd(u_int rm, u_int rn, u_int rd)
152 {
153   assert(rm < 31);
154   assert(rn < 31);
155   assert(rd < 31);
156   return (rm << 16) | (rn << 5) | rd;
157 }
158
159 static u_int imm16_rd(u_int imm16, u_int rd)
160 {
161   assert(imm16 < 0x10000);
162   assert(rd < 31);
163   return (imm16 << 5) | rd;
164 }
165
166 static u_int genjmp(u_char *addr)
167 {
168   intptr_t offset = addr - out;
169   if (offset < -134217728 || offset > 134217727) {
170     if ((uintptr_t)addr > 2) {
171       SysPrintf("%s: out of range: %08x\n", __func__, offset);
172       exit(1);
173     }
174     return 0;
175   }
176   return ((u_int)offset >> 2) & 0x01ffffff;
177 }
178
179 static u_int genjmpcc(u_char *addr)
180 {
181   intptr_t offset = addr - out;
182   if (offset < -1048576 || offset > 1048572) {
183     if ((uintptr_t)addr > 2) {
184       SysPrintf("%s: out of range: %08x\n", __func__, offset);
185       exit(1);
186     }
187     return 0;
188   }
189   return ((u_int)offset >> 2) & 0xfffff;
190 }
191
192 static void emit_mov(u_int rs, u_int rt)
193 {
194   assem_debug("mov %s,%s\n",regname[rt],regname[rs]);
195   assert(0);
196 }
197
198 static void emit_movs(u_int rs, u_int rt)
199 {
200   assem_debug("mov %s,%s\n",regname[rt],regname[rs]);
201   assert(0);
202 }
203
204 static void emit_add(u_int rs1,u_int rs2,u_int rt)
205 {
206   assem_debug("add %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
207   assert(0);
208 }
209
210 static void emit_sbc(u_int rs1,u_int rs2,u_int rt)
211 {
212   assem_debug("sbc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
213   assert(0);
214 }
215
216 static void emit_neg(u_int rs, u_int rt)
217 {
218   assem_debug("rsb %s,%s,#0\n",regname[rt],regname[rs]);
219   assert(0);
220 }
221
222 static void emit_negs(u_int rs, u_int rt)
223 {
224   assem_debug("rsbs %s,%s,#0\n",regname[rt],regname[rs]);
225   assert(0);
226 }
227
228 static void emit_sub(u_int rs1,u_int rs2,u_int rt)
229 {
230   assem_debug("sub %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
231   assert(0);
232 }
233
234 static void emit_subs(u_int rs1,u_int rs2,u_int rt)
235 {
236   assem_debug("subs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
237   assert(0);
238 }
239
240 static void emit_zeroreg(u_int rt)
241 {
242   assem_debug("mov %s,#0\n",regname[rt]);
243   assert(0);
244 }
245
246 static void emit_movw(u_int imm,u_int rt)
247 {
248   assert(imm<65536);
249   assem_debug("movw %s,#%d (0x%x)\n",regname[rt],imm,imm);
250   assert(0);
251 }
252
253 static void emit_movt(u_int imm,u_int rt)
254 {
255   assem_debug("movt %s,#%d (0x%x)\n",regname[rt],imm&0xffff0000,imm&0xffff0000);
256   assert(0);
257 }
258
259 static void emit_movimm(u_int imm, u_int rt)
260 {
261   assem_debug("mov %s,#%x\n", regname[rt], imm);
262   if      ((imm & 0xffff0000) == 0)
263     output_w32(0x52800000 | imm16_rd(imm, rt));
264   else if ((imm & 0xffff0000) == 0xffff0000)
265     assert(0);
266   else {
267     output_w32(0x52800000 | imm16_rd(imm & 0xffff, rt));
268     output_w32(0x72a00000 | imm16_rd(imm >> 16, rt));
269   }
270 }
271
272 static void emit_loadreg(u_int r, u_int hr)
273 {
274   assert(r < 64);
275   if (r == 0)
276     emit_zeroreg(hr);
277   else {
278     void *addr = &reg[r];
279     switch (r) {
280     case HIREG: addr = &hi; break;
281     case LOREG: addr = &lo; break;
282     case CCREG: addr = &cycle_count; break;
283     case CSREG: addr = &Status; break;
284     case INVCP: addr = &invc_ptr; break;
285     default: assert(r < 32); break;
286     }
287     uintptr_t offset = (u_char *)addr - (u_char *)&dynarec_local;
288     assert(offset < 4096);
289     assem_debug("ldr %s,fp+%lx\n", regname[hr], offset);
290     assert(0);
291   }
292 }
293
294 static void emit_storereg(u_int r, int hr)
295 {
296   assert(r < 64);
297   void *addr = &reg[r];
298   switch (r) {
299   case HIREG: addr = &hi; break;
300   case LOREG: addr = &lo; break;
301   case CCREG: addr = &cycle_count; break;
302   default: assert(r < 32); break;
303   }
304   uintptr_t offset = (u_char *)addr - (u_char *)&dynarec_local;
305   assert(offset < 4096);
306   assem_debug("str %s,fp+%lx\n", regname[hr], offset);
307   assert(0);
308 }
309
310 static void emit_test(u_int rs, u_int rt)
311 {
312   assem_debug("tst %s,%s\n",regname[rs],regname[rt]);
313   assert(0);
314 }
315
316 static void emit_testimm(u_int rs,int imm)
317 {
318   assem_debug("tst %s,#%d\n",regname[rs],imm);
319   assert(0);
320 }
321
322 static void emit_testeqimm(u_int rs,int imm)
323 {
324   assem_debug("tsteq %s,$%d\n",regname[rs],imm);
325   assert(0);
326 }
327
328 static void emit_not(u_int rs,u_int rt)
329 {
330   assem_debug("mvn %s,%s\n",regname[rt],regname[rs]);
331   assert(0);
332 }
333
334 static void emit_mvnmi(u_int rs,u_int rt)
335 {
336   assem_debug("mvnmi %s,%s\n",regname[rt],regname[rs]);
337   assert(0);
338 }
339
340 static void emit_and(u_int rs1,u_int rs2,u_int rt)
341 {
342   assem_debug("and %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
343   assert(0);
344 }
345
346 static void emit_or(u_int rs1,u_int rs2,u_int rt)
347 {
348   assem_debug("orr %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
349   assert(0);
350 }
351
352 static void emit_orrshl_imm(u_int rs,u_int imm,u_int rt)
353 {
354   assert(rs < 31);
355   assert(rt < 31);
356   assert(imm < 32);
357   assem_debug("orr %s,%s,%s,lsl #%d\n",regname[rt],regname[rt],regname[rs],imm);
358   assert(0);
359 }
360
361 static void emit_orrshr_imm(u_int rs,u_int imm,u_int rt)
362 {
363   assert(rs < 31);
364   assert(rt < 31);
365   assert(imm < 32);
366   assem_debug("orr %s,%s,%s,lsr #%d\n",regname[rt],regname[rt],regname[rs],imm);
367   assert(0);
368 }
369
370 static void emit_or_and_set_flags(u_int rs1,u_int rs2,u_int rt)
371 {
372   assem_debug("orrs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
373   assert(0);
374 }
375
376 static void emit_xor(u_int rs1,u_int rs2,u_int rt)
377 {
378   assem_debug("eor %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
379   assert(0);
380 }
381
382 static void emit_addimm(u_int rs, uintptr_t imm, u_int rt)
383 {
384   assert(rs < 31);
385   assert(rt < 31);
386   assert(0);
387 }
388
389 static void emit_addimm_and_set_flags(int imm, u_int rt)
390 {
391   assert(0);
392 }
393
394 static void emit_addimm_no_flags(u_int imm,u_int rt)
395 {
396   emit_addimm(rt,imm,rt);
397 }
398
399 static void emit_addnop(u_int r)
400 {
401   assert(r<16);
402   assem_debug("add %s,%s,#0 (nop)\n",regname[r],regname[r]);
403   assert(0);
404 }
405
406 static void emit_adcimm(u_int rs,int imm,u_int rt)
407 {
408   assem_debug("adc %s,%s,#%d\n",regname[rt],regname[rs],imm);
409   assert(0);
410 }
411
412 static void emit_rscimm(u_int rs,int imm,u_int rt)
413 {
414   assem_debug("rsc %s,%s,#%d\n",regname[rt],regname[rs],imm);
415   assert(0);
416 }
417
418 static void emit_addimm64_32(u_int rsh,u_int rsl,int imm,u_int rth,u_int rtl)
419 {
420   assert(0);
421 }
422
423 static void emit_andimm(u_int rs,int imm,u_int rt)
424 {
425   assert(0);
426 }
427
428 static void emit_orimm(u_int rs,int imm,u_int rt)
429 {
430   assert(0);
431 }
432
433 static void emit_xorimm(u_int rs,int imm,u_int rt)
434 {
435   assert(0);
436 }
437
438 static void emit_shlimm(u_int rs,u_int imm,u_int rt)
439 {
440   assert(imm>0);
441   assert(imm<32);
442   assem_debug("lsl %s,%s,#%d\n",regname[rt],regname[rs],imm);
443   assert(0);
444 }
445
446 static void emit_lsls_imm(u_int rs,int imm,u_int rt)
447 {
448   assert(imm>0);
449   assert(imm<32);
450   assem_debug("lsls %s,%s,#%d\n",regname[rt],regname[rs],imm);
451   assert(0);
452 }
453
454 static unused void emit_lslpls_imm(u_int rs,int imm,u_int rt)
455 {
456   assert(imm>0);
457   assert(imm<32);
458   assem_debug("lslpls %s,%s,#%d\n",regname[rt],regname[rs],imm);
459   assert(0);
460 }
461
462 static void emit_shrimm(u_int rs,u_int imm,u_int rt)
463 {
464   assert(imm>0);
465   assert(imm<32);
466   assem_debug("lsr %s,%s,#%d\n",regname[rt],regname[rs],imm);
467   assert(0);
468 }
469
470 static void emit_sarimm(u_int rs,u_int imm,u_int rt)
471 {
472   assert(imm>0);
473   assert(imm<32);
474   assem_debug("asr %s,%s,#%d\n",regname[rt],regname[rs],imm);
475   assert(0);
476 }
477
478 static void emit_rorimm(u_int rs,u_int imm,u_int rt)
479 {
480   assert(imm>0);
481   assert(imm<32);
482   assem_debug("ror %s,%s,#%d\n",regname[rt],regname[rs],imm);
483   assert(0);
484 }
485
486 static void emit_signextend16(u_int rs, u_int rt)
487 {
488   assem_debug("sxth %s,%s\n", regname[rt], regname[rs]);
489   assert(0);
490 }
491
492 static void emit_shl(u_int rs,u_int shift,u_int rt)
493 {
494   assert(rs < 31);
495   assert(rt < 31);
496   assert(shift < 16);
497   assert(0);
498 }
499
500 static void emit_shr(u_int rs,u_int shift,u_int rt)
501 {
502   assert(rs < 31);
503   assert(rt < 31);
504   assert(shift<16);
505   assem_debug("lsr %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
506   assert(0);
507 }
508
509 static void emit_sar(u_int rs,u_int shift,u_int rt)
510 {
511   assert(rs < 31);
512   assert(rt < 31);
513   assert(shift<16);
514   assem_debug("asr %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
515   assert(0);
516 }
517
518 static void emit_orrshl(u_int rs,u_int shift,u_int rt)
519 {
520   assert(rs < 31);
521   assert(rt < 31);
522   assert(shift<16);
523   assem_debug("orr %s,%s,%s,lsl %s\n",regname[rt],regname[rt],regname[rs],regname[shift]);
524   assert(0);
525 }
526
527 static void emit_orrshr(u_int rs,u_int shift,u_int rt)
528 {
529   assert(rs < 31);
530   assert(rt < 31);
531   assert(shift<16);
532   assem_debug("orr %s,%s,%s,lsr %s\n",regname[rt],regname[rt],regname[rs],regname[shift]);
533   assert(0);
534 }
535
536 static void emit_cmpimm(u_int rs,int imm)
537 {
538   assert(0);
539 }
540
541 static void emit_cmovne_imm(int imm,u_int rt)
542 {
543   assem_debug("movne %s,#%d\n",regname[rt],imm);
544   assert(0);
545 }
546
547 static void emit_cmovl_imm(int imm,u_int rt)
548 {
549   assem_debug("movlt %s,#%d\n",regname[rt],imm);
550   assert(0);
551 }
552
553 static void emit_cmovb_imm(int imm,u_int rt)
554 {
555   assem_debug("movcc %s,#%d\n",regname[rt],imm);
556   assert(0);
557 }
558
559 static void emit_cmovs_imm(int imm,u_int rt)
560 {
561   assem_debug("movmi %s,#%d\n",regname[rt],imm);
562   assert(0);
563 }
564
565 static void emit_cmovne_reg(u_int rs,u_int rt)
566 {
567   assem_debug("movne %s,%s\n",regname[rt],regname[rs]);
568   assert(0);
569 }
570
571 static void emit_cmovl_reg(u_int rs,u_int rt)
572 {
573   assem_debug("movlt %s,%s\n",regname[rt],regname[rs]);
574   assert(0);
575 }
576
577 static void emit_cmovs_reg(u_int rs,u_int rt)
578 {
579   assem_debug("movmi %s,%s\n",regname[rt],regname[rs]);
580   assert(0);
581 }
582
583 static void emit_slti32(u_int rs,int imm,u_int rt)
584 {
585   if(rs!=rt) emit_zeroreg(rt);
586   emit_cmpimm(rs,imm);
587   if(rs==rt) emit_movimm(0,rt);
588   emit_cmovl_imm(1,rt);
589 }
590
591 static void emit_sltiu32(u_int rs,int imm,u_int rt)
592 {
593   if(rs!=rt) emit_zeroreg(rt);
594   emit_cmpimm(rs,imm);
595   if(rs==rt) emit_movimm(0,rt);
596   emit_cmovb_imm(1,rt);
597 }
598
599 static void emit_cmp(u_int rs,u_int rt)
600 {
601   assem_debug("cmp %s,%s\n",regname[rs],regname[rt]);
602   assert(0);
603 }
604
605 static void emit_set_gz32(u_int rs, u_int rt)
606 {
607   //assem_debug("set_gz32\n");
608   emit_cmpimm(rs,1);
609   emit_movimm(1,rt);
610   emit_cmovl_imm(0,rt);
611 }
612
613 static void emit_set_nz32(u_int rs, u_int rt)
614 {
615   //assem_debug("set_nz32\n");
616   assert(0);
617 }
618
619 static void emit_set_if_less32(u_int rs1, u_int rs2, u_int rt)
620 {
621   //assem_debug("set if less (%%%s,%%%s),%%%s\n",regname[rs1],regname[rs2],regname[rt]);
622   if(rs1!=rt&&rs2!=rt) emit_zeroreg(rt);
623   emit_cmp(rs1,rs2);
624   if(rs1==rt||rs2==rt) emit_movimm(0,rt);
625   emit_cmovl_imm(1,rt);
626 }
627
628 static void emit_set_if_carry32(u_int rs1, u_int rs2, u_int rt)
629 {
630   //assem_debug("set if carry (%%%s,%%%s),%%%s\n",regname[rs1],regname[rs2],regname[rt]);
631   if(rs1!=rt&&rs2!=rt) emit_zeroreg(rt);
632   emit_cmp(rs1,rs2);
633   if(rs1==rt||rs2==rt) emit_movimm(0,rt);
634   emit_cmovb_imm(1,rt);
635 }
636
637 #pragma GCC diagnostic ignored "-Wunused-variable"
638 static void emit_call(const void *a_)
639 {
640   uintptr_t a = (uintptr_t)a_;
641   assem_debug("bl %p (%p+%lx)%s\n", a_, out, (u_char *)a_ - out, func_name(a));
642   assert(0);
643 }
644
645 static void emit_jmp(const void *a_)
646 {
647   uintptr_t a = (uintptr_t)a_;
648   assem_debug("b %p (%p+%lx)%s\n", a_, out, (u_char *)a_ - out, func_name(a));
649   assert(0);
650 }
651
652 static void emit_jne(const void *a_)
653 {
654   uintptr_t a = (uintptr_t)a_;
655   assem_debug("bne %p\n", a_);
656   assert(0);
657 }
658
659 static void emit_jeq(int a)
660 {
661   assem_debug("beq %x\n",a);
662   assert(0);
663 }
664
665 static void emit_js(int a)
666 {
667   assem_debug("bmi %x\n",a);
668   assert(0);
669 }
670
671 static void emit_jns(int a)
672 {
673   assem_debug("bpl %x\n",a);
674   assert(0);
675 }
676
677 static void emit_jl(int a)
678 {
679   assem_debug("blt %x\n",a);
680   assert(0);
681 }
682
683 static void emit_jge(int a)
684 {
685   assem_debug("bge %x\n",a);
686   assert(0);
687 }
688
689 static void emit_jno(int a)
690 {
691   assem_debug("bvc %x\n",a);
692   assert(0);
693 }
694
695 static void emit_jc(int a)
696 {
697   assem_debug("bcs %x\n",a);
698   assert(0);
699 }
700
701 static void emit_jcc(void *a_)
702 {
703   uintptr_t a = (uintptr_t)a_;
704   assem_debug("bcc %p\n", a_);
705   assert(0);
706 }
707
708 static void emit_callreg(u_int r)
709 {
710   assert(r < 31);
711   assem_debug("blx %s\n", regname[r]);
712   assert(0);
713 }
714
715 static void emit_jmpreg(u_int r)
716 {
717   assem_debug("mov pc,%s\n",regname[r]);
718   assert(0);
719 }
720
721 static void emit_retreg(u_int r)
722 {
723   assem_debug("ret %s\n", r == LR ? "" : regname[r]);
724   output_w32(0xd65f0000 | rm_rn_rd(0, r, 0));
725 }
726
727 static void emit_ret(void)
728 {
729   emit_retreg(LR);
730 }
731
732 static void emit_readword_indexed(int offset, u_int rs, u_int rt)
733 {
734   assem_debug("ldr %s,%s+%d\n",regname[rt],regname[rs],offset);
735   assert(0);
736 }
737
738 static void emit_readword_dualindexedx4(u_int rs1, u_int rs2, u_int rt)
739 {
740   assem_debug("ldr %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
741   assert(0);
742 }
743
744 static void emit_ldrcc_dualindexed(u_int rs1, u_int rs2, u_int rt)
745 {
746   assem_debug("ldrcc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
747   assert(0);
748 }
749
750 static void emit_ldrccb_dualindexed(u_int rs1, u_int rs2, u_int rt)
751 {
752   assem_debug("ldrccb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
753   assert(0);
754 }
755
756 static void emit_ldrccsb_dualindexed(u_int rs1, u_int rs2, u_int rt)
757 {
758   assem_debug("ldrccsb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
759   assert(0);
760 }
761
762 static void emit_ldrcch_dualindexed(u_int rs1, u_int rs2, u_int rt)
763 {
764   assem_debug("ldrcch %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
765   assert(0);
766 }
767
768 static void emit_ldrccsh_dualindexed(u_int rs1, u_int rs2, u_int rt)
769 {
770   assem_debug("ldrccsh %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
771   assert(0);
772 }
773
774 static void emit_movsbl_indexed(int offset, u_int rs, u_int rt)
775 {
776   assem_debug("ldrsb %s,%s+%d\n",regname[rt],regname[rs],offset);
777   assert(0);
778 }
779
780 static void emit_movswl_indexed(int offset, u_int rs, u_int rt)
781 {
782   assem_debug("ldrsh %s,%s+%d\n",regname[rt],regname[rs],offset);
783   assert(0);
784 }
785
786 static void emit_movzbl_indexed(int offset, u_int rs, u_int rt)
787 {
788   assem_debug("ldrb %s,%s+%d\n",regname[rt],regname[rs],offset);
789   assert(0);
790 }
791
792 static void emit_movzwl_indexed(int offset, u_int rs, u_int rt)
793 {
794   assem_debug("ldrh %s,%s+%d\n",regname[rt],regname[rs],offset);
795   assert(0);
796 }
797
798 static void emit_ldrd(int offset, u_int rs, u_int rt)
799 {
800   assem_debug("ldrd %s,%s+%d\n",regname[rt],regname[rs],offset);
801   assert(0);
802 }
803
804 static void emit_readword(void *addr, u_int rt)
805 {
806   uintptr_t offset = (u_char *)addr - (u_char *)&dynarec_local;
807   assert(offset<4096);
808   assem_debug("ldr %s,fp+%lx\n", regname[rt], offset);
809   assert(0);
810 }
811
812 static void emit_writeword_indexed(u_int rt, int offset, u_int rs)
813 {
814   assert(offset>-4096&&offset<4096);
815   assem_debug("str %s,%s+%x\n",regname[rt],regname[rs],offset);
816   assert(0);
817 }
818
819 static void emit_writehword_indexed(u_int rt, int offset, u_int rs)
820 {
821   assert(offset>-256&&offset<256);
822   assem_debug("strh %s,%s+%d\n",regname[rt],regname[rs],offset);
823   assert(0);
824 }
825
826 static void emit_writebyte_indexed(u_int rt, int offset, u_int rs)
827 {
828   assert(offset>-4096&&offset<4096);
829   assem_debug("strb %s,%s+%d\n",regname[rt],regname[rs],offset);
830   assert(0);
831 }
832
833 static void emit_strcc_dualindexed(u_int rs1, u_int rs2, u_int rt)
834 {
835   assem_debug("strcc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
836   assert(0);
837 }
838
839 static void emit_strccb_dualindexed(u_int rs1, u_int rs2, u_int rt)
840 {
841   assem_debug("strccb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
842   assert(0);
843 }
844
845 static void emit_strcch_dualindexed(u_int rs1, u_int rs2, u_int rt)
846 {
847   assem_debug("strcch %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
848   assert(0);
849 }
850
851 static void emit_writeword(u_int rt, void *addr)
852 {
853   uintptr_t offset = (u_char *)addr - (u_char *)&dynarec_local;
854   assert(offset<4096);
855   assem_debug("str %s,fp+%lx\n", regname[rt], offset);
856   assert(0);
857 }
858
859 static void emit_umull(u_int rs1, u_int rs2, u_int hi, u_int lo)
860 {
861   assem_debug("umull %s, %s, %s, %s\n",regname[lo],regname[hi],regname[rs1],regname[rs2]);
862   assert(rs1<16);
863   assert(rs2<16);
864   assert(hi<16);
865   assert(lo<16);
866   assert(0);
867 }
868
869 static void emit_smull(u_int rs1, u_int rs2, u_int hi, u_int lo)
870 {
871   assem_debug("smull %s, %s, %s, %s\n",regname[lo],regname[hi],regname[rs1],regname[rs2]);
872   assert(rs1<16);
873   assert(rs2<16);
874   assert(hi<16);
875   assert(lo<16);
876   assert(0);
877 }
878
879 static void emit_clz(u_int rs,u_int rt)
880 {
881   assem_debug("clz %s,%s\n",regname[rt],regname[rs]);
882   assert(0);
883 }
884
885 // Load 2 immediates optimizing for small code size
886 static void emit_mov2imm_compact(int imm1,u_int rt1,int imm2,u_int rt2)
887 {
888   assert(0);
889 }
890
891 // Conditionally select one of two immediates, optimizing for small code size
892 // This will only be called if HAVE_CMOV_IMM is defined
893 static void emit_cmov2imm_e_ne_compact(int imm1,int imm2,u_int rt)
894 {
895   assert(0);
896 }
897
898 // special case for checking invalid_code
899 static void emit_cmpmem_indexedsr12_reg(int base,u_int r,int imm)
900 {
901   assert(imm<128&&imm>=0);
902   assert(r>=0&&r<16);
903   assem_debug("ldrb lr,%s,%s lsr #12\n",regname[base],regname[r]);
904   assert(0);
905 }
906
907 // Used to preload hash table entries
908 static unused void emit_prefetchreg(u_int r)
909 {
910   assem_debug("pld %s\n",regname[r]);
911   assert(0);
912 }
913
914 // Special case for mini_ht
915 static void emit_ldreq_indexed(u_int rs, u_int offset, u_int rt)
916 {
917   assert(offset<4096);
918   assem_debug("ldreq %s,[%s, #%d]\n",regname[rt],regname[rs],offset);
919   assert(0);
920 }
921
922 static void emit_orrne_imm(u_int rs,int imm,u_int rt)
923 {
924   assem_debug("orrne %s,%s,#%d\n",regname[rt],regname[rs],imm);
925   assert(0);
926 }
927
928 static void emit_andne_imm(u_int rs,int imm,u_int rt)
929 {
930   assem_debug("andne %s,%s,#%d\n",regname[rt],regname[rs],imm);
931   assert(0);
932 }
933
934 static unused void emit_addpl_imm(u_int rs,int imm,u_int rt)
935 {
936   assem_debug("addpl %s,%s,#%d\n",regname[rt],regname[rs],imm);
937   assert(0);
938 }
939
940 static void save_regs_all(u_int reglist)
941 {
942   if(!reglist) return;
943   assert(0);
944 }
945
946 static void restore_regs_all(u_int reglist)
947 {
948   if(!reglist) return;
949   assert(0);
950 }
951
952 // Save registers before function call
953 static void save_regs(u_int reglist)
954 {
955   reglist &= CALLER_SAVE_REGS; // only save the caller-save registers
956   save_regs_all(reglist);
957 }
958
959 // Restore registers after function call
960 static void restore_regs(u_int reglist)
961 {
962   reglist &= CALLER_SAVE_REGS;
963   restore_regs_all(reglist);
964 }
965
966 /* Stubs/epilogue */
967
968 static void literal_pool(int n)
969 {
970   (void)literals;
971 }
972
973 static void literal_pool_jumpover(int n)
974 {
975 }
976
977 static void emit_extjump2(u_char *addr, int target, void *linker)
978 {
979   assert(0);
980 }
981
982 static void emit_extjump(void *addr, int target)
983 {
984   emit_extjump2(addr, target, dyna_linker);
985 }
986
987 static void emit_extjump_ds(void *addr, int target)
988 {
989   emit_extjump2(addr, target, dyna_linker_ds);
990 }
991
992 // put rt_val into rt, potentially making use of rs with value rs_val
993 static void emit_movimm_from(u_int rs_val,u_int rs,u_int rt_val,u_int rt)
994 {
995   assert(0);
996 }
997
998 // return 1 if above function can do it's job cheaply
999 static int is_similar_value(u_int v1,u_int v2)
1000 {
1001   assert(0);
1002   return 0;
1003 }
1004
1005 //#include "pcsxmem.h"
1006 //#include "pcsxmem_inline.c"
1007
1008 static void do_readstub(int n)
1009 {
1010   assem_debug("do_readstub %x\n",start+stubs[n].a*4);
1011   assert(0);
1012 }
1013
1014 static void inline_readstub(enum stub_type type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
1015 {
1016   assert(0);
1017 }
1018
1019 static void do_writestub(int n)
1020 {
1021   assem_debug("do_writestub %x\n",start+stubs[n].a*4);
1022   assert(0);
1023 }
1024
1025 static void inline_writestub(enum stub_type type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
1026 {
1027   assert(0);
1028 }
1029
1030 static void do_unalignedwritestub(int n)
1031 {
1032   assem_debug("do_unalignedwritestub %x\n",start+stubs[n].a*4);
1033   assert(0);
1034 }
1035
1036 static void do_invstub(int n)
1037 {
1038   assert(0);
1039 }
1040
1041 void *do_dirty_stub(int i)
1042 {
1043   assem_debug("do_dirty_stub %x\n",start+i*4);
1044   // Careful about the code output here, verify_dirty needs to parse it.
1045   assert(0);
1046   load_regs_entry(i);
1047   return NULL;
1048 }
1049
1050 static void do_dirty_stub_ds()
1051 {
1052   // Careful about the code output here, verify_dirty needs to parse it.
1053   assert(0);
1054 }
1055
1056 /* Special assem */
1057
1058 #define shift_assemble shift_assemble_arm64
1059
1060 static void shift_assemble_arm64(int i,struct regstat *i_regs)
1061 {
1062   assert(0);
1063 }
1064 #define loadlr_assemble loadlr_assemble_arm64
1065
1066 static void loadlr_assemble_arm64(int i,struct regstat *i_regs)
1067 {
1068   assert(0);
1069 }
1070
1071 static void c2op_assemble(int i,struct regstat *i_regs)
1072 {
1073   assert(0);
1074 }
1075
1076 static void multdiv_assemble_arm64(int i,struct regstat *i_regs)
1077 {
1078   assert(0);
1079 }
1080 #define multdiv_assemble multdiv_assemble_arm64
1081
1082 static void do_preload_rhash(u_int r) {
1083   // Don't need this for ARM.  On x86, this puts the value 0xf8 into the
1084   // register.  On ARM the hash can be done with a single instruction (below)
1085 }
1086
1087 static void do_preload_rhtbl(u_int ht) {
1088   emit_addimm(FP, (u_char *)&mini_ht - (u_char *)&dynarec_local, ht);
1089 }
1090
1091 static void do_rhash(u_int rs,u_int rh) {
1092   emit_andimm(rs, 0xf8, rh);
1093 }
1094
1095 static void do_miniht_load(int ht,u_int rh) {
1096   assem_debug("ldr %s,[%s,%s]!\n",regname[rh],regname[ht],regname[rh]);
1097   assert(0);
1098 }
1099
1100 static void do_miniht_jump(u_int rs,u_int rh,int ht) {
1101   emit_cmp(rh,rs);
1102   emit_ldreq_indexed(ht,4,15);
1103   //emit_jmp(jump_vaddr_reg[rs]);
1104   assert(0);
1105 }
1106
1107 static void do_miniht_insert(u_int return_address,u_int rt,int temp) {
1108   assert(0);
1109 }
1110
1111 static void mark_clear_cache(void *target)
1112 {
1113   u_long offset = (u_char *)target - translation_cache;
1114   u_int mask = 1u << ((offset >> 12) & 31);
1115   if (!(needs_clear_cache[offset >> 17] & mask)) {
1116     char *start = (char *)((u_long)target & ~4095ul);
1117     start_tcache_write(start, start + 4096);
1118     needs_clear_cache[offset >> 17] |= mask;
1119   }
1120 }
1121
1122 // Clearing the cache is rather slow on ARM Linux, so mark the areas
1123 // that need to be cleared, and then only clear these areas once.
1124 static void do_clear_cache()
1125 {
1126   int i,j;
1127   for (i=0;i<(1<<(TARGET_SIZE_2-17));i++)
1128   {
1129     u_int bitmap=needs_clear_cache[i];
1130     if(bitmap) {
1131       u_char *start, *end;
1132       for(j=0;j<32;j++)
1133       {
1134         if(bitmap&(1<<j)) {
1135           start=translation_cache+i*131072+j*4096;
1136           end=start+4095;
1137           j++;
1138           while(j<32) {
1139             if(bitmap&(1<<j)) {
1140               end+=4096;
1141               j++;
1142             }else{
1143               end_tcache_write(start, end);
1144               break;
1145             }
1146           }
1147         }
1148       }
1149       needs_clear_cache[i]=0;
1150     }
1151   }
1152 }
1153
1154 // CPU-architecture-specific initialization
1155 static void arch_init() {
1156 }
1157
1158 // vim:shiftwidth=2:expandtab