drc: starting arm64 support
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / assem_arm64.c
CommitLineData
be516ebe 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)
26u_char *translation_cache;
27#else
28u_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
35extern int cycle_count;
36extern int last_count;
37extern int pcaddr;
38extern int pending_exception;
39extern int branch_target;
40extern u_int mini_ht[32][2];
41
42static u_int needs_clear_cache[1<<(TARGET_SIZE_2-17)];
43
44//void indirect_jump_indexed();
45//void indirect_jump();
46void do_interrupt();
47//void jump_vaddr_r0();
48
49void * const jump_vaddr_reg[32];
50
51/* Linker */
52
53static 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
60static 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
70static 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
79static void *get_clean_addr(void *addr)
80{
81 assert(0);
82 return NULL;
83}
84
85static 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
93static 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)
100static void get_bounds(void *addr, u_char **start, u_char **end)
101{
102 assert(0);
103}
104
105// Allocate a specific ARM register.
106static 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
127static 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
137static 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"
145static void output_w32(u_int word)
146{
147 *((u_int *)out) = word;
148 out += 4;
149}
150
151static 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
159static 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
166static 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
179static 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
192static 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
198static 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
204static 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
210static 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
216static 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
222static 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
228static 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
234static 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
240static void emit_zeroreg(u_int rt)
241{
242 assem_debug("mov %s,#0\n",regname[rt]);
243 assert(0);
244}
245
246static 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
253static 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
259static 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
272static 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
294static 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
310static 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
316static void emit_testimm(u_int rs,int imm)
317{
318 assem_debug("tst %s,#%d\n",regname[rs],imm);
319 assert(0);
320}
321
322static void emit_testeqimm(u_int rs,int imm)
323{
324 assem_debug("tsteq %s,$%d\n",regname[rs],imm);
325 assert(0);
326}
327
328static 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
334static 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
340static 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
346static 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
352static 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
361static 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
370static 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
376static 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
382static 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
389static void emit_addimm_and_set_flags(int imm, u_int rt)
390{
391 assert(0);
392}
393
394static void emit_addimm_no_flags(u_int imm,u_int rt)
395{
396 emit_addimm(rt,imm,rt);
397}
398
399static 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
406static 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
412static 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
418static void emit_addimm64_32(u_int rsh,u_int rsl,int imm,u_int rth,u_int rtl)
419{
420 assert(0);
421}
422
423static void emit_andimm(u_int rs,int imm,u_int rt)
424{
425 assert(0);
426}
427
428static void emit_orimm(u_int rs,int imm,u_int rt)
429{
430 assert(0);
431}
432
433static void emit_xorimm(u_int rs,int imm,u_int rt)
434{
435 assert(0);
436}
437
438static 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
446static 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
454static 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
462static 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
470static 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
478static 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
486static 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
492static 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
500static 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
509static 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
518static 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
527static 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
536static void emit_cmpimm(u_int rs,int imm)
537{
538 assert(0);
539}
540
541static 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
547static 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
553static 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
559static 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
565static 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
571static 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
577static 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
583static 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
591static 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
599static 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
605static 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
613static void emit_set_nz32(u_int rs, u_int rt)
614{
615 //assem_debug("set_nz32\n");
616 assert(0);
617}
618
619static 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
628static 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"
638static 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
645static 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
652static 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
659static void emit_jeq(int a)
660{
661 assem_debug("beq %x\n",a);
662 assert(0);
663}
664
665static void emit_js(int a)
666{
667 assem_debug("bmi %x\n",a);
668 assert(0);
669}
670
671static void emit_jns(int a)
672{
673 assem_debug("bpl %x\n",a);
674 assert(0);
675}
676
677static void emit_jl(int a)
678{
679 assem_debug("blt %x\n",a);
680 assert(0);
681}
682
683static void emit_jge(int a)
684{
685 assem_debug("bge %x\n",a);
686 assert(0);
687}
688
689static void emit_jno(int a)
690{
691 assem_debug("bvc %x\n",a);
692 assert(0);
693}
694
695static void emit_jc(int a)
696{
697 assem_debug("bcs %x\n",a);
698 assert(0);
699}
700
701static 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
708static void emit_callreg(u_int r)
709{
710 assert(r < 31);
711 assem_debug("blx %s\n", regname[r]);
712 assert(0);
713}
714
715static void emit_jmpreg(u_int r)
716{
717 assem_debug("mov pc,%s\n",regname[r]);
718 assert(0);
719}
720
721static 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
727static void emit_ret(void)
728{
729 emit_retreg(LR);
730}
731
732static 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
738static 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
744static 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
750static 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
756static 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
762static 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
768static 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
774static 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
780static 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
786static 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
792static 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
798static 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
804static 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
812static 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
819static 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
826static 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
833static 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
839static 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
845static 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
851static 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
859static 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
869static 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
879static 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
886static 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
893static 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
899static 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
908static 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
915static 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
922static 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
928static 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
934static 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
940static void save_regs_all(u_int reglist)
941{
942 if(!reglist) return;
943 assert(0);
944}
945
946static void restore_regs_all(u_int reglist)
947{
948 if(!reglist) return;
949 assert(0);
950}
951
952// Save registers before function call
953static 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
960static void restore_regs(u_int reglist)
961{
962 reglist &= CALLER_SAVE_REGS;
963 restore_regs_all(reglist);
964}
965
966/* Stubs/epilogue */
967
968static void literal_pool(int n)
969{
970 (void)literals;
971}
972
973static void literal_pool_jumpover(int n)
974{
975}
976
977static void emit_extjump2(u_char *addr, int target, void *linker)
978{
979 assert(0);
980}
981
982static void emit_extjump(void *addr, int target)
983{
984 emit_extjump2(addr, target, dyna_linker);
985}
986
987static 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
993static 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
999static 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
1008static void do_readstub(int n)
1009{
1010 assem_debug("do_readstub %x\n",start+stubs[n].a*4);
1011 assert(0);
1012}
1013
1014static 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
1019static void do_writestub(int n)
1020{
1021 assem_debug("do_writestub %x\n",start+stubs[n].a*4);
1022 assert(0);
1023}
1024
1025static 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
1030static void do_unalignedwritestub(int n)
1031{
1032 assem_debug("do_unalignedwritestub %x\n",start+stubs[n].a*4);
1033 assert(0);
1034}
1035
1036static void do_invstub(int n)
1037{
1038 assert(0);
1039}
1040
1041void *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
1050static 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
1060static void shift_assemble_arm64(int i,struct regstat *i_regs)
1061{
1062 assert(0);
1063}
1064#define loadlr_assemble loadlr_assemble_arm64
1065
1066static void loadlr_assemble_arm64(int i,struct regstat *i_regs)
1067{
1068 assert(0);
1069}
1070
1071static void c2op_assemble(int i,struct regstat *i_regs)
1072{
1073 assert(0);
1074}
1075
1076static void multdiv_assemble_arm64(int i,struct regstat *i_regs)
1077{
1078 assert(0);
1079}
1080#define multdiv_assemble multdiv_assemble_arm64
1081
1082static 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
1087static void do_preload_rhtbl(u_int ht) {
1088 emit_addimm(FP, (u_char *)&mini_ht - (u_char *)&dynarec_local, ht);
1089}
1090
1091static void do_rhash(u_int rs,u_int rh) {
1092 emit_andimm(rs, 0xf8, rh);
1093}
1094
1095static 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
1100static 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
1107static void do_miniht_insert(u_int return_address,u_int rt,int temp) {
1108 assert(0);
1109}
1110
1111static 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.
1124static 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
1155static void arch_init() {
1156}
1157
1158// vim:shiftwidth=2:expandtab