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