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