0fafc60addcee38035eda9bff7e6d264fdec8215
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / new_dynarec.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   Mupen64plus - new_dynarec.c                                           *
3  *   Copyright (C) 2009-2011 Ari64                                         *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
19  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20
21 #include <stdlib.h>
22 #include <stdint.h> //include for uint64_t
23 #include <assert.h>
24 #include <errno.h>
25 #include <sys/mman.h>
26 #ifdef __MACH__
27 #include <libkern/OSCacheControl.h>
28 #endif
29 #ifdef _3DS
30 #include <3ds_utils.h>
31 #endif
32 #ifdef HAVE_LIBNX
33 #include <switch.h>
34 static Jit g_jit;
35 #endif
36
37 #include "new_dynarec_config.h"
38 #include "../psxhle.h"
39 #include "../psxinterpreter.h"
40 #include "../gte.h"
41 #include "emu_if.h" // emulator interface
42 #include "arm_features.h"
43
44 #ifdef __clang__
45 #define noinline __attribute__((noinline))
46 #else
47 #define noinline __attribute__((noinline,noclone))
48 #endif
49 #ifndef ARRAY_SIZE
50 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
51 #endif
52 #ifndef min
53 #define min(a, b) ((b) < (a) ? (b) : (a))
54 #endif
55 #ifndef max
56 #define max(a, b) ((b) > (a) ? (b) : (a))
57 #endif
58
59 //#define DISASM
60 //#define ASSEM_PRINT
61 //#define STAT_PRINT
62
63 #ifdef ASSEM_PRINT
64 #define assem_debug printf
65 #else
66 #define assem_debug(...)
67 #endif
68 //#define inv_debug printf
69 #define inv_debug(...)
70
71 #ifdef __i386__
72 #include "assem_x86.h"
73 #endif
74 #ifdef __x86_64__
75 #include "assem_x64.h"
76 #endif
77 #ifdef __arm__
78 #include "assem_arm.h"
79 #endif
80 #ifdef __aarch64__
81 #include "assem_arm64.h"
82 #endif
83
84 #define RAM_SIZE 0x200000
85 #define MAXBLOCK 4096
86 #define MAX_OUTPUT_BLOCK_SIZE 262144
87 #define EXPIRITY_OFFSET (MAX_OUTPUT_BLOCK_SIZE * 2)
88 #define PAGE_COUNT 1024
89
90 #if defined(HAVE_CONDITIONAL_CALL) && !defined(DESTRUCTIVE_SHIFT)
91 #define INVALIDATE_USE_COND_CALL
92 #endif
93
94 #ifdef VITA
95 // apparently Vita has a 16MB limit, so either we cut tc in half,
96 // or use this hack (it's a hack because tc size was designed to be power-of-2)
97 #define TC_REDUCE_BYTES 4096
98 #else
99 #define TC_REDUCE_BYTES 0
100 #endif
101
102 struct ndrc_tramp
103 {
104   struct tramp_insns ops[2048 / sizeof(struct tramp_insns)];
105   const void *f[2048 / sizeof(void *)];
106 };
107
108 struct ndrc_mem
109 {
110   u_char translation_cache[(1 << TARGET_SIZE_2) - TC_REDUCE_BYTES];
111   struct ndrc_tramp tramp;
112 };
113
114 #ifdef BASE_ADDR_DYNAMIC
115 static struct ndrc_mem *ndrc;
116 #else
117 static struct ndrc_mem ndrc_ __attribute__((aligned(4096)));
118 static struct ndrc_mem *ndrc = &ndrc_;
119 #endif
120 #ifdef TC_WRITE_OFFSET
121 # ifdef __GLIBC__
122 # include <sys/types.h>
123 # include <sys/stat.h>
124 # include <fcntl.h>
125 # include <unistd.h>
126 # endif
127 static long ndrc_write_ofs;
128 #define NDRC_WRITE_OFFSET(x) (void *)((char *)(x) + ndrc_write_ofs)
129 #else
130 #define NDRC_WRITE_OFFSET(x) (x)
131 #endif
132
133 // stubs
134 enum stub_type {
135   CC_STUB = 1,
136   FP_STUB = 2,
137   LOADB_STUB = 3,
138   LOADH_STUB = 4,
139   LOADW_STUB = 5,
140   LOADD_STUB = 6,
141   LOADBU_STUB = 7,
142   LOADHU_STUB = 8,
143   STOREB_STUB = 9,
144   STOREH_STUB = 10,
145   STOREW_STUB = 11,
146   STORED_STUB = 12,
147   STORELR_STUB = 13,
148   INVCODE_STUB = 14,
149 };
150
151 // regmap_pre[i]    - regs before [i] insn starts; dirty things here that
152 //                    don't match .regmap will be written back
153 // [i].regmap_entry - regs that must be set up if someone jumps here
154 // [i].regmap       - regs [i] insn will read/(over)write
155 // branch_regs[i].* - same as above but for branches, takes delay slot into account
156 struct regstat
157 {
158   signed char regmap_entry[HOST_REGS];
159   signed char regmap[HOST_REGS];
160   uint64_t wasdirty;
161   uint64_t dirty;
162   uint64_t u;
163   u_int wasconst;                // before; for example 'lw r2, (r2)' wasconst is true
164   u_int isconst;                 //  ... but isconst is false when r2 is known
165   u_int loadedconst;             // host regs that have constants loaded
166   u_int waswritten;              // MIPS regs that were used as store base before
167 };
168
169 struct ht_entry
170 {
171   u_int vaddr[2];
172   void *tcaddr[2];
173 };
174
175 struct code_stub
176 {
177   enum stub_type type;
178   void *addr;
179   void *retaddr;
180   u_int a;
181   uintptr_t b;
182   uintptr_t c;
183   u_int d;
184   u_int e;
185 };
186
187 struct link_entry
188 {
189   void *addr;
190   u_int target;
191   u_int internal;
192 };
193
194 struct block_info
195 {
196   struct block_info *next;
197   const void *source;
198   const void *copy;
199   u_int start; // vaddr of the block start
200   u_int len;   // of the whole block source
201   u_int tc_offs;
202   //u_int tc_len;
203   u_int reg_sv_flags;
204   u_char is_dirty;
205   u_char inv_near_misses;
206   u_short jump_in_cnt;
207   struct {
208     u_int vaddr;
209     void *addr;
210   } jump_in[0];
211 };
212
213 struct jump_info
214 {
215   int alloc;
216   int count;
217   struct {
218     u_int target_vaddr;
219     void *stub;
220   } e[0];
221 };
222
223 static struct decoded_insn
224 {
225   u_char itype;
226   u_char opcode;
227   u_char opcode2;
228   u_char rs1;
229   u_char rs2;
230   u_char rt1;
231   u_char rt2;
232   u_char use_lt1:1;
233   u_char bt:1;
234   u_char ooo:1;
235   u_char is_ds:1;
236   u_char is_jump:1;
237   u_char is_ujump:1;
238   u_char is_load:1;
239   u_char is_store:1;
240 } dops[MAXBLOCK];
241
242   static u_char *out;
243   static struct ht_entry hash_table[65536];
244   static struct block_info *blocks[PAGE_COUNT];
245   static struct jump_info *jumps[PAGE_COUNT];
246   static u_int start;
247   static u_int *source;
248   static uint64_t gte_rs[MAXBLOCK]; // gte: 32 data and 32 ctl regs
249   static uint64_t gte_rt[MAXBLOCK];
250   static uint64_t gte_unneeded[MAXBLOCK];
251   static u_int smrv[32]; // speculated MIPS register values
252   static u_int smrv_strong; // mask or regs that are likely to have correct values
253   static u_int smrv_weak; // same, but somewhat less likely
254   static u_int smrv_strong_next; // same, but after current insn executes
255   static u_int smrv_weak_next;
256   static int imm[MAXBLOCK];
257   static u_int ba[MAXBLOCK];
258   static uint64_t unneeded_reg[MAXBLOCK];
259   static uint64_t branch_unneeded_reg[MAXBLOCK];
260   // see 'struct regstat' for a description
261   static signed char regmap_pre[MAXBLOCK][HOST_REGS];
262   // contains 'real' consts at [i] insn, but may differ from what's actually
263   // loaded in host reg as 'final' value is always loaded, see get_final_value()
264   static uint32_t current_constmap[HOST_REGS];
265   static uint32_t constmap[MAXBLOCK][HOST_REGS];
266   static struct regstat regs[MAXBLOCK];
267   static struct regstat branch_regs[MAXBLOCK];
268   static signed char minimum_free_regs[MAXBLOCK];
269   static int ccadj[MAXBLOCK];
270   static int slen;
271   static void *instr_addr[MAXBLOCK];
272   static struct link_entry link_addr[MAXBLOCK];
273   static int linkcount;
274   static struct code_stub stubs[MAXBLOCK*3];
275   static int stubcount;
276   static u_int literals[1024][2];
277   static int literalcount;
278   static int is_delayslot;
279   static char shadow[1048576]  __attribute__((aligned(16)));
280   static void *copy;
281   static u_int expirep;
282   static u_int stop_after_jal;
283   static u_int f1_hack;
284 #ifdef STAT_PRINT
285   static int stat_bc_direct;
286   static int stat_bc_pre;
287   static int stat_bc_restore;
288   static int stat_ht_lookups;
289   static int stat_jump_in_lookups;
290   static int stat_restore_tries;
291   static int stat_restore_compares;
292   static int stat_inv_addr_calls;
293   static int stat_inv_hits;
294   static int stat_blocks;
295   static int stat_links;
296   #define stat_inc(s) s++
297   #define stat_dec(s) s--
298   #define stat_clear(s) s = 0
299 #else
300   #define stat_inc(s)
301   #define stat_dec(s)
302   #define stat_clear(s)
303 #endif
304
305   int new_dynarec_hacks;
306   int new_dynarec_hacks_pergame;
307   int new_dynarec_hacks_old;
308   int new_dynarec_did_compile;
309
310   #define HACK_ENABLED(x) ((new_dynarec_hacks | new_dynarec_hacks_pergame) & (x))
311
312   extern int cycle_count; // ... until end of the timeslice, counts -N -> 0
313   extern int last_count;  // last absolute target, often = next_interupt
314   extern int pcaddr;
315   extern int pending_exception;
316   extern int branch_target;
317   extern uintptr_t ram_offset;
318   extern uintptr_t mini_ht[32][2];
319
320   /* registers that may be allocated */
321   /* 1-31 gpr */
322 #define LOREG 32 // lo
323 #define HIREG 33 // hi
324 //#define FSREG 34 // FPU status (FCSR)
325 #define CSREG 35 // Coprocessor status
326 #define CCREG 36 // Cycle count
327 #define INVCP 37 // Pointer to invalid_code
328 //#define MMREG 38 // Pointer to memory_map
329 #define ROREG 39 // ram offset (if rdram!=0x80000000)
330 #define TEMPREG 40
331 #define FTEMP 40 // FPU temporary register
332 #define PTEMP 41 // Prefetch temporary register
333 //#define TLREG 42 // TLB mapping offset
334 #define RHASH 43 // Return address hash
335 #define RHTBL 44 // Return address hash table address
336 #define RTEMP 45 // JR/JALR address register
337 #define MAXREG 45
338 #define AGEN1 46 // Address generation temporary register
339 //#define AGEN2 47 // Address generation temporary register
340 //#define MGEN1 48 // Maptable address generation temporary register
341 //#define MGEN2 49 // Maptable address generation temporary register
342 #define BTREG 50 // Branch target temporary register
343
344   /* instruction types */
345 #define NOP 0     // No operation
346 #define LOAD 1    // Load
347 #define STORE 2   // Store
348 #define LOADLR 3  // Unaligned load
349 #define STORELR 4 // Unaligned store
350 #define MOV 5     // Move
351 #define ALU 6     // Arithmetic/logic
352 #define MULTDIV 7 // Multiply/divide
353 #define SHIFT 8   // Shift by register
354 #define SHIFTIMM 9// Shift by immediate
355 #define IMM16 10  // 16-bit immediate
356 #define RJUMP 11  // Unconditional jump to register
357 #define UJUMP 12  // Unconditional jump
358 #define CJUMP 13  // Conditional branch (BEQ/BNE/BGTZ/BLEZ)
359 #define SJUMP 14  // Conditional branch (regimm format)
360 #define COP0 15   // Coprocessor 0
361 #define COP1 16   // Coprocessor 1
362 #define C1LS 17   // Coprocessor 1 load/store
363 //#define FJUMP 18  // Conditional branch (floating point)
364 //#define FLOAT 19  // Floating point unit
365 //#define FCONV 20  // Convert integer to float
366 //#define FCOMP 21  // Floating point compare (sets FSREG)
367 #define SYSCALL 22// SYSCALL,BREAK
368 #define OTHER 23  // Other
369 //#define SPAN 24   // Branch/delay slot spans 2 pages
370 #define NI 25     // Not implemented
371 #define HLECALL 26// PCSX fake opcodes for HLE
372 #define COP2 27   // Coprocessor 2 move
373 #define C2LS 28   // Coprocessor 2 load/store
374 #define C2OP 29   // Coprocessor 2 operation
375 #define INTCALL 30// Call interpreter to handle rare corner cases
376
377   /* branch codes */
378 #define TAKEN 1
379 #define NOTTAKEN 2
380 #define NULLDS 3
381
382 #define DJT_1 (void *)1l // no function, just a label in assem_debug log
383 #define DJT_2 (void *)2l
384
385 // asm linkage
386 void dyna_linker();
387 void cc_interrupt();
388 void fp_exception();
389 void fp_exception_ds();
390 void jump_syscall   (u_int u0, u_int u1, u_int pc);
391 void jump_syscall_ds(u_int u0, u_int u1, u_int pc);
392 void jump_break   (u_int u0, u_int u1, u_int pc);
393 void jump_break_ds(u_int u0, u_int u1, u_int pc);
394 void jump_to_new_pc();
395 void call_gteStall();
396 void new_dyna_leave();
397
398 void *ndrc_get_addr_ht_param(u_int vaddr, int can_compile);
399 void *ndrc_get_addr_ht(u_int vaddr);
400 void ndrc_invalidate_addr(u_int addr);
401 void ndrc_add_jump_out(u_int vaddr, void *src);
402
403 static int new_recompile_block(u_int addr);
404 static void invalidate_block(struct block_info *block);
405
406 // Needed by assembler
407 static void wb_register(signed char r, const signed char regmap[], uint64_t dirty);
408 static void wb_dirtys(const signed char i_regmap[], uint64_t i_dirty);
409 static void wb_needed_dirtys(const signed char i_regmap[], uint64_t i_dirty, int addr);
410 static void load_all_regs(const signed char i_regmap[]);
411 static void load_needed_regs(const signed char i_regmap[], const signed char next_regmap[]);
412 static void load_regs_entry(int t);
413 static void load_all_consts(const signed char regmap[], u_int dirty, int i);
414 static u_int get_host_reglist(const signed char *regmap);
415
416 static int get_final_value(int hr, int i, int *value);
417 static void add_stub(enum stub_type type, void *addr, void *retaddr,
418   u_int a, uintptr_t b, uintptr_t c, u_int d, u_int e);
419 static void add_stub_r(enum stub_type type, void *addr, void *retaddr,
420   int i, int addr_reg, const struct regstat *i_regs, int ccadj, u_int reglist);
421 static void add_to_linker(void *addr, u_int target, int ext);
422 static void *emit_fastpath_cmp_jump(int i, const struct regstat *i_regs,
423   int addr, int *offset_reg, int *addr_reg_override);
424 static void *get_direct_memhandler(void *table, u_int addr,
425   enum stub_type type, uintptr_t *addr_host);
426 static void cop2_do_stall_check(u_int op, int i, const struct regstat *i_regs, u_int reglist);
427 static void pass_args(int a0, int a1);
428 static void emit_far_jump(const void *f);
429 static void emit_far_call(const void *f);
430
431 #ifdef VITA
432 #include <psp2/kernel/sysmem.h>
433 static int sceBlock;
434 // note: this interacts with RetroArch's Vita bootstrap code: bootstrap/vita/sbrk.c
435 extern int getVMBlock();
436 int _newlib_vm_size_user = sizeof(*ndrc);
437 #endif
438
439 static void mprotect_w_x(void *start, void *end, int is_x)
440 {
441 #ifdef NO_WRITE_EXEC
442   #if defined(VITA)
443   // *Open* enables write on all memory that was
444   // allocated by sceKernelAllocMemBlockForVM()?
445   if (is_x)
446     sceKernelCloseVMDomain();
447   else
448     sceKernelOpenVMDomain();
449   #elif defined(HAVE_LIBNX)
450   Result rc;
451   // check to avoid the full flush in jitTransitionToExecutable()
452   if (g_jit.type != JitType_CodeMemory) {
453     if (is_x)
454       rc = jitTransitionToExecutable(&g_jit);
455     else
456       rc = jitTransitionToWritable(&g_jit);
457     if (R_FAILED(rc))
458       ;//SysPrintf("jitTransition %d %08x\n", is_x, rc);
459   }
460   #elif defined(TC_WRITE_OFFSET)
461   // separated rx and rw areas are always available
462   #else
463   u_long mstart = (u_long)start & ~4095ul;
464   u_long mend = (u_long)end;
465   if (mprotect((void *)mstart, mend - mstart,
466                PROT_READ | (is_x ? PROT_EXEC : PROT_WRITE)) != 0)
467     SysPrintf("mprotect(%c) failed: %s\n", is_x ? 'x' : 'w', strerror(errno));
468   #endif
469 #endif
470 }
471
472 static void start_tcache_write(void *start, void *end)
473 {
474   mprotect_w_x(start, end, 0);
475 }
476
477 static void end_tcache_write(void *start, void *end)
478 {
479 #if defined(__arm__) || defined(__aarch64__)
480   size_t len = (char *)end - (char *)start;
481   #if   defined(__BLACKBERRY_QNX__)
482   msync(start, len, MS_SYNC | MS_CACHE_ONLY | MS_INVALIDATE_ICACHE);
483   #elif defined(__MACH__)
484   sys_cache_control(kCacheFunctionPrepareForExecution, start, len);
485   #elif defined(VITA)
486   sceKernelSyncVMDomain(sceBlock, start, len);
487   #elif defined(_3DS)
488   ctr_flush_invalidate_cache();
489   #elif defined(HAVE_LIBNX)
490   if (g_jit.type == JitType_CodeMemory) {
491     armDCacheClean(start, len);
492     armICacheInvalidate((char *)start - ndrc_write_ofs, len);
493     // as of v4.2.1 libnx lacks isb
494     __asm__ volatile("isb" ::: "memory");
495   }
496   #elif defined(__aarch64__)
497   // as of 2021, __clear_cache() is still broken on arm64
498   // so here is a custom one :(
499   clear_cache_arm64(start, end);
500   #else
501   __clear_cache(start, end);
502   #endif
503   (void)len;
504 #endif
505
506   mprotect_w_x(start, end, 1);
507 }
508
509 static void *start_block(void)
510 {
511   u_char *end = out + MAX_OUTPUT_BLOCK_SIZE;
512   if (end > ndrc->translation_cache + sizeof(ndrc->translation_cache))
513     end = ndrc->translation_cache + sizeof(ndrc->translation_cache);
514   start_tcache_write(NDRC_WRITE_OFFSET(out), NDRC_WRITE_OFFSET(end));
515   return out;
516 }
517
518 static void end_block(void *start)
519 {
520   end_tcache_write(NDRC_WRITE_OFFSET(start), NDRC_WRITE_OFFSET(out));
521 }
522
523 #ifdef NDRC_CACHE_FLUSH_ALL
524
525 static int needs_clear_cache;
526
527 static void mark_clear_cache(void *target)
528 {
529   if (!needs_clear_cache) {
530     start_tcache_write(NDRC_WRITE_OFFSET(ndrc), NDRC_WRITE_OFFSET(ndrc + 1));
531     needs_clear_cache = 1;
532   }
533 }
534
535 static void do_clear_cache(void)
536 {
537   if (needs_clear_cache) {
538     end_tcache_write(NDRC_WRITE_OFFSET(ndrc), NDRC_WRITE_OFFSET(ndrc + 1));
539     needs_clear_cache = 0;
540   }
541 }
542
543 #else
544
545 // also takes care of w^x mappings when patching code
546 static u_int needs_clear_cache[1<<(TARGET_SIZE_2-17)];
547
548 static void mark_clear_cache(void *target)
549 {
550   uintptr_t offset = (u_char *)target - ndrc->translation_cache;
551   u_int mask = 1u << ((offset >> 12) & 31);
552   if (!(needs_clear_cache[offset >> 17] & mask)) {
553     char *start = (char *)NDRC_WRITE_OFFSET((uintptr_t)target & ~4095l);
554     start_tcache_write(start, start + 4095);
555     needs_clear_cache[offset >> 17] |= mask;
556   }
557 }
558
559 // Clearing the cache is rather slow on ARM Linux, so mark the areas
560 // that need to be cleared, and then only clear these areas once.
561 static void do_clear_cache(void)
562 {
563   int i, j;
564   for (i = 0; i < (1<<(TARGET_SIZE_2-17)); i++)
565   {
566     u_int bitmap = needs_clear_cache[i];
567     if (!bitmap)
568       continue;
569     for (j = 0; j < 32; j++)
570     {
571       u_char *start, *end;
572       if (!(bitmap & (1u << j)))
573         continue;
574
575       start = ndrc->translation_cache + i*131072 + j*4096;
576       end = start + 4095;
577       for (j++; j < 32; j++) {
578         if (!(bitmap & (1u << j)))
579           break;
580         end += 4096;
581       }
582       end_tcache_write(NDRC_WRITE_OFFSET(start), NDRC_WRITE_OFFSET(end));
583     }
584     needs_clear_cache[i] = 0;
585   }
586 }
587
588 #endif // NDRC_CACHE_FLUSH_ALL
589
590 #define NO_CYCLE_PENALTY_THR 12
591
592 int cycle_multiplier = CYCLE_MULT_DEFAULT; // 100 for 1.0
593 int cycle_multiplier_override;
594 int cycle_multiplier_old;
595 static int cycle_multiplier_active;
596
597 static int CLOCK_ADJUST(int x)
598 {
599   int m = cycle_multiplier_active;
600   int s = (x >> 31) | 1;
601   return (x * m + s * 50) / 100;
602 }
603
604 static int ds_writes_rjump_rs(int i)
605 {
606   return dops[i].rs1 != 0 && (dops[i].rs1 == dops[i+1].rt1 || dops[i].rs1 == dops[i+1].rt2);
607 }
608
609 // psx addr mirror masking (for invalidation)
610 static u_int pmmask(u_int vaddr)
611 {
612   vaddr &= ~0xe0000000;
613   if (vaddr < 0x01000000)
614     vaddr &= ~0x00e00000; // RAM mirrors
615   return vaddr;
616 }
617
618 static u_int get_page(u_int vaddr)
619 {
620   u_int page = pmmask(vaddr) >> 12;
621   if (page >= PAGE_COUNT / 2)
622     page = PAGE_COUNT / 2 + (page & (PAGE_COUNT / 2 - 1));
623   return page;
624 }
625
626 // get a page for looking for a block that has vaddr
627 // (needed because the block may start in previous page)
628 static u_int get_page_prev(u_int vaddr)
629 {
630   assert(MAXBLOCK <= (1 << 12));
631   u_int page = get_page(vaddr);
632   if (page & 511)
633     page--;
634   return page;
635 }
636
637 static struct ht_entry *hash_table_get(u_int vaddr)
638 {
639   return &hash_table[((vaddr>>16)^vaddr)&0xFFFF];
640 }
641
642 static void hash_table_add(u_int vaddr, void *tcaddr)
643 {
644   struct ht_entry *ht_bin = hash_table_get(vaddr);
645   assert(tcaddr);
646   ht_bin->vaddr[1] = ht_bin->vaddr[0];
647   ht_bin->tcaddr[1] = ht_bin->tcaddr[0];
648   ht_bin->vaddr[0] = vaddr;
649   ht_bin->tcaddr[0] = tcaddr;
650 }
651
652 static void hash_table_remove(int vaddr)
653 {
654   //printf("remove hash: %x\n",vaddr);
655   struct ht_entry *ht_bin = hash_table_get(vaddr);
656   if (ht_bin->vaddr[1] == vaddr) {
657     ht_bin->vaddr[1] = -1;
658     ht_bin->tcaddr[1] = NULL;
659   }
660   if (ht_bin->vaddr[0] == vaddr) {
661     ht_bin->vaddr[0] = ht_bin->vaddr[1];
662     ht_bin->tcaddr[0] = ht_bin->tcaddr[1];
663     ht_bin->vaddr[1] = -1;
664     ht_bin->tcaddr[1] = NULL;
665   }
666 }
667
668 static void mark_invalid_code(u_int vaddr, u_int len, char invalid)
669 {
670   u_int vaddr_m = vaddr & 0x1fffffff;
671   u_int i, j;
672   for (i = vaddr_m & ~0xfff; i < vaddr_m + len; i += 0x1000) {
673     // ram mirrors, but should not hurt bios
674     for (j = 0; j < 0x800000; j += 0x200000) {
675       invalid_code[(i|j) >> 12] =
676       invalid_code[(i|j|0x80000000u) >> 12] =
677       invalid_code[(i|j|0xa0000000u) >> 12] = invalid;
678     }
679   }
680   if (!invalid && vaddr + len > inv_code_start && vaddr <= inv_code_end)
681     inv_code_start = inv_code_end = ~0;
682 }
683
684 static int doesnt_expire_soon(u_char *tcaddr)
685 {
686   u_int diff = (u_int)(tcaddr - out) & ((1u << TARGET_SIZE_2) - 1u);
687   return diff > EXPIRITY_OFFSET + MAX_OUTPUT_BLOCK_SIZE;
688 }
689
690 static void *try_restore_block(u_int vaddr, u_int start_page, u_int end_page)
691 {
692   void *found_clean = NULL;
693   u_int i, page;
694
695   stat_inc(stat_restore_tries);
696   for (page = start_page; page <= end_page; page++) {
697     struct block_info *block;
698     for (block = blocks[page]; block != NULL; block = block->next) {
699       if (vaddr < block->start)
700         break;
701       if (!block->is_dirty || vaddr >= block->start + block->len)
702         continue;
703       for (i = 0; i < block->jump_in_cnt; i++)
704         if (block->jump_in[i].vaddr == vaddr)
705           break;
706       if (i == block->jump_in_cnt)
707         continue;
708       assert(block->source && block->copy);
709       stat_inc(stat_restore_compares);
710       if (memcmp(block->source, block->copy, block->len))
711         continue;
712
713       block->is_dirty = block->inv_near_misses = 0;
714       found_clean = block->jump_in[i].addr;
715       hash_table_add(vaddr, found_clean);
716       mark_invalid_code(block->start, block->len, 0);
717       stat_inc(stat_bc_restore);
718       inv_debug("INV: restored %08x %p (%d)\n", vaddr, found_clean, block->jump_in_cnt);
719       return found_clean;
720     }
721   }
722   return NULL;
723 }
724
725 // Get address from virtual address
726 // This is called from the recompiled JR/JALR instructions
727 static void noinline *get_addr(u_int vaddr, int can_compile)
728 {
729   u_int start_page = get_page_prev(vaddr);
730   u_int i, page, end_page = get_page(vaddr);
731   void *found_clean = NULL;
732
733   stat_inc(stat_jump_in_lookups);
734   for (page = start_page; page <= end_page; page++) {
735     const struct block_info *block;
736     for (block = blocks[page]; block != NULL; block = block->next) {
737       if (vaddr < block->start)
738         break;
739       if (block->is_dirty || vaddr >= block->start + block->len)
740         continue;
741       for (i = 0; i < block->jump_in_cnt; i++)
742         if (block->jump_in[i].vaddr == vaddr)
743           break;
744       if (i == block->jump_in_cnt)
745         continue;
746       found_clean = block->jump_in[i].addr;
747       hash_table_add(vaddr, found_clean);
748       return found_clean;
749     }
750   }
751   found_clean = try_restore_block(vaddr, start_page, end_page);
752   if (found_clean)
753     return found_clean;
754
755   if (!can_compile)
756     return NULL;
757
758   int r = new_recompile_block(vaddr);
759   if (r == 0)
760     return ndrc_get_addr_ht(vaddr);
761
762   // generate an address error
763   Status|=2;
764   Cause=(vaddr<<31)|(4<<2);
765   EPC=(vaddr&1)?vaddr-5:vaddr;
766   BadVAddr=(vaddr&~1);
767   return ndrc_get_addr_ht(0x80000080);
768 }
769
770 // Look up address in hash table first
771 void *ndrc_get_addr_ht_param(u_int vaddr, int can_compile)
772 {
773   const struct ht_entry *ht_bin = hash_table_get(vaddr);
774   stat_inc(stat_ht_lookups);
775   if (ht_bin->vaddr[0] == vaddr) return ht_bin->tcaddr[0];
776   if (ht_bin->vaddr[1] == vaddr) return ht_bin->tcaddr[1];
777   return get_addr(vaddr, can_compile);
778 }
779
780 void *ndrc_get_addr_ht(u_int vaddr)
781 {
782   return ndrc_get_addr_ht_param(vaddr, 1);
783 }
784
785 static void clear_all_regs(signed char regmap[])
786 {
787   memset(regmap, -1, sizeof(regmap[0]) * HOST_REGS);
788 }
789
790 // get_reg: get allocated host reg from mips reg
791 // returns -1 if no such mips reg was allocated
792 #if defined(__arm__) && defined(HAVE_ARMV6) && HOST_REGS == 13 && EXCLUDE_REG == 11
793
794 extern signed char get_reg(const signed char regmap[], signed char r);
795
796 #else
797
798 static signed char get_reg(const signed char regmap[], signed char r)
799 {
800   int hr;
801   for (hr = 0; hr < HOST_REGS; hr++) {
802     if (hr == EXCLUDE_REG)
803       continue;
804     if (regmap[hr] == r)
805       return hr;
806   }
807   return -1;
808 }
809
810 #endif
811
812 // get reg as mask bit (1 << hr)
813 static u_int get_regm(const signed char regmap[], signed char r)
814 {
815   return (1u << (get_reg(regmap, r) & 31)) & ~(1u << 31);
816 }
817
818 static signed char get_reg_temp(const signed char regmap[])
819 {
820   int hr;
821   for (hr = 0; hr < HOST_REGS; hr++) {
822     if (hr == EXCLUDE_REG)
823       continue;
824     if (regmap[hr] == (signed char)-1)
825       return hr;
826   }
827   return -1;
828 }
829
830 // Find a register that is available for two consecutive cycles
831 static signed char get_reg2(signed char regmap1[], const signed char regmap2[], int r)
832 {
833   int hr;
834   for (hr=0;hr<HOST_REGS;hr++) if(hr!=EXCLUDE_REG&&regmap1[hr]==r&&regmap2[hr]==r) return hr;
835   return -1;
836 }
837
838 // reverse reg map: mips -> host
839 #define RRMAP_SIZE 64
840 static void make_rregs(const signed char regmap[], signed char rrmap[RRMAP_SIZE],
841   u_int *regs_can_change)
842 {
843   u_int r, hr, hr_can_change = 0;
844   memset(rrmap, -1, RRMAP_SIZE);
845   for (hr = 0; hr < HOST_REGS; )
846   {
847     r = regmap[hr];
848     rrmap[r & (RRMAP_SIZE - 1)] = hr;
849     // only add mips $1-$31+$lo, others shifted out
850     hr_can_change |= (uint64_t)1 << (hr + ((r - 1) & 32));
851     hr++;
852     if (hr == EXCLUDE_REG)
853       hr++;
854   }
855   hr_can_change |= 1u << (rrmap[33] & 31);
856   hr_can_change |= 1u << (rrmap[CCREG] & 31);
857   hr_can_change &= ~(1u << 31);
858   *regs_can_change = hr_can_change;
859 }
860
861 // same as get_reg, but takes rrmap
862 static signed char get_rreg(signed char rrmap[RRMAP_SIZE], signed char r)
863 {
864   assert(0 <= r && r < RRMAP_SIZE);
865   return rrmap[r];
866 }
867
868 static int count_free_regs(const signed char regmap[])
869 {
870   int count=0;
871   int hr;
872   for(hr=0;hr<HOST_REGS;hr++)
873   {
874     if(hr!=EXCLUDE_REG) {
875       if(regmap[hr]<0) count++;
876     }
877   }
878   return count;
879 }
880
881 static void dirty_reg(struct regstat *cur, signed char reg)
882 {
883   int hr;
884   if (!reg) return;
885   hr = get_reg(cur->regmap, reg);
886   if (hr >= 0)
887     cur->dirty |= 1<<hr;
888 }
889
890 static void set_const(struct regstat *cur, signed char reg, uint32_t value)
891 {
892   int hr;
893   if (!reg) return;
894   hr = get_reg(cur->regmap, reg);
895   if (hr >= 0) {
896     cur->isconst |= 1<<hr;
897     current_constmap[hr] = value;
898   }
899 }
900
901 static void clear_const(struct regstat *cur, signed char reg)
902 {
903   int hr;
904   if (!reg) return;
905   hr = get_reg(cur->regmap, reg);
906   if (hr >= 0)
907     cur->isconst &= ~(1<<hr);
908 }
909
910 static int is_const(const struct regstat *cur, signed char reg)
911 {
912   int hr;
913   if (reg < 0) return 0;
914   if (!reg) return 1;
915   hr = get_reg(cur->regmap, reg);
916   if (hr >= 0)
917     return (cur->isconst>>hr)&1;
918   return 0;
919 }
920
921 static uint32_t get_const(const struct regstat *cur, signed char reg)
922 {
923   int hr;
924   if (!reg) return 0;
925   hr = get_reg(cur->regmap, reg);
926   if (hr >= 0)
927     return current_constmap[hr];
928
929   SysPrintf("Unknown constant in r%d\n", reg);
930   abort();
931 }
932
933 // Least soon needed registers
934 // Look at the next ten instructions and see which registers
935 // will be used.  Try not to reallocate these.
936 static void lsn(u_char hsn[], int i, int *preferred_reg)
937 {
938   int j;
939   int b=-1;
940   for(j=0;j<9;j++)
941   {
942     if(i+j>=slen) {
943       j=slen-i-1;
944       break;
945     }
946     if (dops[i+j].is_ujump)
947     {
948       // Don't go past an unconditonal jump
949       j++;
950       break;
951     }
952   }
953   for(;j>=0;j--)
954   {
955     if(dops[i+j].rs1) hsn[dops[i+j].rs1]=j;
956     if(dops[i+j].rs2) hsn[dops[i+j].rs2]=j;
957     if(dops[i+j].rt1) hsn[dops[i+j].rt1]=j;
958     if(dops[i+j].rt2) hsn[dops[i+j].rt2]=j;
959     if(dops[i+j].itype==STORE || dops[i+j].itype==STORELR) {
960       // Stores can allocate zero
961       hsn[dops[i+j].rs1]=j;
962       hsn[dops[i+j].rs2]=j;
963     }
964     if (ram_offset && (dops[i+j].is_load || dops[i+j].is_store))
965       hsn[ROREG] = j;
966     // On some architectures stores need invc_ptr
967     #if defined(HOST_IMM8)
968     if (dops[i+j].is_store)
969       hsn[INVCP] = j;
970     #endif
971     if(i+j>=0&&(dops[i+j].itype==UJUMP||dops[i+j].itype==CJUMP||dops[i+j].itype==SJUMP))
972     {
973       hsn[CCREG]=j;
974       b=j;
975     }
976   }
977   if(b>=0)
978   {
979     if(ba[i+b]>=start && ba[i+b]<(start+slen*4))
980     {
981       // Follow first branch
982       int t=(ba[i+b]-start)>>2;
983       j=7-b;if(t+j>=slen) j=slen-t-1;
984       for(;j>=0;j--)
985       {
986         if(dops[t+j].rs1) if(hsn[dops[t+j].rs1]>j+b+2) hsn[dops[t+j].rs1]=j+b+2;
987         if(dops[t+j].rs2) if(hsn[dops[t+j].rs2]>j+b+2) hsn[dops[t+j].rs2]=j+b+2;
988         //if(dops[t+j].rt1) if(hsn[dops[t+j].rt1]>j+b+2) hsn[dops[t+j].rt1]=j+b+2;
989         //if(dops[t+j].rt2) if(hsn[dops[t+j].rt2]>j+b+2) hsn[dops[t+j].rt2]=j+b+2;
990       }
991     }
992     // TODO: preferred register based on backward branch
993   }
994   // Delay slot should preferably not overwrite branch conditions or cycle count
995   if (i > 0 && dops[i-1].is_jump) {
996     if(dops[i-1].rs1) if(hsn[dops[i-1].rs1]>1) hsn[dops[i-1].rs1]=1;
997     if(dops[i-1].rs2) if(hsn[dops[i-1].rs2]>1) hsn[dops[i-1].rs2]=1;
998     hsn[CCREG]=1;
999     // ...or hash tables
1000     hsn[RHASH]=1;
1001     hsn[RHTBL]=1;
1002   }
1003   // Coprocessor load/store needs FTEMP, even if not declared
1004   if(dops[i].itype==C2LS) {
1005     hsn[FTEMP]=0;
1006   }
1007   // Load L/R also uses FTEMP as a temporary register
1008   if(dops[i].itype==LOADLR) {
1009     hsn[FTEMP]=0;
1010   }
1011   // Also SWL/SWR/SDL/SDR
1012   if(dops[i].opcode==0x2a||dops[i].opcode==0x2e||dops[i].opcode==0x2c||dops[i].opcode==0x2d) {
1013     hsn[FTEMP]=0;
1014   }
1015   // Don't remove the miniht registers
1016   if(dops[i].itype==UJUMP||dops[i].itype==RJUMP)
1017   {
1018     hsn[RHASH]=0;
1019     hsn[RHTBL]=0;
1020   }
1021 }
1022
1023 // We only want to allocate registers if we're going to use them again soon
1024 static int needed_again(int r, int i)
1025 {
1026   int j;
1027   int b=-1;
1028   int rn=10;
1029
1030   if (i > 0 && dops[i-1].is_ujump)
1031   {
1032     if(ba[i-1]<start || ba[i-1]>start+slen*4-4)
1033       return 0; // Don't need any registers if exiting the block
1034   }
1035   for(j=0;j<9;j++)
1036   {
1037     if(i+j>=slen) {
1038       j=slen-i-1;
1039       break;
1040     }
1041     if (dops[i+j].is_ujump)
1042     {
1043       // Don't go past an unconditonal jump
1044       j++;
1045       break;
1046     }
1047     if(dops[i+j].itype==SYSCALL||dops[i+j].itype==HLECALL||dops[i+j].itype==INTCALL||((source[i+j]&0xfc00003f)==0x0d))
1048     {
1049       break;
1050     }
1051   }
1052   for(;j>=1;j--)
1053   {
1054     if(dops[i+j].rs1==r) rn=j;
1055     if(dops[i+j].rs2==r) rn=j;
1056     if((unneeded_reg[i+j]>>r)&1) rn=10;
1057     if(i+j>=0&&(dops[i+j].itype==UJUMP||dops[i+j].itype==CJUMP||dops[i+j].itype==SJUMP))
1058     {
1059       b=j;
1060     }
1061   }
1062   if(rn<10) return 1;
1063   (void)b;
1064   return 0;
1065 }
1066
1067 // Try to match register allocations at the end of a loop with those
1068 // at the beginning
1069 static int loop_reg(int i, int r, int hr)
1070 {
1071   int j,k;
1072   for(j=0;j<9;j++)
1073   {
1074     if(i+j>=slen) {
1075       j=slen-i-1;
1076       break;
1077     }
1078     if (dops[i+j].is_ujump)
1079     {
1080       // Don't go past an unconditonal jump
1081       j++;
1082       break;
1083     }
1084   }
1085   k=0;
1086   if(i>0){
1087     if(dops[i-1].itype==UJUMP||dops[i-1].itype==CJUMP||dops[i-1].itype==SJUMP)
1088       k--;
1089   }
1090   for(;k<j;k++)
1091   {
1092     assert(r < 64);
1093     if((unneeded_reg[i+k]>>r)&1) return hr;
1094     if(i+k>=0&&(dops[i+k].itype==UJUMP||dops[i+k].itype==CJUMP||dops[i+k].itype==SJUMP))
1095     {
1096       if(ba[i+k]>=start && ba[i+k]<(start+i*4))
1097       {
1098         int t=(ba[i+k]-start)>>2;
1099         int reg=get_reg(regs[t].regmap_entry,r);
1100         if(reg>=0) return reg;
1101         //reg=get_reg(regs[t+1].regmap_entry,r);
1102         //if(reg>=0) return reg;
1103       }
1104     }
1105   }
1106   return hr;
1107 }
1108
1109
1110 // Allocate every register, preserving source/target regs
1111 static void alloc_all(struct regstat *cur,int i)
1112 {
1113   int hr;
1114
1115   for(hr=0;hr<HOST_REGS;hr++) {
1116     if(hr!=EXCLUDE_REG) {
1117       if((cur->regmap[hr]!=dops[i].rs1)&&(cur->regmap[hr]!=dops[i].rs2)&&
1118          (cur->regmap[hr]!=dops[i].rt1)&&(cur->regmap[hr]!=dops[i].rt2))
1119       {
1120         cur->regmap[hr]=-1;
1121         cur->dirty&=~(1<<hr);
1122       }
1123       // Don't need zeros
1124       if(cur->regmap[hr]==0)
1125       {
1126         cur->regmap[hr]=-1;
1127         cur->dirty&=~(1<<hr);
1128       }
1129     }
1130   }
1131 }
1132
1133 #ifndef NDEBUG
1134 static int host_tempreg_in_use;
1135
1136 static void host_tempreg_acquire(void)
1137 {
1138   assert(!host_tempreg_in_use);
1139   host_tempreg_in_use = 1;
1140 }
1141
1142 static void host_tempreg_release(void)
1143 {
1144   host_tempreg_in_use = 0;
1145 }
1146 #else
1147 static void host_tempreg_acquire(void) {}
1148 static void host_tempreg_release(void) {}
1149 #endif
1150
1151 #ifdef ASSEM_PRINT
1152 extern void gen_interupt();
1153 extern void do_insn_cmp();
1154 #define FUNCNAME(f) { f, " " #f }
1155 static const struct {
1156   void *addr;
1157   const char *name;
1158 } function_names[] = {
1159   FUNCNAME(cc_interrupt),
1160   FUNCNAME(gen_interupt),
1161   FUNCNAME(ndrc_get_addr_ht),
1162   FUNCNAME(jump_handler_read8),
1163   FUNCNAME(jump_handler_read16),
1164   FUNCNAME(jump_handler_read32),
1165   FUNCNAME(jump_handler_write8),
1166   FUNCNAME(jump_handler_write16),
1167   FUNCNAME(jump_handler_write32),
1168   FUNCNAME(ndrc_invalidate_addr),
1169   FUNCNAME(jump_to_new_pc),
1170   FUNCNAME(jump_break),
1171   FUNCNAME(jump_break_ds),
1172   FUNCNAME(jump_syscall),
1173   FUNCNAME(jump_syscall_ds),
1174   FUNCNAME(call_gteStall),
1175   FUNCNAME(new_dyna_leave),
1176   FUNCNAME(pcsx_mtc0),
1177   FUNCNAME(pcsx_mtc0_ds),
1178 #ifdef DRC_DBG
1179   FUNCNAME(do_insn_cmp),
1180 #endif
1181 };
1182
1183 static const char *func_name(const void *a)
1184 {
1185   int i;
1186   for (i = 0; i < sizeof(function_names)/sizeof(function_names[0]); i++)
1187     if (function_names[i].addr == a)
1188       return function_names[i].name;
1189   return "";
1190 }
1191 #else
1192 #define func_name(x) ""
1193 #endif
1194
1195 #ifdef __i386__
1196 #include "assem_x86.c"
1197 #endif
1198 #ifdef __x86_64__
1199 #include "assem_x64.c"
1200 #endif
1201 #ifdef __arm__
1202 #include "assem_arm.c"
1203 #endif
1204 #ifdef __aarch64__
1205 #include "assem_arm64.c"
1206 #endif
1207
1208 static void *get_trampoline(const void *f)
1209 {
1210   struct ndrc_tramp *tramp = NDRC_WRITE_OFFSET(&ndrc->tramp);
1211   size_t i;
1212
1213   for (i = 0; i < ARRAY_SIZE(tramp->f); i++) {
1214     if (tramp->f[i] == f || tramp->f[i] == NULL)
1215       break;
1216   }
1217   if (i == ARRAY_SIZE(tramp->f)) {
1218     SysPrintf("trampoline table is full, last func %p\n", f);
1219     abort();
1220   }
1221   if (tramp->f[i] == NULL) {
1222     start_tcache_write(&tramp->f[i], &tramp->f[i + 1]);
1223     tramp->f[i] = f;
1224     end_tcache_write(&tramp->f[i], &tramp->f[i + 1]);
1225 #ifdef HAVE_LIBNX
1226     // invalidate the RX mirror (unsure if necessary, but just in case...)
1227     armDCacheFlush(&ndrc->tramp.f[i], sizeof(ndrc->tramp.f[i]));
1228 #endif
1229   }
1230   return &ndrc->tramp.ops[i];
1231 }
1232
1233 static void emit_far_jump(const void *f)
1234 {
1235   if (can_jump_or_call(f)) {
1236     emit_jmp(f);
1237     return;
1238   }
1239
1240   f = get_trampoline(f);
1241   emit_jmp(f);
1242 }
1243
1244 static void emit_far_call(const void *f)
1245 {
1246   if (can_jump_or_call(f)) {
1247     emit_call(f);
1248     return;
1249   }
1250
1251   f = get_trampoline(f);
1252   emit_call(f);
1253 }
1254
1255 // Check if an address is already compiled
1256 // but don't return addresses which are about to expire from the cache
1257 static void *check_addr(u_int vaddr)
1258 {
1259   struct ht_entry *ht_bin = hash_table_get(vaddr);
1260   size_t i;
1261   for (i = 0; i < ARRAY_SIZE(ht_bin->vaddr); i++) {
1262     if (ht_bin->vaddr[i] == vaddr)
1263       if (doesnt_expire_soon(ht_bin->tcaddr[i]))
1264         return ht_bin->tcaddr[i];
1265   }
1266
1267   // refactor to get_addr_nocompile?
1268   u_int start_page = get_page_prev(vaddr);
1269   u_int page, end_page = get_page(vaddr);
1270
1271   stat_inc(stat_jump_in_lookups);
1272   for (page = start_page; page <= end_page; page++) {
1273     const struct block_info *block;
1274     for (block = blocks[page]; block != NULL; block = block->next) {
1275       if (vaddr < block->start)
1276         break;
1277       if (block->is_dirty || vaddr >= block->start + block->len)
1278         continue;
1279       if (!doesnt_expire_soon(ndrc->translation_cache + block->tc_offs))
1280         continue;
1281       for (i = 0; i < block->jump_in_cnt; i++)
1282         if (block->jump_in[i].vaddr == vaddr)
1283           break;
1284       if (i == block->jump_in_cnt)
1285         continue;
1286
1287       // Update existing entry with current address
1288       void *addr = block->jump_in[i].addr;
1289       if (ht_bin->vaddr[0] == vaddr) {
1290         ht_bin->tcaddr[0] = addr;
1291         return addr;
1292       }
1293       if (ht_bin->vaddr[1] == vaddr) {
1294         ht_bin->tcaddr[1] = addr;
1295         return addr;
1296       }
1297       // Insert into hash table with low priority.
1298       // Don't evict existing entries, as they are probably
1299       // addresses that are being accessed frequently.
1300       if (ht_bin->vaddr[0] == -1) {
1301         ht_bin->vaddr[0] = vaddr;
1302         ht_bin->tcaddr[0] = addr;
1303       }
1304       else if (ht_bin->vaddr[1] == -1) {
1305         ht_bin->vaddr[1] = vaddr;
1306         ht_bin->tcaddr[1] = addr;
1307       }
1308       return addr;
1309     }
1310   }
1311   return NULL;
1312 }
1313
1314 static void blocks_clear(struct block_info **head)
1315 {
1316   struct block_info *cur, *next;
1317
1318   if ((cur = *head)) {
1319     *head = NULL;
1320     while (cur) {
1321       next = cur->next;
1322       free(cur);
1323       cur = next;
1324     }
1325   }
1326 }
1327
1328 static int blocks_remove_matching_addrs(struct block_info **head,
1329   u_int base_offs, int shift)
1330 {
1331   struct block_info *next;
1332   int hit = 0;
1333   while (*head) {
1334     if ((((*head)->tc_offs ^ base_offs) >> shift) == 0) {
1335       inv_debug("EXP: rm block %08x (tc_offs %zx)\n", (*head)->start, (*head)->tc_offs);
1336       invalidate_block(*head);
1337       next = (*head)->next;
1338       free(*head);
1339       *head = next;
1340       stat_dec(stat_blocks);
1341       hit = 1;
1342     }
1343     else
1344     {
1345       head = &((*head)->next);
1346     }
1347   }
1348   return hit;
1349 }
1350
1351 // This is called when we write to a compiled block (see do_invstub)
1352 static void unlink_jumps_vaddr_range(u_int start, u_int end)
1353 {
1354   u_int page, start_page = get_page(start), end_page = get_page(end - 1);
1355   int i;
1356
1357   for (page = start_page; page <= end_page; page++) {
1358     struct jump_info *ji = jumps[page];
1359     if (ji == NULL)
1360       continue;
1361     for (i = 0; i < ji->count; ) {
1362       if (ji->e[i].target_vaddr < start || ji->e[i].target_vaddr >= end) {
1363         i++;
1364         continue;
1365       }
1366
1367       inv_debug("INV: rm link to %08x (tc_offs %zx)\n", ji->e[i].target_vaddr,
1368         (u_char *)ji->e[i].stub - ndrc->translation_cache);
1369       void *host_addr = find_extjump_insn(ji->e[i].stub);
1370       mark_clear_cache(host_addr);
1371       set_jump_target(host_addr, ji->e[i].stub); // point back to dyna_linker stub
1372
1373       stat_dec(stat_links);
1374       ji->count--;
1375       if (i < ji->count) {
1376         ji->e[i] = ji->e[ji->count];
1377         continue;
1378       }
1379       i++;
1380     }
1381   }
1382 }
1383
1384 static void unlink_jumps_tc_range(struct jump_info *ji, u_int base_offs, int shift)
1385 {
1386   int i;
1387   if (ji == NULL)
1388     return;
1389   for (i = 0; i < ji->count; ) {
1390     u_int tc_offs = (u_char *)ji->e[i].stub - ndrc->translation_cache;
1391     if (((tc_offs ^ base_offs) >> shift) != 0) {
1392       i++;
1393       continue;
1394     }
1395
1396     inv_debug("EXP: rm link to %08x (tc_offs %zx)\n", ji->e[i].target_vaddr, tc_offs);
1397     stat_dec(stat_links);
1398     ji->count--;
1399     if (i < ji->count) {
1400       ji->e[i] = ji->e[ji->count];
1401       continue;
1402     }
1403     i++;
1404   }
1405 }
1406
1407 static void invalidate_block(struct block_info *block)
1408 {
1409   u_int i;
1410
1411   block->is_dirty = 1;
1412   unlink_jumps_vaddr_range(block->start, block->start + block->len);
1413   for (i = 0; i < block->jump_in_cnt; i++)
1414     hash_table_remove(block->jump_in[i].vaddr);
1415 }
1416
1417 static int invalidate_range(u_int start, u_int end,
1418   u32 *inv_start_ret, u32 *inv_end_ret)
1419 {
1420   struct block_info *last_block = NULL;
1421   u_int start_page = get_page_prev(start);
1422   u_int end_page = get_page(end - 1);
1423   u_int start_m = pmmask(start);
1424   u_int end_m = pmmask(end - 1);
1425   u_int inv_start, inv_end;
1426   u_int blk_start_m, blk_end_m;
1427   u_int page;
1428   int hit = 0;
1429
1430   // additional area without code (to supplement invalid_code[]), [start, end)
1431   // avoids excessive ndrc_invalidate_addr() calls
1432   inv_start = start_m & ~0xfff;
1433   inv_end = end_m | 0xfff;
1434
1435   for (page = start_page; page <= end_page; page++) {
1436     struct block_info *block;
1437     for (block = blocks[page]; block != NULL; block = block->next) {
1438       if (block->is_dirty)
1439         continue;
1440       last_block = block;
1441       blk_end_m = pmmask(block->start + block->len);
1442       if (blk_end_m <= start_m) {
1443         inv_start = max(inv_start, blk_end_m);
1444         continue;
1445       }
1446       blk_start_m = pmmask(block->start);
1447       if (end_m <= blk_start_m) {
1448         inv_end = min(inv_end, blk_start_m - 1);
1449         continue;
1450       }
1451       if (!block->source) // "hack" block - leave it alone
1452         continue;
1453
1454       hit++;
1455       invalidate_block(block);
1456       stat_inc(stat_inv_hits);
1457     }
1458   }
1459
1460   if (!hit && last_block && last_block->source) {
1461     // could be some leftover unused block, uselessly trapping writes
1462     last_block->inv_near_misses++;
1463     if (last_block->inv_near_misses > 128) {
1464       invalidate_block(last_block);
1465       stat_inc(stat_inv_hits);
1466       hit++;
1467     }
1468   }
1469   if (hit) {
1470     do_clear_cache();
1471 #ifdef USE_MINI_HT
1472     memset(mini_ht, -1, sizeof(mini_ht));
1473 #endif
1474   }
1475
1476   if (inv_start <= (start_m & ~0xfff) && inv_end >= (start_m | 0xfff))
1477     // the whole page is empty now
1478     mark_invalid_code(start, 1, 1);
1479
1480   if (inv_start_ret) *inv_start_ret = inv_start | (start & 0xe0000000);
1481   if (inv_end_ret) *inv_end_ret = inv_end | (end & 0xe0000000);
1482   return hit;
1483 }
1484
1485 void new_dynarec_invalidate_range(unsigned int start, unsigned int end)
1486 {
1487   invalidate_range(start, end, NULL, NULL);
1488 }
1489
1490 void ndrc_invalidate_addr(u_int addr)
1491 {
1492   // this check is done by the caller
1493   //if (inv_code_start<=addr&&addr<=inv_code_end) { rhits++; return; }
1494   int ret = invalidate_range(addr, addr + 4, &inv_code_start, &inv_code_end);
1495   if (ret)
1496     inv_debug("INV ADDR: %08x hit %d blocks\n", addr, ret);
1497   else
1498     inv_debug("INV ADDR: %08x miss, inv %08x-%08x\n", addr, inv_code_start, inv_code_end);
1499   stat_inc(stat_inv_addr_calls);
1500 }
1501
1502 // This is called when loading a save state.
1503 // Anything could have changed, so invalidate everything.
1504 void new_dynarec_invalidate_all_pages(void)
1505 {
1506   struct block_info *block;
1507   u_int page;
1508   for (page = 0; page < ARRAY_SIZE(blocks); page++) {
1509     for (block = blocks[page]; block != NULL; block = block->next) {
1510       if (block->is_dirty)
1511         continue;
1512       if (!block->source) // hack block?
1513         continue;
1514       invalidate_block(block);
1515     }
1516   }
1517
1518   #ifdef USE_MINI_HT
1519   memset(mini_ht, -1, sizeof(mini_ht));
1520   #endif
1521   do_clear_cache();
1522 }
1523
1524 static void do_invstub(int n)
1525 {
1526   literal_pool(20);
1527   u_int reglist = stubs[n].a;
1528   set_jump_target(stubs[n].addr, out);
1529   save_regs(reglist);
1530   if (stubs[n].b != 0)
1531     emit_mov(stubs[n].b, 0);
1532   emit_readword(&inv_code_start, 1);
1533   emit_readword(&inv_code_end, 2);
1534   emit_cmp(0, 1);
1535   emit_cmpcs(2, 0);
1536   void *jaddr = out;
1537   emit_jc(0);
1538   emit_far_call(ndrc_invalidate_addr);
1539   set_jump_target(jaddr, out);
1540   restore_regs(reglist);
1541   emit_jmp(stubs[n].retaddr); // return address
1542 }
1543
1544 // Add an entry to jump_out after making a link
1545 // src should point to code by emit_extjump()
1546 void ndrc_add_jump_out(u_int vaddr, void *src)
1547 {
1548   inv_debug("ndrc_add_jump_out: %p -> %x\n", src, vaddr);
1549   u_int page = get_page(vaddr);
1550   struct jump_info *ji;
1551
1552   stat_inc(stat_links);
1553   check_extjump2(src);
1554   ji = jumps[page];
1555   if (ji == NULL) {
1556     ji = malloc(sizeof(*ji) + sizeof(ji->e[0]) * 16);
1557     ji->alloc = 16;
1558     ji->count = 0;
1559   }
1560   else if (ji->count >= ji->alloc) {
1561     ji->alloc += 16;
1562     ji = realloc(ji, sizeof(*ji) + sizeof(ji->e[0]) * ji->alloc);
1563   }
1564   jumps[page] = ji;
1565   ji->e[ji->count].target_vaddr = vaddr;
1566   ji->e[ji->count].stub = src;
1567   ji->count++;
1568 }
1569
1570 /* Register allocation */
1571
1572 // Note: registers are allocated clean (unmodified state)
1573 // if you intend to modify the register, you must call dirty_reg().
1574 static void alloc_reg(struct regstat *cur,int i,signed char reg)
1575 {
1576   int r,hr;
1577   int preferred_reg = PREFERRED_REG_FIRST
1578     + reg % (PREFERRED_REG_LAST - PREFERRED_REG_FIRST + 1);
1579   if (reg == CCREG) preferred_reg = HOST_CCREG;
1580   if (reg == PTEMP || reg == FTEMP) preferred_reg = 12;
1581   assert(PREFERRED_REG_FIRST != EXCLUDE_REG && EXCLUDE_REG != HOST_REGS);
1582   assert(reg >= 0);
1583
1584   // Don't allocate unused registers
1585   if((cur->u>>reg)&1) return;
1586
1587   // see if it's already allocated
1588   if (get_reg(cur->regmap, reg) >= 0)
1589     return;
1590
1591   // Keep the same mapping if the register was already allocated in a loop
1592   preferred_reg = loop_reg(i,reg,preferred_reg);
1593
1594   // Try to allocate the preferred register
1595   if(cur->regmap[preferred_reg]==-1) {
1596     cur->regmap[preferred_reg]=reg;
1597     cur->dirty&=~(1<<preferred_reg);
1598     cur->isconst&=~(1<<preferred_reg);
1599     return;
1600   }
1601   r=cur->regmap[preferred_reg];
1602   assert(r < 64);
1603   if((cur->u>>r)&1) {
1604     cur->regmap[preferred_reg]=reg;
1605     cur->dirty&=~(1<<preferred_reg);
1606     cur->isconst&=~(1<<preferred_reg);
1607     return;
1608   }
1609
1610   // Clear any unneeded registers
1611   // We try to keep the mapping consistent, if possible, because it
1612   // makes branches easier (especially loops).  So we try to allocate
1613   // first (see above) before removing old mappings.  If this is not
1614   // possible then go ahead and clear out the registers that are no
1615   // longer needed.
1616   for(hr=0;hr<HOST_REGS;hr++)
1617   {
1618     r=cur->regmap[hr];
1619     if(r>=0) {
1620       assert(r < 64);
1621       if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
1622     }
1623   }
1624
1625   // Try to allocate any available register, but prefer
1626   // registers that have not been used recently.
1627   if (i > 0) {
1628     for (hr = PREFERRED_REG_FIRST; ; ) {
1629       if (cur->regmap[hr] < 0) {
1630         int oldreg = regs[i-1].regmap[hr];
1631         if (oldreg < 0 || (oldreg != dops[i-1].rs1 && oldreg != dops[i-1].rs2
1632              && oldreg != dops[i-1].rt1 && oldreg != dops[i-1].rt2))
1633         {
1634           cur->regmap[hr]=reg;
1635           cur->dirty&=~(1<<hr);
1636           cur->isconst&=~(1<<hr);
1637           return;
1638         }
1639       }
1640       hr++;
1641       if (hr == EXCLUDE_REG)
1642         hr++;
1643       if (hr == HOST_REGS)
1644         hr = 0;
1645       if (hr == PREFERRED_REG_FIRST)
1646         break;
1647     }
1648   }
1649
1650   // Try to allocate any available register
1651   for (hr = PREFERRED_REG_FIRST; ; ) {
1652     if (cur->regmap[hr] < 0) {
1653       cur->regmap[hr]=reg;
1654       cur->dirty&=~(1<<hr);
1655       cur->isconst&=~(1<<hr);
1656       return;
1657     }
1658     hr++;
1659     if (hr == EXCLUDE_REG)
1660       hr++;
1661     if (hr == HOST_REGS)
1662       hr = 0;
1663     if (hr == PREFERRED_REG_FIRST)
1664       break;
1665   }
1666
1667   // Ok, now we have to evict someone
1668   // Pick a register we hopefully won't need soon
1669   u_char hsn[MAXREG+1];
1670   memset(hsn,10,sizeof(hsn));
1671   int j;
1672   lsn(hsn,i,&preferred_reg);
1673   //printf("eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",cur->regmap[0],cur->regmap[1],cur->regmap[2],cur->regmap[3],cur->regmap[5],cur->regmap[6],cur->regmap[7]);
1674   //printf("hsn(%x): %d %d %d %d %d %d %d\n",start+i*4,hsn[cur->regmap[0]&63],hsn[cur->regmap[1]&63],hsn[cur->regmap[2]&63],hsn[cur->regmap[3]&63],hsn[cur->regmap[5]&63],hsn[cur->regmap[6]&63],hsn[cur->regmap[7]&63]);
1675   if(i>0) {
1676     // Don't evict the cycle count at entry points, otherwise the entry
1677     // stub will have to write it.
1678     if(dops[i].bt&&hsn[CCREG]>2) hsn[CCREG]=2;
1679     if (i>1 && hsn[CCREG] > 2 && dops[i-2].is_jump) hsn[CCREG]=2;
1680     for(j=10;j>=3;j--)
1681     {
1682       // Alloc preferred register if available
1683       if(hsn[r=cur->regmap[preferred_reg]&63]==j) {
1684         for(hr=0;hr<HOST_REGS;hr++) {
1685           // Evict both parts of a 64-bit register
1686           if(cur->regmap[hr]==r) {
1687             cur->regmap[hr]=-1;
1688             cur->dirty&=~(1<<hr);
1689             cur->isconst&=~(1<<hr);
1690           }
1691         }
1692         cur->regmap[preferred_reg]=reg;
1693         return;
1694       }
1695       for(r=1;r<=MAXREG;r++)
1696       {
1697         if(hsn[r]==j&&r!=dops[i-1].rs1&&r!=dops[i-1].rs2&&r!=dops[i-1].rt1&&r!=dops[i-1].rt2) {
1698           for(hr=0;hr<HOST_REGS;hr++) {
1699             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
1700               if(cur->regmap[hr]==r) {
1701                 cur->regmap[hr]=reg;
1702                 cur->dirty&=~(1<<hr);
1703                 cur->isconst&=~(1<<hr);
1704                 return;
1705               }
1706             }
1707           }
1708         }
1709       }
1710     }
1711   }
1712   for(j=10;j>=0;j--)
1713   {
1714     for(r=1;r<=MAXREG;r++)
1715     {
1716       if(hsn[r]==j) {
1717         for(hr=0;hr<HOST_REGS;hr++) {
1718           if(cur->regmap[hr]==r) {
1719             cur->regmap[hr]=reg;
1720             cur->dirty&=~(1<<hr);
1721             cur->isconst&=~(1<<hr);
1722             return;
1723           }
1724         }
1725       }
1726     }
1727   }
1728   SysPrintf("This shouldn't happen (alloc_reg)");abort();
1729 }
1730
1731 // Allocate a temporary register.  This is done without regard to
1732 // dirty status or whether the register we request is on the unneeded list
1733 // Note: This will only allocate one register, even if called multiple times
1734 static void alloc_reg_temp(struct regstat *cur,int i,signed char reg)
1735 {
1736   int r,hr;
1737   int preferred_reg = -1;
1738
1739   // see if it's already allocated
1740   for(hr=0;hr<HOST_REGS;hr++)
1741   {
1742     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==reg) return;
1743   }
1744
1745   // Try to allocate any available register
1746   for(hr=HOST_REGS-1;hr>=0;hr--) {
1747     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
1748       cur->regmap[hr]=reg;
1749       cur->dirty&=~(1<<hr);
1750       cur->isconst&=~(1<<hr);
1751       return;
1752     }
1753   }
1754
1755   // Find an unneeded register
1756   for(hr=HOST_REGS-1;hr>=0;hr--)
1757   {
1758     r=cur->regmap[hr];
1759     if(r>=0) {
1760       assert(r < 64);
1761       if((cur->u>>r)&1) {
1762         if(i==0||((unneeded_reg[i-1]>>r)&1)) {
1763           cur->regmap[hr]=reg;
1764           cur->dirty&=~(1<<hr);
1765           cur->isconst&=~(1<<hr);
1766           return;
1767         }
1768       }
1769     }
1770   }
1771
1772   // Ok, now we have to evict someone
1773   // Pick a register we hopefully won't need soon
1774   // TODO: we might want to follow unconditional jumps here
1775   // TODO: get rid of dupe code and make this into a function
1776   u_char hsn[MAXREG+1];
1777   memset(hsn,10,sizeof(hsn));
1778   int j;
1779   lsn(hsn,i,&preferred_reg);
1780   //printf("hsn: %d %d %d %d %d %d %d\n",hsn[cur->regmap[0]&63],hsn[cur->regmap[1]&63],hsn[cur->regmap[2]&63],hsn[cur->regmap[3]&63],hsn[cur->regmap[5]&63],hsn[cur->regmap[6]&63],hsn[cur->regmap[7]&63]);
1781   if(i>0) {
1782     // Don't evict the cycle count at entry points, otherwise the entry
1783     // stub will have to write it.
1784     if(dops[i].bt&&hsn[CCREG]>2) hsn[CCREG]=2;
1785     if (i>1 && hsn[CCREG] > 2 && dops[i-2].is_jump) hsn[CCREG]=2;
1786     for(j=10;j>=3;j--)
1787     {
1788       for(r=1;r<=MAXREG;r++)
1789       {
1790         if(hsn[r]==j&&r!=dops[i-1].rs1&&r!=dops[i-1].rs2&&r!=dops[i-1].rt1&&r!=dops[i-1].rt2) {
1791           for(hr=0;hr<HOST_REGS;hr++) {
1792             if(hr!=HOST_CCREG||hsn[CCREG]>2) {
1793               if(cur->regmap[hr]==r) {
1794                 cur->regmap[hr]=reg;
1795                 cur->dirty&=~(1<<hr);
1796                 cur->isconst&=~(1<<hr);
1797                 return;
1798               }
1799             }
1800           }
1801         }
1802       }
1803     }
1804   }
1805   for(j=10;j>=0;j--)
1806   {
1807     for(r=1;r<=MAXREG;r++)
1808     {
1809       if(hsn[r]==j) {
1810         for(hr=0;hr<HOST_REGS;hr++) {
1811           if(cur->regmap[hr]==r) {
1812             cur->regmap[hr]=reg;
1813             cur->dirty&=~(1<<hr);
1814             cur->isconst&=~(1<<hr);
1815             return;
1816           }
1817         }
1818       }
1819     }
1820   }
1821   SysPrintf("This shouldn't happen");abort();
1822 }
1823
1824 static void mov_alloc(struct regstat *current,int i)
1825 {
1826   if (dops[i].rs1 == HIREG || dops[i].rs1 == LOREG) {
1827     alloc_cc(current,i); // for stalls
1828     dirty_reg(current,CCREG);
1829   }
1830
1831   // Note: Don't need to actually alloc the source registers
1832   //alloc_reg(current,i,dops[i].rs1);
1833   alloc_reg(current,i,dops[i].rt1);
1834
1835   clear_const(current,dops[i].rs1);
1836   clear_const(current,dops[i].rt1);
1837   dirty_reg(current,dops[i].rt1);
1838 }
1839
1840 static void shiftimm_alloc(struct regstat *current,int i)
1841 {
1842   if(dops[i].opcode2<=0x3) // SLL/SRL/SRA
1843   {
1844     if(dops[i].rt1) {
1845       if(dops[i].rs1&&needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
1846       else dops[i].use_lt1=!!dops[i].rs1;
1847       alloc_reg(current,i,dops[i].rt1);
1848       dirty_reg(current,dops[i].rt1);
1849       if(is_const(current,dops[i].rs1)) {
1850         int v=get_const(current,dops[i].rs1);
1851         if(dops[i].opcode2==0x00) set_const(current,dops[i].rt1,v<<imm[i]);
1852         if(dops[i].opcode2==0x02) set_const(current,dops[i].rt1,(u_int)v>>imm[i]);
1853         if(dops[i].opcode2==0x03) set_const(current,dops[i].rt1,v>>imm[i]);
1854       }
1855       else clear_const(current,dops[i].rt1);
1856     }
1857   }
1858   else
1859   {
1860     clear_const(current,dops[i].rs1);
1861     clear_const(current,dops[i].rt1);
1862   }
1863
1864   if(dops[i].opcode2>=0x38&&dops[i].opcode2<=0x3b) // DSLL/DSRL/DSRA
1865   {
1866     assert(0);
1867   }
1868   if(dops[i].opcode2==0x3c) // DSLL32
1869   {
1870     assert(0);
1871   }
1872   if(dops[i].opcode2==0x3e) // DSRL32
1873   {
1874     assert(0);
1875   }
1876   if(dops[i].opcode2==0x3f) // DSRA32
1877   {
1878     assert(0);
1879   }
1880 }
1881
1882 static void shift_alloc(struct regstat *current,int i)
1883 {
1884   if(dops[i].rt1) {
1885     if(dops[i].opcode2<=0x07) // SLLV/SRLV/SRAV
1886     {
1887       if(dops[i].rs1) alloc_reg(current,i,dops[i].rs1);
1888       if(dops[i].rs2) alloc_reg(current,i,dops[i].rs2);
1889       alloc_reg(current,i,dops[i].rt1);
1890       if(dops[i].rt1==dops[i].rs2) {
1891         alloc_reg_temp(current,i,-1);
1892         minimum_free_regs[i]=1;
1893       }
1894     } else { // DSLLV/DSRLV/DSRAV
1895       assert(0);
1896     }
1897     clear_const(current,dops[i].rs1);
1898     clear_const(current,dops[i].rs2);
1899     clear_const(current,dops[i].rt1);
1900     dirty_reg(current,dops[i].rt1);
1901   }
1902 }
1903
1904 static void alu_alloc(struct regstat *current,int i)
1905 {
1906   if(dops[i].opcode2>=0x20&&dops[i].opcode2<=0x23) { // ADD/ADDU/SUB/SUBU
1907     if(dops[i].rt1) {
1908       if(dops[i].rs1&&dops[i].rs2) {
1909         alloc_reg(current,i,dops[i].rs1);
1910         alloc_reg(current,i,dops[i].rs2);
1911       }
1912       else {
1913         if(dops[i].rs1&&needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
1914         if(dops[i].rs2&&needed_again(dops[i].rs2,i)) alloc_reg(current,i,dops[i].rs2);
1915       }
1916       alloc_reg(current,i,dops[i].rt1);
1917     }
1918   }
1919   if(dops[i].opcode2==0x2a||dops[i].opcode2==0x2b) { // SLT/SLTU
1920     if(dops[i].rt1) {
1921       alloc_reg(current,i,dops[i].rs1);
1922       alloc_reg(current,i,dops[i].rs2);
1923       alloc_reg(current,i,dops[i].rt1);
1924     }
1925   }
1926   if(dops[i].opcode2>=0x24&&dops[i].opcode2<=0x27) { // AND/OR/XOR/NOR
1927     if(dops[i].rt1) {
1928       if(dops[i].rs1&&dops[i].rs2) {
1929         alloc_reg(current,i,dops[i].rs1);
1930         alloc_reg(current,i,dops[i].rs2);
1931       }
1932       else
1933       {
1934         if(dops[i].rs1&&needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
1935         if(dops[i].rs2&&needed_again(dops[i].rs2,i)) alloc_reg(current,i,dops[i].rs2);
1936       }
1937       alloc_reg(current,i,dops[i].rt1);
1938     }
1939   }
1940   if(dops[i].opcode2>=0x2c&&dops[i].opcode2<=0x2f) { // DADD/DADDU/DSUB/DSUBU
1941     assert(0);
1942   }
1943   clear_const(current,dops[i].rs1);
1944   clear_const(current,dops[i].rs2);
1945   clear_const(current,dops[i].rt1);
1946   dirty_reg(current,dops[i].rt1);
1947 }
1948
1949 static void imm16_alloc(struct regstat *current,int i)
1950 {
1951   if(dops[i].rs1&&needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
1952   else dops[i].use_lt1=!!dops[i].rs1;
1953   if(dops[i].rt1) alloc_reg(current,i,dops[i].rt1);
1954   if(dops[i].opcode==0x18||dops[i].opcode==0x19) { // DADDI/DADDIU
1955     assert(0);
1956   }
1957   else if(dops[i].opcode==0x0a||dops[i].opcode==0x0b) { // SLTI/SLTIU
1958     clear_const(current,dops[i].rs1);
1959     clear_const(current,dops[i].rt1);
1960   }
1961   else if(dops[i].opcode>=0x0c&&dops[i].opcode<=0x0e) { // ANDI/ORI/XORI
1962     if(is_const(current,dops[i].rs1)) {
1963       int v=get_const(current,dops[i].rs1);
1964       if(dops[i].opcode==0x0c) set_const(current,dops[i].rt1,v&imm[i]);
1965       if(dops[i].opcode==0x0d) set_const(current,dops[i].rt1,v|imm[i]);
1966       if(dops[i].opcode==0x0e) set_const(current,dops[i].rt1,v^imm[i]);
1967     }
1968     else clear_const(current,dops[i].rt1);
1969   }
1970   else if(dops[i].opcode==0x08||dops[i].opcode==0x09) { // ADDI/ADDIU
1971     if(is_const(current,dops[i].rs1)) {
1972       int v=get_const(current,dops[i].rs1);
1973       set_const(current,dops[i].rt1,v+imm[i]);
1974     }
1975     else clear_const(current,dops[i].rt1);
1976   }
1977   else {
1978     set_const(current,dops[i].rt1,imm[i]<<16); // LUI
1979   }
1980   dirty_reg(current,dops[i].rt1);
1981 }
1982
1983 static void load_alloc(struct regstat *current,int i)
1984 {
1985   clear_const(current,dops[i].rt1);
1986   //if(dops[i].rs1!=dops[i].rt1&&needed_again(dops[i].rs1,i)) clear_const(current,dops[i].rs1); // Does this help or hurt?
1987   if(!dops[i].rs1) current->u&=~1LL; // Allow allocating r0 if it's the source register
1988   if (needed_again(dops[i].rs1, i))
1989     alloc_reg(current, i, dops[i].rs1);
1990   if (ram_offset)
1991     alloc_reg(current, i, ROREG);
1992   if(dops[i].rt1&&!((current->u>>dops[i].rt1)&1)) {
1993     alloc_reg(current,i,dops[i].rt1);
1994     assert(get_reg(current->regmap,dops[i].rt1)>=0);
1995     if(dops[i].opcode==0x27||dops[i].opcode==0x37) // LWU/LD
1996     {
1997       assert(0);
1998     }
1999     else if(dops[i].opcode==0x1A||dops[i].opcode==0x1B) // LDL/LDR
2000     {
2001       assert(0);
2002     }
2003     dirty_reg(current,dops[i].rt1);
2004     // LWL/LWR need a temporary register for the old value
2005     if(dops[i].opcode==0x22||dops[i].opcode==0x26)
2006     {
2007       alloc_reg(current,i,FTEMP);
2008       alloc_reg_temp(current,i,-1);
2009       minimum_free_regs[i]=1;
2010     }
2011   }
2012   else
2013   {
2014     // Load to r0 or unneeded register (dummy load)
2015     // but we still need a register to calculate the address
2016     if(dops[i].opcode==0x22||dops[i].opcode==0x26)
2017     {
2018       alloc_reg(current,i,FTEMP); // LWL/LWR need another temporary
2019     }
2020     alloc_reg_temp(current,i,-1);
2021     minimum_free_regs[i]=1;
2022     if(dops[i].opcode==0x1A||dops[i].opcode==0x1B) // LDL/LDR
2023     {
2024       assert(0);
2025     }
2026   }
2027 }
2028
2029 static void store_alloc(struct regstat *current,int i)
2030 {
2031   clear_const(current,dops[i].rs2);
2032   if(!(dops[i].rs2)) current->u&=~1LL; // Allow allocating r0 if necessary
2033   if(needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
2034   alloc_reg(current,i,dops[i].rs2);
2035   if(dops[i].opcode==0x2c||dops[i].opcode==0x2d||dops[i].opcode==0x3f) { // 64-bit SDL/SDR/SD
2036     assert(0);
2037   }
2038   if (ram_offset)
2039     alloc_reg(current, i, ROREG);
2040   #if defined(HOST_IMM8)
2041   // On CPUs without 32-bit immediates we need a pointer to invalid_code
2042   alloc_reg(current, i, INVCP);
2043   #endif
2044   if(dops[i].opcode==0x2a||dops[i].opcode==0x2e||dops[i].opcode==0x2c||dops[i].opcode==0x2d) { // SWL/SWL/SDL/SDR
2045     alloc_reg(current,i,FTEMP);
2046   }
2047   // We need a temporary register for address generation
2048   alloc_reg_temp(current,i,-1);
2049   minimum_free_regs[i]=1;
2050 }
2051
2052 static void c1ls_alloc(struct regstat *current,int i)
2053 {
2054   clear_const(current,dops[i].rt1);
2055   alloc_reg(current,i,CSREG); // Status
2056 }
2057
2058 static void c2ls_alloc(struct regstat *current,int i)
2059 {
2060   clear_const(current,dops[i].rt1);
2061   if(needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
2062   alloc_reg(current,i,FTEMP);
2063   if (ram_offset)
2064     alloc_reg(current, i, ROREG);
2065   #if defined(HOST_IMM8)
2066   // On CPUs without 32-bit immediates we need a pointer to invalid_code
2067   if (dops[i].opcode == 0x3a) // SWC2
2068     alloc_reg(current,i,INVCP);
2069   #endif
2070   // We need a temporary register for address generation
2071   alloc_reg_temp(current,i,-1);
2072   minimum_free_regs[i]=1;
2073 }
2074
2075 #ifndef multdiv_alloc
2076 static void multdiv_alloc(struct regstat *current,int i)
2077 {
2078   //  case 0x18: MULT
2079   //  case 0x19: MULTU
2080   //  case 0x1A: DIV
2081   //  case 0x1B: DIVU
2082   //  case 0x1C: DMULT
2083   //  case 0x1D: DMULTU
2084   //  case 0x1E: DDIV
2085   //  case 0x1F: DDIVU
2086   clear_const(current,dops[i].rs1);
2087   clear_const(current,dops[i].rs2);
2088   alloc_cc(current,i); // for stalls
2089   if(dops[i].rs1&&dops[i].rs2)
2090   {
2091     if((dops[i].opcode2&4)==0) // 32-bit
2092     {
2093       current->u&=~(1LL<<HIREG);
2094       current->u&=~(1LL<<LOREG);
2095       alloc_reg(current,i,HIREG);
2096       alloc_reg(current,i,LOREG);
2097       alloc_reg(current,i,dops[i].rs1);
2098       alloc_reg(current,i,dops[i].rs2);
2099       dirty_reg(current,HIREG);
2100       dirty_reg(current,LOREG);
2101     }
2102     else // 64-bit
2103     {
2104       assert(0);
2105     }
2106   }
2107   else
2108   {
2109     // Multiply by zero is zero.
2110     // MIPS does not have a divide by zero exception.
2111     // The result is undefined, we return zero.
2112     alloc_reg(current,i,HIREG);
2113     alloc_reg(current,i,LOREG);
2114     dirty_reg(current,HIREG);
2115     dirty_reg(current,LOREG);
2116   }
2117 }
2118 #endif
2119
2120 static void cop0_alloc(struct regstat *current,int i)
2121 {
2122   if(dops[i].opcode2==0) // MFC0
2123   {
2124     if(dops[i].rt1) {
2125       clear_const(current,dops[i].rt1);
2126       alloc_all(current,i);
2127       alloc_reg(current,i,dops[i].rt1);
2128       dirty_reg(current,dops[i].rt1);
2129     }
2130   }
2131   else if(dops[i].opcode2==4) // MTC0
2132   {
2133     if(dops[i].rs1){
2134       clear_const(current,dops[i].rs1);
2135       alloc_reg(current,i,dops[i].rs1);
2136       alloc_all(current,i);
2137     }
2138     else {
2139       alloc_all(current,i); // FIXME: Keep r0
2140       current->u&=~1LL;
2141       alloc_reg(current,i,0);
2142     }
2143   }
2144   else
2145   {
2146     // RFE
2147     assert(dops[i].opcode2==0x10);
2148     alloc_all(current,i);
2149   }
2150   minimum_free_regs[i]=HOST_REGS;
2151 }
2152
2153 static void cop2_alloc(struct regstat *current,int i)
2154 {
2155   if (dops[i].opcode2 < 3) // MFC2/CFC2
2156   {
2157     alloc_cc(current,i); // for stalls
2158     dirty_reg(current,CCREG);
2159     if(dops[i].rt1){
2160       clear_const(current,dops[i].rt1);
2161       alloc_reg(current,i,dops[i].rt1);
2162       dirty_reg(current,dops[i].rt1);
2163     }
2164   }
2165   else if (dops[i].opcode2 > 3) // MTC2/CTC2
2166   {
2167     if(dops[i].rs1){
2168       clear_const(current,dops[i].rs1);
2169       alloc_reg(current,i,dops[i].rs1);
2170     }
2171     else {
2172       current->u&=~1LL;
2173       alloc_reg(current,i,0);
2174     }
2175   }
2176   alloc_reg_temp(current,i,-1);
2177   minimum_free_regs[i]=1;
2178 }
2179
2180 static void c2op_alloc(struct regstat *current,int i)
2181 {
2182   alloc_cc(current,i); // for stalls
2183   dirty_reg(current,CCREG);
2184   alloc_reg_temp(current,i,-1);
2185 }
2186
2187 static void syscall_alloc(struct regstat *current,int i)
2188 {
2189   alloc_cc(current,i);
2190   dirty_reg(current,CCREG);
2191   alloc_all(current,i);
2192   minimum_free_regs[i]=HOST_REGS;
2193   current->isconst=0;
2194 }
2195
2196 static void delayslot_alloc(struct regstat *current,int i)
2197 {
2198   switch(dops[i].itype) {
2199     case UJUMP:
2200     case CJUMP:
2201     case SJUMP:
2202     case RJUMP:
2203     case SYSCALL:
2204     case HLECALL:
2205     case IMM16:
2206       imm16_alloc(current,i);
2207       break;
2208     case LOAD:
2209     case LOADLR:
2210       load_alloc(current,i);
2211       break;
2212     case STORE:
2213     case STORELR:
2214       store_alloc(current,i);
2215       break;
2216     case ALU:
2217       alu_alloc(current,i);
2218       break;
2219     case SHIFT:
2220       shift_alloc(current,i);
2221       break;
2222     case MULTDIV:
2223       multdiv_alloc(current,i);
2224       break;
2225     case SHIFTIMM:
2226       shiftimm_alloc(current,i);
2227       break;
2228     case MOV:
2229       mov_alloc(current,i);
2230       break;
2231     case COP0:
2232       cop0_alloc(current,i);
2233       break;
2234     case COP1:
2235       break;
2236     case COP2:
2237       cop2_alloc(current,i);
2238       break;
2239     case C1LS:
2240       c1ls_alloc(current,i);
2241       break;
2242     case C2LS:
2243       c2ls_alloc(current,i);
2244       break;
2245     case C2OP:
2246       c2op_alloc(current,i);
2247       break;
2248   }
2249 }
2250
2251 static void add_stub(enum stub_type type, void *addr, void *retaddr,
2252   u_int a, uintptr_t b, uintptr_t c, u_int d, u_int e)
2253 {
2254   assert(stubcount < ARRAY_SIZE(stubs));
2255   stubs[stubcount].type = type;
2256   stubs[stubcount].addr = addr;
2257   stubs[stubcount].retaddr = retaddr;
2258   stubs[stubcount].a = a;
2259   stubs[stubcount].b = b;
2260   stubs[stubcount].c = c;
2261   stubs[stubcount].d = d;
2262   stubs[stubcount].e = e;
2263   stubcount++;
2264 }
2265
2266 static void add_stub_r(enum stub_type type, void *addr, void *retaddr,
2267   int i, int addr_reg, const struct regstat *i_regs, int ccadj, u_int reglist)
2268 {
2269   add_stub(type, addr, retaddr, i, addr_reg, (uintptr_t)i_regs, ccadj, reglist);
2270 }
2271
2272 // Write out a single register
2273 static void wb_register(signed char r, const signed char regmap[], uint64_t dirty)
2274 {
2275   int hr;
2276   for(hr=0;hr<HOST_REGS;hr++) {
2277     if(hr!=EXCLUDE_REG) {
2278       if(regmap[hr]==r) {
2279         if((dirty>>hr)&1) {
2280           assert(regmap[hr]<64);
2281           emit_storereg(r,hr);
2282         }
2283       }
2284     }
2285   }
2286 }
2287
2288 static void wb_valid(signed char pre[],signed char entry[],u_int dirty_pre,u_int dirty,uint64_t u)
2289 {
2290   //if(dirty_pre==dirty) return;
2291   int hr, r;
2292   for (hr = 0; hr < HOST_REGS; hr++) {
2293     r = pre[hr];
2294     if (r < 1 || r > 33 || ((u >> r) & 1))
2295       continue;
2296     if (((dirty_pre & ~dirty) >> hr) & 1)
2297       emit_storereg(r, hr);
2298   }
2299 }
2300
2301 // trashes r2
2302 static void pass_args(int a0, int a1)
2303 {
2304   if(a0==1&&a1==0) {
2305     // must swap
2306     emit_mov(a0,2); emit_mov(a1,1); emit_mov(2,0);
2307   }
2308   else if(a0!=0&&a1==0) {
2309     emit_mov(a1,1);
2310     if (a0>=0) emit_mov(a0,0);
2311   }
2312   else {
2313     if(a0>=0&&a0!=0) emit_mov(a0,0);
2314     if(a1>=0&&a1!=1) emit_mov(a1,1);
2315   }
2316 }
2317
2318 static void alu_assemble(int i, const struct regstat *i_regs)
2319 {
2320   if(dops[i].opcode2>=0x20&&dops[i].opcode2<=0x23) { // ADD/ADDU/SUB/SUBU
2321     if(dops[i].rt1) {
2322       signed char s1,s2,t;
2323       t=get_reg(i_regs->regmap,dops[i].rt1);
2324       if(t>=0) {
2325         s1=get_reg(i_regs->regmap,dops[i].rs1);
2326         s2=get_reg(i_regs->regmap,dops[i].rs2);
2327         if(dops[i].rs1&&dops[i].rs2) {
2328           assert(s1>=0);
2329           assert(s2>=0);
2330           if(dops[i].opcode2&2) emit_sub(s1,s2,t);
2331           else emit_add(s1,s2,t);
2332         }
2333         else if(dops[i].rs1) {
2334           if(s1>=0) emit_mov(s1,t);
2335           else emit_loadreg(dops[i].rs1,t);
2336         }
2337         else if(dops[i].rs2) {
2338           if(s2>=0) {
2339             if(dops[i].opcode2&2) emit_neg(s2,t);
2340             else emit_mov(s2,t);
2341           }
2342           else {
2343             emit_loadreg(dops[i].rs2,t);
2344             if(dops[i].opcode2&2) emit_neg(t,t);
2345           }
2346         }
2347         else emit_zeroreg(t);
2348       }
2349     }
2350   }
2351   if(dops[i].opcode2>=0x2c&&dops[i].opcode2<=0x2f) { // DADD/DADDU/DSUB/DSUBU
2352     assert(0);
2353   }
2354   if(dops[i].opcode2==0x2a||dops[i].opcode2==0x2b) { // SLT/SLTU
2355     if(dops[i].rt1) {
2356       signed char s1l,s2l,t;
2357       {
2358         t=get_reg(i_regs->regmap,dops[i].rt1);
2359         //assert(t>=0);
2360         if(t>=0) {
2361           s1l=get_reg(i_regs->regmap,dops[i].rs1);
2362           s2l=get_reg(i_regs->regmap,dops[i].rs2);
2363           if(dops[i].rs2==0) // rx<r0
2364           {
2365             if(dops[i].opcode2==0x2a&&dops[i].rs1!=0) { // SLT
2366               assert(s1l>=0);
2367               emit_shrimm(s1l,31,t);
2368             }
2369             else // SLTU (unsigned can not be less than zero, 0<0)
2370               emit_zeroreg(t);
2371           }
2372           else if(dops[i].rs1==0) // r0<rx
2373           {
2374             assert(s2l>=0);
2375             if(dops[i].opcode2==0x2a) // SLT
2376               emit_set_gz32(s2l,t);
2377             else // SLTU (set if not zero)
2378               emit_set_nz32(s2l,t);
2379           }
2380           else{
2381             assert(s1l>=0);assert(s2l>=0);
2382             if(dops[i].opcode2==0x2a) // SLT
2383               emit_set_if_less32(s1l,s2l,t);
2384             else // SLTU
2385               emit_set_if_carry32(s1l,s2l,t);
2386           }
2387         }
2388       }
2389     }
2390   }
2391   if(dops[i].opcode2>=0x24&&dops[i].opcode2<=0x27) { // AND/OR/XOR/NOR
2392     if(dops[i].rt1) {
2393       signed char s1l,s2l,tl;
2394       tl=get_reg(i_regs->regmap,dops[i].rt1);
2395       {
2396         if(tl>=0) {
2397           s1l=get_reg(i_regs->regmap,dops[i].rs1);
2398           s2l=get_reg(i_regs->regmap,dops[i].rs2);
2399           if(dops[i].rs1&&dops[i].rs2) {
2400             assert(s1l>=0);
2401             assert(s2l>=0);
2402             if(dops[i].opcode2==0x24) { // AND
2403               emit_and(s1l,s2l,tl);
2404             } else
2405             if(dops[i].opcode2==0x25) { // OR
2406               emit_or(s1l,s2l,tl);
2407             } else
2408             if(dops[i].opcode2==0x26) { // XOR
2409               emit_xor(s1l,s2l,tl);
2410             } else
2411             if(dops[i].opcode2==0x27) { // NOR
2412               emit_or(s1l,s2l,tl);
2413               emit_not(tl,tl);
2414             }
2415           }
2416           else
2417           {
2418             if(dops[i].opcode2==0x24) { // AND
2419               emit_zeroreg(tl);
2420             } else
2421             if(dops[i].opcode2==0x25||dops[i].opcode2==0x26) { // OR/XOR
2422               if(dops[i].rs1){
2423                 if(s1l>=0) emit_mov(s1l,tl);
2424                 else emit_loadreg(dops[i].rs1,tl); // CHECK: regmap_entry?
2425               }
2426               else
2427               if(dops[i].rs2){
2428                 if(s2l>=0) emit_mov(s2l,tl);
2429                 else emit_loadreg(dops[i].rs2,tl); // CHECK: regmap_entry?
2430               }
2431               else emit_zeroreg(tl);
2432             } else
2433             if(dops[i].opcode2==0x27) { // NOR
2434               if(dops[i].rs1){
2435                 if(s1l>=0) emit_not(s1l,tl);
2436                 else {
2437                   emit_loadreg(dops[i].rs1,tl);
2438                   emit_not(tl,tl);
2439                 }
2440               }
2441               else
2442               if(dops[i].rs2){
2443                 if(s2l>=0) emit_not(s2l,tl);
2444                 else {
2445                   emit_loadreg(dops[i].rs2,tl);
2446                   emit_not(tl,tl);
2447                 }
2448               }
2449               else emit_movimm(-1,tl);
2450             }
2451           }
2452         }
2453       }
2454     }
2455   }
2456 }
2457
2458 static void imm16_assemble(int i, const struct regstat *i_regs)
2459 {
2460   if (dops[i].opcode==0x0f) { // LUI
2461     if(dops[i].rt1) {
2462       signed char t;
2463       t=get_reg(i_regs->regmap,dops[i].rt1);
2464       //assert(t>=0);
2465       if(t>=0) {
2466         if(!((i_regs->isconst>>t)&1))
2467           emit_movimm(imm[i]<<16,t);
2468       }
2469     }
2470   }
2471   if(dops[i].opcode==0x08||dops[i].opcode==0x09) { // ADDI/ADDIU
2472     if(dops[i].rt1) {
2473       signed char s,t;
2474       t=get_reg(i_regs->regmap,dops[i].rt1);
2475       s=get_reg(i_regs->regmap,dops[i].rs1);
2476       if(dops[i].rs1) {
2477         //assert(t>=0);
2478         //assert(s>=0);
2479         if(t>=0) {
2480           if(!((i_regs->isconst>>t)&1)) {
2481             if(s<0) {
2482               if(i_regs->regmap_entry[t]!=dops[i].rs1) emit_loadreg(dops[i].rs1,t);
2483               emit_addimm(t,imm[i],t);
2484             }else{
2485               if(!((i_regs->wasconst>>s)&1))
2486                 emit_addimm(s,imm[i],t);
2487               else
2488                 emit_movimm(constmap[i][s]+imm[i],t);
2489             }
2490           }
2491         }
2492       } else {
2493         if(t>=0) {
2494           if(!((i_regs->isconst>>t)&1))
2495             emit_movimm(imm[i],t);
2496         }
2497       }
2498     }
2499   }
2500   if(dops[i].opcode==0x18||dops[i].opcode==0x19) { // DADDI/DADDIU
2501     if(dops[i].rt1) {
2502       signed char sl,tl;
2503       tl=get_reg(i_regs->regmap,dops[i].rt1);
2504       sl=get_reg(i_regs->regmap,dops[i].rs1);
2505       if(tl>=0) {
2506         if(dops[i].rs1) {
2507           assert(sl>=0);
2508           emit_addimm(sl,imm[i],tl);
2509         } else {
2510           emit_movimm(imm[i],tl);
2511         }
2512       }
2513     }
2514   }
2515   else if(dops[i].opcode==0x0a||dops[i].opcode==0x0b) { // SLTI/SLTIU
2516     if(dops[i].rt1) {
2517       //assert(dops[i].rs1!=0); // r0 might be valid, but it's probably a bug
2518       signed char sl,t;
2519       t=get_reg(i_regs->regmap,dops[i].rt1);
2520       sl=get_reg(i_regs->regmap,dops[i].rs1);
2521       //assert(t>=0);
2522       if(t>=0) {
2523         if(dops[i].rs1>0) {
2524             if(dops[i].opcode==0x0a) { // SLTI
2525               if(sl<0) {
2526                 if(i_regs->regmap_entry[t]!=dops[i].rs1) emit_loadreg(dops[i].rs1,t);
2527                 emit_slti32(t,imm[i],t);
2528               }else{
2529                 emit_slti32(sl,imm[i],t);
2530               }
2531             }
2532             else { // SLTIU
2533               if(sl<0) {
2534                 if(i_regs->regmap_entry[t]!=dops[i].rs1) emit_loadreg(dops[i].rs1,t);
2535                 emit_sltiu32(t,imm[i],t);
2536               }else{
2537                 emit_sltiu32(sl,imm[i],t);
2538               }
2539             }
2540         }else{
2541           // SLTI(U) with r0 is just stupid,
2542           // nonetheless examples can be found
2543           if(dops[i].opcode==0x0a) // SLTI
2544             if(0<imm[i]) emit_movimm(1,t);
2545             else emit_zeroreg(t);
2546           else // SLTIU
2547           {
2548             if(imm[i]) emit_movimm(1,t);
2549             else emit_zeroreg(t);
2550           }
2551         }
2552       }
2553     }
2554   }
2555   else if(dops[i].opcode>=0x0c&&dops[i].opcode<=0x0e) { // ANDI/ORI/XORI
2556     if(dops[i].rt1) {
2557       signed char sl,tl;
2558       tl=get_reg(i_regs->regmap,dops[i].rt1);
2559       sl=get_reg(i_regs->regmap,dops[i].rs1);
2560       if(tl>=0 && !((i_regs->isconst>>tl)&1)) {
2561         if(dops[i].opcode==0x0c) //ANDI
2562         {
2563           if(dops[i].rs1) {
2564             if(sl<0) {
2565               if(i_regs->regmap_entry[tl]!=dops[i].rs1) emit_loadreg(dops[i].rs1,tl);
2566               emit_andimm(tl,imm[i],tl);
2567             }else{
2568               if(!((i_regs->wasconst>>sl)&1))
2569                 emit_andimm(sl,imm[i],tl);
2570               else
2571                 emit_movimm(constmap[i][sl]&imm[i],tl);
2572             }
2573           }
2574           else
2575             emit_zeroreg(tl);
2576         }
2577         else
2578         {
2579           if(dops[i].rs1) {
2580             if(sl<0) {
2581               if(i_regs->regmap_entry[tl]!=dops[i].rs1) emit_loadreg(dops[i].rs1,tl);
2582             }
2583             if(dops[i].opcode==0x0d) { // ORI
2584               if(sl<0) {
2585                 emit_orimm(tl,imm[i],tl);
2586               }else{
2587                 if(!((i_regs->wasconst>>sl)&1))
2588                   emit_orimm(sl,imm[i],tl);
2589                 else
2590                   emit_movimm(constmap[i][sl]|imm[i],tl);
2591               }
2592             }
2593             if(dops[i].opcode==0x0e) { // XORI
2594               if(sl<0) {
2595                 emit_xorimm(tl,imm[i],tl);
2596               }else{
2597                 if(!((i_regs->wasconst>>sl)&1))
2598                   emit_xorimm(sl,imm[i],tl);
2599                 else
2600                   emit_movimm(constmap[i][sl]^imm[i],tl);
2601               }
2602             }
2603           }
2604           else {
2605             emit_movimm(imm[i],tl);
2606           }
2607         }
2608       }
2609     }
2610   }
2611 }
2612
2613 static void shiftimm_assemble(int i, const struct regstat *i_regs)
2614 {
2615   if(dops[i].opcode2<=0x3) // SLL/SRL/SRA
2616   {
2617     if(dops[i].rt1) {
2618       signed char s,t;
2619       t=get_reg(i_regs->regmap,dops[i].rt1);
2620       s=get_reg(i_regs->regmap,dops[i].rs1);
2621       //assert(t>=0);
2622       if(t>=0&&!((i_regs->isconst>>t)&1)){
2623         if(dops[i].rs1==0)
2624         {
2625           emit_zeroreg(t);
2626         }
2627         else
2628         {
2629           if(s<0&&i_regs->regmap_entry[t]!=dops[i].rs1) emit_loadreg(dops[i].rs1,t);
2630           if(imm[i]) {
2631             if(dops[i].opcode2==0) // SLL
2632             {
2633               emit_shlimm(s<0?t:s,imm[i],t);
2634             }
2635             if(dops[i].opcode2==2) // SRL
2636             {
2637               emit_shrimm(s<0?t:s,imm[i],t);
2638             }
2639             if(dops[i].opcode2==3) // SRA
2640             {
2641               emit_sarimm(s<0?t:s,imm[i],t);
2642             }
2643           }else{
2644             // Shift by zero
2645             if(s>=0 && s!=t) emit_mov(s,t);
2646           }
2647         }
2648       }
2649       //emit_storereg(dops[i].rt1,t); //DEBUG
2650     }
2651   }
2652   if(dops[i].opcode2>=0x38&&dops[i].opcode2<=0x3b) // DSLL/DSRL/DSRA
2653   {
2654     assert(0);
2655   }
2656   if(dops[i].opcode2==0x3c) // DSLL32
2657   {
2658     assert(0);
2659   }
2660   if(dops[i].opcode2==0x3e) // DSRL32
2661   {
2662     assert(0);
2663   }
2664   if(dops[i].opcode2==0x3f) // DSRA32
2665   {
2666     assert(0);
2667   }
2668 }
2669
2670 #ifndef shift_assemble
2671 static void shift_assemble(int i, const struct regstat *i_regs)
2672 {
2673   signed char s,t,shift;
2674   if (dops[i].rt1 == 0)
2675     return;
2676   assert(dops[i].opcode2<=0x07); // SLLV/SRLV/SRAV
2677   t = get_reg(i_regs->regmap, dops[i].rt1);
2678   s = get_reg(i_regs->regmap, dops[i].rs1);
2679   shift = get_reg(i_regs->regmap, dops[i].rs2);
2680   if (t < 0)
2681     return;
2682
2683   if(dops[i].rs1==0)
2684     emit_zeroreg(t);
2685   else if(dops[i].rs2==0) {
2686     assert(s>=0);
2687     if(s!=t) emit_mov(s,t);
2688   }
2689   else {
2690     host_tempreg_acquire();
2691     emit_andimm(shift,31,HOST_TEMPREG);
2692     switch(dops[i].opcode2) {
2693     case 4: // SLLV
2694       emit_shl(s,HOST_TEMPREG,t);
2695       break;
2696     case 6: // SRLV
2697       emit_shr(s,HOST_TEMPREG,t);
2698       break;
2699     case 7: // SRAV
2700       emit_sar(s,HOST_TEMPREG,t);
2701       break;
2702     default:
2703       assert(0);
2704     }
2705     host_tempreg_release();
2706   }
2707 }
2708
2709 #endif
2710
2711 enum {
2712   MTYPE_8000 = 0,
2713   MTYPE_8020,
2714   MTYPE_0000,
2715   MTYPE_A000,
2716   MTYPE_1F80,
2717 };
2718
2719 static int get_ptr_mem_type(u_int a)
2720 {
2721   if(a < 0x00200000) {
2722     if(a<0x1000&&((start>>20)==0xbfc||(start>>24)==0xa0))
2723       // return wrong, must use memhandler for BIOS self-test to pass
2724       // 007 does similar stuff from a00 mirror, weird stuff
2725       return MTYPE_8000;
2726     return MTYPE_0000;
2727   }
2728   if(0x1f800000 <= a && a < 0x1f801000)
2729     return MTYPE_1F80;
2730   if(0x80200000 <= a && a < 0x80800000)
2731     return MTYPE_8020;
2732   if(0xa0000000 <= a && a < 0xa0200000)
2733     return MTYPE_A000;
2734   return MTYPE_8000;
2735 }
2736
2737 static int get_ro_reg(const struct regstat *i_regs, int host_tempreg_free)
2738 {
2739   int r = get_reg(i_regs->regmap, ROREG);
2740   if (r < 0 && host_tempreg_free) {
2741     host_tempreg_acquire();
2742     emit_loadreg(ROREG, r = HOST_TEMPREG);
2743   }
2744   if (r < 0)
2745     abort();
2746   return r;
2747 }
2748
2749 static void *emit_fastpath_cmp_jump(int i, const struct regstat *i_regs,
2750   int addr, int *offset_reg, int *addr_reg_override)
2751 {
2752   void *jaddr = NULL;
2753   int type = 0;
2754   int mr = dops[i].rs1;
2755   *offset_reg = -1;
2756   if(((smrv_strong|smrv_weak)>>mr)&1) {
2757     type=get_ptr_mem_type(smrv[mr]);
2758     //printf("set %08x @%08x r%d %d\n", smrv[mr], start+i*4, mr, type);
2759   }
2760   else {
2761     // use the mirror we are running on
2762     type=get_ptr_mem_type(start);
2763     //printf("set nospec   @%08x r%d %d\n", start+i*4, mr, type);
2764   }
2765
2766   if(type==MTYPE_8020) { // RAM 80200000+ mirror
2767     host_tempreg_acquire();
2768     emit_andimm(addr,~0x00e00000,HOST_TEMPREG);
2769     addr=*addr_reg_override=HOST_TEMPREG;
2770     type=0;
2771   }
2772   else if(type==MTYPE_0000) { // RAM 0 mirror
2773     host_tempreg_acquire();
2774     emit_orimm(addr,0x80000000,HOST_TEMPREG);
2775     addr=*addr_reg_override=HOST_TEMPREG;
2776     type=0;
2777   }
2778   else if(type==MTYPE_A000) { // RAM A mirror
2779     host_tempreg_acquire();
2780     emit_andimm(addr,~0x20000000,HOST_TEMPREG);
2781     addr=*addr_reg_override=HOST_TEMPREG;
2782     type=0;
2783   }
2784   else if(type==MTYPE_1F80) { // scratchpad
2785     if (psxH == (void *)0x1f800000) {
2786       host_tempreg_acquire();
2787       emit_xorimm(addr,0x1f800000,HOST_TEMPREG);
2788       emit_cmpimm(HOST_TEMPREG,0x1000);
2789       host_tempreg_release();
2790       jaddr=out;
2791       emit_jc(0);
2792     }
2793     else {
2794       // do the usual RAM check, jump will go to the right handler
2795       type=0;
2796     }
2797   }
2798
2799   if (type == 0) // need ram check
2800   {
2801     emit_cmpimm(addr,RAM_SIZE);
2802     jaddr = out;
2803     #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
2804     // Hint to branch predictor that the branch is unlikely to be taken
2805     if (dops[i].rs1 >= 28)
2806       emit_jno_unlikely(0);
2807     else
2808     #endif
2809       emit_jno(0);
2810     if (ram_offset != 0)
2811       *offset_reg = get_ro_reg(i_regs, 0);
2812   }
2813
2814   return jaddr;
2815 }
2816
2817 // return memhandler, or get directly accessable address and return 0
2818 static void *get_direct_memhandler(void *table, u_int addr,
2819   enum stub_type type, uintptr_t *addr_host)
2820 {
2821   uintptr_t msb = 1ull << (sizeof(uintptr_t)*8 - 1);
2822   uintptr_t l1, l2 = 0;
2823   l1 = ((uintptr_t *)table)[addr>>12];
2824   if (!(l1 & msb)) {
2825     uintptr_t v = l1 << 1;
2826     *addr_host = v + addr;
2827     return NULL;
2828   }
2829   else {
2830     l1 <<= 1;
2831     if (type == LOADB_STUB || type == LOADBU_STUB || type == STOREB_STUB)
2832       l2 = ((uintptr_t *)l1)[0x1000/4 + 0x1000/2 + (addr&0xfff)];
2833     else if (type == LOADH_STUB || type == LOADHU_STUB || type == STOREH_STUB)
2834       l2 = ((uintptr_t *)l1)[0x1000/4 + (addr&0xfff)/2];
2835     else
2836       l2 = ((uintptr_t *)l1)[(addr&0xfff)/4];
2837     if (!(l2 & msb)) {
2838       uintptr_t v = l2 << 1;
2839       *addr_host = v + (addr&0xfff);
2840       return NULL;
2841     }
2842     return (void *)(l2 << 1);
2843   }
2844 }
2845
2846 static u_int get_host_reglist(const signed char *regmap)
2847 {
2848   u_int reglist = 0, hr;
2849   for (hr = 0; hr < HOST_REGS; hr++) {
2850     if (hr != EXCLUDE_REG && regmap[hr] >= 0)
2851       reglist |= 1 << hr;
2852   }
2853   return reglist;
2854 }
2855
2856 static u_int reglist_exclude(u_int reglist, int r1, int r2)
2857 {
2858   if (r1 >= 0)
2859     reglist &= ~(1u << r1);
2860   if (r2 >= 0)
2861     reglist &= ~(1u << r2);
2862   return reglist;
2863 }
2864
2865 // find a temp caller-saved register not in reglist (so assumed to be free)
2866 static int reglist_find_free(u_int reglist)
2867 {
2868   u_int free_regs = ~reglist & CALLER_SAVE_REGS;
2869   if (free_regs == 0)
2870     return -1;
2871   return __builtin_ctz(free_regs);
2872 }
2873
2874 static void do_load_word(int a, int rt, int offset_reg)
2875 {
2876   if (offset_reg >= 0)
2877     emit_ldr_dualindexed(offset_reg, a, rt);
2878   else
2879     emit_readword_indexed(0, a, rt);
2880 }
2881
2882 static void do_store_word(int a, int ofs, int rt, int offset_reg, int preseve_a)
2883 {
2884   if (offset_reg < 0) {
2885     emit_writeword_indexed(rt, ofs, a);
2886     return;
2887   }
2888   if (ofs != 0)
2889     emit_addimm(a, ofs, a);
2890   emit_str_dualindexed(offset_reg, a, rt);
2891   if (ofs != 0 && preseve_a)
2892     emit_addimm(a, -ofs, a);
2893 }
2894
2895 static void do_store_hword(int a, int ofs, int rt, int offset_reg, int preseve_a)
2896 {
2897   if (offset_reg < 0) {
2898     emit_writehword_indexed(rt, ofs, a);
2899     return;
2900   }
2901   if (ofs != 0)
2902     emit_addimm(a, ofs, a);
2903   emit_strh_dualindexed(offset_reg, a, rt);
2904   if (ofs != 0 && preseve_a)
2905     emit_addimm(a, -ofs, a);
2906 }
2907
2908 static void do_store_byte(int a, int rt, int offset_reg)
2909 {
2910   if (offset_reg >= 0)
2911     emit_strb_dualindexed(offset_reg, a, rt);
2912   else
2913     emit_writebyte_indexed(rt, 0, a);
2914 }
2915
2916 static void load_assemble(int i, const struct regstat *i_regs, int ccadj_)
2917 {
2918   int s,tl,addr;
2919   int offset;
2920   void *jaddr=0;
2921   int memtarget=0,c=0;
2922   int offset_reg = -1;
2923   int fastio_reg_override = -1;
2924   u_int reglist=get_host_reglist(i_regs->regmap);
2925   tl=get_reg(i_regs->regmap,dops[i].rt1);
2926   s=get_reg(i_regs->regmap,dops[i].rs1);
2927   offset=imm[i];
2928   if(i_regs->regmap[HOST_CCREG]==CCREG) reglist&=~(1<<HOST_CCREG);
2929   if(s>=0) {
2930     c=(i_regs->wasconst>>s)&1;
2931     if (c) {
2932       memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE;
2933     }
2934   }
2935   //printf("load_assemble: c=%d\n",c);
2936   //if(c) printf("load_assemble: const=%lx\n",(long)constmap[i][s]+offset);
2937   // FIXME: Even if the load is a NOP, we should check for pagefaults...
2938   if((tl<0&&(!c||(((u_int)constmap[i][s]+offset)>>16)==0x1f80))
2939     ||dops[i].rt1==0) {
2940       // could be FIFO, must perform the read
2941       // ||dummy read
2942       assem_debug("(forced read)\n");
2943       tl=get_reg_temp(i_regs->regmap);
2944       assert(tl>=0);
2945   }
2946   if(offset||s<0||c) addr=tl;
2947   else addr=s;
2948   //if(tl<0) tl=get_reg_temp(i_regs->regmap);
2949  if(tl>=0) {
2950   //printf("load_assemble: c=%d\n",c);
2951   //if(c) printf("load_assemble: const=%lx\n",(long)constmap[i][s]+offset);
2952   assert(tl>=0); // Even if the load is a NOP, we must check for pagefaults and I/O
2953   reglist&=~(1<<tl);
2954   if(!c) {
2955     #ifdef R29_HACK
2956     // Strmnnrmn's speed hack
2957     if(dops[i].rs1!=29||start<0x80001000||start>=0x80000000+RAM_SIZE)
2958     #endif
2959     {
2960       jaddr = emit_fastpath_cmp_jump(i, i_regs, addr,
2961                 &offset_reg, &fastio_reg_override);
2962     }
2963   }
2964   else if (ram_offset && memtarget) {
2965     offset_reg = get_ro_reg(i_regs, 0);
2966   }
2967   int dummy=(dops[i].rt1==0)||(tl!=get_reg(i_regs->regmap,dops[i].rt1)); // ignore loads to r0 and unneeded reg
2968   switch (dops[i].opcode) {
2969   case 0x20: // LB
2970     if(!c||memtarget) {
2971       if(!dummy) {
2972         int a = tl;
2973         if (!c) a = addr;
2974         if (fastio_reg_override >= 0)
2975           a = fastio_reg_override;
2976
2977         if (offset_reg >= 0)
2978           emit_ldrsb_dualindexed(offset_reg, a, tl);
2979         else
2980           emit_movsbl_indexed(0, a, tl);
2981       }
2982       if(jaddr)
2983         add_stub_r(LOADB_STUB,jaddr,out,i,addr,i_regs,ccadj_,reglist);
2984     }
2985     else
2986       inline_readstub(LOADB_STUB,i,constmap[i][s]+offset,i_regs->regmap,dops[i].rt1,ccadj_,reglist);
2987     break;
2988   case 0x21: // LH
2989     if(!c||memtarget) {
2990       if(!dummy) {
2991         int a = tl;
2992         if (!c) a = addr;
2993         if (fastio_reg_override >= 0)
2994           a = fastio_reg_override;
2995         if (offset_reg >= 0)
2996           emit_ldrsh_dualindexed(offset_reg, a, tl);
2997         else
2998           emit_movswl_indexed(0, a, tl);
2999       }
3000       if(jaddr)
3001         add_stub_r(LOADH_STUB,jaddr,out,i,addr,i_regs,ccadj_,reglist);
3002     }
3003     else
3004       inline_readstub(LOADH_STUB,i,constmap[i][s]+offset,i_regs->regmap,dops[i].rt1,ccadj_,reglist);
3005     break;
3006   case 0x23: // LW
3007     if(!c||memtarget) {
3008       if(!dummy) {
3009         int a = addr;
3010         if (fastio_reg_override >= 0)
3011           a = fastio_reg_override;
3012         do_load_word(a, tl, offset_reg);
3013       }
3014       if(jaddr)
3015         add_stub_r(LOADW_STUB,jaddr,out,i,addr,i_regs,ccadj_,reglist);
3016     }
3017     else
3018       inline_readstub(LOADW_STUB,i,constmap[i][s]+offset,i_regs->regmap,dops[i].rt1,ccadj_,reglist);
3019     break;
3020   case 0x24: // LBU
3021     if(!c||memtarget) {
3022       if(!dummy) {
3023         int a = tl;
3024         if (!c) a = addr;
3025         if (fastio_reg_override >= 0)
3026           a = fastio_reg_override;
3027
3028         if (offset_reg >= 0)
3029           emit_ldrb_dualindexed(offset_reg, a, tl);
3030         else
3031           emit_movzbl_indexed(0, a, tl);
3032       }
3033       if(jaddr)
3034         add_stub_r(LOADBU_STUB,jaddr,out,i,addr,i_regs,ccadj_,reglist);
3035     }
3036     else
3037       inline_readstub(LOADBU_STUB,i,constmap[i][s]+offset,i_regs->regmap,dops[i].rt1,ccadj_,reglist);
3038     break;
3039   case 0x25: // LHU
3040     if(!c||memtarget) {
3041       if(!dummy) {
3042         int a = tl;
3043         if(!c) a = addr;
3044         if (fastio_reg_override >= 0)
3045           a = fastio_reg_override;
3046         if (offset_reg >= 0)
3047           emit_ldrh_dualindexed(offset_reg, a, tl);
3048         else
3049           emit_movzwl_indexed(0, a, tl);
3050       }
3051       if(jaddr)
3052         add_stub_r(LOADHU_STUB,jaddr,out,i,addr,i_regs,ccadj_,reglist);
3053     }
3054     else
3055       inline_readstub(LOADHU_STUB,i,constmap[i][s]+offset,i_regs->regmap,dops[i].rt1,ccadj_,reglist);
3056     break;
3057   case 0x27: // LWU
3058   case 0x37: // LD
3059   default:
3060     assert(0);
3061   }
3062  }
3063  if (fastio_reg_override == HOST_TEMPREG || offset_reg == HOST_TEMPREG)
3064    host_tempreg_release();
3065 }
3066
3067 #ifndef loadlr_assemble
3068 static void loadlr_assemble(int i, const struct regstat *i_regs, int ccadj_)
3069 {
3070   int s,tl,temp,temp2,addr;
3071   int offset;
3072   void *jaddr=0;
3073   int memtarget=0,c=0;
3074   int offset_reg = -1;
3075   int fastio_reg_override = -1;
3076   u_int reglist=get_host_reglist(i_regs->regmap);
3077   tl=get_reg(i_regs->regmap,dops[i].rt1);
3078   s=get_reg(i_regs->regmap,dops[i].rs1);
3079   temp=get_reg_temp(i_regs->regmap);
3080   temp2=get_reg(i_regs->regmap,FTEMP);
3081   addr=get_reg(i_regs->regmap,AGEN1+(i&1));
3082   assert(addr<0);
3083   offset=imm[i];
3084   reglist|=1<<temp;
3085   if(offset||s<0||c) addr=temp2;
3086   else addr=s;
3087   if(s>=0) {
3088     c=(i_regs->wasconst>>s)&1;
3089     if(c) {
3090       memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE;
3091     }
3092   }
3093   if(!c) {
3094     emit_shlimm(addr,3,temp);
3095     if (dops[i].opcode==0x22||dops[i].opcode==0x26) {
3096       emit_andimm(addr,0xFFFFFFFC,temp2); // LWL/LWR
3097     }else{
3098       emit_andimm(addr,0xFFFFFFF8,temp2); // LDL/LDR
3099     }
3100     jaddr = emit_fastpath_cmp_jump(i, i_regs, temp2,
3101               &offset_reg, &fastio_reg_override);
3102   }
3103   else {
3104     if (ram_offset && memtarget) {
3105       offset_reg = get_ro_reg(i_regs, 0);
3106     }
3107     if (dops[i].opcode==0x22||dops[i].opcode==0x26) {
3108       emit_movimm(((constmap[i][s]+offset)<<3)&24,temp); // LWL/LWR
3109     }else{
3110       emit_movimm(((constmap[i][s]+offset)<<3)&56,temp); // LDL/LDR
3111     }
3112   }
3113   if (dops[i].opcode==0x22||dops[i].opcode==0x26) { // LWL/LWR
3114     if(!c||memtarget) {
3115       int a = temp2;
3116       if (fastio_reg_override >= 0)
3117         a = fastio_reg_override;
3118       do_load_word(a, temp2, offset_reg);
3119       if (fastio_reg_override == HOST_TEMPREG || offset_reg == HOST_TEMPREG)
3120         host_tempreg_release();
3121       if(jaddr) add_stub_r(LOADW_STUB,jaddr,out,i,temp2,i_regs,ccadj_,reglist);
3122     }
3123     else
3124       inline_readstub(LOADW_STUB,i,(constmap[i][s]+offset)&0xFFFFFFFC,i_regs->regmap,FTEMP,ccadj_,reglist);
3125     if(dops[i].rt1) {
3126       assert(tl>=0);
3127       emit_andimm(temp,24,temp);
3128       if (dops[i].opcode==0x22) // LWL
3129         emit_xorimm(temp,24,temp);
3130       host_tempreg_acquire();
3131       emit_movimm(-1,HOST_TEMPREG);
3132       if (dops[i].opcode==0x26) {
3133         emit_shr(temp2,temp,temp2);
3134         emit_bic_lsr(tl,HOST_TEMPREG,temp,tl);
3135       }else{
3136         emit_shl(temp2,temp,temp2);
3137         emit_bic_lsl(tl,HOST_TEMPREG,temp,tl);
3138       }
3139       host_tempreg_release();
3140       emit_or(temp2,tl,tl);
3141     }
3142     //emit_storereg(dops[i].rt1,tl); // DEBUG
3143   }
3144   if (dops[i].opcode==0x1A||dops[i].opcode==0x1B) { // LDL/LDR
3145     assert(0);
3146   }
3147 }
3148 #endif
3149
3150 static void store_assemble(int i, const struct regstat *i_regs, int ccadj_)
3151 {
3152   int s,tl;
3153   int addr,temp;
3154   int offset;
3155   void *jaddr=0;
3156   enum stub_type type=0;
3157   int memtarget=0,c=0;
3158   int agr=AGEN1+(i&1);
3159   int offset_reg = -1;
3160   int fastio_reg_override = -1;
3161   u_int reglist=get_host_reglist(i_regs->regmap);
3162   tl=get_reg(i_regs->regmap,dops[i].rs2);
3163   s=get_reg(i_regs->regmap,dops[i].rs1);
3164   temp=get_reg(i_regs->regmap,agr);
3165   if(temp<0) temp=get_reg_temp(i_regs->regmap);
3166   offset=imm[i];
3167   if(s>=0) {
3168     c=(i_regs->wasconst>>s)&1;
3169     if(c) {
3170       memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE;
3171     }
3172   }
3173   assert(tl>=0);
3174   assert(temp>=0);
3175   if(i_regs->regmap[HOST_CCREG]==CCREG) reglist&=~(1<<HOST_CCREG);
3176   if(offset||s<0||c) addr=temp;
3177   else addr=s;
3178   if (!c) {
3179     jaddr = emit_fastpath_cmp_jump(i, i_regs, addr,
3180               &offset_reg, &fastio_reg_override);
3181   }
3182   else if (ram_offset && memtarget) {
3183     offset_reg = get_ro_reg(i_regs, 0);
3184   }
3185
3186   switch (dops[i].opcode) {
3187   case 0x28: // SB
3188     if(!c||memtarget) {
3189       int a = temp;
3190       if (!c) a = addr;
3191       if (fastio_reg_override >= 0)
3192         a = fastio_reg_override;
3193       do_store_byte(a, tl, offset_reg);
3194     }
3195     type = STOREB_STUB;
3196     break;
3197   case 0x29: // SH
3198     if(!c||memtarget) {
3199       int a = temp;
3200       if (!c) a = addr;
3201       if (fastio_reg_override >= 0)
3202         a = fastio_reg_override;
3203       do_store_hword(a, 0, tl, offset_reg, 1);
3204     }
3205     type = STOREH_STUB;
3206     break;
3207   case 0x2B: // SW
3208     if(!c||memtarget) {
3209       int a = addr;
3210       if (fastio_reg_override >= 0)
3211         a = fastio_reg_override;
3212       do_store_word(a, 0, tl, offset_reg, 1);
3213     }
3214     type = STOREW_STUB;
3215     break;
3216   case 0x3F: // SD
3217   default:
3218     assert(0);
3219   }
3220   if (fastio_reg_override == HOST_TEMPREG || offset_reg == HOST_TEMPREG)
3221     host_tempreg_release();
3222   if(jaddr) {
3223     // PCSX store handlers don't check invcode again
3224     reglist|=1<<addr;
3225     add_stub_r(type,jaddr,out,i,addr,i_regs,ccadj_,reglist);
3226     jaddr=0;
3227   }
3228   if(!(i_regs->waswritten&(1<<dops[i].rs1)) && !HACK_ENABLED(NDHACK_NO_SMC_CHECK)) {
3229     if(!c||memtarget) {
3230       #ifdef DESTRUCTIVE_SHIFT
3231       // The x86 shift operation is 'destructive'; it overwrites the
3232       // source register, so we need to make a copy first and use that.
3233       addr=temp;
3234       #endif
3235       #if defined(HOST_IMM8)
3236       int ir=get_reg(i_regs->regmap,INVCP);
3237       assert(ir>=0);
3238       emit_cmpmem_indexedsr12_reg(ir,addr,1);
3239       #else
3240       emit_cmpmem_indexedsr12_imm(invalid_code,addr,1);
3241       #endif
3242       #ifdef INVALIDATE_USE_COND_CALL
3243       emit_callne(invalidate_addr_reg[addr]);
3244       #else
3245       void *jaddr2 = out;
3246       emit_jne(0);
3247       add_stub(INVCODE_STUB,jaddr2,out,reglist|(1<<HOST_CCREG),addr,0,0,0);
3248       #endif
3249     }
3250   }
3251   u_int addr_val=constmap[i][s]+offset;
3252   if(jaddr) {
3253     add_stub_r(type,jaddr,out,i,addr,i_regs,ccadj_,reglist);
3254   } else if(c&&!memtarget) {
3255     inline_writestub(type,i,addr_val,i_regs->regmap,dops[i].rs2,ccadj_,reglist);
3256   }
3257   // basic current block modification detection..
3258   // not looking back as that should be in mips cache already
3259   // (see Spyro2 title->attract mode)
3260   if(c&&start+i*4<addr_val&&addr_val<start+slen*4) {
3261     SysPrintf("write to %08x hits block %08x, pc=%08x\n",addr_val,start,start+i*4);
3262     assert(i_regs->regmap==regs[i].regmap); // not delay slot
3263     if(i_regs->regmap==regs[i].regmap) {
3264       load_all_consts(regs[i].regmap_entry,regs[i].wasdirty,i);
3265       wb_dirtys(regs[i].regmap_entry,regs[i].wasdirty);
3266       emit_movimm(start+i*4+4,0);
3267       emit_writeword(0,&pcaddr);
3268       emit_addimm(HOST_CCREG,2,HOST_CCREG);
3269       emit_far_call(ndrc_get_addr_ht);
3270       emit_jmpreg(0);
3271     }
3272   }
3273 }
3274
3275 static void storelr_assemble(int i, const struct regstat *i_regs, int ccadj_)
3276 {
3277   int s,tl;
3278   int temp;
3279   int offset;
3280   void *jaddr=0;
3281   void *case1, *case23, *case3;
3282   void *done0, *done1, *done2;
3283   int memtarget=0,c=0;
3284   int agr=AGEN1+(i&1);
3285   int offset_reg = -1;
3286   u_int reglist=get_host_reglist(i_regs->regmap);
3287   tl=get_reg(i_regs->regmap,dops[i].rs2);
3288   s=get_reg(i_regs->regmap,dops[i].rs1);
3289   temp=get_reg(i_regs->regmap,agr);
3290   if(temp<0) temp=get_reg_temp(i_regs->regmap);
3291   offset=imm[i];
3292   if(s>=0) {
3293     c=(i_regs->isconst>>s)&1;
3294     if(c) {
3295       memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE;
3296     }
3297   }
3298   assert(tl>=0);
3299   assert(temp>=0);
3300   if(!c) {
3301     emit_cmpimm(s<0||offset?temp:s,RAM_SIZE);
3302     if(!offset&&s!=temp) emit_mov(s,temp);
3303     jaddr=out;
3304     emit_jno(0);
3305   }
3306   else
3307   {
3308     if(!memtarget||!dops[i].rs1) {
3309       jaddr=out;
3310       emit_jmp(0);
3311     }
3312   }
3313   if (ram_offset)
3314     offset_reg = get_ro_reg(i_regs, 0);
3315
3316   if (dops[i].opcode==0x2C||dops[i].opcode==0x2D) { // SDL/SDR
3317     assert(0);
3318   }
3319
3320   emit_testimm(temp,2);
3321   case23=out;
3322   emit_jne(0);
3323   emit_testimm(temp,1);
3324   case1=out;
3325   emit_jne(0);
3326   // 0
3327   if (dops[i].opcode == 0x2A) { // SWL
3328     // Write msb into least significant byte
3329     if (dops[i].rs2) emit_rorimm(tl, 24, tl);
3330     do_store_byte(temp, tl, offset_reg);
3331     if (dops[i].rs2) emit_rorimm(tl, 8, tl);
3332   }
3333   else if (dops[i].opcode == 0x2E) { // SWR
3334     // Write entire word
3335     do_store_word(temp, 0, tl, offset_reg, 1);
3336   }
3337   done0 = out;
3338   emit_jmp(0);
3339   // 1
3340   set_jump_target(case1, out);
3341   if (dops[i].opcode == 0x2A) { // SWL
3342     // Write two msb into two least significant bytes
3343     if (dops[i].rs2) emit_rorimm(tl, 16, tl);
3344     do_store_hword(temp, -1, tl, offset_reg, 0);
3345     if (dops[i].rs2) emit_rorimm(tl, 16, tl);
3346   }
3347   else if (dops[i].opcode == 0x2E) { // SWR
3348     // Write 3 lsb into three most significant bytes
3349     do_store_byte(temp, tl, offset_reg);
3350     if (dops[i].rs2) emit_rorimm(tl, 8, tl);
3351     do_store_hword(temp, 1, tl, offset_reg, 0);
3352     if (dops[i].rs2) emit_rorimm(tl, 24, tl);
3353   }
3354   done1=out;
3355   emit_jmp(0);
3356   // 2,3
3357   set_jump_target(case23, out);
3358   emit_testimm(temp,1);
3359   case3 = out;
3360   emit_jne(0);
3361   // 2
3362   if (dops[i].opcode==0x2A) { // SWL
3363     // Write 3 msb into three least significant bytes
3364     if (dops[i].rs2) emit_rorimm(tl, 8, tl);
3365     do_store_hword(temp, -2, tl, offset_reg, 1);
3366     if (dops[i].rs2) emit_rorimm(tl, 16, tl);
3367     do_store_byte(temp, tl, offset_reg);
3368     if (dops[i].rs2) emit_rorimm(tl, 8, tl);
3369   }
3370   else if (dops[i].opcode == 0x2E) { // SWR
3371     // Write two lsb into two most significant bytes
3372     do_store_hword(temp, 0, tl, offset_reg, 1);
3373   }
3374   done2 = out;
3375   emit_jmp(0);
3376   // 3
3377   set_jump_target(case3, out);
3378   if (dops[i].opcode == 0x2A) { // SWL
3379     do_store_word(temp, -3, tl, offset_reg, 0);
3380   }
3381   else if (dops[i].opcode == 0x2E) { // SWR
3382     do_store_byte(temp, tl, offset_reg);
3383   }
3384   set_jump_target(done0, out);
3385   set_jump_target(done1, out);
3386   set_jump_target(done2, out);
3387   if (offset_reg == HOST_TEMPREG)
3388     host_tempreg_release();
3389   if(!c||!memtarget)
3390     add_stub_r(STORELR_STUB,jaddr,out,i,temp,i_regs,ccadj_,reglist);
3391   if(!(i_regs->waswritten&(1<<dops[i].rs1)) && !HACK_ENABLED(NDHACK_NO_SMC_CHECK)) {
3392     #if defined(HOST_IMM8)
3393     int ir=get_reg(i_regs->regmap,INVCP);
3394     assert(ir>=0);
3395     emit_cmpmem_indexedsr12_reg(ir,temp,1);
3396     #else
3397     emit_cmpmem_indexedsr12_imm(invalid_code,temp,1);
3398     #endif
3399     #ifdef INVALIDATE_USE_COND_CALL
3400     emit_callne(invalidate_addr_reg[temp]);
3401     #else
3402     void *jaddr2 = out;
3403     emit_jne(0);
3404     add_stub(INVCODE_STUB,jaddr2,out,reglist|(1<<HOST_CCREG),temp,0,0,0);
3405     #endif
3406   }
3407 }
3408
3409 static void cop0_assemble(int i, const struct regstat *i_regs, int ccadj_)
3410 {
3411   if(dops[i].opcode2==0) // MFC0
3412   {
3413     signed char t=get_reg(i_regs->regmap,dops[i].rt1);
3414     u_int copr=(source[i]>>11)&0x1f;
3415     //assert(t>=0); // Why does this happen?  OOT is weird
3416     if(t>=0&&dops[i].rt1!=0) {
3417       emit_readword(&reg_cop0[copr],t);
3418     }
3419   }
3420   else if(dops[i].opcode2==4) // MTC0
3421   {
3422     signed char s=get_reg(i_regs->regmap,dops[i].rs1);
3423     char copr=(source[i]>>11)&0x1f;
3424     assert(s>=0);
3425     wb_register(dops[i].rs1,i_regs->regmap,i_regs->dirty);
3426     if(copr==9||copr==11||copr==12||copr==13) {
3427       emit_readword(&last_count,HOST_TEMPREG);
3428       emit_loadreg(CCREG,HOST_CCREG); // TODO: do proper reg alloc
3429       emit_add(HOST_CCREG,HOST_TEMPREG,HOST_CCREG);
3430       emit_addimm(HOST_CCREG,ccadj_,HOST_CCREG);
3431       emit_writeword(HOST_CCREG,&Count);
3432     }
3433     // What a mess.  The status register (12) can enable interrupts,
3434     // so needs a special case to handle a pending interrupt.
3435     // The interrupt must be taken immediately, because a subsequent
3436     // instruction might disable interrupts again.
3437     if(copr==12||copr==13) {
3438       if (is_delayslot) {
3439         // burn cycles to cause cc_interrupt, which will
3440         // reschedule next_interupt. Relies on CCREG from above.
3441         assem_debug("MTC0 DS %d\n", copr);
3442         emit_writeword(HOST_CCREG,&last_count);
3443         emit_movimm(0,HOST_CCREG);
3444         emit_storereg(CCREG,HOST_CCREG);
3445         emit_loadreg(dops[i].rs1,1);
3446         emit_movimm(copr,0);
3447         emit_far_call(pcsx_mtc0_ds);
3448         emit_loadreg(dops[i].rs1,s);
3449         return;
3450       }
3451       emit_movimm(start+i*4+4,HOST_TEMPREG);
3452       emit_writeword(HOST_TEMPREG,&pcaddr);
3453       emit_movimm(0,HOST_TEMPREG);
3454       emit_writeword(HOST_TEMPREG,&pending_exception);
3455     }
3456     if(s==HOST_CCREG)
3457       emit_loadreg(dops[i].rs1,1);
3458     else if(s!=1)
3459       emit_mov(s,1);
3460     emit_movimm(copr,0);
3461     emit_far_call(pcsx_mtc0);
3462     if(copr==9||copr==11||copr==12||copr==13) {
3463       emit_readword(&Count,HOST_CCREG);
3464       emit_readword(&next_interupt,HOST_TEMPREG);
3465       emit_addimm(HOST_CCREG,-ccadj_,HOST_CCREG);
3466       emit_sub(HOST_CCREG,HOST_TEMPREG,HOST_CCREG);
3467       emit_writeword(HOST_TEMPREG,&last_count);
3468       emit_storereg(CCREG,HOST_CCREG);
3469     }
3470     if(copr==12||copr==13) {
3471       assert(!is_delayslot);
3472       emit_readword(&pending_exception,14);
3473       emit_test(14,14);
3474       void *jaddr = out;
3475       emit_jeq(0);
3476       emit_readword(&pcaddr, 0);
3477       emit_addimm(HOST_CCREG,2,HOST_CCREG);
3478       emit_far_call(ndrc_get_addr_ht);
3479       emit_jmpreg(0);
3480       set_jump_target(jaddr, out);
3481     }
3482     emit_loadreg(dops[i].rs1,s);
3483   }
3484   else
3485   {
3486     assert(dops[i].opcode2==0x10);
3487     //if((source[i]&0x3f)==0x10) // RFE
3488     {
3489       emit_readword(&Status,0);
3490       emit_andimm(0,0x3c,1);
3491       emit_andimm(0,~0xf,0);
3492       emit_orrshr_imm(1,2,0);
3493       emit_writeword(0,&Status);
3494     }
3495   }
3496 }
3497
3498 static void cop1_unusable(int i, const struct regstat *i_regs)
3499 {
3500   // XXX: should just just do the exception instead
3501   //if(!cop1_usable)
3502   {
3503     void *jaddr=out;
3504     emit_jmp(0);
3505     add_stub_r(FP_STUB,jaddr,out,i,0,i_regs,is_delayslot,0);
3506   }
3507 }
3508
3509 static void cop1_assemble(int i, const struct regstat *i_regs)
3510 {
3511   cop1_unusable(i, i_regs);
3512 }
3513
3514 static void c1ls_assemble(int i, const struct regstat *i_regs)
3515 {
3516   cop1_unusable(i, i_regs);
3517 }
3518
3519 // FP_STUB
3520 static void do_cop1stub(int n)
3521 {
3522   literal_pool(256);
3523   assem_debug("do_cop1stub %x\n",start+stubs[n].a*4);
3524   set_jump_target(stubs[n].addr, out);
3525   int i=stubs[n].a;
3526 //  int rs=stubs[n].b;
3527   struct regstat *i_regs=(struct regstat *)stubs[n].c;
3528   int ds=stubs[n].d;
3529   if(!ds) {
3530     load_all_consts(regs[i].regmap_entry,regs[i].wasdirty,i);
3531     //if(i_regs!=&regs[i]) printf("oops: regs[i]=%x i_regs=%x",(int)&regs[i],(int)i_regs);
3532   }
3533   //else {printf("fp exception in delay slot\n");}
3534   wb_dirtys(i_regs->regmap_entry,i_regs->wasdirty);
3535   if(regs[i].regmap_entry[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
3536   emit_movimm(start+(i-ds)*4,EAX); // Get PC
3537   emit_addimm(HOST_CCREG,ccadj[i],HOST_CCREG); // CHECK: is this right?  There should probably be an extra cycle...
3538   emit_far_jump(ds?fp_exception_ds:fp_exception);
3539 }
3540
3541 static int cop2_is_stalling_op(int i, int *cycles)
3542 {
3543   if (dops[i].opcode == 0x3a) { // SWC2
3544     *cycles = 0;
3545     return 1;
3546   }
3547   if (dops[i].itype == COP2 && (dops[i].opcode2 == 0 || dops[i].opcode2 == 2)) { // MFC2/CFC2
3548     *cycles = 0;
3549     return 1;
3550   }
3551   if (dops[i].itype == C2OP) {
3552     *cycles = gte_cycletab[source[i] & 0x3f];
3553     return 1;
3554   }
3555   // ... what about MTC2/CTC2/LWC2?
3556   return 0;
3557 }
3558
3559 #if 0
3560 static void log_gte_stall(int stall, u_int cycle)
3561 {
3562   if ((u_int)stall <= 44)
3563     printf("x    stall %2d %u\n", stall, cycle + last_count);
3564 }
3565
3566 static void emit_log_gte_stall(int i, int stall, u_int reglist)
3567 {
3568   save_regs(reglist);
3569   if (stall > 0)
3570     emit_movimm(stall, 0);
3571   else
3572     emit_mov(HOST_TEMPREG, 0);
3573   emit_addimm(HOST_CCREG, ccadj[i], 1);
3574   emit_far_call(log_gte_stall);
3575   restore_regs(reglist);
3576 }
3577 #endif
3578
3579 static void cop2_do_stall_check(u_int op, int i, const struct regstat *i_regs, u_int reglist)
3580 {
3581   int j = i, other_gte_op_cycles = -1, stall = -MAXBLOCK, cycles_passed;
3582   int rtmp = reglist_find_free(reglist);
3583
3584   if (HACK_ENABLED(NDHACK_NO_STALLS))
3585     return;
3586   if (get_reg(i_regs->regmap, CCREG) != HOST_CCREG) {
3587     // happens occasionally... cc evicted? Don't bother then
3588     //printf("no cc %08x\n", start + i*4);
3589     return;
3590   }
3591   if (!dops[i].bt) {
3592     for (j = i - 1; j >= 0; j--) {
3593       //if (dops[j].is_ds) break;
3594       if (cop2_is_stalling_op(j, &other_gte_op_cycles) || dops[j].bt)
3595         break;
3596       if (j > 0 && ccadj[j - 1] > ccadj[j])
3597         break;
3598     }
3599     j = max(j, 0);
3600   }
3601   cycles_passed = ccadj[i] - ccadj[j];
3602   if (other_gte_op_cycles >= 0)
3603     stall = other_gte_op_cycles - cycles_passed;
3604   else if (cycles_passed >= 44)
3605     stall = 0; // can't stall
3606   if (stall == -MAXBLOCK && rtmp >= 0) {
3607     // unknown stall, do the expensive runtime check
3608     assem_debug("; cop2_do_stall_check\n");
3609 #if 0 // too slow
3610     save_regs(reglist);
3611     emit_movimm(gte_cycletab[op], 0);
3612     emit_addimm(HOST_CCREG, ccadj[i], 1);
3613     emit_far_call(call_gteStall);
3614     restore_regs(reglist);
3615 #else
3616     host_tempreg_acquire();
3617     emit_readword(&psxRegs.gteBusyCycle, rtmp);
3618     emit_addimm(rtmp, -ccadj[i], rtmp);
3619     emit_sub(rtmp, HOST_CCREG, HOST_TEMPREG);
3620     emit_cmpimm(HOST_TEMPREG, 44);
3621     emit_cmovb_reg(rtmp, HOST_CCREG);
3622     //emit_log_gte_stall(i, 0, reglist);
3623     host_tempreg_release();
3624 #endif
3625   }
3626   else if (stall > 0) {
3627     //emit_log_gte_stall(i, stall, reglist);
3628     emit_addimm(HOST_CCREG, stall, HOST_CCREG);
3629   }
3630
3631   // save gteBusyCycle, if needed
3632   if (gte_cycletab[op] == 0)
3633     return;
3634   other_gte_op_cycles = -1;
3635   for (j = i + 1; j < slen; j++) {
3636     if (cop2_is_stalling_op(j, &other_gte_op_cycles))
3637       break;
3638     if (dops[j].is_jump) {
3639       // check ds
3640       if (j + 1 < slen && cop2_is_stalling_op(j + 1, &other_gte_op_cycles))
3641         j++;
3642       break;
3643     }
3644   }
3645   if (other_gte_op_cycles >= 0)
3646     // will handle stall when assembling that op
3647     return;
3648   cycles_passed = ccadj[min(j, slen -1)] - ccadj[i];
3649   if (cycles_passed >= 44)
3650     return;
3651   assem_debug("; save gteBusyCycle\n");
3652   host_tempreg_acquire();
3653 #if 0
3654   emit_readword(&last_count, HOST_TEMPREG);
3655   emit_add(HOST_TEMPREG, HOST_CCREG, HOST_TEMPREG);
3656   emit_addimm(HOST_TEMPREG, ccadj[i], HOST_TEMPREG);
3657   emit_addimm(HOST_TEMPREG, gte_cycletab[op]), HOST_TEMPREG);
3658   emit_writeword(HOST_TEMPREG, &psxRegs.gteBusyCycle);
3659 #else
3660   emit_addimm(HOST_CCREG, ccadj[i] + gte_cycletab[op], HOST_TEMPREG);
3661   emit_writeword(HOST_TEMPREG, &psxRegs.gteBusyCycle);
3662 #endif
3663   host_tempreg_release();
3664 }
3665
3666 static int is_mflohi(int i)
3667 {
3668   return (dops[i].itype == MOV && (dops[i].rs1 == HIREG || dops[i].rs1 == LOREG));
3669 }
3670
3671 static int check_multdiv(int i, int *cycles)
3672 {
3673   if (dops[i].itype != MULTDIV)
3674     return 0;
3675   if (dops[i].opcode2 == 0x18 || dops[i].opcode2 == 0x19) // MULT(U)
3676     *cycles = 11; // approx from 7 11 14
3677   else
3678     *cycles = 37;
3679   return 1;
3680 }
3681
3682 static void multdiv_prepare_stall(int i, const struct regstat *i_regs, int ccadj_)
3683 {
3684   int j, found = 0, c = 0;
3685   if (HACK_ENABLED(NDHACK_NO_STALLS))
3686     return;
3687   if (get_reg(i_regs->regmap, CCREG) != HOST_CCREG) {
3688     // happens occasionally... cc evicted? Don't bother then
3689     return;
3690   }
3691   for (j = i + 1; j < slen; j++) {
3692     if (dops[j].bt)
3693       break;
3694     if ((found = is_mflohi(j)))
3695       break;
3696     if (dops[j].is_jump) {
3697       // check ds
3698       if (j + 1 < slen && (found = is_mflohi(j + 1)))
3699         j++;
3700       break;
3701     }
3702   }
3703   if (found)
3704     // handle all in multdiv_do_stall()
3705     return;
3706   check_multdiv(i, &c);
3707   assert(c > 0);
3708   assem_debug("; muldiv prepare stall %d\n", c);
3709   host_tempreg_acquire();
3710   emit_addimm(HOST_CCREG, ccadj_ + c, HOST_TEMPREG);
3711   emit_writeword(HOST_TEMPREG, &psxRegs.muldivBusyCycle);
3712   host_tempreg_release();
3713 }
3714
3715 static void multdiv_do_stall(int i, const struct regstat *i_regs)
3716 {
3717   int j, known_cycles = 0;
3718   u_int reglist = get_host_reglist(i_regs->regmap);
3719   int rtmp = get_reg_temp(i_regs->regmap);
3720   if (rtmp < 0)
3721     rtmp = reglist_find_free(reglist);
3722   if (HACK_ENABLED(NDHACK_NO_STALLS))
3723     return;
3724   if (get_reg(i_regs->regmap, CCREG) != HOST_CCREG || rtmp < 0) {
3725     // happens occasionally... cc evicted? Don't bother then
3726     //printf("no cc/rtmp %08x\n", start + i*4);
3727     return;
3728   }
3729   if (!dops[i].bt) {
3730     for (j = i - 1; j >= 0; j--) {
3731       if (dops[j].is_ds) break;
3732       if (check_multdiv(j, &known_cycles))
3733         break;
3734       if (is_mflohi(j))
3735         // already handled by this op
3736         return;
3737       if (dops[j].bt || (j > 0 && ccadj[j - 1] > ccadj[j]))
3738         break;
3739     }
3740     j = max(j, 0);
3741   }
3742   if (known_cycles > 0) {
3743     known_cycles -= ccadj[i] - ccadj[j];
3744     assem_debug("; muldiv stall resolved %d\n", known_cycles);
3745     if (known_cycles > 0)
3746       emit_addimm(HOST_CCREG, known_cycles, HOST_CCREG);
3747     return;
3748   }
3749   assem_debug("; muldiv stall unresolved\n");
3750   host_tempreg_acquire();
3751   emit_readword(&psxRegs.muldivBusyCycle, rtmp);
3752   emit_addimm(rtmp, -ccadj[i], rtmp);
3753   emit_sub(rtmp, HOST_CCREG, HOST_TEMPREG);
3754   emit_cmpimm(HOST_TEMPREG, 37);
3755   emit_cmovb_reg(rtmp, HOST_CCREG);
3756   //emit_log_gte_stall(i, 0, reglist);
3757   host_tempreg_release();
3758 }
3759
3760 static void cop2_get_dreg(u_int copr,signed char tl,signed char temp)
3761 {
3762   switch (copr) {
3763     case 1:
3764     case 3:
3765     case 5:
3766     case 8:
3767     case 9:
3768     case 10:
3769     case 11:
3770       emit_readword(&reg_cop2d[copr],tl);
3771       emit_signextend16(tl,tl);
3772       emit_writeword(tl,&reg_cop2d[copr]); // hmh
3773       break;
3774     case 7:
3775     case 16:
3776     case 17:
3777     case 18:
3778     case 19:
3779       emit_readword(&reg_cop2d[copr],tl);
3780       emit_andimm(tl,0xffff,tl);
3781       emit_writeword(tl,&reg_cop2d[copr]);
3782       break;
3783     case 15:
3784       emit_readword(&reg_cop2d[14],tl); // SXY2
3785       emit_writeword(tl,&reg_cop2d[copr]);
3786       break;
3787     case 28:
3788     case 29:
3789       c2op_mfc2_29_assemble(tl,temp);
3790       break;
3791     default:
3792       emit_readword(&reg_cop2d[copr],tl);
3793       break;
3794   }
3795 }
3796
3797 static void cop2_put_dreg(u_int copr,signed char sl,signed char temp)
3798 {
3799   switch (copr) {
3800     case 15:
3801       emit_readword(&reg_cop2d[13],temp);  // SXY1
3802       emit_writeword(sl,&reg_cop2d[copr]);
3803       emit_writeword(temp,&reg_cop2d[12]); // SXY0
3804       emit_readword(&reg_cop2d[14],temp);  // SXY2
3805       emit_writeword(sl,&reg_cop2d[14]);
3806       emit_writeword(temp,&reg_cop2d[13]); // SXY1
3807       break;
3808     case 28:
3809       emit_andimm(sl,0x001f,temp);
3810       emit_shlimm(temp,7,temp);
3811       emit_writeword(temp,&reg_cop2d[9]);
3812       emit_andimm(sl,0x03e0,temp);
3813       emit_shlimm(temp,2,temp);
3814       emit_writeword(temp,&reg_cop2d[10]);
3815       emit_andimm(sl,0x7c00,temp);
3816       emit_shrimm(temp,3,temp);
3817       emit_writeword(temp,&reg_cop2d[11]);
3818       emit_writeword(sl,&reg_cop2d[28]);
3819       break;
3820     case 30:
3821       emit_xorsar_imm(sl,sl,31,temp);
3822 #if defined(HAVE_ARMV5) || defined(__aarch64__)
3823       emit_clz(temp,temp);
3824 #else
3825       emit_movs(temp,HOST_TEMPREG);
3826       emit_movimm(0,temp);
3827       emit_jeq((int)out+4*4);
3828       emit_addpl_imm(temp,1,temp);
3829       emit_lslpls_imm(HOST_TEMPREG,1,HOST_TEMPREG);
3830       emit_jns((int)out-2*4);
3831 #endif
3832       emit_writeword(sl,&reg_cop2d[30]);
3833       emit_writeword(temp,&reg_cop2d[31]);
3834       break;
3835     case 31:
3836       break;
3837     default:
3838       emit_writeword(sl,&reg_cop2d[copr]);
3839       break;
3840   }
3841 }
3842
3843 static void c2ls_assemble(int i, const struct regstat *i_regs, int ccadj_)
3844 {
3845   int s,tl;
3846   int ar;
3847   int offset;
3848   int memtarget=0,c=0;
3849   void *jaddr2=NULL;
3850   enum stub_type type;
3851   int agr=AGEN1+(i&1);
3852   int offset_reg = -1;
3853   int fastio_reg_override = -1;
3854   u_int reglist=get_host_reglist(i_regs->regmap);
3855   u_int copr=(source[i]>>16)&0x1f;
3856   s=get_reg(i_regs->regmap,dops[i].rs1);
3857   tl=get_reg(i_regs->regmap,FTEMP);
3858   offset=imm[i];
3859   assert(dops[i].rs1>0);
3860   assert(tl>=0);
3861
3862   if(i_regs->regmap[HOST_CCREG]==CCREG)
3863     reglist&=~(1<<HOST_CCREG);
3864
3865   // get the address
3866   if (dops[i].opcode==0x3a) { // SWC2
3867     ar=get_reg(i_regs->regmap,agr);
3868     if(ar<0) ar=get_reg_temp(i_regs->regmap);
3869     reglist|=1<<ar;
3870   } else { // LWC2
3871     ar=tl;
3872   }
3873   if(s>=0) c=(i_regs->wasconst>>s)&1;
3874   memtarget=c&&(((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE);
3875   if (!offset&&!c&&s>=0) ar=s;
3876   assert(ar>=0);
3877
3878   cop2_do_stall_check(0, i, i_regs, reglist);
3879
3880   if (dops[i].opcode==0x3a) { // SWC2
3881     cop2_get_dreg(copr,tl,-1);
3882     type=STOREW_STUB;
3883   }
3884   else
3885     type=LOADW_STUB;
3886
3887   if(c&&!memtarget) {
3888     jaddr2=out;
3889     emit_jmp(0); // inline_readstub/inline_writestub?
3890   }
3891   else {
3892     if(!c) {
3893       jaddr2 = emit_fastpath_cmp_jump(i, i_regs, ar,
3894                 &offset_reg, &fastio_reg_override);
3895     }
3896     else if (ram_offset && memtarget) {
3897       offset_reg = get_ro_reg(i_regs, 0);
3898     }
3899     switch (dops[i].opcode) {
3900     case 0x32: { // LWC2
3901       int a = ar;
3902       if (fastio_reg_override >= 0)
3903         a = fastio_reg_override;
3904       do_load_word(a, tl, offset_reg);
3905       break;
3906     }
3907     case 0x3a: { // SWC2
3908       #ifdef DESTRUCTIVE_SHIFT
3909       if(!offset&&!c&&s>=0) emit_mov(s,ar);
3910       #endif
3911       int a = ar;
3912       if (fastio_reg_override >= 0)
3913         a = fastio_reg_override;
3914       do_store_word(a, 0, tl, offset_reg, 1);
3915       break;
3916     }
3917     default:
3918       assert(0);
3919     }
3920   }
3921   if (fastio_reg_override == HOST_TEMPREG || offset_reg == HOST_TEMPREG)
3922     host_tempreg_release();
3923   if(jaddr2)
3924     add_stub_r(type,jaddr2,out,i,ar,i_regs,ccadj_,reglist);
3925   if(dops[i].opcode==0x3a) // SWC2
3926   if(!(i_regs->waswritten&(1<<dops[i].rs1)) && !HACK_ENABLED(NDHACK_NO_SMC_CHECK)) {
3927 #if defined(HOST_IMM8)
3928     int ir=get_reg(i_regs->regmap,INVCP);
3929     assert(ir>=0);
3930     emit_cmpmem_indexedsr12_reg(ir,ar,1);
3931 #else
3932     emit_cmpmem_indexedsr12_imm(invalid_code,ar,1);
3933 #endif
3934     #ifdef INVALIDATE_USE_COND_CALL
3935     emit_callne(invalidate_addr_reg[ar]);
3936     #else
3937     void *jaddr3 = out;
3938     emit_jne(0);
3939     add_stub(INVCODE_STUB,jaddr3,out,reglist|(1<<HOST_CCREG),ar,0,0,0);
3940     #endif
3941   }
3942   if (dops[i].opcode==0x32) { // LWC2
3943     host_tempreg_acquire();
3944     cop2_put_dreg(copr,tl,HOST_TEMPREG);
3945     host_tempreg_release();
3946   }
3947 }
3948
3949 static void cop2_assemble(int i, const struct regstat *i_regs)
3950 {
3951   u_int copr = (source[i]>>11) & 0x1f;
3952   signed char temp = get_reg_temp(i_regs->regmap);
3953
3954   if (!HACK_ENABLED(NDHACK_NO_STALLS)) {
3955     u_int reglist = reglist_exclude(get_host_reglist(i_regs->regmap), temp, -1);
3956     if (dops[i].opcode2 == 0 || dops[i].opcode2 == 2) { // MFC2/CFC2
3957       signed char tl = get_reg(i_regs->regmap, dops[i].rt1);
3958       reglist = reglist_exclude(reglist, tl, -1);
3959     }
3960     cop2_do_stall_check(0, i, i_regs, reglist);
3961   }
3962   if (dops[i].opcode2==0) { // MFC2
3963     signed char tl=get_reg(i_regs->regmap,dops[i].rt1);
3964     if(tl>=0&&dops[i].rt1!=0)
3965       cop2_get_dreg(copr,tl,temp);
3966   }
3967   else if (dops[i].opcode2==4) { // MTC2
3968     signed char sl=get_reg(i_regs->regmap,dops[i].rs1);
3969     cop2_put_dreg(copr,sl,temp);
3970   }
3971   else if (dops[i].opcode2==2) // CFC2
3972   {
3973     signed char tl=get_reg(i_regs->regmap,dops[i].rt1);
3974     if(tl>=0&&dops[i].rt1!=0)
3975       emit_readword(&reg_cop2c[copr],tl);
3976   }
3977   else if (dops[i].opcode2==6) // CTC2
3978   {
3979     signed char sl=get_reg(i_regs->regmap,dops[i].rs1);
3980     switch(copr) {
3981       case 4:
3982       case 12:
3983       case 20:
3984       case 26:
3985       case 27:
3986       case 29:
3987       case 30:
3988         emit_signextend16(sl,temp);
3989         break;
3990       case 31:
3991         c2op_ctc2_31_assemble(sl,temp);
3992         break;
3993       default:
3994         temp=sl;
3995         break;
3996     }
3997     emit_writeword(temp,&reg_cop2c[copr]);
3998     assert(sl>=0);
3999   }
4000 }
4001
4002 static void do_unalignedwritestub(int n)
4003 {
4004   assem_debug("do_unalignedwritestub %x\n",start+stubs[n].a*4);
4005   literal_pool(256);
4006   set_jump_target(stubs[n].addr, out);
4007
4008   int i=stubs[n].a;
4009   struct regstat *i_regs=(struct regstat *)stubs[n].c;
4010   int addr=stubs[n].b;
4011   u_int reglist=stubs[n].e;
4012   signed char *i_regmap=i_regs->regmap;
4013   int temp2=get_reg(i_regmap,FTEMP);
4014   int rt;
4015   rt=get_reg(i_regmap,dops[i].rs2);
4016   assert(rt>=0);
4017   assert(addr>=0);
4018   assert(dops[i].opcode==0x2a||dops[i].opcode==0x2e); // SWL/SWR only implemented
4019   reglist|=(1<<addr);
4020   reglist&=~(1<<temp2);
4021
4022   // don't bother with it and call write handler
4023   save_regs(reglist);
4024   pass_args(addr,rt);
4025   int cc=get_reg(i_regmap,CCREG);
4026   if(cc<0)
4027     emit_loadreg(CCREG,2);
4028   emit_addimm(cc<0?2:cc,(int)stubs[n].d+1,2);
4029   emit_far_call((dops[i].opcode==0x2a?jump_handle_swl:jump_handle_swr));
4030   emit_addimm(0,-((int)stubs[n].d+1),cc<0?2:cc);
4031   if(cc<0)
4032     emit_storereg(CCREG,2);
4033   restore_regs(reglist);
4034   emit_jmp(stubs[n].retaddr); // return address
4035 }
4036
4037 #ifndef multdiv_assemble
4038 void multdiv_assemble(int i,struct regstat *i_regs)
4039 {
4040   printf("Need multdiv_assemble for this architecture.\n");
4041   abort();
4042 }
4043 #endif
4044
4045 static void mov_assemble(int i, const struct regstat *i_regs)
4046 {
4047   //if(dops[i].opcode2==0x10||dops[i].opcode2==0x12) { // MFHI/MFLO
4048   //if(dops[i].opcode2==0x11||dops[i].opcode2==0x13) { // MTHI/MTLO
4049   if(dops[i].rt1) {
4050     signed char sl,tl;
4051     tl=get_reg(i_regs->regmap,dops[i].rt1);
4052     //assert(tl>=0);
4053     if(tl>=0) {
4054       sl=get_reg(i_regs->regmap,dops[i].rs1);
4055       if(sl>=0) emit_mov(sl,tl);
4056       else emit_loadreg(dops[i].rs1,tl);
4057     }
4058   }
4059   if (dops[i].rs1 == HIREG || dops[i].rs1 == LOREG) // MFHI/MFLO
4060     multdiv_do_stall(i, i_regs);
4061 }
4062
4063 // call interpreter, exception handler, things that change pc/regs/cycles ...
4064 static void call_c_cpu_handler(int i, const struct regstat *i_regs, int ccadj_, u_int pc, void *func)
4065 {
4066   signed char ccreg=get_reg(i_regs->regmap,CCREG);
4067   assert(ccreg==HOST_CCREG);
4068   assert(!is_delayslot);
4069   (void)ccreg;
4070
4071   emit_movimm(pc,3); // Get PC
4072   emit_readword(&last_count,2);
4073   emit_writeword(3,&psxRegs.pc);
4074   emit_addimm(HOST_CCREG,ccadj_,HOST_CCREG);
4075   emit_add(2,HOST_CCREG,2);
4076   emit_writeword(2,&psxRegs.cycle);
4077   emit_far_call(func);
4078   emit_far_jump(jump_to_new_pc);
4079 }
4080
4081 static void syscall_assemble(int i, const struct regstat *i_regs, int ccadj_)
4082 {
4083   // 'break' tends to be littered around to catch things like
4084   // division by 0 and is almost never executed, so don't emit much code here
4085   void *func = (dops[i].opcode2 == 0x0C)
4086     ? (is_delayslot ? jump_syscall_ds : jump_syscall)
4087     : (is_delayslot ? jump_break_ds : jump_break);
4088   assert(get_reg(i_regs->regmap, CCREG) == HOST_CCREG);
4089   emit_movimm(start + i*4, 2); // pc
4090   emit_addimm(HOST_CCREG, ccadj_ + CLOCK_ADJUST(1), HOST_CCREG);
4091   emit_far_jump(func);
4092 }
4093
4094 static void hlecall_assemble(int i, const struct regstat *i_regs, int ccadj_)
4095 {
4096   void *hlefunc = psxNULL;
4097   uint32_t hleCode = source[i] & 0x03ffffff;
4098   if (hleCode < ARRAY_SIZE(psxHLEt))
4099     hlefunc = psxHLEt[hleCode];
4100
4101   call_c_cpu_handler(i, i_regs, ccadj_, start + i*4+4, hlefunc);
4102 }
4103
4104 static void intcall_assemble(int i, const struct regstat *i_regs, int ccadj_)
4105 {
4106   call_c_cpu_handler(i, i_regs, ccadj_, start + i*4, execI);
4107 }
4108
4109 static void speculate_mov(int rs,int rt)
4110 {
4111   if(rt!=0) {
4112     smrv_strong_next|=1<<rt;
4113     smrv[rt]=smrv[rs];
4114   }
4115 }
4116
4117 static void speculate_mov_weak(int rs,int rt)
4118 {
4119   if(rt!=0) {
4120     smrv_weak_next|=1<<rt;
4121     smrv[rt]=smrv[rs];
4122   }
4123 }
4124
4125 static void speculate_register_values(int i)
4126 {
4127   if(i==0) {
4128     memcpy(smrv,psxRegs.GPR.r,sizeof(smrv));
4129     // gp,sp are likely to stay the same throughout the block
4130     smrv_strong_next=(1<<28)|(1<<29)|(1<<30);
4131     smrv_weak_next=~smrv_strong_next;
4132     //printf(" llr %08x\n", smrv[4]);
4133   }
4134   smrv_strong=smrv_strong_next;
4135   smrv_weak=smrv_weak_next;
4136   switch(dops[i].itype) {
4137     case ALU:
4138       if     ((smrv_strong>>dops[i].rs1)&1) speculate_mov(dops[i].rs1,dops[i].rt1);
4139       else if((smrv_strong>>dops[i].rs2)&1) speculate_mov(dops[i].rs2,dops[i].rt1);
4140       else if((smrv_weak>>dops[i].rs1)&1) speculate_mov_weak(dops[i].rs1,dops[i].rt1);
4141       else if((smrv_weak>>dops[i].rs2)&1) speculate_mov_weak(dops[i].rs2,dops[i].rt1);
4142       else {
4143         smrv_strong_next&=~(1<<dops[i].rt1);
4144         smrv_weak_next&=~(1<<dops[i].rt1);
4145       }
4146       break;
4147     case SHIFTIMM:
4148       smrv_strong_next&=~(1<<dops[i].rt1);
4149       smrv_weak_next&=~(1<<dops[i].rt1);
4150       // fallthrough
4151     case IMM16:
4152       if(dops[i].rt1&&is_const(&regs[i],dops[i].rt1)) {
4153         int value,hr=get_reg(regs[i].regmap,dops[i].rt1);
4154         if(hr>=0) {
4155           if(get_final_value(hr,i,&value))
4156                smrv[dops[i].rt1]=value;
4157           else smrv[dops[i].rt1]=constmap[i][hr];
4158           smrv_strong_next|=1<<dops[i].rt1;
4159         }
4160       }
4161       else {
4162         if     ((smrv_strong>>dops[i].rs1)&1) speculate_mov(dops[i].rs1,dops[i].rt1);
4163         else if((smrv_weak>>dops[i].rs1)&1) speculate_mov_weak(dops[i].rs1,dops[i].rt1);
4164       }
4165       break;
4166     case LOAD:
4167       if(start<0x2000&&(dops[i].rt1==26||(smrv[dops[i].rt1]>>24)==0xa0)) {
4168         // special case for BIOS
4169         smrv[dops[i].rt1]=0xa0000000;
4170         smrv_strong_next|=1<<dops[i].rt1;
4171         break;
4172       }
4173       // fallthrough
4174     case SHIFT:
4175     case LOADLR:
4176     case MOV:
4177       smrv_strong_next&=~(1<<dops[i].rt1);
4178       smrv_weak_next&=~(1<<dops[i].rt1);
4179       break;
4180     case COP0:
4181     case COP2:
4182       if(dops[i].opcode2==0||dops[i].opcode2==2) { // MFC/CFC
4183         smrv_strong_next&=~(1<<dops[i].rt1);
4184         smrv_weak_next&=~(1<<dops[i].rt1);
4185       }
4186       break;
4187     case C2LS:
4188       if (dops[i].opcode==0x32) { // LWC2
4189         smrv_strong_next&=~(1<<dops[i].rt1);
4190         smrv_weak_next&=~(1<<dops[i].rt1);
4191       }
4192       break;
4193   }
4194 #if 0
4195   int r=4;
4196   printf("x %08x %08x %d %d c %08x %08x\n",smrv[r],start+i*4,
4197     ((smrv_strong>>r)&1),(smrv_weak>>r)&1,regs[i].isconst,regs[i].wasconst);
4198 #endif
4199 }
4200
4201 static void ujump_assemble(int i, const struct regstat *i_regs);
4202 static void rjump_assemble(int i, const struct regstat *i_regs);
4203 static void cjump_assemble(int i, const struct regstat *i_regs);
4204 static void sjump_assemble(int i, const struct regstat *i_regs);
4205
4206 static int assemble(int i, const struct regstat *i_regs, int ccadj_)
4207 {
4208   int ds = 0;
4209   switch (dops[i].itype) {
4210     case ALU:
4211       alu_assemble(i, i_regs);
4212       break;
4213     case IMM16:
4214       imm16_assemble(i, i_regs);
4215       break;
4216     case SHIFT:
4217       shift_assemble(i, i_regs);
4218       break;
4219     case SHIFTIMM:
4220       shiftimm_assemble(i, i_regs);
4221       break;
4222     case LOAD:
4223       load_assemble(i, i_regs, ccadj_);
4224       break;
4225     case LOADLR:
4226       loadlr_assemble(i, i_regs, ccadj_);
4227       break;
4228     case STORE:
4229       store_assemble(i, i_regs, ccadj_);
4230       break;
4231     case STORELR:
4232       storelr_assemble(i, i_regs, ccadj_);
4233       break;
4234     case COP0:
4235       cop0_assemble(i, i_regs, ccadj_);
4236       break;
4237     case COP1:
4238       cop1_assemble(i, i_regs);
4239       break;
4240     case C1LS:
4241       c1ls_assemble(i, i_regs);
4242       break;
4243     case COP2:
4244       cop2_assemble(i, i_regs);
4245       break;
4246     case C2LS:
4247       c2ls_assemble(i, i_regs, ccadj_);
4248       break;
4249     case C2OP:
4250       c2op_assemble(i, i_regs);
4251       break;
4252     case MULTDIV:
4253       multdiv_assemble(i, i_regs);
4254       multdiv_prepare_stall(i, i_regs, ccadj_);
4255       break;
4256     case MOV:
4257       mov_assemble(i, i_regs);
4258       break;
4259     case SYSCALL:
4260       syscall_assemble(i, i_regs, ccadj_);
4261       break;
4262     case HLECALL:
4263       hlecall_assemble(i, i_regs, ccadj_);
4264       break;
4265     case INTCALL:
4266       intcall_assemble(i, i_regs, ccadj_);
4267       break;
4268     case UJUMP:
4269       ujump_assemble(i, i_regs);
4270       ds = 1;
4271       break;
4272     case RJUMP:
4273       rjump_assemble(i, i_regs);
4274       ds = 1;
4275       break;
4276     case CJUMP:
4277       cjump_assemble(i, i_regs);
4278       ds = 1;
4279       break;
4280     case SJUMP:
4281       sjump_assemble(i, i_regs);
4282       ds = 1;
4283       break;
4284     case NOP:
4285     case OTHER:
4286     case NI:
4287       // not handled, just skip
4288       break;
4289     default:
4290       assert(0);
4291   }
4292   return ds;
4293 }
4294
4295 static void ds_assemble(int i, const struct regstat *i_regs)
4296 {
4297   speculate_register_values(i);
4298   is_delayslot = 1;
4299   switch (dops[i].itype) {
4300     case SYSCALL:
4301     case HLECALL:
4302     case INTCALL:
4303     case UJUMP:
4304     case RJUMP:
4305     case CJUMP:
4306     case SJUMP:
4307       SysPrintf("Jump in the delay slot.  This is probably a bug.\n");
4308       break;
4309     default:
4310       assemble(i, i_regs, ccadj[i]);
4311   }
4312   is_delayslot = 0;
4313 }
4314
4315 // Is the branch target a valid internal jump?
4316 static int internal_branch(int addr)
4317 {
4318   if(addr&1) return 0; // Indirect (register) jump
4319   if(addr>=start && addr<start+slen*4-4)
4320   {
4321     return 1;
4322   }
4323   return 0;
4324 }
4325
4326 static void wb_invalidate(signed char pre[],signed char entry[],uint64_t dirty,uint64_t u)
4327 {
4328   int hr;
4329   for(hr=0;hr<HOST_REGS;hr++) {
4330     if(hr!=EXCLUDE_REG) {
4331       if(pre[hr]!=entry[hr]) {
4332         if(pre[hr]>=0) {
4333           if((dirty>>hr)&1) {
4334             if(get_reg(entry,pre[hr])<0) {
4335               assert(pre[hr]<64);
4336               if(!((u>>pre[hr])&1))
4337                 emit_storereg(pre[hr],hr);
4338             }
4339           }
4340         }
4341       }
4342     }
4343   }
4344   // Move from one register to another (no writeback)
4345   for(hr=0;hr<HOST_REGS;hr++) {
4346     if(hr!=EXCLUDE_REG) {
4347       if(pre[hr]!=entry[hr]) {
4348         if(pre[hr]>=0&&pre[hr]<TEMPREG) {
4349           int nr;
4350           if((nr=get_reg(entry,pre[hr]))>=0) {
4351             emit_mov(hr,nr);
4352           }
4353         }
4354       }
4355     }
4356   }
4357 }
4358
4359 // Load the specified registers
4360 // This only loads the registers given as arguments because
4361 // we don't want to load things that will be overwritten
4362 static inline void load_reg(signed char entry[], signed char regmap[], int rs)
4363 {
4364   int hr = get_reg(regmap, rs);
4365   if (hr >= 0 && entry[hr] != regmap[hr])
4366     emit_loadreg(regmap[hr], hr);
4367 }
4368
4369 static void load_regs(signed char entry[], signed char regmap[], int rs1, int rs2)
4370 {
4371   load_reg(entry, regmap, rs1);
4372   if (rs1 != rs2)
4373     load_reg(entry, regmap, rs2);
4374 }
4375
4376 // Load registers prior to the start of a loop
4377 // so that they are not loaded within the loop
4378 static void loop_preload(signed char pre[],signed char entry[])
4379 {
4380   int hr;
4381   for (hr = 0; hr < HOST_REGS; hr++) {
4382     int r = entry[hr];
4383     if (r >= 0 && pre[hr] != r && get_reg(pre, r) < 0) {
4384       assem_debug("loop preload:\n");
4385       if (r < TEMPREG)
4386         emit_loadreg(r, hr);
4387     }
4388   }
4389 }
4390
4391 // Generate address for load/store instruction
4392 // goes to AGEN for writes, FTEMP for LOADLR and cop1/2 loads
4393 static void address_generation(int i, const struct regstat *i_regs, signed char entry[])
4394 {
4395   if (dops[i].is_load || dops[i].is_store) {
4396     int ra=-1;
4397     int agr=AGEN1+(i&1);
4398     if(dops[i].itype==LOAD) {
4399       ra=get_reg(i_regs->regmap,dops[i].rt1);
4400       if(ra<0) ra=get_reg_temp(i_regs->regmap);
4401       assert(ra>=0);
4402     }
4403     if(dops[i].itype==LOADLR) {
4404       ra=get_reg(i_regs->regmap,FTEMP);
4405     }
4406     if(dops[i].itype==STORE||dops[i].itype==STORELR) {
4407       ra=get_reg(i_regs->regmap,agr);
4408       if(ra<0) ra=get_reg_temp(i_regs->regmap);
4409     }
4410     if(dops[i].itype==C2LS) {
4411       if ((dops[i].opcode&0x3b)==0x31||(dops[i].opcode&0x3b)==0x32) // LWC1/LDC1/LWC2/LDC2
4412         ra=get_reg(i_regs->regmap,FTEMP);
4413       else { // SWC1/SDC1/SWC2/SDC2
4414         ra=get_reg(i_regs->regmap,agr);
4415         if(ra<0) ra=get_reg_temp(i_regs->regmap);
4416       }
4417     }
4418     int rs=get_reg(i_regs->regmap,dops[i].rs1);
4419     if(ra>=0) {
4420       int offset=imm[i];
4421       int c=(i_regs->wasconst>>rs)&1;
4422       if(dops[i].rs1==0) {
4423         // Using r0 as a base address
4424         if(!entry||entry[ra]!=agr) {
4425           if (dops[i].opcode==0x22||dops[i].opcode==0x26) {
4426             emit_movimm(offset&0xFFFFFFFC,ra); // LWL/LWR
4427           }else if (dops[i].opcode==0x1a||dops[i].opcode==0x1b) {
4428             emit_movimm(offset&0xFFFFFFF8,ra); // LDL/LDR
4429           }else{
4430             emit_movimm(offset,ra);
4431           }
4432         } // else did it in the previous cycle
4433       }
4434       else if(rs<0) {
4435         if(!entry||entry[ra]!=dops[i].rs1)
4436           emit_loadreg(dops[i].rs1,ra);
4437         //if(!entry||entry[ra]!=dops[i].rs1)
4438         //  printf("poor load scheduling!\n");
4439       }
4440       else if(c) {
4441         if(dops[i].rs1!=dops[i].rt1||dops[i].itype!=LOAD) {
4442           if(!entry||entry[ra]!=agr) {
4443             if (dops[i].opcode==0x22||dops[i].opcode==0x26) {
4444               emit_movimm((constmap[i][rs]+offset)&0xFFFFFFFC,ra); // LWL/LWR
4445             }else if (dops[i].opcode==0x1a||dops[i].opcode==0x1b) {
4446               emit_movimm((constmap[i][rs]+offset)&0xFFFFFFF8,ra); // LDL/LDR
4447             }else{
4448               emit_movimm(constmap[i][rs]+offset,ra);
4449               regs[i].loadedconst|=1<<ra;
4450             }
4451           } // else did it in the previous cycle
4452         } // else load_consts already did it
4453       }
4454       if(offset&&!c&&dops[i].rs1) {
4455         if(rs>=0) {
4456           emit_addimm(rs,offset,ra);
4457         }else{
4458           emit_addimm(ra,offset,ra);
4459         }
4460       }
4461     }
4462   }
4463   // Preload constants for next instruction
4464   if (dops[i+1].is_load || dops[i+1].is_store) {
4465     int agr,ra;
4466     // Actual address
4467     agr=AGEN1+((i+1)&1);
4468     ra=get_reg(i_regs->regmap,agr);
4469     if(ra>=0) {
4470       int rs=get_reg(regs[i+1].regmap,dops[i+1].rs1);
4471       int offset=imm[i+1];
4472       int c=(regs[i+1].wasconst>>rs)&1;
4473       if(c&&(dops[i+1].rs1!=dops[i+1].rt1||dops[i+1].itype!=LOAD)) {
4474         if (dops[i+1].opcode==0x22||dops[i+1].opcode==0x26) {
4475           emit_movimm((constmap[i+1][rs]+offset)&0xFFFFFFFC,ra); // LWL/LWR
4476         }else if (dops[i+1].opcode==0x1a||dops[i+1].opcode==0x1b) {
4477           emit_movimm((constmap[i+1][rs]+offset)&0xFFFFFFF8,ra); // LDL/LDR
4478         }else{
4479           emit_movimm(constmap[i+1][rs]+offset,ra);
4480           regs[i+1].loadedconst|=1<<ra;
4481         }
4482       }
4483       else if(dops[i+1].rs1==0) {
4484         // Using r0 as a base address
4485         if (dops[i+1].opcode==0x22||dops[i+1].opcode==0x26) {
4486           emit_movimm(offset&0xFFFFFFFC,ra); // LWL/LWR
4487         }else if (dops[i+1].opcode==0x1a||dops[i+1].opcode==0x1b) {
4488           emit_movimm(offset&0xFFFFFFF8,ra); // LDL/LDR
4489         }else{
4490           emit_movimm(offset,ra);
4491         }
4492       }
4493     }
4494   }
4495 }
4496
4497 static int get_final_value(int hr, int i, int *value)
4498 {
4499   int reg=regs[i].regmap[hr];
4500   while(i<slen-1) {
4501     if(regs[i+1].regmap[hr]!=reg) break;
4502     if(!((regs[i+1].isconst>>hr)&1)) break;
4503     if(dops[i+1].bt) break;
4504     i++;
4505   }
4506   if(i<slen-1) {
4507     if (dops[i].is_jump) {
4508       *value=constmap[i][hr];
4509       return 1;
4510     }
4511     if(!dops[i+1].bt) {
4512       if (dops[i+1].is_jump) {
4513         // Load in delay slot, out-of-order execution
4514         if(dops[i+2].itype==LOAD&&dops[i+2].rs1==reg&&dops[i+2].rt1==reg&&((regs[i+1].wasconst>>hr)&1))
4515         {
4516           // Precompute load address
4517           *value=constmap[i][hr]+imm[i+2];
4518           return 1;
4519         }
4520       }
4521       if(dops[i+1].itype==LOAD&&dops[i+1].rs1==reg&&dops[i+1].rt1==reg)
4522       {
4523         // Precompute load address
4524         *value=constmap[i][hr]+imm[i+1];
4525         //printf("c=%x imm=%lx\n",(long)constmap[i][hr],imm[i+1]);
4526         return 1;
4527       }
4528     }
4529   }
4530   *value=constmap[i][hr];
4531   //printf("c=%lx\n",(long)constmap[i][hr]);
4532   if(i==slen-1) return 1;
4533   assert(reg < 64);
4534   return !((unneeded_reg[i+1]>>reg)&1);
4535 }
4536
4537 // Load registers with known constants
4538 static void load_consts(signed char pre[],signed char regmap[],int i)
4539 {
4540   int hr,hr2;
4541   // propagate loaded constant flags
4542   if(i==0||dops[i].bt)
4543     regs[i].loadedconst=0;
4544   else {
4545     for(hr=0;hr<HOST_REGS;hr++) {
4546       if(hr!=EXCLUDE_REG&&regmap[hr]>=0&&((regs[i-1].isconst>>hr)&1)&&pre[hr]==regmap[hr]
4547          &&regmap[hr]==regs[i-1].regmap[hr]&&((regs[i-1].loadedconst>>hr)&1))
4548       {
4549         regs[i].loadedconst|=1<<hr;
4550       }
4551     }
4552   }
4553   // Load 32-bit regs
4554   for(hr=0;hr<HOST_REGS;hr++) {
4555     if(hr!=EXCLUDE_REG&&regmap[hr]>=0) {
4556       //if(entry[hr]!=regmap[hr]) {
4557       if(!((regs[i].loadedconst>>hr)&1)) {
4558         assert(regmap[hr]<64);
4559         if(((regs[i].isconst>>hr)&1)&&regmap[hr]>0) {
4560           int value,similar=0;
4561           if(get_final_value(hr,i,&value)) {
4562             // see if some other register has similar value
4563             for(hr2=0;hr2<HOST_REGS;hr2++) {
4564               if(hr2!=EXCLUDE_REG&&((regs[i].loadedconst>>hr2)&1)) {
4565                 if(is_similar_value(value,constmap[i][hr2])) {
4566                   similar=1;
4567                   break;
4568                 }
4569               }
4570             }
4571             if(similar) {
4572               int value2;
4573               if(get_final_value(hr2,i,&value2)) // is this needed?
4574                 emit_movimm_from(value2,hr2,value,hr);
4575               else
4576                 emit_movimm(value,hr);
4577             }
4578             else if(value==0) {
4579               emit_zeroreg(hr);
4580             }
4581             else {
4582               emit_movimm(value,hr);
4583             }
4584           }
4585           regs[i].loadedconst|=1<<hr;
4586         }
4587       }
4588     }
4589   }
4590 }
4591
4592 static void load_all_consts(const signed char regmap[], u_int dirty, int i)
4593 {
4594   int hr;
4595   // Load 32-bit regs
4596   for(hr=0;hr<HOST_REGS;hr++) {
4597     if(hr!=EXCLUDE_REG&&regmap[hr]>=0&&((dirty>>hr)&1)) {
4598       assert(regmap[hr] < 64);
4599       if(((regs[i].isconst>>hr)&1)&&regmap[hr]>0) {
4600         int value=constmap[i][hr];
4601         if(value==0) {
4602           emit_zeroreg(hr);
4603         }
4604         else {
4605           emit_movimm(value,hr);
4606         }
4607       }
4608     }
4609   }
4610 }
4611
4612 // Write out all dirty registers (except cycle count)
4613 static void wb_dirtys(const signed char i_regmap[], uint64_t i_dirty)
4614 {
4615   int hr;
4616   for(hr=0;hr<HOST_REGS;hr++) {
4617     if(hr!=EXCLUDE_REG) {
4618       if(i_regmap[hr]>0) {
4619         if(i_regmap[hr]!=CCREG) {
4620           if((i_dirty>>hr)&1) {
4621             assert(i_regmap[hr]<64);
4622             emit_storereg(i_regmap[hr],hr);
4623           }
4624         }
4625       }
4626     }
4627   }
4628 }
4629
4630 // Write out dirty registers that we need to reload (pair with load_needed_regs)
4631 // This writes the registers not written by store_regs_bt
4632 static void wb_needed_dirtys(const signed char i_regmap[], uint64_t i_dirty, int addr)
4633 {
4634   int hr;
4635   int t=(addr-start)>>2;
4636   for(hr=0;hr<HOST_REGS;hr++) {
4637     if(hr!=EXCLUDE_REG) {
4638       if(i_regmap[hr]>0) {
4639         if(i_regmap[hr]!=CCREG) {
4640           if(i_regmap[hr]==regs[t].regmap_entry[hr] && ((regs[t].dirty>>hr)&1)) {
4641             if((i_dirty>>hr)&1) {
4642               assert(i_regmap[hr]<64);
4643               emit_storereg(i_regmap[hr],hr);
4644             }
4645           }
4646         }
4647       }
4648     }
4649   }
4650 }
4651
4652 // Load all registers (except cycle count)
4653 static void load_all_regs(const signed char i_regmap[])
4654 {
4655   int hr;
4656   for(hr=0;hr<HOST_REGS;hr++) {
4657     if(hr!=EXCLUDE_REG) {
4658       if(i_regmap[hr]==0) {
4659         emit_zeroreg(hr);
4660       }
4661       else
4662       if(i_regmap[hr]>0 && i_regmap[hr]<TEMPREG && i_regmap[hr]!=CCREG)
4663       {
4664         emit_loadreg(i_regmap[hr],hr);
4665       }
4666     }
4667   }
4668 }
4669
4670 // Load all current registers also needed by next instruction
4671 static void load_needed_regs(const signed char i_regmap[], const signed char next_regmap[])
4672 {
4673   int hr;
4674   for(hr=0;hr<HOST_REGS;hr++) {
4675     if(hr!=EXCLUDE_REG) {
4676       if(get_reg(next_regmap,i_regmap[hr])>=0) {
4677         if(i_regmap[hr]==0) {
4678           emit_zeroreg(hr);
4679         }
4680         else
4681         if(i_regmap[hr]>0 && i_regmap[hr]<TEMPREG && i_regmap[hr]!=CCREG)
4682         {
4683           emit_loadreg(i_regmap[hr],hr);
4684         }
4685       }
4686     }
4687   }
4688 }
4689
4690 // Load all regs, storing cycle count if necessary
4691 static void load_regs_entry(int t)
4692 {
4693   int hr;
4694   if(dops[t].is_ds) emit_addimm(HOST_CCREG,CLOCK_ADJUST(1),HOST_CCREG);
4695   else if(ccadj[t]) emit_addimm(HOST_CCREG,-ccadj[t],HOST_CCREG);
4696   if(regs[t].regmap_entry[HOST_CCREG]!=CCREG) {
4697     emit_storereg(CCREG,HOST_CCREG);
4698   }
4699   // Load 32-bit regs
4700   for(hr=0;hr<HOST_REGS;hr++) {
4701     if(regs[t].regmap_entry[hr]>=0&&regs[t].regmap_entry[hr]<TEMPREG) {
4702       if(regs[t].regmap_entry[hr]==0) {
4703         emit_zeroreg(hr);
4704       }
4705       else if(regs[t].regmap_entry[hr]!=CCREG)
4706       {
4707         emit_loadreg(regs[t].regmap_entry[hr],hr);
4708       }
4709     }
4710   }
4711 }
4712
4713 // Store dirty registers prior to branch
4714 static void store_regs_bt(signed char i_regmap[],uint64_t i_dirty,int addr)
4715 {
4716   if(internal_branch(addr))
4717   {
4718     int t=(addr-start)>>2;
4719     int hr;
4720     for(hr=0;hr<HOST_REGS;hr++) {
4721       if(hr!=EXCLUDE_REG) {
4722         if(i_regmap[hr]>0 && i_regmap[hr]!=CCREG) {
4723           if(i_regmap[hr]!=regs[t].regmap_entry[hr] || !((regs[t].dirty>>hr)&1)) {
4724             if((i_dirty>>hr)&1) {
4725               assert(i_regmap[hr]<64);
4726               if(!((unneeded_reg[t]>>i_regmap[hr])&1))
4727                 emit_storereg(i_regmap[hr],hr);
4728             }
4729           }
4730         }
4731       }
4732     }
4733   }
4734   else
4735   {
4736     // Branch out of this block, write out all dirty regs
4737     wb_dirtys(i_regmap,i_dirty);
4738   }
4739 }
4740
4741 // Load all needed registers for branch target
4742 static void load_regs_bt(signed char i_regmap[],uint64_t i_dirty,int addr)
4743 {
4744   //if(addr>=start && addr<(start+slen*4))
4745   if(internal_branch(addr))
4746   {
4747     int t=(addr-start)>>2;
4748     int hr;
4749     // Store the cycle count before loading something else
4750     if(i_regmap[HOST_CCREG]!=CCREG) {
4751       assert(i_regmap[HOST_CCREG]==-1);
4752     }
4753     if(regs[t].regmap_entry[HOST_CCREG]!=CCREG) {
4754       emit_storereg(CCREG,HOST_CCREG);
4755     }
4756     // Load 32-bit regs
4757     for(hr=0;hr<HOST_REGS;hr++) {
4758       if(hr!=EXCLUDE_REG&&regs[t].regmap_entry[hr]>=0&&regs[t].regmap_entry[hr]<TEMPREG) {
4759         if(i_regmap[hr]!=regs[t].regmap_entry[hr]) {
4760           if(regs[t].regmap_entry[hr]==0) {
4761             emit_zeroreg(hr);
4762           }
4763           else if(regs[t].regmap_entry[hr]!=CCREG)
4764           {
4765             emit_loadreg(regs[t].regmap_entry[hr],hr);
4766           }
4767         }
4768       }
4769     }
4770   }
4771 }
4772
4773 static int match_bt(signed char i_regmap[],uint64_t i_dirty,int addr)
4774 {
4775   if(addr>=start && addr<start+slen*4-4)
4776   {
4777     int t=(addr-start)>>2;
4778     int hr;
4779     if(regs[t].regmap_entry[HOST_CCREG]!=CCREG) return 0;
4780     for(hr=0;hr<HOST_REGS;hr++)
4781     {
4782       if(hr!=EXCLUDE_REG)
4783       {
4784         if(i_regmap[hr]!=regs[t].regmap_entry[hr])
4785         {
4786           if(regs[t].regmap_entry[hr]>=0&&(regs[t].regmap_entry[hr]|64)<TEMPREG+64)
4787           {
4788             return 0;
4789           }
4790           else
4791           if((i_dirty>>hr)&1)
4792           {
4793             if(i_regmap[hr]<TEMPREG)
4794             {
4795               if(!((unneeded_reg[t]>>i_regmap[hr])&1))
4796                 return 0;
4797             }
4798             else if(i_regmap[hr]>=64&&i_regmap[hr]<TEMPREG+64)
4799             {
4800               assert(0);
4801             }
4802           }
4803         }
4804         else // Same register but is it 32-bit or dirty?
4805         if(i_regmap[hr]>=0)
4806         {
4807           if(!((regs[t].dirty>>hr)&1))
4808           {
4809             if((i_dirty>>hr)&1)
4810             {
4811               if(!((unneeded_reg[t]>>i_regmap[hr])&1))
4812               {
4813                 //printf("%x: dirty no match\n",addr);
4814                 return 0;
4815               }
4816             }
4817           }
4818         }
4819       }
4820     }
4821     // Delay slots are not valid branch targets
4822     //if(t>0&&(dops[t-1].is_jump) return 0;
4823     // Delay slots require additional processing, so do not match
4824     if(dops[t].is_ds) return 0;
4825   }
4826   else
4827   {
4828     int hr;
4829     for(hr=0;hr<HOST_REGS;hr++)
4830     {
4831       if(hr!=EXCLUDE_REG)
4832       {
4833         if(i_regmap[hr]>=0)
4834         {
4835           if(hr!=HOST_CCREG||i_regmap[hr]!=CCREG)
4836           {
4837             if((i_dirty>>hr)&1)
4838             {
4839               return 0;
4840             }
4841           }
4842         }
4843       }
4844     }
4845   }
4846   return 1;
4847 }
4848
4849 #ifdef DRC_DBG
4850 static void drc_dbg_emit_do_cmp(int i, int ccadj_)
4851 {
4852   extern void do_insn_cmp();
4853   //extern int cycle;
4854   u_int hr, reglist = get_host_reglist(regs[i].regmap);
4855
4856   assem_debug("//do_insn_cmp %08x\n", start+i*4);
4857   save_regs(reglist);
4858   // write out changed consts to match the interpreter
4859   if (i > 0 && !dops[i].bt) {
4860     for (hr = 0; hr < HOST_REGS; hr++) {
4861       int reg = regs[i].regmap_entry[hr]; // regs[i-1].regmap[hr];
4862       if (hr == EXCLUDE_REG || reg < 0)
4863         continue;
4864       if (!((regs[i-1].isconst >> hr) & 1))
4865         continue;
4866       if (i > 1 && reg == regs[i-2].regmap[hr] && constmap[i-1][hr] == constmap[i-2][hr])
4867         continue;
4868       emit_movimm(constmap[i-1][hr],0);
4869       emit_storereg(reg, 0);
4870     }
4871   }
4872   emit_movimm(start+i*4,0);
4873   emit_writeword(0,&pcaddr);
4874   int cc = get_reg(regs[i].regmap_entry, CCREG);
4875   if (cc < 0)
4876     emit_loadreg(CCREG, cc = 0);
4877   emit_addimm(cc, ccadj_, 0);
4878   emit_writeword(0, &psxRegs.cycle);
4879   emit_far_call(do_insn_cmp);
4880   //emit_readword(&cycle,0);
4881   //emit_addimm(0,2,0);
4882   //emit_writeword(0,&cycle);
4883   (void)get_reg2;
4884   restore_regs(reglist);
4885   assem_debug("\\\\do_insn_cmp\n");
4886 }
4887 #else
4888 #define drc_dbg_emit_do_cmp(x,y)
4889 #endif
4890
4891 // Used when a branch jumps into the delay slot of another branch
4892 static void ds_assemble_entry(int i)
4893 {
4894   int t = (ba[i] - start) >> 2;
4895   int ccadj_ = -CLOCK_ADJUST(1);
4896   if (!instr_addr[t])
4897     instr_addr[t] = out;
4898   assem_debug("Assemble delay slot at %x\n",ba[i]);
4899   assem_debug("<->\n");
4900   drc_dbg_emit_do_cmp(t, ccadj_);
4901   if(regs[t].regmap_entry[HOST_CCREG]==CCREG&&regs[t].regmap[HOST_CCREG]!=CCREG)
4902     wb_register(CCREG,regs[t].regmap_entry,regs[t].wasdirty);
4903   load_regs(regs[t].regmap_entry,regs[t].regmap,dops[t].rs1,dops[t].rs2);
4904   address_generation(t,&regs[t],regs[t].regmap_entry);
4905   if (ram_offset && (dops[t].is_load || dops[t].is_store))
4906     load_reg(regs[t].regmap_entry,regs[t].regmap,ROREG);
4907   if (dops[t].is_store)
4908     load_reg(regs[t].regmap_entry,regs[t].regmap,INVCP);
4909   is_delayslot=0;
4910   switch (dops[t].itype) {
4911     case SYSCALL:
4912     case HLECALL:
4913     case INTCALL:
4914     case UJUMP:
4915     case RJUMP:
4916     case CJUMP:
4917     case SJUMP:
4918       SysPrintf("Jump in the delay slot.  This is probably a bug.\n");
4919       break;
4920     default:
4921       assemble(t, &regs[t], ccadj_);
4922   }
4923   store_regs_bt(regs[t].regmap,regs[t].dirty,ba[i]+4);
4924   load_regs_bt(regs[t].regmap,regs[t].dirty,ba[i]+4);
4925   if(internal_branch(ba[i]+4))
4926     assem_debug("branch: internal\n");
4927   else
4928     assem_debug("branch: external\n");
4929   assert(internal_branch(ba[i]+4));
4930   add_to_linker(out,ba[i]+4,internal_branch(ba[i]+4));
4931   emit_jmp(0);
4932 }
4933
4934 // Load 2 immediates optimizing for small code size
4935 static void emit_mov2imm_compact(int imm1,u_int rt1,int imm2,u_int rt2)
4936 {
4937   emit_movimm(imm1,rt1);
4938   emit_movimm_from(imm1,rt1,imm2,rt2);
4939 }
4940
4941 static void do_cc(int i, const signed char i_regmap[], int *adj,
4942   int addr, int taken, int invert)
4943 {
4944   int count, count_plus2;
4945   void *jaddr;
4946   void *idle=NULL;
4947   int t=0;
4948   if(dops[i].itype==RJUMP)
4949   {
4950     *adj=0;
4951   }
4952   //if(ba[i]>=start && ba[i]<(start+slen*4))
4953   if(internal_branch(ba[i]))
4954   {
4955     t=(ba[i]-start)>>2;
4956     if(dops[t].is_ds) *adj=-CLOCK_ADJUST(1); // Branch into delay slot adds an extra cycle
4957     else *adj=ccadj[t];
4958   }
4959   else
4960   {
4961     *adj=0;
4962   }
4963   count = ccadj[i];
4964   count_plus2 = count + CLOCK_ADJUST(2);
4965   if(taken==TAKEN && i==(ba[i]-start)>>2 && source[i+1]==0) {
4966     // Idle loop
4967     if(count&1) emit_addimm_and_set_flags(2*(count+2),HOST_CCREG);
4968     idle=out;
4969     //emit_subfrommem(&idlecount,HOST_CCREG); // Count idle cycles
4970     emit_andimm(HOST_CCREG,3,HOST_CCREG);
4971     jaddr=out;
4972     emit_jmp(0);
4973   }
4974   else if(*adj==0||invert) {
4975     int cycles = count_plus2;
4976     // faster loop HACK
4977 #if 0
4978     if (t&&*adj) {
4979       int rel=t-i;
4980       if(-NO_CYCLE_PENALTY_THR<rel&&rel<0)
4981         cycles=*adj+count+2-*adj;
4982     }
4983 #endif
4984     emit_addimm_and_set_flags(cycles, HOST_CCREG);
4985     jaddr = out;
4986     emit_jns(0);
4987   }
4988   else
4989   {
4990     emit_cmpimm(HOST_CCREG, -count_plus2);
4991     jaddr = out;
4992     emit_jns(0);
4993   }
4994   add_stub(CC_STUB,jaddr,idle?idle:out,(*adj==0||invert||idle)?0:count_plus2,i,addr,taken,0);
4995 }
4996
4997 static void do_ccstub(int n)
4998 {
4999   literal_pool(256);
5000   assem_debug("do_ccstub %x\n",start+(u_int)stubs[n].b*4);
5001   set_jump_target(stubs[n].addr, out);
5002   int i=stubs[n].b;
5003   if(stubs[n].d==NULLDS) {
5004     // Delay slot instruction is nullified ("likely" branch)
5005     wb_dirtys(regs[i].regmap,regs[i].dirty);
5006   }
5007   else if(stubs[n].d!=TAKEN) {
5008     wb_dirtys(branch_regs[i].regmap,branch_regs[i].dirty);
5009   }
5010   else {
5011     if(internal_branch(ba[i]))
5012       wb_needed_dirtys(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5013   }
5014   if(stubs[n].c!=-1)
5015   {
5016     // Save PC as return address
5017     emit_movimm(stubs[n].c,EAX);
5018     emit_writeword(EAX,&pcaddr);
5019   }
5020   else
5021   {
5022     // Return address depends on which way the branch goes
5023     if(dops[i].itype==CJUMP||dops[i].itype==SJUMP)
5024     {
5025       int s1l=get_reg(branch_regs[i].regmap,dops[i].rs1);
5026       int s2l=get_reg(branch_regs[i].regmap,dops[i].rs2);
5027       if(dops[i].rs1==0)
5028       {
5029         s1l=s2l;
5030         s2l=-1;
5031       }
5032       else if(dops[i].rs2==0)
5033       {
5034         s2l=-1;
5035       }
5036       assert(s1l>=0);
5037       #ifdef DESTRUCTIVE_WRITEBACK
5038       if(dops[i].rs1) {
5039         if((branch_regs[i].dirty>>s1l)&&1)
5040           emit_loadreg(dops[i].rs1,s1l);
5041       }
5042       else {
5043         if((branch_regs[i].dirty>>s1l)&1)
5044           emit_loadreg(dops[i].rs2,s1l);
5045       }
5046       if(s2l>=0)
5047         if((branch_regs[i].dirty>>s2l)&1)
5048           emit_loadreg(dops[i].rs2,s2l);
5049       #endif
5050       int hr=0;
5051       int addr=-1,alt=-1,ntaddr=-1;
5052       while(hr<HOST_REGS)
5053       {
5054         if(hr!=EXCLUDE_REG && hr!=HOST_CCREG &&
5055            branch_regs[i].regmap[hr]!=dops[i].rs1 &&
5056            branch_regs[i].regmap[hr]!=dops[i].rs2 )
5057         {
5058           addr=hr++;break;
5059         }
5060         hr++;
5061       }
5062       while(hr<HOST_REGS)
5063       {
5064         if(hr!=EXCLUDE_REG && hr!=HOST_CCREG &&
5065            branch_regs[i].regmap[hr]!=dops[i].rs1 &&
5066            branch_regs[i].regmap[hr]!=dops[i].rs2 )
5067         {
5068           alt=hr++;break;
5069         }
5070         hr++;
5071       }
5072       if((dops[i].opcode&0x2E)==6) // BLEZ/BGTZ needs another register
5073       {
5074         while(hr<HOST_REGS)
5075         {
5076           if(hr!=EXCLUDE_REG && hr!=HOST_CCREG &&
5077              branch_regs[i].regmap[hr]!=dops[i].rs1 &&
5078              branch_regs[i].regmap[hr]!=dops[i].rs2 )
5079           {
5080             ntaddr=hr;break;
5081           }
5082           hr++;
5083         }
5084         assert(hr<HOST_REGS);
5085       }
5086       if((dops[i].opcode&0x2f)==4) // BEQ
5087       {
5088         #ifdef HAVE_CMOV_IMM
5089         if(s2l>=0) emit_cmp(s1l,s2l);
5090         else emit_test(s1l,s1l);
5091         emit_cmov2imm_e_ne_compact(ba[i],start+i*4+8,addr);
5092         #else
5093         emit_mov2imm_compact(ba[i],addr,start+i*4+8,alt);
5094         if(s2l>=0) emit_cmp(s1l,s2l);
5095         else emit_test(s1l,s1l);
5096         emit_cmovne_reg(alt,addr);
5097         #endif
5098       }
5099       if((dops[i].opcode&0x2f)==5) // BNE
5100       {
5101         #ifdef HAVE_CMOV_IMM
5102         if(s2l>=0) emit_cmp(s1l,s2l);
5103         else emit_test(s1l,s1l);
5104         emit_cmov2imm_e_ne_compact(start+i*4+8,ba[i],addr);
5105         #else
5106         emit_mov2imm_compact(start+i*4+8,addr,ba[i],alt);
5107         if(s2l>=0) emit_cmp(s1l,s2l);
5108         else emit_test(s1l,s1l);
5109         emit_cmovne_reg(alt,addr);
5110         #endif
5111       }
5112       if((dops[i].opcode&0x2f)==6) // BLEZ
5113       {
5114         //emit_movimm(ba[i],alt);
5115         //emit_movimm(start+i*4+8,addr);
5116         emit_mov2imm_compact(ba[i],alt,start+i*4+8,addr);
5117         emit_cmpimm(s1l,1);
5118         emit_cmovl_reg(alt,addr);
5119       }
5120       if((dops[i].opcode&0x2f)==7) // BGTZ
5121       {
5122         //emit_movimm(ba[i],addr);
5123         //emit_movimm(start+i*4+8,ntaddr);
5124         emit_mov2imm_compact(ba[i],addr,start+i*4+8,ntaddr);
5125         emit_cmpimm(s1l,1);
5126         emit_cmovl_reg(ntaddr,addr);
5127       }
5128       if((dops[i].opcode==1)&&(dops[i].opcode2&0x2D)==0) // BLTZ
5129       {
5130         //emit_movimm(ba[i],alt);
5131         //emit_movimm(start+i*4+8,addr);
5132         emit_mov2imm_compact(ba[i],alt,start+i*4+8,addr);
5133         emit_test(s1l,s1l);
5134         emit_cmovs_reg(alt,addr);
5135       }
5136       if((dops[i].opcode==1)&&(dops[i].opcode2&0x2D)==1) // BGEZ
5137       {
5138         //emit_movimm(ba[i],addr);
5139         //emit_movimm(start+i*4+8,alt);
5140         emit_mov2imm_compact(ba[i],addr,start+i*4+8,alt);
5141         emit_test(s1l,s1l);
5142         emit_cmovs_reg(alt,addr);
5143       }
5144       if(dops[i].opcode==0x11 && dops[i].opcode2==0x08 ) {
5145         if(source[i]&0x10000) // BC1T
5146         {
5147           //emit_movimm(ba[i],alt);
5148           //emit_movimm(start+i*4+8,addr);
5149           emit_mov2imm_compact(ba[i],alt,start+i*4+8,addr);
5150           emit_testimm(s1l,0x800000);
5151           emit_cmovne_reg(alt,addr);
5152         }
5153         else // BC1F
5154         {
5155           //emit_movimm(ba[i],addr);
5156           //emit_movimm(start+i*4+8,alt);
5157           emit_mov2imm_compact(ba[i],addr,start+i*4+8,alt);
5158           emit_testimm(s1l,0x800000);
5159           emit_cmovne_reg(alt,addr);
5160         }
5161       }
5162       emit_writeword(addr,&pcaddr);
5163     }
5164     else
5165     if(dops[i].itype==RJUMP)
5166     {
5167       int r=get_reg(branch_regs[i].regmap,dops[i].rs1);
5168       if (ds_writes_rjump_rs(i)) {
5169         r=get_reg(branch_regs[i].regmap,RTEMP);
5170       }
5171       emit_writeword(r,&pcaddr);
5172     }
5173     else {SysPrintf("Unknown branch type in do_ccstub\n");abort();}
5174   }
5175   // Update cycle count
5176   assert(branch_regs[i].regmap[HOST_CCREG]==CCREG||branch_regs[i].regmap[HOST_CCREG]==-1);
5177   if(stubs[n].a) emit_addimm(HOST_CCREG,(int)stubs[n].a,HOST_CCREG);
5178   emit_far_call(cc_interrupt);
5179   if(stubs[n].a) emit_addimm(HOST_CCREG,-(int)stubs[n].a,HOST_CCREG);
5180   if(stubs[n].d==TAKEN) {
5181     if(internal_branch(ba[i]))
5182       load_needed_regs(branch_regs[i].regmap,regs[(ba[i]-start)>>2].regmap_entry);
5183     else if(dops[i].itype==RJUMP) {
5184       if(get_reg(branch_regs[i].regmap,RTEMP)>=0)
5185         emit_readword(&pcaddr,get_reg(branch_regs[i].regmap,RTEMP));
5186       else
5187         emit_loadreg(dops[i].rs1,get_reg(branch_regs[i].regmap,dops[i].rs1));
5188     }
5189   }else if(stubs[n].d==NOTTAKEN) {
5190     if(i<slen-2) load_needed_regs(branch_regs[i].regmap,regmap_pre[i+2]);
5191     else load_all_regs(branch_regs[i].regmap);
5192   }else if(stubs[n].d==NULLDS) {
5193     // Delay slot instruction is nullified ("likely" branch)
5194     if(i<slen-2) load_needed_regs(regs[i].regmap,regmap_pre[i+2]);
5195     else load_all_regs(regs[i].regmap);
5196   }else{
5197     load_all_regs(branch_regs[i].regmap);
5198   }
5199   if (stubs[n].retaddr)
5200     emit_jmp(stubs[n].retaddr);
5201   else
5202     do_jump_vaddr(stubs[n].e);
5203 }
5204
5205 static void add_to_linker(void *addr, u_int target, int is_internal)
5206 {
5207   assert(linkcount < ARRAY_SIZE(link_addr));
5208   link_addr[linkcount].addr = addr;
5209   link_addr[linkcount].target = target;
5210   link_addr[linkcount].internal = is_internal;
5211   linkcount++;
5212 }
5213
5214 static void ujump_assemble_write_ra(int i)
5215 {
5216   int rt;
5217   unsigned int return_address;
5218   rt=get_reg(branch_regs[i].regmap,31);
5219   assem_debug("branch(%d): eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",i,branch_regs[i].regmap[0],branch_regs[i].regmap[1],branch_regs[i].regmap[2],branch_regs[i].regmap[3],branch_regs[i].regmap[5],branch_regs[i].regmap[6],branch_regs[i].regmap[7]);
5220   //assert(rt>=0);
5221   return_address=start+i*4+8;
5222   if(rt>=0) {
5223     #ifdef USE_MINI_HT
5224     if(internal_branch(return_address)&&dops[i+1].rt1!=31) {
5225       int temp=-1; // note: must be ds-safe
5226       #ifdef HOST_TEMPREG
5227       temp=HOST_TEMPREG;
5228       #endif
5229       if(temp>=0) do_miniht_insert(return_address,rt,temp);
5230       else emit_movimm(return_address,rt);
5231     }
5232     else
5233     #endif
5234     {
5235       #ifdef REG_PREFETCH
5236       if(temp>=0)
5237       {
5238         if(i_regmap[temp]!=PTEMP) emit_movimm((uintptr_t)hash_table_get(return_address),temp);
5239       }
5240       #endif
5241       emit_movimm(return_address,rt); // PC into link register
5242       #ifdef IMM_PREFETCH
5243       emit_prefetch(hash_table_get(return_address));
5244       #endif
5245     }
5246   }
5247 }
5248
5249 static void ujump_assemble(int i, const struct regstat *i_regs)
5250 {
5251   int ra_done=0;
5252   if(i==(ba[i]-start)>>2) assem_debug("idle loop\n");
5253   address_generation(i+1,i_regs,regs[i].regmap_entry);
5254   #ifdef REG_PREFETCH
5255   int temp=get_reg(branch_regs[i].regmap,PTEMP);
5256   if(dops[i].rt1==31&&temp>=0)
5257   {
5258     signed char *i_regmap=i_regs->regmap;
5259     int return_address=start+i*4+8;
5260     if(get_reg(branch_regs[i].regmap,31)>0)
5261     if(i_regmap[temp]==PTEMP) emit_movimm((uintptr_t)hash_table_get(return_address),temp);
5262   }
5263   #endif
5264   if(dops[i].rt1==31&&(dops[i].rt1==dops[i+1].rs1||dops[i].rt1==dops[i+1].rs2)) {
5265     ujump_assemble_write_ra(i); // writeback ra for DS
5266     ra_done=1;
5267   }
5268   ds_assemble(i+1,i_regs);
5269   uint64_t bc_unneeded=branch_regs[i].u;
5270   bc_unneeded|=1|(1LL<<dops[i].rt1);
5271   wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,bc_unneeded);
5272   load_reg(regs[i].regmap,branch_regs[i].regmap,CCREG);
5273   if(!ra_done&&dops[i].rt1==31)
5274     ujump_assemble_write_ra(i);
5275   int cc,adj;
5276   cc=get_reg(branch_regs[i].regmap,CCREG);
5277   assert(cc==HOST_CCREG);
5278   store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5279   #ifdef REG_PREFETCH
5280   if(dops[i].rt1==31&&temp>=0) emit_prefetchreg(temp);
5281   #endif
5282   do_cc(i,branch_regs[i].regmap,&adj,ba[i],TAKEN,0);
5283   if(adj) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5284   load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5285   if(internal_branch(ba[i]))
5286     assem_debug("branch: internal\n");
5287   else
5288     assem_debug("branch: external\n");
5289   if (internal_branch(ba[i]) && dops[(ba[i]-start)>>2].is_ds) {
5290     ds_assemble_entry(i);
5291   }
5292   else {
5293     add_to_linker(out,ba[i],internal_branch(ba[i]));
5294     emit_jmp(0);
5295   }
5296 }
5297
5298 static void rjump_assemble_write_ra(int i)
5299 {
5300   int rt,return_address;
5301   assert(dops[i+1].rt1!=dops[i].rt1);
5302   assert(dops[i+1].rt2!=dops[i].rt1);
5303   rt=get_reg(branch_regs[i].regmap,dops[i].rt1);
5304   assem_debug("branch(%d): eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",i,branch_regs[i].regmap[0],branch_regs[i].regmap[1],branch_regs[i].regmap[2],branch_regs[i].regmap[3],branch_regs[i].regmap[5],branch_regs[i].regmap[6],branch_regs[i].regmap[7]);
5305   assert(rt>=0);
5306   return_address=start+i*4+8;
5307   #ifdef REG_PREFETCH
5308   if(temp>=0)
5309   {
5310     if(i_regmap[temp]!=PTEMP) emit_movimm((uintptr_t)hash_table_get(return_address),temp);
5311   }
5312   #endif
5313   emit_movimm(return_address,rt); // PC into link register
5314   #ifdef IMM_PREFETCH
5315   emit_prefetch(hash_table_get(return_address));
5316   #endif
5317 }
5318
5319 static void rjump_assemble(int i, const struct regstat *i_regs)
5320 {
5321   int temp;
5322   int rs,cc;
5323   int ra_done=0;
5324   rs=get_reg(branch_regs[i].regmap,dops[i].rs1);
5325   assert(rs>=0);
5326   if (ds_writes_rjump_rs(i)) {
5327     // Delay slot abuse, make a copy of the branch address register
5328     temp=get_reg(branch_regs[i].regmap,RTEMP);
5329     assert(temp>=0);
5330     assert(regs[i].regmap[temp]==RTEMP);
5331     emit_mov(rs,temp);
5332     rs=temp;
5333   }
5334   address_generation(i+1,i_regs,regs[i].regmap_entry);
5335   #ifdef REG_PREFETCH
5336   if(dops[i].rt1==31)
5337   {
5338     if((temp=get_reg(branch_regs[i].regmap,PTEMP))>=0) {
5339       signed char *i_regmap=i_regs->regmap;
5340       int return_address=start+i*4+8;
5341       if(i_regmap[temp]==PTEMP) emit_movimm((uintptr_t)hash_table_get(return_address),temp);
5342     }
5343   }
5344   #endif
5345   #ifdef USE_MINI_HT
5346   if(dops[i].rs1==31) {
5347     int rh=get_reg(regs[i].regmap,RHASH);
5348     if(rh>=0) do_preload_rhash(rh);
5349   }
5350   #endif
5351   if(dops[i].rt1!=0&&(dops[i].rt1==dops[i+1].rs1||dops[i].rt1==dops[i+1].rs2)) {
5352     rjump_assemble_write_ra(i);
5353     ra_done=1;
5354   }
5355   ds_assemble(i+1,i_regs);
5356   uint64_t bc_unneeded=branch_regs[i].u;
5357   bc_unneeded|=1|(1LL<<dops[i].rt1);
5358   bc_unneeded&=~(1LL<<dops[i].rs1);
5359   wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,bc_unneeded);
5360   load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i].rs1,CCREG);
5361   if(!ra_done&&dops[i].rt1!=0)
5362     rjump_assemble_write_ra(i);
5363   cc=get_reg(branch_regs[i].regmap,CCREG);
5364   assert(cc==HOST_CCREG);
5365   (void)cc;
5366   #ifdef USE_MINI_HT
5367   int rh=get_reg(branch_regs[i].regmap,RHASH);
5368   int ht=get_reg(branch_regs[i].regmap,RHTBL);
5369   if(dops[i].rs1==31) {
5370     if(regs[i].regmap[rh]!=RHASH) do_preload_rhash(rh);
5371     do_preload_rhtbl(ht);
5372     do_rhash(rs,rh);
5373   }
5374   #endif
5375   store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,-1);
5376   #ifdef DESTRUCTIVE_WRITEBACK
5377   if((branch_regs[i].dirty>>rs)&1) {
5378     if(dops[i].rs1!=dops[i+1].rt1&&dops[i].rs1!=dops[i+1].rt2) {
5379       emit_loadreg(dops[i].rs1,rs);
5380     }
5381   }
5382   #endif
5383   #ifdef REG_PREFETCH
5384   if(dops[i].rt1==31&&temp>=0) emit_prefetchreg(temp);
5385   #endif
5386   #ifdef USE_MINI_HT
5387   if(dops[i].rs1==31) {
5388     do_miniht_load(ht,rh);
5389   }
5390   #endif
5391   //do_cc(i,branch_regs[i].regmap,&adj,-1,TAKEN);
5392   //if(adj) emit_addimm(cc,2*(ccadj[i]+2-adj),cc); // ??? - Shouldn't happen
5393   //assert(adj==0);
5394   emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), HOST_CCREG);
5395   add_stub(CC_STUB,out,NULL,0,i,-1,TAKEN,rs);
5396   if(dops[i+1].itype==COP0 && dops[i+1].opcode2==0x10)
5397     // special case for RFE
5398     emit_jmp(0);
5399   else
5400     emit_jns(0);
5401   //load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,-1);
5402   #ifdef USE_MINI_HT
5403   if(dops[i].rs1==31) {
5404     do_miniht_jump(rs,rh,ht);
5405   }
5406   else
5407   #endif
5408   {
5409     do_jump_vaddr(rs);
5410   }
5411   #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5412   if(dops[i].rt1!=31&&i<slen-2&&(((u_int)out)&7)) emit_mov(13,13);
5413   #endif
5414 }
5415
5416 static void cjump_assemble(int i, const struct regstat *i_regs)
5417 {
5418   const signed char *i_regmap = i_regs->regmap;
5419   int cc;
5420   int match;
5421   match=match_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5422   assem_debug("match=%d\n",match);
5423   int s1l,s2l;
5424   int unconditional=0,nop=0;
5425   int invert=0;
5426   int internal=internal_branch(ba[i]);
5427   if(i==(ba[i]-start)>>2) assem_debug("idle loop\n");
5428   if(!match) invert=1;
5429   #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5430   if(i>(ba[i]-start)>>2) invert=1;
5431   #endif
5432   #ifdef __aarch64__
5433   invert=1; // because of near cond. branches
5434   #endif
5435
5436   if(dops[i].ooo) {
5437     s1l=get_reg(branch_regs[i].regmap,dops[i].rs1);
5438     s2l=get_reg(branch_regs[i].regmap,dops[i].rs2);
5439   }
5440   else {
5441     s1l=get_reg(i_regmap,dops[i].rs1);
5442     s2l=get_reg(i_regmap,dops[i].rs2);
5443   }
5444   if(dops[i].rs1==0&&dops[i].rs2==0)
5445   {
5446     if(dops[i].opcode&1) nop=1;
5447     else unconditional=1;
5448     //assert(dops[i].opcode!=5);
5449     //assert(dops[i].opcode!=7);
5450     //assert(dops[i].opcode!=0x15);
5451     //assert(dops[i].opcode!=0x17);
5452   }
5453   else if(dops[i].rs1==0)
5454   {
5455     s1l=s2l;
5456     s2l=-1;
5457   }
5458   else if(dops[i].rs2==0)
5459   {
5460     s2l=-1;
5461   }
5462
5463   if(dops[i].ooo) {
5464     // Out of order execution (delay slot first)
5465     //printf("OOOE\n");
5466     address_generation(i+1,i_regs,regs[i].regmap_entry);
5467     ds_assemble(i+1,i_regs);
5468     int adj;
5469     uint64_t bc_unneeded=branch_regs[i].u;
5470     bc_unneeded&=~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
5471     bc_unneeded|=1;
5472     wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,bc_unneeded);
5473     load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i].rs1,dops[i].rs2);
5474     load_reg(regs[i].regmap,branch_regs[i].regmap,CCREG);
5475     cc=get_reg(branch_regs[i].regmap,CCREG);
5476     assert(cc==HOST_CCREG);
5477     if(unconditional)
5478       store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5479     //do_cc(i,branch_regs[i].regmap,&adj,unconditional?ba[i]:-1,unconditional);
5480     //assem_debug("cycle count (adj)\n");
5481     if(unconditional) {
5482       do_cc(i,branch_regs[i].regmap,&adj,ba[i],TAKEN,0);
5483       if(i!=(ba[i]-start)>>2 || source[i+1]!=0) {
5484         if(adj) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5485         load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5486         if(internal)
5487           assem_debug("branch: internal\n");
5488         else
5489           assem_debug("branch: external\n");
5490         if (internal && dops[(ba[i]-start)>>2].is_ds) {
5491           ds_assemble_entry(i);
5492         }
5493         else {
5494           add_to_linker(out,ba[i],internal);
5495           emit_jmp(0);
5496         }
5497         #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5498         if(((u_int)out)&7) emit_addnop(0);
5499         #endif
5500       }
5501     }
5502     else if(nop) {
5503       emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), cc);
5504       void *jaddr=out;
5505       emit_jns(0);
5506       add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5507     }
5508     else {
5509       void *taken = NULL, *nottaken = NULL, *nottaken1 = NULL;
5510       do_cc(i,branch_regs[i].regmap,&adj,-1,0,invert);
5511       if(adj&&!invert) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5512
5513       //printf("branch(%d): eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",i,branch_regs[i].regmap[0],branch_regs[i].regmap[1],branch_regs[i].regmap[2],branch_regs[i].regmap[3],branch_regs[i].regmap[5],branch_regs[i].regmap[6],branch_regs[i].regmap[7]);
5514       assert(s1l>=0);
5515       if(dops[i].opcode==4) // BEQ
5516       {
5517         if(s2l>=0) emit_cmp(s1l,s2l);
5518         else emit_test(s1l,s1l);
5519         if(invert){
5520           nottaken=out;
5521           emit_jne(DJT_1);
5522         }else{
5523           add_to_linker(out,ba[i],internal);
5524           emit_jeq(0);
5525         }
5526       }
5527       if(dops[i].opcode==5) // BNE
5528       {
5529         if(s2l>=0) emit_cmp(s1l,s2l);
5530         else emit_test(s1l,s1l);
5531         if(invert){
5532           nottaken=out;
5533           emit_jeq(DJT_1);
5534         }else{
5535           add_to_linker(out,ba[i],internal);
5536           emit_jne(0);
5537         }
5538       }
5539       if(dops[i].opcode==6) // BLEZ
5540       {
5541         emit_cmpimm(s1l,1);
5542         if(invert){
5543           nottaken=out;
5544           emit_jge(DJT_1);
5545         }else{
5546           add_to_linker(out,ba[i],internal);
5547           emit_jl(0);
5548         }
5549       }
5550       if(dops[i].opcode==7) // BGTZ
5551       {
5552         emit_cmpimm(s1l,1);
5553         if(invert){
5554           nottaken=out;
5555           emit_jl(DJT_1);
5556         }else{
5557           add_to_linker(out,ba[i],internal);
5558           emit_jge(0);
5559         }
5560       }
5561       if(invert) {
5562         if(taken) set_jump_target(taken, out);
5563         #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5564         if (match && (!internal || !dops[(ba[i]-start)>>2].is_ds)) {
5565           if(adj) {
5566             emit_addimm(cc,-adj,cc);
5567             add_to_linker(out,ba[i],internal);
5568           }else{
5569             emit_addnop(13);
5570             add_to_linker(out,ba[i],internal*2);
5571           }
5572           emit_jmp(0);
5573         }else
5574         #endif
5575         {
5576           if(adj) emit_addimm(cc,-adj,cc);
5577           store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5578           load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5579           if(internal)
5580             assem_debug("branch: internal\n");
5581           else
5582             assem_debug("branch: external\n");
5583           if (internal && dops[(ba[i] - start) >> 2].is_ds) {
5584             ds_assemble_entry(i);
5585           }
5586           else {
5587             add_to_linker(out,ba[i],internal);
5588             emit_jmp(0);
5589           }
5590         }
5591         set_jump_target(nottaken, out);
5592       }
5593
5594       if(nottaken1) set_jump_target(nottaken1, out);
5595       if(adj) {
5596         if(!invert) emit_addimm(cc,adj,cc);
5597       }
5598     } // (!unconditional)
5599   } // if(ooo)
5600   else
5601   {
5602     // In-order execution (branch first)
5603     void *taken = NULL, *nottaken = NULL, *nottaken1 = NULL;
5604     if(!unconditional&&!nop) {
5605       //printf("branch(%d): eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",i,branch_regs[i].regmap[0],branch_regs[i].regmap[1],branch_regs[i].regmap[2],branch_regs[i].regmap[3],branch_regs[i].regmap[5],branch_regs[i].regmap[6],branch_regs[i].regmap[7]);
5606       assert(s1l>=0);
5607       if((dops[i].opcode&0x2f)==4) // BEQ
5608       {
5609         if(s2l>=0) emit_cmp(s1l,s2l);
5610         else emit_test(s1l,s1l);
5611         nottaken=out;
5612         emit_jne(DJT_2);
5613       }
5614       if((dops[i].opcode&0x2f)==5) // BNE
5615       {
5616         if(s2l>=0) emit_cmp(s1l,s2l);
5617         else emit_test(s1l,s1l);
5618         nottaken=out;
5619         emit_jeq(DJT_2);
5620       }
5621       if((dops[i].opcode&0x2f)==6) // BLEZ
5622       {
5623         emit_cmpimm(s1l,1);
5624         nottaken=out;
5625         emit_jge(DJT_2);
5626       }
5627       if((dops[i].opcode&0x2f)==7) // BGTZ
5628       {
5629         emit_cmpimm(s1l,1);
5630         nottaken=out;
5631         emit_jl(DJT_2);
5632       }
5633     } // if(!unconditional)
5634     int adj;
5635     uint64_t ds_unneeded=branch_regs[i].u;
5636     ds_unneeded&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
5637     ds_unneeded|=1;
5638     // branch taken
5639     if(!nop) {
5640       if(taken) set_jump_target(taken, out);
5641       assem_debug("1:\n");
5642       wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,ds_unneeded);
5643       // load regs
5644       load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i+1].rs1,dops[i+1].rs2);
5645       address_generation(i+1,&branch_regs[i],0);
5646       if (ram_offset)
5647         load_reg(regs[i].regmap,branch_regs[i].regmap,ROREG);
5648       load_regs(regs[i].regmap,branch_regs[i].regmap,CCREG,INVCP);
5649       ds_assemble(i+1,&branch_regs[i]);
5650       cc=get_reg(branch_regs[i].regmap,CCREG);
5651       if(cc==-1) {
5652         emit_loadreg(CCREG,cc=HOST_CCREG);
5653         // CHECK: Is the following instruction (fall thru) allocated ok?
5654       }
5655       assert(cc==HOST_CCREG);
5656       store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5657       do_cc(i,i_regmap,&adj,ba[i],TAKEN,0);
5658       assem_debug("cycle count (adj)\n");
5659       if(adj) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5660       load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5661       if(internal)
5662         assem_debug("branch: internal\n");
5663       else
5664         assem_debug("branch: external\n");
5665       if (internal && dops[(ba[i] - start) >> 2].is_ds) {
5666         ds_assemble_entry(i);
5667       }
5668       else {
5669         add_to_linker(out,ba[i],internal);
5670         emit_jmp(0);
5671       }
5672     }
5673     // branch not taken
5674     if(!unconditional) {
5675       if(nottaken1) set_jump_target(nottaken1, out);
5676       set_jump_target(nottaken, out);
5677       assem_debug("2:\n");
5678       wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,ds_unneeded);
5679       // load regs
5680       load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i+1].rs1,dops[i+1].rs2);
5681       address_generation(i+1,&branch_regs[i],0);
5682       if (ram_offset)
5683         load_reg(regs[i].regmap,branch_regs[i].regmap,ROREG);
5684       load_regs(regs[i].regmap,branch_regs[i].regmap,CCREG,INVCP);
5685       ds_assemble(i+1,&branch_regs[i]);
5686       cc=get_reg(branch_regs[i].regmap,CCREG);
5687       if (cc == -1) {
5688         // Cycle count isn't in a register, temporarily load it then write it out
5689         emit_loadreg(CCREG,HOST_CCREG);
5690         emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), HOST_CCREG);
5691         void *jaddr=out;
5692         emit_jns(0);
5693         add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5694         emit_storereg(CCREG,HOST_CCREG);
5695       }
5696       else{
5697         cc=get_reg(i_regmap,CCREG);
5698         assert(cc==HOST_CCREG);
5699         emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), cc);
5700         void *jaddr=out;
5701         emit_jns(0);
5702         add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5703       }
5704     }
5705   }
5706 }
5707
5708 static void sjump_assemble(int i, const struct regstat *i_regs)
5709 {
5710   const signed char *i_regmap = i_regs->regmap;
5711   int cc;
5712   int match;
5713   match=match_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5714   assem_debug("smatch=%d ooo=%d\n", match, dops[i].ooo);
5715   int s1l;
5716   int unconditional=0,nevertaken=0;
5717   int invert=0;
5718   int internal=internal_branch(ba[i]);
5719   if(i==(ba[i]-start)>>2) assem_debug("idle loop\n");
5720   if(!match) invert=1;
5721   #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5722   if(i>(ba[i]-start)>>2) invert=1;
5723   #endif
5724   #ifdef __aarch64__
5725   invert=1; // because of near cond. branches
5726   #endif
5727
5728   //if(dops[i].opcode2>=0x10) return; // FIXME (BxxZAL)
5729   //assert(dops[i].opcode2<0x10||dops[i].rs1==0); // FIXME (BxxZAL)
5730
5731   if(dops[i].ooo) {
5732     s1l=get_reg(branch_regs[i].regmap,dops[i].rs1);
5733   }
5734   else {
5735     s1l=get_reg(i_regmap,dops[i].rs1);
5736   }
5737   if(dops[i].rs1==0)
5738   {
5739     if(dops[i].opcode2&1) unconditional=1;
5740     else nevertaken=1;
5741     // These are never taken (r0 is never less than zero)
5742     //assert(dops[i].opcode2!=0);
5743     //assert(dops[i].opcode2!=2);
5744     //assert(dops[i].opcode2!=0x10);
5745     //assert(dops[i].opcode2!=0x12);
5746   }
5747
5748   if(dops[i].ooo) {
5749     // Out of order execution (delay slot first)
5750     //printf("OOOE\n");
5751     address_generation(i+1,i_regs,regs[i].regmap_entry);
5752     ds_assemble(i+1,i_regs);
5753     int adj;
5754     uint64_t bc_unneeded=branch_regs[i].u;
5755     bc_unneeded&=~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
5756     bc_unneeded|=1;
5757     wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,bc_unneeded);
5758     load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i].rs1,dops[i].rs1);
5759     load_reg(regs[i].regmap,branch_regs[i].regmap,CCREG);
5760     if(dops[i].rt1==31) {
5761       int rt,return_address;
5762       rt=get_reg(branch_regs[i].regmap,31);
5763       assem_debug("branch(%d): eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",i,branch_regs[i].regmap[0],branch_regs[i].regmap[1],branch_regs[i].regmap[2],branch_regs[i].regmap[3],branch_regs[i].regmap[5],branch_regs[i].regmap[6],branch_regs[i].regmap[7]);
5764       if(rt>=0) {
5765         // Save the PC even if the branch is not taken
5766         return_address=start+i*4+8;
5767         emit_movimm(return_address,rt); // PC into link register
5768         #ifdef IMM_PREFETCH
5769         if(!nevertaken) emit_prefetch(hash_table_get(return_address));
5770         #endif
5771       }
5772     }
5773     cc=get_reg(branch_regs[i].regmap,CCREG);
5774     assert(cc==HOST_CCREG);
5775     if(unconditional)
5776       store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5777     //do_cc(i,branch_regs[i].regmap,&adj,unconditional?ba[i]:-1,unconditional);
5778     assem_debug("cycle count (adj)\n");
5779     if(unconditional) {
5780       do_cc(i,branch_regs[i].regmap,&adj,ba[i],TAKEN,0);
5781       if(i!=(ba[i]-start)>>2 || source[i+1]!=0) {
5782         if(adj) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5783         load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5784         if(internal)
5785           assem_debug("branch: internal\n");
5786         else
5787           assem_debug("branch: external\n");
5788         if (internal && dops[(ba[i] - start) >> 2].is_ds) {
5789           ds_assemble_entry(i);
5790         }
5791         else {
5792           add_to_linker(out,ba[i],internal);
5793           emit_jmp(0);
5794         }
5795         #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5796         if(((u_int)out)&7) emit_addnop(0);
5797         #endif
5798       }
5799     }
5800     else if(nevertaken) {
5801       emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), cc);
5802       void *jaddr=out;
5803       emit_jns(0);
5804       add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5805     }
5806     else {
5807       void *nottaken = NULL;
5808       do_cc(i,branch_regs[i].regmap,&adj,-1,0,invert);
5809       if(adj&&!invert) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5810       {
5811         assert(s1l>=0);
5812         if((dops[i].opcode2&0xf)==0) // BLTZ/BLTZAL
5813         {
5814           emit_test(s1l,s1l);
5815           if(invert){
5816             nottaken=out;
5817             emit_jns(DJT_1);
5818           }else{
5819             add_to_linker(out,ba[i],internal);
5820             emit_js(0);
5821           }
5822         }
5823         if((dops[i].opcode2&0xf)==1) // BGEZ/BLTZAL
5824         {
5825           emit_test(s1l,s1l);
5826           if(invert){
5827             nottaken=out;
5828             emit_js(DJT_1);
5829           }else{
5830             add_to_linker(out,ba[i],internal);
5831             emit_jns(0);
5832           }
5833         }
5834       }
5835
5836       if(invert) {
5837         #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5838         if (match && (!internal || !dops[(ba[i] - start) >> 2].is_ds)) {
5839           if(adj) {
5840             emit_addimm(cc,-adj,cc);
5841             add_to_linker(out,ba[i],internal);
5842           }else{
5843             emit_addnop(13);
5844             add_to_linker(out,ba[i],internal*2);
5845           }
5846           emit_jmp(0);
5847         }else
5848         #endif
5849         {
5850           if(adj) emit_addimm(cc,-adj,cc);
5851           store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5852           load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5853           if(internal)
5854             assem_debug("branch: internal\n");
5855           else
5856             assem_debug("branch: external\n");
5857           if (internal && dops[(ba[i] - start) >> 2].is_ds) {
5858             ds_assemble_entry(i);
5859           }
5860           else {
5861             add_to_linker(out,ba[i],internal);
5862             emit_jmp(0);
5863           }
5864         }
5865         set_jump_target(nottaken, out);
5866       }
5867
5868       if(adj) {
5869         if(!invert) emit_addimm(cc,adj,cc);
5870       }
5871     } // (!unconditional)
5872   } // if(ooo)
5873   else
5874   {
5875     // In-order execution (branch first)
5876     //printf("IOE\n");
5877     void *nottaken = NULL;
5878     if(dops[i].rt1==31) {
5879       int rt,return_address;
5880       rt=get_reg(branch_regs[i].regmap,31);
5881       if(rt>=0) {
5882         // Save the PC even if the branch is not taken
5883         return_address=start+i*4+8;
5884         emit_movimm(return_address,rt); // PC into link register
5885         #ifdef IMM_PREFETCH
5886         emit_prefetch(hash_table_get(return_address));
5887         #endif
5888       }
5889     }
5890     if(!unconditional) {
5891       //printf("branch(%d): eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",i,branch_regs[i].regmap[0],branch_regs[i].regmap[1],branch_regs[i].regmap[2],branch_regs[i].regmap[3],branch_regs[i].regmap[5],branch_regs[i].regmap[6],branch_regs[i].regmap[7]);
5892         assert(s1l>=0);
5893         if((dops[i].opcode2&0x0d)==0) // BLTZ/BLTZL/BLTZAL/BLTZALL
5894         {
5895           emit_test(s1l,s1l);
5896           nottaken=out;
5897           emit_jns(DJT_1);
5898         }
5899         if((dops[i].opcode2&0x0d)==1) // BGEZ/BGEZL/BGEZAL/BGEZALL
5900         {
5901           emit_test(s1l,s1l);
5902           nottaken=out;
5903           emit_js(DJT_1);
5904         }
5905     } // if(!unconditional)
5906     int adj;
5907     uint64_t ds_unneeded=branch_regs[i].u;
5908     ds_unneeded&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
5909     ds_unneeded|=1;
5910     // branch taken
5911     if(!nevertaken) {
5912       //assem_debug("1:\n");
5913       wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,ds_unneeded);
5914       // load regs
5915       load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i+1].rs1,dops[i+1].rs2);
5916       address_generation(i+1,&branch_regs[i],0);
5917       if (ram_offset)
5918         load_reg(regs[i].regmap,branch_regs[i].regmap,ROREG);
5919       load_regs(regs[i].regmap,branch_regs[i].regmap,CCREG,INVCP);
5920       ds_assemble(i+1,&branch_regs[i]);
5921       cc=get_reg(branch_regs[i].regmap,CCREG);
5922       if(cc==-1) {
5923         emit_loadreg(CCREG,cc=HOST_CCREG);
5924         // CHECK: Is the following instruction (fall thru) allocated ok?
5925       }
5926       assert(cc==HOST_CCREG);
5927       store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5928       do_cc(i,i_regmap,&adj,ba[i],TAKEN,0);
5929       assem_debug("cycle count (adj)\n");
5930       if(adj) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5931       load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5932       if(internal)
5933         assem_debug("branch: internal\n");
5934       else
5935         assem_debug("branch: external\n");
5936       if (internal && dops[(ba[i] - start) >> 2].is_ds) {
5937         ds_assemble_entry(i);
5938       }
5939       else {
5940         add_to_linker(out,ba[i],internal);
5941         emit_jmp(0);
5942       }
5943     }
5944     // branch not taken
5945     if(!unconditional) {
5946       set_jump_target(nottaken, out);
5947       assem_debug("1:\n");
5948       wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,ds_unneeded);
5949       load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i+1].rs1,dops[i+1].rs2);
5950       address_generation(i+1,&branch_regs[i],0);
5951       if (ram_offset)
5952         load_reg(regs[i].regmap,branch_regs[i].regmap,ROREG);
5953       load_regs(regs[i].regmap,branch_regs[i].regmap,CCREG,INVCP);
5954       ds_assemble(i+1,&branch_regs[i]);
5955       cc=get_reg(branch_regs[i].regmap,CCREG);
5956       if (cc == -1) {
5957         // Cycle count isn't in a register, temporarily load it then write it out
5958         emit_loadreg(CCREG,HOST_CCREG);
5959         emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), HOST_CCREG);
5960         void *jaddr=out;
5961         emit_jns(0);
5962         add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5963         emit_storereg(CCREG,HOST_CCREG);
5964       }
5965       else{
5966         cc=get_reg(i_regmap,CCREG);
5967         assert(cc==HOST_CCREG);
5968         emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), cc);
5969         void *jaddr=out;
5970         emit_jns(0);
5971         add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5972       }
5973     }
5974   }
5975 }
5976
5977 static void check_regmap(signed char *regmap)
5978 {
5979 #ifndef NDEBUG
5980   int i,j;
5981   for (i = 0; i < HOST_REGS; i++) {
5982     if (regmap[i] < 0)
5983       continue;
5984     for (j = i + 1; j < HOST_REGS; j++)
5985       assert(regmap[i] != regmap[j]);
5986   }
5987 #endif
5988 }
5989
5990 #ifdef DISASM
5991 #include <inttypes.h>
5992 static char insn[MAXBLOCK][10];
5993
5994 #define set_mnemonic(i_, n_) \
5995   strcpy(insn[i_], n_)
5996
5997 void print_regmap(const char *name, const signed char *regmap)
5998 {
5999   char buf[5];
6000   int i, l;
6001   fputs(name, stdout);
6002   for (i = 0; i < HOST_REGS; i++) {
6003     l = 0;
6004     if (regmap[i] >= 0)
6005       l = snprintf(buf, sizeof(buf), "$%d", regmap[i]);
6006     for (; l < 3; l++)
6007       buf[l] = ' ';
6008     buf[l] = 0;
6009     printf(" r%d=%s", i, buf);
6010   }
6011   fputs("\n", stdout);
6012 }
6013
6014   /* disassembly */
6015 void disassemble_inst(int i)
6016 {
6017     if (dops[i].bt) printf("*"); else printf(" ");
6018     switch(dops[i].itype) {
6019       case UJUMP:
6020         printf (" %x: %s %8x\n",start+i*4,insn[i],ba[i]);break;
6021       case CJUMP:
6022         printf (" %x: %s r%d,r%d,%8x\n",start+i*4,insn[i],dops[i].rs1,dops[i].rs2,i?start+i*4+4+((signed int)((unsigned int)source[i]<<16)>>14):*ba);break;
6023       case SJUMP:
6024         printf (" %x: %s r%d,%8x\n",start+i*4,insn[i],dops[i].rs1,start+i*4+4+((signed int)((unsigned int)source[i]<<16)>>14));break;
6025       case RJUMP:
6026         if (dops[i].opcode==0x9&&dops[i].rt1!=31)
6027           printf (" %x: %s r%d,r%d\n",start+i*4,insn[i],dops[i].rt1,dops[i].rs1);
6028         else
6029           printf (" %x: %s r%d\n",start+i*4,insn[i],dops[i].rs1);
6030         break;
6031       case IMM16:
6032         if(dops[i].opcode==0xf) //LUI
6033           printf (" %x: %s r%d,%4x0000\n",start+i*4,insn[i],dops[i].rt1,imm[i]&0xffff);
6034         else
6035           printf (" %x: %s r%d,r%d,%d\n",start+i*4,insn[i],dops[i].rt1,dops[i].rs1,imm[i]);
6036         break;
6037       case LOAD:
6038       case LOADLR:
6039         printf (" %x: %s r%d,r%d+%x\n",start+i*4,insn[i],dops[i].rt1,dops[i].rs1,imm[i]);
6040         break;
6041       case STORE:
6042       case STORELR:
6043         printf (" %x: %s r%d,r%d+%x\n",start+i*4,insn[i],dops[i].rs2,dops[i].rs1,imm[i]);
6044         break;
6045       case ALU:
6046       case SHIFT:
6047         printf (" %x: %s r%d,r%d,r%d\n",start+i*4,insn[i],dops[i].rt1,dops[i].rs1,dops[i].rs2);
6048         break;
6049       case MULTDIV:
6050         printf (" %x: %s r%d,r%d\n",start+i*4,insn[i],dops[i].rs1,dops[i].rs2);
6051         break;
6052       case SHIFTIMM:
6053         printf (" %x: %s r%d,r%d,%d\n",start+i*4,insn[i],dops[i].rt1,dops[i].rs1,imm[i]);
6054         break;
6055       case MOV:
6056         if((dops[i].opcode2&0x1d)==0x10)
6057           printf (" %x: %s r%d\n",start+i*4,insn[i],dops[i].rt1);
6058         else if((dops[i].opcode2&0x1d)==0x11)
6059           printf (" %x: %s r%d\n",start+i*4,insn[i],dops[i].rs1);
6060         else
6061           printf (" %x: %s\n",start+i*4,insn[i]);
6062         break;
6063       case COP0:
6064         if(dops[i].opcode2==0)
6065           printf (" %x: %s r%d,cpr0[%d]\n",start+i*4,insn[i],dops[i].rt1,(source[i]>>11)&0x1f); // MFC0
6066         else if(dops[i].opcode2==4)
6067           printf (" %x: %s r%d,cpr0[%d]\n",start+i*4,insn[i],dops[i].rs1,(source[i]>>11)&0x1f); // MTC0
6068         else printf (" %x: %s\n",start+i*4,insn[i]);
6069         break;
6070       case COP1:
6071         if(dops[i].opcode2<3)
6072           printf (" %x: %s r%d,cpr1[%d]\n",start+i*4,insn[i],dops[i].rt1,(source[i]>>11)&0x1f); // MFC1
6073         else if(dops[i].opcode2>3)
6074           printf (" %x: %s r%d,cpr1[%d]\n",start+i*4,insn[i],dops[i].rs1,(source[i]>>11)&0x1f); // MTC1
6075         else printf (" %x: %s\n",start+i*4,insn[i]);
6076         break;
6077       case COP2:
6078         if(dops[i].opcode2<3)
6079           printf (" %x: %s r%d,cpr2[%d]\n",start+i*4,insn[i],dops[i].rt1,(source[i]>>11)&0x1f); // MFC2
6080         else if(dops[i].opcode2>3)
6081           printf (" %x: %s r%d,cpr2[%d]\n",start+i*4,insn[i],dops[i].rs1,(source[i]>>11)&0x1f); // MTC2
6082         else printf (" %x: %s\n",start+i*4,insn[i]);
6083         break;
6084       case C1LS:
6085         printf (" %x: %s cpr1[%d],r%d+%x\n",start+i*4,insn[i],(source[i]>>16)&0x1f,dops[i].rs1,imm[i]);
6086         break;
6087       case C2LS:
6088         printf (" %x: %s cpr2[%d],r%d+%x\n",start+i*4,insn[i],(source[i]>>16)&0x1f,dops[i].rs1,imm[i]);
6089         break;
6090       case INTCALL:
6091         printf (" %x: %s (INTCALL)\n",start+i*4,insn[i]);
6092         break;
6093       default:
6094         //printf (" %s %8x\n",insn[i],source[i]);
6095         printf (" %x: %s\n",start+i*4,insn[i]);
6096     }
6097     return;
6098     printf("D: %"PRIu64"  WD: %"PRIu64"  U: %"PRIu64"\n",
6099       regs[i].dirty, regs[i].wasdirty, unneeded_reg[i]);
6100     print_regmap("pre:   ", regmap_pre[i]);
6101     print_regmap("entry: ", regs[i].regmap_entry);
6102     print_regmap("map:   ", regs[i].regmap);
6103     if (dops[i].is_jump) {
6104       print_regmap("bentry:", branch_regs[i].regmap_entry);
6105       print_regmap("bmap:  ", branch_regs[i].regmap);
6106     }
6107 }
6108 #else
6109 #define set_mnemonic(i_, n_)
6110 static void disassemble_inst(int i) {}
6111 #endif // DISASM
6112
6113 #define DRC_TEST_VAL 0x74657374
6114
6115 static noinline void new_dynarec_test(void)
6116 {
6117   int (*testfunc)(void);
6118   void *beginning;
6119   int ret[2];
6120   size_t i;
6121
6122   // check structure linkage
6123   if ((u_char *)rcnts - (u_char *)&psxRegs != sizeof(psxRegs))
6124   {
6125     SysPrintf("linkage_arm* miscompilation/breakage detected.\n");
6126   }
6127
6128   SysPrintf("(%p) testing if we can run recompiled code @%p...\n",
6129     new_dynarec_test, out);
6130   ((volatile u_int *)NDRC_WRITE_OFFSET(out))[0]++; // make the cache dirty
6131
6132   for (i = 0; i < ARRAY_SIZE(ret); i++) {
6133     out = ndrc->translation_cache;
6134     beginning = start_block();
6135     emit_movimm(DRC_TEST_VAL + i, 0); // test
6136     emit_ret();
6137     literal_pool(0);
6138     end_block(beginning);
6139     testfunc = beginning;
6140     ret[i] = testfunc();
6141   }
6142
6143   if (ret[0] == DRC_TEST_VAL && ret[1] == DRC_TEST_VAL + 1)
6144     SysPrintf("test passed.\n");
6145   else
6146     SysPrintf("test failed, will likely crash soon (r=%08x %08x)\n", ret[0], ret[1]);
6147   out = ndrc->translation_cache;
6148 }
6149
6150 // clear the state completely, instead of just marking
6151 // things invalid like invalidate_all_pages() does
6152 void new_dynarec_clear_full(void)
6153 {
6154   int n;
6155   out = ndrc->translation_cache;
6156   memset(invalid_code,1,sizeof(invalid_code));
6157   memset(hash_table,0xff,sizeof(hash_table));
6158   memset(mini_ht,-1,sizeof(mini_ht));
6159   memset(shadow,0,sizeof(shadow));
6160   copy=shadow;
6161   expirep = EXPIRITY_OFFSET;
6162   pending_exception=0;
6163   literalcount=0;
6164   stop_after_jal=0;
6165   inv_code_start=inv_code_end=~0;
6166   hack_addr=0;
6167   f1_hack=0;
6168   for (n = 0; n < ARRAY_SIZE(blocks); n++)
6169     blocks_clear(&blocks[n]);
6170   for (n = 0; n < ARRAY_SIZE(jumps); n++) {
6171     free(jumps[n]);
6172     jumps[n] = NULL;
6173   }
6174   stat_clear(stat_blocks);
6175   stat_clear(stat_links);
6176
6177   cycle_multiplier_old = cycle_multiplier;
6178   new_dynarec_hacks_old = new_dynarec_hacks;
6179 }
6180
6181 void new_dynarec_init(void)
6182 {
6183   SysPrintf("Init new dynarec, ndrc size %x\n", (int)sizeof(*ndrc));
6184
6185 #ifdef _3DS
6186   check_rosalina();
6187 #endif
6188 #ifdef BASE_ADDR_DYNAMIC
6189   #ifdef VITA
6190   sceBlock = getVMBlock(); //sceKernelAllocMemBlockForVM("code", sizeof(*ndrc));
6191   if (sceBlock <= 0)
6192     SysPrintf("sceKernelAllocMemBlockForVM failed: %x\n", sceBlock);
6193   int ret = sceKernelGetMemBlockBase(sceBlock, (void **)&ndrc);
6194   if (ret < 0)
6195     SysPrintf("sceKernelGetMemBlockBase failed: %x\n", ret);
6196   sceKernelOpenVMDomain();
6197   sceClibPrintf("translation_cache = 0x%08lx\n ", (long)ndrc->translation_cache);
6198   #elif defined(_MSC_VER)
6199   ndrc = VirtualAlloc(NULL, sizeof(*ndrc), MEM_COMMIT | MEM_RESERVE,
6200     PAGE_EXECUTE_READWRITE);
6201   #elif defined(HAVE_LIBNX)
6202   Result rc = jitCreate(&g_jit, sizeof(*ndrc));
6203   if (R_FAILED(rc))
6204     SysPrintf("jitCreate failed: %08x\n", rc);
6205   SysPrintf("jitCreate: RX: %p RW: %p type: %d\n", g_jit.rx_addr, g_jit.rw_addr, g_jit.type);
6206   jitTransitionToWritable(&g_jit);
6207   ndrc = g_jit.rx_addr;
6208   ndrc_write_ofs = (char *)g_jit.rw_addr - (char *)ndrc;
6209   memset(NDRC_WRITE_OFFSET(&ndrc->tramp), 0, sizeof(ndrc->tramp));
6210   #else
6211   uintptr_t desired_addr = 0;
6212   int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
6213   int flags = MAP_PRIVATE | MAP_ANONYMOUS;
6214   int fd = -1;
6215   #ifdef __ELF__
6216   extern char _end;
6217   desired_addr = ((uintptr_t)&_end + 0xffffff) & ~0xffffffl;
6218   #endif
6219   #ifdef TC_WRITE_OFFSET
6220   // mostly for testing
6221   fd = open("/dev/shm/pcsxr", O_CREAT | O_RDWR, 0600);
6222   ftruncate(fd, sizeof(*ndrc));
6223   void *mw = mmap(NULL, sizeof(*ndrc), PROT_READ | PROT_WRITE,
6224                   (flags = MAP_SHARED), fd, 0);
6225   assert(mw != MAP_FAILED);
6226   prot = PROT_READ | PROT_EXEC;
6227   #endif
6228   ndrc = mmap((void *)desired_addr, sizeof(*ndrc), prot, flags, fd, 0);
6229   if (ndrc == MAP_FAILED) {
6230     SysPrintf("mmap() failed: %s\n", strerror(errno));
6231     abort();
6232   }
6233   #ifdef TC_WRITE_OFFSET
6234   ndrc_write_ofs = (char *)mw - (char *)ndrc;
6235   #endif
6236   #endif
6237 #else
6238   #ifndef NO_WRITE_EXEC
6239   // not all systems allow execute in data segment by default
6240   // size must be 4K aligned for 3DS?
6241   if (mprotect(ndrc, sizeof(*ndrc),
6242                PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
6243     SysPrintf("mprotect() failed: %s\n", strerror(errno));
6244   #endif
6245 #endif
6246   out = ndrc->translation_cache;
6247   cycle_multiplier=200;
6248   new_dynarec_clear_full();
6249 #ifdef HOST_IMM8
6250   // Copy this into local area so we don't have to put it in every literal pool
6251   invc_ptr=invalid_code;
6252 #endif
6253   arch_init();
6254   new_dynarec_test();
6255   ram_offset=(uintptr_t)rdram-0x80000000;
6256   if (ram_offset!=0)
6257     SysPrintf("warning: RAM is not directly mapped, performance will suffer\n");
6258   SysPrintf("Mapped (RAM/scrp/ROM/LUTs/TC):\n");
6259   SysPrintf("%p/%p/%p/%p/%p\n", psxM, psxH, psxR, mem_rtab, out);
6260 }
6261
6262 void new_dynarec_cleanup(void)
6263 {
6264   int n;
6265 #ifdef BASE_ADDR_DYNAMIC
6266   #ifdef VITA
6267   // sceBlock is managed by retroarch's bootstrap code
6268   //sceKernelFreeMemBlock(sceBlock);
6269   //sceBlock = -1;
6270   #elif defined(HAVE_LIBNX)
6271   jitClose(&g_jit);
6272   ndrc = NULL;
6273   #else
6274   if (munmap(ndrc, sizeof(*ndrc)) < 0)
6275     SysPrintf("munmap() failed\n");
6276   ndrc = NULL;
6277   #endif
6278 #endif
6279   for (n = 0; n < ARRAY_SIZE(blocks); n++)
6280     blocks_clear(&blocks[n]);
6281   for (n = 0; n < ARRAY_SIZE(jumps); n++) {
6282     free(jumps[n]);
6283     jumps[n] = NULL;
6284   }
6285   stat_clear(stat_blocks);
6286   stat_clear(stat_links);
6287   new_dynarec_print_stats();
6288 }
6289
6290 static u_int *get_source_start(u_int addr, u_int *limit)
6291 {
6292   if (addr < 0x00200000 ||
6293     (0xa0000000 <= addr && addr < 0xa0200000))
6294   {
6295     // used for BIOS calls mostly?
6296     *limit = (addr&0xa0000000)|0x00200000;
6297     return (u_int *)(rdram + (addr&0x1fffff));
6298   }
6299   else if (!Config.HLE && (
6300     /* (0x9fc00000 <= addr && addr < 0x9fc80000) ||*/
6301     (0xbfc00000 <= addr && addr < 0xbfc80000)))
6302   {
6303     // BIOS. The multiplier should be much higher as it's uncached 8bit mem,
6304     // but timings in PCSX are too tied to the interpreter's BIAS
6305     if (!HACK_ENABLED(NDHACK_OVERRIDE_CYCLE_M))
6306       cycle_multiplier_active = 200;
6307
6308     *limit = (addr & 0xfff00000) | 0x80000;
6309     return (u_int *)((u_char *)psxR + (addr&0x7ffff));
6310   }
6311   else if (addr >= 0x80000000 && addr < 0x80000000+RAM_SIZE) {
6312     *limit = (addr & 0x80600000) + 0x00200000;
6313     return (u_int *)(rdram + (addr&0x1fffff));
6314   }
6315   return NULL;
6316 }
6317
6318 static u_int scan_for_ret(u_int addr)
6319 {
6320   u_int limit = 0;
6321   u_int *mem;
6322
6323   mem = get_source_start(addr, &limit);
6324   if (mem == NULL)
6325     return addr;
6326
6327   if (limit > addr + 0x1000)
6328     limit = addr + 0x1000;
6329   for (; addr < limit; addr += 4, mem++) {
6330     if (*mem == 0x03e00008) // jr $ra
6331       return addr + 8;
6332   }
6333   return addr;
6334 }
6335
6336 struct savestate_block {
6337   uint32_t addr;
6338   uint32_t regflags;
6339 };
6340
6341 static int addr_cmp(const void *p1_, const void *p2_)
6342 {
6343   const struct savestate_block *p1 = p1_, *p2 = p2_;
6344   return p1->addr - p2->addr;
6345 }
6346
6347 int new_dynarec_save_blocks(void *save, int size)
6348 {
6349   struct savestate_block *sblocks = save;
6350   int maxcount = size / sizeof(sblocks[0]);
6351   struct savestate_block tmp_blocks[1024];
6352   struct block_info *block;
6353   int p, s, d, o, bcnt;
6354   u_int addr;
6355
6356   o = 0;
6357   for (p = 0; p < ARRAY_SIZE(blocks); p++) {
6358     bcnt = 0;
6359     for (block = blocks[p]; block != NULL; block = block->next) {
6360       if (block->is_dirty)
6361         continue;
6362       tmp_blocks[bcnt].addr = block->start;
6363       tmp_blocks[bcnt].regflags = block->reg_sv_flags;
6364       bcnt++;
6365     }
6366     if (bcnt < 1)
6367       continue;
6368     qsort(tmp_blocks, bcnt, sizeof(tmp_blocks[0]), addr_cmp);
6369
6370     addr = tmp_blocks[0].addr;
6371     for (s = d = 0; s < bcnt; s++) {
6372       if (tmp_blocks[s].addr < addr)
6373         continue;
6374       if (d == 0 || tmp_blocks[d-1].addr != tmp_blocks[s].addr)
6375         tmp_blocks[d++] = tmp_blocks[s];
6376       addr = scan_for_ret(tmp_blocks[s].addr);
6377     }
6378
6379     if (o + d > maxcount)
6380       d = maxcount - o;
6381     memcpy(&sblocks[o], tmp_blocks, d * sizeof(sblocks[0]));
6382     o += d;
6383   }
6384
6385   return o * sizeof(sblocks[0]);
6386 }
6387
6388 void new_dynarec_load_blocks(const void *save, int size)
6389 {
6390   const struct savestate_block *sblocks = save;
6391   int count = size / sizeof(sblocks[0]);
6392   struct block_info *block;
6393   u_int regs_save[32];
6394   u_int page;
6395   uint32_t f;
6396   int i, b;
6397
6398   // restore clean blocks, if any
6399   for (page = 0, b = i = 0; page < ARRAY_SIZE(blocks); page++) {
6400     for (block = blocks[page]; block != NULL; block = block->next, b++) {
6401       if (!block->is_dirty)
6402         continue;
6403       assert(block->source && block->copy);
6404       if (memcmp(block->source, block->copy, block->len))
6405         continue;
6406
6407       // see try_restore_block
6408       block->is_dirty = 0;
6409       mark_invalid_code(block->start, block->len, 0);
6410       i++;
6411     }
6412   }
6413   inv_debug("load_blocks: %d/%d clean blocks\n", i, b);
6414
6415   // change GPRs for speculation to at least partially work..
6416   memcpy(regs_save, &psxRegs.GPR, sizeof(regs_save));
6417   for (i = 1; i < 32; i++)
6418     psxRegs.GPR.r[i] = 0x80000000;
6419
6420   for (b = 0; b < count; b++) {
6421     for (f = sblocks[b].regflags, i = 0; f; f >>= 1, i++) {
6422       if (f & 1)
6423         psxRegs.GPR.r[i] = 0x1f800000;
6424     }
6425
6426     ndrc_get_addr_ht(sblocks[b].addr);
6427
6428     for (f = sblocks[b].regflags, i = 0; f; f >>= 1, i++) {
6429       if (f & 1)
6430         psxRegs.GPR.r[i] = 0x80000000;
6431     }
6432   }
6433
6434   memcpy(&psxRegs.GPR, regs_save, sizeof(regs_save));
6435 }
6436
6437 void new_dynarec_print_stats(void)
6438 {
6439 #ifdef STAT_PRINT
6440   printf("cc %3d,%3d,%3d lu%6d,%3d,%3d c%3d inv%3d,%3d tc_offs %zu b %u,%u\n",
6441     stat_bc_pre, stat_bc_direct, stat_bc_restore,
6442     stat_ht_lookups, stat_jump_in_lookups, stat_restore_tries,
6443     stat_restore_compares, stat_inv_addr_calls, stat_inv_hits,
6444     out - ndrc->translation_cache, stat_blocks, stat_links);
6445   stat_bc_direct = stat_bc_pre = stat_bc_restore =
6446   stat_ht_lookups = stat_jump_in_lookups = stat_restore_tries =
6447   stat_restore_compares = stat_inv_addr_calls = stat_inv_hits = 0;
6448 #endif
6449 }
6450
6451 static int apply_hacks(void)
6452 {
6453   int i;
6454   if (HACK_ENABLED(NDHACK_NO_COMPAT_HACKS))
6455     return 0;
6456   /* special hack(s) */
6457   for (i = 0; i < slen - 4; i++)
6458   {
6459     // lui a4, 0xf200; jal <rcnt_read>; addu a0, 2; slti v0, 28224
6460     if (source[i] == 0x3c04f200 && dops[i+1].itype == UJUMP
6461         && source[i+2] == 0x34840002 && dops[i+3].opcode == 0x0a
6462         && imm[i+3] == 0x6e40 && dops[i+3].rs1 == 2)
6463     {
6464       SysPrintf("PE2 hack @%08x\n", start + (i+3)*4);
6465       dops[i + 3].itype = NOP;
6466     }
6467   }
6468   i = slen;
6469   if (i > 10 && source[i-1] == 0 && source[i-2] == 0x03e00008
6470       && source[i-4] == 0x8fbf0018 && source[i-6] == 0x00c0f809
6471       && dops[i-7].itype == STORE)
6472   {
6473     i = i-8;
6474     if (dops[i].itype == IMM16)
6475       i--;
6476     // swl r2, 15(r6); swr r2, 12(r6); sw r6, *; jalr r6
6477     if (dops[i].itype == STORELR && dops[i].rs1 == 6
6478       && dops[i-1].itype == STORELR && dops[i-1].rs1 == 6)
6479     {
6480       SysPrintf("F1 hack from %08x, old dst %08x\n", start, hack_addr);
6481       f1_hack = 1;
6482       return 1;
6483     }
6484   }
6485   return 0;
6486 }
6487
6488 static noinline void pass1_disassemble(u_int pagelimit)
6489 {
6490   int i, j, done = 0, ni_count = 0;
6491   unsigned int type,op,op2;
6492
6493   for (i = 0; !done; i++)
6494   {
6495     memset(&dops[i], 0, sizeof(dops[i]));
6496     op2=0;
6497     minimum_free_regs[i]=0;
6498     dops[i].opcode=op=source[i]>>26;
6499     switch(op)
6500     {
6501       case 0x00: set_mnemonic(i, "special"); type=NI;
6502         op2=source[i]&0x3f;
6503         switch(op2)
6504         {
6505           case 0x00: set_mnemonic(i, "SLL"); type=SHIFTIMM; break;
6506           case 0x02: set_mnemonic(i, "SRL"); type=SHIFTIMM; break;
6507           case 0x03: set_mnemonic(i, "SRA"); type=SHIFTIMM; break;
6508           case 0x04: set_mnemonic(i, "SLLV"); type=SHIFT; break;
6509           case 0x06: set_mnemonic(i, "SRLV"); type=SHIFT; break;
6510           case 0x07: set_mnemonic(i, "SRAV"); type=SHIFT; break;
6511           case 0x08: set_mnemonic(i, "JR"); type=RJUMP; break;
6512           case 0x09: set_mnemonic(i, "JALR"); type=RJUMP; break;
6513           case 0x0C: set_mnemonic(i, "SYSCALL"); type=SYSCALL; break;
6514           case 0x0D: set_mnemonic(i, "BREAK"); type=SYSCALL; break;
6515           case 0x0F: set_mnemonic(i, "SYNC"); type=OTHER; break;
6516           case 0x10: set_mnemonic(i, "MFHI"); type=MOV; break;
6517           case 0x11: set_mnemonic(i, "MTHI"); type=MOV; break;
6518           case 0x12: set_mnemonic(i, "MFLO"); type=MOV; break;
6519           case 0x13: set_mnemonic(i, "MTLO"); type=MOV; break;
6520           case 0x18: set_mnemonic(i, "MULT"); type=MULTDIV; break;
6521           case 0x19: set_mnemonic(i, "MULTU"); type=MULTDIV; break;
6522           case 0x1A: set_mnemonic(i, "DIV"); type=MULTDIV; break;
6523           case 0x1B: set_mnemonic(i, "DIVU"); type=MULTDIV; break;
6524           case 0x20: set_mnemonic(i, "ADD"); type=ALU; break;
6525           case 0x21: set_mnemonic(i, "ADDU"); type=ALU; break;
6526           case 0x22: set_mnemonic(i, "SUB"); type=ALU; break;
6527           case 0x23: set_mnemonic(i, "SUBU"); type=ALU; break;
6528           case 0x24: set_mnemonic(i, "AND"); type=ALU; break;
6529           case 0x25: set_mnemonic(i, "OR"); type=ALU; break;
6530           case 0x26: set_mnemonic(i, "XOR"); type=ALU; break;
6531           case 0x27: set_mnemonic(i, "NOR"); type=ALU; break;
6532           case 0x2A: set_mnemonic(i, "SLT"); type=ALU; break;
6533           case 0x2B: set_mnemonic(i, "SLTU"); type=ALU; break;
6534           case 0x30: set_mnemonic(i, "TGE"); type=NI; break;
6535           case 0x31: set_mnemonic(i, "TGEU"); type=NI; break;
6536           case 0x32: set_mnemonic(i, "TLT"); type=NI; break;
6537           case 0x33: set_mnemonic(i, "TLTU"); type=NI; break;
6538           case 0x34: set_mnemonic(i, "TEQ"); type=NI; break;
6539           case 0x36: set_mnemonic(i, "TNE"); type=NI; break;
6540 #if 0
6541           case 0x14: set_mnemonic(i, "DSLLV"); type=SHIFT; break;
6542           case 0x16: set_mnemonic(i, "DSRLV"); type=SHIFT; break;
6543           case 0x17: set_mnemonic(i, "DSRAV"); type=SHIFT; break;
6544           case 0x1C: set_mnemonic(i, "DMULT"); type=MULTDIV; break;
6545           case 0x1D: set_mnemonic(i, "DMULTU"); type=MULTDIV; break;
6546           case 0x1E: set_mnemonic(i, "DDIV"); type=MULTDIV; break;
6547           case 0x1F: set_mnemonic(i, "DDIVU"); type=MULTDIV; break;
6548           case 0x2C: set_mnemonic(i, "DADD"); type=ALU; break;
6549           case 0x2D: set_mnemonic(i, "DADDU"); type=ALU; break;
6550           case 0x2E: set_mnemonic(i, "DSUB"); type=ALU; break;
6551           case 0x2F: set_mnemonic(i, "DSUBU"); type=ALU; break;
6552           case 0x38: set_mnemonic(i, "DSLL"); type=SHIFTIMM; break;
6553           case 0x3A: set_mnemonic(i, "DSRL"); type=SHIFTIMM; break;
6554           case 0x3B: set_mnemonic(i, "DSRA"); type=SHIFTIMM; break;
6555           case 0x3C: set_mnemonic(i, "DSLL32"); type=SHIFTIMM; break;
6556           case 0x3E: set_mnemonic(i, "DSRL32"); type=SHIFTIMM; break;
6557           case 0x3F: set_mnemonic(i, "DSRA32"); type=SHIFTIMM; break;
6558 #endif
6559         }
6560         break;
6561       case 0x01: set_mnemonic(i, "regimm"); type=NI;
6562         op2=(source[i]>>16)&0x1f;
6563         switch(op2)
6564         {
6565           case 0x00: set_mnemonic(i, "BLTZ"); type=SJUMP; break;
6566           case 0x01: set_mnemonic(i, "BGEZ"); type=SJUMP; break;
6567           //case 0x02: set_mnemonic(i, "BLTZL"); type=SJUMP; break;
6568           //case 0x03: set_mnemonic(i, "BGEZL"); type=SJUMP; break;
6569           //case 0x08: set_mnemonic(i, "TGEI"); type=NI; break;
6570           //case 0x09: set_mnemonic(i, "TGEIU"); type=NI; break;
6571           //case 0x0A: set_mnemonic(i, "TLTI"); type=NI; break;
6572           //case 0x0B: set_mnemonic(i, "TLTIU"); type=NI; break;
6573           //case 0x0C: set_mnemonic(i, "TEQI"); type=NI; break;
6574           //case 0x0E: set_mnemonic(i, "TNEI"); type=NI; break;
6575           case 0x10: set_mnemonic(i, "BLTZAL"); type=SJUMP; break;
6576           case 0x11: set_mnemonic(i, "BGEZAL"); type=SJUMP; break;
6577           //case 0x12: set_mnemonic(i, "BLTZALL"); type=SJUMP; break;
6578           //case 0x13: set_mnemonic(i, "BGEZALL"); type=SJUMP; break;
6579         }
6580         break;
6581       case 0x02: set_mnemonic(i, "J"); type=UJUMP; break;
6582       case 0x03: set_mnemonic(i, "JAL"); type=UJUMP; break;
6583       case 0x04: set_mnemonic(i, "BEQ"); type=CJUMP; break;
6584       case 0x05: set_mnemonic(i, "BNE"); type=CJUMP; break;
6585       case 0x06: set_mnemonic(i, "BLEZ"); type=CJUMP; break;
6586       case 0x07: set_mnemonic(i, "BGTZ"); type=CJUMP; break;
6587       case 0x08: set_mnemonic(i, "ADDI"); type=IMM16; break;
6588       case 0x09: set_mnemonic(i, "ADDIU"); type=IMM16; break;
6589       case 0x0A: set_mnemonic(i, "SLTI"); type=IMM16; break;
6590       case 0x0B: set_mnemonic(i, "SLTIU"); type=IMM16; break;
6591       case 0x0C: set_mnemonic(i, "ANDI"); type=IMM16; break;
6592       case 0x0D: set_mnemonic(i, "ORI"); type=IMM16; break;
6593       case 0x0E: set_mnemonic(i, "XORI"); type=IMM16; break;
6594       case 0x0F: set_mnemonic(i, "LUI"); type=IMM16; break;
6595       case 0x10: set_mnemonic(i, "cop0"); type=NI;
6596         op2=(source[i]>>21)&0x1f;
6597         switch(op2)
6598         {
6599           case 0x00: set_mnemonic(i, "MFC0"); type=COP0; break;
6600           case 0x02: set_mnemonic(i, "CFC0"); type=COP0; break;
6601           case 0x04: set_mnemonic(i, "MTC0"); type=COP0; break;
6602           case 0x06: set_mnemonic(i, "CTC0"); type=COP0; break;
6603           case 0x10: set_mnemonic(i, "RFE"); type=COP0; break;
6604         }
6605         break;
6606       case 0x11: set_mnemonic(i, "cop1"); type=COP1;
6607         op2=(source[i]>>21)&0x1f;
6608         break;
6609 #if 0
6610       case 0x14: set_mnemonic(i, "BEQL"); type=CJUMP; break;
6611       case 0x15: set_mnemonic(i, "BNEL"); type=CJUMP; break;
6612       case 0x16: set_mnemonic(i, "BLEZL"); type=CJUMP; break;
6613       case 0x17: set_mnemonic(i, "BGTZL"); type=CJUMP; break;
6614       case 0x18: set_mnemonic(i, "DADDI"); type=IMM16; break;
6615       case 0x19: set_mnemonic(i, "DADDIU"); type=IMM16; break;
6616       case 0x1A: set_mnemonic(i, "LDL"); type=LOADLR; break;
6617       case 0x1B: set_mnemonic(i, "LDR"); type=LOADLR; break;
6618 #endif
6619       case 0x20: set_mnemonic(i, "LB"); type=LOAD; break;
6620       case 0x21: set_mnemonic(i, "LH"); type=LOAD; break;
6621       case 0x22: set_mnemonic(i, "LWL"); type=LOADLR; break;
6622       case 0x23: set_mnemonic(i, "LW"); type=LOAD; break;
6623       case 0x24: set_mnemonic(i, "LBU"); type=LOAD; break;
6624       case 0x25: set_mnemonic(i, "LHU"); type=LOAD; break;
6625       case 0x26: set_mnemonic(i, "LWR"); type=LOADLR; break;
6626 #if 0
6627       case 0x27: set_mnemonic(i, "LWU"); type=LOAD; break;
6628 #endif
6629       case 0x28: set_mnemonic(i, "SB"); type=STORE; break;
6630       case 0x29: set_mnemonic(i, "SH"); type=STORE; break;
6631       case 0x2A: set_mnemonic(i, "SWL"); type=STORELR; break;
6632       case 0x2B: set_mnemonic(i, "SW"); type=STORE; break;
6633 #if 0
6634       case 0x2C: set_mnemonic(i, "SDL"); type=STORELR; break;
6635       case 0x2D: set_mnemonic(i, "SDR"); type=STORELR; break;
6636 #endif
6637       case 0x2E: set_mnemonic(i, "SWR"); type=STORELR; break;
6638       case 0x2F: set_mnemonic(i, "CACHE"); type=NOP; break;
6639       case 0x30: set_mnemonic(i, "LL"); type=NI; break;
6640       case 0x31: set_mnemonic(i, "LWC1"); type=C1LS; break;
6641 #if 0
6642       case 0x34: set_mnemonic(i, "LLD"); type=NI; break;
6643       case 0x35: set_mnemonic(i, "LDC1"); type=C1LS; break;
6644       case 0x37: set_mnemonic(i, "LD"); type=LOAD; break;
6645 #endif
6646       case 0x38: set_mnemonic(i, "SC"); type=NI; break;
6647       case 0x39: set_mnemonic(i, "SWC1"); type=C1LS; break;
6648 #if 0
6649       case 0x3C: set_mnemonic(i, "SCD"); type=NI; break;
6650       case 0x3D: set_mnemonic(i, "SDC1"); type=C1LS; break;
6651       case 0x3F: set_mnemonic(i, "SD"); type=STORE; break;
6652 #endif
6653       case 0x12: set_mnemonic(i, "COP2"); type=NI;
6654         op2=(source[i]>>21)&0x1f;
6655         //if (op2 & 0x10)
6656         if (source[i]&0x3f) { // use this hack to support old savestates with patched gte insns
6657           if (gte_handlers[source[i]&0x3f]!=NULL) {
6658 #ifdef DISASM
6659             if (gte_regnames[source[i]&0x3f]!=NULL)
6660               strcpy(insn[i],gte_regnames[source[i]&0x3f]);
6661             else
6662               snprintf(insn[i], sizeof(insn[i]), "COP2 %x", source[i]&0x3f);
6663 #endif
6664             type=C2OP;
6665           }
6666         }
6667         else switch(op2)
6668         {
6669           case 0x00: set_mnemonic(i, "MFC2"); type=COP2; break;
6670           case 0x02: set_mnemonic(i, "CFC2"); type=COP2; break;
6671           case 0x04: set_mnemonic(i, "MTC2"); type=COP2; break;
6672           case 0x06: set_mnemonic(i, "CTC2"); type=COP2; break;
6673         }
6674         break;
6675       case 0x32: set_mnemonic(i, "LWC2"); type=C2LS; break;
6676       case 0x3A: set_mnemonic(i, "SWC2"); type=C2LS; break;
6677       case 0x3B: set_mnemonic(i, "HLECALL"); type=HLECALL; break;
6678       default: set_mnemonic(i, "???"); type=NI;
6679         SysPrintf("NI %08x @%08x (%08x)\n", source[i], start + i*4, start);
6680         break;
6681     }
6682     dops[i].itype=type;
6683     dops[i].opcode2=op2;
6684     /* Get registers/immediates */
6685     dops[i].use_lt1=0;
6686     gte_rs[i]=gte_rt[i]=0;
6687     switch(type) {
6688       case LOAD:
6689         dops[i].rs1=(source[i]>>21)&0x1f;
6690         dops[i].rs2=0;
6691         dops[i].rt1=(source[i]>>16)&0x1f;
6692         dops[i].rt2=0;
6693         imm[i]=(short)source[i];
6694         break;
6695       case STORE:
6696       case STORELR:
6697         dops[i].rs1=(source[i]>>21)&0x1f;
6698         dops[i].rs2=(source[i]>>16)&0x1f;
6699         dops[i].rt1=0;
6700         dops[i].rt2=0;
6701         imm[i]=(short)source[i];
6702         break;
6703       case LOADLR:
6704         // LWL/LWR only load part of the register,
6705         // therefore the target register must be treated as a source too
6706         dops[i].rs1=(source[i]>>21)&0x1f;
6707         dops[i].rs2=(source[i]>>16)&0x1f;
6708         dops[i].rt1=(source[i]>>16)&0x1f;
6709         dops[i].rt2=0;
6710         imm[i]=(short)source[i];
6711         break;
6712       case IMM16:
6713         if (op==0x0f) dops[i].rs1=0; // LUI instruction has no source register
6714         else dops[i].rs1=(source[i]>>21)&0x1f;
6715         dops[i].rs2=0;
6716         dops[i].rt1=(source[i]>>16)&0x1f;
6717         dops[i].rt2=0;
6718         if(op>=0x0c&&op<=0x0e) { // ANDI/ORI/XORI
6719           imm[i]=(unsigned short)source[i];
6720         }else{
6721           imm[i]=(short)source[i];
6722         }
6723         break;
6724       case UJUMP:
6725         dops[i].rs1=0;
6726         dops[i].rs2=0;
6727         dops[i].rt1=0;
6728         dops[i].rt2=0;
6729         // The JAL instruction writes to r31.
6730         if (op&1) {
6731           dops[i].rt1=31;
6732         }
6733         dops[i].rs2=CCREG;
6734         break;
6735       case RJUMP:
6736         dops[i].rs1=(source[i]>>21)&0x1f;
6737         dops[i].rs2=0;
6738         dops[i].rt1=0;
6739         dops[i].rt2=0;
6740         // The JALR instruction writes to rd.
6741         if (op2&1) {
6742           dops[i].rt1=(source[i]>>11)&0x1f;
6743         }
6744         dops[i].rs2=CCREG;
6745         break;
6746       case CJUMP:
6747         dops[i].rs1=(source[i]>>21)&0x1f;
6748         dops[i].rs2=(source[i]>>16)&0x1f;
6749         dops[i].rt1=0;
6750         dops[i].rt2=0;
6751         if(op&2) { // BGTZ/BLEZ
6752           dops[i].rs2=0;
6753         }
6754         break;
6755       case SJUMP:
6756         dops[i].rs1=(source[i]>>21)&0x1f;
6757         dops[i].rs2=CCREG;
6758         dops[i].rt1=0;
6759         dops[i].rt2=0;
6760         if(op2&0x10) { // BxxAL
6761           dops[i].rt1=31;
6762           // NOTE: If the branch is not taken, r31 is still overwritten
6763         }
6764         break;
6765       case ALU:
6766         dops[i].rs1=(source[i]>>21)&0x1f; // source
6767         dops[i].rs2=(source[i]>>16)&0x1f; // subtract amount
6768         dops[i].rt1=(source[i]>>11)&0x1f; // destination
6769         dops[i].rt2=0;
6770         break;
6771       case MULTDIV:
6772         dops[i].rs1=(source[i]>>21)&0x1f; // source
6773         dops[i].rs2=(source[i]>>16)&0x1f; // divisor
6774         dops[i].rt1=HIREG;
6775         dops[i].rt2=LOREG;
6776         break;
6777       case MOV:
6778         dops[i].rs1=0;
6779         dops[i].rs2=0;
6780         dops[i].rt1=0;
6781         dops[i].rt2=0;
6782         if(op2==0x10) dops[i].rs1=HIREG; // MFHI
6783         if(op2==0x11) dops[i].rt1=HIREG; // MTHI
6784         if(op2==0x12) dops[i].rs1=LOREG; // MFLO
6785         if(op2==0x13) dops[i].rt1=LOREG; // MTLO
6786         if((op2&0x1d)==0x10) dops[i].rt1=(source[i]>>11)&0x1f; // MFxx
6787         if((op2&0x1d)==0x11) dops[i].rs1=(source[i]>>21)&0x1f; // MTxx
6788         break;
6789       case SHIFT:
6790         dops[i].rs1=(source[i]>>16)&0x1f; // target of shift
6791         dops[i].rs2=(source[i]>>21)&0x1f; // shift amount
6792         dops[i].rt1=(source[i]>>11)&0x1f; // destination
6793         dops[i].rt2=0;
6794         break;
6795       case SHIFTIMM:
6796         dops[i].rs1=(source[i]>>16)&0x1f;
6797         dops[i].rs2=0;
6798         dops[i].rt1=(source[i]>>11)&0x1f;
6799         dops[i].rt2=0;
6800         imm[i]=(source[i]>>6)&0x1f;
6801         // DSxx32 instructions
6802         if(op2>=0x3c) imm[i]|=0x20;
6803         break;
6804       case COP0:
6805         dops[i].rs1=0;
6806         dops[i].rs2=0;
6807         dops[i].rt1=0;
6808         dops[i].rt2=0;
6809         if(op2==0||op2==2) dops[i].rt1=(source[i]>>16)&0x1F; // MFC0/CFC0
6810         if(op2==4||op2==6) dops[i].rs1=(source[i]>>16)&0x1F; // MTC0/CTC0
6811         if(op2==4&&((source[i]>>11)&0x1f)==12) dops[i].rt2=CSREG; // Status
6812         if(op2==16) if((source[i]&0x3f)==0x18) dops[i].rs2=CCREG; // ERET
6813         break;
6814       case COP1:
6815         dops[i].rs1=0;
6816         dops[i].rs2=0;
6817         dops[i].rt1=0;
6818         dops[i].rt2=0;
6819         if(op2<3) dops[i].rt1=(source[i]>>16)&0x1F; // MFC1/DMFC1/CFC1
6820         if(op2>3) dops[i].rs1=(source[i]>>16)&0x1F; // MTC1/DMTC1/CTC1
6821         dops[i].rs2=CSREG;
6822         break;
6823       case COP2:
6824         dops[i].rs1=0;
6825         dops[i].rs2=0;
6826         dops[i].rt1=0;
6827         dops[i].rt2=0;
6828         if(op2<3) dops[i].rt1=(source[i]>>16)&0x1F; // MFC2/CFC2
6829         if(op2>3) dops[i].rs1=(source[i]>>16)&0x1F; // MTC2/CTC2
6830         dops[i].rs2=CSREG;
6831         int gr=(source[i]>>11)&0x1F;
6832         switch(op2)
6833         {
6834           case 0x00: gte_rs[i]=1ll<<gr; break; // MFC2
6835           case 0x04: gte_rt[i]=1ll<<gr; break; // MTC2
6836           case 0x02: gte_rs[i]=1ll<<(gr+32); break; // CFC2
6837           case 0x06: gte_rt[i]=1ll<<(gr+32); break; // CTC2
6838         }
6839         break;
6840       case C1LS:
6841         dops[i].rs1=(source[i]>>21)&0x1F;
6842         dops[i].rs2=CSREG;
6843         dops[i].rt1=0;
6844         dops[i].rt2=0;
6845         imm[i]=(short)source[i];
6846         break;
6847       case C2LS:
6848         dops[i].rs1=(source[i]>>21)&0x1F;
6849         dops[i].rs2=0;
6850         dops[i].rt1=0;
6851         dops[i].rt2=0;
6852         imm[i]=(short)source[i];
6853         if(op==0x32) gte_rt[i]=1ll<<((source[i]>>16)&0x1F); // LWC2
6854         else gte_rs[i]=1ll<<((source[i]>>16)&0x1F); // SWC2
6855         break;
6856       case C2OP:
6857         dops[i].rs1=0;
6858         dops[i].rs2=0;
6859         dops[i].rt1=0;
6860         dops[i].rt2=0;
6861         gte_rs[i]=gte_reg_reads[source[i]&0x3f];
6862         gte_rt[i]=gte_reg_writes[source[i]&0x3f];
6863         gte_rt[i]|=1ll<<63; // every op changes flags
6864         if((source[i]&0x3f)==GTE_MVMVA) {
6865           int v = (source[i] >> 15) & 3;
6866           gte_rs[i]&=~0xe3fll;
6867           if(v==3) gte_rs[i]|=0xe00ll;
6868           else gte_rs[i]|=3ll<<(v*2);
6869         }
6870         break;
6871       case SYSCALL:
6872       case HLECALL:
6873       case INTCALL:
6874         dops[i].rs1=CCREG;
6875         dops[i].rs2=0;
6876         dops[i].rt1=0;
6877         dops[i].rt2=0;
6878         break;
6879       default:
6880         dops[i].rs1=0;
6881         dops[i].rs2=0;
6882         dops[i].rt1=0;
6883         dops[i].rt2=0;
6884     }
6885     /* Calculate branch target addresses */
6886     if(type==UJUMP)
6887       ba[i]=((start+i*4+4)&0xF0000000)|(((unsigned int)source[i]<<6)>>4);
6888     else if(type==CJUMP&&dops[i].rs1==dops[i].rs2&&(op&1))
6889       ba[i]=start+i*4+8; // Ignore never taken branch
6890     else if(type==SJUMP&&dops[i].rs1==0&&!(op2&1))
6891       ba[i]=start+i*4+8; // Ignore never taken branch
6892     else if(type==CJUMP||type==SJUMP)
6893       ba[i]=start+i*4+4+((signed int)((unsigned int)source[i]<<16)>>14);
6894     else ba[i]=-1;
6895
6896     /* simplify always (not)taken branches */
6897     if (type == CJUMP && dops[i].rs1 == dops[i].rs2) {
6898       dops[i].rs1 = dops[i].rs2 = 0;
6899       if (!(op & 1)) {
6900         dops[i].itype = type = UJUMP;
6901         dops[i].rs2 = CCREG;
6902       }
6903     }
6904     else if (type == SJUMP && dops[i].rs1 == 0 && (op2 & 1))
6905       dops[i].itype = type = UJUMP;
6906
6907     dops[i].is_jump = (dops[i].itype == RJUMP || dops[i].itype == UJUMP || dops[i].itype == CJUMP || dops[i].itype == SJUMP);
6908     dops[i].is_ujump = (dops[i].itype == RJUMP || dops[i].itype == UJUMP); // || (source[i] >> 16) == 0x1000 // beq r0,r0
6909     dops[i].is_load = (dops[i].itype == LOAD || dops[i].itype == LOADLR || op == 0x32); // LWC2
6910     dops[i].is_store = (dops[i].itype == STORE || dops[i].itype == STORELR || op == 0x3a); // SWC2
6911
6912     /* messy cases to just pass over to the interpreter */
6913     if (i > 0 && dops[i-1].is_jump) {
6914       int do_in_intrp=0;
6915       // branch in delay slot?
6916       if (dops[i].is_jump) {
6917         // don't handle first branch and call interpreter if it's hit
6918         SysPrintf("branch in delay slot @%08x (%08x)\n", start + i*4, start);
6919         do_in_intrp=1;
6920       }
6921       // basic load delay detection
6922       else if((type==LOAD||type==LOADLR||type==COP0||type==COP2||type==C2LS)&&dops[i].rt1!=0) {
6923         int t=(ba[i-1]-start)/4;
6924         if(0 <= t && t < i &&(dops[i].rt1==dops[t].rs1||dops[i].rt1==dops[t].rs2)&&dops[t].itype!=CJUMP&&dops[t].itype!=SJUMP) {
6925           // jump target wants DS result - potential load delay effect
6926           SysPrintf("load delay @%08x (%08x)\n", start + i*4, start);
6927           do_in_intrp=1;
6928           dops[t+1].bt=1; // expected return from interpreter
6929         }
6930         else if(i>=2&&dops[i-2].rt1==2&&dops[i].rt1==2&&dops[i].rs1!=2&&dops[i].rs2!=2&&dops[i-1].rs1!=2&&dops[i-1].rs2!=2&&
6931               !(i>=3&&dops[i-3].is_jump)) {
6932           // v0 overwrite like this is a sign of trouble, bail out
6933           SysPrintf("v0 overwrite @%08x (%08x)\n", start + i*4, start);
6934           do_in_intrp=1;
6935         }
6936       }
6937       if (do_in_intrp) {
6938         memset(&dops[i-1], 0, sizeof(dops[i-1]));
6939         dops[i-1].itype = INTCALL;
6940         dops[i-1].rs1 = CCREG;
6941         ba[i-1] = -1;
6942         done = 2;
6943         i--; // don't compile the DS
6944       }
6945     }
6946
6947     /* Is this the end of the block? */
6948     if (i > 0 && dops[i-1].is_ujump) {
6949       if (dops[i-1].rt1 == 0) { // not jal
6950         int found_bbranch = 0, t = (ba[i-1] - start) / 4;
6951         if ((u_int)(t - i) < 64 && start + (t+64)*4 < pagelimit) {
6952           // scan for a branch back to i+1
6953           for (j = t; j < t + 64; j++) {
6954             int tmpop = source[j] >> 26;
6955             if (tmpop == 1 || ((tmpop & ~3) == 4)) {
6956               int t2 = j + 1 + (int)(signed short)source[j];
6957               if (t2 == i + 1) {
6958                 //printf("blk expand %08x<-%08x\n", start + (i+1)*4, start + j*4);
6959                 found_bbranch = 1;
6960                 break;
6961               }
6962             }
6963           }
6964         }
6965         if (!found_bbranch)
6966           done = 2;
6967       }
6968       else {
6969         if(stop_after_jal) done=1;
6970         // Stop on BREAK
6971         if((source[i+1]&0xfc00003f)==0x0d) done=1;
6972       }
6973       // Don't recompile stuff that's already compiled
6974       if(check_addr(start+i*4+4)) done=1;
6975       // Don't get too close to the limit
6976       if(i>MAXBLOCK/2) done=1;
6977     }
6978     if (dops[i].itype == SYSCALL || dops[i].itype == HLECALL || dops[i].itype == INTCALL)
6979       done = stop_after_jal ? 1 : 2;
6980     if (done == 2) {
6981       // Does the block continue due to a branch?
6982       for(j=i-1;j>=0;j--)
6983       {
6984         if(ba[j]==start+i*4) done=j=0; // Branch into delay slot
6985         if(ba[j]==start+i*4+4) done=j=0;
6986         if(ba[j]==start+i*4+8) done=j=0;
6987       }
6988     }
6989     //assert(i<MAXBLOCK-1);
6990     if(start+i*4==pagelimit-4) done=1;
6991     assert(start+i*4<pagelimit);
6992     if (i==MAXBLOCK-1) done=1;
6993     // Stop if we're compiling junk
6994     if(dops[i].itype == NI && (++ni_count > 8 || dops[i].opcode == 0x11)) {
6995       done=stop_after_jal=1;
6996       SysPrintf("Disabled speculative precompilation\n");
6997     }
6998   }
6999   while (i > 0 && dops[i-1].is_jump)
7000     i--;
7001   assert(i > 0);
7002   assert(!dops[i-1].is_jump);
7003   slen = i;
7004 }
7005
7006 // Basic liveness analysis for MIPS registers
7007 static noinline void pass2_unneeded_regs(int istart,int iend,int r)
7008 {
7009   int i;
7010   uint64_t u,gte_u,b,gte_b;
7011   uint64_t temp_u,temp_gte_u=0;
7012   uint64_t gte_u_unknown=0;
7013   if (HACK_ENABLED(NDHACK_GTE_UNNEEDED))
7014     gte_u_unknown=~0ll;
7015   if(iend==slen-1) {
7016     u=1;
7017     gte_u=gte_u_unknown;
7018   }else{
7019     //u=unneeded_reg[iend+1];
7020     u=1;
7021     gte_u=gte_unneeded[iend+1];
7022   }
7023
7024   for (i=iend;i>=istart;i--)
7025   {
7026     //printf("unneeded registers i=%d (%d,%d) r=%d\n",i,istart,iend,r);
7027     if(dops[i].is_jump)
7028     {
7029       // If subroutine call, flag return address as a possible branch target
7030       if(dops[i].rt1==31 && i<slen-2) dops[i+2].bt=1;
7031
7032       if(ba[i]<start || ba[i]>=(start+slen*4))
7033       {
7034         // Branch out of this block, flush all regs
7035         u=1;
7036         gte_u=gte_u_unknown;
7037         branch_unneeded_reg[i]=u;
7038         // Merge in delay slot
7039         u|=(1LL<<dops[i+1].rt1)|(1LL<<dops[i+1].rt2);
7040         u&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
7041         u|=1;
7042         gte_u|=gte_rt[i+1];
7043         gte_u&=~gte_rs[i+1];
7044       }
7045       else
7046       {
7047         // Internal branch, flag target
7048         dops[(ba[i]-start)>>2].bt=1;
7049         if(ba[i]<=start+i*4) {
7050           // Backward branch
7051           if(dops[i].is_ujump)
7052           {
7053             // Unconditional branch
7054             temp_u=1;
7055             temp_gte_u=0;
7056           } else {
7057             // Conditional branch (not taken case)
7058             temp_u=unneeded_reg[i+2];
7059             temp_gte_u&=gte_unneeded[i+2];
7060           }
7061           // Merge in delay slot
7062           temp_u|=(1LL<<dops[i+1].rt1)|(1LL<<dops[i+1].rt2);
7063           temp_u&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
7064           temp_u|=1;
7065           temp_gte_u|=gte_rt[i+1];
7066           temp_gte_u&=~gte_rs[i+1];
7067           temp_u|=(1LL<<dops[i].rt1)|(1LL<<dops[i].rt2);
7068           temp_u&=~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
7069           temp_u|=1;
7070           temp_gte_u|=gte_rt[i];
7071           temp_gte_u&=~gte_rs[i];
7072           unneeded_reg[i]=temp_u;
7073           gte_unneeded[i]=temp_gte_u;
7074           // Only go three levels deep.  This recursion can take an
7075           // excessive amount of time if there are a lot of nested loops.
7076           if(r<2) {
7077             pass2_unneeded_regs((ba[i]-start)>>2,i-1,r+1);
7078           }else{
7079             unneeded_reg[(ba[i]-start)>>2]=1;
7080             gte_unneeded[(ba[i]-start)>>2]=gte_u_unknown;
7081           }
7082         } /*else*/ if(1) {
7083           if (dops[i].is_ujump)
7084           {
7085             // Unconditional branch
7086             u=unneeded_reg[(ba[i]-start)>>2];
7087             gte_u=gte_unneeded[(ba[i]-start)>>2];
7088             branch_unneeded_reg[i]=u;
7089             // Merge in delay slot
7090             u|=(1LL<<dops[i+1].rt1)|(1LL<<dops[i+1].rt2);
7091             u&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
7092             u|=1;
7093             gte_u|=gte_rt[i+1];
7094             gte_u&=~gte_rs[i+1];
7095           } else {
7096             // Conditional branch
7097             b=unneeded_reg[(ba[i]-start)>>2];
7098             gte_b=gte_unneeded[(ba[i]-start)>>2];
7099             branch_unneeded_reg[i]=b;
7100             // Branch delay slot
7101             b|=(1LL<<dops[i+1].rt1)|(1LL<<dops[i+1].rt2);
7102             b&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
7103             b|=1;
7104             gte_b|=gte_rt[i+1];
7105             gte_b&=~gte_rs[i+1];
7106             u&=b;
7107             gte_u&=gte_b;
7108             if(i<slen-1) {
7109               branch_unneeded_reg[i]&=unneeded_reg[i+2];
7110             } else {
7111               branch_unneeded_reg[i]=1;
7112             }
7113           }
7114         }
7115       }
7116     }
7117     else if(dops[i].itype==SYSCALL||dops[i].itype==HLECALL||dops[i].itype==INTCALL)
7118     {
7119       // SYSCALL instruction (software interrupt)
7120       u=1;
7121     }
7122     else if(dops[i].itype==COP0 && dops[i].opcode2==0x10)
7123     {
7124       // RFE
7125       u=1;
7126     }
7127     //u=1; // DEBUG
7128     // Written registers are unneeded
7129     u|=1LL<<dops[i].rt1;
7130     u|=1LL<<dops[i].rt2;
7131     gte_u|=gte_rt[i];
7132     // Accessed registers are needed
7133     u&=~(1LL<<dops[i].rs1);
7134     u&=~(1LL<<dops[i].rs2);
7135     gte_u&=~gte_rs[i];
7136     if(gte_rs[i]&&dops[i].rt1&&(unneeded_reg[i+1]&(1ll<<dops[i].rt1)))
7137       gte_u|=gte_rs[i]&gte_unneeded[i+1]; // MFC2/CFC2 to dead register, unneeded
7138     // Source-target dependencies
7139     // R0 is always unneeded
7140     u|=1;
7141     // Save it
7142     unneeded_reg[i]=u;
7143     gte_unneeded[i]=gte_u;
7144     /*
7145     printf("ur (%d,%d) %x: ",istart,iend,start+i*4);
7146     printf("U:");
7147     int r;
7148     for(r=1;r<=CCREG;r++) {
7149       if((unneeded_reg[i]>>r)&1) {
7150         if(r==HIREG) printf(" HI");
7151         else if(r==LOREG) printf(" LO");
7152         else printf(" r%d",r);
7153       }
7154     }
7155     printf("\n");
7156     */
7157   }
7158 }
7159
7160 static noinline void pass3_register_alloc(u_int addr)
7161 {
7162   struct regstat current; // Current register allocations/status
7163   clear_all_regs(current.regmap_entry);
7164   clear_all_regs(current.regmap);
7165   current.wasdirty = current.dirty = 0;
7166   current.u = unneeded_reg[0];
7167   alloc_reg(&current, 0, CCREG);
7168   dirty_reg(&current, CCREG);
7169   current.wasconst = 0;
7170   current.isconst = 0;
7171   current.loadedconst = 0;
7172   current.waswritten = 0;
7173   int ds=0;
7174   int cc=0;
7175   int hr;
7176   int i, j;
7177
7178   if (addr & 1) {
7179     // First instruction is delay slot
7180     cc=-1;
7181     dops[1].bt=1;
7182     ds=1;
7183     unneeded_reg[0]=1;
7184     current.regmap[HOST_BTREG]=BTREG;
7185   }
7186
7187   for(i=0;i<slen;i++)
7188   {
7189     if(dops[i].bt)
7190     {
7191       for(hr=0;hr<HOST_REGS;hr++)
7192       {
7193         // Is this really necessary?
7194         if(current.regmap[hr]==0) current.regmap[hr]=-1;
7195       }
7196       current.isconst=0;
7197       current.waswritten=0;
7198     }
7199
7200     memcpy(regmap_pre[i],current.regmap,sizeof(current.regmap));
7201     regs[i].wasconst=current.isconst;
7202     regs[i].wasdirty=current.dirty;
7203     regs[i].dirty=0;
7204     regs[i].u=0;
7205     regs[i].isconst=0;
7206     regs[i].loadedconst=0;
7207     if (!dops[i].is_jump) {
7208       if(i+1<slen) {
7209         current.u=unneeded_reg[i+1]&~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
7210         current.u|=1;
7211       } else {
7212         current.u=1;
7213       }
7214     } else {
7215       if(i+1<slen) {
7216         current.u=branch_unneeded_reg[i]&~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
7217         current.u&=~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
7218         current.u|=1;
7219       } else {
7220         SysPrintf("oops, branch at end of block with no delay slot @%08x\n", start + i*4);
7221         abort();
7222       }
7223     }
7224     dops[i].is_ds=ds;
7225     if(ds) {
7226       ds=0; // Skip delay slot, already allocated as part of branch
7227       // ...but we need to alloc it in case something jumps here
7228       if(i+1<slen) {
7229         current.u=branch_unneeded_reg[i-1]&unneeded_reg[i+1];
7230       }else{
7231         current.u=branch_unneeded_reg[i-1];
7232       }
7233       current.u&=~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
7234       current.u|=1;
7235       struct regstat temp;
7236       memcpy(&temp,&current,sizeof(current));
7237       temp.wasdirty=temp.dirty;
7238       // TODO: Take into account unconditional branches, as below
7239       delayslot_alloc(&temp,i);
7240       memcpy(regs[i].regmap,temp.regmap,sizeof(temp.regmap));
7241       regs[i].wasdirty=temp.wasdirty;
7242       regs[i].dirty=temp.dirty;
7243       regs[i].isconst=0;
7244       regs[i].wasconst=0;
7245       current.isconst=0;
7246       // Create entry (branch target) regmap
7247       for(hr=0;hr<HOST_REGS;hr++)
7248       {
7249         int r=temp.regmap[hr];
7250         if(r>=0) {
7251           if(r!=regmap_pre[i][hr]) {
7252             regs[i].regmap_entry[hr]=-1;
7253           }
7254           else
7255           {
7256               assert(r < 64);
7257               if((current.u>>r)&1) {
7258                 regs[i].regmap_entry[hr]=-1;
7259                 regs[i].regmap[hr]=-1;
7260                 //Don't clear regs in the delay slot as the branch might need them
7261                 //current.regmap[hr]=-1;
7262               }else
7263                 regs[i].regmap_entry[hr]=r;
7264           }
7265         } else {
7266           // First instruction expects CCREG to be allocated
7267           if(i==0&&hr==HOST_CCREG)
7268             regs[i].regmap_entry[hr]=CCREG;
7269           else
7270             regs[i].regmap_entry[hr]=-1;
7271         }
7272       }
7273     }
7274     else { // Not delay slot
7275       switch(dops[i].itype) {
7276         case UJUMP:
7277           //current.isconst=0; // DEBUG
7278           //current.wasconst=0; // DEBUG
7279           //regs[i].wasconst=0; // DEBUG
7280           clear_const(&current,dops[i].rt1);
7281           alloc_cc(&current,i);
7282           dirty_reg(&current,CCREG);
7283           if (dops[i].rt1==31) {
7284             alloc_reg(&current,i,31);
7285             dirty_reg(&current,31);
7286             //assert(dops[i+1].rs1!=31&&dops[i+1].rs2!=31);
7287             //assert(dops[i+1].rt1!=dops[i].rt1);
7288             #ifdef REG_PREFETCH
7289             alloc_reg(&current,i,PTEMP);
7290             #endif
7291           }
7292           dops[i].ooo=1;
7293           delayslot_alloc(&current,i+1);
7294           //current.isconst=0; // DEBUG
7295           ds=1;
7296           //printf("i=%d, isconst=%x\n",i,current.isconst);
7297           break;
7298         case RJUMP:
7299           //current.isconst=0;
7300           //current.wasconst=0;
7301           //regs[i].wasconst=0;
7302           clear_const(&current,dops[i].rs1);
7303           clear_const(&current,dops[i].rt1);
7304           alloc_cc(&current,i);
7305           dirty_reg(&current,CCREG);
7306           if (!ds_writes_rjump_rs(i)) {
7307             alloc_reg(&current,i,dops[i].rs1);
7308             if (dops[i].rt1!=0) {
7309               alloc_reg(&current,i,dops[i].rt1);
7310               dirty_reg(&current,dops[i].rt1);
7311               assert(dops[i+1].rs1!=dops[i].rt1&&dops[i+1].rs2!=dops[i].rt1);
7312               assert(dops[i+1].rt1!=dops[i].rt1);
7313               #ifdef REG_PREFETCH
7314               alloc_reg(&current,i,PTEMP);
7315               #endif
7316             }
7317             #ifdef USE_MINI_HT
7318             if(dops[i].rs1==31) { // JALR
7319               alloc_reg(&current,i,RHASH);
7320               alloc_reg(&current,i,RHTBL);
7321             }
7322             #endif
7323             delayslot_alloc(&current,i+1);
7324           } else {
7325             // The delay slot overwrites our source register,
7326             // allocate a temporary register to hold the old value.
7327             current.isconst=0;
7328             current.wasconst=0;
7329             regs[i].wasconst=0;
7330             delayslot_alloc(&current,i+1);
7331             current.isconst=0;
7332             alloc_reg(&current,i,RTEMP);
7333           }
7334           //current.isconst=0; // DEBUG
7335           dops[i].ooo=1;
7336           ds=1;
7337           break;
7338         case CJUMP:
7339           //current.isconst=0;
7340           //current.wasconst=0;
7341           //regs[i].wasconst=0;
7342           clear_const(&current,dops[i].rs1);
7343           clear_const(&current,dops[i].rs2);
7344           if((dops[i].opcode&0x3E)==4) // BEQ/BNE
7345           {
7346             alloc_cc(&current,i);
7347             dirty_reg(&current,CCREG);
7348             if(dops[i].rs1) alloc_reg(&current,i,dops[i].rs1);
7349             if(dops[i].rs2) alloc_reg(&current,i,dops[i].rs2);
7350             if((dops[i].rs1&&(dops[i].rs1==dops[i+1].rt1||dops[i].rs1==dops[i+1].rt2))||
7351                (dops[i].rs2&&(dops[i].rs2==dops[i+1].rt1||dops[i].rs2==dops[i+1].rt2))) {
7352               // The delay slot overwrites one of our conditions.
7353               // Allocate the branch condition registers instead.
7354               current.isconst=0;
7355               current.wasconst=0;
7356               regs[i].wasconst=0;
7357               if(dops[i].rs1) alloc_reg(&current,i,dops[i].rs1);
7358               if(dops[i].rs2) alloc_reg(&current,i,dops[i].rs2);
7359             }
7360             else
7361             {
7362               dops[i].ooo=1;
7363               delayslot_alloc(&current,i+1);
7364             }
7365           }
7366           else
7367           if((dops[i].opcode&0x3E)==6) // BLEZ/BGTZ
7368           {
7369             alloc_cc(&current,i);
7370             dirty_reg(&current,CCREG);
7371             alloc_reg(&current,i,dops[i].rs1);
7372             if(dops[i].rs1&&(dops[i].rs1==dops[i+1].rt1||dops[i].rs1==dops[i+1].rt2)) {
7373               // The delay slot overwrites one of our conditions.
7374               // Allocate the branch condition registers instead.
7375               current.isconst=0;
7376               current.wasconst=0;
7377               regs[i].wasconst=0;
7378               if(dops[i].rs1) alloc_reg(&current,i,dops[i].rs1);
7379             }
7380             else
7381             {
7382               dops[i].ooo=1;
7383               delayslot_alloc(&current,i+1);
7384             }
7385           }
7386           else
7387           // Don't alloc the delay slot yet because we might not execute it
7388           if((dops[i].opcode&0x3E)==0x14) // BEQL/BNEL
7389           {
7390             current.isconst=0;
7391             current.wasconst=0;
7392             regs[i].wasconst=0;
7393             alloc_cc(&current,i);
7394             dirty_reg(&current,CCREG);
7395             alloc_reg(&current,i,dops[i].rs1);
7396             alloc_reg(&current,i,dops[i].rs2);
7397           }
7398           else
7399           if((dops[i].opcode&0x3E)==0x16) // BLEZL/BGTZL
7400           {
7401             current.isconst=0;
7402             current.wasconst=0;
7403             regs[i].wasconst=0;
7404             alloc_cc(&current,i);
7405             dirty_reg(&current,CCREG);
7406             alloc_reg(&current,i,dops[i].rs1);
7407           }
7408           ds=1;
7409           //current.isconst=0;
7410           break;
7411         case SJUMP:
7412           //current.isconst=0;
7413           //current.wasconst=0;
7414           //regs[i].wasconst=0;
7415           clear_const(&current,dops[i].rs1);
7416           clear_const(&current,dops[i].rt1);
7417           //if((dops[i].opcode2&0x1E)==0x0) // BLTZ/BGEZ
7418           if((dops[i].opcode2&0x0E)==0x0) // BLTZ/BGEZ
7419           {
7420             alloc_cc(&current,i);
7421             dirty_reg(&current,CCREG);
7422             alloc_reg(&current,i,dops[i].rs1);
7423             if (dops[i].rt1==31) { // BLTZAL/BGEZAL
7424               alloc_reg(&current,i,31);
7425               dirty_reg(&current,31);
7426               //#ifdef REG_PREFETCH
7427               //alloc_reg(&current,i,PTEMP);
7428               //#endif
7429             }
7430             if((dops[i].rs1&&(dops[i].rs1==dops[i+1].rt1||dops[i].rs1==dops[i+1].rt2)) // The delay slot overwrites the branch condition.
7431                ||(dops[i].rt1==31&&(dops[i+1].rs1==31||dops[i+1].rs2==31||dops[i+1].rt1==31||dops[i+1].rt2==31))) { // DS touches $ra
7432               // Allocate the branch condition registers instead.
7433               current.isconst=0;
7434               current.wasconst=0;
7435               regs[i].wasconst=0;
7436               if(dops[i].rs1) alloc_reg(&current,i,dops[i].rs1);
7437             }
7438             else
7439             {
7440               dops[i].ooo=1;
7441               delayslot_alloc(&current,i+1);
7442             }
7443           }
7444           else
7445           // Don't alloc the delay slot yet because we might not execute it
7446           if((dops[i].opcode2&0x1E)==0x2) // BLTZL/BGEZL
7447           {
7448             current.isconst=0;
7449             current.wasconst=0;
7450             regs[i].wasconst=0;
7451             alloc_cc(&current,i);
7452             dirty_reg(&current,CCREG);
7453             alloc_reg(&current,i,dops[i].rs1);
7454           }
7455           ds=1;
7456           //current.isconst=0;
7457           break;
7458         case IMM16:
7459           imm16_alloc(&current,i);
7460           break;
7461         case LOAD:
7462         case LOADLR:
7463           load_alloc(&current,i);
7464           break;
7465         case STORE:
7466         case STORELR:
7467           store_alloc(&current,i);
7468           break;
7469         case ALU:
7470           alu_alloc(&current,i);
7471           break;
7472         case SHIFT:
7473           shift_alloc(&current,i);
7474           break;
7475         case MULTDIV:
7476           multdiv_alloc(&current,i);
7477           break;
7478         case SHIFTIMM:
7479           shiftimm_alloc(&current,i);
7480           break;
7481         case MOV:
7482           mov_alloc(&current,i);
7483           break;
7484         case COP0:
7485           cop0_alloc(&current,i);
7486           break;
7487         case COP1:
7488           break;
7489         case COP2:
7490           cop2_alloc(&current,i);
7491           break;
7492         case C1LS:
7493           c1ls_alloc(&current,i);
7494           break;
7495         case C2LS:
7496           c2ls_alloc(&current,i);
7497           break;
7498         case C2OP:
7499           c2op_alloc(&current,i);
7500           break;
7501         case SYSCALL:
7502         case HLECALL:
7503         case INTCALL:
7504           syscall_alloc(&current,i);
7505           break;
7506       }
7507
7508       // Create entry (branch target) regmap
7509       for(hr=0;hr<HOST_REGS;hr++)
7510       {
7511         int r,or;
7512         r=current.regmap[hr];
7513         if(r>=0) {
7514           if(r!=regmap_pre[i][hr]) {
7515             // TODO: delay slot (?)
7516             or=get_reg(regmap_pre[i],r); // Get old mapping for this register
7517             if(or<0||r>=TEMPREG){
7518               regs[i].regmap_entry[hr]=-1;
7519             }
7520             else
7521             {
7522               // Just move it to a different register
7523               regs[i].regmap_entry[hr]=r;
7524               // If it was dirty before, it's still dirty
7525               if((regs[i].wasdirty>>or)&1) dirty_reg(&current,r);
7526             }
7527           }
7528           else
7529           {
7530             // Unneeded
7531             if(r==0){
7532               regs[i].regmap_entry[hr]=0;
7533             }
7534             else
7535             {
7536               assert(r<64);
7537               if((current.u>>r)&1) {
7538                 regs[i].regmap_entry[hr]=-1;
7539                 //regs[i].regmap[hr]=-1;
7540                 current.regmap[hr]=-1;
7541               }else
7542                 regs[i].regmap_entry[hr]=r;
7543             }
7544           }
7545         } else {
7546           // Branches expect CCREG to be allocated at the target
7547           if(regmap_pre[i][hr]==CCREG)
7548             regs[i].regmap_entry[hr]=CCREG;
7549           else
7550             regs[i].regmap_entry[hr]=-1;
7551         }
7552       }
7553       memcpy(regs[i].regmap,current.regmap,sizeof(current.regmap));
7554     }
7555
7556     if(i>0&&(dops[i-1].itype==STORE||dops[i-1].itype==STORELR||(dops[i-1].itype==C2LS&&dops[i-1].opcode==0x3a))&&(u_int)imm[i-1]<0x800)
7557       current.waswritten|=1<<dops[i-1].rs1;
7558     current.waswritten&=~(1<<dops[i].rt1);
7559     current.waswritten&=~(1<<dops[i].rt2);
7560     if((dops[i].itype==STORE||dops[i].itype==STORELR||(dops[i].itype==C2LS&&dops[i].opcode==0x3a))&&(u_int)imm[i]>=0x800)
7561       current.waswritten&=~(1<<dops[i].rs1);
7562
7563     /* Branch post-alloc */
7564     if(i>0)
7565     {
7566       current.wasdirty=current.dirty;
7567       switch(dops[i-1].itype) {
7568         case UJUMP:
7569           memcpy(&branch_regs[i-1],&current,sizeof(current));
7570           branch_regs[i-1].isconst=0;
7571           branch_regs[i-1].wasconst=0;
7572           branch_regs[i-1].u=branch_unneeded_reg[i-1]&~((1LL<<dops[i-1].rs1)|(1LL<<dops[i-1].rs2));
7573           alloc_cc(&branch_regs[i-1],i-1);
7574           dirty_reg(&branch_regs[i-1],CCREG);
7575           if(dops[i-1].rt1==31) { // JAL
7576             alloc_reg(&branch_regs[i-1],i-1,31);
7577             dirty_reg(&branch_regs[i-1],31);
7578           }
7579           memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
7580           memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
7581           break;
7582         case RJUMP:
7583           memcpy(&branch_regs[i-1],&current,sizeof(current));
7584           branch_regs[i-1].isconst=0;
7585           branch_regs[i-1].wasconst=0;
7586           branch_regs[i-1].u=branch_unneeded_reg[i-1]&~((1LL<<dops[i-1].rs1)|(1LL<<dops[i-1].rs2));
7587           alloc_cc(&branch_regs[i-1],i-1);
7588           dirty_reg(&branch_regs[i-1],CCREG);
7589           alloc_reg(&branch_regs[i-1],i-1,dops[i-1].rs1);
7590           if(dops[i-1].rt1!=0) { // JALR
7591             alloc_reg(&branch_regs[i-1],i-1,dops[i-1].rt1);
7592             dirty_reg(&branch_regs[i-1],dops[i-1].rt1);
7593           }
7594           #ifdef USE_MINI_HT
7595           if(dops[i-1].rs1==31) { // JALR
7596             alloc_reg(&branch_regs[i-1],i-1,RHASH);
7597             alloc_reg(&branch_regs[i-1],i-1,RHTBL);
7598           }
7599           #endif
7600           memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
7601           memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
7602           break;
7603         case CJUMP:
7604           if((dops[i-1].opcode&0x3E)==4) // BEQ/BNE
7605           {
7606             alloc_cc(&current,i-1);
7607             dirty_reg(&current,CCREG);
7608             if((dops[i-1].rs1&&(dops[i-1].rs1==dops[i].rt1||dops[i-1].rs1==dops[i].rt2))||
7609                (dops[i-1].rs2&&(dops[i-1].rs2==dops[i].rt1||dops[i-1].rs2==dops[i].rt2))) {
7610               // The delay slot overwrote one of our conditions
7611               // Delay slot goes after the test (in order)
7612               current.u=branch_unneeded_reg[i-1]&~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
7613               current.u|=1;
7614               delayslot_alloc(&current,i);
7615               current.isconst=0;
7616             }
7617             else
7618             {
7619               current.u=branch_unneeded_reg[i-1]&~((1LL<<dops[i-1].rs1)|(1LL<<dops[i-1].rs2));
7620               // Alloc the branch condition registers
7621               if(dops[i-1].rs1) alloc_reg(&current,i-1,dops[i-1].rs1);
7622               if(dops[i-1].rs2) alloc_reg(&current,i-1,dops[i-1].rs2);
7623             }
7624             memcpy(&branch_regs[i-1],&current,sizeof(current));
7625             branch_regs[i-1].isconst=0;
7626             branch_regs[i-1].wasconst=0;
7627             memcpy(&branch_regs[i-1].regmap_entry,&current.regmap,sizeof(current.regmap));
7628             memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
7629           }
7630           else
7631           if((dops[i-1].opcode&0x3E)==6) // BLEZ/BGTZ
7632           {
7633             alloc_cc(&current,i-1);
7634             dirty_reg(&current,CCREG);
7635             if(dops[i-1].rs1==dops[i].rt1||dops[i-1].rs1==dops[i].rt2) {
7636               // The delay slot overwrote the branch condition
7637               // Delay slot goes after the test (in order)
7638               current.u=branch_unneeded_reg[i-1]&~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
7639               current.u|=1;
7640               delayslot_alloc(&current,i);
7641               current.isconst=0;
7642             }
7643             else
7644             {
7645               current.u=branch_unneeded_reg[i-1]&~(1LL<<dops[i-1].rs1);
7646               // Alloc the branch condition register
7647               alloc_reg(&current,i-1,dops[i-1].rs1);
7648             }
7649             memcpy(&branch_regs[i-1],&current,sizeof(current));
7650             branch_regs[i-1].isconst=0;
7651             branch_regs[i-1].wasconst=0;
7652             memcpy(&branch_regs[i-1].regmap_entry,&current.regmap,sizeof(current.regmap));
7653             memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
7654           }
7655           else
7656           // Alloc the delay slot in case the branch is taken
7657           if((dops[i-1].opcode&0x3E)==0x14) // BEQL/BNEL
7658           {
7659             memcpy(&branch_regs[i-1],&current,sizeof(current));
7660             branch_regs[i-1].u=(branch_unneeded_reg[i-1]&~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2)|(1LL<<dops[i].rt1)|(1LL<<dops[i].rt2)))|1;
7661             alloc_cc(&branch_regs[i-1],i);
7662             dirty_reg(&branch_regs[i-1],CCREG);
7663             delayslot_alloc(&branch_regs[i-1],i);
7664             branch_regs[i-1].isconst=0;
7665             alloc_reg(&current,i,CCREG); // Not taken path
7666             dirty_reg(&current,CCREG);
7667             memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
7668           }
7669           else
7670           if((dops[i-1].opcode&0x3E)==0x16) // BLEZL/BGTZL
7671           {
7672             memcpy(&branch_regs[i-1],&current,sizeof(current));
7673             branch_regs[i-1].u=(branch_unneeded_reg[i-1]&~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2)|(1LL<<dops[i].rt1)|(1LL<<dops[i].rt2)))|1;
7674             alloc_cc(&branch_regs[i-1],i);
7675             dirty_reg(&branch_regs[i-1],CCREG);
7676             delayslot_alloc(&branch_regs[i-1],i);
7677             branch_regs[i-1].isconst=0;
7678             alloc_reg(&current,i,CCREG); // Not taken path
7679             dirty_reg(&current,CCREG);
7680             memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
7681           }
7682           break;
7683         case SJUMP:
7684           //if((dops[i-1].opcode2&0x1E)==0) // BLTZ/BGEZ
7685           if((dops[i-1].opcode2&0x0E)==0) // BLTZ/BGEZ
7686           {
7687             alloc_cc(&current,i-1);
7688             dirty_reg(&current,CCREG);
7689             if(dops[i-1].rs1==dops[i].rt1||dops[i-1].rs1==dops[i].rt2) {
7690               // The delay slot overwrote the branch condition
7691               // Delay slot goes after the test (in order)
7692               current.u=branch_unneeded_reg[i-1]&~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
7693               current.u|=1;
7694               delayslot_alloc(&current,i);
7695               current.isconst=0;
7696             }
7697             else
7698             {
7699               current.u=branch_unneeded_reg[i-1]&~(1LL<<dops[i-1].rs1);
7700               // Alloc the branch condition register
7701               alloc_reg(&current,i-1,dops[i-1].rs1);
7702             }
7703             memcpy(&branch_regs[i-1],&current,sizeof(current));
7704             branch_regs[i-1].isconst=0;
7705             branch_regs[i-1].wasconst=0;
7706             memcpy(&branch_regs[i-1].regmap_entry,&current.regmap,sizeof(current.regmap));
7707             memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
7708           }
7709           else
7710           // Alloc the delay slot in case the branch is taken
7711           if((dops[i-1].opcode2&0x1E)==2) // BLTZL/BGEZL
7712           {
7713             memcpy(&branch_regs[i-1],&current,sizeof(current));
7714             branch_regs[i-1].u=(branch_unneeded_reg[i-1]&~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2)|(1LL<<dops[i].rt1)|(1LL<<dops[i].rt2)))|1;
7715             alloc_cc(&branch_regs[i-1],i);
7716             dirty_reg(&branch_regs[i-1],CCREG);
7717             delayslot_alloc(&branch_regs[i-1],i);
7718             branch_regs[i-1].isconst=0;
7719             alloc_reg(&current,i,CCREG); // Not taken path
7720             dirty_reg(&current,CCREG);
7721             memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
7722           }
7723           // FIXME: BLTZAL/BGEZAL
7724           if(dops[i-1].opcode2&0x10) { // BxxZAL
7725             alloc_reg(&branch_regs[i-1],i-1,31);
7726             dirty_reg(&branch_regs[i-1],31);
7727           }
7728           break;
7729       }
7730
7731       if (dops[i-1].is_ujump)
7732       {
7733         if(dops[i-1].rt1==31) // JAL/JALR
7734         {
7735           // Subroutine call will return here, don't alloc any registers
7736           current.dirty=0;
7737           clear_all_regs(current.regmap);
7738           alloc_reg(&current,i,CCREG);
7739           dirty_reg(&current,CCREG);
7740         }
7741         else if(i+1<slen)
7742         {
7743           // Internal branch will jump here, match registers to caller
7744           current.dirty=0;
7745           clear_all_regs(current.regmap);
7746           alloc_reg(&current,i,CCREG);
7747           dirty_reg(&current,CCREG);
7748           for(j=i-1;j>=0;j--)
7749           {
7750             if(ba[j]==start+i*4+4) {
7751               memcpy(current.regmap,branch_regs[j].regmap,sizeof(current.regmap));
7752               current.dirty=branch_regs[j].dirty;
7753               break;
7754             }
7755           }
7756           while(j>=0) {
7757             if(ba[j]==start+i*4+4) {
7758               for(hr=0;hr<HOST_REGS;hr++) {
7759                 if(current.regmap[hr]!=branch_regs[j].regmap[hr]) {
7760                   current.regmap[hr]=-1;
7761                 }
7762                 current.dirty&=branch_regs[j].dirty;
7763               }
7764             }
7765             j--;
7766           }
7767         }
7768       }
7769     }
7770
7771     // Count cycles in between branches
7772     ccadj[i] = CLOCK_ADJUST(cc);
7773     if (i > 0 && (dops[i-1].is_jump || dops[i].itype == SYSCALL || dops[i].itype == HLECALL))
7774     {
7775       cc=0;
7776     }
7777 #if !defined(DRC_DBG)
7778     else if(dops[i].itype==C2OP&&gte_cycletab[source[i]&0x3f]>2)
7779     {
7780       // this should really be removed since the real stalls have been implemented,
7781       // but doing so causes sizeable perf regression against the older version
7782       u_int gtec = gte_cycletab[source[i] & 0x3f];
7783       cc += HACK_ENABLED(NDHACK_NO_STALLS) ? gtec/2 : 2;
7784     }
7785     else if(i>1&&dops[i].itype==STORE&&dops[i-1].itype==STORE&&dops[i-2].itype==STORE&&!dops[i].bt)
7786     {
7787       cc+=4;
7788     }
7789     else if(dops[i].itype==C2LS)
7790     {
7791       // same as with C2OP
7792       cc += HACK_ENABLED(NDHACK_NO_STALLS) ? 4 : 2;
7793     }
7794 #endif
7795     else
7796     {
7797       cc++;
7798     }
7799
7800     if(!dops[i].is_ds) {
7801       regs[i].dirty=current.dirty;
7802       regs[i].isconst=current.isconst;
7803       memcpy(constmap[i],current_constmap,sizeof(constmap[i]));
7804     }
7805     for(hr=0;hr<HOST_REGS;hr++) {
7806       if(hr!=EXCLUDE_REG&&regs[i].regmap[hr]>=0) {
7807         if(regmap_pre[i][hr]!=regs[i].regmap[hr]) {
7808           regs[i].wasconst&=~(1<<hr);
7809         }
7810       }
7811     }
7812     if(current.regmap[HOST_BTREG]==BTREG) current.regmap[HOST_BTREG]=-1;
7813     regs[i].waswritten=current.waswritten;
7814   }
7815 }
7816
7817 static noinline void pass4_cull_unused_regs(void)
7818 {
7819   u_int last_needed_regs[4] = {0,0,0,0};
7820   u_int nr=0;
7821   int i;
7822
7823   for (i=slen-1;i>=0;i--)
7824   {
7825     int hr;
7826     __builtin_prefetch(regs[i-2].regmap);
7827     if(dops[i].is_jump)
7828     {
7829       if(ba[i]<start || ba[i]>=(start+slen*4))
7830       {
7831         // Branch out of this block, don't need anything
7832         nr=0;
7833       }
7834       else
7835       {
7836         // Internal branch
7837         // Need whatever matches the target
7838         nr=0;
7839         int t=(ba[i]-start)>>2;
7840         for(hr=0;hr<HOST_REGS;hr++)
7841         {
7842           if(regs[i].regmap_entry[hr]>=0) {
7843             if(regs[i].regmap_entry[hr]==regs[t].regmap_entry[hr]) nr|=1<<hr;
7844           }
7845         }
7846       }
7847       // Conditional branch may need registers for following instructions
7848       if (!dops[i].is_ujump)
7849       {
7850         if(i<slen-2) {
7851           nr |= last_needed_regs[(i+2) & 3];
7852           for(hr=0;hr<HOST_REGS;hr++)
7853           {
7854             if(regmap_pre[i+2][hr]>=0&&get_reg(regs[i+2].regmap_entry,regmap_pre[i+2][hr])<0) nr&=~(1<<hr);
7855             //if((regmap_entry[i+2][hr])>=0) if(!((nr>>hr)&1)) printf("%x-bogus(%d=%d)\n",start+i*4,hr,regmap_entry[i+2][hr]);
7856           }
7857         }
7858       }
7859       // Don't need stuff which is overwritten
7860       //if(regs[i].regmap[hr]!=regmap_pre[i][hr]) nr&=~(1<<hr);
7861       //if(regs[i].regmap[hr]<0) nr&=~(1<<hr);
7862       // Merge in delay slot
7863       if (dops[i+1].rt1) nr &= ~get_regm(regs[i].regmap, dops[i+1].rt1);
7864       if (dops[i+1].rt2) nr &= ~get_regm(regs[i].regmap, dops[i+1].rt2);
7865       nr |= get_regm(regmap_pre[i], dops[i+1].rs1);
7866       nr |= get_regm(regmap_pre[i], dops[i+1].rs2);
7867       nr |= get_regm(regs[i].regmap_entry, dops[i+1].rs1);
7868       nr |= get_regm(regs[i].regmap_entry, dops[i+1].rs2);
7869       if (ram_offset && (dops[i+1].is_load || dops[i+1].is_store)) {
7870         nr |= get_regm(regmap_pre[i], ROREG);
7871         nr |= get_regm(regs[i].regmap_entry, ROREG);
7872       }
7873       if (dops[i+1].is_store) {
7874         nr |= get_regm(regmap_pre[i], INVCP);
7875         nr |= get_regm(regs[i].regmap_entry, INVCP);
7876       }
7877     }
7878     else if(dops[i].itype==SYSCALL||dops[i].itype==HLECALL||dops[i].itype==INTCALL)
7879     {
7880       // SYSCALL instruction (software interrupt)
7881       nr=0;
7882     }
7883     else if(dops[i].itype==COP0 && (source[i]&0x3f)==0x18)
7884     {
7885       // ERET instruction (return from interrupt)
7886       nr=0;
7887     }
7888     else // Non-branch
7889     {
7890       if(i<slen-1) {
7891         for(hr=0;hr<HOST_REGS;hr++) {
7892           if(regmap_pre[i+1][hr]>=0&&get_reg(regs[i+1].regmap_entry,regmap_pre[i+1][hr])<0) nr&=~(1<<hr);
7893           if(regs[i].regmap[hr]!=regmap_pre[i+1][hr]) nr&=~(1<<hr);
7894           if(regs[i].regmap[hr]!=regmap_pre[i][hr]) nr&=~(1<<hr);
7895           if(regs[i].regmap[hr]<0) nr&=~(1<<hr);
7896         }
7897       }
7898     }
7899     // Overwritten registers are not needed
7900     if (dops[i].rt1) nr &= ~get_regm(regs[i].regmap, dops[i].rt1);
7901     if (dops[i].rt2) nr &= ~get_regm(regs[i].regmap, dops[i].rt2);
7902     nr &= ~get_regm(regs[i].regmap, FTEMP);
7903     // Source registers are needed
7904     nr |= get_regm(regmap_pre[i], dops[i].rs1);
7905     nr |= get_regm(regmap_pre[i], dops[i].rs2);
7906     nr |= get_regm(regs[i].regmap_entry, dops[i].rs1);
7907     nr |= get_regm(regs[i].regmap_entry, dops[i].rs2);
7908     if (ram_offset && (dops[i].is_load || dops[i].is_store)) {
7909       nr |= get_regm(regmap_pre[i], ROREG);
7910       nr |= get_regm(regs[i].regmap_entry, ROREG);
7911     }
7912     if (dops[i].is_store) {
7913       nr |= get_regm(regmap_pre[i], INVCP);
7914       nr |= get_regm(regs[i].regmap_entry, INVCP);
7915     }
7916
7917     if (i > 0 && !dops[i].bt && regs[i].wasdirty)
7918     for(hr=0;hr<HOST_REGS;hr++)
7919     {
7920       // Don't store a register immediately after writing it,
7921       // may prevent dual-issue.
7922       // But do so if this is a branch target, otherwise we
7923       // might have to load the register before the branch.
7924       if((regs[i].wasdirty>>hr)&1) {
7925         if((regmap_pre[i][hr]>0&&!((unneeded_reg[i]>>regmap_pre[i][hr])&1))) {
7926           if(dops[i-1].rt1==regmap_pre[i][hr]) nr|=1<<hr;
7927           if(dops[i-1].rt2==regmap_pre[i][hr]) nr|=1<<hr;
7928         }
7929         if((regs[i].regmap_entry[hr]>0&&!((unneeded_reg[i]>>regs[i].regmap_entry[hr])&1))) {
7930           if(dops[i-1].rt1==regs[i].regmap_entry[hr]) nr|=1<<hr;
7931           if(dops[i-1].rt2==regs[i].regmap_entry[hr]) nr|=1<<hr;
7932         }
7933       }
7934     }
7935     // Cycle count is needed at branches.  Assume it is needed at the target too.
7936     if(i==0||dops[i].bt||dops[i].itype==CJUMP) {
7937       if(regmap_pre[i][HOST_CCREG]==CCREG) nr|=1<<HOST_CCREG;
7938       if(regs[i].regmap_entry[HOST_CCREG]==CCREG) nr|=1<<HOST_CCREG;
7939     }
7940     // Save it
7941     last_needed_regs[i & 3] = nr;
7942
7943     // Deallocate unneeded registers
7944     for(hr=0;hr<HOST_REGS;hr++)
7945     {
7946       if(!((nr>>hr)&1)) {
7947         if(regs[i].regmap_entry[hr]!=CCREG) regs[i].regmap_entry[hr]=-1;
7948         if(dops[i].is_jump)
7949         {
7950           int map1 = 0, map2 = 0, temp = 0; // or -1 ??
7951           if (dops[i+1].is_load || dops[i+1].is_store)
7952             map1 = ROREG;
7953           if (dops[i+1].is_store)
7954             map2 = INVCP;
7955           if(dops[i+1].itype==LOADLR || dops[i+1].itype==STORELR || dops[i+1].itype==C2LS)
7956             temp = FTEMP;
7957           if(regs[i].regmap[hr]!=dops[i].rs1 && regs[i].regmap[hr]!=dops[i].rs2 &&
7958              regs[i].regmap[hr]!=dops[i].rt1 && regs[i].regmap[hr]!=dops[i].rt2 &&
7959              regs[i].regmap[hr]!=dops[i+1].rt1 && regs[i].regmap[hr]!=dops[i+1].rt2 &&
7960              regs[i].regmap[hr]!=dops[i+1].rs1 && regs[i].regmap[hr]!=dops[i+1].rs2 &&
7961              regs[i].regmap[hr]!=temp && regs[i].regmap[hr]!=PTEMP &&
7962              regs[i].regmap[hr]!=RHASH && regs[i].regmap[hr]!=RHTBL &&
7963              regs[i].regmap[hr]!=RTEMP && regs[i].regmap[hr]!=CCREG &&
7964              regs[i].regmap[hr]!=map1 && regs[i].regmap[hr]!=map2)
7965           {
7966             regs[i].regmap[hr]=-1;
7967             regs[i].isconst&=~(1<<hr);
7968             regs[i].dirty&=~(1<<hr);
7969             regs[i+1].wasdirty&=~(1<<hr);
7970             if(branch_regs[i].regmap[hr]!=dops[i].rs1 && branch_regs[i].regmap[hr]!=dops[i].rs2 &&
7971                branch_regs[i].regmap[hr]!=dops[i].rt1 && branch_regs[i].regmap[hr]!=dops[i].rt2 &&
7972                branch_regs[i].regmap[hr]!=dops[i+1].rt1 && branch_regs[i].regmap[hr]!=dops[i+1].rt2 &&
7973                branch_regs[i].regmap[hr]!=dops[i+1].rs1 && branch_regs[i].regmap[hr]!=dops[i+1].rs2 &&
7974                branch_regs[i].regmap[hr]!=temp && branch_regs[i].regmap[hr]!=PTEMP &&
7975                branch_regs[i].regmap[hr]!=RHASH && branch_regs[i].regmap[hr]!=RHTBL &&
7976                branch_regs[i].regmap[hr]!=RTEMP && branch_regs[i].regmap[hr]!=CCREG &&
7977                branch_regs[i].regmap[hr]!=map1 && branch_regs[i].regmap[hr]!=map2)
7978             {
7979               branch_regs[i].regmap[hr]=-1;
7980               branch_regs[i].regmap_entry[hr]=-1;
7981               if (!dops[i].is_ujump)
7982               {
7983                 if (i < slen-2) {
7984                   regmap_pre[i+2][hr]=-1;
7985                   regs[i+2].wasconst&=~(1<<hr);
7986                 }
7987               }
7988             }
7989           }
7990         }
7991         else
7992         {
7993           // Non-branch
7994           if(i>0)
7995           {
7996             int map1 = -1, map2 = -1, temp=-1;
7997             if (dops[i].is_load || dops[i].is_store)
7998               map1 = ROREG;
7999             if (dops[i].is_store)
8000               map2 = INVCP;
8001             if (dops[i].itype==LOADLR || dops[i].itype==STORELR || dops[i].itype==C2LS)
8002               temp = FTEMP;
8003             if(regs[i].regmap[hr]!=dops[i].rt1 && regs[i].regmap[hr]!=dops[i].rt2 &&
8004                regs[i].regmap[hr]!=dops[i].rs1 && regs[i].regmap[hr]!=dops[i].rs2 &&
8005                regs[i].regmap[hr]!=temp && regs[i].regmap[hr]!=map1 && regs[i].regmap[hr]!=map2 &&
8006                //(dops[i].itype!=SPAN||regs[i].regmap[hr]!=CCREG)
8007                regs[i].regmap[hr] != CCREG)
8008             {
8009               if(i<slen-1&&!dops[i].is_ds) {
8010                 assert(regs[i].regmap[hr]<64);
8011                 if(regmap_pre[i+1][hr]!=-1 || regs[i].regmap[hr]>0)
8012                 if(regmap_pre[i+1][hr]!=regs[i].regmap[hr])
8013                 {
8014                   SysPrintf("fail: %x (%d %d!=%d)\n",start+i*4,hr,regmap_pre[i+1][hr],regs[i].regmap[hr]);
8015                   assert(regmap_pre[i+1][hr]==regs[i].regmap[hr]);
8016                 }
8017                 regmap_pre[i+1][hr]=-1;
8018                 if(regs[i+1].regmap_entry[hr]==CCREG) regs[i+1].regmap_entry[hr]=-1;
8019                 regs[i+1].wasconst&=~(1<<hr);
8020               }
8021               regs[i].regmap[hr]=-1;
8022               regs[i].isconst&=~(1<<hr);
8023               regs[i].dirty&=~(1<<hr);
8024               regs[i+1].wasdirty&=~(1<<hr);
8025             }
8026           }
8027         }
8028       } // if needed
8029     } // for hr
8030   }
8031 }
8032
8033 // If a register is allocated during a loop, try to allocate it for the
8034 // entire loop, if possible.  This avoids loading/storing registers
8035 // inside of the loop.
8036 static noinline void pass5a_preallocate1(void)
8037 {
8038   int i, j, hr;
8039   signed char f_regmap[HOST_REGS];
8040   clear_all_regs(f_regmap);
8041   for(i=0;i<slen-1;i++)
8042   {
8043     if(dops[i].itype==UJUMP||dops[i].itype==CJUMP||dops[i].itype==SJUMP)
8044     {
8045       if(ba[i]>=start && ba[i]<(start+i*4))
8046       if(dops[i+1].itype==NOP||dops[i+1].itype==MOV||dops[i+1].itype==ALU
8047       ||dops[i+1].itype==SHIFTIMM||dops[i+1].itype==IMM16||dops[i+1].itype==LOAD
8048       ||dops[i+1].itype==STORE||dops[i+1].itype==STORELR||dops[i+1].itype==C1LS
8049       ||dops[i+1].itype==SHIFT||dops[i+1].itype==COP1
8050       ||dops[i+1].itype==COP2||dops[i+1].itype==C2LS||dops[i+1].itype==C2OP)
8051       {
8052         int t=(ba[i]-start)>>2;
8053         if(t > 0 && !dops[t-1].is_jump) // loop_preload can't handle jumps into delay slots
8054         if(t<2||(dops[t-2].itype!=UJUMP&&dops[t-2].itype!=RJUMP)||dops[t-2].rt1!=31) // call/ret assumes no registers allocated
8055         for(hr=0;hr<HOST_REGS;hr++)
8056         {
8057           if(regs[i].regmap[hr]>=0) {
8058             if(f_regmap[hr]!=regs[i].regmap[hr]) {
8059               // dealloc old register
8060               int n;
8061               for(n=0;n<HOST_REGS;n++)
8062               {
8063                 if(f_regmap[n]==regs[i].regmap[hr]) {f_regmap[n]=-1;}
8064               }
8065               // and alloc new one
8066               f_regmap[hr]=regs[i].regmap[hr];
8067             }
8068           }
8069           if(branch_regs[i].regmap[hr]>=0) {
8070             if(f_regmap[hr]!=branch_regs[i].regmap[hr]) {
8071               // dealloc old register
8072               int n;
8073               for(n=0;n<HOST_REGS;n++)
8074               {
8075                 if(f_regmap[n]==branch_regs[i].regmap[hr]) {f_regmap[n]=-1;}
8076               }
8077               // and alloc new one
8078               f_regmap[hr]=branch_regs[i].regmap[hr];
8079             }
8080           }
8081           if(dops[i].ooo) {
8082             if(count_free_regs(regs[i].regmap)<=minimum_free_regs[i+1])
8083               f_regmap[hr]=branch_regs[i].regmap[hr];
8084           }else{
8085             if(count_free_regs(branch_regs[i].regmap)<=minimum_free_regs[i+1])
8086               f_regmap[hr]=branch_regs[i].regmap[hr];
8087           }
8088           // Avoid dirty->clean transition
8089           #ifdef DESTRUCTIVE_WRITEBACK
8090           if(t>0) if(get_reg(regmap_pre[t],f_regmap[hr])>=0) if((regs[t].wasdirty>>get_reg(regmap_pre[t],f_regmap[hr]))&1) f_regmap[hr]=-1;
8091           #endif
8092           // This check is only strictly required in the DESTRUCTIVE_WRITEBACK
8093           // case above, however it's always a good idea.  We can't hoist the
8094           // load if the register was already allocated, so there's no point
8095           // wasting time analyzing most of these cases.  It only "succeeds"
8096           // when the mapping was different and the load can be replaced with
8097           // a mov, which is of negligible benefit.  So such cases are
8098           // skipped below.
8099           if(f_regmap[hr]>0) {
8100             if(regs[t].regmap[hr]==f_regmap[hr]||(regs[t].regmap_entry[hr]<0&&get_reg(regmap_pre[t],f_regmap[hr])<0)) {
8101               int r=f_regmap[hr];
8102               for(j=t;j<=i;j++)
8103               {
8104                 //printf("Test %x -> %x, %x %d/%d\n",start+i*4,ba[i],start+j*4,hr,r);
8105                 if(r<34&&((unneeded_reg[j]>>r)&1)) break;
8106                 assert(r < 64);
8107                 if(regs[j].regmap[hr]==f_regmap[hr]&&f_regmap[hr]<TEMPREG) {
8108                   //printf("Hit %x -> %x, %x %d/%d\n",start+i*4,ba[i],start+j*4,hr,r);
8109                   int k;
8110                   if(regs[i].regmap[hr]==-1&&branch_regs[i].regmap[hr]==-1) {
8111                     if(get_reg(regs[i].regmap,f_regmap[hr])>=0) break;
8112                     if(get_reg(regs[i+2].regmap,f_regmap[hr])>=0) break;
8113                     k=i;
8114                     while(k>1&&regs[k-1].regmap[hr]==-1) {
8115                       if(count_free_regs(regs[k-1].regmap)<=minimum_free_regs[k-1]) {
8116                         //printf("no free regs for store %x\n",start+(k-1)*4);
8117                         break;
8118                       }
8119                       if(get_reg(regs[k-1].regmap,f_regmap[hr])>=0) {
8120                         //printf("no-match due to different register\n");
8121                         break;
8122                       }
8123                       if (dops[k-2].is_jump) {
8124                         //printf("no-match due to branch\n");
8125                         break;
8126                       }
8127                       // call/ret fast path assumes no registers allocated
8128                       if(k>2&&(dops[k-3].itype==UJUMP||dops[k-3].itype==RJUMP)&&dops[k-3].rt1==31) {
8129                         break;
8130                       }
8131                       k--;
8132                     }
8133                     if(regs[k-1].regmap[hr]==f_regmap[hr]&&regmap_pre[k][hr]==f_regmap[hr]) {
8134                       //printf("Extend r%d, %x ->\n",hr,start+k*4);
8135                       while(k<i) {
8136                         regs[k].regmap_entry[hr]=f_regmap[hr];
8137                         regs[k].regmap[hr]=f_regmap[hr];
8138                         regmap_pre[k+1][hr]=f_regmap[hr];
8139                         regs[k].wasdirty&=~(1<<hr);
8140                         regs[k].dirty&=~(1<<hr);
8141                         regs[k].wasdirty|=(1<<hr)&regs[k-1].dirty;
8142                         regs[k].dirty|=(1<<hr)&regs[k].wasdirty;
8143                         regs[k].wasconst&=~(1<<hr);
8144                         regs[k].isconst&=~(1<<hr);
8145                         k++;
8146                       }
8147                     }
8148                     else {
8149                       //printf("Fail Extend r%d, %x ->\n",hr,start+k*4);
8150                       break;
8151                     }
8152                     assert(regs[i-1].regmap[hr]==f_regmap[hr]);
8153                     if(regs[i-1].regmap[hr]==f_regmap[hr]&&regmap_pre[i][hr]==f_regmap[hr]) {
8154                       //printf("OK fill %x (r%d)\n",start+i*4,hr);
8155                       regs[i].regmap_entry[hr]=f_regmap[hr];
8156                       regs[i].regmap[hr]=f_regmap[hr];
8157                       regs[i].wasdirty&=~(1<<hr);
8158                       regs[i].dirty&=~(1<<hr);
8159                       regs[i].wasdirty|=(1<<hr)&regs[i-1].dirty;
8160                       regs[i].dirty|=(1<<hr)&regs[i-1].dirty;
8161                       regs[i].wasconst&=~(1<<hr);
8162                       regs[i].isconst&=~(1<<hr);
8163                       branch_regs[i].regmap_entry[hr]=f_regmap[hr];
8164                       branch_regs[i].wasdirty&=~(1<<hr);
8165                       branch_regs[i].wasdirty|=(1<<hr)&regs[i].dirty;
8166                       branch_regs[i].regmap[hr]=f_regmap[hr];
8167                       branch_regs[i].dirty&=~(1<<hr);
8168                       branch_regs[i].dirty|=(1<<hr)&regs[i].dirty;
8169                       branch_regs[i].wasconst&=~(1<<hr);
8170                       branch_regs[i].isconst&=~(1<<hr);
8171                       if (!dops[i].is_ujump) {
8172                         regmap_pre[i+2][hr]=f_regmap[hr];
8173                         regs[i+2].wasdirty&=~(1<<hr);
8174                         regs[i+2].wasdirty|=(1<<hr)&regs[i].dirty;
8175                       }
8176                     }
8177                   }
8178                   for(k=t;k<j;k++) {
8179                     // Alloc register clean at beginning of loop,
8180                     // but may dirty it in pass 6
8181                     regs[k].regmap_entry[hr]=f_regmap[hr];
8182                     regs[k].regmap[hr]=f_regmap[hr];
8183                     regs[k].dirty&=~(1<<hr);
8184                     regs[k].wasconst&=~(1<<hr);
8185                     regs[k].isconst&=~(1<<hr);
8186                     if (dops[k].is_jump) {
8187                       branch_regs[k].regmap_entry[hr]=f_regmap[hr];
8188                       branch_regs[k].regmap[hr]=f_regmap[hr];
8189                       branch_regs[k].dirty&=~(1<<hr);
8190                       branch_regs[k].wasconst&=~(1<<hr);
8191                       branch_regs[k].isconst&=~(1<<hr);
8192                       if (!dops[k].is_ujump) {
8193                         regmap_pre[k+2][hr]=f_regmap[hr];
8194                         regs[k+2].wasdirty&=~(1<<hr);
8195                       }
8196                     }
8197                     else
8198                     {
8199                       regmap_pre[k+1][hr]=f_regmap[hr];
8200                       regs[k+1].wasdirty&=~(1<<hr);
8201                     }
8202                   }
8203                   if(regs[j].regmap[hr]==f_regmap[hr])
8204                     regs[j].regmap_entry[hr]=f_regmap[hr];
8205                   break;
8206                 }
8207                 if(j==i) break;
8208                 if(regs[j].regmap[hr]>=0)
8209                   break;
8210                 if(get_reg(regs[j].regmap,f_regmap[hr])>=0) {
8211                   //printf("no-match due to different register\n");
8212                   break;
8213                 }
8214                 if (dops[j].is_ujump)
8215                 {
8216                   // Stop on unconditional branch
8217                   break;
8218                 }
8219                 if(dops[j].itype==CJUMP||dops[j].itype==SJUMP)
8220                 {
8221                   if(dops[j].ooo) {
8222                     if(count_free_regs(regs[j].regmap)<=minimum_free_regs[j+1])
8223                       break;
8224                   }else{
8225                     if(count_free_regs(branch_regs[j].regmap)<=minimum_free_regs[j+1])
8226                       break;
8227                   }
8228                   if(get_reg(branch_regs[j].regmap,f_regmap[hr])>=0) {
8229                     //printf("no-match due to different register (branch)\n");
8230                     break;
8231                   }
8232                 }
8233                 if(count_free_regs(regs[j].regmap)<=minimum_free_regs[j]) {
8234                   //printf("No free regs for store %x\n",start+j*4);
8235                   break;
8236                 }
8237                 assert(f_regmap[hr]<64);
8238               }
8239             }
8240           }
8241         }
8242       }
8243     }else{
8244       // Non branch or undetermined branch target
8245       for(hr=0;hr<HOST_REGS;hr++)
8246       {
8247         if(hr!=EXCLUDE_REG) {
8248           if(regs[i].regmap[hr]>=0) {
8249             if(f_regmap[hr]!=regs[i].regmap[hr]) {
8250               // dealloc old register
8251               int n;
8252               for(n=0;n<HOST_REGS;n++)
8253               {
8254                 if(f_regmap[n]==regs[i].regmap[hr]) {f_regmap[n]=-1;}
8255               }
8256               // and alloc new one
8257               f_regmap[hr]=regs[i].regmap[hr];
8258             }
8259           }
8260         }
8261       }
8262       // Try to restore cycle count at branch targets
8263       if(dops[i].bt) {
8264         for(j=i;j<slen-1;j++) {
8265           if(regs[j].regmap[HOST_CCREG]!=-1) break;
8266           if(count_free_regs(regs[j].regmap)<=minimum_free_regs[j]) {
8267             //printf("no free regs for store %x\n",start+j*4);
8268             break;
8269           }
8270         }
8271         if(regs[j].regmap[HOST_CCREG]==CCREG) {
8272           int k=i;
8273           //printf("Extend CC, %x -> %x\n",start+k*4,start+j*4);
8274           while(k<j) {
8275             regs[k].regmap_entry[HOST_CCREG]=CCREG;
8276             regs[k].regmap[HOST_CCREG]=CCREG;
8277             regmap_pre[k+1][HOST_CCREG]=CCREG;
8278             regs[k+1].wasdirty|=1<<HOST_CCREG;
8279             regs[k].dirty|=1<<HOST_CCREG;
8280             regs[k].wasconst&=~(1<<HOST_CCREG);
8281             regs[k].isconst&=~(1<<HOST_CCREG);
8282             k++;
8283           }
8284           regs[j].regmap_entry[HOST_CCREG]=CCREG;
8285         }
8286         // Work backwards from the branch target
8287         if(j>i&&f_regmap[HOST_CCREG]==CCREG)
8288         {
8289           //printf("Extend backwards\n");
8290           int k;
8291           k=i;
8292           while(regs[k-1].regmap[HOST_CCREG]==-1) {
8293             if(count_free_regs(regs[k-1].regmap)<=minimum_free_regs[k-1]) {
8294               //printf("no free regs for store %x\n",start+(k-1)*4);
8295               break;
8296             }
8297             k--;
8298           }
8299           if(regs[k-1].regmap[HOST_CCREG]==CCREG) {
8300             //printf("Extend CC, %x ->\n",start+k*4);
8301             while(k<=i) {
8302               regs[k].regmap_entry[HOST_CCREG]=CCREG;
8303               regs[k].regmap[HOST_CCREG]=CCREG;
8304               regmap_pre[k+1][HOST_CCREG]=CCREG;
8305               regs[k+1].wasdirty|=1<<HOST_CCREG;
8306               regs[k].dirty|=1<<HOST_CCREG;
8307               regs[k].wasconst&=~(1<<HOST_CCREG);
8308               regs[k].isconst&=~(1<<HOST_CCREG);
8309               k++;
8310             }
8311           }
8312           else {
8313             //printf("Fail Extend CC, %x ->\n",start+k*4);
8314           }
8315         }
8316       }
8317       if(dops[i].itype!=STORE&&dops[i].itype!=STORELR&&dops[i].itype!=C1LS&&dops[i].itype!=SHIFT&&
8318          dops[i].itype!=NOP&&dops[i].itype!=MOV&&dops[i].itype!=ALU&&dops[i].itype!=SHIFTIMM&&
8319          dops[i].itype!=IMM16&&dops[i].itype!=LOAD&&dops[i].itype!=COP1)
8320       {
8321         memcpy(f_regmap,regs[i].regmap,sizeof(f_regmap));
8322       }
8323     }
8324   }
8325 }
8326
8327 // This allocates registers (if possible) one instruction prior
8328 // to use, which can avoid a load-use penalty on certain CPUs.
8329 static noinline void pass5b_preallocate2(void)
8330 {
8331   int i, hr;
8332   for(i=0;i<slen-1;i++)
8333   {
8334     if (!i || !dops[i-1].is_jump)
8335     {
8336       if(!dops[i+1].bt)
8337       {
8338         if(dops[i].itype==ALU||dops[i].itype==MOV||dops[i].itype==LOAD||dops[i].itype==SHIFTIMM||dops[i].itype==IMM16
8339            ||((dops[i].itype==COP1||dops[i].itype==COP2)&&dops[i].opcode2<3))
8340         {
8341           if(dops[i+1].rs1) {
8342             if((hr=get_reg(regs[i+1].regmap,dops[i+1].rs1))>=0)
8343             {
8344               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
8345               {
8346                 regs[i].regmap[hr]=regs[i+1].regmap[hr];
8347                 regmap_pre[i+1][hr]=regs[i+1].regmap[hr];
8348                 regs[i+1].regmap_entry[hr]=regs[i+1].regmap[hr];
8349                 regs[i].isconst&=~(1<<hr);
8350                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
8351                 constmap[i][hr]=constmap[i+1][hr];
8352                 regs[i+1].wasdirty&=~(1<<hr);
8353                 regs[i].dirty&=~(1<<hr);
8354               }
8355             }
8356           }
8357           if(dops[i+1].rs2) {
8358             if((hr=get_reg(regs[i+1].regmap,dops[i+1].rs2))>=0)
8359             {
8360               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
8361               {
8362                 regs[i].regmap[hr]=regs[i+1].regmap[hr];
8363                 regmap_pre[i+1][hr]=regs[i+1].regmap[hr];
8364                 regs[i+1].regmap_entry[hr]=regs[i+1].regmap[hr];
8365                 regs[i].isconst&=~(1<<hr);
8366                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
8367                 constmap[i][hr]=constmap[i+1][hr];
8368                 regs[i+1].wasdirty&=~(1<<hr);
8369                 regs[i].dirty&=~(1<<hr);
8370               }
8371             }
8372           }
8373           // Preload target address for load instruction (non-constant)
8374           if(dops[i+1].itype==LOAD&&dops[i+1].rs1&&get_reg(regs[i+1].regmap,dops[i+1].rs1)<0) {
8375             if((hr=get_reg(regs[i+1].regmap,dops[i+1].rt1))>=0)
8376             {
8377               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
8378               {
8379                 regs[i].regmap[hr]=dops[i+1].rs1;
8380                 regmap_pre[i+1][hr]=dops[i+1].rs1;
8381                 regs[i+1].regmap_entry[hr]=dops[i+1].rs1;
8382                 regs[i].isconst&=~(1<<hr);
8383                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
8384                 constmap[i][hr]=constmap[i+1][hr];
8385                 regs[i+1].wasdirty&=~(1<<hr);
8386                 regs[i].dirty&=~(1<<hr);
8387               }
8388             }
8389           }
8390           // Load source into target register
8391           if(dops[i+1].use_lt1&&get_reg(regs[i+1].regmap,dops[i+1].rs1)<0) {
8392             if((hr=get_reg(regs[i+1].regmap,dops[i+1].rt1))>=0)
8393             {
8394               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
8395               {
8396                 regs[i].regmap[hr]=dops[i+1].rs1;
8397                 regmap_pre[i+1][hr]=dops[i+1].rs1;
8398                 regs[i+1].regmap_entry[hr]=dops[i+1].rs1;
8399                 regs[i].isconst&=~(1<<hr);
8400                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
8401                 constmap[i][hr]=constmap[i+1][hr];
8402                 regs[i+1].wasdirty&=~(1<<hr);
8403                 regs[i].dirty&=~(1<<hr);
8404               }
8405             }
8406           }
8407           // Address for store instruction (non-constant)
8408           if(dops[i+1].itype==STORE||dops[i+1].itype==STORELR
8409              ||(dops[i+1].opcode&0x3b)==0x39||(dops[i+1].opcode&0x3b)==0x3a) { // SB/SH/SW/SD/SWC1/SDC1/SWC2/SDC2
8410             if(get_reg(regs[i+1].regmap,dops[i+1].rs1)<0) {
8411               hr=get_reg2(regs[i].regmap,regs[i+1].regmap,-1);
8412               if(hr<0) hr=get_reg_temp(regs[i+1].regmap);
8413               else {
8414                 regs[i+1].regmap[hr]=AGEN1+((i+1)&1);
8415                 regs[i+1].isconst&=~(1<<hr);
8416               }
8417               assert(hr>=0);
8418               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
8419               {
8420                 regs[i].regmap[hr]=dops[i+1].rs1;
8421                 regmap_pre[i+1][hr]=dops[i+1].rs1;
8422                 regs[i+1].regmap_entry[hr]=dops[i+1].rs1;
8423                 regs[i].isconst&=~(1<<hr);
8424                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
8425                 constmap[i][hr]=constmap[i+1][hr];
8426                 regs[i+1].wasdirty&=~(1<<hr);
8427                 regs[i].dirty&=~(1<<hr);
8428               }
8429             }
8430           }
8431           if(dops[i+1].itype==LOADLR||(dops[i+1].opcode&0x3b)==0x31||(dops[i+1].opcode&0x3b)==0x32) { // LWC1/LDC1, LWC2/LDC2
8432             if(get_reg(regs[i+1].regmap,dops[i+1].rs1)<0) {
8433               int nr;
8434               hr=get_reg(regs[i+1].regmap,FTEMP);
8435               assert(hr>=0);
8436               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
8437               {
8438                 regs[i].regmap[hr]=dops[i+1].rs1;
8439                 regmap_pre[i+1][hr]=dops[i+1].rs1;
8440                 regs[i+1].regmap_entry[hr]=dops[i+1].rs1;
8441                 regs[i].isconst&=~(1<<hr);
8442                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
8443                 constmap[i][hr]=constmap[i+1][hr];
8444                 regs[i+1].wasdirty&=~(1<<hr);
8445                 regs[i].dirty&=~(1<<hr);
8446               }
8447               else if((nr=get_reg2(regs[i].regmap,regs[i+1].regmap,-1))>=0)
8448               {
8449                 // move it to another register
8450                 regs[i+1].regmap[hr]=-1;
8451                 regmap_pre[i+2][hr]=-1;
8452                 regs[i+1].regmap[nr]=FTEMP;
8453                 regmap_pre[i+2][nr]=FTEMP;
8454                 regs[i].regmap[nr]=dops[i+1].rs1;
8455                 regmap_pre[i+1][nr]=dops[i+1].rs1;
8456                 regs[i+1].regmap_entry[nr]=dops[i+1].rs1;
8457                 regs[i].isconst&=~(1<<nr);
8458                 regs[i+1].isconst&=~(1<<nr);
8459                 regs[i].dirty&=~(1<<nr);
8460                 regs[i+1].wasdirty&=~(1<<nr);
8461                 regs[i+1].dirty&=~(1<<nr);
8462                 regs[i+2].wasdirty&=~(1<<nr);
8463               }
8464             }
8465           }
8466           if(dops[i+1].itype==LOAD||dops[i+1].itype==LOADLR||dops[i+1].itype==STORE||dops[i+1].itype==STORELR/*||dops[i+1].itype==C1LS||||dops[i+1].itype==C2LS*/) {
8467             hr = -1;
8468             if(dops[i+1].itype==LOAD)
8469               hr=get_reg(regs[i+1].regmap,dops[i+1].rt1);
8470             if(dops[i+1].itype==LOADLR||(dops[i+1].opcode&0x3b)==0x31||(dops[i+1].opcode&0x3b)==0x32) // LWC1/LDC1, LWC2/LDC2
8471               hr=get_reg(regs[i+1].regmap,FTEMP);
8472             if(dops[i+1].itype==STORE||dops[i+1].itype==STORELR||(dops[i+1].opcode&0x3b)==0x39||(dops[i+1].opcode&0x3b)==0x3a) { // SWC1/SDC1/SWC2/SDC2
8473               hr=get_reg(regs[i+1].regmap,AGEN1+((i+1)&1));
8474               if(hr<0) hr=get_reg_temp(regs[i+1].regmap);
8475             }
8476             if(hr>=0&&regs[i].regmap[hr]<0) {
8477               int rs=get_reg(regs[i+1].regmap,dops[i+1].rs1);
8478               if(rs>=0&&((regs[i+1].wasconst>>rs)&1)) {
8479                 regs[i].regmap[hr]=AGEN1+((i+1)&1);
8480                 regmap_pre[i+1][hr]=AGEN1+((i+1)&1);
8481                 regs[i+1].regmap_entry[hr]=AGEN1+((i+1)&1);
8482                 regs[i].isconst&=~(1<<hr);
8483                 regs[i+1].wasdirty&=~(1<<hr);
8484                 regs[i].dirty&=~(1<<hr);
8485               }
8486             }
8487           }
8488         }
8489       }
8490     }
8491   }
8492 }
8493
8494 // Write back dirty registers as soon as we will no longer modify them,
8495 // so that we don't end up with lots of writes at the branches.
8496 static noinline void pass6_clean_registers(int istart, int iend, int wr)
8497 {
8498   static u_int wont_dirty[MAXBLOCK];
8499   static u_int will_dirty[MAXBLOCK];
8500   int i;
8501   int r;
8502   u_int will_dirty_i,will_dirty_next,temp_will_dirty;
8503   u_int wont_dirty_i,wont_dirty_next,temp_wont_dirty;
8504   if(iend==slen-1) {
8505     will_dirty_i=will_dirty_next=0;
8506     wont_dirty_i=wont_dirty_next=0;
8507   }else{
8508     will_dirty_i=will_dirty_next=will_dirty[iend+1];
8509     wont_dirty_i=wont_dirty_next=wont_dirty[iend+1];
8510   }
8511   for (i=iend;i>=istart;i--)
8512   {
8513     signed char rregmap_i[RRMAP_SIZE];
8514     u_int hr_candirty = 0;
8515     assert(HOST_REGS < 32);
8516     make_rregs(regs[i].regmap, rregmap_i, &hr_candirty);
8517     __builtin_prefetch(regs[i-1].regmap);
8518     if(dops[i].is_jump)
8519     {
8520       signed char branch_rregmap_i[RRMAP_SIZE];
8521       u_int branch_hr_candirty = 0;
8522       make_rregs(branch_regs[i].regmap, branch_rregmap_i, &branch_hr_candirty);
8523       if(ba[i]<start || ba[i]>=(start+slen*4))
8524       {
8525         // Branch out of this block, flush all regs
8526         will_dirty_i = 0;
8527         will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt1) & 31);
8528         will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt2) & 31);
8529         will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt1) & 31);
8530         will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt2) & 31);
8531         will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, CCREG) & 31);
8532         will_dirty_i &= branch_hr_candirty;
8533         if (dops[i].is_ujump)
8534         {
8535           // Unconditional branch
8536           wont_dirty_i = 0;
8537           // Merge in delay slot (will dirty)
8538           will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt1) & 31);
8539           will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt2) & 31);
8540           will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt1) & 31);
8541           will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt2) & 31);
8542           will_dirty_i |= 1u << (get_rreg(rregmap_i, CCREG) & 31);
8543           will_dirty_i &= hr_candirty;
8544         }
8545         else
8546         {
8547           // Conditional branch
8548           wont_dirty_i = wont_dirty_next;
8549           // Merge in delay slot (will dirty)
8550           // (the original code had no explanation why these 2 are commented out)
8551           //will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt1) & 31);
8552           //will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt2) & 31);
8553           will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt1) & 31);
8554           will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt2) & 31);
8555           will_dirty_i |= 1u << (get_rreg(rregmap_i, CCREG) & 31);
8556           will_dirty_i &= hr_candirty;
8557         }
8558         // Merge in delay slot (wont dirty)
8559         wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt1) & 31);
8560         wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt2) & 31);
8561         wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt1) & 31);
8562         wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt2) & 31);
8563         wont_dirty_i |= 1u << (get_rreg(rregmap_i, CCREG) & 31);
8564         wont_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt1) & 31);
8565         wont_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt2) & 31);
8566         wont_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt1) & 31);
8567         wont_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt2) & 31);
8568         wont_dirty_i |= 1u << (get_rreg(branch_rregmap_i, CCREG) & 31);
8569         wont_dirty_i &= ~(1u << 31);
8570         if(wr) {
8571           #ifndef DESTRUCTIVE_WRITEBACK
8572           branch_regs[i].dirty&=wont_dirty_i;
8573           #endif
8574           branch_regs[i].dirty|=will_dirty_i;
8575         }
8576       }
8577       else
8578       {
8579         // Internal branch
8580         if(ba[i]<=start+i*4) {
8581           // Backward branch
8582           if (dops[i].is_ujump)
8583           {
8584             // Unconditional branch
8585             temp_will_dirty=0;
8586             temp_wont_dirty=0;
8587             // Merge in delay slot (will dirty)
8588             temp_will_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt1) & 31);
8589             temp_will_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt2) & 31);
8590             temp_will_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt1) & 31);
8591             temp_will_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt2) & 31);
8592             temp_will_dirty |= 1u << (get_rreg(branch_rregmap_i, CCREG) & 31);
8593             temp_will_dirty &= branch_hr_candirty;
8594             temp_will_dirty |= 1u << (get_rreg(rregmap_i, dops[i].rt1) & 31);
8595             temp_will_dirty |= 1u << (get_rreg(rregmap_i, dops[i].rt2) & 31);
8596             temp_will_dirty |= 1u << (get_rreg(rregmap_i, dops[i+1].rt1) & 31);
8597             temp_will_dirty |= 1u << (get_rreg(rregmap_i, dops[i+1].rt2) & 31);
8598             temp_will_dirty |= 1u << (get_rreg(rregmap_i, CCREG) & 31);
8599             temp_will_dirty &= hr_candirty;
8600           } else {
8601             // Conditional branch (not taken case)
8602             temp_will_dirty=will_dirty_next;
8603             temp_wont_dirty=wont_dirty_next;
8604             // Merge in delay slot (will dirty)
8605             temp_will_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt1) & 31);
8606             temp_will_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt2) & 31);
8607             temp_will_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt1) & 31);
8608             temp_will_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt2) & 31);
8609             temp_will_dirty |= 1u << (get_rreg(branch_rregmap_i, CCREG) & 31);
8610             temp_will_dirty &= branch_hr_candirty;
8611             //temp_will_dirty |= 1u << (get_rreg(rregmap_i, dops[i].rt1) & 31);
8612             //temp_will_dirty |= 1u << (get_rreg(rregmap_i, dops[i].rt2) & 31);
8613             temp_will_dirty |= 1u << (get_rreg(rregmap_i, dops[i+1].rt1) & 31);
8614             temp_will_dirty |= 1u << (get_rreg(rregmap_i, dops[i+1].rt2) & 31);
8615             temp_will_dirty |= 1u << (get_rreg(rregmap_i, CCREG) & 31);
8616             temp_will_dirty &= hr_candirty;
8617           }
8618           // Merge in delay slot (wont dirty)
8619           temp_wont_dirty |= 1u << (get_rreg(rregmap_i, dops[i].rt1) & 31);
8620           temp_wont_dirty |= 1u << (get_rreg(rregmap_i, dops[i].rt2) & 31);
8621           temp_wont_dirty |= 1u << (get_rreg(rregmap_i, dops[i+1].rt1) & 31);
8622           temp_wont_dirty |= 1u << (get_rreg(rregmap_i, dops[i+1].rt2) & 31);
8623           temp_wont_dirty |= 1u << (get_rreg(rregmap_i, CCREG) & 31);
8624           temp_wont_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt1) & 31);
8625           temp_wont_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt2) & 31);
8626           temp_wont_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt1) & 31);
8627           temp_wont_dirty |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt2) & 31);
8628           temp_wont_dirty |= 1u << (get_rreg(branch_rregmap_i, CCREG) & 31);
8629           temp_wont_dirty &= ~(1u << 31);
8630           // Deal with changed mappings
8631           if(i<iend) {
8632             for(r=0;r<HOST_REGS;r++) {
8633               if(r!=EXCLUDE_REG) {
8634                 if(regs[i].regmap[r]!=regmap_pre[i][r]) {
8635                   temp_will_dirty&=~(1<<r);
8636                   temp_wont_dirty&=~(1<<r);
8637                   if(regmap_pre[i][r]>0 && regmap_pre[i][r]<34) {
8638                     temp_will_dirty|=((unneeded_reg[i]>>regmap_pre[i][r])&1)<<r;
8639                     temp_wont_dirty|=((unneeded_reg[i]>>regmap_pre[i][r])&1)<<r;
8640                   } else {
8641                     temp_will_dirty|=1<<r;
8642                     temp_wont_dirty|=1<<r;
8643                   }
8644                 }
8645               }
8646             }
8647           }
8648           if(wr) {
8649             will_dirty[i]=temp_will_dirty;
8650             wont_dirty[i]=temp_wont_dirty;
8651             pass6_clean_registers((ba[i]-start)>>2,i-1,0);
8652           }else{
8653             // Limit recursion.  It can take an excessive amount
8654             // of time if there are a lot of nested loops.
8655             will_dirty[(ba[i]-start)>>2]=0;
8656             wont_dirty[(ba[i]-start)>>2]=-1;
8657           }
8658         }
8659         /*else*/ if(1)
8660         {
8661           if (dops[i].is_ujump)
8662           {
8663             // Unconditional branch
8664             will_dirty_i=0;
8665             wont_dirty_i=0;
8666           //if(ba[i]>start+i*4) { // Disable recursion (for debugging)
8667             for(r=0;r<HOST_REGS;r++) {
8668               if(r!=EXCLUDE_REG) {
8669                 if(branch_regs[i].regmap[r]==regs[(ba[i]-start)>>2].regmap_entry[r]) {
8670                   will_dirty_i|=will_dirty[(ba[i]-start)>>2]&(1<<r);
8671                   wont_dirty_i|=wont_dirty[(ba[i]-start)>>2]&(1<<r);
8672                 }
8673                 if(branch_regs[i].regmap[r]>=0) {
8674                   will_dirty_i|=((unneeded_reg[(ba[i]-start)>>2]>>branch_regs[i].regmap[r])&1)<<r;
8675                   wont_dirty_i|=((unneeded_reg[(ba[i]-start)>>2]>>branch_regs[i].regmap[r])&1)<<r;
8676                 }
8677               }
8678             }
8679           //}
8680             // Merge in delay slot
8681             will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt1) & 31);
8682             will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt2) & 31);
8683             will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt1) & 31);
8684             will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt2) & 31);
8685             will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, CCREG) & 31);
8686             will_dirty_i &= branch_hr_candirty;
8687             will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt1) & 31);
8688             will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt2) & 31);
8689             will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt1) & 31);
8690             will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt2) & 31);
8691             will_dirty_i |= 1u << (get_rreg(rregmap_i, CCREG) & 31);
8692             will_dirty_i &= hr_candirty;
8693           } else {
8694             // Conditional branch
8695             will_dirty_i=will_dirty_next;
8696             wont_dirty_i=wont_dirty_next;
8697           //if(ba[i]>start+i*4) // Disable recursion (for debugging)
8698             for(r=0;r<HOST_REGS;r++) {
8699               if(r!=EXCLUDE_REG) {
8700                 signed char target_reg=branch_regs[i].regmap[r];
8701                 if(target_reg==regs[(ba[i]-start)>>2].regmap_entry[r]) {
8702                   will_dirty_i&=will_dirty[(ba[i]-start)>>2]&(1<<r);
8703                   wont_dirty_i|=wont_dirty[(ba[i]-start)>>2]&(1<<r);
8704                 }
8705                 else if(target_reg>=0) {
8706                   will_dirty_i&=((unneeded_reg[(ba[i]-start)>>2]>>target_reg)&1)<<r;
8707                   wont_dirty_i|=((unneeded_reg[(ba[i]-start)>>2]>>target_reg)&1)<<r;
8708                 }
8709               }
8710             }
8711             // Merge in delay slot
8712             will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt1) & 31);
8713             will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt2) & 31);
8714             will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt1) & 31);
8715             will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt2) & 31);
8716             will_dirty_i |= 1u << (get_rreg(branch_rregmap_i, CCREG) & 31);
8717             will_dirty_i &= branch_hr_candirty;
8718             //will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt1) & 31);
8719             //will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt2) & 31);
8720             will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt1) & 31);
8721             will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt2) & 31);
8722             will_dirty_i |= 1u << (get_rreg(rregmap_i, CCREG) & 31);
8723             will_dirty_i &= hr_candirty;
8724           }
8725           // Merge in delay slot (won't dirty)
8726           wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt1) & 31);
8727           wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt2) & 31);
8728           wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt1) & 31);
8729           wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i+1].rt2) & 31);
8730           wont_dirty_i |= 1u << (get_rreg(rregmap_i, CCREG) & 31);
8731           wont_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt1) & 31);
8732           wont_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i].rt2) & 31);
8733           wont_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt1) & 31);
8734           wont_dirty_i |= 1u << (get_rreg(branch_rregmap_i, dops[i+1].rt2) & 31);
8735           wont_dirty_i |= 1u << (get_rreg(branch_rregmap_i, CCREG) & 31);
8736           wont_dirty_i &= ~(1u << 31);
8737           if(wr) {
8738             #ifndef DESTRUCTIVE_WRITEBACK
8739             branch_regs[i].dirty&=wont_dirty_i;
8740             #endif
8741             branch_regs[i].dirty|=will_dirty_i;
8742           }
8743         }
8744       }
8745     }
8746     else if(dops[i].itype==SYSCALL||dops[i].itype==HLECALL||dops[i].itype==INTCALL)
8747     {
8748       // SYSCALL instruction (software interrupt)
8749       will_dirty_i=0;
8750       wont_dirty_i=0;
8751     }
8752     else if(dops[i].itype==COP0 && (source[i]&0x3f)==0x18)
8753     {
8754       // ERET instruction (return from interrupt)
8755       will_dirty_i=0;
8756       wont_dirty_i=0;
8757     }
8758     will_dirty_next=will_dirty_i;
8759     wont_dirty_next=wont_dirty_i;
8760     will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt1) & 31);
8761     will_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt2) & 31);
8762     will_dirty_i |= 1u << (get_rreg(rregmap_i, CCREG) & 31);
8763     will_dirty_i &= hr_candirty;
8764     wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt1) & 31);
8765     wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i].rt2) & 31);
8766     wont_dirty_i |= 1u << (get_rreg(rregmap_i, CCREG) & 31);
8767     wont_dirty_i &= ~(1u << 31);
8768     if (i > istart && !dops[i].is_jump) {
8769       // Don't store a register immediately after writing it,
8770       // may prevent dual-issue.
8771       wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i-1].rt1) & 31);
8772       wont_dirty_i |= 1u << (get_rreg(rregmap_i, dops[i-1].rt2) & 31);
8773     }
8774     // Save it
8775     will_dirty[i]=will_dirty_i;
8776     wont_dirty[i]=wont_dirty_i;
8777     // Mark registers that won't be dirtied as not dirty
8778     if(wr) {
8779         regs[i].dirty|=will_dirty_i;
8780         #ifndef DESTRUCTIVE_WRITEBACK
8781         regs[i].dirty&=wont_dirty_i;
8782         if(dops[i].is_jump)
8783         {
8784           if (i < iend-1 && !dops[i].is_ujump) {
8785             for(r=0;r<HOST_REGS;r++) {
8786               if(r!=EXCLUDE_REG) {
8787                 if(regs[i].regmap[r]==regmap_pre[i+2][r]) {
8788                   regs[i+2].wasdirty&=wont_dirty_i|~(1<<r);
8789                 }else {/*printf("i: %x (%d) mismatch(+2): %d\n",start+i*4,i,r);assert(!((wont_dirty_i>>r)&1));*/}
8790               }
8791             }
8792           }
8793         }
8794         else
8795         {
8796           if(i<iend) {
8797             for(r=0;r<HOST_REGS;r++) {
8798               if(r!=EXCLUDE_REG) {
8799                 if(regs[i].regmap[r]==regmap_pre[i+1][r]) {
8800                   regs[i+1].wasdirty&=wont_dirty_i|~(1<<r);
8801                 }else {/*printf("i: %x (%d) mismatch(+1): %d\n",start+i*4,i,r);assert(!((wont_dirty_i>>r)&1));*/}
8802               }
8803             }
8804           }
8805         }
8806         #endif
8807     }
8808     // Deal with changed mappings
8809     temp_will_dirty=will_dirty_i;
8810     temp_wont_dirty=wont_dirty_i;
8811     for(r=0;r<HOST_REGS;r++) {
8812       if(r!=EXCLUDE_REG) {
8813         int nr;
8814         if(regs[i].regmap[r]==regmap_pre[i][r]) {
8815           if(wr) {
8816             #ifndef DESTRUCTIVE_WRITEBACK
8817             regs[i].wasdirty&=wont_dirty_i|~(1<<r);
8818             #endif
8819             regs[i].wasdirty|=will_dirty_i&(1<<r);
8820           }
8821         }
8822         else if(regmap_pre[i][r]>=0&&(nr=get_rreg(rregmap_i,regmap_pre[i][r]))>=0) {
8823           // Register moved to a different register
8824           will_dirty_i&=~(1<<r);
8825           wont_dirty_i&=~(1<<r);
8826           will_dirty_i|=((temp_will_dirty>>nr)&1)<<r;
8827           wont_dirty_i|=((temp_wont_dirty>>nr)&1)<<r;
8828           if(wr) {
8829             #ifndef DESTRUCTIVE_WRITEBACK
8830             regs[i].wasdirty&=wont_dirty_i|~(1<<r);
8831             #endif
8832             regs[i].wasdirty|=will_dirty_i&(1<<r);
8833           }
8834         }
8835         else {
8836           will_dirty_i&=~(1<<r);
8837           wont_dirty_i&=~(1<<r);
8838           if(regmap_pre[i][r]>0 && regmap_pre[i][r]<34) {
8839             will_dirty_i|=((unneeded_reg[i]>>regmap_pre[i][r])&1)<<r;
8840             wont_dirty_i|=((unneeded_reg[i]>>regmap_pre[i][r])&1)<<r;
8841           } else {
8842             wont_dirty_i|=1<<r;
8843             /*printf("i: %x (%d) mismatch: %d\n",start+i*4,i,r);assert(!((will_dirty>>r)&1));*/
8844           }
8845         }
8846       }
8847     }
8848   }
8849 }
8850
8851 static noinline void pass10_expire_blocks(void)
8852 {
8853   u_int step = MAX_OUTPUT_BLOCK_SIZE / PAGE_COUNT / 2;
8854   // not sizeof(ndrc->translation_cache) due to vita hack
8855   u_int step_mask = ((1u << TARGET_SIZE_2) - 1u) & ~(step - 1u);
8856   u_int end = (out - ndrc->translation_cache + EXPIRITY_OFFSET) & step_mask;
8857   u_int base_shift = __builtin_ctz(MAX_OUTPUT_BLOCK_SIZE);
8858   int hit;
8859
8860   for (; expirep != end; expirep = ((expirep + step) & step_mask))
8861   {
8862     u_int base_offs = expirep & ~(MAX_OUTPUT_BLOCK_SIZE - 1);
8863     u_int block_i = expirep / step & (PAGE_COUNT - 1);
8864     u_int phase = (expirep >> (base_shift - 1)) & 1u;
8865     if (!(expirep & (MAX_OUTPUT_BLOCK_SIZE / 2 - 1))) {
8866       inv_debug("EXP: base_offs %x/%x phase %u\n", base_offs,
8867         out - ndrc->translation_cache, phase);
8868     }
8869
8870     if (!phase) {
8871       hit = blocks_remove_matching_addrs(&blocks[block_i], base_offs, base_shift);
8872       if (hit) {
8873         do_clear_cache();
8874         #ifdef USE_MINI_HT
8875         memset(mini_ht, -1, sizeof(mini_ht));
8876         #endif
8877       }
8878     }
8879     else
8880       unlink_jumps_tc_range(jumps[block_i], base_offs, base_shift);
8881   }
8882 }
8883
8884 static struct block_info *new_block_info(u_int start, u_int len,
8885   const void *source, const void *copy, u_char *beginning, u_short jump_in_count)
8886 {
8887   struct block_info **b_pptr;
8888   struct block_info *block;
8889   u_int page = get_page(start);
8890
8891   block = malloc(sizeof(*block) + jump_in_count * sizeof(block->jump_in[0]));
8892   assert(block);
8893   assert(jump_in_count > 0);
8894   block->source = source;
8895   block->copy = copy;
8896   block->start = start;
8897   block->len = len;
8898   block->reg_sv_flags = 0;
8899   block->tc_offs = beginning - ndrc->translation_cache;
8900   //block->tc_len = out - beginning;
8901   block->is_dirty = 0;
8902   block->inv_near_misses = 0;
8903   block->jump_in_cnt = jump_in_count;
8904
8905   // insert sorted by start mirror-unmasked vaddr
8906   for (b_pptr = &blocks[page]; ; b_pptr = &((*b_pptr)->next)) {
8907     if (*b_pptr == NULL || (*b_pptr)->start >= start) {
8908       block->next = *b_pptr;
8909       *b_pptr = block;
8910       break;
8911     }
8912   }
8913   stat_inc(stat_blocks);
8914   return block;
8915 }
8916
8917 static int new_recompile_block(u_int addr)
8918 {
8919   u_int pagelimit = 0;
8920   u_int state_rflags = 0;
8921   int i;
8922
8923   assem_debug("NOTCOMPILED: addr = %x -> %p\n", addr, out);
8924
8925   // this is just for speculation
8926   for (i = 1; i < 32; i++) {
8927     if ((psxRegs.GPR.r[i] & 0xffff0000) == 0x1f800000)
8928       state_rflags |= 1 << i;
8929   }
8930
8931   assert(!(addr & 3));
8932   start = addr & ~3;
8933   new_dynarec_did_compile=1;
8934   if (Config.HLE && start == 0x80001000) // hlecall
8935   {
8936     // XXX: is this enough? Maybe check hleSoftCall?
8937     void *beginning = start_block();
8938
8939     emit_movimm(start,0);
8940     emit_writeword(0,&pcaddr);
8941     emit_far_jump(new_dyna_leave);
8942     literal_pool(0);
8943     end_block(beginning);
8944     struct block_info *block = new_block_info(start, 4, NULL, NULL, beginning, 1);
8945     block->jump_in[0].vaddr = start;
8946     block->jump_in[0].addr = beginning;
8947     return 0;
8948   }
8949   else if (f1_hack && hack_addr == 0) {
8950     void *beginning = start_block();
8951     emit_movimm(start, 0);
8952     emit_writeword(0, &hack_addr);
8953     emit_readword(&psxRegs.GPR.n.sp, 0);
8954     emit_readptr(&mem_rtab, 1);
8955     emit_shrimm(0, 12, 2);
8956     emit_readptr_dualindexedx_ptrlen(1, 2, 1);
8957     emit_addimm(0, 0x18, 0);
8958     emit_adds_ptr(1, 1, 1);
8959     emit_ldr_dualindexed(1, 0, 0);
8960     emit_writeword(0, &psxRegs.GPR.r[26]); // lw k0, 0x18(sp)
8961     emit_far_call(ndrc_get_addr_ht);
8962     emit_jmpreg(0); // jr k0
8963     literal_pool(0);
8964     end_block(beginning);
8965
8966     struct block_info *block = new_block_info(start, 4, NULL, NULL, beginning, 1);
8967     block->jump_in[0].vaddr = start;
8968     block->jump_in[0].addr = beginning;
8969     SysPrintf("F1 hack to   %08x\n", start);
8970     return 0;
8971   }
8972
8973   cycle_multiplier_active = cycle_multiplier_override && cycle_multiplier == CYCLE_MULT_DEFAULT
8974     ? cycle_multiplier_override : cycle_multiplier;
8975
8976   source = get_source_start(start, &pagelimit);
8977   if (source == NULL) {
8978     if (addr != hack_addr) {
8979       SysPrintf("Compile at bogus memory address: %08x\n", addr);
8980       hack_addr = addr;
8981     }
8982     //abort();
8983     return -1;
8984   }
8985
8986   /* Pass 1: disassemble */
8987   /* Pass 2: register dependencies, branch targets */
8988   /* Pass 3: register allocation */
8989   /* Pass 4: branch dependencies */
8990   /* Pass 5: pre-alloc */
8991   /* Pass 6: optimize clean/dirty state */
8992   /* Pass 7: flag 32-bit registers */
8993   /* Pass 8: assembly */
8994   /* Pass 9: linker */
8995   /* Pass 10: garbage collection / free memory */
8996
8997   /* Pass 1 disassembly */
8998
8999   pass1_disassemble(pagelimit);
9000
9001   int clear_hack_addr = apply_hacks();
9002
9003   /* Pass 2 - Register dependencies and branch targets */
9004
9005   pass2_unneeded_regs(0,slen-1,0);
9006
9007   /* Pass 3 - Register allocation */
9008
9009   pass3_register_alloc(addr);
9010
9011   /* Pass 4 - Cull unused host registers */
9012
9013   pass4_cull_unused_regs();
9014
9015   /* Pass 5 - Pre-allocate registers */
9016
9017   pass5a_preallocate1();
9018   pass5b_preallocate2();
9019
9020   /* Pass 6 - Optimize clean/dirty state */
9021   pass6_clean_registers(0, slen-1, 1);
9022
9023   /* Pass 7 - Identify 32-bit registers */
9024   for (i=slen-1;i>=0;i--)
9025   {
9026     if(dops[i].itype==CJUMP||dops[i].itype==SJUMP)
9027     {
9028       // Conditional branch
9029       if((source[i]>>16)!=0x1000&&i<slen-2) {
9030         // Mark this address as a branch target since it may be called
9031         // upon return from interrupt
9032         dops[i+2].bt=1;
9033       }
9034     }
9035   }
9036
9037   /* Pass 8 - Assembly */
9038   linkcount=0;stubcount=0;
9039   is_delayslot=0;
9040   u_int dirty_pre=0;
9041   void *beginning=start_block();
9042   void *instr_addr0_override = NULL;
9043   int ds = 0;
9044
9045   if (start == 0x80030000) {
9046     // nasty hack for the fastbios thing
9047     // override block entry to this code
9048     instr_addr0_override = out;
9049     emit_movimm(start,0);
9050     // abuse io address var as a flag that we
9051     // have already returned here once
9052     emit_readword(&address,1);
9053     emit_writeword(0,&pcaddr);
9054     emit_writeword(0,&address);
9055     emit_cmp(0,1);
9056     #ifdef __aarch64__
9057     emit_jeq(out + 4*2);
9058     emit_far_jump(new_dyna_leave);
9059     #else
9060     emit_jne(new_dyna_leave);
9061     #endif
9062   }
9063   for(i=0;i<slen;i++)
9064   {
9065     __builtin_prefetch(regs[i+1].regmap);
9066     check_regmap(regmap_pre[i]);
9067     check_regmap(regs[i].regmap_entry);
9068     check_regmap(regs[i].regmap);
9069     //if(ds) printf("ds: ");
9070     disassemble_inst(i);
9071     if(ds) {
9072       ds=0; // Skip delay slot
9073       if(dops[i].bt) assem_debug("OOPS - branch into delay slot\n");
9074       instr_addr[i] = NULL;
9075     } else {
9076       speculate_register_values(i);
9077       #ifndef DESTRUCTIVE_WRITEBACK
9078       if (i < 2 || !dops[i-2].is_ujump)
9079       {
9080         wb_valid(regmap_pre[i],regs[i].regmap_entry,dirty_pre,regs[i].wasdirty,unneeded_reg[i]);
9081       }
9082       if((dops[i].itype==CJUMP||dops[i].itype==SJUMP)) {
9083         dirty_pre=branch_regs[i].dirty;
9084       }else{
9085         dirty_pre=regs[i].dirty;
9086       }
9087       #endif
9088       // write back
9089       if (i < 2 || !dops[i-2].is_ujump)
9090       {
9091         wb_invalidate(regmap_pre[i],regs[i].regmap_entry,regs[i].wasdirty,unneeded_reg[i]);
9092         loop_preload(regmap_pre[i],regs[i].regmap_entry);
9093       }
9094       // branch target entry point
9095       instr_addr[i] = out;
9096       assem_debug("<->\n");
9097       drc_dbg_emit_do_cmp(i, ccadj[i]);
9098       if (clear_hack_addr) {
9099         emit_movimm(0, 0);
9100         emit_writeword(0, &hack_addr);
9101         clear_hack_addr = 0;
9102       }
9103
9104       // load regs
9105       if(regs[i].regmap_entry[HOST_CCREG]==CCREG&&regs[i].regmap[HOST_CCREG]!=CCREG)
9106         wb_register(CCREG,regs[i].regmap_entry,regs[i].wasdirty);
9107       load_regs(regs[i].regmap_entry,regs[i].regmap,dops[i].rs1,dops[i].rs2);
9108       address_generation(i,&regs[i],regs[i].regmap_entry);
9109       load_consts(regmap_pre[i],regs[i].regmap,i);
9110       if(dops[i].is_jump)
9111       {
9112         // Load the delay slot registers if necessary
9113         if(dops[i+1].rs1!=dops[i].rs1&&dops[i+1].rs1!=dops[i].rs2&&(dops[i+1].rs1!=dops[i].rt1||dops[i].rt1==0))
9114           load_regs(regs[i].regmap_entry,regs[i].regmap,dops[i+1].rs1,dops[i+1].rs1);
9115         if(dops[i+1].rs2!=dops[i+1].rs1&&dops[i+1].rs2!=dops[i].rs1&&dops[i+1].rs2!=dops[i].rs2&&(dops[i+1].rs2!=dops[i].rt1||dops[i].rt1==0))
9116           load_regs(regs[i].regmap_entry,regs[i].regmap,dops[i+1].rs2,dops[i+1].rs2);
9117         if (ram_offset && (dops[i+1].is_load || dops[i+1].is_store))
9118           load_reg(regs[i].regmap_entry,regs[i].regmap,ROREG);
9119         if (dops[i+1].is_store)
9120           load_reg(regs[i].regmap_entry,regs[i].regmap,INVCP);
9121       }
9122       else if(i+1<slen)
9123       {
9124         // Preload registers for following instruction
9125         if(dops[i+1].rs1!=dops[i].rs1&&dops[i+1].rs1!=dops[i].rs2)
9126           if(dops[i+1].rs1!=dops[i].rt1&&dops[i+1].rs1!=dops[i].rt2)
9127             load_regs(regs[i].regmap_entry,regs[i].regmap,dops[i+1].rs1,dops[i+1].rs1);
9128         if(dops[i+1].rs2!=dops[i+1].rs1&&dops[i+1].rs2!=dops[i].rs1&&dops[i+1].rs2!=dops[i].rs2)
9129           if(dops[i+1].rs2!=dops[i].rt1&&dops[i+1].rs2!=dops[i].rt2)
9130             load_regs(regs[i].regmap_entry,regs[i].regmap,dops[i+1].rs2,dops[i+1].rs2);
9131       }
9132       // TODO: if(is_ooo(i)) address_generation(i+1);
9133       if (!dops[i].is_jump || dops[i].itype == CJUMP)
9134         load_reg(regs[i].regmap_entry,regs[i].regmap,CCREG);
9135       if (ram_offset && (dops[i].is_load || dops[i].is_store))
9136         load_reg(regs[i].regmap_entry,regs[i].regmap,ROREG);
9137       if (dops[i].is_store)
9138         load_reg(regs[i].regmap_entry,regs[i].regmap,INVCP);
9139
9140       ds = assemble(i, &regs[i], ccadj[i]);
9141
9142       if (dops[i].is_ujump)
9143         literal_pool(1024);
9144       else
9145         literal_pool_jumpover(256);
9146     }
9147   }
9148
9149   assert(slen > 0);
9150   if (slen > 0 && dops[slen-1].itype == INTCALL) {
9151     // no ending needed for this block since INTCALL never returns
9152   }
9153   // If the block did not end with an unconditional branch,
9154   // add a jump to the next instruction.
9155   else if (i > 1) {
9156     if (!dops[i-2].is_ujump) {
9157       assert(!dops[i-1].is_jump);
9158       assert(i==slen);
9159       if(dops[i-2].itype!=CJUMP&&dops[i-2].itype!=SJUMP) {
9160         store_regs_bt(regs[i-1].regmap,regs[i-1].dirty,start+i*4);
9161         if(regs[i-1].regmap[HOST_CCREG]!=CCREG)
9162           emit_loadreg(CCREG,HOST_CCREG);
9163         emit_addimm(HOST_CCREG, ccadj[i-1] + CLOCK_ADJUST(1), HOST_CCREG);
9164       }
9165       else
9166       {
9167         store_regs_bt(branch_regs[i-2].regmap,branch_regs[i-2].dirty,start+i*4);
9168         assert(branch_regs[i-2].regmap[HOST_CCREG]==CCREG);
9169       }
9170       add_to_linker(out,start+i*4,0);
9171       emit_jmp(0);
9172     }
9173   }
9174   else
9175   {
9176     assert(i>0);
9177     assert(!dops[i-1].is_jump);
9178     store_regs_bt(regs[i-1].regmap,regs[i-1].dirty,start+i*4);
9179     if(regs[i-1].regmap[HOST_CCREG]!=CCREG)
9180       emit_loadreg(CCREG,HOST_CCREG);
9181     emit_addimm(HOST_CCREG, ccadj[i-1] + CLOCK_ADJUST(1), HOST_CCREG);
9182     add_to_linker(out,start+i*4,0);
9183     emit_jmp(0);
9184   }
9185
9186   // TODO: delay slot stubs?
9187   // Stubs
9188   for(i=0;i<stubcount;i++)
9189   {
9190     switch(stubs[i].type)
9191     {
9192       case LOADB_STUB:
9193       case LOADH_STUB:
9194       case LOADW_STUB:
9195       case LOADD_STUB:
9196       case LOADBU_STUB:
9197       case LOADHU_STUB:
9198         do_readstub(i);break;
9199       case STOREB_STUB:
9200       case STOREH_STUB:
9201       case STOREW_STUB:
9202       case STORED_STUB:
9203         do_writestub(i);break;
9204       case CC_STUB:
9205         do_ccstub(i);break;
9206       case INVCODE_STUB:
9207         do_invstub(i);break;
9208       case FP_STUB:
9209         do_cop1stub(i);break;
9210       case STORELR_STUB:
9211         do_unalignedwritestub(i);break;
9212     }
9213   }
9214
9215   if (instr_addr0_override)
9216     instr_addr[0] = instr_addr0_override;
9217
9218 #if 0
9219   /* check for improper expiration */
9220   for (i = 0; i < ARRAY_SIZE(jumps); i++) {
9221     int j;
9222     if (!jumps[i])
9223       continue;
9224     for (j = 0; j < jumps[i]->count; j++)
9225       assert(jumps[i]->e[j].stub < beginning || (u_char *)jumps[i]->e[j].stub > out);
9226   }
9227 #endif
9228
9229   /* Pass 9 - Linker */
9230   for(i=0;i<linkcount;i++)
9231   {
9232     assem_debug("%p -> %8x\n",link_addr[i].addr,link_addr[i].target);
9233     literal_pool(64);
9234     if (!link_addr[i].internal)
9235     {
9236       void *stub = out;
9237       void *addr = check_addr(link_addr[i].target);
9238       emit_extjump(link_addr[i].addr, link_addr[i].target);
9239       if (addr) {
9240         set_jump_target(link_addr[i].addr, addr);
9241         ndrc_add_jump_out(link_addr[i].target,stub);
9242       }
9243       else
9244         set_jump_target(link_addr[i].addr, stub);
9245     }
9246     else
9247     {
9248       // Internal branch
9249       int target=(link_addr[i].target-start)>>2;
9250       assert(target>=0&&target<slen);
9251       assert(instr_addr[target]);
9252       //#ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
9253       //set_jump_target_fillslot(link_addr[i].addr,instr_addr[target],link_addr[i].ext>>1);
9254       //#else
9255       set_jump_target(link_addr[i].addr, instr_addr[target]);
9256       //#endif
9257     }
9258   }
9259
9260   u_int source_len = slen*4;
9261   if (dops[slen-1].itype == INTCALL && source_len > 4)
9262     // no need to treat the last instruction as compiled
9263     // as interpreter fully handles it
9264     source_len -= 4;
9265
9266   if ((u_char *)copy + source_len > (u_char *)shadow + sizeof(shadow))
9267     copy = shadow;
9268
9269   // External Branch Targets (jump_in)
9270   int jump_in_count = 1;
9271   assert(instr_addr[0]);
9272   for (i = 1; i < slen; i++)
9273   {
9274     if (dops[i].bt && instr_addr[i])
9275       jump_in_count++;
9276   }
9277
9278   struct block_info *block =
9279     new_block_info(start, slen * 4, source, copy, beginning, jump_in_count);
9280   block->reg_sv_flags = state_rflags;
9281
9282   int jump_in_i = 0;
9283   for (i = 0; i < slen; i++)
9284   {
9285     if ((i == 0 || dops[i].bt) && instr_addr[i])
9286     {
9287       assem_debug("%p (%d) <- %8x\n", instr_addr[i], i, start + i*4);
9288       u_int vaddr = start + i*4;
9289
9290       literal_pool(256);
9291       void *entry = out;
9292       load_regs_entry(i);
9293       if (entry == out)
9294         entry = instr_addr[i];
9295       else
9296         emit_jmp(instr_addr[i]);
9297
9298       block->jump_in[jump_in_i].vaddr = vaddr;
9299       block->jump_in[jump_in_i].addr = entry;
9300       jump_in_i++;
9301     }
9302   }
9303   assert(jump_in_i == jump_in_count);
9304   hash_table_add(block->jump_in[0].vaddr, block->jump_in[0].addr);
9305   // Write out the literal pool if necessary
9306   literal_pool(0);
9307   #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
9308   // Align code
9309   if(((u_int)out)&7) emit_addnop(13);
9310   #endif
9311   assert(out - (u_char *)beginning < MAX_OUTPUT_BLOCK_SIZE);
9312   //printf("shadow buffer: %p-%p\n",copy,(u_char *)copy+slen*4);
9313   memcpy(copy, source, source_len);
9314   copy += source_len;
9315
9316   end_block(beginning);
9317
9318   // If we're within 256K of the end of the buffer,
9319   // start over from the beginning. (Is 256K enough?)
9320   if (out > ndrc->translation_cache + sizeof(ndrc->translation_cache) - MAX_OUTPUT_BLOCK_SIZE)
9321     out = ndrc->translation_cache;
9322
9323   // Trap writes to any of the pages we compiled
9324   mark_invalid_code(start, slen*4, 0);
9325
9326   /* Pass 10 - Free memory by expiring oldest blocks */
9327
9328   pass10_expire_blocks();
9329
9330 #ifdef ASSEM_PRINT
9331   fflush(stdout);
9332 #endif
9333   stat_inc(stat_bc_direct);
9334   return 0;
9335 }
9336
9337 // vim:shiftwidth=2:expandtab