drc: use optimized get_reg
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / new_dynarec.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   Mupen64plus - new_dynarec.c                                           *
3  *   Copyright (C) 2009-2011 Ari64                                         *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
19  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20
21 #include <stdlib.h>
22 #include <stdint.h> //include for uint64_t
23 #include <assert.h>
24 #include <errno.h>
25 #include <sys/mman.h>
26 #ifdef __MACH__
27 #include <libkern/OSCacheControl.h>
28 #endif
29 #ifdef _3DS
30 #include <3ds_utils.h>
31 #endif
32
33 #include "new_dynarec_config.h"
34 #include "../psxhle.h"
35 #include "../psxinterpreter.h"
36 #include "../gte.h"
37 #include "emu_if.h" // emulator interface
38 #include "arm_features.h"
39
40 #define noinline __attribute__((noinline,noclone))
41 #ifndef ARRAY_SIZE
42 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
43 #endif
44 #ifndef min
45 #define min(a, b) ((b) < (a) ? (b) : (a))
46 #endif
47 #ifndef max
48 #define max(a, b) ((b) > (a) ? (b) : (a))
49 #endif
50
51 //#define DISASM
52 //#define ASSEM_PRINT
53 //#define REG_ALLOC_PRINT
54
55 #ifdef ASSEM_PRINT
56 #define assem_debug printf
57 #else
58 #define assem_debug(...)
59 #endif
60 //#define inv_debug printf
61 #define inv_debug(...)
62
63 #ifdef __i386__
64 #include "assem_x86.h"
65 #endif
66 #ifdef __x86_64__
67 #include "assem_x64.h"
68 #endif
69 #ifdef __arm__
70 #include "assem_arm.h"
71 #endif
72 #ifdef __aarch64__
73 #include "assem_arm64.h"
74 #endif
75
76 #define RAM_SIZE 0x200000
77 #define MAXBLOCK 4096
78 #define MAX_OUTPUT_BLOCK_SIZE 262144
79
80 #ifdef VITA
81 // apparently Vita has a 16MB limit, so either we cut tc in half,
82 // or use this hack (it's a hack because tc size was designed to be power-of-2)
83 #define TC_REDUCE_BYTES 4096
84 #else
85 #define TC_REDUCE_BYTES 0
86 #endif
87
88 struct ndrc_mem
89 {
90   u_char translation_cache[(1 << TARGET_SIZE_2) - TC_REDUCE_BYTES];
91   struct
92   {
93     struct tramp_insns ops[2048 / sizeof(struct tramp_insns)];
94     const void *f[2048 / sizeof(void *)];
95   } tramp;
96 };
97
98 #ifdef BASE_ADDR_DYNAMIC
99 static struct ndrc_mem *ndrc;
100 #else
101 static struct ndrc_mem ndrc_ __attribute__((aligned(4096)));
102 static struct ndrc_mem *ndrc = &ndrc_;
103 #endif
104
105 // stubs
106 enum stub_type {
107   CC_STUB = 1,
108   FP_STUB = 2,
109   LOADB_STUB = 3,
110   LOADH_STUB = 4,
111   LOADW_STUB = 5,
112   LOADD_STUB = 6,
113   LOADBU_STUB = 7,
114   LOADHU_STUB = 8,
115   STOREB_STUB = 9,
116   STOREH_STUB = 10,
117   STOREW_STUB = 11,
118   STORED_STUB = 12,
119   STORELR_STUB = 13,
120   INVCODE_STUB = 14,
121 };
122
123 // regmap_pre[i]    - regs before [i] insn starts; dirty things here that
124 //                    don't match .regmap will be written back
125 // [i].regmap_entry - regs that must be set up if someone jumps here
126 // [i].regmap       - regs [i] insn will read/(over)write
127 // branch_regs[i].* - same as above but for branches, takes delay slot into account
128 struct regstat
129 {
130   signed char regmap_entry[HOST_REGS];
131   signed char regmap[HOST_REGS];
132   uint64_t wasdirty;
133   uint64_t dirty;
134   uint64_t u;
135   u_int wasconst;                // before; for example 'lw r2, (r2)' wasconst is true
136   u_int isconst;                 //  ... but isconst is false when r2 is known
137   u_int loadedconst;             // host regs that have constants loaded
138   u_int waswritten;              // MIPS regs that were used as store base before
139 };
140
141 // note: asm depends on this layout
142 struct ll_entry
143 {
144   u_int vaddr;
145   u_int reg_sv_flags;
146   void *addr;
147   struct ll_entry *next;
148 };
149
150 struct ht_entry
151 {
152   u_int vaddr[2];
153   void *tcaddr[2];
154 };
155
156 struct code_stub
157 {
158   enum stub_type type;
159   void *addr;
160   void *retaddr;
161   u_int a;
162   uintptr_t b;
163   uintptr_t c;
164   u_int d;
165   u_int e;
166 };
167
168 struct link_entry
169 {
170   void *addr;
171   u_int target;
172   u_int ext;
173 };
174
175 static struct decoded_insn
176 {
177   u_char itype;
178   u_char opcode;
179   u_char opcode2;
180   u_char rs1;
181   u_char rs2;
182   u_char rt1;
183   u_char rt2;
184   u_char lt1;
185   u_char bt:1;
186   u_char ooo:1;
187   u_char is_ds:1;
188   u_char is_jump:1;
189   u_char is_ujump:1;
190   u_char is_load:1;
191   u_char is_store:1;
192 } dops[MAXBLOCK];
193
194   // used by asm:
195   u_char *out;
196   struct ht_entry hash_table[65536]  __attribute__((aligned(16)));
197   struct ll_entry *jump_in[4096] __attribute__((aligned(16)));
198   struct ll_entry *jump_dirty[4096];
199
200   static struct ll_entry *jump_out[4096];
201   static u_int start;
202   static u_int *source;
203   static char insn[MAXBLOCK][10];
204   static uint64_t gte_rs[MAXBLOCK]; // gte: 32 data and 32 ctl regs
205   static uint64_t gte_rt[MAXBLOCK];
206   static uint64_t gte_unneeded[MAXBLOCK];
207   static u_int smrv[32]; // speculated MIPS register values
208   static u_int smrv_strong; // mask or regs that are likely to have correct values
209   static u_int smrv_weak; // same, but somewhat less likely
210   static u_int smrv_strong_next; // same, but after current insn executes
211   static u_int smrv_weak_next;
212   static int imm[MAXBLOCK];
213   static u_int ba[MAXBLOCK];
214   static uint64_t unneeded_reg[MAXBLOCK];
215   static uint64_t branch_unneeded_reg[MAXBLOCK];
216   // see 'struct regstat' for a description
217   static signed char regmap_pre[MAXBLOCK][HOST_REGS];
218   // contains 'real' consts at [i] insn, but may differ from what's actually
219   // loaded in host reg as 'final' value is always loaded, see get_final_value()
220   static uint32_t current_constmap[HOST_REGS];
221   static uint32_t constmap[MAXBLOCK][HOST_REGS];
222   static struct regstat regs[MAXBLOCK];
223   static struct regstat branch_regs[MAXBLOCK];
224   static signed char minimum_free_regs[MAXBLOCK];
225   static u_int needed_reg[MAXBLOCK];
226   static u_int wont_dirty[MAXBLOCK];
227   static u_int will_dirty[MAXBLOCK];
228   static int ccadj[MAXBLOCK];
229   static int slen;
230   static void *instr_addr[MAXBLOCK];
231   static struct link_entry link_addr[MAXBLOCK];
232   static int linkcount;
233   static struct code_stub stubs[MAXBLOCK*3];
234   static int stubcount;
235   static u_int literals[1024][2];
236   static int literalcount;
237   static int is_delayslot;
238   static char shadow[1048576]  __attribute__((aligned(16)));
239   static void *copy;
240   static int expirep;
241   static u_int stop_after_jal;
242   static u_int f1_hack;
243
244   int new_dynarec_hacks;
245   int new_dynarec_hacks_pergame;
246   int new_dynarec_hacks_old;
247   int new_dynarec_did_compile;
248
249   #define HACK_ENABLED(x) ((new_dynarec_hacks | new_dynarec_hacks_pergame) & (x))
250
251   extern int cycle_count; // ... until end of the timeslice, counts -N -> 0
252   extern int last_count;  // last absolute target, often = next_interupt
253   extern int pcaddr;
254   extern int pending_exception;
255   extern int branch_target;
256   extern uintptr_t ram_offset;
257   extern uintptr_t mini_ht[32][2];
258   extern u_char restore_candidate[512];
259
260   /* registers that may be allocated */
261   /* 1-31 gpr */
262 #define LOREG 32 // lo
263 #define HIREG 33 // hi
264 //#define FSREG 34 // FPU status (FCSR)
265 #define CSREG 35 // Coprocessor status
266 #define CCREG 36 // Cycle count
267 #define INVCP 37 // Pointer to invalid_code
268 //#define MMREG 38 // Pointer to memory_map
269 #define ROREG 39 // ram offset (if rdram!=0x80000000)
270 #define TEMPREG 40
271 #define FTEMP 40 // FPU temporary register
272 #define PTEMP 41 // Prefetch temporary register
273 //#define TLREG 42 // TLB mapping offset
274 #define RHASH 43 // Return address hash
275 #define RHTBL 44 // Return address hash table address
276 #define RTEMP 45 // JR/JALR address register
277 #define MAXREG 45
278 #define AGEN1 46 // Address generation temporary register
279 //#define AGEN2 47 // Address generation temporary register
280 //#define MGEN1 48 // Maptable address generation temporary register
281 //#define MGEN2 49 // Maptable address generation temporary register
282 #define BTREG 50 // Branch target temporary register
283
284   /* instruction types */
285 #define NOP 0     // No operation
286 #define LOAD 1    // Load
287 #define STORE 2   // Store
288 #define LOADLR 3  // Unaligned load
289 #define STORELR 4 // Unaligned store
290 #define MOV 5     // Move
291 #define ALU 6     // Arithmetic/logic
292 #define MULTDIV 7 // Multiply/divide
293 #define SHIFT 8   // Shift by register
294 #define SHIFTIMM 9// Shift by immediate
295 #define IMM16 10  // 16-bit immediate
296 #define RJUMP 11  // Unconditional jump to register
297 #define UJUMP 12  // Unconditional jump
298 #define CJUMP 13  // Conditional branch (BEQ/BNE/BGTZ/BLEZ)
299 #define SJUMP 14  // Conditional branch (regimm format)
300 #define COP0 15   // Coprocessor 0
301 #define COP1 16   // Coprocessor 1
302 #define C1LS 17   // Coprocessor 1 load/store
303 //#define FJUMP 18  // Conditional branch (floating point)
304 //#define FLOAT 19  // Floating point unit
305 //#define FCONV 20  // Convert integer to float
306 //#define FCOMP 21  // Floating point compare (sets FSREG)
307 #define SYSCALL 22// SYSCALL,BREAK
308 #define OTHER 23  // Other
309 #define SPAN 24   // Branch/delay slot spans 2 pages
310 #define NI 25     // Not implemented
311 #define HLECALL 26// PCSX fake opcodes for HLE
312 #define COP2 27   // Coprocessor 2 move
313 #define C2LS 28   // Coprocessor 2 load/store
314 #define C2OP 29   // Coprocessor 2 operation
315 #define INTCALL 30// Call interpreter to handle rare corner cases
316
317   /* branch codes */
318 #define TAKEN 1
319 #define NOTTAKEN 2
320 #define NULLDS 3
321
322 #define DJT_1 (void *)1l // no function, just a label in assem_debug log
323 #define DJT_2 (void *)2l
324
325 // asm linkage
326 int new_recompile_block(u_int addr);
327 void *get_addr_ht(u_int vaddr);
328 void invalidate_block(u_int block);
329 void invalidate_addr(u_int addr);
330 void remove_hash(int vaddr);
331 void dyna_linker();
332 void dyna_linker_ds();
333 void verify_code();
334 void verify_code_ds();
335 void cc_interrupt();
336 void fp_exception();
337 void fp_exception_ds();
338 void jump_syscall   (u_int u0, u_int u1, u_int pc);
339 void jump_syscall_ds(u_int u0, u_int u1, u_int pc);
340 void jump_break   (u_int u0, u_int u1, u_int pc);
341 void jump_break_ds(u_int u0, u_int u1, u_int pc);
342 void jump_to_new_pc();
343 void call_gteStall();
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 static int count_free_regs(const signed char regmap[])
652 {
653   int count=0;
654   int hr;
655   for(hr=0;hr<HOST_REGS;hr++)
656   {
657     if(hr!=EXCLUDE_REG) {
658       if(regmap[hr]<0) count++;
659     }
660   }
661   return count;
662 }
663
664 static void dirty_reg(struct regstat *cur, signed char reg)
665 {
666   int hr;
667   if (!reg) return;
668   hr = get_reg(cur->regmap, reg);
669   if (hr >= 0)
670     cur->dirty |= 1<<hr;
671 }
672
673 static void set_const(struct regstat *cur, signed char reg, uint32_t value)
674 {
675   int hr;
676   if (!reg) return;
677   hr = get_reg(cur->regmap, reg);
678   if (hr >= 0) {
679     cur->isconst |= 1<<hr;
680     current_constmap[hr] = value;
681   }
682 }
683
684 static void clear_const(struct regstat *cur, signed char reg)
685 {
686   int hr;
687   if (!reg) return;
688   hr = get_reg(cur->regmap, reg);
689   if (hr >= 0)
690     cur->isconst &= ~(1<<hr);
691 }
692
693 static int is_const(const struct regstat *cur, signed char reg)
694 {
695   int hr;
696   if (reg < 0) return 0;
697   if (!reg) return 1;
698   hr = get_reg(cur->regmap, reg);
699   if (hr >= 0)
700     return (cur->isconst>>hr)&1;
701   return 0;
702 }
703
704 static uint32_t get_const(const struct regstat *cur, signed char reg)
705 {
706   int hr;
707   if (!reg) return 0;
708   hr = get_reg(cur->regmap, reg);
709   if (hr >= 0)
710     return current_constmap[hr];
711
712   SysPrintf("Unknown constant in r%d\n", reg);
713   abort();
714 }
715
716 // Least soon needed registers
717 // Look at the next ten instructions and see which registers
718 // will be used.  Try not to reallocate these.
719 void lsn(u_char hsn[], int i, int *preferred_reg)
720 {
721   int j;
722   int b=-1;
723   for(j=0;j<9;j++)
724   {
725     if(i+j>=slen) {
726       j=slen-i-1;
727       break;
728     }
729     if (dops[i+j].is_ujump)
730     {
731       // Don't go past an unconditonal jump
732       j++;
733       break;
734     }
735   }
736   for(;j>=0;j--)
737   {
738     if(dops[i+j].rs1) hsn[dops[i+j].rs1]=j;
739     if(dops[i+j].rs2) hsn[dops[i+j].rs2]=j;
740     if(dops[i+j].rt1) hsn[dops[i+j].rt1]=j;
741     if(dops[i+j].rt2) hsn[dops[i+j].rt2]=j;
742     if(dops[i+j].itype==STORE || dops[i+j].itype==STORELR) {
743       // Stores can allocate zero
744       hsn[dops[i+j].rs1]=j;
745       hsn[dops[i+j].rs2]=j;
746     }
747     if (ram_offset && (dops[i+j].is_load || dops[i+j].is_store))
748       hsn[ROREG] = j;
749     // On some architectures stores need invc_ptr
750     #if defined(HOST_IMM8)
751     if (dops[i+j].is_store)
752       hsn[INVCP] = j;
753     #endif
754     if(i+j>=0&&(dops[i+j].itype==UJUMP||dops[i+j].itype==CJUMP||dops[i+j].itype==SJUMP))
755     {
756       hsn[CCREG]=j;
757       b=j;
758     }
759   }
760   if(b>=0)
761   {
762     if(ba[i+b]>=start && ba[i+b]<(start+slen*4))
763     {
764       // Follow first branch
765       int t=(ba[i+b]-start)>>2;
766       j=7-b;if(t+j>=slen) j=slen-t-1;
767       for(;j>=0;j--)
768       {
769         if(dops[t+j].rs1) if(hsn[dops[t+j].rs1]>j+b+2) hsn[dops[t+j].rs1]=j+b+2;
770         if(dops[t+j].rs2) if(hsn[dops[t+j].rs2]>j+b+2) hsn[dops[t+j].rs2]=j+b+2;
771         //if(dops[t+j].rt1) if(hsn[dops[t+j].rt1]>j+b+2) hsn[dops[t+j].rt1]=j+b+2;
772         //if(dops[t+j].rt2) if(hsn[dops[t+j].rt2]>j+b+2) hsn[dops[t+j].rt2]=j+b+2;
773       }
774     }
775     // TODO: preferred register based on backward branch
776   }
777   // Delay slot should preferably not overwrite branch conditions or cycle count
778   if (i > 0 && dops[i-1].is_jump) {
779     if(dops[i-1].rs1) if(hsn[dops[i-1].rs1]>1) hsn[dops[i-1].rs1]=1;
780     if(dops[i-1].rs2) if(hsn[dops[i-1].rs2]>1) hsn[dops[i-1].rs2]=1;
781     hsn[CCREG]=1;
782     // ...or hash tables
783     hsn[RHASH]=1;
784     hsn[RHTBL]=1;
785   }
786   // Coprocessor load/store needs FTEMP, even if not declared
787   if(dops[i].itype==C2LS) {
788     hsn[FTEMP]=0;
789   }
790   // Load L/R also uses FTEMP as a temporary register
791   if(dops[i].itype==LOADLR) {
792     hsn[FTEMP]=0;
793   }
794   // Also SWL/SWR/SDL/SDR
795   if(dops[i].opcode==0x2a||dops[i].opcode==0x2e||dops[i].opcode==0x2c||dops[i].opcode==0x2d) {
796     hsn[FTEMP]=0;
797   }
798   // Don't remove the miniht registers
799   if(dops[i].itype==UJUMP||dops[i].itype==RJUMP)
800   {
801     hsn[RHASH]=0;
802     hsn[RHTBL]=0;
803   }
804 }
805
806 // We only want to allocate registers if we're going to use them again soon
807 int needed_again(int r, int i)
808 {
809   int j;
810   int b=-1;
811   int rn=10;
812
813   if (i > 0 && dops[i-1].is_ujump)
814   {
815     if(ba[i-1]<start || ba[i-1]>start+slen*4-4)
816       return 0; // Don't need any registers if exiting the block
817   }
818   for(j=0;j<9;j++)
819   {
820     if(i+j>=slen) {
821       j=slen-i-1;
822       break;
823     }
824     if (dops[i+j].is_ujump)
825     {
826       // Don't go past an unconditonal jump
827       j++;
828       break;
829     }
830     if(dops[i+j].itype==SYSCALL||dops[i+j].itype==HLECALL||dops[i+j].itype==INTCALL||((source[i+j]&0xfc00003f)==0x0d))
831     {
832       break;
833     }
834   }
835   for(;j>=1;j--)
836   {
837     if(dops[i+j].rs1==r) rn=j;
838     if(dops[i+j].rs2==r) rn=j;
839     if((unneeded_reg[i+j]>>r)&1) rn=10;
840     if(i+j>=0&&(dops[i+j].itype==UJUMP||dops[i+j].itype==CJUMP||dops[i+j].itype==SJUMP))
841     {
842       b=j;
843     }
844   }
845   if(rn<10) return 1;
846   (void)b;
847   return 0;
848 }
849
850 // Try to match register allocations at the end of a loop with those
851 // at the beginning
852 int loop_reg(int i, int r, int hr)
853 {
854   int j,k;
855   for(j=0;j<9;j++)
856   {
857     if(i+j>=slen) {
858       j=slen-i-1;
859       break;
860     }
861     if (dops[i+j].is_ujump)
862     {
863       // Don't go past an unconditonal jump
864       j++;
865       break;
866     }
867   }
868   k=0;
869   if(i>0){
870     if(dops[i-1].itype==UJUMP||dops[i-1].itype==CJUMP||dops[i-1].itype==SJUMP)
871       k--;
872   }
873   for(;k<j;k++)
874   {
875     assert(r < 64);
876     if((unneeded_reg[i+k]>>r)&1) return hr;
877     if(i+k>=0&&(dops[i+k].itype==UJUMP||dops[i+k].itype==CJUMP||dops[i+k].itype==SJUMP))
878     {
879       if(ba[i+k]>=start && ba[i+k]<(start+i*4))
880       {
881         int t=(ba[i+k]-start)>>2;
882         int reg=get_reg(regs[t].regmap_entry,r);
883         if(reg>=0) return reg;
884         //reg=get_reg(regs[t+1].regmap_entry,r);
885         //if(reg>=0) return reg;
886       }
887     }
888   }
889   return hr;
890 }
891
892
893 // Allocate every register, preserving source/target regs
894 void alloc_all(struct regstat *cur,int i)
895 {
896   int hr;
897
898   for(hr=0;hr<HOST_REGS;hr++) {
899     if(hr!=EXCLUDE_REG) {
900       if((cur->regmap[hr]!=dops[i].rs1)&&(cur->regmap[hr]!=dops[i].rs2)&&
901          (cur->regmap[hr]!=dops[i].rt1)&&(cur->regmap[hr]!=dops[i].rt2))
902       {
903         cur->regmap[hr]=-1;
904         cur->dirty&=~(1<<hr);
905       }
906       // Don't need zeros
907       if(cur->regmap[hr]==0)
908       {
909         cur->regmap[hr]=-1;
910         cur->dirty&=~(1<<hr);
911       }
912     }
913   }
914 }
915
916 #ifndef NDEBUG
917 static int host_tempreg_in_use;
918
919 static void host_tempreg_acquire(void)
920 {
921   assert(!host_tempreg_in_use);
922   host_tempreg_in_use = 1;
923 }
924
925 static void host_tempreg_release(void)
926 {
927   host_tempreg_in_use = 0;
928 }
929 #else
930 static void host_tempreg_acquire(void) {}
931 static void host_tempreg_release(void) {}
932 #endif
933
934 #ifdef ASSEM_PRINT
935 extern void gen_interupt();
936 extern void do_insn_cmp();
937 #define FUNCNAME(f) { f, " " #f }
938 static const struct {
939   void *addr;
940   const char *name;
941 } function_names[] = {
942   FUNCNAME(cc_interrupt),
943   FUNCNAME(gen_interupt),
944   FUNCNAME(get_addr_ht),
945   FUNCNAME(get_addr),
946   FUNCNAME(jump_handler_read8),
947   FUNCNAME(jump_handler_read16),
948   FUNCNAME(jump_handler_read32),
949   FUNCNAME(jump_handler_write8),
950   FUNCNAME(jump_handler_write16),
951   FUNCNAME(jump_handler_write32),
952   FUNCNAME(invalidate_addr),
953   FUNCNAME(jump_to_new_pc),
954   FUNCNAME(jump_break),
955   FUNCNAME(jump_break_ds),
956   FUNCNAME(jump_syscall),
957   FUNCNAME(jump_syscall_ds),
958   FUNCNAME(call_gteStall),
959   FUNCNAME(new_dyna_leave),
960   FUNCNAME(pcsx_mtc0),
961   FUNCNAME(pcsx_mtc0_ds),
962 #ifdef DRC_DBG
963   FUNCNAME(do_insn_cmp),
964 #endif
965 #ifdef __arm__
966   FUNCNAME(verify_code),
967 #endif
968 };
969
970 static const char *func_name(const void *a)
971 {
972   int i;
973   for (i = 0; i < sizeof(function_names)/sizeof(function_names[0]); i++)
974     if (function_names[i].addr == a)
975       return function_names[i].name;
976   return "";
977 }
978 #else
979 #define func_name(x) ""
980 #endif
981
982 #ifdef __i386__
983 #include "assem_x86.c"
984 #endif
985 #ifdef __x86_64__
986 #include "assem_x64.c"
987 #endif
988 #ifdef __arm__
989 #include "assem_arm.c"
990 #endif
991 #ifdef __aarch64__
992 #include "assem_arm64.c"
993 #endif
994
995 static void *get_trampoline(const void *f)
996 {
997   size_t i;
998
999   for (i = 0; i < ARRAY_SIZE(ndrc->tramp.f); i++) {
1000     if (ndrc->tramp.f[i] == f || ndrc->tramp.f[i] == NULL)
1001       break;
1002   }
1003   if (i == ARRAY_SIZE(ndrc->tramp.f)) {
1004     SysPrintf("trampoline table is full, last func %p\n", f);
1005     abort();
1006   }
1007   if (ndrc->tramp.f[i] == NULL) {
1008     start_tcache_write(&ndrc->tramp.f[i], &ndrc->tramp.f[i + 1]);
1009     ndrc->tramp.f[i] = f;
1010     end_tcache_write(&ndrc->tramp.f[i], &ndrc->tramp.f[i + 1]);
1011   }
1012   return &ndrc->tramp.ops[i];
1013 }
1014
1015 static void emit_far_jump(const void *f)
1016 {
1017   if (can_jump_or_call(f)) {
1018     emit_jmp(f);
1019     return;
1020   }
1021
1022   f = get_trampoline(f);
1023   emit_jmp(f);
1024 }
1025
1026 static void emit_far_call(const void *f)
1027 {
1028   if (can_jump_or_call(f)) {
1029     emit_call(f);
1030     return;
1031   }
1032
1033   f = get_trampoline(f);
1034   emit_call(f);
1035 }
1036
1037 // Add virtual address mapping to linked list
1038 void ll_add(struct ll_entry **head,int vaddr,void *addr)
1039 {
1040   struct ll_entry *new_entry;
1041   new_entry=malloc(sizeof(struct ll_entry));
1042   assert(new_entry!=NULL);
1043   new_entry->vaddr=vaddr;
1044   new_entry->reg_sv_flags=0;
1045   new_entry->addr=addr;
1046   new_entry->next=*head;
1047   *head=new_entry;
1048 }
1049
1050 void ll_add_flags(struct ll_entry **head,int vaddr,u_int reg_sv_flags,void *addr)
1051 {
1052   ll_add(head,vaddr,addr);
1053   (*head)->reg_sv_flags=reg_sv_flags;
1054 }
1055
1056 // Check if an address is already compiled
1057 // but don't return addresses which are about to expire from the cache
1058 void *check_addr(u_int vaddr)
1059 {
1060   struct ht_entry *ht_bin = hash_table_get(vaddr);
1061   size_t i;
1062   for (i = 0; i < ARRAY_SIZE(ht_bin->vaddr); i++) {
1063     if (ht_bin->vaddr[i] == vaddr)
1064       if (doesnt_expire_soon((u_char *)ht_bin->tcaddr[i] - MAX_OUTPUT_BLOCK_SIZE))
1065         if (isclean(ht_bin->tcaddr[i]))
1066           return ht_bin->tcaddr[i];
1067   }
1068   u_int page=get_page(vaddr);
1069   struct ll_entry *head;
1070   head=jump_in[page];
1071   while (head != NULL) {
1072     if (head->vaddr == vaddr) {
1073       if (doesnt_expire_soon(head->addr)) {
1074         // Update existing entry with current address
1075         if (ht_bin->vaddr[0] == vaddr) {
1076           ht_bin->tcaddr[0] = head->addr;
1077           return head->addr;
1078         }
1079         if (ht_bin->vaddr[1] == vaddr) {
1080           ht_bin->tcaddr[1] = head->addr;
1081           return head->addr;
1082         }
1083         // Insert into hash table with low priority.
1084         // Don't evict existing entries, as they are probably
1085         // addresses that are being accessed frequently.
1086         if (ht_bin->vaddr[0] == -1) {
1087           ht_bin->vaddr[0] = vaddr;
1088           ht_bin->tcaddr[0] = head->addr;
1089         }
1090         else if (ht_bin->vaddr[1] == -1) {
1091           ht_bin->vaddr[1] = vaddr;
1092           ht_bin->tcaddr[1] = head->addr;
1093         }
1094         return head->addr;
1095       }
1096     }
1097     head=head->next;
1098   }
1099   return 0;
1100 }
1101
1102 void remove_hash(int vaddr)
1103 {
1104   //printf("remove hash: %x\n",vaddr);
1105   struct ht_entry *ht_bin = hash_table_get(vaddr);
1106   if (ht_bin->vaddr[1] == vaddr) {
1107     ht_bin->vaddr[1] = -1;
1108     ht_bin->tcaddr[1] = NULL;
1109   }
1110   if (ht_bin->vaddr[0] == vaddr) {
1111     ht_bin->vaddr[0] = ht_bin->vaddr[1];
1112     ht_bin->tcaddr[0] = ht_bin->tcaddr[1];
1113     ht_bin->vaddr[1] = -1;
1114     ht_bin->tcaddr[1] = NULL;
1115   }
1116 }
1117
1118 static void ll_remove_matching_addrs(struct ll_entry **head,
1119   uintptr_t base_offs_s, int shift)
1120 {
1121   struct ll_entry *next;
1122   while(*head) {
1123     uintptr_t o1 = (u_char *)(*head)->addr - ndrc->translation_cache;
1124     uintptr_t o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
1125     if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s)
1126     {
1127       inv_debug("EXP: Remove pointer to %p (%x)\n",(*head)->addr,(*head)->vaddr);
1128       remove_hash((*head)->vaddr);
1129       next=(*head)->next;
1130       free(*head);
1131       *head=next;
1132     }
1133     else
1134     {
1135       head=&((*head)->next);
1136     }
1137   }
1138 }
1139
1140 // Remove all entries from linked list
1141 void ll_clear(struct ll_entry **head)
1142 {
1143   struct ll_entry *cur;
1144   struct ll_entry *next;
1145   if((cur=*head)) {
1146     *head=0;
1147     while(cur) {
1148       next=cur->next;
1149       free(cur);
1150       cur=next;
1151     }
1152   }
1153 }
1154
1155 // Dereference the pointers and remove if it matches
1156 static void ll_kill_pointers(struct ll_entry *head,
1157   uintptr_t base_offs_s, int shift)
1158 {
1159   while(head) {
1160     u_char *ptr = get_pointer(head->addr);
1161     uintptr_t o1 = ptr - ndrc->translation_cache;
1162     uintptr_t o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
1163     inv_debug("EXP: Lookup pointer to %p at %p (%x)\n",ptr,head->addr,head->vaddr);
1164     if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s)
1165     {
1166       inv_debug("EXP: Kill pointer at %p (%x)\n",head->addr,head->vaddr);
1167       void *host_addr=find_extjump_insn(head->addr);
1168       mark_clear_cache(host_addr);
1169       set_jump_target(host_addr, head->addr);
1170     }
1171     head=head->next;
1172   }
1173 }
1174
1175 // This is called when we write to a compiled block (see do_invstub)
1176 static void invalidate_page(u_int page)
1177 {
1178   struct ll_entry *head;
1179   struct ll_entry *next;
1180   head=jump_in[page];
1181   jump_in[page]=0;
1182   while(head!=NULL) {
1183     inv_debug("INVALIDATE: %x\n",head->vaddr);
1184     remove_hash(head->vaddr);
1185     next=head->next;
1186     free(head);
1187     head=next;
1188   }
1189   head=jump_out[page];
1190   jump_out[page]=0;
1191   while(head!=NULL) {
1192     inv_debug("INVALIDATE: kill pointer to %x (%p)\n",head->vaddr,head->addr);
1193     void *host_addr=find_extjump_insn(head->addr);
1194     mark_clear_cache(host_addr);
1195     set_jump_target(host_addr, head->addr); // point back to dyna_linker
1196     next=head->next;
1197     free(head);
1198     head=next;
1199   }
1200 }
1201
1202 static void invalidate_block_range(u_int block, u_int first, u_int last)
1203 {
1204   u_int page=get_page(block<<12);
1205   //printf("first=%d last=%d\n",first,last);
1206   invalidate_page(page);
1207   assert(first+5>page); // NB: this assumes MAXBLOCK<=4096 (4 pages)
1208   assert(last<page+5);
1209   // Invalidate the adjacent pages if a block crosses a 4K boundary
1210   while(first<page) {
1211     invalidate_page(first);
1212     first++;
1213   }
1214   for(first=page+1;first<last;first++) {
1215     invalidate_page(first);
1216   }
1217   do_clear_cache();
1218
1219   // Don't trap writes
1220   invalid_code[block]=1;
1221
1222   #ifdef USE_MINI_HT
1223   memset(mini_ht,-1,sizeof(mini_ht));
1224   #endif
1225 }
1226
1227 void invalidate_block(u_int block)
1228 {
1229   u_int page=get_page(block<<12);
1230   u_int vpage=get_vpage(block<<12);
1231   inv_debug("INVALIDATE: %x (%d)\n",block<<12,page);
1232   //inv_debug("invalid_code[block]=%d\n",invalid_code[block]);
1233   u_int first,last;
1234   first=last=page;
1235   struct ll_entry *head;
1236   head=jump_dirty[vpage];
1237   //printf("page=%d vpage=%d\n",page,vpage);
1238   while(head!=NULL) {
1239     if(vpage>2047||(head->vaddr>>12)==block) { // Ignore vaddr hash collision
1240       u_char *start, *end;
1241       get_bounds(head->addr, &start, &end);
1242       //printf("start: %p end: %p\n", start, end);
1243       if (page < 2048 && start >= rdram && end < rdram+RAM_SIZE) {
1244         if (((start-rdram)>>12) <= page && ((end-1-rdram)>>12) >= page) {
1245           if ((((start-rdram)>>12)&2047) < first) first = ((start-rdram)>>12)&2047;
1246           if ((((end-1-rdram)>>12)&2047) > last)  last = ((end-1-rdram)>>12)&2047;
1247         }
1248       }
1249     }
1250     head=head->next;
1251   }
1252   invalidate_block_range(block,first,last);
1253 }
1254
1255 void invalidate_addr(u_int addr)
1256 {
1257   //static int rhits;
1258   // this check is done by the caller
1259   //if (inv_code_start<=addr&&addr<=inv_code_end) { rhits++; return; }
1260   u_int page=get_vpage(addr);
1261   if(page<2048) { // RAM
1262     struct ll_entry *head;
1263     u_int addr_min=~0, addr_max=0;
1264     u_int mask=RAM_SIZE-1;
1265     u_int addr_main=0x80000000|(addr&mask);
1266     int pg1;
1267     inv_code_start=addr_main&~0xfff;
1268     inv_code_end=addr_main|0xfff;
1269     pg1=page;
1270     if (pg1>0) {
1271       // must check previous page too because of spans..
1272       pg1--;
1273       inv_code_start-=0x1000;
1274     }
1275     for(;pg1<=page;pg1++) {
1276       for(head=jump_dirty[pg1];head!=NULL;head=head->next) {
1277         u_char *start_h, *end_h;
1278         u_int start, end;
1279         get_bounds(head->addr, &start_h, &end_h);
1280         start = (uintptr_t)start_h - ram_offset;
1281         end = (uintptr_t)end_h - ram_offset;
1282         if(start<=addr_main&&addr_main<end) {
1283           if(start<addr_min) addr_min=start;
1284           if(end>addr_max) addr_max=end;
1285         }
1286         else if(addr_main<start) {
1287           if(start<inv_code_end)
1288             inv_code_end=start-1;
1289         }
1290         else {
1291           if(end>inv_code_start)
1292             inv_code_start=end;
1293         }
1294       }
1295     }
1296     if (addr_min!=~0) {
1297       inv_debug("INV ADDR: %08x hit %08x-%08x\n", addr, addr_min, addr_max);
1298       inv_code_start=inv_code_end=~0;
1299       invalidate_block_range(addr>>12,(addr_min&mask)>>12,(addr_max&mask)>>12);
1300       return;
1301     }
1302     else {
1303       inv_code_start=(addr&~mask)|(inv_code_start&mask);
1304       inv_code_end=(addr&~mask)|(inv_code_end&mask);
1305       inv_debug("INV ADDR: %08x miss, inv %08x-%08x, sk %d\n", addr, inv_code_start, inv_code_end, 0);
1306       return;
1307     }
1308   }
1309   invalidate_block(addr>>12);
1310 }
1311
1312 // This is called when loading a save state.
1313 // Anything could have changed, so invalidate everything.
1314 void invalidate_all_pages(void)
1315 {
1316   u_int page;
1317   for(page=0;page<4096;page++)
1318     invalidate_page(page);
1319   for(page=0;page<1048576;page++)
1320     if(!invalid_code[page]) {
1321       restore_candidate[(page&2047)>>3]|=1<<(page&7);
1322       restore_candidate[((page&2047)>>3)+256]|=1<<(page&7);
1323     }
1324   #ifdef USE_MINI_HT
1325   memset(mini_ht,-1,sizeof(mini_ht));
1326   #endif
1327   do_clear_cache();
1328 }
1329
1330 static void do_invstub(int n)
1331 {
1332   literal_pool(20);
1333   u_int reglist=stubs[n].a;
1334   set_jump_target(stubs[n].addr, out);
1335   save_regs(reglist);
1336   if(stubs[n].b!=0) emit_mov(stubs[n].b,0);
1337   emit_far_call(invalidate_addr);
1338   restore_regs(reglist);
1339   emit_jmp(stubs[n].retaddr); // return address
1340 }
1341
1342 // Add an entry to jump_out after making a link
1343 // src should point to code by emit_extjump2()
1344 void add_jump_out(u_int vaddr,void *src)
1345 {
1346   u_int page=get_page(vaddr);
1347   inv_debug("add_jump_out: %p -> %x (%d)\n",src,vaddr,page);
1348   check_extjump2(src);
1349   ll_add(jump_out+page,vaddr,src);
1350   //inv_debug("add_jump_out:  to %p\n",get_pointer(src));
1351 }
1352
1353 // If a code block was found to be unmodified (bit was set in
1354 // restore_candidate) and it remains unmodified (bit is clear
1355 // in invalid_code) then move the entries for that 4K page from
1356 // the dirty list to the clean list.
1357 void clean_blocks(u_int page)
1358 {
1359   struct ll_entry *head;
1360   inv_debug("INV: clean_blocks page=%d\n",page);
1361   head=jump_dirty[page];
1362   while(head!=NULL) {
1363     if(!invalid_code[head->vaddr>>12]) {
1364       // Don't restore blocks which are about to expire from the cache
1365       if (doesnt_expire_soon(head->addr)) {
1366         if(verify_dirty(head->addr)) {
1367           u_char *start, *end;
1368           //printf("Possibly Restore %x (%p)\n",head->vaddr, head->addr);
1369           u_int i;
1370           u_int inv=0;
1371           get_bounds(head->addr, &start, &end);
1372           if (start - rdram < RAM_SIZE) {
1373             for (i = (start-rdram+0x80000000)>>12; i <= (end-1-rdram+0x80000000)>>12; i++) {
1374               inv|=invalid_code[i];
1375             }
1376           }
1377           else if((signed int)head->vaddr>=(signed int)0x80000000+RAM_SIZE) {
1378             inv=1;
1379           }
1380           if(!inv) {
1381             void *clean_addr = get_clean_addr(head->addr);
1382             if (doesnt_expire_soon(clean_addr)) {
1383               u_int ppage=page;
1384               inv_debug("INV: Restored %x (%p/%p)\n",head->vaddr, head->addr, clean_addr);
1385               //printf("page=%x, addr=%x\n",page,head->vaddr);
1386               //assert(head->vaddr>>12==(page|0x80000));
1387               ll_add_flags(jump_in+ppage,head->vaddr,head->reg_sv_flags,clean_addr);
1388               struct ht_entry *ht_bin = hash_table_get(head->vaddr);
1389               if (ht_bin->vaddr[0] == head->vaddr)
1390                 ht_bin->tcaddr[0] = clean_addr; // Replace existing entry
1391               if (ht_bin->vaddr[1] == head->vaddr)
1392                 ht_bin->tcaddr[1] = clean_addr; // Replace existing entry
1393             }
1394           }
1395         }
1396       }
1397     }
1398     head=head->next;
1399   }
1400 }
1401
1402 /* Register allocation */
1403
1404 // Note: registers are allocated clean (unmodified state)
1405 // if you intend to modify the register, you must call dirty_reg().
1406 static void alloc_reg(struct regstat *cur,int i,signed char reg)
1407 {
1408   int r,hr;
1409   int preferred_reg = PREFERRED_REG_FIRST
1410     + reg % (PREFERRED_REG_LAST - PREFERRED_REG_FIRST + 1);
1411   if (reg == CCREG) preferred_reg = HOST_CCREG;
1412   if (reg == PTEMP || reg == FTEMP) preferred_reg = 12;
1413   assert(PREFERRED_REG_FIRST != EXCLUDE_REG && EXCLUDE_REG != HOST_REGS);
1414
1415   // Don't allocate unused registers
1416   if((cur->u>>reg)&1) return;
1417
1418   // see if it's already allocated
1419   for(hr=0;hr<HOST_REGS;hr++)
1420   {
1421     if(cur->regmap[hr]==reg) return;
1422   }
1423
1424   // Keep the same mapping if the register was already allocated in a loop
1425   preferred_reg = loop_reg(i,reg,preferred_reg);
1426
1427   // Try to allocate the preferred register
1428   if(cur->regmap[preferred_reg]==-1) {
1429     cur->regmap[preferred_reg]=reg;
1430     cur->dirty&=~(1<<preferred_reg);
1431     cur->isconst&=~(1<<preferred_reg);
1432     return;
1433   }
1434   r=cur->regmap[preferred_reg];
1435   assert(r < 64);
1436   if((cur->u>>r)&1) {
1437     cur->regmap[preferred_reg]=reg;
1438     cur->dirty&=~(1<<preferred_reg);
1439     cur->isconst&=~(1<<preferred_reg);
1440     return;
1441   }
1442
1443   // Clear any unneeded registers
1444   // We try to keep the mapping consistent, if possible, because it
1445   // makes branches easier (especially loops).  So we try to allocate
1446   // first (see above) before removing old mappings.  If this is not
1447   // possible then go ahead and clear out the registers that are no
1448   // longer needed.
1449   for(hr=0;hr<HOST_REGS;hr++)
1450   {
1451     r=cur->regmap[hr];
1452     if(r>=0) {
1453       assert(r < 64);
1454       if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
1455     }
1456   }
1457
1458   // Try to allocate any available register, but prefer
1459   // registers that have not been used recently.
1460   if (i > 0) {
1461     for (hr = PREFERRED_REG_FIRST; ; ) {
1462       if (cur->regmap[hr] < 0) {
1463         int oldreg = regs[i-1].regmap[hr];
1464         if (oldreg < 0 || (oldreg != dops[i-1].rs1 && oldreg != dops[i-1].rs2
1465              && oldreg != dops[i-1].rt1 && oldreg != dops[i-1].rt2))
1466         {
1467           cur->regmap[hr]=reg;
1468           cur->dirty&=~(1<<hr);
1469           cur->isconst&=~(1<<hr);
1470           return;
1471         }
1472       }
1473       hr++;
1474       if (hr == EXCLUDE_REG)
1475         hr++;
1476       if (hr == HOST_REGS)
1477         hr = 0;
1478       if (hr == PREFERRED_REG_FIRST)
1479         break;
1480     }
1481   }
1482
1483   // Try to allocate any available register
1484   for (hr = PREFERRED_REG_FIRST; ; ) {
1485     if (cur->regmap[hr] < 0) {
1486       cur->regmap[hr]=reg;
1487       cur->dirty&=~(1<<hr);
1488       cur->isconst&=~(1<<hr);
1489       return;
1490     }
1491     hr++;
1492     if (hr == EXCLUDE_REG)
1493       hr++;
1494     if (hr == HOST_REGS)
1495       hr = 0;
1496     if (hr == PREFERRED_REG_FIRST)
1497       break;
1498   }
1499
1500   // Ok, now we have to evict someone
1501   // Pick a register we hopefully won't need soon
1502   u_char hsn[MAXREG+1];
1503   memset(hsn,10,sizeof(hsn));
1504   int j;
1505   lsn(hsn,i,&preferred_reg);
1506   //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]);
1507   //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]);
1508   if(i>0) {
1509     // Don't evict the cycle count at entry points, otherwise the entry
1510     // stub will have to write it.
1511     if(dops[i].bt&&hsn[CCREG]>2) hsn[CCREG]=2;
1512     if (i>1 && hsn[CCREG] > 2 && dops[i-2].is_jump) hsn[CCREG]=2;
1513     for(j=10;j>=3;j--)
1514     {
1515       // Alloc preferred register if available
1516       if(hsn[r=cur->regmap[preferred_reg]&63]==j) {
1517         for(hr=0;hr<HOST_REGS;hr++) {
1518           // Evict both parts of a 64-bit register
1519           if(cur->regmap[hr]==r) {
1520             cur->regmap[hr]=-1;
1521             cur->dirty&=~(1<<hr);
1522             cur->isconst&=~(1<<hr);
1523           }
1524         }
1525         cur->regmap[preferred_reg]=reg;
1526         return;
1527       }
1528       for(r=1;r<=MAXREG;r++)
1529       {
1530         if(hsn[r]==j&&r!=dops[i-1].rs1&&r!=dops[i-1].rs2&&r!=dops[i-1].rt1&&r!=dops[i-1].rt2) {
1531           for(hr=0;hr<HOST_REGS;hr++) {
1532             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
1533               if(cur->regmap[hr]==r) {
1534                 cur->regmap[hr]=reg;
1535                 cur->dirty&=~(1<<hr);
1536                 cur->isconst&=~(1<<hr);
1537                 return;
1538               }
1539             }
1540           }
1541         }
1542       }
1543     }
1544   }
1545   for(j=10;j>=0;j--)
1546   {
1547     for(r=1;r<=MAXREG;r++)
1548     {
1549       if(hsn[r]==j) {
1550         for(hr=0;hr<HOST_REGS;hr++) {
1551           if(cur->regmap[hr]==r) {
1552             cur->regmap[hr]=reg;
1553             cur->dirty&=~(1<<hr);
1554             cur->isconst&=~(1<<hr);
1555             return;
1556           }
1557         }
1558       }
1559     }
1560   }
1561   SysPrintf("This shouldn't happen (alloc_reg)");abort();
1562 }
1563
1564 // Allocate a temporary register.  This is done without regard to
1565 // dirty status or whether the register we request is on the unneeded list
1566 // Note: This will only allocate one register, even if called multiple times
1567 static void alloc_reg_temp(struct regstat *cur,int i,signed char reg)
1568 {
1569   int r,hr;
1570   int preferred_reg = -1;
1571
1572   // see if it's already allocated
1573   for(hr=0;hr<HOST_REGS;hr++)
1574   {
1575     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==reg) return;
1576   }
1577
1578   // Try to allocate any available register
1579   for(hr=HOST_REGS-1;hr>=0;hr--) {
1580     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
1581       cur->regmap[hr]=reg;
1582       cur->dirty&=~(1<<hr);
1583       cur->isconst&=~(1<<hr);
1584       return;
1585     }
1586   }
1587
1588   // Find an unneeded register
1589   for(hr=HOST_REGS-1;hr>=0;hr--)
1590   {
1591     r=cur->regmap[hr];
1592     if(r>=0) {
1593       assert(r < 64);
1594       if((cur->u>>r)&1) {
1595         if(i==0||((unneeded_reg[i-1]>>r)&1)) {
1596           cur->regmap[hr]=reg;
1597           cur->dirty&=~(1<<hr);
1598           cur->isconst&=~(1<<hr);
1599           return;
1600         }
1601       }
1602     }
1603   }
1604
1605   // Ok, now we have to evict someone
1606   // Pick a register we hopefully won't need soon
1607   // TODO: we might want to follow unconditional jumps here
1608   // TODO: get rid of dupe code and make this into a function
1609   u_char hsn[MAXREG+1];
1610   memset(hsn,10,sizeof(hsn));
1611   int j;
1612   lsn(hsn,i,&preferred_reg);
1613   //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]);
1614   if(i>0) {
1615     // Don't evict the cycle count at entry points, otherwise the entry
1616     // stub will have to write it.
1617     if(dops[i].bt&&hsn[CCREG]>2) hsn[CCREG]=2;
1618     if (i>1 && hsn[CCREG] > 2 && dops[i-2].is_jump) hsn[CCREG]=2;
1619     for(j=10;j>=3;j--)
1620     {
1621       for(r=1;r<=MAXREG;r++)
1622       {
1623         if(hsn[r]==j&&r!=dops[i-1].rs1&&r!=dops[i-1].rs2&&r!=dops[i-1].rt1&&r!=dops[i-1].rt2) {
1624           for(hr=0;hr<HOST_REGS;hr++) {
1625             if(hr!=HOST_CCREG||hsn[CCREG]>2) {
1626               if(cur->regmap[hr]==r) {
1627                 cur->regmap[hr]=reg;
1628                 cur->dirty&=~(1<<hr);
1629                 cur->isconst&=~(1<<hr);
1630                 return;
1631               }
1632             }
1633           }
1634         }
1635       }
1636     }
1637   }
1638   for(j=10;j>=0;j--)
1639   {
1640     for(r=1;r<=MAXREG;r++)
1641     {
1642       if(hsn[r]==j) {
1643         for(hr=0;hr<HOST_REGS;hr++) {
1644           if(cur->regmap[hr]==r) {
1645             cur->regmap[hr]=reg;
1646             cur->dirty&=~(1<<hr);
1647             cur->isconst&=~(1<<hr);
1648             return;
1649           }
1650         }
1651       }
1652     }
1653   }
1654   SysPrintf("This shouldn't happen");abort();
1655 }
1656
1657 static void mov_alloc(struct regstat *current,int i)
1658 {
1659   if (dops[i].rs1 == HIREG || dops[i].rs1 == LOREG) {
1660     alloc_cc(current,i); // for stalls
1661     dirty_reg(current,CCREG);
1662   }
1663
1664   // Note: Don't need to actually alloc the source registers
1665   //alloc_reg(current,i,dops[i].rs1);
1666   alloc_reg(current,i,dops[i].rt1);
1667
1668   clear_const(current,dops[i].rs1);
1669   clear_const(current,dops[i].rt1);
1670   dirty_reg(current,dops[i].rt1);
1671 }
1672
1673 static void shiftimm_alloc(struct regstat *current,int i)
1674 {
1675   if(dops[i].opcode2<=0x3) // SLL/SRL/SRA
1676   {
1677     if(dops[i].rt1) {
1678       if(dops[i].rs1&&needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
1679       else dops[i].lt1=dops[i].rs1;
1680       alloc_reg(current,i,dops[i].rt1);
1681       dirty_reg(current,dops[i].rt1);
1682       if(is_const(current,dops[i].rs1)) {
1683         int v=get_const(current,dops[i].rs1);
1684         if(dops[i].opcode2==0x00) set_const(current,dops[i].rt1,v<<imm[i]);
1685         if(dops[i].opcode2==0x02) set_const(current,dops[i].rt1,(u_int)v>>imm[i]);
1686         if(dops[i].opcode2==0x03) set_const(current,dops[i].rt1,v>>imm[i]);
1687       }
1688       else clear_const(current,dops[i].rt1);
1689     }
1690   }
1691   else
1692   {
1693     clear_const(current,dops[i].rs1);
1694     clear_const(current,dops[i].rt1);
1695   }
1696
1697   if(dops[i].opcode2>=0x38&&dops[i].opcode2<=0x3b) // DSLL/DSRL/DSRA
1698   {
1699     assert(0);
1700   }
1701   if(dops[i].opcode2==0x3c) // DSLL32
1702   {
1703     assert(0);
1704   }
1705   if(dops[i].opcode2==0x3e) // DSRL32
1706   {
1707     assert(0);
1708   }
1709   if(dops[i].opcode2==0x3f) // DSRA32
1710   {
1711     assert(0);
1712   }
1713 }
1714
1715 static void shift_alloc(struct regstat *current,int i)
1716 {
1717   if(dops[i].rt1) {
1718     if(dops[i].opcode2<=0x07) // SLLV/SRLV/SRAV
1719     {
1720       if(dops[i].rs1) alloc_reg(current,i,dops[i].rs1);
1721       if(dops[i].rs2) alloc_reg(current,i,dops[i].rs2);
1722       alloc_reg(current,i,dops[i].rt1);
1723       if(dops[i].rt1==dops[i].rs2) {
1724         alloc_reg_temp(current,i,-1);
1725         minimum_free_regs[i]=1;
1726       }
1727     } else { // DSLLV/DSRLV/DSRAV
1728       assert(0);
1729     }
1730     clear_const(current,dops[i].rs1);
1731     clear_const(current,dops[i].rs2);
1732     clear_const(current,dops[i].rt1);
1733     dirty_reg(current,dops[i].rt1);
1734   }
1735 }
1736
1737 static void alu_alloc(struct regstat *current,int i)
1738 {
1739   if(dops[i].opcode2>=0x20&&dops[i].opcode2<=0x23) { // ADD/ADDU/SUB/SUBU
1740     if(dops[i].rt1) {
1741       if(dops[i].rs1&&dops[i].rs2) {
1742         alloc_reg(current,i,dops[i].rs1);
1743         alloc_reg(current,i,dops[i].rs2);
1744       }
1745       else {
1746         if(dops[i].rs1&&needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
1747         if(dops[i].rs2&&needed_again(dops[i].rs2,i)) alloc_reg(current,i,dops[i].rs2);
1748       }
1749       alloc_reg(current,i,dops[i].rt1);
1750     }
1751   }
1752   if(dops[i].opcode2==0x2a||dops[i].opcode2==0x2b) { // SLT/SLTU
1753     if(dops[i].rt1) {
1754       alloc_reg(current,i,dops[i].rs1);
1755       alloc_reg(current,i,dops[i].rs2);
1756       alloc_reg(current,i,dops[i].rt1);
1757     }
1758   }
1759   if(dops[i].opcode2>=0x24&&dops[i].opcode2<=0x27) { // AND/OR/XOR/NOR
1760     if(dops[i].rt1) {
1761       if(dops[i].rs1&&dops[i].rs2) {
1762         alloc_reg(current,i,dops[i].rs1);
1763         alloc_reg(current,i,dops[i].rs2);
1764       }
1765       else
1766       {
1767         if(dops[i].rs1&&needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
1768         if(dops[i].rs2&&needed_again(dops[i].rs2,i)) alloc_reg(current,i,dops[i].rs2);
1769       }
1770       alloc_reg(current,i,dops[i].rt1);
1771     }
1772   }
1773   if(dops[i].opcode2>=0x2c&&dops[i].opcode2<=0x2f) { // DADD/DADDU/DSUB/DSUBU
1774     assert(0);
1775   }
1776   clear_const(current,dops[i].rs1);
1777   clear_const(current,dops[i].rs2);
1778   clear_const(current,dops[i].rt1);
1779   dirty_reg(current,dops[i].rt1);
1780 }
1781
1782 static void imm16_alloc(struct regstat *current,int i)
1783 {
1784   if(dops[i].rs1&&needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
1785   else dops[i].lt1=dops[i].rs1;
1786   if(dops[i].rt1) alloc_reg(current,i,dops[i].rt1);
1787   if(dops[i].opcode==0x18||dops[i].opcode==0x19) { // DADDI/DADDIU
1788     assert(0);
1789   }
1790   else if(dops[i].opcode==0x0a||dops[i].opcode==0x0b) { // SLTI/SLTIU
1791     clear_const(current,dops[i].rs1);
1792     clear_const(current,dops[i].rt1);
1793   }
1794   else if(dops[i].opcode>=0x0c&&dops[i].opcode<=0x0e) { // ANDI/ORI/XORI
1795     if(is_const(current,dops[i].rs1)) {
1796       int v=get_const(current,dops[i].rs1);
1797       if(dops[i].opcode==0x0c) set_const(current,dops[i].rt1,v&imm[i]);
1798       if(dops[i].opcode==0x0d) set_const(current,dops[i].rt1,v|imm[i]);
1799       if(dops[i].opcode==0x0e) set_const(current,dops[i].rt1,v^imm[i]);
1800     }
1801     else clear_const(current,dops[i].rt1);
1802   }
1803   else if(dops[i].opcode==0x08||dops[i].opcode==0x09) { // ADDI/ADDIU
1804     if(is_const(current,dops[i].rs1)) {
1805       int v=get_const(current,dops[i].rs1);
1806       set_const(current,dops[i].rt1,v+imm[i]);
1807     }
1808     else clear_const(current,dops[i].rt1);
1809   }
1810   else {
1811     set_const(current,dops[i].rt1,imm[i]<<16); // LUI
1812   }
1813   dirty_reg(current,dops[i].rt1);
1814 }
1815
1816 static void load_alloc(struct regstat *current,int i)
1817 {
1818   clear_const(current,dops[i].rt1);
1819   //if(dops[i].rs1!=dops[i].rt1&&needed_again(dops[i].rs1,i)) clear_const(current,dops[i].rs1); // Does this help or hurt?
1820   if(!dops[i].rs1) current->u&=~1LL; // Allow allocating r0 if it's the source register
1821   if (needed_again(dops[i].rs1, i))
1822     alloc_reg(current, i, dops[i].rs1);
1823   if (ram_offset)
1824     alloc_reg(current, i, ROREG);
1825   if(dops[i].rt1&&!((current->u>>dops[i].rt1)&1)) {
1826     alloc_reg(current,i,dops[i].rt1);
1827     assert(get_reg(current->regmap,dops[i].rt1)>=0);
1828     if(dops[i].opcode==0x27||dops[i].opcode==0x37) // LWU/LD
1829     {
1830       assert(0);
1831     }
1832     else if(dops[i].opcode==0x1A||dops[i].opcode==0x1B) // LDL/LDR
1833     {
1834       assert(0);
1835     }
1836     dirty_reg(current,dops[i].rt1);
1837     // LWL/LWR need a temporary register for the old value
1838     if(dops[i].opcode==0x22||dops[i].opcode==0x26)
1839     {
1840       alloc_reg(current,i,FTEMP);
1841       alloc_reg_temp(current,i,-1);
1842       minimum_free_regs[i]=1;
1843     }
1844   }
1845   else
1846   {
1847     // Load to r0 or unneeded register (dummy load)
1848     // but we still need a register to calculate the address
1849     if(dops[i].opcode==0x22||dops[i].opcode==0x26)
1850     {
1851       alloc_reg(current,i,FTEMP); // LWL/LWR need another temporary
1852     }
1853     alloc_reg_temp(current,i,-1);
1854     minimum_free_regs[i]=1;
1855     if(dops[i].opcode==0x1A||dops[i].opcode==0x1B) // LDL/LDR
1856     {
1857       assert(0);
1858     }
1859   }
1860 }
1861
1862 void store_alloc(struct regstat *current,int i)
1863 {
1864   clear_const(current,dops[i].rs2);
1865   if(!(dops[i].rs2)) current->u&=~1LL; // Allow allocating r0 if necessary
1866   if(needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
1867   alloc_reg(current,i,dops[i].rs2);
1868   if(dops[i].opcode==0x2c||dops[i].opcode==0x2d||dops[i].opcode==0x3f) { // 64-bit SDL/SDR/SD
1869     assert(0);
1870   }
1871   if (ram_offset)
1872     alloc_reg(current, i, ROREG);
1873   #if defined(HOST_IMM8)
1874   // On CPUs without 32-bit immediates we need a pointer to invalid_code
1875   alloc_reg(current, i, INVCP);
1876   #endif
1877   if(dops[i].opcode==0x2a||dops[i].opcode==0x2e||dops[i].opcode==0x2c||dops[i].opcode==0x2d) { // SWL/SWL/SDL/SDR
1878     alloc_reg(current,i,FTEMP);
1879   }
1880   // We need a temporary register for address generation
1881   alloc_reg_temp(current,i,-1);
1882   minimum_free_regs[i]=1;
1883 }
1884
1885 void c1ls_alloc(struct regstat *current,int i)
1886 {
1887   clear_const(current,dops[i].rt1);
1888   alloc_reg(current,i,CSREG); // Status
1889 }
1890
1891 void c2ls_alloc(struct regstat *current,int i)
1892 {
1893   clear_const(current,dops[i].rt1);
1894   if(needed_again(dops[i].rs1,i)) alloc_reg(current,i,dops[i].rs1);
1895   alloc_reg(current,i,FTEMP);
1896   if (ram_offset)
1897     alloc_reg(current, i, ROREG);
1898   #if defined(HOST_IMM8)
1899   // On CPUs without 32-bit immediates we need a pointer to invalid_code
1900   if (dops[i].opcode == 0x3a) // SWC2
1901     alloc_reg(current,i,INVCP);
1902   #endif
1903   // We need a temporary register for address generation
1904   alloc_reg_temp(current,i,-1);
1905   minimum_free_regs[i]=1;
1906 }
1907
1908 #ifndef multdiv_alloc
1909 void multdiv_alloc(struct regstat *current,int i)
1910 {
1911   //  case 0x18: MULT
1912   //  case 0x19: MULTU
1913   //  case 0x1A: DIV
1914   //  case 0x1B: DIVU
1915   //  case 0x1C: DMULT
1916   //  case 0x1D: DMULTU
1917   //  case 0x1E: DDIV
1918   //  case 0x1F: DDIVU
1919   clear_const(current,dops[i].rs1);
1920   clear_const(current,dops[i].rs2);
1921   alloc_cc(current,i); // for stalls
1922   if(dops[i].rs1&&dops[i].rs2)
1923   {
1924     if((dops[i].opcode2&4)==0) // 32-bit
1925     {
1926       current->u&=~(1LL<<HIREG);
1927       current->u&=~(1LL<<LOREG);
1928       alloc_reg(current,i,HIREG);
1929       alloc_reg(current,i,LOREG);
1930       alloc_reg(current,i,dops[i].rs1);
1931       alloc_reg(current,i,dops[i].rs2);
1932       dirty_reg(current,HIREG);
1933       dirty_reg(current,LOREG);
1934     }
1935     else // 64-bit
1936     {
1937       assert(0);
1938     }
1939   }
1940   else
1941   {
1942     // Multiply by zero is zero.
1943     // MIPS does not have a divide by zero exception.
1944     // The result is undefined, we return zero.
1945     alloc_reg(current,i,HIREG);
1946     alloc_reg(current,i,LOREG);
1947     dirty_reg(current,HIREG);
1948     dirty_reg(current,LOREG);
1949   }
1950 }
1951 #endif
1952
1953 void cop0_alloc(struct regstat *current,int i)
1954 {
1955   if(dops[i].opcode2==0) // MFC0
1956   {
1957     if(dops[i].rt1) {
1958       clear_const(current,dops[i].rt1);
1959       alloc_all(current,i);
1960       alloc_reg(current,i,dops[i].rt1);
1961       dirty_reg(current,dops[i].rt1);
1962     }
1963   }
1964   else if(dops[i].opcode2==4) // MTC0
1965   {
1966     if(dops[i].rs1){
1967       clear_const(current,dops[i].rs1);
1968       alloc_reg(current,i,dops[i].rs1);
1969       alloc_all(current,i);
1970     }
1971     else {
1972       alloc_all(current,i); // FIXME: Keep r0
1973       current->u&=~1LL;
1974       alloc_reg(current,i,0);
1975     }
1976   }
1977   else
1978   {
1979     // TLBR/TLBWI/TLBWR/TLBP/ERET
1980     assert(dops[i].opcode2==0x10);
1981     alloc_all(current,i);
1982   }
1983   minimum_free_regs[i]=HOST_REGS;
1984 }
1985
1986 static void cop2_alloc(struct regstat *current,int i)
1987 {
1988   if (dops[i].opcode2 < 3) // MFC2/CFC2
1989   {
1990     alloc_cc(current,i); // for stalls
1991     dirty_reg(current,CCREG);
1992     if(dops[i].rt1){
1993       clear_const(current,dops[i].rt1);
1994       alloc_reg(current,i,dops[i].rt1);
1995       dirty_reg(current,dops[i].rt1);
1996     }
1997   }
1998   else if (dops[i].opcode2 > 3) // MTC2/CTC2
1999   {
2000     if(dops[i].rs1){
2001       clear_const(current,dops[i].rs1);
2002       alloc_reg(current,i,dops[i].rs1);
2003     }
2004     else {
2005       current->u&=~1LL;
2006       alloc_reg(current,i,0);
2007     }
2008   }
2009   alloc_reg_temp(current,i,-1);
2010   minimum_free_regs[i]=1;
2011 }
2012
2013 void c2op_alloc(struct regstat *current,int i)
2014 {
2015   alloc_cc(current,i); // for stalls
2016   dirty_reg(current,CCREG);
2017   alloc_reg_temp(current,i,-1);
2018 }
2019
2020 void syscall_alloc(struct regstat *current,int i)
2021 {
2022   alloc_cc(current,i);
2023   dirty_reg(current,CCREG);
2024   alloc_all(current,i);
2025   minimum_free_regs[i]=HOST_REGS;
2026   current->isconst=0;
2027 }
2028
2029 void delayslot_alloc(struct regstat *current,int i)
2030 {
2031   switch(dops[i].itype) {
2032     case UJUMP:
2033     case CJUMP:
2034     case SJUMP:
2035     case RJUMP:
2036     case SYSCALL:
2037     case HLECALL:
2038     case SPAN:
2039       assem_debug("jump in the delay slot.  this shouldn't happen.\n");//abort();
2040       SysPrintf("Disabled speculative precompilation\n");
2041       stop_after_jal=1;
2042       break;
2043     case IMM16:
2044       imm16_alloc(current,i);
2045       break;
2046     case LOAD:
2047     case LOADLR:
2048       load_alloc(current,i);
2049       break;
2050     case STORE:
2051     case STORELR:
2052       store_alloc(current,i);
2053       break;
2054     case ALU:
2055       alu_alloc(current,i);
2056       break;
2057     case SHIFT:
2058       shift_alloc(current,i);
2059       break;
2060     case MULTDIV:
2061       multdiv_alloc(current,i);
2062       break;
2063     case SHIFTIMM:
2064       shiftimm_alloc(current,i);
2065       break;
2066     case MOV:
2067       mov_alloc(current,i);
2068       break;
2069     case COP0:
2070       cop0_alloc(current,i);
2071       break;
2072     case COP1:
2073       break;
2074     case COP2:
2075       cop2_alloc(current,i);
2076       break;
2077     case C1LS:
2078       c1ls_alloc(current,i);
2079       break;
2080     case C2LS:
2081       c2ls_alloc(current,i);
2082       break;
2083     case C2OP:
2084       c2op_alloc(current,i);
2085       break;
2086   }
2087 }
2088
2089 // Special case where a branch and delay slot span two pages in virtual memory
2090 static void pagespan_alloc(struct regstat *current,int i)
2091 {
2092   current->isconst=0;
2093   current->wasconst=0;
2094   regs[i].wasconst=0;
2095   minimum_free_regs[i]=HOST_REGS;
2096   alloc_all(current,i);
2097   alloc_cc(current,i);
2098   dirty_reg(current,CCREG);
2099   if(dops[i].opcode==3) // JAL
2100   {
2101     alloc_reg(current,i,31);
2102     dirty_reg(current,31);
2103   }
2104   if(dops[i].opcode==0&&(dops[i].opcode2&0x3E)==8) // JR/JALR
2105   {
2106     alloc_reg(current,i,dops[i].rs1);
2107     if (dops[i].rt1!=0) {
2108       alloc_reg(current,i,dops[i].rt1);
2109       dirty_reg(current,dops[i].rt1);
2110     }
2111   }
2112   if((dops[i].opcode&0x2E)==4) // BEQ/BNE/BEQL/BNEL
2113   {
2114     if(dops[i].rs1) alloc_reg(current,i,dops[i].rs1);
2115     if(dops[i].rs2) alloc_reg(current,i,dops[i].rs2);
2116   }
2117   else
2118   if((dops[i].opcode&0x2E)==6) // BLEZ/BGTZ/BLEZL/BGTZL
2119   {
2120     if(dops[i].rs1) alloc_reg(current,i,dops[i].rs1);
2121   }
2122   //else ...
2123 }
2124
2125 static void add_stub(enum stub_type type, void *addr, void *retaddr,
2126   u_int a, uintptr_t b, uintptr_t c, u_int d, u_int e)
2127 {
2128   assert(stubcount < ARRAY_SIZE(stubs));
2129   stubs[stubcount].type = type;
2130   stubs[stubcount].addr = addr;
2131   stubs[stubcount].retaddr = retaddr;
2132   stubs[stubcount].a = a;
2133   stubs[stubcount].b = b;
2134   stubs[stubcount].c = c;
2135   stubs[stubcount].d = d;
2136   stubs[stubcount].e = e;
2137   stubcount++;
2138 }
2139
2140 static void add_stub_r(enum stub_type type, void *addr, void *retaddr,
2141   int i, int addr_reg, const struct regstat *i_regs, int ccadj, u_int reglist)
2142 {
2143   add_stub(type, addr, retaddr, i, addr_reg, (uintptr_t)i_regs, ccadj, reglist);
2144 }
2145
2146 // Write out a single register
2147 static void wb_register(signed char r, const signed char regmap[], uint64_t dirty)
2148 {
2149   int hr;
2150   for(hr=0;hr<HOST_REGS;hr++) {
2151     if(hr!=EXCLUDE_REG) {
2152       if(regmap[hr]==r) {
2153         if((dirty>>hr)&1) {
2154           assert(regmap[hr]<64);
2155           emit_storereg(r,hr);
2156         }
2157       }
2158     }
2159   }
2160 }
2161
2162 static void wb_valid(signed char pre[],signed char entry[],u_int dirty_pre,u_int dirty,uint64_t u)
2163 {
2164   //if(dirty_pre==dirty) return;
2165   int hr,reg;
2166   for(hr=0;hr<HOST_REGS;hr++) {
2167     if(hr!=EXCLUDE_REG) {
2168       reg=pre[hr];
2169       if(((~u)>>reg)&1) {
2170         if(reg>0) {
2171           if(((dirty_pre&~dirty)>>hr)&1) {
2172             if(reg>0&&reg<34) {
2173               emit_storereg(reg,hr);
2174             }
2175             else if(reg>=64) {
2176               assert(0);
2177             }
2178           }
2179         }
2180       }
2181     }
2182   }
2183 }
2184
2185 // trashes r2
2186 static void pass_args(int a0, int a1)
2187 {
2188   if(a0==1&&a1==0) {
2189     // must swap
2190     emit_mov(a0,2); emit_mov(a1,1); emit_mov(2,0);
2191   }
2192   else if(a0!=0&&a1==0) {
2193     emit_mov(a1,1);
2194     if (a0>=0) emit_mov(a0,0);
2195   }
2196   else {
2197     if(a0>=0&&a0!=0) emit_mov(a0,0);
2198     if(a1>=0&&a1!=1) emit_mov(a1,1);
2199   }
2200 }
2201
2202 static void alu_assemble(int i, const struct regstat *i_regs)
2203 {
2204   if(dops[i].opcode2>=0x20&&dops[i].opcode2<=0x23) { // ADD/ADDU/SUB/SUBU
2205     if(dops[i].rt1) {
2206       signed char s1,s2,t;
2207       t=get_reg(i_regs->regmap,dops[i].rt1);
2208       if(t>=0) {
2209         s1=get_reg(i_regs->regmap,dops[i].rs1);
2210         s2=get_reg(i_regs->regmap,dops[i].rs2);
2211         if(dops[i].rs1&&dops[i].rs2) {
2212           assert(s1>=0);
2213           assert(s2>=0);
2214           if(dops[i].opcode2&2) emit_sub(s1,s2,t);
2215           else emit_add(s1,s2,t);
2216         }
2217         else if(dops[i].rs1) {
2218           if(s1>=0) emit_mov(s1,t);
2219           else emit_loadreg(dops[i].rs1,t);
2220         }
2221         else if(dops[i].rs2) {
2222           if(s2>=0) {
2223             if(dops[i].opcode2&2) emit_neg(s2,t);
2224             else emit_mov(s2,t);
2225           }
2226           else {
2227             emit_loadreg(dops[i].rs2,t);
2228             if(dops[i].opcode2&2) emit_neg(t,t);
2229           }
2230         }
2231         else emit_zeroreg(t);
2232       }
2233     }
2234   }
2235   if(dops[i].opcode2>=0x2c&&dops[i].opcode2<=0x2f) { // DADD/DADDU/DSUB/DSUBU
2236     assert(0);
2237   }
2238   if(dops[i].opcode2==0x2a||dops[i].opcode2==0x2b) { // SLT/SLTU
2239     if(dops[i].rt1) {
2240       signed char s1l,s2l,t;
2241       {
2242         t=get_reg(i_regs->regmap,dops[i].rt1);
2243         //assert(t>=0);
2244         if(t>=0) {
2245           s1l=get_reg(i_regs->regmap,dops[i].rs1);
2246           s2l=get_reg(i_regs->regmap,dops[i].rs2);
2247           if(dops[i].rs2==0) // rx<r0
2248           {
2249             if(dops[i].opcode2==0x2a&&dops[i].rs1!=0) { // SLT
2250               assert(s1l>=0);
2251               emit_shrimm(s1l,31,t);
2252             }
2253             else // SLTU (unsigned can not be less than zero, 0<0)
2254               emit_zeroreg(t);
2255           }
2256           else if(dops[i].rs1==0) // r0<rx
2257           {
2258             assert(s2l>=0);
2259             if(dops[i].opcode2==0x2a) // SLT
2260               emit_set_gz32(s2l,t);
2261             else // SLTU (set if not zero)
2262               emit_set_nz32(s2l,t);
2263           }
2264           else{
2265             assert(s1l>=0);assert(s2l>=0);
2266             if(dops[i].opcode2==0x2a) // SLT
2267               emit_set_if_less32(s1l,s2l,t);
2268             else // SLTU
2269               emit_set_if_carry32(s1l,s2l,t);
2270           }
2271         }
2272       }
2273     }
2274   }
2275   if(dops[i].opcode2>=0x24&&dops[i].opcode2<=0x27) { // AND/OR/XOR/NOR
2276     if(dops[i].rt1) {
2277       signed char s1l,s2l,tl;
2278       tl=get_reg(i_regs->regmap,dops[i].rt1);
2279       {
2280         if(tl>=0) {
2281           s1l=get_reg(i_regs->regmap,dops[i].rs1);
2282           s2l=get_reg(i_regs->regmap,dops[i].rs2);
2283           if(dops[i].rs1&&dops[i].rs2) {
2284             assert(s1l>=0);
2285             assert(s2l>=0);
2286             if(dops[i].opcode2==0x24) { // AND
2287               emit_and(s1l,s2l,tl);
2288             } else
2289             if(dops[i].opcode2==0x25) { // OR
2290               emit_or(s1l,s2l,tl);
2291             } else
2292             if(dops[i].opcode2==0x26) { // XOR
2293               emit_xor(s1l,s2l,tl);
2294             } else
2295             if(dops[i].opcode2==0x27) { // NOR
2296               emit_or(s1l,s2l,tl);
2297               emit_not(tl,tl);
2298             }
2299           }
2300           else
2301           {
2302             if(dops[i].opcode2==0x24) { // AND
2303               emit_zeroreg(tl);
2304             } else
2305             if(dops[i].opcode2==0x25||dops[i].opcode2==0x26) { // OR/XOR
2306               if(dops[i].rs1){
2307                 if(s1l>=0) emit_mov(s1l,tl);
2308                 else emit_loadreg(dops[i].rs1,tl); // CHECK: regmap_entry?
2309               }
2310               else
2311               if(dops[i].rs2){
2312                 if(s2l>=0) emit_mov(s2l,tl);
2313                 else emit_loadreg(dops[i].rs2,tl); // CHECK: regmap_entry?
2314               }
2315               else emit_zeroreg(tl);
2316             } else
2317             if(dops[i].opcode2==0x27) { // NOR
2318               if(dops[i].rs1){
2319                 if(s1l>=0) emit_not(s1l,tl);
2320                 else {
2321                   emit_loadreg(dops[i].rs1,tl);
2322                   emit_not(tl,tl);
2323                 }
2324               }
2325               else
2326               if(dops[i].rs2){
2327                 if(s2l>=0) emit_not(s2l,tl);
2328                 else {
2329                   emit_loadreg(dops[i].rs2,tl);
2330                   emit_not(tl,tl);
2331                 }
2332               }
2333               else emit_movimm(-1,tl);
2334             }
2335           }
2336         }
2337       }
2338     }
2339   }
2340 }
2341
2342 static void imm16_assemble(int i, const struct regstat *i_regs)
2343 {
2344   if (dops[i].opcode==0x0f) { // LUI
2345     if(dops[i].rt1) {
2346       signed char t;
2347       t=get_reg(i_regs->regmap,dops[i].rt1);
2348       //assert(t>=0);
2349       if(t>=0) {
2350         if(!((i_regs->isconst>>t)&1))
2351           emit_movimm(imm[i]<<16,t);
2352       }
2353     }
2354   }
2355   if(dops[i].opcode==0x08||dops[i].opcode==0x09) { // ADDI/ADDIU
2356     if(dops[i].rt1) {
2357       signed char s,t;
2358       t=get_reg(i_regs->regmap,dops[i].rt1);
2359       s=get_reg(i_regs->regmap,dops[i].rs1);
2360       if(dops[i].rs1) {
2361         //assert(t>=0);
2362         //assert(s>=0);
2363         if(t>=0) {
2364           if(!((i_regs->isconst>>t)&1)) {
2365             if(s<0) {
2366               if(i_regs->regmap_entry[t]!=dops[i].rs1) emit_loadreg(dops[i].rs1,t);
2367               emit_addimm(t,imm[i],t);
2368             }else{
2369               if(!((i_regs->wasconst>>s)&1))
2370                 emit_addimm(s,imm[i],t);
2371               else
2372                 emit_movimm(constmap[i][s]+imm[i],t);
2373             }
2374           }
2375         }
2376       } else {
2377         if(t>=0) {
2378           if(!((i_regs->isconst>>t)&1))
2379             emit_movimm(imm[i],t);
2380         }
2381       }
2382     }
2383   }
2384   if(dops[i].opcode==0x18||dops[i].opcode==0x19) { // DADDI/DADDIU
2385     if(dops[i].rt1) {
2386       signed char sl,tl;
2387       tl=get_reg(i_regs->regmap,dops[i].rt1);
2388       sl=get_reg(i_regs->regmap,dops[i].rs1);
2389       if(tl>=0) {
2390         if(dops[i].rs1) {
2391           assert(sl>=0);
2392           emit_addimm(sl,imm[i],tl);
2393         } else {
2394           emit_movimm(imm[i],tl);
2395         }
2396       }
2397     }
2398   }
2399   else if(dops[i].opcode==0x0a||dops[i].opcode==0x0b) { // SLTI/SLTIU
2400     if(dops[i].rt1) {
2401       //assert(dops[i].rs1!=0); // r0 might be valid, but it's probably a bug
2402       signed char sl,t;
2403       t=get_reg(i_regs->regmap,dops[i].rt1);
2404       sl=get_reg(i_regs->regmap,dops[i].rs1);
2405       //assert(t>=0);
2406       if(t>=0) {
2407         if(dops[i].rs1>0) {
2408             if(dops[i].opcode==0x0a) { // SLTI
2409               if(sl<0) {
2410                 if(i_regs->regmap_entry[t]!=dops[i].rs1) emit_loadreg(dops[i].rs1,t);
2411                 emit_slti32(t,imm[i],t);
2412               }else{
2413                 emit_slti32(sl,imm[i],t);
2414               }
2415             }
2416             else { // SLTIU
2417               if(sl<0) {
2418                 if(i_regs->regmap_entry[t]!=dops[i].rs1) emit_loadreg(dops[i].rs1,t);
2419                 emit_sltiu32(t,imm[i],t);
2420               }else{
2421                 emit_sltiu32(sl,imm[i],t);
2422               }
2423             }
2424         }else{
2425           // SLTI(U) with r0 is just stupid,
2426           // nonetheless examples can be found
2427           if(dops[i].opcode==0x0a) // SLTI
2428             if(0<imm[i]) emit_movimm(1,t);
2429             else emit_zeroreg(t);
2430           else // SLTIU
2431           {
2432             if(imm[i]) emit_movimm(1,t);
2433             else emit_zeroreg(t);
2434           }
2435         }
2436       }
2437     }
2438   }
2439   else if(dops[i].opcode>=0x0c&&dops[i].opcode<=0x0e) { // ANDI/ORI/XORI
2440     if(dops[i].rt1) {
2441       signed char sl,tl;
2442       tl=get_reg(i_regs->regmap,dops[i].rt1);
2443       sl=get_reg(i_regs->regmap,dops[i].rs1);
2444       if(tl>=0 && !((i_regs->isconst>>tl)&1)) {
2445         if(dops[i].opcode==0x0c) //ANDI
2446         {
2447           if(dops[i].rs1) {
2448             if(sl<0) {
2449               if(i_regs->regmap_entry[tl]!=dops[i].rs1) emit_loadreg(dops[i].rs1,tl);
2450               emit_andimm(tl,imm[i],tl);
2451             }else{
2452               if(!((i_regs->wasconst>>sl)&1))
2453                 emit_andimm(sl,imm[i],tl);
2454               else
2455                 emit_movimm(constmap[i][sl]&imm[i],tl);
2456             }
2457           }
2458           else
2459             emit_zeroreg(tl);
2460         }
2461         else
2462         {
2463           if(dops[i].rs1) {
2464             if(sl<0) {
2465               if(i_regs->regmap_entry[tl]!=dops[i].rs1) emit_loadreg(dops[i].rs1,tl);
2466             }
2467             if(dops[i].opcode==0x0d) { // ORI
2468               if(sl<0) {
2469                 emit_orimm(tl,imm[i],tl);
2470               }else{
2471                 if(!((i_regs->wasconst>>sl)&1))
2472                   emit_orimm(sl,imm[i],tl);
2473                 else
2474                   emit_movimm(constmap[i][sl]|imm[i],tl);
2475               }
2476             }
2477             if(dops[i].opcode==0x0e) { // XORI
2478               if(sl<0) {
2479                 emit_xorimm(tl,imm[i],tl);
2480               }else{
2481                 if(!((i_regs->wasconst>>sl)&1))
2482                   emit_xorimm(sl,imm[i],tl);
2483                 else
2484                   emit_movimm(constmap[i][sl]^imm[i],tl);
2485               }
2486             }
2487           }
2488           else {
2489             emit_movimm(imm[i],tl);
2490           }
2491         }
2492       }
2493     }
2494   }
2495 }
2496
2497 static void shiftimm_assemble(int i, const struct regstat *i_regs)
2498 {
2499   if(dops[i].opcode2<=0x3) // SLL/SRL/SRA
2500   {
2501     if(dops[i].rt1) {
2502       signed char s,t;
2503       t=get_reg(i_regs->regmap,dops[i].rt1);
2504       s=get_reg(i_regs->regmap,dops[i].rs1);
2505       //assert(t>=0);
2506       if(t>=0&&!((i_regs->isconst>>t)&1)){
2507         if(dops[i].rs1==0)
2508         {
2509           emit_zeroreg(t);
2510         }
2511         else
2512         {
2513           if(s<0&&i_regs->regmap_entry[t]!=dops[i].rs1) emit_loadreg(dops[i].rs1,t);
2514           if(imm[i]) {
2515             if(dops[i].opcode2==0) // SLL
2516             {
2517               emit_shlimm(s<0?t:s,imm[i],t);
2518             }
2519             if(dops[i].opcode2==2) // SRL
2520             {
2521               emit_shrimm(s<0?t:s,imm[i],t);
2522             }
2523             if(dops[i].opcode2==3) // SRA
2524             {
2525               emit_sarimm(s<0?t:s,imm[i],t);
2526             }
2527           }else{
2528             // Shift by zero
2529             if(s>=0 && s!=t) emit_mov(s,t);
2530           }
2531         }
2532       }
2533       //emit_storereg(dops[i].rt1,t); //DEBUG
2534     }
2535   }
2536   if(dops[i].opcode2>=0x38&&dops[i].opcode2<=0x3b) // DSLL/DSRL/DSRA
2537   {
2538     assert(0);
2539   }
2540   if(dops[i].opcode2==0x3c) // DSLL32
2541   {
2542     assert(0);
2543   }
2544   if(dops[i].opcode2==0x3e) // DSRL32
2545   {
2546     assert(0);
2547   }
2548   if(dops[i].opcode2==0x3f) // DSRA32
2549   {
2550     assert(0);
2551   }
2552 }
2553
2554 #ifndef shift_assemble
2555 static void shift_assemble(int i, const struct regstat *i_regs)
2556 {
2557   signed char s,t,shift;
2558   if (dops[i].rt1 == 0)
2559     return;
2560   assert(dops[i].opcode2<=0x07); // SLLV/SRLV/SRAV
2561   t = get_reg(i_regs->regmap, dops[i].rt1);
2562   s = get_reg(i_regs->regmap, dops[i].rs1);
2563   shift = get_reg(i_regs->regmap, dops[i].rs2);
2564   if (t < 0)
2565     return;
2566
2567   if(dops[i].rs1==0)
2568     emit_zeroreg(t);
2569   else if(dops[i].rs2==0) {
2570     assert(s>=0);
2571     if(s!=t) emit_mov(s,t);
2572   }
2573   else {
2574     host_tempreg_acquire();
2575     emit_andimm(shift,31,HOST_TEMPREG);
2576     switch(dops[i].opcode2) {
2577     case 4: // SLLV
2578       emit_shl(s,HOST_TEMPREG,t);
2579       break;
2580     case 6: // SRLV
2581       emit_shr(s,HOST_TEMPREG,t);
2582       break;
2583     case 7: // SRAV
2584       emit_sar(s,HOST_TEMPREG,t);
2585       break;
2586     default:
2587       assert(0);
2588     }
2589     host_tempreg_release();
2590   }
2591 }
2592
2593 #endif
2594
2595 enum {
2596   MTYPE_8000 = 0,
2597   MTYPE_8020,
2598   MTYPE_0000,
2599   MTYPE_A000,
2600   MTYPE_1F80,
2601 };
2602
2603 static int get_ptr_mem_type(u_int a)
2604 {
2605   if(a < 0x00200000) {
2606     if(a<0x1000&&((start>>20)==0xbfc||(start>>24)==0xa0))
2607       // return wrong, must use memhandler for BIOS self-test to pass
2608       // 007 does similar stuff from a00 mirror, weird stuff
2609       return MTYPE_8000;
2610     return MTYPE_0000;
2611   }
2612   if(0x1f800000 <= a && a < 0x1f801000)
2613     return MTYPE_1F80;
2614   if(0x80200000 <= a && a < 0x80800000)
2615     return MTYPE_8020;
2616   if(0xa0000000 <= a && a < 0xa0200000)
2617     return MTYPE_A000;
2618   return MTYPE_8000;
2619 }
2620
2621 static int get_ro_reg(const struct regstat *i_regs, int host_tempreg_free)
2622 {
2623   int r = get_reg(i_regs->regmap, ROREG);
2624   if (r < 0 && host_tempreg_free) {
2625     host_tempreg_acquire();
2626     emit_loadreg(ROREG, r = HOST_TEMPREG);
2627   }
2628   if (r < 0)
2629     abort();
2630   return r;
2631 }
2632
2633 static void *emit_fastpath_cmp_jump(int i, const struct regstat *i_regs,
2634   int addr, int *offset_reg, int *addr_reg_override)
2635 {
2636   void *jaddr = NULL;
2637   int type = 0;
2638   int mr = dops[i].rs1;
2639   *offset_reg = -1;
2640   if(((smrv_strong|smrv_weak)>>mr)&1) {
2641     type=get_ptr_mem_type(smrv[mr]);
2642     //printf("set %08x @%08x r%d %d\n", smrv[mr], start+i*4, mr, type);
2643   }
2644   else {
2645     // use the mirror we are running on
2646     type=get_ptr_mem_type(start);
2647     //printf("set nospec   @%08x r%d %d\n", start+i*4, mr, type);
2648   }
2649
2650   if(type==MTYPE_8020) { // RAM 80200000+ mirror
2651     host_tempreg_acquire();
2652     emit_andimm(addr,~0x00e00000,HOST_TEMPREG);
2653     addr=*addr_reg_override=HOST_TEMPREG;
2654     type=0;
2655   }
2656   else if(type==MTYPE_0000) { // RAM 0 mirror
2657     host_tempreg_acquire();
2658     emit_orimm(addr,0x80000000,HOST_TEMPREG);
2659     addr=*addr_reg_override=HOST_TEMPREG;
2660     type=0;
2661   }
2662   else if(type==MTYPE_A000) { // RAM A mirror
2663     host_tempreg_acquire();
2664     emit_andimm(addr,~0x20000000,HOST_TEMPREG);
2665     addr=*addr_reg_override=HOST_TEMPREG;
2666     type=0;
2667   }
2668   else if(type==MTYPE_1F80) { // scratchpad
2669     if (psxH == (void *)0x1f800000) {
2670       host_tempreg_acquire();
2671       emit_xorimm(addr,0x1f800000,HOST_TEMPREG);
2672       emit_cmpimm(HOST_TEMPREG,0x1000);
2673       host_tempreg_release();
2674       jaddr=out;
2675       emit_jc(0);
2676     }
2677     else {
2678       // do the usual RAM check, jump will go to the right handler
2679       type=0;
2680     }
2681   }
2682
2683   if (type == 0) // need ram check
2684   {
2685     emit_cmpimm(addr,RAM_SIZE);
2686     jaddr = out;
2687     #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
2688     // Hint to branch predictor that the branch is unlikely to be taken
2689     if (dops[i].rs1 >= 28)
2690       emit_jno_unlikely(0);
2691     else
2692     #endif
2693       emit_jno(0);
2694     if (ram_offset != 0)
2695       *offset_reg = get_ro_reg(i_regs, 0);
2696   }
2697
2698   return jaddr;
2699 }
2700
2701 // return memhandler, or get directly accessable address and return 0
2702 static void *get_direct_memhandler(void *table, u_int addr,
2703   enum stub_type type, uintptr_t *addr_host)
2704 {
2705   uintptr_t msb = 1ull << (sizeof(uintptr_t)*8 - 1);
2706   uintptr_t l1, l2 = 0;
2707   l1 = ((uintptr_t *)table)[addr>>12];
2708   if (!(l1 & msb)) {
2709     uintptr_t v = l1 << 1;
2710     *addr_host = v + addr;
2711     return NULL;
2712   }
2713   else {
2714     l1 <<= 1;
2715     if (type == LOADB_STUB || type == LOADBU_STUB || type == STOREB_STUB)
2716       l2 = ((uintptr_t *)l1)[0x1000/4 + 0x1000/2 + (addr&0xfff)];
2717     else if (type == LOADH_STUB || type == LOADHU_STUB || type == STOREH_STUB)
2718       l2 = ((uintptr_t *)l1)[0x1000/4 + (addr&0xfff)/2];
2719     else
2720       l2 = ((uintptr_t *)l1)[(addr&0xfff)/4];
2721     if (!(l2 & msb)) {
2722       uintptr_t v = l2 << 1;
2723       *addr_host = v + (addr&0xfff);
2724       return NULL;
2725     }
2726     return (void *)(l2 << 1);
2727   }
2728 }
2729
2730 static u_int get_host_reglist(const signed char *regmap)
2731 {
2732   u_int reglist = 0, hr;
2733   for (hr = 0; hr < HOST_REGS; hr++) {
2734     if (hr != EXCLUDE_REG && regmap[hr] >= 0)
2735       reglist |= 1 << hr;
2736   }
2737   return reglist;
2738 }
2739
2740 static u_int reglist_exclude(u_int reglist, int r1, int r2)
2741 {
2742   if (r1 >= 0)
2743     reglist &= ~(1u << r1);
2744   if (r2 >= 0)
2745     reglist &= ~(1u << r2);
2746   return reglist;
2747 }
2748
2749 // find a temp caller-saved register not in reglist (so assumed to be free)
2750 static int reglist_find_free(u_int reglist)
2751 {
2752   u_int free_regs = ~reglist & CALLER_SAVE_REGS;
2753   if (free_regs == 0)
2754     return -1;
2755   return __builtin_ctz(free_regs);
2756 }
2757
2758 static void do_load_word(int a, int rt, int offset_reg)
2759 {
2760   if (offset_reg >= 0)
2761     emit_ldr_dualindexed(offset_reg, a, rt);
2762   else
2763     emit_readword_indexed(0, a, rt);
2764 }
2765
2766 static void do_store_word(int a, int ofs, int rt, int offset_reg, int preseve_a)
2767 {
2768   if (offset_reg < 0) {
2769     emit_writeword_indexed(rt, ofs, a);
2770     return;
2771   }
2772   if (ofs != 0)
2773     emit_addimm(a, ofs, a);
2774   emit_str_dualindexed(offset_reg, a, rt);
2775   if (ofs != 0 && preseve_a)
2776     emit_addimm(a, -ofs, a);
2777 }
2778
2779 static void do_store_hword(int a, int ofs, int rt, int offset_reg, int preseve_a)
2780 {
2781   if (offset_reg < 0) {
2782     emit_writehword_indexed(rt, ofs, a);
2783     return;
2784   }
2785   if (ofs != 0)
2786     emit_addimm(a, ofs, a);
2787   emit_strh_dualindexed(offset_reg, a, rt);
2788   if (ofs != 0 && preseve_a)
2789     emit_addimm(a, -ofs, a);
2790 }
2791
2792 static void do_store_byte(int a, int rt, int offset_reg)
2793 {
2794   if (offset_reg >= 0)
2795     emit_strb_dualindexed(offset_reg, a, rt);
2796   else
2797     emit_writebyte_indexed(rt, 0, a);
2798 }
2799
2800 static void load_assemble(int i, const struct regstat *i_regs, int ccadj_)
2801 {
2802   int s,tl,addr;
2803   int offset;
2804   void *jaddr=0;
2805   int memtarget=0,c=0;
2806   int offset_reg = -1;
2807   int fastio_reg_override = -1;
2808   u_int reglist=get_host_reglist(i_regs->regmap);
2809   tl=get_reg(i_regs->regmap,dops[i].rt1);
2810   s=get_reg(i_regs->regmap,dops[i].rs1);
2811   offset=imm[i];
2812   if(i_regs->regmap[HOST_CCREG]==CCREG) reglist&=~(1<<HOST_CCREG);
2813   if(s>=0) {
2814     c=(i_regs->wasconst>>s)&1;
2815     if (c) {
2816       memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE;
2817     }
2818   }
2819   //printf("load_assemble: c=%d\n",c);
2820   //if(c) printf("load_assemble: const=%lx\n",(long)constmap[i][s]+offset);
2821   // FIXME: Even if the load is a NOP, we should check for pagefaults...
2822   if((tl<0&&(!c||(((u_int)constmap[i][s]+offset)>>16)==0x1f80))
2823     ||dops[i].rt1==0) {
2824       // could be FIFO, must perform the read
2825       // ||dummy read
2826       assem_debug("(forced read)\n");
2827       tl=get_reg_temp(i_regs->regmap);
2828       assert(tl>=0);
2829   }
2830   if(offset||s<0||c) addr=tl;
2831   else addr=s;
2832   //if(tl<0) tl=get_reg_temp(i_regs->regmap);
2833  if(tl>=0) {
2834   //printf("load_assemble: c=%d\n",c);
2835   //if(c) printf("load_assemble: const=%lx\n",(long)constmap[i][s]+offset);
2836   assert(tl>=0); // Even if the load is a NOP, we must check for pagefaults and I/O
2837   reglist&=~(1<<tl);
2838   if(!c) {
2839     #ifdef R29_HACK
2840     // Strmnnrmn's speed hack
2841     if(dops[i].rs1!=29||start<0x80001000||start>=0x80000000+RAM_SIZE)
2842     #endif
2843     {
2844       jaddr = emit_fastpath_cmp_jump(i, i_regs, addr,
2845                 &offset_reg, &fastio_reg_override);
2846     }
2847   }
2848   else if (ram_offset && memtarget) {
2849     offset_reg = get_ro_reg(i_regs, 0);
2850   }
2851   int dummy=(dops[i].rt1==0)||(tl!=get_reg(i_regs->regmap,dops[i].rt1)); // ignore loads to r0 and unneeded reg
2852   switch (dops[i].opcode) {
2853   case 0x20: // LB
2854     if(!c||memtarget) {
2855       if(!dummy) {
2856         int a = tl;
2857         if (!c) a = addr;
2858         if (fastio_reg_override >= 0)
2859           a = fastio_reg_override;
2860
2861         if (offset_reg >= 0)
2862           emit_ldrsb_dualindexed(offset_reg, a, tl);
2863         else
2864           emit_movsbl_indexed(0, a, tl);
2865       }
2866       if(jaddr)
2867         add_stub_r(LOADB_STUB,jaddr,out,i,addr,i_regs,ccadj_,reglist);
2868     }
2869     else
2870       inline_readstub(LOADB_STUB,i,constmap[i][s]+offset,i_regs->regmap,dops[i].rt1,ccadj_,reglist);
2871     break;
2872   case 0x21: // LH
2873     if(!c||memtarget) {
2874       if(!dummy) {
2875         int a = tl;
2876         if (!c) a = addr;
2877         if (fastio_reg_override >= 0)
2878           a = fastio_reg_override;
2879         if (offset_reg >= 0)
2880           emit_ldrsh_dualindexed(offset_reg, a, tl);
2881         else
2882           emit_movswl_indexed(0, a, tl);
2883       }
2884       if(jaddr)
2885         add_stub_r(LOADH_STUB,jaddr,out,i,addr,i_regs,ccadj_,reglist);
2886     }
2887     else
2888       inline_readstub(LOADH_STUB,i,constmap[i][s]+offset,i_regs->regmap,dops[i].rt1,ccadj_,reglist);
2889     break;
2890   case 0x23: // LW
2891     if(!c||memtarget) {
2892       if(!dummy) {
2893         int a = addr;
2894         if (fastio_reg_override >= 0)
2895           a = fastio_reg_override;
2896         do_load_word(a, tl, offset_reg);
2897       }
2898       if(jaddr)
2899         add_stub_r(LOADW_STUB,jaddr,out,i,addr,i_regs,ccadj_,reglist);
2900     }
2901     else
2902       inline_readstub(LOADW_STUB,i,constmap[i][s]+offset,i_regs->regmap,dops[i].rt1,ccadj_,reglist);
2903     break;
2904   case 0x24: // LBU
2905     if(!c||memtarget) {
2906       if(!dummy) {
2907         int a = tl;
2908         if (!c) a = addr;
2909         if (fastio_reg_override >= 0)
2910           a = fastio_reg_override;
2911
2912         if (offset_reg >= 0)
2913           emit_ldrb_dualindexed(offset_reg, a, tl);
2914         else
2915           emit_movzbl_indexed(0, a, tl);
2916       }
2917       if(jaddr)
2918         add_stub_r(LOADBU_STUB,jaddr,out,i,addr,i_regs,ccadj_,reglist);
2919     }
2920     else
2921       inline_readstub(LOADBU_STUB,i,constmap[i][s]+offset,i_regs->regmap,dops[i].rt1,ccadj_,reglist);
2922     break;
2923   case 0x25: // LHU
2924     if(!c||memtarget) {
2925       if(!dummy) {
2926         int a = tl;
2927         if(!c) a = addr;
2928         if (fastio_reg_override >= 0)
2929           a = fastio_reg_override;
2930         if (offset_reg >= 0)
2931           emit_ldrh_dualindexed(offset_reg, a, tl);
2932         else
2933           emit_movzwl_indexed(0, a, tl);
2934       }
2935       if(jaddr)
2936         add_stub_r(LOADHU_STUB,jaddr,out,i,addr,i_regs,ccadj_,reglist);
2937     }
2938     else
2939       inline_readstub(LOADHU_STUB,i,constmap[i][s]+offset,i_regs->regmap,dops[i].rt1,ccadj_,reglist);
2940     break;
2941   case 0x27: // LWU
2942   case 0x37: // LD
2943   default:
2944     assert(0);
2945   }
2946  }
2947  if (fastio_reg_override == HOST_TEMPREG || offset_reg == HOST_TEMPREG)
2948    host_tempreg_release();
2949 }
2950
2951 #ifndef loadlr_assemble
2952 static void loadlr_assemble(int i, const struct regstat *i_regs, int ccadj_)
2953 {
2954   int s,tl,temp,temp2,addr;
2955   int offset;
2956   void *jaddr=0;
2957   int memtarget=0,c=0;
2958   int offset_reg = -1;
2959   int fastio_reg_override = -1;
2960   u_int reglist=get_host_reglist(i_regs->regmap);
2961   tl=get_reg(i_regs->regmap,dops[i].rt1);
2962   s=get_reg(i_regs->regmap,dops[i].rs1);
2963   temp=get_reg_temp(i_regs->regmap);
2964   temp2=get_reg(i_regs->regmap,FTEMP);
2965   addr=get_reg(i_regs->regmap,AGEN1+(i&1));
2966   assert(addr<0);
2967   offset=imm[i];
2968   reglist|=1<<temp;
2969   if(offset||s<0||c) addr=temp2;
2970   else addr=s;
2971   if(s>=0) {
2972     c=(i_regs->wasconst>>s)&1;
2973     if(c) {
2974       memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE;
2975     }
2976   }
2977   if(!c) {
2978     emit_shlimm(addr,3,temp);
2979     if (dops[i].opcode==0x22||dops[i].opcode==0x26) {
2980       emit_andimm(addr,0xFFFFFFFC,temp2); // LWL/LWR
2981     }else{
2982       emit_andimm(addr,0xFFFFFFF8,temp2); // LDL/LDR
2983     }
2984     jaddr = emit_fastpath_cmp_jump(i, i_regs, temp2,
2985               &offset_reg, &fastio_reg_override);
2986   }
2987   else {
2988     if (ram_offset && memtarget) {
2989       offset_reg = get_ro_reg(i_regs, 0);
2990     }
2991     if (dops[i].opcode==0x22||dops[i].opcode==0x26) {
2992       emit_movimm(((constmap[i][s]+offset)<<3)&24,temp); // LWL/LWR
2993     }else{
2994       emit_movimm(((constmap[i][s]+offset)<<3)&56,temp); // LDL/LDR
2995     }
2996   }
2997   if (dops[i].opcode==0x22||dops[i].opcode==0x26) { // LWL/LWR
2998     if(!c||memtarget) {
2999       int a = temp2;
3000       if (fastio_reg_override >= 0)
3001         a = fastio_reg_override;
3002       do_load_word(a, temp2, offset_reg);
3003       if (fastio_reg_override == HOST_TEMPREG || offset_reg == HOST_TEMPREG)
3004         host_tempreg_release();
3005       if(jaddr) add_stub_r(LOADW_STUB,jaddr,out,i,temp2,i_regs,ccadj_,reglist);
3006     }
3007     else
3008       inline_readstub(LOADW_STUB,i,(constmap[i][s]+offset)&0xFFFFFFFC,i_regs->regmap,FTEMP,ccadj_,reglist);
3009     if(dops[i].rt1) {
3010       assert(tl>=0);
3011       emit_andimm(temp,24,temp);
3012       if (dops[i].opcode==0x22) // LWL
3013         emit_xorimm(temp,24,temp);
3014       host_tempreg_acquire();
3015       emit_movimm(-1,HOST_TEMPREG);
3016       if (dops[i].opcode==0x26) {
3017         emit_shr(temp2,temp,temp2);
3018         emit_bic_lsr(tl,HOST_TEMPREG,temp,tl);
3019       }else{
3020         emit_shl(temp2,temp,temp2);
3021         emit_bic_lsl(tl,HOST_TEMPREG,temp,tl);
3022       }
3023       host_tempreg_release();
3024       emit_or(temp2,tl,tl);
3025     }
3026     //emit_storereg(dops[i].rt1,tl); // DEBUG
3027   }
3028   if (dops[i].opcode==0x1A||dops[i].opcode==0x1B) { // LDL/LDR
3029     assert(0);
3030   }
3031 }
3032 #endif
3033
3034 static void store_assemble(int i, const struct regstat *i_regs, int ccadj_)
3035 {
3036   int s,tl;
3037   int addr,temp;
3038   int offset;
3039   void *jaddr=0;
3040   enum stub_type type=0;
3041   int memtarget=0,c=0;
3042   int agr=AGEN1+(i&1);
3043   int offset_reg = -1;
3044   int fastio_reg_override = -1;
3045   u_int reglist=get_host_reglist(i_regs->regmap);
3046   tl=get_reg(i_regs->regmap,dops[i].rs2);
3047   s=get_reg(i_regs->regmap,dops[i].rs1);
3048   temp=get_reg(i_regs->regmap,agr);
3049   if(temp<0) temp=get_reg_temp(i_regs->regmap);
3050   offset=imm[i];
3051   if(s>=0) {
3052     c=(i_regs->wasconst>>s)&1;
3053     if(c) {
3054       memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE;
3055     }
3056   }
3057   assert(tl>=0);
3058   assert(temp>=0);
3059   if(i_regs->regmap[HOST_CCREG]==CCREG) reglist&=~(1<<HOST_CCREG);
3060   if(offset||s<0||c) addr=temp;
3061   else addr=s;
3062   if (!c) {
3063     jaddr = emit_fastpath_cmp_jump(i, i_regs, addr,
3064               &offset_reg, &fastio_reg_override);
3065   }
3066   else if (ram_offset && memtarget) {
3067     offset_reg = get_ro_reg(i_regs, 0);
3068   }
3069
3070   switch (dops[i].opcode) {
3071   case 0x28: // SB
3072     if(!c||memtarget) {
3073       int a = temp;
3074       if (!c) a = addr;
3075       if (fastio_reg_override >= 0)
3076         a = fastio_reg_override;
3077       do_store_byte(a, tl, offset_reg);
3078     }
3079     type = STOREB_STUB;
3080     break;
3081   case 0x29: // SH
3082     if(!c||memtarget) {
3083       int a = temp;
3084       if (!c) a = addr;
3085       if (fastio_reg_override >= 0)
3086         a = fastio_reg_override;
3087       do_store_hword(a, 0, tl, offset_reg, 1);
3088     }
3089     type = STOREH_STUB;
3090     break;
3091   case 0x2B: // SW
3092     if(!c||memtarget) {
3093       int a = addr;
3094       if (fastio_reg_override >= 0)
3095         a = fastio_reg_override;
3096       do_store_word(a, 0, tl, offset_reg, 1);
3097     }
3098     type = STOREW_STUB;
3099     break;
3100   case 0x3F: // SD
3101   default:
3102     assert(0);
3103   }
3104   if (fastio_reg_override == HOST_TEMPREG || offset_reg == HOST_TEMPREG)
3105     host_tempreg_release();
3106   if(jaddr) {
3107     // PCSX store handlers don't check invcode again
3108     reglist|=1<<addr;
3109     add_stub_r(type,jaddr,out,i,addr,i_regs,ccadj_,reglist);
3110     jaddr=0;
3111   }
3112   if(!(i_regs->waswritten&(1<<dops[i].rs1)) && !HACK_ENABLED(NDHACK_NO_SMC_CHECK)) {
3113     if(!c||memtarget) {
3114       #ifdef DESTRUCTIVE_SHIFT
3115       // The x86 shift operation is 'destructive'; it overwrites the
3116       // source register, so we need to make a copy first and use that.
3117       addr=temp;
3118       #endif
3119       #if defined(HOST_IMM8)
3120       int ir=get_reg(i_regs->regmap,INVCP);
3121       assert(ir>=0);
3122       emit_cmpmem_indexedsr12_reg(ir,addr,1);
3123       #else
3124       emit_cmpmem_indexedsr12_imm(invalid_code,addr,1);
3125       #endif
3126       #if defined(HAVE_CONDITIONAL_CALL) && !defined(DESTRUCTIVE_SHIFT)
3127       emit_callne(invalidate_addr_reg[addr]);
3128       #else
3129       void *jaddr2 = out;
3130       emit_jne(0);
3131       add_stub(INVCODE_STUB,jaddr2,out,reglist|(1<<HOST_CCREG),addr,0,0,0);
3132       #endif
3133     }
3134   }
3135   u_int addr_val=constmap[i][s]+offset;
3136   if(jaddr) {
3137     add_stub_r(type,jaddr,out,i,addr,i_regs,ccadj_,reglist);
3138   } else if(c&&!memtarget) {
3139     inline_writestub(type,i,addr_val,i_regs->regmap,dops[i].rs2,ccadj_,reglist);
3140   }
3141   // basic current block modification detection..
3142   // not looking back as that should be in mips cache already
3143   // (see Spyro2 title->attract mode)
3144   if(c&&start+i*4<addr_val&&addr_val<start+slen*4) {
3145     SysPrintf("write to %08x hits block %08x, pc=%08x\n",addr_val,start,start+i*4);
3146     assert(i_regs->regmap==regs[i].regmap); // not delay slot
3147     if(i_regs->regmap==regs[i].regmap) {
3148       load_all_consts(regs[i].regmap_entry,regs[i].wasdirty,i);
3149       wb_dirtys(regs[i].regmap_entry,regs[i].wasdirty);
3150       emit_movimm(start+i*4+4,0);
3151       emit_writeword(0,&pcaddr);
3152       emit_addimm(HOST_CCREG,2,HOST_CCREG);
3153       emit_far_call(get_addr_ht);
3154       emit_jmpreg(0);
3155     }
3156   }
3157 }
3158
3159 static void storelr_assemble(int i, const struct regstat *i_regs, int ccadj_)
3160 {
3161   int s,tl;
3162   int temp;
3163   int offset;
3164   void *jaddr=0;
3165   void *case1, *case23, *case3;
3166   void *done0, *done1, *done2;
3167   int memtarget=0,c=0;
3168   int agr=AGEN1+(i&1);
3169   int offset_reg = -1;
3170   u_int reglist=get_host_reglist(i_regs->regmap);
3171   tl=get_reg(i_regs->regmap,dops[i].rs2);
3172   s=get_reg(i_regs->regmap,dops[i].rs1);
3173   temp=get_reg(i_regs->regmap,agr);
3174   if(temp<0) temp=get_reg_temp(i_regs->regmap);
3175   offset=imm[i];
3176   if(s>=0) {
3177     c=(i_regs->isconst>>s)&1;
3178     if(c) {
3179       memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE;
3180     }
3181   }
3182   assert(tl>=0);
3183   assert(temp>=0);
3184   if(!c) {
3185     emit_cmpimm(s<0||offset?temp:s,RAM_SIZE);
3186     if(!offset&&s!=temp) emit_mov(s,temp);
3187     jaddr=out;
3188     emit_jno(0);
3189   }
3190   else
3191   {
3192     if(!memtarget||!dops[i].rs1) {
3193       jaddr=out;
3194       emit_jmp(0);
3195     }
3196   }
3197   if (ram_offset)
3198     offset_reg = get_ro_reg(i_regs, 0);
3199
3200   if (dops[i].opcode==0x2C||dops[i].opcode==0x2D) { // SDL/SDR
3201     assert(0);
3202   }
3203
3204   emit_testimm(temp,2);
3205   case23=out;
3206   emit_jne(0);
3207   emit_testimm(temp,1);
3208   case1=out;
3209   emit_jne(0);
3210   // 0
3211   if (dops[i].opcode == 0x2A) { // SWL
3212     // Write msb into least significant byte
3213     if (dops[i].rs2) emit_rorimm(tl, 24, tl);
3214     do_store_byte(temp, tl, offset_reg);
3215     if (dops[i].rs2) emit_rorimm(tl, 8, tl);
3216   }
3217   else if (dops[i].opcode == 0x2E) { // SWR
3218     // Write entire word
3219     do_store_word(temp, 0, tl, offset_reg, 1);
3220   }
3221   done0 = out;
3222   emit_jmp(0);
3223   // 1
3224   set_jump_target(case1, out);
3225   if (dops[i].opcode == 0x2A) { // SWL
3226     // Write two msb into two least significant bytes
3227     if (dops[i].rs2) emit_rorimm(tl, 16, tl);
3228     do_store_hword(temp, -1, tl, offset_reg, 0);
3229     if (dops[i].rs2) emit_rorimm(tl, 16, tl);
3230   }
3231   else if (dops[i].opcode == 0x2E) { // SWR
3232     // Write 3 lsb into three most significant bytes
3233     do_store_byte(temp, tl, offset_reg);
3234     if (dops[i].rs2) emit_rorimm(tl, 8, tl);
3235     do_store_hword(temp, 1, tl, offset_reg, 0);
3236     if (dops[i].rs2) emit_rorimm(tl, 24, tl);
3237   }
3238   done1=out;
3239   emit_jmp(0);
3240   // 2,3
3241   set_jump_target(case23, out);
3242   emit_testimm(temp,1);
3243   case3 = out;
3244   emit_jne(0);
3245   // 2
3246   if (dops[i].opcode==0x2A) { // SWL
3247     // Write 3 msb into three least significant bytes
3248     if (dops[i].rs2) emit_rorimm(tl, 8, tl);
3249     do_store_hword(temp, -2, tl, offset_reg, 1);
3250     if (dops[i].rs2) emit_rorimm(tl, 16, tl);
3251     do_store_byte(temp, tl, offset_reg);
3252     if (dops[i].rs2) emit_rorimm(tl, 8, tl);
3253   }
3254   else if (dops[i].opcode == 0x2E) { // SWR
3255     // Write two lsb into two most significant bytes
3256     do_store_hword(temp, 0, tl, offset_reg, 1);
3257   }
3258   done2 = out;
3259   emit_jmp(0);
3260   // 3
3261   set_jump_target(case3, out);
3262   if (dops[i].opcode == 0x2A) { // SWL
3263     do_store_word(temp, -3, tl, offset_reg, 0);
3264   }
3265   else if (dops[i].opcode == 0x2E) { // SWR
3266     do_store_byte(temp, tl, offset_reg);
3267   }
3268   set_jump_target(done0, out);
3269   set_jump_target(done1, out);
3270   set_jump_target(done2, out);
3271   if (offset_reg == HOST_TEMPREG)
3272     host_tempreg_release();
3273   if(!c||!memtarget)
3274     add_stub_r(STORELR_STUB,jaddr,out,i,temp,i_regs,ccadj_,reglist);
3275   if(!(i_regs->waswritten&(1<<dops[i].rs1)) && !HACK_ENABLED(NDHACK_NO_SMC_CHECK)) {
3276     #if defined(HOST_IMM8)
3277     int ir=get_reg(i_regs->regmap,INVCP);
3278     assert(ir>=0);
3279     emit_cmpmem_indexedsr12_reg(ir,temp,1);
3280     #else
3281     emit_cmpmem_indexedsr12_imm(invalid_code,temp,1);
3282     #endif
3283     #if defined(HAVE_CONDITIONAL_CALL) && !defined(DESTRUCTIVE_SHIFT)
3284     emit_callne(invalidate_addr_reg[temp]);
3285     #else
3286     void *jaddr2 = out;
3287     emit_jne(0);
3288     add_stub(INVCODE_STUB,jaddr2,out,reglist|(1<<HOST_CCREG),temp,0,0,0);
3289     #endif
3290   }
3291 }
3292
3293 static void cop0_assemble(int i, const struct regstat *i_regs, int ccadj_)
3294 {
3295   if(dops[i].opcode2==0) // MFC0
3296   {
3297     signed char t=get_reg(i_regs->regmap,dops[i].rt1);
3298     u_int copr=(source[i]>>11)&0x1f;
3299     //assert(t>=0); // Why does this happen?  OOT is weird
3300     if(t>=0&&dops[i].rt1!=0) {
3301       emit_readword(&reg_cop0[copr],t);
3302     }
3303   }
3304   else if(dops[i].opcode2==4) // MTC0
3305   {
3306     signed char s=get_reg(i_regs->regmap,dops[i].rs1);
3307     char copr=(source[i]>>11)&0x1f;
3308     assert(s>=0);
3309     wb_register(dops[i].rs1,i_regs->regmap,i_regs->dirty);
3310     if(copr==9||copr==11||copr==12||copr==13) {
3311       emit_readword(&last_count,HOST_TEMPREG);
3312       emit_loadreg(CCREG,HOST_CCREG); // TODO: do proper reg alloc
3313       emit_add(HOST_CCREG,HOST_TEMPREG,HOST_CCREG);
3314       emit_addimm(HOST_CCREG,ccadj_,HOST_CCREG);
3315       emit_writeword(HOST_CCREG,&Count);
3316     }
3317     // What a mess.  The status register (12) can enable interrupts,
3318     // so needs a special case to handle a pending interrupt.
3319     // The interrupt must be taken immediately, because a subsequent
3320     // instruction might disable interrupts again.
3321     if(copr==12||copr==13) {
3322       if (is_delayslot) {
3323         // burn cycles to cause cc_interrupt, which will
3324         // reschedule next_interupt. Relies on CCREG from above.
3325         assem_debug("MTC0 DS %d\n", copr);
3326         emit_writeword(HOST_CCREG,&last_count);
3327         emit_movimm(0,HOST_CCREG);
3328         emit_storereg(CCREG,HOST_CCREG);
3329         emit_loadreg(dops[i].rs1,1);
3330         emit_movimm(copr,0);
3331         emit_far_call(pcsx_mtc0_ds);
3332         emit_loadreg(dops[i].rs1,s);
3333         return;
3334       }
3335       emit_movimm(start+i*4+4,HOST_TEMPREG);
3336       emit_writeword(HOST_TEMPREG,&pcaddr);
3337       emit_movimm(0,HOST_TEMPREG);
3338       emit_writeword(HOST_TEMPREG,&pending_exception);
3339     }
3340     if(s==HOST_CCREG)
3341       emit_loadreg(dops[i].rs1,1);
3342     else if(s!=1)
3343       emit_mov(s,1);
3344     emit_movimm(copr,0);
3345     emit_far_call(pcsx_mtc0);
3346     if(copr==9||copr==11||copr==12||copr==13) {
3347       emit_readword(&Count,HOST_CCREG);
3348       emit_readword(&next_interupt,HOST_TEMPREG);
3349       emit_addimm(HOST_CCREG,-ccadj_,HOST_CCREG);
3350       emit_sub(HOST_CCREG,HOST_TEMPREG,HOST_CCREG);
3351       emit_writeword(HOST_TEMPREG,&last_count);
3352       emit_storereg(CCREG,HOST_CCREG);
3353     }
3354     if(copr==12||copr==13) {
3355       assert(!is_delayslot);
3356       emit_readword(&pending_exception,14);
3357       emit_test(14,14);
3358       void *jaddr = out;
3359       emit_jeq(0);
3360       emit_readword(&pcaddr, 0);
3361       emit_addimm(HOST_CCREG,2,HOST_CCREG);
3362       emit_far_call(get_addr_ht);
3363       emit_jmpreg(0);
3364       set_jump_target(jaddr, out);
3365     }
3366     emit_loadreg(dops[i].rs1,s);
3367   }
3368   else
3369   {
3370     assert(dops[i].opcode2==0x10);
3371     //if((source[i]&0x3f)==0x10) // RFE
3372     {
3373       emit_readword(&Status,0);
3374       emit_andimm(0,0x3c,1);
3375       emit_andimm(0,~0xf,0);
3376       emit_orrshr_imm(1,2,0);
3377       emit_writeword(0,&Status);
3378     }
3379   }
3380 }
3381
3382 static void cop1_unusable(int i, const struct regstat *i_regs)
3383 {
3384   // XXX: should just just do the exception instead
3385   //if(!cop1_usable)
3386   {
3387     void *jaddr=out;
3388     emit_jmp(0);
3389     add_stub_r(FP_STUB,jaddr,out,i,0,i_regs,is_delayslot,0);
3390   }
3391 }
3392
3393 static void cop1_assemble(int i, const struct regstat *i_regs)
3394 {
3395   cop1_unusable(i, i_regs);
3396 }
3397
3398 static void c1ls_assemble(int i, const struct regstat *i_regs)
3399 {
3400   cop1_unusable(i, i_regs);
3401 }
3402
3403 // FP_STUB
3404 static void do_cop1stub(int n)
3405 {
3406   literal_pool(256);
3407   assem_debug("do_cop1stub %x\n",start+stubs[n].a*4);
3408   set_jump_target(stubs[n].addr, out);
3409   int i=stubs[n].a;
3410 //  int rs=stubs[n].b;
3411   struct regstat *i_regs=(struct regstat *)stubs[n].c;
3412   int ds=stubs[n].d;
3413   if(!ds) {
3414     load_all_consts(regs[i].regmap_entry,regs[i].wasdirty,i);
3415     //if(i_regs!=&regs[i]) printf("oops: regs[i]=%x i_regs=%x",(int)&regs[i],(int)i_regs);
3416   }
3417   //else {printf("fp exception in delay slot\n");}
3418   wb_dirtys(i_regs->regmap_entry,i_regs->wasdirty);
3419   if(regs[i].regmap_entry[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
3420   emit_movimm(start+(i-ds)*4,EAX); // Get PC
3421   emit_addimm(HOST_CCREG,ccadj[i],HOST_CCREG); // CHECK: is this right?  There should probably be an extra cycle...
3422   emit_far_jump(ds?fp_exception_ds:fp_exception);
3423 }
3424
3425 static int cop2_is_stalling_op(int i, int *cycles)
3426 {
3427   if (dops[i].opcode == 0x3a) { // SWC2
3428     *cycles = 0;
3429     return 1;
3430   }
3431   if (dops[i].itype == COP2 && (dops[i].opcode2 == 0 || dops[i].opcode2 == 2)) { // MFC2/CFC2
3432     *cycles = 0;
3433     return 1;
3434   }
3435   if (dops[i].itype == C2OP) {
3436     *cycles = gte_cycletab[source[i] & 0x3f];
3437     return 1;
3438   }
3439   // ... what about MTC2/CTC2/LWC2?
3440   return 0;
3441 }
3442
3443 #if 0
3444 static void log_gte_stall(int stall, u_int cycle)
3445 {
3446   if ((u_int)stall <= 44)
3447     printf("x    stall %2d %u\n", stall, cycle + last_count);
3448 }
3449
3450 static void emit_log_gte_stall(int i, int stall, u_int reglist)
3451 {
3452   save_regs(reglist);
3453   if (stall > 0)
3454     emit_movimm(stall, 0);
3455   else
3456     emit_mov(HOST_TEMPREG, 0);
3457   emit_addimm(HOST_CCREG, ccadj[i], 1);
3458   emit_far_call(log_gte_stall);
3459   restore_regs(reglist);
3460 }
3461 #endif
3462
3463 static void cop2_do_stall_check(u_int op, int i, const struct regstat *i_regs, u_int reglist)
3464 {
3465   int j = i, other_gte_op_cycles = -1, stall = -MAXBLOCK, cycles_passed;
3466   int rtmp = reglist_find_free(reglist);
3467
3468   if (HACK_ENABLED(NDHACK_NO_STALLS))
3469     return;
3470   if (get_reg(i_regs->regmap, CCREG) != HOST_CCREG) {
3471     // happens occasionally... cc evicted? Don't bother then
3472     //printf("no cc %08x\n", start + i*4);
3473     return;
3474   }
3475   if (!dops[i].bt) {
3476     for (j = i - 1; j >= 0; j--) {
3477       //if (dops[j].is_ds) break;
3478       if (cop2_is_stalling_op(j, &other_gte_op_cycles) || dops[j].bt)
3479         break;
3480       if (j > 0 && ccadj[j - 1] > ccadj[j])
3481         break;
3482     }
3483     j = max(j, 0);
3484   }
3485   cycles_passed = ccadj[i] - ccadj[j];
3486   if (other_gte_op_cycles >= 0)
3487     stall = other_gte_op_cycles - cycles_passed;
3488   else if (cycles_passed >= 44)
3489     stall = 0; // can't stall
3490   if (stall == -MAXBLOCK && rtmp >= 0) {
3491     // unknown stall, do the expensive runtime check
3492     assem_debug("; cop2_do_stall_check\n");
3493 #if 0 // too slow
3494     save_regs(reglist);
3495     emit_movimm(gte_cycletab[op], 0);
3496     emit_addimm(HOST_CCREG, ccadj[i], 1);
3497     emit_far_call(call_gteStall);
3498     restore_regs(reglist);
3499 #else
3500     host_tempreg_acquire();
3501     emit_readword(&psxRegs.gteBusyCycle, rtmp);
3502     emit_addimm(rtmp, -ccadj[i], rtmp);
3503     emit_sub(rtmp, HOST_CCREG, HOST_TEMPREG);
3504     emit_cmpimm(HOST_TEMPREG, 44);
3505     emit_cmovb_reg(rtmp, HOST_CCREG);
3506     //emit_log_gte_stall(i, 0, reglist);
3507     host_tempreg_release();
3508 #endif
3509   }
3510   else if (stall > 0) {
3511     //emit_log_gte_stall(i, stall, reglist);
3512     emit_addimm(HOST_CCREG, stall, HOST_CCREG);
3513   }
3514
3515   // save gteBusyCycle, if needed
3516   if (gte_cycletab[op] == 0)
3517     return;
3518   other_gte_op_cycles = -1;
3519   for (j = i + 1; j < slen; j++) {
3520     if (cop2_is_stalling_op(j, &other_gte_op_cycles))
3521       break;
3522     if (dops[j].is_jump) {
3523       // check ds
3524       if (j + 1 < slen && cop2_is_stalling_op(j + 1, &other_gte_op_cycles))
3525         j++;
3526       break;
3527     }
3528   }
3529   if (other_gte_op_cycles >= 0)
3530     // will handle stall when assembling that op
3531     return;
3532   cycles_passed = ccadj[min(j, slen -1)] - ccadj[i];
3533   if (cycles_passed >= 44)
3534     return;
3535   assem_debug("; save gteBusyCycle\n");
3536   host_tempreg_acquire();
3537 #if 0
3538   emit_readword(&last_count, HOST_TEMPREG);
3539   emit_add(HOST_TEMPREG, HOST_CCREG, HOST_TEMPREG);
3540   emit_addimm(HOST_TEMPREG, ccadj[i], HOST_TEMPREG);
3541   emit_addimm(HOST_TEMPREG, gte_cycletab[op]), HOST_TEMPREG);
3542   emit_writeword(HOST_TEMPREG, &psxRegs.gteBusyCycle);
3543 #else
3544   emit_addimm(HOST_CCREG, ccadj[i] + gte_cycletab[op], HOST_TEMPREG);
3545   emit_writeword(HOST_TEMPREG, &psxRegs.gteBusyCycle);
3546 #endif
3547   host_tempreg_release();
3548 }
3549
3550 static int is_mflohi(int i)
3551 {
3552   return (dops[i].itype == MOV && (dops[i].rs1 == HIREG || dops[i].rs1 == LOREG));
3553 }
3554
3555 static int check_multdiv(int i, int *cycles)
3556 {
3557   if (dops[i].itype != MULTDIV)
3558     return 0;
3559   if (dops[i].opcode2 == 0x18 || dops[i].opcode2 == 0x19) // MULT(U)
3560     *cycles = 11; // approx from 7 11 14
3561   else
3562     *cycles = 37;
3563   return 1;
3564 }
3565
3566 static void multdiv_prepare_stall(int i, const struct regstat *i_regs, int ccadj_)
3567 {
3568   int j, found = 0, c = 0;
3569   if (HACK_ENABLED(NDHACK_NO_STALLS))
3570     return;
3571   if (get_reg(i_regs->regmap, CCREG) != HOST_CCREG) {
3572     // happens occasionally... cc evicted? Don't bother then
3573     return;
3574   }
3575   for (j = i + 1; j < slen; j++) {
3576     if (dops[j].bt)
3577       break;
3578     if ((found = is_mflohi(j)))
3579       break;
3580     if (dops[j].is_jump) {
3581       // check ds
3582       if (j + 1 < slen && (found = is_mflohi(j + 1)))
3583         j++;
3584       break;
3585     }
3586   }
3587   if (found)
3588     // handle all in multdiv_do_stall()
3589     return;
3590   check_multdiv(i, &c);
3591   assert(c > 0);
3592   assem_debug("; muldiv prepare stall %d\n", c);
3593   host_tempreg_acquire();
3594   emit_addimm(HOST_CCREG, ccadj_ + c, HOST_TEMPREG);
3595   emit_writeword(HOST_TEMPREG, &psxRegs.muldivBusyCycle);
3596   host_tempreg_release();
3597 }
3598
3599 static void multdiv_do_stall(int i, const struct regstat *i_regs)
3600 {
3601   int j, known_cycles = 0;
3602   u_int reglist = get_host_reglist(i_regs->regmap);
3603   int rtmp = get_reg_temp(i_regs->regmap);
3604   if (rtmp < 0)
3605     rtmp = reglist_find_free(reglist);
3606   if (HACK_ENABLED(NDHACK_NO_STALLS))
3607     return;
3608   if (get_reg(i_regs->regmap, CCREG) != HOST_CCREG || rtmp < 0) {
3609     // happens occasionally... cc evicted? Don't bother then
3610     //printf("no cc/rtmp %08x\n", start + i*4);
3611     return;
3612   }
3613   if (!dops[i].bt) {
3614     for (j = i - 1; j >= 0; j--) {
3615       if (dops[j].is_ds) break;
3616       if (check_multdiv(j, &known_cycles))
3617         break;
3618       if (is_mflohi(j))
3619         // already handled by this op
3620         return;
3621       if (dops[j].bt || (j > 0 && ccadj[j - 1] > ccadj[j]))
3622         break;
3623     }
3624     j = max(j, 0);
3625   }
3626   if (known_cycles > 0) {
3627     known_cycles -= ccadj[i] - ccadj[j];
3628     assem_debug("; muldiv stall resolved %d\n", known_cycles);
3629     if (known_cycles > 0)
3630       emit_addimm(HOST_CCREG, known_cycles, HOST_CCREG);
3631     return;
3632   }
3633   assem_debug("; muldiv stall unresolved\n");
3634   host_tempreg_acquire();
3635   emit_readword(&psxRegs.muldivBusyCycle, rtmp);
3636   emit_addimm(rtmp, -ccadj[i], rtmp);
3637   emit_sub(rtmp, HOST_CCREG, HOST_TEMPREG);
3638   emit_cmpimm(HOST_TEMPREG, 37);
3639   emit_cmovb_reg(rtmp, HOST_CCREG);
3640   //emit_log_gte_stall(i, 0, reglist);
3641   host_tempreg_release();
3642 }
3643
3644 static void cop2_get_dreg(u_int copr,signed char tl,signed char temp)
3645 {
3646   switch (copr) {
3647     case 1:
3648     case 3:
3649     case 5:
3650     case 8:
3651     case 9:
3652     case 10:
3653     case 11:
3654       emit_readword(&reg_cop2d[copr],tl);
3655       emit_signextend16(tl,tl);
3656       emit_writeword(tl,&reg_cop2d[copr]); // hmh
3657       break;
3658     case 7:
3659     case 16:
3660     case 17:
3661     case 18:
3662     case 19:
3663       emit_readword(&reg_cop2d[copr],tl);
3664       emit_andimm(tl,0xffff,tl);
3665       emit_writeword(tl,&reg_cop2d[copr]);
3666       break;
3667     case 15:
3668       emit_readword(&reg_cop2d[14],tl); // SXY2
3669       emit_writeword(tl,&reg_cop2d[copr]);
3670       break;
3671     case 28:
3672     case 29:
3673       c2op_mfc2_29_assemble(tl,temp);
3674       break;
3675     default:
3676       emit_readword(&reg_cop2d[copr],tl);
3677       break;
3678   }
3679 }
3680
3681 static void cop2_put_dreg(u_int copr,signed char sl,signed char temp)
3682 {
3683   switch (copr) {
3684     case 15:
3685       emit_readword(&reg_cop2d[13],temp);  // SXY1
3686       emit_writeword(sl,&reg_cop2d[copr]);
3687       emit_writeword(temp,&reg_cop2d[12]); // SXY0
3688       emit_readword(&reg_cop2d[14],temp);  // SXY2
3689       emit_writeword(sl,&reg_cop2d[14]);
3690       emit_writeword(temp,&reg_cop2d[13]); // SXY1
3691       break;
3692     case 28:
3693       emit_andimm(sl,0x001f,temp);
3694       emit_shlimm(temp,7,temp);
3695       emit_writeword(temp,&reg_cop2d[9]);
3696       emit_andimm(sl,0x03e0,temp);
3697       emit_shlimm(temp,2,temp);
3698       emit_writeword(temp,&reg_cop2d[10]);
3699       emit_andimm(sl,0x7c00,temp);
3700       emit_shrimm(temp,3,temp);
3701       emit_writeword(temp,&reg_cop2d[11]);
3702       emit_writeword(sl,&reg_cop2d[28]);
3703       break;
3704     case 30:
3705       emit_xorsar_imm(sl,sl,31,temp);
3706 #if defined(HAVE_ARMV5) || defined(__aarch64__)
3707       emit_clz(temp,temp);
3708 #else
3709       emit_movs(temp,HOST_TEMPREG);
3710       emit_movimm(0,temp);
3711       emit_jeq((int)out+4*4);
3712       emit_addpl_imm(temp,1,temp);
3713       emit_lslpls_imm(HOST_TEMPREG,1,HOST_TEMPREG);
3714       emit_jns((int)out-2*4);
3715 #endif
3716       emit_writeword(sl,&reg_cop2d[30]);
3717       emit_writeword(temp,&reg_cop2d[31]);
3718       break;
3719     case 31:
3720       break;
3721     default:
3722       emit_writeword(sl,&reg_cop2d[copr]);
3723       break;
3724   }
3725 }
3726
3727 static void c2ls_assemble(int i, const struct regstat *i_regs, int ccadj_)
3728 {
3729   int s,tl;
3730   int ar;
3731   int offset;
3732   int memtarget=0,c=0;
3733   void *jaddr2=NULL;
3734   enum stub_type type;
3735   int agr=AGEN1+(i&1);
3736   int offset_reg = -1;
3737   int fastio_reg_override = -1;
3738   u_int reglist=get_host_reglist(i_regs->regmap);
3739   u_int copr=(source[i]>>16)&0x1f;
3740   s=get_reg(i_regs->regmap,dops[i].rs1);
3741   tl=get_reg(i_regs->regmap,FTEMP);
3742   offset=imm[i];
3743   assert(dops[i].rs1>0);
3744   assert(tl>=0);
3745
3746   if(i_regs->regmap[HOST_CCREG]==CCREG)
3747     reglist&=~(1<<HOST_CCREG);
3748
3749   // get the address
3750   if (dops[i].opcode==0x3a) { // SWC2
3751     ar=get_reg(i_regs->regmap,agr);
3752     if(ar<0) ar=get_reg_temp(i_regs->regmap);
3753     reglist|=1<<ar;
3754   } else { // LWC2
3755     ar=tl;
3756   }
3757   if(s>=0) c=(i_regs->wasconst>>s)&1;
3758   memtarget=c&&(((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE);
3759   if (!offset&&!c&&s>=0) ar=s;
3760   assert(ar>=0);
3761
3762   cop2_do_stall_check(0, i, i_regs, reglist);
3763
3764   if (dops[i].opcode==0x3a) { // SWC2
3765     cop2_get_dreg(copr,tl,-1);
3766     type=STOREW_STUB;
3767   }
3768   else
3769     type=LOADW_STUB;
3770
3771   if(c&&!memtarget) {
3772     jaddr2=out;
3773     emit_jmp(0); // inline_readstub/inline_writestub?
3774   }
3775   else {
3776     if(!c) {
3777       jaddr2 = emit_fastpath_cmp_jump(i, i_regs, ar,
3778                 &offset_reg, &fastio_reg_override);
3779     }
3780     else if (ram_offset && memtarget) {
3781       offset_reg = get_ro_reg(i_regs, 0);
3782     }
3783     switch (dops[i].opcode) {
3784     case 0x32: { // LWC2
3785       int a = ar;
3786       if (fastio_reg_override >= 0)
3787         a = fastio_reg_override;
3788       do_load_word(a, tl, offset_reg);
3789       break;
3790     }
3791     case 0x3a: { // SWC2
3792       #ifdef DESTRUCTIVE_SHIFT
3793       if(!offset&&!c&&s>=0) emit_mov(s,ar);
3794       #endif
3795       int a = ar;
3796       if (fastio_reg_override >= 0)
3797         a = fastio_reg_override;
3798       do_store_word(a, 0, tl, offset_reg, 1);
3799       break;
3800     }
3801     default:
3802       assert(0);
3803     }
3804   }
3805   if (fastio_reg_override == HOST_TEMPREG || offset_reg == HOST_TEMPREG)
3806     host_tempreg_release();
3807   if(jaddr2)
3808     add_stub_r(type,jaddr2,out,i,ar,i_regs,ccadj_,reglist);
3809   if(dops[i].opcode==0x3a) // SWC2
3810   if(!(i_regs->waswritten&(1<<dops[i].rs1)) && !HACK_ENABLED(NDHACK_NO_SMC_CHECK)) {
3811 #if defined(HOST_IMM8)
3812     int ir=get_reg(i_regs->regmap,INVCP);
3813     assert(ir>=0);
3814     emit_cmpmem_indexedsr12_reg(ir,ar,1);
3815 #else
3816     emit_cmpmem_indexedsr12_imm(invalid_code,ar,1);
3817 #endif
3818     #if defined(HAVE_CONDITIONAL_CALL) && !defined(DESTRUCTIVE_SHIFT)
3819     emit_callne(invalidate_addr_reg[ar]);
3820     #else
3821     void *jaddr3 = out;
3822     emit_jne(0);
3823     add_stub(INVCODE_STUB,jaddr3,out,reglist|(1<<HOST_CCREG),ar,0,0,0);
3824     #endif
3825   }
3826   if (dops[i].opcode==0x32) { // LWC2
3827     host_tempreg_acquire();
3828     cop2_put_dreg(copr,tl,HOST_TEMPREG);
3829     host_tempreg_release();
3830   }
3831 }
3832
3833 static void cop2_assemble(int i, const struct regstat *i_regs)
3834 {
3835   u_int copr = (source[i]>>11) & 0x1f;
3836   signed char temp = get_reg_temp(i_regs->regmap);
3837
3838   if (!HACK_ENABLED(NDHACK_NO_STALLS)) {
3839     u_int reglist = reglist_exclude(get_host_reglist(i_regs->regmap), temp, -1);
3840     if (dops[i].opcode2 == 0 || dops[i].opcode2 == 2) { // MFC2/CFC2
3841       signed char tl = get_reg(i_regs->regmap, dops[i].rt1);
3842       reglist = reglist_exclude(reglist, tl, -1);
3843     }
3844     cop2_do_stall_check(0, i, i_regs, reglist);
3845   }
3846   if (dops[i].opcode2==0) { // MFC2
3847     signed char tl=get_reg(i_regs->regmap,dops[i].rt1);
3848     if(tl>=0&&dops[i].rt1!=0)
3849       cop2_get_dreg(copr,tl,temp);
3850   }
3851   else if (dops[i].opcode2==4) { // MTC2
3852     signed char sl=get_reg(i_regs->regmap,dops[i].rs1);
3853     cop2_put_dreg(copr,sl,temp);
3854   }
3855   else if (dops[i].opcode2==2) // CFC2
3856   {
3857     signed char tl=get_reg(i_regs->regmap,dops[i].rt1);
3858     if(tl>=0&&dops[i].rt1!=0)
3859       emit_readword(&reg_cop2c[copr],tl);
3860   }
3861   else if (dops[i].opcode2==6) // CTC2
3862   {
3863     signed char sl=get_reg(i_regs->regmap,dops[i].rs1);
3864     switch(copr) {
3865       case 4:
3866       case 12:
3867       case 20:
3868       case 26:
3869       case 27:
3870       case 29:
3871       case 30:
3872         emit_signextend16(sl,temp);
3873         break;
3874       case 31:
3875         c2op_ctc2_31_assemble(sl,temp);
3876         break;
3877       default:
3878         temp=sl;
3879         break;
3880     }
3881     emit_writeword(temp,&reg_cop2c[copr]);
3882     assert(sl>=0);
3883   }
3884 }
3885
3886 static void do_unalignedwritestub(int n)
3887 {
3888   assem_debug("do_unalignedwritestub %x\n",start+stubs[n].a*4);
3889   literal_pool(256);
3890   set_jump_target(stubs[n].addr, out);
3891
3892   int i=stubs[n].a;
3893   struct regstat *i_regs=(struct regstat *)stubs[n].c;
3894   int addr=stubs[n].b;
3895   u_int reglist=stubs[n].e;
3896   signed char *i_regmap=i_regs->regmap;
3897   int temp2=get_reg(i_regmap,FTEMP);
3898   int rt;
3899   rt=get_reg(i_regmap,dops[i].rs2);
3900   assert(rt>=0);
3901   assert(addr>=0);
3902   assert(dops[i].opcode==0x2a||dops[i].opcode==0x2e); // SWL/SWR only implemented
3903   reglist|=(1<<addr);
3904   reglist&=~(1<<temp2);
3905
3906   // don't bother with it and call write handler
3907   save_regs(reglist);
3908   pass_args(addr,rt);
3909   int cc=get_reg(i_regmap,CCREG);
3910   if(cc<0)
3911     emit_loadreg(CCREG,2);
3912   emit_addimm(cc<0?2:cc,(int)stubs[n].d+1,2);
3913   emit_far_call((dops[i].opcode==0x2a?jump_handle_swl:jump_handle_swr));
3914   emit_addimm(0,-((int)stubs[n].d+1),cc<0?2:cc);
3915   if(cc<0)
3916     emit_storereg(CCREG,2);
3917   restore_regs(reglist);
3918   emit_jmp(stubs[n].retaddr); // return address
3919 }
3920
3921 #ifndef multdiv_assemble
3922 void multdiv_assemble(int i,struct regstat *i_regs)
3923 {
3924   printf("Need multdiv_assemble for this architecture.\n");
3925   abort();
3926 }
3927 #endif
3928
3929 static void mov_assemble(int i, const struct regstat *i_regs)
3930 {
3931   //if(dops[i].opcode2==0x10||dops[i].opcode2==0x12) { // MFHI/MFLO
3932   //if(dops[i].opcode2==0x11||dops[i].opcode2==0x13) { // MTHI/MTLO
3933   if(dops[i].rt1) {
3934     signed char sl,tl;
3935     tl=get_reg(i_regs->regmap,dops[i].rt1);
3936     //assert(tl>=0);
3937     if(tl>=0) {
3938       sl=get_reg(i_regs->regmap,dops[i].rs1);
3939       if(sl>=0) emit_mov(sl,tl);
3940       else emit_loadreg(dops[i].rs1,tl);
3941     }
3942   }
3943   if (dops[i].rs1 == HIREG || dops[i].rs1 == LOREG) // MFHI/MFLO
3944     multdiv_do_stall(i, i_regs);
3945 }
3946
3947 // call interpreter, exception handler, things that change pc/regs/cycles ...
3948 static void call_c_cpu_handler(int i, const struct regstat *i_regs, int ccadj_, u_int pc, void *func)
3949 {
3950   signed char ccreg=get_reg(i_regs->regmap,CCREG);
3951   assert(ccreg==HOST_CCREG);
3952   assert(!is_delayslot);
3953   (void)ccreg;
3954
3955   emit_movimm(pc,3); // Get PC
3956   emit_readword(&last_count,2);
3957   emit_writeword(3,&psxRegs.pc);
3958   emit_addimm(HOST_CCREG,ccadj_,HOST_CCREG);
3959   emit_add(2,HOST_CCREG,2);
3960   emit_writeword(2,&psxRegs.cycle);
3961   emit_far_call(func);
3962   emit_far_jump(jump_to_new_pc);
3963 }
3964
3965 static void syscall_assemble(int i, const struct regstat *i_regs, int ccadj_)
3966 {
3967   // 'break' tends to be littered around to catch things like
3968   // division by 0 and is almost never executed, so don't emit much code here
3969   void *func = (dops[i].opcode2 == 0x0C)
3970     ? (is_delayslot ? jump_syscall_ds : jump_syscall)
3971     : (is_delayslot ? jump_break_ds : jump_break);
3972   assert(get_reg(i_regs->regmap, CCREG) == HOST_CCREG);
3973   emit_movimm(start + i*4, 2); // pc
3974   emit_addimm(HOST_CCREG, ccadj_ + CLOCK_ADJUST(1), HOST_CCREG);
3975   emit_far_jump(func);
3976 }
3977
3978 static void hlecall_assemble(int i, const struct regstat *i_regs, int ccadj_)
3979 {
3980   void *hlefunc = psxNULL;
3981   uint32_t hleCode = source[i] & 0x03ffffff;
3982   if (hleCode < ARRAY_SIZE(psxHLEt))
3983     hlefunc = psxHLEt[hleCode];
3984
3985   call_c_cpu_handler(i, i_regs, ccadj_, start + i*4+4, hlefunc);
3986 }
3987
3988 static void intcall_assemble(int i, const struct regstat *i_regs, int ccadj_)
3989 {
3990   call_c_cpu_handler(i, i_regs, ccadj_, start + i*4, execI);
3991 }
3992
3993 static void speculate_mov(int rs,int rt)
3994 {
3995   if(rt!=0) {
3996     smrv_strong_next|=1<<rt;
3997     smrv[rt]=smrv[rs];
3998   }
3999 }
4000
4001 static void speculate_mov_weak(int rs,int rt)
4002 {
4003   if(rt!=0) {
4004     smrv_weak_next|=1<<rt;
4005     smrv[rt]=smrv[rs];
4006   }
4007 }
4008
4009 static void speculate_register_values(int i)
4010 {
4011   if(i==0) {
4012     memcpy(smrv,psxRegs.GPR.r,sizeof(smrv));
4013     // gp,sp are likely to stay the same throughout the block
4014     smrv_strong_next=(1<<28)|(1<<29)|(1<<30);
4015     smrv_weak_next=~smrv_strong_next;
4016     //printf(" llr %08x\n", smrv[4]);
4017   }
4018   smrv_strong=smrv_strong_next;
4019   smrv_weak=smrv_weak_next;
4020   switch(dops[i].itype) {
4021     case ALU:
4022       if     ((smrv_strong>>dops[i].rs1)&1) speculate_mov(dops[i].rs1,dops[i].rt1);
4023       else if((smrv_strong>>dops[i].rs2)&1) speculate_mov(dops[i].rs2,dops[i].rt1);
4024       else if((smrv_weak>>dops[i].rs1)&1) speculate_mov_weak(dops[i].rs1,dops[i].rt1);
4025       else if((smrv_weak>>dops[i].rs2)&1) speculate_mov_weak(dops[i].rs2,dops[i].rt1);
4026       else {
4027         smrv_strong_next&=~(1<<dops[i].rt1);
4028         smrv_weak_next&=~(1<<dops[i].rt1);
4029       }
4030       break;
4031     case SHIFTIMM:
4032       smrv_strong_next&=~(1<<dops[i].rt1);
4033       smrv_weak_next&=~(1<<dops[i].rt1);
4034       // fallthrough
4035     case IMM16:
4036       if(dops[i].rt1&&is_const(&regs[i],dops[i].rt1)) {
4037         int value,hr=get_reg(regs[i].regmap,dops[i].rt1);
4038         if(hr>=0) {
4039           if(get_final_value(hr,i,&value))
4040                smrv[dops[i].rt1]=value;
4041           else smrv[dops[i].rt1]=constmap[i][hr];
4042           smrv_strong_next|=1<<dops[i].rt1;
4043         }
4044       }
4045       else {
4046         if     ((smrv_strong>>dops[i].rs1)&1) speculate_mov(dops[i].rs1,dops[i].rt1);
4047         else if((smrv_weak>>dops[i].rs1)&1) speculate_mov_weak(dops[i].rs1,dops[i].rt1);
4048       }
4049       break;
4050     case LOAD:
4051       if(start<0x2000&&(dops[i].rt1==26||(smrv[dops[i].rt1]>>24)==0xa0)) {
4052         // special case for BIOS
4053         smrv[dops[i].rt1]=0xa0000000;
4054         smrv_strong_next|=1<<dops[i].rt1;
4055         break;
4056       }
4057       // fallthrough
4058     case SHIFT:
4059     case LOADLR:
4060     case MOV:
4061       smrv_strong_next&=~(1<<dops[i].rt1);
4062       smrv_weak_next&=~(1<<dops[i].rt1);
4063       break;
4064     case COP0:
4065     case COP2:
4066       if(dops[i].opcode2==0||dops[i].opcode2==2) { // MFC/CFC
4067         smrv_strong_next&=~(1<<dops[i].rt1);
4068         smrv_weak_next&=~(1<<dops[i].rt1);
4069       }
4070       break;
4071     case C2LS:
4072       if (dops[i].opcode==0x32) { // LWC2
4073         smrv_strong_next&=~(1<<dops[i].rt1);
4074         smrv_weak_next&=~(1<<dops[i].rt1);
4075       }
4076       break;
4077   }
4078 #if 0
4079   int r=4;
4080   printf("x %08x %08x %d %d c %08x %08x\n",smrv[r],start+i*4,
4081     ((smrv_strong>>r)&1),(smrv_weak>>r)&1,regs[i].isconst,regs[i].wasconst);
4082 #endif
4083 }
4084
4085 static void ujump_assemble(int i, const struct regstat *i_regs);
4086 static void rjump_assemble(int i, const struct regstat *i_regs);
4087 static void cjump_assemble(int i, const struct regstat *i_regs);
4088 static void sjump_assemble(int i, const struct regstat *i_regs);
4089 static void pagespan_assemble(int i, const struct regstat *i_regs);
4090
4091 static int assemble(int i, const struct regstat *i_regs, int ccadj_)
4092 {
4093   int ds = 0;
4094   switch (dops[i].itype) {
4095     case ALU:
4096       alu_assemble(i, i_regs);
4097       break;
4098     case IMM16:
4099       imm16_assemble(i, i_regs);
4100       break;
4101     case SHIFT:
4102       shift_assemble(i, i_regs);
4103       break;
4104     case SHIFTIMM:
4105       shiftimm_assemble(i, i_regs);
4106       break;
4107     case LOAD:
4108       load_assemble(i, i_regs, ccadj_);
4109       break;
4110     case LOADLR:
4111       loadlr_assemble(i, i_regs, ccadj_);
4112       break;
4113     case STORE:
4114       store_assemble(i, i_regs, ccadj_);
4115       break;
4116     case STORELR:
4117       storelr_assemble(i, i_regs, ccadj_);
4118       break;
4119     case COP0:
4120       cop0_assemble(i, i_regs, ccadj_);
4121       break;
4122     case COP1:
4123       cop1_assemble(i, i_regs);
4124       break;
4125     case C1LS:
4126       c1ls_assemble(i, i_regs);
4127       break;
4128     case COP2:
4129       cop2_assemble(i, i_regs);
4130       break;
4131     case C2LS:
4132       c2ls_assemble(i, i_regs, ccadj_);
4133       break;
4134     case C2OP:
4135       c2op_assemble(i, i_regs);
4136       break;
4137     case MULTDIV:
4138       multdiv_assemble(i, i_regs);
4139       multdiv_prepare_stall(i, i_regs, ccadj_);
4140       break;
4141     case MOV:
4142       mov_assemble(i, i_regs);
4143       break;
4144     case SYSCALL:
4145       syscall_assemble(i, i_regs, ccadj_);
4146       break;
4147     case HLECALL:
4148       hlecall_assemble(i, i_regs, ccadj_);
4149       break;
4150     case INTCALL:
4151       intcall_assemble(i, i_regs, ccadj_);
4152       break;
4153     case UJUMP:
4154       ujump_assemble(i, i_regs);
4155       ds = 1;
4156       break;
4157     case RJUMP:
4158       rjump_assemble(i, i_regs);
4159       ds = 1;
4160       break;
4161     case CJUMP:
4162       cjump_assemble(i, i_regs);
4163       ds = 1;
4164       break;
4165     case SJUMP:
4166       sjump_assemble(i, i_regs);
4167       ds = 1;
4168       break;
4169     case SPAN:
4170       pagespan_assemble(i, i_regs);
4171       break;
4172     case NOP:
4173     case OTHER:
4174     case NI:
4175       // not handled, just skip
4176       break;
4177     default:
4178       assert(0);
4179   }
4180   return ds;
4181 }
4182
4183 static void ds_assemble(int i, const struct regstat *i_regs)
4184 {
4185   speculate_register_values(i);
4186   is_delayslot = 1;
4187   switch (dops[i].itype) {
4188     case SYSCALL:
4189     case HLECALL:
4190     case INTCALL:
4191     case SPAN:
4192     case UJUMP:
4193     case RJUMP:
4194     case CJUMP:
4195     case SJUMP:
4196       SysPrintf("Jump in the delay slot.  This is probably a bug.\n");
4197       break;
4198     default:
4199       assemble(i, i_regs, ccadj[i]);
4200   }
4201   is_delayslot = 0;
4202 }
4203
4204 // Is the branch target a valid internal jump?
4205 static int internal_branch(int addr)
4206 {
4207   if(addr&1) return 0; // Indirect (register) jump
4208   if(addr>=start && addr<start+slen*4-4)
4209   {
4210     return 1;
4211   }
4212   return 0;
4213 }
4214
4215 static void wb_invalidate(signed char pre[],signed char entry[],uint64_t dirty,uint64_t u)
4216 {
4217   int hr;
4218   for(hr=0;hr<HOST_REGS;hr++) {
4219     if(hr!=EXCLUDE_REG) {
4220       if(pre[hr]!=entry[hr]) {
4221         if(pre[hr]>=0) {
4222           if((dirty>>hr)&1) {
4223             if(get_reg(entry,pre[hr])<0) {
4224               assert(pre[hr]<64);
4225               if(!((u>>pre[hr])&1))
4226                 emit_storereg(pre[hr],hr);
4227             }
4228           }
4229         }
4230       }
4231     }
4232   }
4233   // Move from one register to another (no writeback)
4234   for(hr=0;hr<HOST_REGS;hr++) {
4235     if(hr!=EXCLUDE_REG) {
4236       if(pre[hr]!=entry[hr]) {
4237         if(pre[hr]>=0&&pre[hr]<TEMPREG) {
4238           int nr;
4239           if((nr=get_reg(entry,pre[hr]))>=0) {
4240             emit_mov(hr,nr);
4241           }
4242         }
4243       }
4244     }
4245   }
4246 }
4247
4248 // Load the specified registers
4249 // This only loads the registers given as arguments because
4250 // we don't want to load things that will be overwritten
4251 static void load_regs(signed char entry[],signed char regmap[],int rs1,int rs2)
4252 {
4253   int hr;
4254   // Load 32-bit regs
4255   for(hr=0;hr<HOST_REGS;hr++) {
4256     if(hr!=EXCLUDE_REG&&regmap[hr]>=0) {
4257       if(entry[hr]!=regmap[hr]) {
4258         if(regmap[hr]==rs1||regmap[hr]==rs2)
4259         {
4260           if(regmap[hr]==0) {
4261             emit_zeroreg(hr);
4262           }
4263           else
4264           {
4265             emit_loadreg(regmap[hr],hr);
4266           }
4267         }
4268       }
4269     }
4270   }
4271 }
4272
4273 // Load registers prior to the start of a loop
4274 // so that they are not loaded within the loop
4275 static void loop_preload(signed char pre[],signed char entry[])
4276 {
4277   int hr;
4278   for(hr=0;hr<HOST_REGS;hr++) {
4279     if(hr!=EXCLUDE_REG) {
4280       if(pre[hr]!=entry[hr]) {
4281         if(entry[hr]>=0) {
4282           if(get_reg(pre,entry[hr])<0) {
4283             assem_debug("loop preload:\n");
4284             //printf("loop preload: %d\n",hr);
4285             if(entry[hr]==0) {
4286               emit_zeroreg(hr);
4287             }
4288             else if(entry[hr]<TEMPREG)
4289             {
4290               emit_loadreg(entry[hr],hr);
4291             }
4292             else if(entry[hr]-64<TEMPREG)
4293             {
4294               emit_loadreg(entry[hr],hr);
4295             }
4296           }
4297         }
4298       }
4299     }
4300   }
4301 }
4302
4303 // Generate address for load/store instruction
4304 // goes to AGEN for writes, FTEMP for LOADLR and cop1/2 loads
4305 void address_generation(int i, const struct regstat *i_regs, signed char entry[])
4306 {
4307   if (dops[i].is_load || dops[i].is_store) {
4308     int ra=-1;
4309     int agr=AGEN1+(i&1);
4310     if(dops[i].itype==LOAD) {
4311       ra=get_reg(i_regs->regmap,dops[i].rt1);
4312       if(ra<0) ra=get_reg_temp(i_regs->regmap);
4313       assert(ra>=0);
4314     }
4315     if(dops[i].itype==LOADLR) {
4316       ra=get_reg(i_regs->regmap,FTEMP);
4317     }
4318     if(dops[i].itype==STORE||dops[i].itype==STORELR) {
4319       ra=get_reg(i_regs->regmap,agr);
4320       if(ra<0) ra=get_reg_temp(i_regs->regmap);
4321     }
4322     if(dops[i].itype==C2LS) {
4323       if ((dops[i].opcode&0x3b)==0x31||(dops[i].opcode&0x3b)==0x32) // LWC1/LDC1/LWC2/LDC2
4324         ra=get_reg(i_regs->regmap,FTEMP);
4325       else { // SWC1/SDC1/SWC2/SDC2
4326         ra=get_reg(i_regs->regmap,agr);
4327         if(ra<0) ra=get_reg_temp(i_regs->regmap);
4328       }
4329     }
4330     int rs=get_reg(i_regs->regmap,dops[i].rs1);
4331     if(ra>=0) {
4332       int offset=imm[i];
4333       int c=(i_regs->wasconst>>rs)&1;
4334       if(dops[i].rs1==0) {
4335         // Using r0 as a base address
4336         if(!entry||entry[ra]!=agr) {
4337           if (dops[i].opcode==0x22||dops[i].opcode==0x26) {
4338             emit_movimm(offset&0xFFFFFFFC,ra); // LWL/LWR
4339           }else if (dops[i].opcode==0x1a||dops[i].opcode==0x1b) {
4340             emit_movimm(offset&0xFFFFFFF8,ra); // LDL/LDR
4341           }else{
4342             emit_movimm(offset,ra);
4343           }
4344         } // else did it in the previous cycle
4345       }
4346       else if(rs<0) {
4347         if(!entry||entry[ra]!=dops[i].rs1)
4348           emit_loadreg(dops[i].rs1,ra);
4349         //if(!entry||entry[ra]!=dops[i].rs1)
4350         //  printf("poor load scheduling!\n");
4351       }
4352       else if(c) {
4353         if(dops[i].rs1!=dops[i].rt1||dops[i].itype!=LOAD) {
4354           if(!entry||entry[ra]!=agr) {
4355             if (dops[i].opcode==0x22||dops[i].opcode==0x26) {
4356               emit_movimm((constmap[i][rs]+offset)&0xFFFFFFFC,ra); // LWL/LWR
4357             }else if (dops[i].opcode==0x1a||dops[i].opcode==0x1b) {
4358               emit_movimm((constmap[i][rs]+offset)&0xFFFFFFF8,ra); // LDL/LDR
4359             }else{
4360               emit_movimm(constmap[i][rs]+offset,ra);
4361               regs[i].loadedconst|=1<<ra;
4362             }
4363           } // else did it in the previous cycle
4364         } // else load_consts already did it
4365       }
4366       if(offset&&!c&&dops[i].rs1) {
4367         if(rs>=0) {
4368           emit_addimm(rs,offset,ra);
4369         }else{
4370           emit_addimm(ra,offset,ra);
4371         }
4372       }
4373     }
4374   }
4375   // Preload constants for next instruction
4376   if (dops[i+1].is_load || dops[i+1].is_store) {
4377     int agr,ra;
4378     // Actual address
4379     agr=AGEN1+((i+1)&1);
4380     ra=get_reg(i_regs->regmap,agr);
4381     if(ra>=0) {
4382       int rs=get_reg(regs[i+1].regmap,dops[i+1].rs1);
4383       int offset=imm[i+1];
4384       int c=(regs[i+1].wasconst>>rs)&1;
4385       if(c&&(dops[i+1].rs1!=dops[i+1].rt1||dops[i+1].itype!=LOAD)) {
4386         if (dops[i+1].opcode==0x22||dops[i+1].opcode==0x26) {
4387           emit_movimm((constmap[i+1][rs]+offset)&0xFFFFFFFC,ra); // LWL/LWR
4388         }else if (dops[i+1].opcode==0x1a||dops[i+1].opcode==0x1b) {
4389           emit_movimm((constmap[i+1][rs]+offset)&0xFFFFFFF8,ra); // LDL/LDR
4390         }else{
4391           emit_movimm(constmap[i+1][rs]+offset,ra);
4392           regs[i+1].loadedconst|=1<<ra;
4393         }
4394       }
4395       else if(dops[i+1].rs1==0) {
4396         // Using r0 as a base address
4397         if (dops[i+1].opcode==0x22||dops[i+1].opcode==0x26) {
4398           emit_movimm(offset&0xFFFFFFFC,ra); // LWL/LWR
4399         }else if (dops[i+1].opcode==0x1a||dops[i+1].opcode==0x1b) {
4400           emit_movimm(offset&0xFFFFFFF8,ra); // LDL/LDR
4401         }else{
4402           emit_movimm(offset,ra);
4403         }
4404       }
4405     }
4406   }
4407 }
4408
4409 static int get_final_value(int hr, int i, int *value)
4410 {
4411   int reg=regs[i].regmap[hr];
4412   while(i<slen-1) {
4413     if(regs[i+1].regmap[hr]!=reg) break;
4414     if(!((regs[i+1].isconst>>hr)&1)) break;
4415     if(dops[i+1].bt) break;
4416     i++;
4417   }
4418   if(i<slen-1) {
4419     if (dops[i].is_jump) {
4420       *value=constmap[i][hr];
4421       return 1;
4422     }
4423     if(!dops[i+1].bt) {
4424       if (dops[i+1].is_jump) {
4425         // Load in delay slot, out-of-order execution
4426         if(dops[i+2].itype==LOAD&&dops[i+2].rs1==reg&&dops[i+2].rt1==reg&&((regs[i+1].wasconst>>hr)&1))
4427         {
4428           // Precompute load address
4429           *value=constmap[i][hr]+imm[i+2];
4430           return 1;
4431         }
4432       }
4433       if(dops[i+1].itype==LOAD&&dops[i+1].rs1==reg&&dops[i+1].rt1==reg)
4434       {
4435         // Precompute load address
4436         *value=constmap[i][hr]+imm[i+1];
4437         //printf("c=%x imm=%lx\n",(long)constmap[i][hr],imm[i+1]);
4438         return 1;
4439       }
4440     }
4441   }
4442   *value=constmap[i][hr];
4443   //printf("c=%lx\n",(long)constmap[i][hr]);
4444   if(i==slen-1) return 1;
4445   assert(reg < 64);
4446   return !((unneeded_reg[i+1]>>reg)&1);
4447 }
4448
4449 // Load registers with known constants
4450 static void load_consts(signed char pre[],signed char regmap[],int i)
4451 {
4452   int hr,hr2;
4453   // propagate loaded constant flags
4454   if(i==0||dops[i].bt)
4455     regs[i].loadedconst=0;
4456   else {
4457     for(hr=0;hr<HOST_REGS;hr++) {
4458       if(hr!=EXCLUDE_REG&&regmap[hr]>=0&&((regs[i-1].isconst>>hr)&1)&&pre[hr]==regmap[hr]
4459          &&regmap[hr]==regs[i-1].regmap[hr]&&((regs[i-1].loadedconst>>hr)&1))
4460       {
4461         regs[i].loadedconst|=1<<hr;
4462       }
4463     }
4464   }
4465   // Load 32-bit regs
4466   for(hr=0;hr<HOST_REGS;hr++) {
4467     if(hr!=EXCLUDE_REG&&regmap[hr]>=0) {
4468       //if(entry[hr]!=regmap[hr]) {
4469       if(!((regs[i].loadedconst>>hr)&1)) {
4470         assert(regmap[hr]<64);
4471         if(((regs[i].isconst>>hr)&1)&&regmap[hr]>0) {
4472           int value,similar=0;
4473           if(get_final_value(hr,i,&value)) {
4474             // see if some other register has similar value
4475             for(hr2=0;hr2<HOST_REGS;hr2++) {
4476               if(hr2!=EXCLUDE_REG&&((regs[i].loadedconst>>hr2)&1)) {
4477                 if(is_similar_value(value,constmap[i][hr2])) {
4478                   similar=1;
4479                   break;
4480                 }
4481               }
4482             }
4483             if(similar) {
4484               int value2;
4485               if(get_final_value(hr2,i,&value2)) // is this needed?
4486                 emit_movimm_from(value2,hr2,value,hr);
4487               else
4488                 emit_movimm(value,hr);
4489             }
4490             else if(value==0) {
4491               emit_zeroreg(hr);
4492             }
4493             else {
4494               emit_movimm(value,hr);
4495             }
4496           }
4497           regs[i].loadedconst|=1<<hr;
4498         }
4499       }
4500     }
4501   }
4502 }
4503
4504 static void load_all_consts(const signed char regmap[], u_int dirty, int i)
4505 {
4506   int hr;
4507   // Load 32-bit regs
4508   for(hr=0;hr<HOST_REGS;hr++) {
4509     if(hr!=EXCLUDE_REG&&regmap[hr]>=0&&((dirty>>hr)&1)) {
4510       assert(regmap[hr] < 64);
4511       if(((regs[i].isconst>>hr)&1)&&regmap[hr]>0) {
4512         int value=constmap[i][hr];
4513         if(value==0) {
4514           emit_zeroreg(hr);
4515         }
4516         else {
4517           emit_movimm(value,hr);
4518         }
4519       }
4520     }
4521   }
4522 }
4523
4524 // Write out all dirty registers (except cycle count)
4525 static void wb_dirtys(const signed char i_regmap[], uint64_t i_dirty)
4526 {
4527   int hr;
4528   for(hr=0;hr<HOST_REGS;hr++) {
4529     if(hr!=EXCLUDE_REG) {
4530       if(i_regmap[hr]>0) {
4531         if(i_regmap[hr]!=CCREG) {
4532           if((i_dirty>>hr)&1) {
4533             assert(i_regmap[hr]<64);
4534             emit_storereg(i_regmap[hr],hr);
4535           }
4536         }
4537       }
4538     }
4539   }
4540 }
4541
4542 // Write out dirty registers that we need to reload (pair with load_needed_regs)
4543 // This writes the registers not written by store_regs_bt
4544 static void wb_needed_dirtys(const signed char i_regmap[], uint64_t i_dirty, int addr)
4545 {
4546   int hr;
4547   int t=(addr-start)>>2;
4548   for(hr=0;hr<HOST_REGS;hr++) {
4549     if(hr!=EXCLUDE_REG) {
4550       if(i_regmap[hr]>0) {
4551         if(i_regmap[hr]!=CCREG) {
4552           if(i_regmap[hr]==regs[t].regmap_entry[hr] && ((regs[t].dirty>>hr)&1)) {
4553             if((i_dirty>>hr)&1) {
4554               assert(i_regmap[hr]<64);
4555               emit_storereg(i_regmap[hr],hr);
4556             }
4557           }
4558         }
4559       }
4560     }
4561   }
4562 }
4563
4564 // Load all registers (except cycle count)
4565 static void load_all_regs(const signed char i_regmap[])
4566 {
4567   int hr;
4568   for(hr=0;hr<HOST_REGS;hr++) {
4569     if(hr!=EXCLUDE_REG) {
4570       if(i_regmap[hr]==0) {
4571         emit_zeroreg(hr);
4572       }
4573       else
4574       if(i_regmap[hr]>0 && i_regmap[hr]<TEMPREG && i_regmap[hr]!=CCREG)
4575       {
4576         emit_loadreg(i_regmap[hr],hr);
4577       }
4578     }
4579   }
4580 }
4581
4582 // Load all current registers also needed by next instruction
4583 static void load_needed_regs(const signed char i_regmap[], const signed char next_regmap[])
4584 {
4585   int hr;
4586   for(hr=0;hr<HOST_REGS;hr++) {
4587     if(hr!=EXCLUDE_REG) {
4588       if(get_reg(next_regmap,i_regmap[hr])>=0) {
4589         if(i_regmap[hr]==0) {
4590           emit_zeroreg(hr);
4591         }
4592         else
4593         if(i_regmap[hr]>0 && i_regmap[hr]<TEMPREG && i_regmap[hr]!=CCREG)
4594         {
4595           emit_loadreg(i_regmap[hr],hr);
4596         }
4597       }
4598     }
4599   }
4600 }
4601
4602 // Load all regs, storing cycle count if necessary
4603 static void load_regs_entry(int t)
4604 {
4605   int hr;
4606   if(dops[t].is_ds) emit_addimm(HOST_CCREG,CLOCK_ADJUST(1),HOST_CCREG);
4607   else if(ccadj[t]) emit_addimm(HOST_CCREG,-ccadj[t],HOST_CCREG);
4608   if(regs[t].regmap_entry[HOST_CCREG]!=CCREG) {
4609     emit_storereg(CCREG,HOST_CCREG);
4610   }
4611   // Load 32-bit regs
4612   for(hr=0;hr<HOST_REGS;hr++) {
4613     if(regs[t].regmap_entry[hr]>=0&&regs[t].regmap_entry[hr]<TEMPREG) {
4614       if(regs[t].regmap_entry[hr]==0) {
4615         emit_zeroreg(hr);
4616       }
4617       else if(regs[t].regmap_entry[hr]!=CCREG)
4618       {
4619         emit_loadreg(regs[t].regmap_entry[hr],hr);
4620       }
4621     }
4622   }
4623 }
4624
4625 // Store dirty registers prior to branch
4626 void store_regs_bt(signed char i_regmap[],uint64_t i_dirty,int addr)
4627 {
4628   if(internal_branch(addr))
4629   {
4630     int t=(addr-start)>>2;
4631     int hr;
4632     for(hr=0;hr<HOST_REGS;hr++) {
4633       if(hr!=EXCLUDE_REG) {
4634         if(i_regmap[hr]>0 && i_regmap[hr]!=CCREG) {
4635           if(i_regmap[hr]!=regs[t].regmap_entry[hr] || !((regs[t].dirty>>hr)&1)) {
4636             if((i_dirty>>hr)&1) {
4637               assert(i_regmap[hr]<64);
4638               if(!((unneeded_reg[t]>>i_regmap[hr])&1))
4639                 emit_storereg(i_regmap[hr],hr);
4640             }
4641           }
4642         }
4643       }
4644     }
4645   }
4646   else
4647   {
4648     // Branch out of this block, write out all dirty regs
4649     wb_dirtys(i_regmap,i_dirty);
4650   }
4651 }
4652
4653 // Load all needed registers for branch target
4654 static void load_regs_bt(signed char i_regmap[],uint64_t i_dirty,int addr)
4655 {
4656   //if(addr>=start && addr<(start+slen*4))
4657   if(internal_branch(addr))
4658   {
4659     int t=(addr-start)>>2;
4660     int hr;
4661     // Store the cycle count before loading something else
4662     if(i_regmap[HOST_CCREG]!=CCREG) {
4663       assert(i_regmap[HOST_CCREG]==-1);
4664     }
4665     if(regs[t].regmap_entry[HOST_CCREG]!=CCREG) {
4666       emit_storereg(CCREG,HOST_CCREG);
4667     }
4668     // Load 32-bit regs
4669     for(hr=0;hr<HOST_REGS;hr++) {
4670       if(hr!=EXCLUDE_REG&&regs[t].regmap_entry[hr]>=0&&regs[t].regmap_entry[hr]<TEMPREG) {
4671         if(i_regmap[hr]!=regs[t].regmap_entry[hr]) {
4672           if(regs[t].regmap_entry[hr]==0) {
4673             emit_zeroreg(hr);
4674           }
4675           else if(regs[t].regmap_entry[hr]!=CCREG)
4676           {
4677             emit_loadreg(regs[t].regmap_entry[hr],hr);
4678           }
4679         }
4680       }
4681     }
4682   }
4683 }
4684
4685 static int match_bt(signed char i_regmap[],uint64_t i_dirty,int addr)
4686 {
4687   if(addr>=start && addr<start+slen*4-4)
4688   {
4689     int t=(addr-start)>>2;
4690     int hr;
4691     if(regs[t].regmap_entry[HOST_CCREG]!=CCREG) return 0;
4692     for(hr=0;hr<HOST_REGS;hr++)
4693     {
4694       if(hr!=EXCLUDE_REG)
4695       {
4696         if(i_regmap[hr]!=regs[t].regmap_entry[hr])
4697         {
4698           if(regs[t].regmap_entry[hr]>=0&&(regs[t].regmap_entry[hr]|64)<TEMPREG+64)
4699           {
4700             return 0;
4701           }
4702           else
4703           if((i_dirty>>hr)&1)
4704           {
4705             if(i_regmap[hr]<TEMPREG)
4706             {
4707               if(!((unneeded_reg[t]>>i_regmap[hr])&1))
4708                 return 0;
4709             }
4710             else if(i_regmap[hr]>=64&&i_regmap[hr]<TEMPREG+64)
4711             {
4712               assert(0);
4713             }
4714           }
4715         }
4716         else // Same register but is it 32-bit or dirty?
4717         if(i_regmap[hr]>=0)
4718         {
4719           if(!((regs[t].dirty>>hr)&1))
4720           {
4721             if((i_dirty>>hr)&1)
4722             {
4723               if(!((unneeded_reg[t]>>i_regmap[hr])&1))
4724               {
4725                 //printf("%x: dirty no match\n",addr);
4726                 return 0;
4727               }
4728             }
4729           }
4730         }
4731       }
4732     }
4733     // Delay slots are not valid branch targets
4734     //if(t>0&&(dops[t-1].is_jump) return 0;
4735     // Delay slots require additional processing, so do not match
4736     if(dops[t].is_ds) return 0;
4737   }
4738   else
4739   {
4740     int hr;
4741     for(hr=0;hr<HOST_REGS;hr++)
4742     {
4743       if(hr!=EXCLUDE_REG)
4744       {
4745         if(i_regmap[hr]>=0)
4746         {
4747           if(hr!=HOST_CCREG||i_regmap[hr]!=CCREG)
4748           {
4749             if((i_dirty>>hr)&1)
4750             {
4751               return 0;
4752             }
4753           }
4754         }
4755       }
4756     }
4757   }
4758   return 1;
4759 }
4760
4761 #ifdef DRC_DBG
4762 static void drc_dbg_emit_do_cmp(int i, int ccadj_)
4763 {
4764   extern void do_insn_cmp();
4765   //extern int cycle;
4766   u_int hr, reglist = get_host_reglist(regs[i].regmap);
4767
4768   assem_debug("//do_insn_cmp %08x\n", start+i*4);
4769   save_regs(reglist);
4770   // write out changed consts to match the interpreter
4771   if (i > 0 && !dops[i].bt) {
4772     for (hr = 0; hr < HOST_REGS; hr++) {
4773       int reg = regs[i].regmap_entry[hr]; // regs[i-1].regmap[hr];
4774       if (hr == EXCLUDE_REG || reg < 0)
4775         continue;
4776       if (!((regs[i-1].isconst >> hr) & 1))
4777         continue;
4778       if (i > 1 && reg == regs[i-2].regmap[hr] && constmap[i-1][hr] == constmap[i-2][hr])
4779         continue;
4780       emit_movimm(constmap[i-1][hr],0);
4781       emit_storereg(reg, 0);
4782     }
4783   }
4784   emit_movimm(start+i*4,0);
4785   emit_writeword(0,&pcaddr);
4786   int cc = get_reg(regs[i].regmap_entry, CCREG);
4787   if (cc < 0)
4788     emit_loadreg(CCREG, cc = 0);
4789   emit_addimm(cc, ccadj_, 0);
4790   emit_writeword(0, &psxRegs.cycle);
4791   emit_far_call(do_insn_cmp);
4792   //emit_readword(&cycle,0);
4793   //emit_addimm(0,2,0);
4794   //emit_writeword(0,&cycle);
4795   (void)get_reg2;
4796   restore_regs(reglist);
4797   assem_debug("\\\\do_insn_cmp\n");
4798 }
4799 #else
4800 #define drc_dbg_emit_do_cmp(x,y)
4801 #endif
4802
4803 // Used when a branch jumps into the delay slot of another branch
4804 static void ds_assemble_entry(int i)
4805 {
4806   int t = (ba[i] - start) >> 2;
4807   int ccadj_ = -CLOCK_ADJUST(1);
4808   if (!instr_addr[t])
4809     instr_addr[t] = out;
4810   assem_debug("Assemble delay slot at %x\n",ba[i]);
4811   assem_debug("<->\n");
4812   drc_dbg_emit_do_cmp(t, ccadj_);
4813   if(regs[t].regmap_entry[HOST_CCREG]==CCREG&&regs[t].regmap[HOST_CCREG]!=CCREG)
4814     wb_register(CCREG,regs[t].regmap_entry,regs[t].wasdirty);
4815   load_regs(regs[t].regmap_entry,regs[t].regmap,dops[t].rs1,dops[t].rs2);
4816   address_generation(t,&regs[t],regs[t].regmap_entry);
4817   if (ram_offset && (dops[t].is_load || dops[t].is_store))
4818     load_regs(regs[t].regmap_entry,regs[t].regmap,ROREG,ROREG);
4819   if (dops[t].is_store)
4820     load_regs(regs[t].regmap_entry,regs[t].regmap,INVCP,INVCP);
4821   is_delayslot=0;
4822   switch (dops[t].itype) {
4823     case SYSCALL:
4824     case HLECALL:
4825     case INTCALL:
4826     case SPAN:
4827     case UJUMP:
4828     case RJUMP:
4829     case CJUMP:
4830     case SJUMP:
4831       SysPrintf("Jump in the delay slot.  This is probably a bug.\n");
4832       break;
4833     default:
4834       assemble(t, &regs[t], ccadj_);
4835   }
4836   store_regs_bt(regs[t].regmap,regs[t].dirty,ba[i]+4);
4837   load_regs_bt(regs[t].regmap,regs[t].dirty,ba[i]+4);
4838   if(internal_branch(ba[i]+4))
4839     assem_debug("branch: internal\n");
4840   else
4841     assem_debug("branch: external\n");
4842   assert(internal_branch(ba[i]+4));
4843   add_to_linker(out,ba[i]+4,internal_branch(ba[i]+4));
4844   emit_jmp(0);
4845 }
4846
4847 static void emit_extjump(void *addr, u_int target)
4848 {
4849   emit_extjump2(addr, target, dyna_linker);
4850 }
4851
4852 static void emit_extjump_ds(void *addr, u_int target)
4853 {
4854   emit_extjump2(addr, target, dyna_linker_ds);
4855 }
4856
4857 // Load 2 immediates optimizing for small code size
4858 static void emit_mov2imm_compact(int imm1,u_int rt1,int imm2,u_int rt2)
4859 {
4860   emit_movimm(imm1,rt1);
4861   emit_movimm_from(imm1,rt1,imm2,rt2);
4862 }
4863
4864 static void do_cc(int i, const signed char i_regmap[], int *adj,
4865   int addr, int taken, int invert)
4866 {
4867   int count, count_plus2;
4868   void *jaddr;
4869   void *idle=NULL;
4870   int t=0;
4871   if(dops[i].itype==RJUMP)
4872   {
4873     *adj=0;
4874   }
4875   //if(ba[i]>=start && ba[i]<(start+slen*4))
4876   if(internal_branch(ba[i]))
4877   {
4878     t=(ba[i]-start)>>2;
4879     if(dops[t].is_ds) *adj=-CLOCK_ADJUST(1); // Branch into delay slot adds an extra cycle
4880     else *adj=ccadj[t];
4881   }
4882   else
4883   {
4884     *adj=0;
4885   }
4886   count = ccadj[i];
4887   count_plus2 = count + CLOCK_ADJUST(2);
4888   if(taken==TAKEN && i==(ba[i]-start)>>2 && source[i+1]==0) {
4889     // Idle loop
4890     if(count&1) emit_addimm_and_set_flags(2*(count+2),HOST_CCREG);
4891     idle=out;
4892     //emit_subfrommem(&idlecount,HOST_CCREG); // Count idle cycles
4893     emit_andimm(HOST_CCREG,3,HOST_CCREG);
4894     jaddr=out;
4895     emit_jmp(0);
4896   }
4897   else if(*adj==0||invert) {
4898     int cycles = count_plus2;
4899     // faster loop HACK
4900 #if 0
4901     if (t&&*adj) {
4902       int rel=t-i;
4903       if(-NO_CYCLE_PENALTY_THR<rel&&rel<0)
4904         cycles=*adj+count+2-*adj;
4905     }
4906 #endif
4907     emit_addimm_and_set_flags(cycles, HOST_CCREG);
4908     jaddr = out;
4909     emit_jns(0);
4910   }
4911   else
4912   {
4913     emit_cmpimm(HOST_CCREG, -count_plus2);
4914     jaddr = out;
4915     emit_jns(0);
4916   }
4917   add_stub(CC_STUB,jaddr,idle?idle:out,(*adj==0||invert||idle)?0:count_plus2,i,addr,taken,0);
4918 }
4919
4920 static void do_ccstub(int n)
4921 {
4922   literal_pool(256);
4923   assem_debug("do_ccstub %x\n",start+(u_int)stubs[n].b*4);
4924   set_jump_target(stubs[n].addr, out);
4925   int i=stubs[n].b;
4926   if(stubs[n].d==NULLDS) {
4927     // Delay slot instruction is nullified ("likely" branch)
4928     wb_dirtys(regs[i].regmap,regs[i].dirty);
4929   }
4930   else if(stubs[n].d!=TAKEN) {
4931     wb_dirtys(branch_regs[i].regmap,branch_regs[i].dirty);
4932   }
4933   else {
4934     if(internal_branch(ba[i]))
4935       wb_needed_dirtys(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
4936   }
4937   if(stubs[n].c!=-1)
4938   {
4939     // Save PC as return address
4940     emit_movimm(stubs[n].c,EAX);
4941     emit_writeword(EAX,&pcaddr);
4942   }
4943   else
4944   {
4945     // Return address depends on which way the branch goes
4946     if(dops[i].itype==CJUMP||dops[i].itype==SJUMP)
4947     {
4948       int s1l=get_reg(branch_regs[i].regmap,dops[i].rs1);
4949       int s2l=get_reg(branch_regs[i].regmap,dops[i].rs2);
4950       if(dops[i].rs1==0)
4951       {
4952         s1l=s2l;
4953         s2l=-1;
4954       }
4955       else if(dops[i].rs2==0)
4956       {
4957         s2l=-1;
4958       }
4959       assert(s1l>=0);
4960       #ifdef DESTRUCTIVE_WRITEBACK
4961       if(dops[i].rs1) {
4962         if((branch_regs[i].dirty>>s1l)&&1)
4963           emit_loadreg(dops[i].rs1,s1l);
4964       }
4965       else {
4966         if((branch_regs[i].dirty>>s1l)&1)
4967           emit_loadreg(dops[i].rs2,s1l);
4968       }
4969       if(s2l>=0)
4970         if((branch_regs[i].dirty>>s2l)&1)
4971           emit_loadreg(dops[i].rs2,s2l);
4972       #endif
4973       int hr=0;
4974       int addr=-1,alt=-1,ntaddr=-1;
4975       while(hr<HOST_REGS)
4976       {
4977         if(hr!=EXCLUDE_REG && hr!=HOST_CCREG &&
4978            branch_regs[i].regmap[hr]!=dops[i].rs1 &&
4979            branch_regs[i].regmap[hr]!=dops[i].rs2 )
4980         {
4981           addr=hr++;break;
4982         }
4983         hr++;
4984       }
4985       while(hr<HOST_REGS)
4986       {
4987         if(hr!=EXCLUDE_REG && hr!=HOST_CCREG &&
4988            branch_regs[i].regmap[hr]!=dops[i].rs1 &&
4989            branch_regs[i].regmap[hr]!=dops[i].rs2 )
4990         {
4991           alt=hr++;break;
4992         }
4993         hr++;
4994       }
4995       if((dops[i].opcode&0x2E)==6) // BLEZ/BGTZ needs another register
4996       {
4997         while(hr<HOST_REGS)
4998         {
4999           if(hr!=EXCLUDE_REG && hr!=HOST_CCREG &&
5000              branch_regs[i].regmap[hr]!=dops[i].rs1 &&
5001              branch_regs[i].regmap[hr]!=dops[i].rs2 )
5002           {
5003             ntaddr=hr;break;
5004           }
5005           hr++;
5006         }
5007         assert(hr<HOST_REGS);
5008       }
5009       if((dops[i].opcode&0x2f)==4) // BEQ
5010       {
5011         #ifdef HAVE_CMOV_IMM
5012         if(s2l>=0) emit_cmp(s1l,s2l);
5013         else emit_test(s1l,s1l);
5014         emit_cmov2imm_e_ne_compact(ba[i],start+i*4+8,addr);
5015         #else
5016         emit_mov2imm_compact(ba[i],addr,start+i*4+8,alt);
5017         if(s2l>=0) emit_cmp(s1l,s2l);
5018         else emit_test(s1l,s1l);
5019         emit_cmovne_reg(alt,addr);
5020         #endif
5021       }
5022       if((dops[i].opcode&0x2f)==5) // BNE
5023       {
5024         #ifdef HAVE_CMOV_IMM
5025         if(s2l>=0) emit_cmp(s1l,s2l);
5026         else emit_test(s1l,s1l);
5027         emit_cmov2imm_e_ne_compact(start+i*4+8,ba[i],addr);
5028         #else
5029         emit_mov2imm_compact(start+i*4+8,addr,ba[i],alt);
5030         if(s2l>=0) emit_cmp(s1l,s2l);
5031         else emit_test(s1l,s1l);
5032         emit_cmovne_reg(alt,addr);
5033         #endif
5034       }
5035       if((dops[i].opcode&0x2f)==6) // BLEZ
5036       {
5037         //emit_movimm(ba[i],alt);
5038         //emit_movimm(start+i*4+8,addr);
5039         emit_mov2imm_compact(ba[i],alt,start+i*4+8,addr);
5040         emit_cmpimm(s1l,1);
5041         emit_cmovl_reg(alt,addr);
5042       }
5043       if((dops[i].opcode&0x2f)==7) // BGTZ
5044       {
5045         //emit_movimm(ba[i],addr);
5046         //emit_movimm(start+i*4+8,ntaddr);
5047         emit_mov2imm_compact(ba[i],addr,start+i*4+8,ntaddr);
5048         emit_cmpimm(s1l,1);
5049         emit_cmovl_reg(ntaddr,addr);
5050       }
5051       if((dops[i].opcode==1)&&(dops[i].opcode2&0x2D)==0) // BLTZ
5052       {
5053         //emit_movimm(ba[i],alt);
5054         //emit_movimm(start+i*4+8,addr);
5055         emit_mov2imm_compact(ba[i],alt,start+i*4+8,addr);
5056         emit_test(s1l,s1l);
5057         emit_cmovs_reg(alt,addr);
5058       }
5059       if((dops[i].opcode==1)&&(dops[i].opcode2&0x2D)==1) // BGEZ
5060       {
5061         //emit_movimm(ba[i],addr);
5062         //emit_movimm(start+i*4+8,alt);
5063         emit_mov2imm_compact(ba[i],addr,start+i*4+8,alt);
5064         emit_test(s1l,s1l);
5065         emit_cmovs_reg(alt,addr);
5066       }
5067       if(dops[i].opcode==0x11 && dops[i].opcode2==0x08 ) {
5068         if(source[i]&0x10000) // BC1T
5069         {
5070           //emit_movimm(ba[i],alt);
5071           //emit_movimm(start+i*4+8,addr);
5072           emit_mov2imm_compact(ba[i],alt,start+i*4+8,addr);
5073           emit_testimm(s1l,0x800000);
5074           emit_cmovne_reg(alt,addr);
5075         }
5076         else // BC1F
5077         {
5078           //emit_movimm(ba[i],addr);
5079           //emit_movimm(start+i*4+8,alt);
5080           emit_mov2imm_compact(ba[i],addr,start+i*4+8,alt);
5081           emit_testimm(s1l,0x800000);
5082           emit_cmovne_reg(alt,addr);
5083         }
5084       }
5085       emit_writeword(addr,&pcaddr);
5086     }
5087     else
5088     if(dops[i].itype==RJUMP)
5089     {
5090       int r=get_reg(branch_regs[i].regmap,dops[i].rs1);
5091       if (ds_writes_rjump_rs(i)) {
5092         r=get_reg(branch_regs[i].regmap,RTEMP);
5093       }
5094       emit_writeword(r,&pcaddr);
5095     }
5096     else {SysPrintf("Unknown branch type in do_ccstub\n");abort();}
5097   }
5098   // Update cycle count
5099   assert(branch_regs[i].regmap[HOST_CCREG]==CCREG||branch_regs[i].regmap[HOST_CCREG]==-1);
5100   if(stubs[n].a) emit_addimm(HOST_CCREG,(int)stubs[n].a,HOST_CCREG);
5101   emit_far_call(cc_interrupt);
5102   if(stubs[n].a) emit_addimm(HOST_CCREG,-(int)stubs[n].a,HOST_CCREG);
5103   if(stubs[n].d==TAKEN) {
5104     if(internal_branch(ba[i]))
5105       load_needed_regs(branch_regs[i].regmap,regs[(ba[i]-start)>>2].regmap_entry);
5106     else if(dops[i].itype==RJUMP) {
5107       if(get_reg(branch_regs[i].regmap,RTEMP)>=0)
5108         emit_readword(&pcaddr,get_reg(branch_regs[i].regmap,RTEMP));
5109       else
5110         emit_loadreg(dops[i].rs1,get_reg(branch_regs[i].regmap,dops[i].rs1));
5111     }
5112   }else if(stubs[n].d==NOTTAKEN) {
5113     if(i<slen-2) load_needed_regs(branch_regs[i].regmap,regmap_pre[i+2]);
5114     else load_all_regs(branch_regs[i].regmap);
5115   }else if(stubs[n].d==NULLDS) {
5116     // Delay slot instruction is nullified ("likely" branch)
5117     if(i<slen-2) load_needed_regs(regs[i].regmap,regmap_pre[i+2]);
5118     else load_all_regs(regs[i].regmap);
5119   }else{
5120     load_all_regs(branch_regs[i].regmap);
5121   }
5122   if (stubs[n].retaddr)
5123     emit_jmp(stubs[n].retaddr);
5124   else
5125     do_jump_vaddr(stubs[n].e);
5126 }
5127
5128 static void add_to_linker(void *addr, u_int target, int ext)
5129 {
5130   assert(linkcount < ARRAY_SIZE(link_addr));
5131   link_addr[linkcount].addr = addr;
5132   link_addr[linkcount].target = target;
5133   link_addr[linkcount].ext = ext;
5134   linkcount++;
5135 }
5136
5137 static void ujump_assemble_write_ra(int i)
5138 {
5139   int rt;
5140   unsigned int return_address;
5141   rt=get_reg(branch_regs[i].regmap,31);
5142   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]);
5143   //assert(rt>=0);
5144   return_address=start+i*4+8;
5145   if(rt>=0) {
5146     #ifdef USE_MINI_HT
5147     if(internal_branch(return_address)&&dops[i+1].rt1!=31) {
5148       int temp=-1; // note: must be ds-safe
5149       #ifdef HOST_TEMPREG
5150       temp=HOST_TEMPREG;
5151       #endif
5152       if(temp>=0) do_miniht_insert(return_address,rt,temp);
5153       else emit_movimm(return_address,rt);
5154     }
5155     else
5156     #endif
5157     {
5158       #ifdef REG_PREFETCH
5159       if(temp>=0)
5160       {
5161         if(i_regmap[temp]!=PTEMP) emit_movimm((uintptr_t)hash_table_get(return_address),temp);
5162       }
5163       #endif
5164       emit_movimm(return_address,rt); // PC into link register
5165       #ifdef IMM_PREFETCH
5166       emit_prefetch(hash_table_get(return_address));
5167       #endif
5168     }
5169   }
5170 }
5171
5172 static void ujump_assemble(int i, const struct regstat *i_regs)
5173 {
5174   int ra_done=0;
5175   if(i==(ba[i]-start)>>2) assem_debug("idle loop\n");
5176   address_generation(i+1,i_regs,regs[i].regmap_entry);
5177   #ifdef REG_PREFETCH
5178   int temp=get_reg(branch_regs[i].regmap,PTEMP);
5179   if(dops[i].rt1==31&&temp>=0)
5180   {
5181     signed char *i_regmap=i_regs->regmap;
5182     int return_address=start+i*4+8;
5183     if(get_reg(branch_regs[i].regmap,31)>0)
5184     if(i_regmap[temp]==PTEMP) emit_movimm((uintptr_t)hash_table_get(return_address),temp);
5185   }
5186   #endif
5187   if(dops[i].rt1==31&&(dops[i].rt1==dops[i+1].rs1||dops[i].rt1==dops[i+1].rs2)) {
5188     ujump_assemble_write_ra(i); // writeback ra for DS
5189     ra_done=1;
5190   }
5191   ds_assemble(i+1,i_regs);
5192   uint64_t bc_unneeded=branch_regs[i].u;
5193   bc_unneeded|=1|(1LL<<dops[i].rt1);
5194   wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,bc_unneeded);
5195   load_regs(regs[i].regmap,branch_regs[i].regmap,CCREG,CCREG);
5196   if(!ra_done&&dops[i].rt1==31)
5197     ujump_assemble_write_ra(i);
5198   int cc,adj;
5199   cc=get_reg(branch_regs[i].regmap,CCREG);
5200   assert(cc==HOST_CCREG);
5201   store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5202   #ifdef REG_PREFETCH
5203   if(dops[i].rt1==31&&temp>=0) emit_prefetchreg(temp);
5204   #endif
5205   do_cc(i,branch_regs[i].regmap,&adj,ba[i],TAKEN,0);
5206   if(adj) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5207   load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5208   if(internal_branch(ba[i]))
5209     assem_debug("branch: internal\n");
5210   else
5211     assem_debug("branch: external\n");
5212   if (internal_branch(ba[i]) && dops[(ba[i]-start)>>2].is_ds) {
5213     ds_assemble_entry(i);
5214   }
5215   else {
5216     add_to_linker(out,ba[i],internal_branch(ba[i]));
5217     emit_jmp(0);
5218   }
5219 }
5220
5221 static void rjump_assemble_write_ra(int i)
5222 {
5223   int rt,return_address;
5224   assert(dops[i+1].rt1!=dops[i].rt1);
5225   assert(dops[i+1].rt2!=dops[i].rt1);
5226   rt=get_reg(branch_regs[i].regmap,dops[i].rt1);
5227   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]);
5228   assert(rt>=0);
5229   return_address=start+i*4+8;
5230   #ifdef REG_PREFETCH
5231   if(temp>=0)
5232   {
5233     if(i_regmap[temp]!=PTEMP) emit_movimm((uintptr_t)hash_table_get(return_address),temp);
5234   }
5235   #endif
5236   emit_movimm(return_address,rt); // PC into link register
5237   #ifdef IMM_PREFETCH
5238   emit_prefetch(hash_table_get(return_address));
5239   #endif
5240 }
5241
5242 static void rjump_assemble(int i, const struct regstat *i_regs)
5243 {
5244   int temp;
5245   int rs,cc;
5246   int ra_done=0;
5247   rs=get_reg(branch_regs[i].regmap,dops[i].rs1);
5248   assert(rs>=0);
5249   if (ds_writes_rjump_rs(i)) {
5250     // Delay slot abuse, make a copy of the branch address register
5251     temp=get_reg(branch_regs[i].regmap,RTEMP);
5252     assert(temp>=0);
5253     assert(regs[i].regmap[temp]==RTEMP);
5254     emit_mov(rs,temp);
5255     rs=temp;
5256   }
5257   address_generation(i+1,i_regs,regs[i].regmap_entry);
5258   #ifdef REG_PREFETCH
5259   if(dops[i].rt1==31)
5260   {
5261     if((temp=get_reg(branch_regs[i].regmap,PTEMP))>=0) {
5262       signed char *i_regmap=i_regs->regmap;
5263       int return_address=start+i*4+8;
5264       if(i_regmap[temp]==PTEMP) emit_movimm((uintptr_t)hash_table_get(return_address),temp);
5265     }
5266   }
5267   #endif
5268   #ifdef USE_MINI_HT
5269   if(dops[i].rs1==31) {
5270     int rh=get_reg(regs[i].regmap,RHASH);
5271     if(rh>=0) do_preload_rhash(rh);
5272   }
5273   #endif
5274   if(dops[i].rt1!=0&&(dops[i].rt1==dops[i+1].rs1||dops[i].rt1==dops[i+1].rs2)) {
5275     rjump_assemble_write_ra(i);
5276     ra_done=1;
5277   }
5278   ds_assemble(i+1,i_regs);
5279   uint64_t bc_unneeded=branch_regs[i].u;
5280   bc_unneeded|=1|(1LL<<dops[i].rt1);
5281   bc_unneeded&=~(1LL<<dops[i].rs1);
5282   wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,bc_unneeded);
5283   load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i].rs1,CCREG);
5284   if(!ra_done&&dops[i].rt1!=0)
5285     rjump_assemble_write_ra(i);
5286   cc=get_reg(branch_regs[i].regmap,CCREG);
5287   assert(cc==HOST_CCREG);
5288   (void)cc;
5289   #ifdef USE_MINI_HT
5290   int rh=get_reg(branch_regs[i].regmap,RHASH);
5291   int ht=get_reg(branch_regs[i].regmap,RHTBL);
5292   if(dops[i].rs1==31) {
5293     if(regs[i].regmap[rh]!=RHASH) do_preload_rhash(rh);
5294     do_preload_rhtbl(ht);
5295     do_rhash(rs,rh);
5296   }
5297   #endif
5298   store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,-1);
5299   #ifdef DESTRUCTIVE_WRITEBACK
5300   if((branch_regs[i].dirty>>rs)&1) {
5301     if(dops[i].rs1!=dops[i+1].rt1&&dops[i].rs1!=dops[i+1].rt2) {
5302       emit_loadreg(dops[i].rs1,rs);
5303     }
5304   }
5305   #endif
5306   #ifdef REG_PREFETCH
5307   if(dops[i].rt1==31&&temp>=0) emit_prefetchreg(temp);
5308   #endif
5309   #ifdef USE_MINI_HT
5310   if(dops[i].rs1==31) {
5311     do_miniht_load(ht,rh);
5312   }
5313   #endif
5314   //do_cc(i,branch_regs[i].regmap,&adj,-1,TAKEN);
5315   //if(adj) emit_addimm(cc,2*(ccadj[i]+2-adj),cc); // ??? - Shouldn't happen
5316   //assert(adj==0);
5317   emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), HOST_CCREG);
5318   add_stub(CC_STUB,out,NULL,0,i,-1,TAKEN,rs);
5319   if(dops[i+1].itype==COP0&&(source[i+1]&0x3f)==0x10)
5320     // special case for RFE
5321     emit_jmp(0);
5322   else
5323     emit_jns(0);
5324   //load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,-1);
5325   #ifdef USE_MINI_HT
5326   if(dops[i].rs1==31) {
5327     do_miniht_jump(rs,rh,ht);
5328   }
5329   else
5330   #endif
5331   {
5332     do_jump_vaddr(rs);
5333   }
5334   #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5335   if(dops[i].rt1!=31&&i<slen-2&&(((u_int)out)&7)) emit_mov(13,13);
5336   #endif
5337 }
5338
5339 static void cjump_assemble(int i, const struct regstat *i_regs)
5340 {
5341   const signed char *i_regmap = i_regs->regmap;
5342   int cc;
5343   int match;
5344   match=match_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5345   assem_debug("match=%d\n",match);
5346   int s1l,s2l;
5347   int unconditional=0,nop=0;
5348   int invert=0;
5349   int internal=internal_branch(ba[i]);
5350   if(i==(ba[i]-start)>>2) assem_debug("idle loop\n");
5351   if(!match) invert=1;
5352   #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5353   if(i>(ba[i]-start)>>2) invert=1;
5354   #endif
5355   #ifdef __aarch64__
5356   invert=1; // because of near cond. branches
5357   #endif
5358
5359   if(dops[i].ooo) {
5360     s1l=get_reg(branch_regs[i].regmap,dops[i].rs1);
5361     s2l=get_reg(branch_regs[i].regmap,dops[i].rs2);
5362   }
5363   else {
5364     s1l=get_reg(i_regmap,dops[i].rs1);
5365     s2l=get_reg(i_regmap,dops[i].rs2);
5366   }
5367   if(dops[i].rs1==0&&dops[i].rs2==0)
5368   {
5369     if(dops[i].opcode&1) nop=1;
5370     else unconditional=1;
5371     //assert(dops[i].opcode!=5);
5372     //assert(dops[i].opcode!=7);
5373     //assert(dops[i].opcode!=0x15);
5374     //assert(dops[i].opcode!=0x17);
5375   }
5376   else if(dops[i].rs1==0)
5377   {
5378     s1l=s2l;
5379     s2l=-1;
5380   }
5381   else if(dops[i].rs2==0)
5382   {
5383     s2l=-1;
5384   }
5385
5386   if(dops[i].ooo) {
5387     // Out of order execution (delay slot first)
5388     //printf("OOOE\n");
5389     address_generation(i+1,i_regs,regs[i].regmap_entry);
5390     ds_assemble(i+1,i_regs);
5391     int adj;
5392     uint64_t bc_unneeded=branch_regs[i].u;
5393     bc_unneeded&=~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
5394     bc_unneeded|=1;
5395     wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,bc_unneeded);
5396     load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i].rs1,dops[i].rs2);
5397     load_regs(regs[i].regmap,branch_regs[i].regmap,CCREG,CCREG);
5398     cc=get_reg(branch_regs[i].regmap,CCREG);
5399     assert(cc==HOST_CCREG);
5400     if(unconditional)
5401       store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5402     //do_cc(i,branch_regs[i].regmap,&adj,unconditional?ba[i]:-1,unconditional);
5403     //assem_debug("cycle count (adj)\n");
5404     if(unconditional) {
5405       do_cc(i,branch_regs[i].regmap,&adj,ba[i],TAKEN,0);
5406       if(i!=(ba[i]-start)>>2 || source[i+1]!=0) {
5407         if(adj) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5408         load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5409         if(internal)
5410           assem_debug("branch: internal\n");
5411         else
5412           assem_debug("branch: external\n");
5413         if (internal && dops[(ba[i]-start)>>2].is_ds) {
5414           ds_assemble_entry(i);
5415         }
5416         else {
5417           add_to_linker(out,ba[i],internal);
5418           emit_jmp(0);
5419         }
5420         #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5421         if(((u_int)out)&7) emit_addnop(0);
5422         #endif
5423       }
5424     }
5425     else if(nop) {
5426       emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), cc);
5427       void *jaddr=out;
5428       emit_jns(0);
5429       add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5430     }
5431     else {
5432       void *taken = NULL, *nottaken = NULL, *nottaken1 = NULL;
5433       do_cc(i,branch_regs[i].regmap,&adj,-1,0,invert);
5434       if(adj&&!invert) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5435
5436       //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]);
5437       assert(s1l>=0);
5438       if(dops[i].opcode==4) // BEQ
5439       {
5440         if(s2l>=0) emit_cmp(s1l,s2l);
5441         else emit_test(s1l,s1l);
5442         if(invert){
5443           nottaken=out;
5444           emit_jne(DJT_1);
5445         }else{
5446           add_to_linker(out,ba[i],internal);
5447           emit_jeq(0);
5448         }
5449       }
5450       if(dops[i].opcode==5) // BNE
5451       {
5452         if(s2l>=0) emit_cmp(s1l,s2l);
5453         else emit_test(s1l,s1l);
5454         if(invert){
5455           nottaken=out;
5456           emit_jeq(DJT_1);
5457         }else{
5458           add_to_linker(out,ba[i],internal);
5459           emit_jne(0);
5460         }
5461       }
5462       if(dops[i].opcode==6) // BLEZ
5463       {
5464         emit_cmpimm(s1l,1);
5465         if(invert){
5466           nottaken=out;
5467           emit_jge(DJT_1);
5468         }else{
5469           add_to_linker(out,ba[i],internal);
5470           emit_jl(0);
5471         }
5472       }
5473       if(dops[i].opcode==7) // BGTZ
5474       {
5475         emit_cmpimm(s1l,1);
5476         if(invert){
5477           nottaken=out;
5478           emit_jl(DJT_1);
5479         }else{
5480           add_to_linker(out,ba[i],internal);
5481           emit_jge(0);
5482         }
5483       }
5484       if(invert) {
5485         if(taken) set_jump_target(taken, out);
5486         #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5487         if (match && (!internal || !dops[(ba[i]-start)>>2].is_ds)) {
5488           if(adj) {
5489             emit_addimm(cc,-adj,cc);
5490             add_to_linker(out,ba[i],internal);
5491           }else{
5492             emit_addnop(13);
5493             add_to_linker(out,ba[i],internal*2);
5494           }
5495           emit_jmp(0);
5496         }else
5497         #endif
5498         {
5499           if(adj) emit_addimm(cc,-adj,cc);
5500           store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5501           load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5502           if(internal)
5503             assem_debug("branch: internal\n");
5504           else
5505             assem_debug("branch: external\n");
5506           if (internal && dops[(ba[i] - start) >> 2].is_ds) {
5507             ds_assemble_entry(i);
5508           }
5509           else {
5510             add_to_linker(out,ba[i],internal);
5511             emit_jmp(0);
5512           }
5513         }
5514         set_jump_target(nottaken, out);
5515       }
5516
5517       if(nottaken1) set_jump_target(nottaken1, out);
5518       if(adj) {
5519         if(!invert) emit_addimm(cc,adj,cc);
5520       }
5521     } // (!unconditional)
5522   } // if(ooo)
5523   else
5524   {
5525     // In-order execution (branch first)
5526     void *taken = NULL, *nottaken = NULL, *nottaken1 = NULL;
5527     if(!unconditional&&!nop) {
5528       //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]);
5529       assert(s1l>=0);
5530       if((dops[i].opcode&0x2f)==4) // BEQ
5531       {
5532         if(s2l>=0) emit_cmp(s1l,s2l);
5533         else emit_test(s1l,s1l);
5534         nottaken=out;
5535         emit_jne(DJT_2);
5536       }
5537       if((dops[i].opcode&0x2f)==5) // BNE
5538       {
5539         if(s2l>=0) emit_cmp(s1l,s2l);
5540         else emit_test(s1l,s1l);
5541         nottaken=out;
5542         emit_jeq(DJT_2);
5543       }
5544       if((dops[i].opcode&0x2f)==6) // BLEZ
5545       {
5546         emit_cmpimm(s1l,1);
5547         nottaken=out;
5548         emit_jge(DJT_2);
5549       }
5550       if((dops[i].opcode&0x2f)==7) // BGTZ
5551       {
5552         emit_cmpimm(s1l,1);
5553         nottaken=out;
5554         emit_jl(DJT_2);
5555       }
5556     } // if(!unconditional)
5557     int adj;
5558     uint64_t ds_unneeded=branch_regs[i].u;
5559     ds_unneeded&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
5560     ds_unneeded|=1;
5561     // branch taken
5562     if(!nop) {
5563       if(taken) set_jump_target(taken, out);
5564       assem_debug("1:\n");
5565       wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,ds_unneeded);
5566       // load regs
5567       load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i+1].rs1,dops[i+1].rs2);
5568       address_generation(i+1,&branch_regs[i],0);
5569       if (ram_offset)
5570         load_regs(regs[i].regmap,branch_regs[i].regmap,ROREG,ROREG);
5571       load_regs(regs[i].regmap,branch_regs[i].regmap,CCREG,INVCP);
5572       ds_assemble(i+1,&branch_regs[i]);
5573       cc=get_reg(branch_regs[i].regmap,CCREG);
5574       if(cc==-1) {
5575         emit_loadreg(CCREG,cc=HOST_CCREG);
5576         // CHECK: Is the following instruction (fall thru) allocated ok?
5577       }
5578       assert(cc==HOST_CCREG);
5579       store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5580       do_cc(i,i_regmap,&adj,ba[i],TAKEN,0);
5581       assem_debug("cycle count (adj)\n");
5582       if(adj) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5583       load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5584       if(internal)
5585         assem_debug("branch: internal\n");
5586       else
5587         assem_debug("branch: external\n");
5588       if (internal && dops[(ba[i] - start) >> 2].is_ds) {
5589         ds_assemble_entry(i);
5590       }
5591       else {
5592         add_to_linker(out,ba[i],internal);
5593         emit_jmp(0);
5594       }
5595     }
5596     // branch not taken
5597     if(!unconditional) {
5598       if(nottaken1) set_jump_target(nottaken1, out);
5599       set_jump_target(nottaken, out);
5600       assem_debug("2:\n");
5601       wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,ds_unneeded);
5602       // load regs
5603       load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i+1].rs1,dops[i+1].rs2);
5604       address_generation(i+1,&branch_regs[i],0);
5605       if (ram_offset)
5606         load_regs(regs[i].regmap,branch_regs[i].regmap,ROREG,ROREG);
5607       load_regs(regs[i].regmap,branch_regs[i].regmap,CCREG,INVCP);
5608       ds_assemble(i+1,&branch_regs[i]);
5609       cc=get_reg(branch_regs[i].regmap,CCREG);
5610       if (cc == -1) {
5611         // Cycle count isn't in a register, temporarily load it then write it out
5612         emit_loadreg(CCREG,HOST_CCREG);
5613         emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), HOST_CCREG);
5614         void *jaddr=out;
5615         emit_jns(0);
5616         add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5617         emit_storereg(CCREG,HOST_CCREG);
5618       }
5619       else{
5620         cc=get_reg(i_regmap,CCREG);
5621         assert(cc==HOST_CCREG);
5622         emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), cc);
5623         void *jaddr=out;
5624         emit_jns(0);
5625         add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5626       }
5627     }
5628   }
5629 }
5630
5631 static void sjump_assemble(int i, const struct regstat *i_regs)
5632 {
5633   const signed char *i_regmap = i_regs->regmap;
5634   int cc;
5635   int match;
5636   match=match_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5637   assem_debug("smatch=%d ooo=%d\n", match, dops[i].ooo);
5638   int s1l;
5639   int unconditional=0,nevertaken=0;
5640   int invert=0;
5641   int internal=internal_branch(ba[i]);
5642   if(i==(ba[i]-start)>>2) assem_debug("idle loop\n");
5643   if(!match) invert=1;
5644   #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5645   if(i>(ba[i]-start)>>2) invert=1;
5646   #endif
5647   #ifdef __aarch64__
5648   invert=1; // because of near cond. branches
5649   #endif
5650
5651   //if(dops[i].opcode2>=0x10) return; // FIXME (BxxZAL)
5652   //assert(dops[i].opcode2<0x10||dops[i].rs1==0); // FIXME (BxxZAL)
5653
5654   if(dops[i].ooo) {
5655     s1l=get_reg(branch_regs[i].regmap,dops[i].rs1);
5656   }
5657   else {
5658     s1l=get_reg(i_regmap,dops[i].rs1);
5659   }
5660   if(dops[i].rs1==0)
5661   {
5662     if(dops[i].opcode2&1) unconditional=1;
5663     else nevertaken=1;
5664     // These are never taken (r0 is never less than zero)
5665     //assert(dops[i].opcode2!=0);
5666     //assert(dops[i].opcode2!=2);
5667     //assert(dops[i].opcode2!=0x10);
5668     //assert(dops[i].opcode2!=0x12);
5669   }
5670
5671   if(dops[i].ooo) {
5672     // Out of order execution (delay slot first)
5673     //printf("OOOE\n");
5674     address_generation(i+1,i_regs,regs[i].regmap_entry);
5675     ds_assemble(i+1,i_regs);
5676     int adj;
5677     uint64_t bc_unneeded=branch_regs[i].u;
5678     bc_unneeded&=~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
5679     bc_unneeded|=1;
5680     wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,bc_unneeded);
5681     load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i].rs1,dops[i].rs1);
5682     load_regs(regs[i].regmap,branch_regs[i].regmap,CCREG,CCREG);
5683     if(dops[i].rt1==31) {
5684       int rt,return_address;
5685       rt=get_reg(branch_regs[i].regmap,31);
5686       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]);
5687       if(rt>=0) {
5688         // Save the PC even if the branch is not taken
5689         return_address=start+i*4+8;
5690         emit_movimm(return_address,rt); // PC into link register
5691         #ifdef IMM_PREFETCH
5692         if(!nevertaken) emit_prefetch(hash_table_get(return_address));
5693         #endif
5694       }
5695     }
5696     cc=get_reg(branch_regs[i].regmap,CCREG);
5697     assert(cc==HOST_CCREG);
5698     if(unconditional)
5699       store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5700     //do_cc(i,branch_regs[i].regmap,&adj,unconditional?ba[i]:-1,unconditional);
5701     assem_debug("cycle count (adj)\n");
5702     if(unconditional) {
5703       do_cc(i,branch_regs[i].regmap,&adj,ba[i],TAKEN,0);
5704       if(i!=(ba[i]-start)>>2 || source[i+1]!=0) {
5705         if(adj) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5706         load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5707         if(internal)
5708           assem_debug("branch: internal\n");
5709         else
5710           assem_debug("branch: external\n");
5711         if (internal && dops[(ba[i] - start) >> 2].is_ds) {
5712           ds_assemble_entry(i);
5713         }
5714         else {
5715           add_to_linker(out,ba[i],internal);
5716           emit_jmp(0);
5717         }
5718         #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5719         if(((u_int)out)&7) emit_addnop(0);
5720         #endif
5721       }
5722     }
5723     else if(nevertaken) {
5724       emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), cc);
5725       void *jaddr=out;
5726       emit_jns(0);
5727       add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5728     }
5729     else {
5730       void *nottaken = NULL;
5731       do_cc(i,branch_regs[i].regmap,&adj,-1,0,invert);
5732       if(adj&&!invert) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5733       {
5734         assert(s1l>=0);
5735         if((dops[i].opcode2&0xf)==0) // BLTZ/BLTZAL
5736         {
5737           emit_test(s1l,s1l);
5738           if(invert){
5739             nottaken=out;
5740             emit_jns(DJT_1);
5741           }else{
5742             add_to_linker(out,ba[i],internal);
5743             emit_js(0);
5744           }
5745         }
5746         if((dops[i].opcode2&0xf)==1) // BGEZ/BLTZAL
5747         {
5748           emit_test(s1l,s1l);
5749           if(invert){
5750             nottaken=out;
5751             emit_js(DJT_1);
5752           }else{
5753             add_to_linker(out,ba[i],internal);
5754             emit_jns(0);
5755           }
5756         }
5757       }
5758
5759       if(invert) {
5760         #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5761         if (match && (!internal || !dops[(ba[i] - start) >> 2].is_ds)) {
5762           if(adj) {
5763             emit_addimm(cc,-adj,cc);
5764             add_to_linker(out,ba[i],internal);
5765           }else{
5766             emit_addnop(13);
5767             add_to_linker(out,ba[i],internal*2);
5768           }
5769           emit_jmp(0);
5770         }else
5771         #endif
5772         {
5773           if(adj) emit_addimm(cc,-adj,cc);
5774           store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5775           load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5776           if(internal)
5777             assem_debug("branch: internal\n");
5778           else
5779             assem_debug("branch: external\n");
5780           if (internal && dops[(ba[i] - start) >> 2].is_ds) {
5781             ds_assemble_entry(i);
5782           }
5783           else {
5784             add_to_linker(out,ba[i],internal);
5785             emit_jmp(0);
5786           }
5787         }
5788         set_jump_target(nottaken, out);
5789       }
5790
5791       if(adj) {
5792         if(!invert) emit_addimm(cc,adj,cc);
5793       }
5794     } // (!unconditional)
5795   } // if(ooo)
5796   else
5797   {
5798     // In-order execution (branch first)
5799     //printf("IOE\n");
5800     void *nottaken = NULL;
5801     if(dops[i].rt1==31) {
5802       int rt,return_address;
5803       rt=get_reg(branch_regs[i].regmap,31);
5804       if(rt>=0) {
5805         // Save the PC even if the branch is not taken
5806         return_address=start+i*4+8;
5807         emit_movimm(return_address,rt); // PC into link register
5808         #ifdef IMM_PREFETCH
5809         emit_prefetch(hash_table_get(return_address));
5810         #endif
5811       }
5812     }
5813     if(!unconditional) {
5814       //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]);
5815         assert(s1l>=0);
5816         if((dops[i].opcode2&0x0d)==0) // BLTZ/BLTZL/BLTZAL/BLTZALL
5817         {
5818           emit_test(s1l,s1l);
5819           nottaken=out;
5820           emit_jns(DJT_1);
5821         }
5822         if((dops[i].opcode2&0x0d)==1) // BGEZ/BGEZL/BGEZAL/BGEZALL
5823         {
5824           emit_test(s1l,s1l);
5825           nottaken=out;
5826           emit_js(DJT_1);
5827         }
5828     } // if(!unconditional)
5829     int adj;
5830     uint64_t ds_unneeded=branch_regs[i].u;
5831     ds_unneeded&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
5832     ds_unneeded|=1;
5833     // branch taken
5834     if(!nevertaken) {
5835       //assem_debug("1:\n");
5836       wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,ds_unneeded);
5837       // load regs
5838       load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i+1].rs1,dops[i+1].rs2);
5839       address_generation(i+1,&branch_regs[i],0);
5840       if (ram_offset)
5841         load_regs(regs[i].regmap,branch_regs[i].regmap,ROREG,ROREG);
5842       load_regs(regs[i].regmap,branch_regs[i].regmap,CCREG,INVCP);
5843       ds_assemble(i+1,&branch_regs[i]);
5844       cc=get_reg(branch_regs[i].regmap,CCREG);
5845       if(cc==-1) {
5846         emit_loadreg(CCREG,cc=HOST_CCREG);
5847         // CHECK: Is the following instruction (fall thru) allocated ok?
5848       }
5849       assert(cc==HOST_CCREG);
5850       store_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5851       do_cc(i,i_regmap,&adj,ba[i],TAKEN,0);
5852       assem_debug("cycle count (adj)\n");
5853       if(adj) emit_addimm(cc, ccadj[i] + CLOCK_ADJUST(2) - adj, cc);
5854       load_regs_bt(branch_regs[i].regmap,branch_regs[i].dirty,ba[i]);
5855       if(internal)
5856         assem_debug("branch: internal\n");
5857       else
5858         assem_debug("branch: external\n");
5859       if (internal && dops[(ba[i] - start) >> 2].is_ds) {
5860         ds_assemble_entry(i);
5861       }
5862       else {
5863         add_to_linker(out,ba[i],internal);
5864         emit_jmp(0);
5865       }
5866     }
5867     // branch not taken
5868     if(!unconditional) {
5869       set_jump_target(nottaken, out);
5870       assem_debug("1:\n");
5871       wb_invalidate(regs[i].regmap,branch_regs[i].regmap,regs[i].dirty,ds_unneeded);
5872       load_regs(regs[i].regmap,branch_regs[i].regmap,dops[i+1].rs1,dops[i+1].rs2);
5873       address_generation(i+1,&branch_regs[i],0);
5874       if (ram_offset)
5875         load_regs(regs[i].regmap,branch_regs[i].regmap,ROREG,ROREG);
5876       load_regs(regs[i].regmap,branch_regs[i].regmap,CCREG,INVCP);
5877       ds_assemble(i+1,&branch_regs[i]);
5878       cc=get_reg(branch_regs[i].regmap,CCREG);
5879       if (cc == -1) {
5880         // Cycle count isn't in a register, temporarily load it then write it out
5881         emit_loadreg(CCREG,HOST_CCREG);
5882         emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), HOST_CCREG);
5883         void *jaddr=out;
5884         emit_jns(0);
5885         add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5886         emit_storereg(CCREG,HOST_CCREG);
5887       }
5888       else{
5889         cc=get_reg(i_regmap,CCREG);
5890         assert(cc==HOST_CCREG);
5891         emit_addimm_and_set_flags(ccadj[i] + CLOCK_ADJUST(2), cc);
5892         void *jaddr=out;
5893         emit_jns(0);
5894         add_stub(CC_STUB,jaddr,out,0,i,start+i*4+8,NOTTAKEN,0);
5895       }
5896     }
5897   }
5898 }
5899
5900 static void pagespan_assemble(int i, const struct regstat *i_regs)
5901 {
5902   int s1l=get_reg(i_regs->regmap,dops[i].rs1);
5903   int s2l=get_reg(i_regs->regmap,dops[i].rs2);
5904   void *taken = NULL;
5905   void *nottaken = NULL;
5906   int unconditional=0;
5907   if(dops[i].rs1==0)
5908   {
5909     s1l=s2l;
5910     s2l=-1;
5911   }
5912   else if(dops[i].rs2==0)
5913   {
5914     s2l=-1;
5915   }
5916   int hr=0;
5917   int addr=-1,alt=-1,ntaddr=-1;
5918   if(i_regs->regmap[HOST_BTREG]<0) {addr=HOST_BTREG;}
5919   else {
5920     while(hr<HOST_REGS)
5921     {
5922       if(hr!=EXCLUDE_REG && hr!=HOST_CCREG &&
5923          i_regs->regmap[hr]!=dops[i].rs1 &&
5924          i_regs->regmap[hr]!=dops[i].rs2 )
5925       {
5926         addr=hr++;break;
5927       }
5928       hr++;
5929     }
5930   }
5931   while(hr<HOST_REGS)
5932   {
5933     if(hr!=EXCLUDE_REG && hr!=HOST_CCREG && hr!=HOST_BTREG &&
5934        i_regs->regmap[hr]!=dops[i].rs1 &&
5935        i_regs->regmap[hr]!=dops[i].rs2 )
5936     {
5937       alt=hr++;break;
5938     }
5939     hr++;
5940   }
5941   if((dops[i].opcode&0x2E)==6) // BLEZ/BGTZ needs another register
5942   {
5943     while(hr<HOST_REGS)
5944     {
5945       if(hr!=EXCLUDE_REG && hr!=HOST_CCREG && hr!=HOST_BTREG &&
5946          i_regs->regmap[hr]!=dops[i].rs1 &&
5947          i_regs->regmap[hr]!=dops[i].rs2 )
5948       {
5949         ntaddr=hr;break;
5950       }
5951       hr++;
5952     }
5953   }
5954   assert(hr<HOST_REGS);
5955   if((dops[i].opcode&0x2e)==4||dops[i].opcode==0x11) { // BEQ/BNE/BEQL/BNEL/BC1
5956     load_regs(regs[i].regmap_entry,regs[i].regmap,CCREG,CCREG);
5957   }
5958   emit_addimm(HOST_CCREG, ccadj[i] + CLOCK_ADJUST(2), HOST_CCREG);
5959   if(dops[i].opcode==2) // J
5960   {
5961     unconditional=1;
5962   }
5963   if(dops[i].opcode==3) // JAL
5964   {
5965     // TODO: mini_ht
5966     int rt=get_reg(i_regs->regmap,31);
5967     emit_movimm(start+i*4+8,rt);
5968     unconditional=1;
5969   }
5970   if(dops[i].opcode==0&&(dops[i].opcode2&0x3E)==8) // JR/JALR
5971   {
5972     emit_mov(s1l,addr);
5973     if(dops[i].opcode2==9) // JALR
5974     {
5975       int rt=get_reg(i_regs->regmap,dops[i].rt1);
5976       emit_movimm(start+i*4+8,rt);
5977     }
5978   }
5979   if((dops[i].opcode&0x3f)==4) // BEQ
5980   {
5981     if(dops[i].rs1==dops[i].rs2)
5982     {
5983       unconditional=1;
5984     }
5985     else
5986     #ifdef HAVE_CMOV_IMM
5987     if(1) {
5988       if(s2l>=0) emit_cmp(s1l,s2l);
5989       else emit_test(s1l,s1l);
5990       emit_cmov2imm_e_ne_compact(ba[i],start+i*4+8,addr);
5991     }
5992     else
5993     #endif
5994     {
5995       assert(s1l>=0);
5996       emit_mov2imm_compact(ba[i],addr,start+i*4+8,alt);
5997       if(s2l>=0) emit_cmp(s1l,s2l);
5998       else emit_test(s1l,s1l);
5999       emit_cmovne_reg(alt,addr);
6000     }
6001   }
6002   if((dops[i].opcode&0x3f)==5) // BNE
6003   {
6004     #ifdef HAVE_CMOV_IMM
6005     if(s2l>=0) emit_cmp(s1l,s2l);
6006     else emit_test(s1l,s1l);
6007     emit_cmov2imm_e_ne_compact(start+i*4+8,ba[i],addr);
6008     #else
6009     assert(s1l>=0);
6010     emit_mov2imm_compact(start+i*4+8,addr,ba[i],alt);
6011     if(s2l>=0) emit_cmp(s1l,s2l);
6012     else emit_test(s1l,s1l);
6013     emit_cmovne_reg(alt,addr);
6014     #endif
6015   }
6016   if((dops[i].opcode&0x3f)==0x14) // BEQL
6017   {
6018     if(s2l>=0) emit_cmp(s1l,s2l);
6019     else emit_test(s1l,s1l);
6020     if(nottaken) set_jump_target(nottaken, out);
6021     nottaken=out;
6022     emit_jne(0);
6023   }
6024   if((dops[i].opcode&0x3f)==0x15) // BNEL
6025   {
6026     if(s2l>=0) emit_cmp(s1l,s2l);
6027     else emit_test(s1l,s1l);
6028     nottaken=out;
6029     emit_jeq(0);
6030     if(taken) set_jump_target(taken, out);
6031   }
6032   if((dops[i].opcode&0x3f)==6) // BLEZ
6033   {
6034     emit_mov2imm_compact(ba[i],alt,start+i*4+8,addr);
6035     emit_cmpimm(s1l,1);
6036     emit_cmovl_reg(alt,addr);
6037   }
6038   if((dops[i].opcode&0x3f)==7) // BGTZ
6039   {
6040     emit_mov2imm_compact(ba[i],addr,start+i*4+8,ntaddr);
6041     emit_cmpimm(s1l,1);
6042     emit_cmovl_reg(ntaddr,addr);
6043   }
6044   if((dops[i].opcode&0x3f)==0x16) // BLEZL
6045   {
6046     assert((dops[i].opcode&0x3f)!=0x16);
6047   }
6048   if((dops[i].opcode&0x3f)==0x17) // BGTZL
6049   {
6050     assert((dops[i].opcode&0x3f)!=0x17);
6051   }
6052   assert(dops[i].opcode!=1); // BLTZ/BGEZ
6053
6054   //FIXME: Check CSREG
6055   if(dops[i].opcode==0x11 && dops[i].opcode2==0x08 ) {
6056     if((source[i]&0x30000)==0) // BC1F
6057     {
6058       emit_mov2imm_compact(ba[i],addr,start+i*4+8,alt);
6059       emit_testimm(s1l,0x800000);
6060       emit_cmovne_reg(alt,addr);
6061     }
6062     if((source[i]&0x30000)==0x10000) // BC1T
6063     {
6064       emit_mov2imm_compact(ba[i],alt,start+i*4+8,addr);
6065       emit_testimm(s1l,0x800000);
6066       emit_cmovne_reg(alt,addr);
6067     }
6068     if((source[i]&0x30000)==0x20000) // BC1FL
6069     {
6070       emit_testimm(s1l,0x800000);
6071       nottaken=out;
6072       emit_jne(0);
6073     }
6074     if((source[i]&0x30000)==0x30000) // BC1TL
6075     {
6076       emit_testimm(s1l,0x800000);
6077       nottaken=out;
6078       emit_jeq(0);
6079     }
6080   }
6081
6082   assert(i_regs->regmap[HOST_CCREG]==CCREG);
6083   wb_dirtys(regs[i].regmap,regs[i].dirty);
6084   if(unconditional)
6085   {
6086     emit_movimm(ba[i],HOST_BTREG);
6087   }
6088   else if(addr!=HOST_BTREG)
6089   {
6090     emit_mov(addr,HOST_BTREG);
6091   }
6092   void *branch_addr=out;
6093   emit_jmp(0);
6094   int target_addr=start+i*4+5;
6095   void *stub=out;
6096   void *compiled_target_addr=check_addr(target_addr);
6097   emit_extjump_ds(branch_addr, target_addr);
6098   if(compiled_target_addr) {
6099     set_jump_target(branch_addr, compiled_target_addr);
6100     add_jump_out(target_addr,stub);
6101   }
6102   else set_jump_target(branch_addr, stub);
6103 }
6104
6105 // Assemble the delay slot for the above
6106 static void pagespan_ds()
6107 {
6108   assem_debug("initial delay slot:\n");
6109   u_int vaddr=start+1;
6110   u_int page=get_page(vaddr);
6111   u_int vpage=get_vpage(vaddr);
6112   ll_add(jump_dirty+vpage,vaddr,(void *)out);
6113   do_dirty_stub_ds(slen*4);
6114   ll_add(jump_in+page,vaddr,(void *)out);
6115   assert(regs[0].regmap_entry[HOST_CCREG]==CCREG);
6116   if(regs[0].regmap[HOST_CCREG]!=CCREG)
6117     wb_register(CCREG,regs[0].regmap_entry,regs[0].wasdirty);
6118   if(regs[0].regmap[HOST_BTREG]!=BTREG)
6119     emit_writeword(HOST_BTREG,&branch_target);
6120   load_regs(regs[0].regmap_entry,regs[0].regmap,dops[0].rs1,dops[0].rs2);
6121   address_generation(0,&regs[0],regs[0].regmap_entry);
6122   if (ram_offset && (dops[0].is_load || dops[0].is_store))
6123     load_regs(regs[0].regmap_entry,regs[0].regmap,ROREG,ROREG);
6124   if (dops[0].is_store)
6125     load_regs(regs[0].regmap_entry,regs[0].regmap,INVCP,INVCP);
6126   is_delayslot=0;
6127   switch (dops[0].itype) {
6128     case SYSCALL:
6129     case HLECALL:
6130     case INTCALL:
6131     case SPAN:
6132     case UJUMP:
6133     case RJUMP:
6134     case CJUMP:
6135     case SJUMP:
6136       SysPrintf("Jump in the delay slot.  This is probably a bug.\n");
6137       break;
6138     default:
6139       assemble(0, &regs[0], 0);
6140   }
6141   int btaddr=get_reg(regs[0].regmap,BTREG);
6142   if(btaddr<0) {
6143     btaddr=get_reg_temp(regs[0].regmap);
6144     emit_readword(&branch_target,btaddr);
6145   }
6146   assert(btaddr!=HOST_CCREG);
6147   if(regs[0].regmap[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
6148 #ifdef HOST_IMM8
6149   host_tempreg_acquire();
6150   emit_movimm(start+4,HOST_TEMPREG);
6151   emit_cmp(btaddr,HOST_TEMPREG);
6152   host_tempreg_release();
6153 #else
6154   emit_cmpimm(btaddr,start+4);
6155 #endif
6156   void *branch = out;
6157   emit_jeq(0);
6158   store_regs_bt(regs[0].regmap,regs[0].dirty,-1);
6159   do_jump_vaddr(btaddr);
6160   set_jump_target(branch, out);
6161   store_regs_bt(regs[0].regmap,regs[0].dirty,start+4);
6162   load_regs_bt(regs[0].regmap,regs[0].dirty,start+4);
6163 }
6164
6165 static void check_regmap(signed char *regmap)
6166 {
6167 #ifndef NDEBUG
6168   int i,j;
6169   for (i = 0; i < HOST_REGS; i++) {
6170     if (regmap[i] < 0)
6171       continue;
6172     for (j = i + 1; j < HOST_REGS; j++)
6173       assert(regmap[i] != regmap[j]);
6174   }
6175 #endif
6176 }
6177
6178 // Basic liveness analysis for MIPS registers
6179 static void unneeded_registers(int istart,int iend,int r)
6180 {
6181   int i;
6182   uint64_t u,gte_u,b,gte_b;
6183   uint64_t temp_u,temp_gte_u=0;
6184   uint64_t gte_u_unknown=0;
6185   if (HACK_ENABLED(NDHACK_GTE_UNNEEDED))
6186     gte_u_unknown=~0ll;
6187   if(iend==slen-1) {
6188     u=1;
6189     gte_u=gte_u_unknown;
6190   }else{
6191     //u=unneeded_reg[iend+1];
6192     u=1;
6193     gte_u=gte_unneeded[iend+1];
6194   }
6195
6196   for (i=iend;i>=istart;i--)
6197   {
6198     //printf("unneeded registers i=%d (%d,%d) r=%d\n",i,istart,iend,r);
6199     if(dops[i].is_jump)
6200     {
6201       // If subroutine call, flag return address as a possible branch target
6202       if(dops[i].rt1==31 && i<slen-2) dops[i+2].bt=1;
6203
6204       if(ba[i]<start || ba[i]>=(start+slen*4))
6205       {
6206         // Branch out of this block, flush all regs
6207         u=1;
6208         gte_u=gte_u_unknown;
6209         branch_unneeded_reg[i]=u;
6210         // Merge in delay slot
6211         u|=(1LL<<dops[i+1].rt1)|(1LL<<dops[i+1].rt2);
6212         u&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
6213         u|=1;
6214         gte_u|=gte_rt[i+1];
6215         gte_u&=~gte_rs[i+1];
6216       }
6217       else
6218       {
6219         // Internal branch, flag target
6220         dops[(ba[i]-start)>>2].bt=1;
6221         if(ba[i]<=start+i*4) {
6222           // Backward branch
6223           if(dops[i].is_ujump)
6224           {
6225             // Unconditional branch
6226             temp_u=1;
6227             temp_gte_u=0;
6228           } else {
6229             // Conditional branch (not taken case)
6230             temp_u=unneeded_reg[i+2];
6231             temp_gte_u&=gte_unneeded[i+2];
6232           }
6233           // Merge in delay slot
6234           temp_u|=(1LL<<dops[i+1].rt1)|(1LL<<dops[i+1].rt2);
6235           temp_u&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
6236           temp_u|=1;
6237           temp_gte_u|=gte_rt[i+1];
6238           temp_gte_u&=~gte_rs[i+1];
6239           temp_u|=(1LL<<dops[i].rt1)|(1LL<<dops[i].rt2);
6240           temp_u&=~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
6241           temp_u|=1;
6242           temp_gte_u|=gte_rt[i];
6243           temp_gte_u&=~gte_rs[i];
6244           unneeded_reg[i]=temp_u;
6245           gte_unneeded[i]=temp_gte_u;
6246           // Only go three levels deep.  This recursion can take an
6247           // excessive amount of time if there are a lot of nested loops.
6248           if(r<2) {
6249             unneeded_registers((ba[i]-start)>>2,i-1,r+1);
6250           }else{
6251             unneeded_reg[(ba[i]-start)>>2]=1;
6252             gte_unneeded[(ba[i]-start)>>2]=gte_u_unknown;
6253           }
6254         } /*else*/ if(1) {
6255           if (dops[i].is_ujump)
6256           {
6257             // Unconditional branch
6258             u=unneeded_reg[(ba[i]-start)>>2];
6259             gte_u=gte_unneeded[(ba[i]-start)>>2];
6260             branch_unneeded_reg[i]=u;
6261             // Merge in delay slot
6262             u|=(1LL<<dops[i+1].rt1)|(1LL<<dops[i+1].rt2);
6263             u&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
6264             u|=1;
6265             gte_u|=gte_rt[i+1];
6266             gte_u&=~gte_rs[i+1];
6267           } else {
6268             // Conditional branch
6269             b=unneeded_reg[(ba[i]-start)>>2];
6270             gte_b=gte_unneeded[(ba[i]-start)>>2];
6271             branch_unneeded_reg[i]=b;
6272             // Branch delay slot
6273             b|=(1LL<<dops[i+1].rt1)|(1LL<<dops[i+1].rt2);
6274             b&=~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
6275             b|=1;
6276             gte_b|=gte_rt[i+1];
6277             gte_b&=~gte_rs[i+1];
6278             u&=b;
6279             gte_u&=gte_b;
6280             if(i<slen-1) {
6281               branch_unneeded_reg[i]&=unneeded_reg[i+2];
6282             } else {
6283               branch_unneeded_reg[i]=1;
6284             }
6285           }
6286         }
6287       }
6288     }
6289     else if(dops[i].itype==SYSCALL||dops[i].itype==HLECALL||dops[i].itype==INTCALL)
6290     {
6291       // SYSCALL instruction (software interrupt)
6292       u=1;
6293     }
6294     else if(dops[i].itype==COP0 && (source[i]&0x3f)==0x18)
6295     {
6296       // ERET instruction (return from interrupt)
6297       u=1;
6298     }
6299     //u=1; // DEBUG
6300     // Written registers are unneeded
6301     u|=1LL<<dops[i].rt1;
6302     u|=1LL<<dops[i].rt2;
6303     gte_u|=gte_rt[i];
6304     // Accessed registers are needed
6305     u&=~(1LL<<dops[i].rs1);
6306     u&=~(1LL<<dops[i].rs2);
6307     gte_u&=~gte_rs[i];
6308     if(gte_rs[i]&&dops[i].rt1&&(unneeded_reg[i+1]&(1ll<<dops[i].rt1)))
6309       gte_u|=gte_rs[i]&gte_unneeded[i+1]; // MFC2/CFC2 to dead register, unneeded
6310     // Source-target dependencies
6311     // R0 is always unneeded
6312     u|=1;
6313     // Save it
6314     unneeded_reg[i]=u;
6315     gte_unneeded[i]=gte_u;
6316     /*
6317     printf("ur (%d,%d) %x: ",istart,iend,start+i*4);
6318     printf("U:");
6319     int r;
6320     for(r=1;r<=CCREG;r++) {
6321       if((unneeded_reg[i]>>r)&1) {
6322         if(r==HIREG) printf(" HI");
6323         else if(r==LOREG) printf(" LO");
6324         else printf(" r%d",r);
6325       }
6326     }
6327     printf("\n");
6328     */
6329   }
6330 }
6331
6332 // Write back dirty registers as soon as we will no longer modify them,
6333 // so that we don't end up with lots of writes at the branches.
6334 void clean_registers(int istart,int iend,int wr)
6335 {
6336   int i;
6337   int r;
6338   u_int will_dirty_i,will_dirty_next,temp_will_dirty;
6339   u_int wont_dirty_i,wont_dirty_next,temp_wont_dirty;
6340   if(iend==slen-1) {
6341     will_dirty_i=will_dirty_next=0;
6342     wont_dirty_i=wont_dirty_next=0;
6343   }else{
6344     will_dirty_i=will_dirty_next=will_dirty[iend+1];
6345     wont_dirty_i=wont_dirty_next=wont_dirty[iend+1];
6346   }
6347   for (i=iend;i>=istart;i--)
6348   {
6349     __builtin_prefetch(regs[i-1].regmap);
6350     if(dops[i].is_jump)
6351     {
6352       if(ba[i]<start || ba[i]>=(start+slen*4))
6353       {
6354         // Branch out of this block, flush all regs
6355         if (dops[i].is_ujump)
6356         {
6357           // Unconditional branch
6358           will_dirty_i=0;
6359           wont_dirty_i=0;
6360           // Merge in delay slot (will dirty)
6361           for(r=0;r<HOST_REGS;r++) {
6362             if(r!=EXCLUDE_REG) {
6363               if(branch_regs[i].regmap[r]==dops[i].rt1) will_dirty_i|=1<<r;
6364               if(branch_regs[i].regmap[r]==dops[i].rt2) will_dirty_i|=1<<r;
6365               if(branch_regs[i].regmap[r]==dops[i+1].rt1) will_dirty_i|=1<<r;
6366               if(branch_regs[i].regmap[r]==dops[i+1].rt2) will_dirty_i|=1<<r;
6367               if(branch_regs[i].regmap[r]>33) will_dirty_i&=~(1<<r);
6368               if(branch_regs[i].regmap[r]<=0) will_dirty_i&=~(1<<r);
6369               if(branch_regs[i].regmap[r]==CCREG) will_dirty_i|=1<<r;
6370               if(regs[i].regmap[r]==dops[i].rt1) will_dirty_i|=1<<r;
6371               if(regs[i].regmap[r]==dops[i].rt2) will_dirty_i|=1<<r;
6372               if(regs[i].regmap[r]==dops[i+1].rt1) will_dirty_i|=1<<r;
6373               if(regs[i].regmap[r]==dops[i+1].rt2) will_dirty_i|=1<<r;
6374               if(regs[i].regmap[r]>33) will_dirty_i&=~(1<<r);
6375               if(regs[i].regmap[r]<=0) will_dirty_i&=~(1<<r);
6376               if(regs[i].regmap[r]==CCREG) will_dirty_i|=1<<r;
6377             }
6378           }
6379         }
6380         else
6381         {
6382           // Conditional branch
6383           will_dirty_i=0;
6384           wont_dirty_i=wont_dirty_next;
6385           // Merge in delay slot (will dirty)
6386           for(r=0;r<HOST_REGS;r++) {
6387             if(r!=EXCLUDE_REG) {
6388               if (1) { // !dops[i].likely)
6389                 // Might not dirty if likely branch is not taken
6390                 if(branch_regs[i].regmap[r]==dops[i].rt1) will_dirty_i|=1<<r;
6391                 if(branch_regs[i].regmap[r]==dops[i].rt2) will_dirty_i|=1<<r;
6392                 if(branch_regs[i].regmap[r]==dops[i+1].rt1) will_dirty_i|=1<<r;
6393                 if(branch_regs[i].regmap[r]==dops[i+1].rt2) will_dirty_i|=1<<r;
6394                 if(branch_regs[i].regmap[r]>33) will_dirty_i&=~(1<<r);
6395                 if(branch_regs[i].regmap[r]==0) will_dirty_i&=~(1<<r);
6396                 if(branch_regs[i].regmap[r]==CCREG) will_dirty_i|=1<<r;
6397                 //if(regs[i].regmap[r]==dops[i].rt1) will_dirty_i|=1<<r;
6398                 //if(regs[i].regmap[r]==dops[i].rt2) will_dirty_i|=1<<r;
6399                 if(regs[i].regmap[r]==dops[i+1].rt1) will_dirty_i|=1<<r;
6400                 if(regs[i].regmap[r]==dops[i+1].rt2) will_dirty_i|=1<<r;
6401                 if(regs[i].regmap[r]>33) will_dirty_i&=~(1<<r);
6402                 if(regs[i].regmap[r]<=0) will_dirty_i&=~(1<<r);
6403                 if(regs[i].regmap[r]==CCREG) will_dirty_i|=1<<r;
6404               }
6405             }
6406           }
6407         }
6408         // Merge in delay slot (wont dirty)
6409         for(r=0;r<HOST_REGS;r++) {
6410           if(r!=EXCLUDE_REG) {
6411             if(regs[i].regmap[r]==dops[i].rt1) wont_dirty_i|=1<<r;
6412             if(regs[i].regmap[r]==dops[i].rt2) wont_dirty_i|=1<<r;
6413             if(regs[i].regmap[r]==dops[i+1].rt1) wont_dirty_i|=1<<r;
6414             if(regs[i].regmap[r]==dops[i+1].rt2) wont_dirty_i|=1<<r;
6415             if(regs[i].regmap[r]==CCREG) wont_dirty_i|=1<<r;
6416             if(branch_regs[i].regmap[r]==dops[i].rt1) wont_dirty_i|=1<<r;
6417             if(branch_regs[i].regmap[r]==dops[i].rt2) wont_dirty_i|=1<<r;
6418             if(branch_regs[i].regmap[r]==dops[i+1].rt1) wont_dirty_i|=1<<r;
6419             if(branch_regs[i].regmap[r]==dops[i+1].rt2) wont_dirty_i|=1<<r;
6420             if(branch_regs[i].regmap[r]==CCREG) wont_dirty_i|=1<<r;
6421           }
6422         }
6423         if(wr) {
6424           #ifndef DESTRUCTIVE_WRITEBACK
6425           branch_regs[i].dirty&=wont_dirty_i;
6426           #endif
6427           branch_regs[i].dirty|=will_dirty_i;
6428         }
6429       }
6430       else
6431       {
6432         // Internal branch
6433         if(ba[i]<=start+i*4) {
6434           // Backward branch
6435           if (dops[i].is_ujump)
6436           {
6437             // Unconditional branch
6438             temp_will_dirty=0;
6439             temp_wont_dirty=0;
6440             // Merge in delay slot (will dirty)
6441             for(r=0;r<HOST_REGS;r++) {
6442               if(r!=EXCLUDE_REG) {
6443                 if(branch_regs[i].regmap[r]==dops[i].rt1) temp_will_dirty|=1<<r;
6444                 if(branch_regs[i].regmap[r]==dops[i].rt2) temp_will_dirty|=1<<r;
6445                 if(branch_regs[i].regmap[r]==dops[i+1].rt1) temp_will_dirty|=1<<r;
6446                 if(branch_regs[i].regmap[r]==dops[i+1].rt2) temp_will_dirty|=1<<r;
6447                 if(branch_regs[i].regmap[r]>33) temp_will_dirty&=~(1<<r);
6448                 if(branch_regs[i].regmap[r]<=0) temp_will_dirty&=~(1<<r);
6449                 if(branch_regs[i].regmap[r]==CCREG) temp_will_dirty|=1<<r;
6450                 if(regs[i].regmap[r]==dops[i].rt1) temp_will_dirty|=1<<r;
6451                 if(regs[i].regmap[r]==dops[i].rt2) temp_will_dirty|=1<<r;
6452                 if(regs[i].regmap[r]==dops[i+1].rt1) temp_will_dirty|=1<<r;
6453                 if(regs[i].regmap[r]==dops[i+1].rt2) temp_will_dirty|=1<<r;
6454                 if(regs[i].regmap[r]>33) temp_will_dirty&=~(1<<r);
6455                 if(regs[i].regmap[r]<=0) temp_will_dirty&=~(1<<r);
6456                 if(regs[i].regmap[r]==CCREG) temp_will_dirty|=1<<r;
6457               }
6458             }
6459           } else {
6460             // Conditional branch (not taken case)
6461             temp_will_dirty=will_dirty_next;
6462             temp_wont_dirty=wont_dirty_next;
6463             // Merge in delay slot (will dirty)
6464             for(r=0;r<HOST_REGS;r++) {
6465               if(r!=EXCLUDE_REG) {
6466                 if (1) { // !dops[i].likely)
6467                   // Will not dirty if likely branch is not taken
6468                   if(branch_regs[i].regmap[r]==dops[i].rt1) temp_will_dirty|=1<<r;
6469                   if(branch_regs[i].regmap[r]==dops[i].rt2) temp_will_dirty|=1<<r;
6470                   if(branch_regs[i].regmap[r]==dops[i+1].rt1) temp_will_dirty|=1<<r;
6471                   if(branch_regs[i].regmap[r]==dops[i+1].rt2) temp_will_dirty|=1<<r;
6472                   if(branch_regs[i].regmap[r]>33) temp_will_dirty&=~(1<<r);
6473                   if(branch_regs[i].regmap[r]==0) temp_will_dirty&=~(1<<r);
6474                   if(branch_regs[i].regmap[r]==CCREG) temp_will_dirty|=1<<r;
6475                   //if(regs[i].regmap[r]==dops[i].rt1) temp_will_dirty|=1<<r;
6476                   //if(regs[i].regmap[r]==dops[i].rt2) temp_will_dirty|=1<<r;
6477                   if(regs[i].regmap[r]==dops[i+1].rt1) temp_will_dirty|=1<<r;
6478                   if(regs[i].regmap[r]==dops[i+1].rt2) temp_will_dirty|=1<<r;
6479                   if(regs[i].regmap[r]>33) temp_will_dirty&=~(1<<r);
6480                   if(regs[i].regmap[r]<=0) temp_will_dirty&=~(1<<r);
6481                   if(regs[i].regmap[r]==CCREG) temp_will_dirty|=1<<r;
6482                 }
6483               }
6484             }
6485           }
6486           // Merge in delay slot (wont dirty)
6487           for(r=0;r<HOST_REGS;r++) {
6488             if(r!=EXCLUDE_REG) {
6489               if(regs[i].regmap[r]==dops[i].rt1) temp_wont_dirty|=1<<r;
6490               if(regs[i].regmap[r]==dops[i].rt2) temp_wont_dirty|=1<<r;
6491               if(regs[i].regmap[r]==dops[i+1].rt1) temp_wont_dirty|=1<<r;
6492               if(regs[i].regmap[r]==dops[i+1].rt2) temp_wont_dirty|=1<<r;
6493               if(regs[i].regmap[r]==CCREG) temp_wont_dirty|=1<<r;
6494               if(branch_regs[i].regmap[r]==dops[i].rt1) temp_wont_dirty|=1<<r;
6495               if(branch_regs[i].regmap[r]==dops[i].rt2) temp_wont_dirty|=1<<r;
6496               if(branch_regs[i].regmap[r]==dops[i+1].rt1) temp_wont_dirty|=1<<r;
6497               if(branch_regs[i].regmap[r]==dops[i+1].rt2) temp_wont_dirty|=1<<r;
6498               if(branch_regs[i].regmap[r]==CCREG) temp_wont_dirty|=1<<r;
6499             }
6500           }
6501           // Deal with changed mappings
6502           if(i<iend) {
6503             for(r=0;r<HOST_REGS;r++) {
6504               if(r!=EXCLUDE_REG) {
6505                 if(regs[i].regmap[r]!=regmap_pre[i][r]) {
6506                   temp_will_dirty&=~(1<<r);
6507                   temp_wont_dirty&=~(1<<r);
6508                   if(regmap_pre[i][r]>0 && regmap_pre[i][r]<34) {
6509                     temp_will_dirty|=((unneeded_reg[i]>>regmap_pre[i][r])&1)<<r;
6510                     temp_wont_dirty|=((unneeded_reg[i]>>regmap_pre[i][r])&1)<<r;
6511                   } else {
6512                     temp_will_dirty|=1<<r;
6513                     temp_wont_dirty|=1<<r;
6514                   }
6515                 }
6516               }
6517             }
6518           }
6519           if(wr) {
6520             will_dirty[i]=temp_will_dirty;
6521             wont_dirty[i]=temp_wont_dirty;
6522             clean_registers((ba[i]-start)>>2,i-1,0);
6523           }else{
6524             // Limit recursion.  It can take an excessive amount
6525             // of time if there are a lot of nested loops.
6526             will_dirty[(ba[i]-start)>>2]=0;
6527             wont_dirty[(ba[i]-start)>>2]=-1;
6528           }
6529         }
6530         /*else*/ if(1)
6531         {
6532           if (dops[i].is_ujump)
6533           {
6534             // Unconditional branch
6535             will_dirty_i=0;
6536             wont_dirty_i=0;
6537           //if(ba[i]>start+i*4) { // Disable recursion (for debugging)
6538             for(r=0;r<HOST_REGS;r++) {
6539               if(r!=EXCLUDE_REG) {
6540                 if(branch_regs[i].regmap[r]==regs[(ba[i]-start)>>2].regmap_entry[r]) {
6541                   will_dirty_i|=will_dirty[(ba[i]-start)>>2]&(1<<r);
6542                   wont_dirty_i|=wont_dirty[(ba[i]-start)>>2]&(1<<r);
6543                 }
6544                 if(branch_regs[i].regmap[r]>=0) {
6545                   will_dirty_i|=((unneeded_reg[(ba[i]-start)>>2]>>branch_regs[i].regmap[r])&1)<<r;
6546                   wont_dirty_i|=((unneeded_reg[(ba[i]-start)>>2]>>branch_regs[i].regmap[r])&1)<<r;
6547                 }
6548               }
6549             }
6550           //}
6551             // Merge in delay slot
6552             for(r=0;r<HOST_REGS;r++) {
6553               if(r!=EXCLUDE_REG) {
6554                 if(branch_regs[i].regmap[r]==dops[i].rt1) will_dirty_i|=1<<r;
6555                 if(branch_regs[i].regmap[r]==dops[i].rt2) will_dirty_i|=1<<r;
6556                 if(branch_regs[i].regmap[r]==dops[i+1].rt1) will_dirty_i|=1<<r;
6557                 if(branch_regs[i].regmap[r]==dops[i+1].rt2) will_dirty_i|=1<<r;
6558                 if(branch_regs[i].regmap[r]>33) will_dirty_i&=~(1<<r);
6559                 if(branch_regs[i].regmap[r]<=0) will_dirty_i&=~(1<<r);
6560                 if(branch_regs[i].regmap[r]==CCREG) will_dirty_i|=1<<r;
6561                 if(regs[i].regmap[r]==dops[i].rt1) will_dirty_i|=1<<r;
6562                 if(regs[i].regmap[r]==dops[i].rt2) will_dirty_i|=1<<r;
6563                 if(regs[i].regmap[r]==dops[i+1].rt1) will_dirty_i|=1<<r;
6564                 if(regs[i].regmap[r]==dops[i+1].rt2) will_dirty_i|=1<<r;
6565                 if(regs[i].regmap[r]>33) will_dirty_i&=~(1<<r);
6566                 if(regs[i].regmap[r]<=0) will_dirty_i&=~(1<<r);
6567                 if(regs[i].regmap[r]==CCREG) will_dirty_i|=1<<r;
6568               }
6569             }
6570           } else {
6571             // Conditional branch
6572             will_dirty_i=will_dirty_next;
6573             wont_dirty_i=wont_dirty_next;
6574           //if(ba[i]>start+i*4) // Disable recursion (for debugging)
6575             for(r=0;r<HOST_REGS;r++) {
6576               if(r!=EXCLUDE_REG) {
6577                 signed char target_reg=branch_regs[i].regmap[r];
6578                 if(target_reg==regs[(ba[i]-start)>>2].regmap_entry[r]) {
6579                   will_dirty_i&=will_dirty[(ba[i]-start)>>2]&(1<<r);
6580                   wont_dirty_i|=wont_dirty[(ba[i]-start)>>2]&(1<<r);
6581                 }
6582                 else if(target_reg>=0) {
6583                   will_dirty_i&=((unneeded_reg[(ba[i]-start)>>2]>>target_reg)&1)<<r;
6584                   wont_dirty_i|=((unneeded_reg[(ba[i]-start)>>2]>>target_reg)&1)<<r;
6585                 }
6586               }
6587             }
6588             // Merge in delay slot
6589             for(r=0;r<HOST_REGS;r++) {
6590               if(r!=EXCLUDE_REG) {
6591                 if (1) { // !dops[i].likely)
6592                   // Might not dirty if likely branch is not taken
6593                   if(branch_regs[i].regmap[r]==dops[i].rt1) will_dirty_i|=1<<r;
6594                   if(branch_regs[i].regmap[r]==dops[i].rt2) will_dirty_i|=1<<r;
6595                   if(branch_regs[i].regmap[r]==dops[i+1].rt1) will_dirty_i|=1<<r;
6596                   if(branch_regs[i].regmap[r]==dops[i+1].rt2) will_dirty_i|=1<<r;
6597                   if(branch_regs[i].regmap[r]>33) will_dirty_i&=~(1<<r);
6598                   if(branch_regs[i].regmap[r]<=0) will_dirty_i&=~(1<<r);
6599                   if(branch_regs[i].regmap[r]==CCREG) will_dirty_i|=1<<r;
6600                   //if(regs[i].regmap[r]==dops[i].rt1) will_dirty_i|=1<<r;
6601                   //if(regs[i].regmap[r]==dops[i].rt2) will_dirty_i|=1<<r;
6602                   if(regs[i].regmap[r]==dops[i+1].rt1) will_dirty_i|=1<<r;
6603                   if(regs[i].regmap[r]==dops[i+1].rt2) will_dirty_i|=1<<r;
6604                   if(regs[i].regmap[r]>33) will_dirty_i&=~(1<<r);
6605                   if(regs[i].regmap[r]<=0) will_dirty_i&=~(1<<r);
6606                   if(regs[i].regmap[r]==CCREG) will_dirty_i|=1<<r;
6607                 }
6608               }
6609             }
6610           }
6611           // Merge in delay slot (won't dirty)
6612           for(r=0;r<HOST_REGS;r++) {
6613             if(r!=EXCLUDE_REG) {
6614               if(regs[i].regmap[r]==dops[i].rt1) wont_dirty_i|=1<<r;
6615               if(regs[i].regmap[r]==dops[i].rt2) wont_dirty_i|=1<<r;
6616               if(regs[i].regmap[r]==dops[i+1].rt1) wont_dirty_i|=1<<r;
6617               if(regs[i].regmap[r]==dops[i+1].rt2) wont_dirty_i|=1<<r;
6618               if(regs[i].regmap[r]==CCREG) wont_dirty_i|=1<<r;
6619               if(branch_regs[i].regmap[r]==dops[i].rt1) wont_dirty_i|=1<<r;
6620               if(branch_regs[i].regmap[r]==dops[i].rt2) wont_dirty_i|=1<<r;
6621               if(branch_regs[i].regmap[r]==dops[i+1].rt1) wont_dirty_i|=1<<r;
6622               if(branch_regs[i].regmap[r]==dops[i+1].rt2) wont_dirty_i|=1<<r;
6623               if(branch_regs[i].regmap[r]==CCREG) wont_dirty_i|=1<<r;
6624             }
6625           }
6626           if(wr) {
6627             #ifndef DESTRUCTIVE_WRITEBACK
6628             branch_regs[i].dirty&=wont_dirty_i;
6629             #endif
6630             branch_regs[i].dirty|=will_dirty_i;
6631           }
6632         }
6633       }
6634     }
6635     else if(dops[i].itype==SYSCALL||dops[i].itype==HLECALL||dops[i].itype==INTCALL)
6636     {
6637       // SYSCALL instruction (software interrupt)
6638       will_dirty_i=0;
6639       wont_dirty_i=0;
6640     }
6641     else if(dops[i].itype==COP0 && (source[i]&0x3f)==0x18)
6642     {
6643       // ERET instruction (return from interrupt)
6644       will_dirty_i=0;
6645       wont_dirty_i=0;
6646     }
6647     will_dirty_next=will_dirty_i;
6648     wont_dirty_next=wont_dirty_i;
6649     for(r=0;r<HOST_REGS;r++) {
6650       if(r!=EXCLUDE_REG) {
6651         if(regs[i].regmap[r]==dops[i].rt1) will_dirty_i|=1<<r;
6652         if(regs[i].regmap[r]==dops[i].rt2) will_dirty_i|=1<<r;
6653         if(regs[i].regmap[r]>33) will_dirty_i&=~(1<<r);
6654         if(regs[i].regmap[r]<=0) will_dirty_i&=~(1<<r);
6655         if(regs[i].regmap[r]==CCREG) will_dirty_i|=1<<r;
6656         if(regs[i].regmap[r]==dops[i].rt1) wont_dirty_i|=1<<r;
6657         if(regs[i].regmap[r]==dops[i].rt2) wont_dirty_i|=1<<r;
6658         if(regs[i].regmap[r]==CCREG) wont_dirty_i|=1<<r;
6659         if(i>istart) {
6660           if (!dops[i].is_jump)
6661           {
6662             // Don't store a register immediately after writing it,
6663             // may prevent dual-issue.
6664             if(regs[i].regmap[r]==dops[i-1].rt1) wont_dirty_i|=1<<r;
6665             if(regs[i].regmap[r]==dops[i-1].rt2) wont_dirty_i|=1<<r;
6666           }
6667         }
6668       }
6669     }
6670     // Save it
6671     will_dirty[i]=will_dirty_i;
6672     wont_dirty[i]=wont_dirty_i;
6673     // Mark registers that won't be dirtied as not dirty
6674     if(wr) {
6675         regs[i].dirty|=will_dirty_i;
6676         #ifndef DESTRUCTIVE_WRITEBACK
6677         regs[i].dirty&=wont_dirty_i;
6678         if(dops[i].is_jump)
6679         {
6680           if (i < iend-1 && !dops[i].is_ujump) {
6681             for(r=0;r<HOST_REGS;r++) {
6682               if(r!=EXCLUDE_REG) {
6683                 if(regs[i].regmap[r]==regmap_pre[i+2][r]) {
6684                   regs[i+2].wasdirty&=wont_dirty_i|~(1<<r);
6685                 }else {/*printf("i: %x (%d) mismatch(+2): %d\n",start+i*4,i,r);assert(!((wont_dirty_i>>r)&1));*/}
6686               }
6687             }
6688           }
6689         }
6690         else
6691         {
6692           if(i<iend) {
6693             for(r=0;r<HOST_REGS;r++) {
6694               if(r!=EXCLUDE_REG) {
6695                 if(regs[i].regmap[r]==regmap_pre[i+1][r]) {
6696                   regs[i+1].wasdirty&=wont_dirty_i|~(1<<r);
6697                 }else {/*printf("i: %x (%d) mismatch(+1): %d\n",start+i*4,i,r);assert(!((wont_dirty_i>>r)&1));*/}
6698               }
6699             }
6700           }
6701         }
6702         #endif
6703     }
6704     // Deal with changed mappings
6705     temp_will_dirty=will_dirty_i;
6706     temp_wont_dirty=wont_dirty_i;
6707     for(r=0;r<HOST_REGS;r++) {
6708       if(r!=EXCLUDE_REG) {
6709         int nr;
6710         if(regs[i].regmap[r]==regmap_pre[i][r]) {
6711           if(wr) {
6712             #ifndef DESTRUCTIVE_WRITEBACK
6713             regs[i].wasdirty&=wont_dirty_i|~(1<<r);
6714             #endif
6715             regs[i].wasdirty|=will_dirty_i&(1<<r);
6716           }
6717         }
6718         else if(regmap_pre[i][r]>=0&&(nr=get_reg(regs[i].regmap,regmap_pre[i][r]))>=0) {
6719           // Register moved to a different register
6720           will_dirty_i&=~(1<<r);
6721           wont_dirty_i&=~(1<<r);
6722           will_dirty_i|=((temp_will_dirty>>nr)&1)<<r;
6723           wont_dirty_i|=((temp_wont_dirty>>nr)&1)<<r;
6724           if(wr) {
6725             #ifndef DESTRUCTIVE_WRITEBACK
6726             regs[i].wasdirty&=wont_dirty_i|~(1<<r);
6727             #endif
6728             regs[i].wasdirty|=will_dirty_i&(1<<r);
6729           }
6730         }
6731         else {
6732           will_dirty_i&=~(1<<r);
6733           wont_dirty_i&=~(1<<r);
6734           if(regmap_pre[i][r]>0 && regmap_pre[i][r]<34) {
6735             will_dirty_i|=((unneeded_reg[i]>>regmap_pre[i][r])&1)<<r;
6736             wont_dirty_i|=((unneeded_reg[i]>>regmap_pre[i][r])&1)<<r;
6737           } else {
6738             wont_dirty_i|=1<<r;
6739             /*printf("i: %x (%d) mismatch: %d\n",start+i*4,i,r);assert(!((will_dirty>>r)&1));*/
6740           }
6741         }
6742       }
6743     }
6744   }
6745 }
6746
6747 #ifdef DISASM
6748 #include <inttypes.h>
6749 void print_regmap(const char *name, const signed char *regmap)
6750 {
6751   char buf[5];
6752   int i, l;
6753   fputs(name, stdout);
6754   for (i = 0; i < HOST_REGS; i++) {
6755     l = 0;
6756     if (regmap[i] >= 0)
6757       l = snprintf(buf, sizeof(buf), "$%d", regmap[i]);
6758     for (; l < 3; l++)
6759       buf[l] = ' ';
6760     buf[l] = 0;
6761     printf(" r%d=%s", i, buf);
6762   }
6763   fputs("\n", stdout);
6764 }
6765
6766   /* disassembly */
6767 void disassemble_inst(int i)
6768 {
6769     if (dops[i].bt) printf("*"); else printf(" ");
6770     switch(dops[i].itype) {
6771       case UJUMP:
6772         printf (" %x: %s %8x\n",start+i*4,insn[i],ba[i]);break;
6773       case CJUMP:
6774         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;
6775       case SJUMP:
6776         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;
6777       case RJUMP:
6778         if (dops[i].opcode==0x9&&dops[i].rt1!=31)
6779           printf (" %x: %s r%d,r%d\n",start+i*4,insn[i],dops[i].rt1,dops[i].rs1);
6780         else
6781           printf (" %x: %s r%d\n",start+i*4,insn[i],dops[i].rs1);
6782         break;
6783       case SPAN:
6784         printf (" %x: %s (pagespan) r%d,r%d,%8x\n",start+i*4,insn[i],dops[i].rs1,dops[i].rs2,ba[i]);break;
6785       case IMM16:
6786         if(dops[i].opcode==0xf) //LUI
6787           printf (" %x: %s r%d,%4x0000\n",start+i*4,insn[i],dops[i].rt1,imm[i]&0xffff);
6788         else
6789           printf (" %x: %s r%d,r%d,%d\n",start+i*4,insn[i],dops[i].rt1,dops[i].rs1,imm[i]);
6790         break;
6791       case LOAD:
6792       case LOADLR:
6793         printf (" %x: %s r%d,r%d+%x\n",start+i*4,insn[i],dops[i].rt1,dops[i].rs1,imm[i]);
6794         break;
6795       case STORE:
6796       case STORELR:
6797         printf (" %x: %s r%d,r%d+%x\n",start+i*4,insn[i],dops[i].rs2,dops[i].rs1,imm[i]);
6798         break;
6799       case ALU:
6800       case SHIFT:
6801         printf (" %x: %s r%d,r%d,r%d\n",start+i*4,insn[i],dops[i].rt1,dops[i].rs1,dops[i].rs2);
6802         break;
6803       case MULTDIV:
6804         printf (" %x: %s r%d,r%d\n",start+i*4,insn[i],dops[i].rs1,dops[i].rs2);
6805         break;
6806       case SHIFTIMM:
6807         printf (" %x: %s r%d,r%d,%d\n",start+i*4,insn[i],dops[i].rt1,dops[i].rs1,imm[i]);
6808         break;
6809       case MOV:
6810         if((dops[i].opcode2&0x1d)==0x10)
6811           printf (" %x: %s r%d\n",start+i*4,insn[i],dops[i].rt1);
6812         else if((dops[i].opcode2&0x1d)==0x11)
6813           printf (" %x: %s r%d\n",start+i*4,insn[i],dops[i].rs1);
6814         else
6815           printf (" %x: %s\n",start+i*4,insn[i]);
6816         break;
6817       case COP0:
6818         if(dops[i].opcode2==0)
6819           printf (" %x: %s r%d,cpr0[%d]\n",start+i*4,insn[i],dops[i].rt1,(source[i]>>11)&0x1f); // MFC0
6820         else if(dops[i].opcode2==4)
6821           printf (" %x: %s r%d,cpr0[%d]\n",start+i*4,insn[i],dops[i].rs1,(source[i]>>11)&0x1f); // MTC0
6822         else printf (" %x: %s\n",start+i*4,insn[i]);
6823         break;
6824       case COP1:
6825         if(dops[i].opcode2<3)
6826           printf (" %x: %s r%d,cpr1[%d]\n",start+i*4,insn[i],dops[i].rt1,(source[i]>>11)&0x1f); // MFC1
6827         else if(dops[i].opcode2>3)
6828           printf (" %x: %s r%d,cpr1[%d]\n",start+i*4,insn[i],dops[i].rs1,(source[i]>>11)&0x1f); // MTC1
6829         else printf (" %x: %s\n",start+i*4,insn[i]);
6830         break;
6831       case COP2:
6832         if(dops[i].opcode2<3)
6833           printf (" %x: %s r%d,cpr2[%d]\n",start+i*4,insn[i],dops[i].rt1,(source[i]>>11)&0x1f); // MFC2
6834         else if(dops[i].opcode2>3)
6835           printf (" %x: %s r%d,cpr2[%d]\n",start+i*4,insn[i],dops[i].rs1,(source[i]>>11)&0x1f); // MTC2
6836         else printf (" %x: %s\n",start+i*4,insn[i]);
6837         break;
6838       case C1LS:
6839         printf (" %x: %s cpr1[%d],r%d+%x\n",start+i*4,insn[i],(source[i]>>16)&0x1f,dops[i].rs1,imm[i]);
6840         break;
6841       case C2LS:
6842         printf (" %x: %s cpr2[%d],r%d+%x\n",start+i*4,insn[i],(source[i]>>16)&0x1f,dops[i].rs1,imm[i]);
6843         break;
6844       case INTCALL:
6845         printf (" %x: %s (INTCALL)\n",start+i*4,insn[i]);
6846         break;
6847       default:
6848         //printf (" %s %8x\n",insn[i],source[i]);
6849         printf (" %x: %s\n",start+i*4,insn[i]);
6850     }
6851     return;
6852     printf("D: %"PRIu64"  WD: %"PRIu64"  U: %"PRIu64"\n",
6853       regs[i].dirty, regs[i].wasdirty, unneeded_reg[i]);
6854     print_regmap("pre:   ", regmap_pre[i]);
6855     print_regmap("entry: ", regs[i].regmap_entry);
6856     print_regmap("map:   ", regs[i].regmap);
6857     if (dops[i].is_jump) {
6858       print_regmap("bentry:", branch_regs[i].regmap_entry);
6859       print_regmap("bmap:  ", branch_regs[i].regmap);
6860     }
6861 }
6862 #else
6863 static void disassemble_inst(int i) {}
6864 #endif // DISASM
6865
6866 #define DRC_TEST_VAL 0x74657374
6867
6868 static void new_dynarec_test(void)
6869 {
6870   int (*testfunc)(void);
6871   void *beginning;
6872   int ret[2];
6873   size_t i;
6874
6875   // check structure linkage
6876   if ((u_char *)rcnts - (u_char *)&psxRegs != sizeof(psxRegs))
6877   {
6878     SysPrintf("linkage_arm* miscompilation/breakage detected.\n");
6879   }
6880
6881   SysPrintf("testing if we can run recompiled code @%p...\n", out);
6882   ((volatile u_int *)out)[0]++; // make cache dirty
6883
6884   for (i = 0; i < ARRAY_SIZE(ret); i++) {
6885     out = ndrc->translation_cache;
6886     beginning = start_block();
6887     emit_movimm(DRC_TEST_VAL + i, 0); // test
6888     emit_ret();
6889     literal_pool(0);
6890     end_block(beginning);
6891     testfunc = beginning;
6892     ret[i] = testfunc();
6893   }
6894
6895   if (ret[0] == DRC_TEST_VAL && ret[1] == DRC_TEST_VAL + 1)
6896     SysPrintf("test passed.\n");
6897   else
6898     SysPrintf("test failed, will likely crash soon (r=%08x %08x)\n", ret[0], ret[1]);
6899   out = ndrc->translation_cache;
6900 }
6901
6902 // clear the state completely, instead of just marking
6903 // things invalid like invalidate_all_pages() does
6904 void new_dynarec_clear_full(void)
6905 {
6906   int n;
6907   out = ndrc->translation_cache;
6908   memset(invalid_code,1,sizeof(invalid_code));
6909   memset(hash_table,0xff,sizeof(hash_table));
6910   memset(mini_ht,-1,sizeof(mini_ht));
6911   memset(restore_candidate,0,sizeof(restore_candidate));
6912   memset(shadow,0,sizeof(shadow));
6913   copy=shadow;
6914   expirep=16384; // Expiry pointer, +2 blocks
6915   pending_exception=0;
6916   literalcount=0;
6917   stop_after_jal=0;
6918   inv_code_start=inv_code_end=~0;
6919   hack_addr=0;
6920   f1_hack=0;
6921   // TLB
6922   for(n=0;n<4096;n++) ll_clear(jump_in+n);
6923   for(n=0;n<4096;n++) ll_clear(jump_out+n);
6924   for(n=0;n<4096;n++) ll_clear(jump_dirty+n);
6925
6926   cycle_multiplier_old = cycle_multiplier;
6927   new_dynarec_hacks_old = new_dynarec_hacks;
6928 }
6929
6930 void new_dynarec_init(void)
6931 {
6932   SysPrintf("Init new dynarec, ndrc size %x\n", (int)sizeof(*ndrc));
6933
6934 #ifdef _3DS
6935   check_rosalina();
6936 #endif
6937 #ifdef BASE_ADDR_DYNAMIC
6938   #ifdef VITA
6939   sceBlock = getVMBlock(); //sceKernelAllocMemBlockForVM("code", sizeof(*ndrc));
6940   if (sceBlock <= 0)
6941     SysPrintf("sceKernelAllocMemBlockForVM failed: %x\n", sceBlock);
6942   int ret = sceKernelGetMemBlockBase(sceBlock, (void **)&ndrc);
6943   if (ret < 0)
6944     SysPrintf("sceKernelGetMemBlockBase failed: %x\n", ret);
6945   sceKernelOpenVMDomain();
6946   sceClibPrintf("translation_cache = 0x%08lx\n ", (long)ndrc->translation_cache);
6947   #elif defined(_MSC_VER)
6948   ndrc = VirtualAlloc(NULL, sizeof(*ndrc), MEM_COMMIT | MEM_RESERVE,
6949     PAGE_EXECUTE_READWRITE);
6950   #else
6951   uintptr_t desired_addr = 0;
6952   #ifdef __ELF__
6953   extern char _end;
6954   desired_addr = ((uintptr_t)&_end + 0xffffff) & ~0xffffffl;
6955   #endif
6956   ndrc = mmap((void *)desired_addr, sizeof(*ndrc),
6957             PROT_READ | PROT_WRITE | PROT_EXEC,
6958             MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
6959   if (ndrc == MAP_FAILED) {
6960     SysPrintf("mmap() failed: %s\n", strerror(errno));
6961     abort();
6962   }
6963   #endif
6964 #else
6965   #ifndef NO_WRITE_EXEC
6966   // not all systems allow execute in data segment by default
6967   // size must be 4K aligned for 3DS?
6968   if (mprotect(ndrc, sizeof(*ndrc),
6969                PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
6970     SysPrintf("mprotect() failed: %s\n", strerror(errno));
6971   #endif
6972 #endif
6973   out = ndrc->translation_cache;
6974   cycle_multiplier=200;
6975   new_dynarec_clear_full();
6976 #ifdef HOST_IMM8
6977   // Copy this into local area so we don't have to put it in every literal pool
6978   invc_ptr=invalid_code;
6979 #endif
6980   arch_init();
6981   new_dynarec_test();
6982   ram_offset=(uintptr_t)rdram-0x80000000;
6983   if (ram_offset!=0)
6984     SysPrintf("warning: RAM is not directly mapped, performance will suffer\n");
6985 }
6986
6987 void new_dynarec_cleanup(void)
6988 {
6989   int n;
6990 #ifdef BASE_ADDR_DYNAMIC
6991   #ifdef VITA
6992   // sceBlock is managed by retroarch's bootstrap code
6993   //sceKernelFreeMemBlock(sceBlock);
6994   //sceBlock = -1;
6995   #else
6996   if (munmap(ndrc, sizeof(*ndrc)) < 0)
6997     SysPrintf("munmap() failed\n");
6998   #endif
6999 #endif
7000   for(n=0;n<4096;n++) ll_clear(jump_in+n);
7001   for(n=0;n<4096;n++) ll_clear(jump_out+n);
7002   for(n=0;n<4096;n++) ll_clear(jump_dirty+n);
7003   #ifdef ROM_COPY
7004   if (munmap (ROM_COPY, 67108864) < 0) {SysPrintf("munmap() failed\n");}
7005   #endif
7006 }
7007
7008 static u_int *get_source_start(u_int addr, u_int *limit)
7009 {
7010   if (addr < 0x00200000 ||
7011     (0xa0000000 <= addr && addr < 0xa0200000))
7012   {
7013     // used for BIOS calls mostly?
7014     *limit = (addr&0xa0000000)|0x00200000;
7015     return (u_int *)(rdram + (addr&0x1fffff));
7016   }
7017   else if (!Config.HLE && (
7018     /* (0x9fc00000 <= addr && addr < 0x9fc80000) ||*/
7019     (0xbfc00000 <= addr && addr < 0xbfc80000)))
7020   {
7021     // BIOS. The multiplier should be much higher as it's uncached 8bit mem,
7022     // but timings in PCSX are too tied to the interpreter's BIAS
7023     if (!HACK_ENABLED(NDHACK_OVERRIDE_CYCLE_M))
7024       cycle_multiplier_active = 200;
7025
7026     *limit = (addr & 0xfff00000) | 0x80000;
7027     return (u_int *)((u_char *)psxR + (addr&0x7ffff));
7028   }
7029   else if (addr >= 0x80000000 && addr < 0x80000000+RAM_SIZE) {
7030     *limit = (addr & 0x80600000) + 0x00200000;
7031     return (u_int *)(rdram + (addr&0x1fffff));
7032   }
7033   return NULL;
7034 }
7035
7036 static u_int scan_for_ret(u_int addr)
7037 {
7038   u_int limit = 0;
7039   u_int *mem;
7040
7041   mem = get_source_start(addr, &limit);
7042   if (mem == NULL)
7043     return addr;
7044
7045   if (limit > addr + 0x1000)
7046     limit = addr + 0x1000;
7047   for (; addr < limit; addr += 4, mem++) {
7048     if (*mem == 0x03e00008) // jr $ra
7049       return addr + 8;
7050   }
7051   return addr;
7052 }
7053
7054 struct savestate_block {
7055   uint32_t addr;
7056   uint32_t regflags;
7057 };
7058
7059 static int addr_cmp(const void *p1_, const void *p2_)
7060 {
7061   const struct savestate_block *p1 = p1_, *p2 = p2_;
7062   return p1->addr - p2->addr;
7063 }
7064
7065 int new_dynarec_save_blocks(void *save, int size)
7066 {
7067   struct savestate_block *blocks = save;
7068   int maxcount = size / sizeof(blocks[0]);
7069   struct savestate_block tmp_blocks[1024];
7070   struct ll_entry *head;
7071   int p, s, d, o, bcnt;
7072   u_int addr;
7073
7074   o = 0;
7075   for (p = 0; p < ARRAY_SIZE(jump_in); p++) {
7076     bcnt = 0;
7077     for (head = jump_in[p]; head != NULL; head = head->next) {
7078       tmp_blocks[bcnt].addr = head->vaddr;
7079       tmp_blocks[bcnt].regflags = head->reg_sv_flags;
7080       bcnt++;
7081     }
7082     if (bcnt < 1)
7083       continue;
7084     qsort(tmp_blocks, bcnt, sizeof(tmp_blocks[0]), addr_cmp);
7085
7086     addr = tmp_blocks[0].addr;
7087     for (s = d = 0; s < bcnt; s++) {
7088       if (tmp_blocks[s].addr < addr)
7089         continue;
7090       if (d == 0 || tmp_blocks[d-1].addr != tmp_blocks[s].addr)
7091         tmp_blocks[d++] = tmp_blocks[s];
7092       addr = scan_for_ret(tmp_blocks[s].addr);
7093     }
7094
7095     if (o + d > maxcount)
7096       d = maxcount - o;
7097     memcpy(&blocks[o], tmp_blocks, d * sizeof(blocks[0]));
7098     o += d;
7099   }
7100
7101   return o * sizeof(blocks[0]);
7102 }
7103
7104 void new_dynarec_load_blocks(const void *save, int size)
7105 {
7106   const struct savestate_block *blocks = save;
7107   int count = size / sizeof(blocks[0]);
7108   u_int regs_save[32];
7109   uint32_t f;
7110   int i, b;
7111
7112   get_addr(psxRegs.pc);
7113
7114   // change GPRs for speculation to at least partially work..
7115   memcpy(regs_save, &psxRegs.GPR, sizeof(regs_save));
7116   for (i = 1; i < 32; i++)
7117     psxRegs.GPR.r[i] = 0x80000000;
7118
7119   for (b = 0; b < count; b++) {
7120     for (f = blocks[b].regflags, i = 0; f; f >>= 1, i++) {
7121       if (f & 1)
7122         psxRegs.GPR.r[i] = 0x1f800000;
7123     }
7124
7125     get_addr(blocks[b].addr);
7126
7127     for (f = blocks[b].regflags, i = 0; f; f >>= 1, i++) {
7128       if (f & 1)
7129         psxRegs.GPR.r[i] = 0x80000000;
7130     }
7131   }
7132
7133   memcpy(&psxRegs.GPR, regs_save, sizeof(regs_save));
7134 }
7135
7136 static int apply_hacks(void)
7137 {
7138   int i;
7139   if (HACK_ENABLED(NDHACK_NO_COMPAT_HACKS))
7140     return 0;
7141   /* special hack(s) */
7142   for (i = 0; i < slen - 4; i++)
7143   {
7144     // lui a4, 0xf200; jal <rcnt_read>; addu a0, 2; slti v0, 28224
7145     if (source[i] == 0x3c04f200 && dops[i+1].itype == UJUMP
7146         && source[i+2] == 0x34840002 && dops[i+3].opcode == 0x0a
7147         && imm[i+3] == 0x6e40 && dops[i+3].rs1 == 2)
7148     {
7149       SysPrintf("PE2 hack @%08x\n", start + (i+3)*4);
7150       dops[i + 3].itype = NOP;
7151     }
7152   }
7153   i = slen;
7154   if (i > 10 && source[i-1] == 0 && source[i-2] == 0x03e00008
7155       && source[i-4] == 0x8fbf0018 && source[i-6] == 0x00c0f809
7156       && dops[i-7].itype == STORE)
7157   {
7158     i = i-8;
7159     if (dops[i].itype == IMM16)
7160       i--;
7161     // swl r2, 15(r6); swr r2, 12(r6); sw r6, *; jalr r6
7162     if (dops[i].itype == STORELR && dops[i].rs1 == 6
7163       && dops[i-1].itype == STORELR && dops[i-1].rs1 == 6)
7164     {
7165       SysPrintf("F1 hack from %08x, old dst %08x\n", start, hack_addr);
7166       f1_hack = 1;
7167       return 1;
7168     }
7169   }
7170   return 0;
7171 }
7172
7173 int new_recompile_block(u_int addr)
7174 {
7175   u_int pagelimit = 0;
7176   u_int state_rflags = 0;
7177   int i;
7178
7179   assem_debug("NOTCOMPILED: addr = %x -> %p\n", addr, out);
7180   //printf("TRACE: count=%d next=%d (compile %x)\n",Count,next_interupt,addr);
7181   //if(debug)
7182   //printf("fpu mapping=%x enabled=%x\n",(Status & 0x04000000)>>26,(Status & 0x20000000)>>29);
7183
7184   // this is just for speculation
7185   for (i = 1; i < 32; i++) {
7186     if ((psxRegs.GPR.r[i] & 0xffff0000) == 0x1f800000)
7187       state_rflags |= 1 << i;
7188   }
7189
7190   start = (u_int)addr&~3;
7191   //assert(((u_int)addr&1)==0); // start-in-delay-slot flag
7192   new_dynarec_did_compile=1;
7193   if (Config.HLE && start == 0x80001000) // hlecall
7194   {
7195     // XXX: is this enough? Maybe check hleSoftCall?
7196     void *beginning=start_block();
7197     u_int page=get_page(start);
7198
7199     invalid_code[start>>12]=0;
7200     emit_movimm(start,0);
7201     emit_writeword(0,&pcaddr);
7202     emit_far_jump(new_dyna_leave);
7203     literal_pool(0);
7204     end_block(beginning);
7205     ll_add_flags(jump_in+page,start,state_rflags,(void *)beginning);
7206     return 0;
7207   }
7208   else if (f1_hack && hack_addr == 0) {
7209     void *beginning = start_block();
7210     u_int page = get_page(start);
7211     emit_movimm(start, 0);
7212     emit_writeword(0, &hack_addr);
7213     emit_readword(&psxRegs.GPR.n.sp, 0);
7214     emit_readptr(&mem_rtab, 1);
7215     emit_shrimm(0, 12, 2);
7216     emit_readptr_dualindexedx_ptrlen(1, 2, 1);
7217     emit_addimm(0, 0x18, 0);
7218     emit_adds_ptr(1, 1, 1);
7219     emit_ldr_dualindexed(1, 0, 0);
7220     emit_writeword(0, &psxRegs.GPR.r[26]); // lw k0, 0x18(sp)
7221     emit_far_call(get_addr_ht);
7222     emit_jmpreg(0); // jr k0
7223     literal_pool(0);
7224     end_block(beginning);
7225
7226     ll_add_flags(jump_in + page, start, state_rflags, beginning);
7227     SysPrintf("F1 hack to   %08x\n", start);
7228     return 0;
7229   }
7230
7231   cycle_multiplier_active = cycle_multiplier_override && cycle_multiplier == CYCLE_MULT_DEFAULT
7232     ? cycle_multiplier_override : cycle_multiplier;
7233
7234   source = get_source_start(start, &pagelimit);
7235   if (source == NULL) {
7236     if (addr != hack_addr) {
7237       SysPrintf("Compile at bogus memory address: %08x\n", addr);
7238       hack_addr = addr;
7239     }
7240     //abort();
7241     return -1;
7242   }
7243
7244   /* Pass 1: disassemble */
7245   /* Pass 2: register dependencies, branch targets */
7246   /* Pass 3: register allocation */
7247   /* Pass 4: branch dependencies */
7248   /* Pass 5: pre-alloc */
7249   /* Pass 6: optimize clean/dirty state */
7250   /* Pass 7: flag 32-bit registers */
7251   /* Pass 8: assembly */
7252   /* Pass 9: linker */
7253   /* Pass 10: garbage collection / free memory */
7254
7255   int j;
7256   int done = 0, ni_count = 0;
7257   unsigned int type,op,op2;
7258
7259   //printf("addr = %x source = %x %x\n", addr,source,source[0]);
7260
7261   /* Pass 1 disassembly */
7262
7263   for (i = 0; !done; i++)
7264   {
7265     memset(&dops[i], 0, sizeof(dops[i]));
7266     op2=0;
7267     minimum_free_regs[i]=0;
7268     dops[i].opcode=op=source[i]>>26;
7269     switch(op)
7270     {
7271       case 0x00: strcpy(insn[i],"special"); type=NI;
7272         op2=source[i]&0x3f;
7273         switch(op2)
7274         {
7275           case 0x00: strcpy(insn[i],"SLL"); type=SHIFTIMM; break;
7276           case 0x02: strcpy(insn[i],"SRL"); type=SHIFTIMM; break;
7277           case 0x03: strcpy(insn[i],"SRA"); type=SHIFTIMM; break;
7278           case 0x04: strcpy(insn[i],"SLLV"); type=SHIFT; break;
7279           case 0x06: strcpy(insn[i],"SRLV"); type=SHIFT; break;
7280           case 0x07: strcpy(insn[i],"SRAV"); type=SHIFT; break;
7281           case 0x08: strcpy(insn[i],"JR"); type=RJUMP; break;
7282           case 0x09: strcpy(insn[i],"JALR"); type=RJUMP; break;
7283           case 0x0C: strcpy(insn[i],"SYSCALL"); type=SYSCALL; break;
7284           case 0x0D: strcpy(insn[i],"BREAK"); type=SYSCALL; break;
7285           case 0x0F: strcpy(insn[i],"SYNC"); type=OTHER; break;
7286           case 0x10: strcpy(insn[i],"MFHI"); type=MOV; break;
7287           case 0x11: strcpy(insn[i],"MTHI"); type=MOV; break;
7288           case 0x12: strcpy(insn[i],"MFLO"); type=MOV; break;
7289           case 0x13: strcpy(insn[i],"MTLO"); type=MOV; break;
7290           case 0x18: strcpy(insn[i],"MULT"); type=MULTDIV; break;
7291           case 0x19: strcpy(insn[i],"MULTU"); type=MULTDIV; break;
7292           case 0x1A: strcpy(insn[i],"DIV"); type=MULTDIV; break;
7293           case 0x1B: strcpy(insn[i],"DIVU"); type=MULTDIV; break;
7294           case 0x20: strcpy(insn[i],"ADD"); type=ALU; break;
7295           case 0x21: strcpy(insn[i],"ADDU"); type=ALU; break;
7296           case 0x22: strcpy(insn[i],"SUB"); type=ALU; break;
7297           case 0x23: strcpy(insn[i],"SUBU"); type=ALU; break;
7298           case 0x24: strcpy(insn[i],"AND"); type=ALU; break;
7299           case 0x25: strcpy(insn[i],"OR"); type=ALU; break;
7300           case 0x26: strcpy(insn[i],"XOR"); type=ALU; break;
7301           case 0x27: strcpy(insn[i],"NOR"); type=ALU; break;
7302           case 0x2A: strcpy(insn[i],"SLT"); type=ALU; break;
7303           case 0x2B: strcpy(insn[i],"SLTU"); type=ALU; break;
7304           case 0x30: strcpy(insn[i],"TGE"); type=NI; break;
7305           case 0x31: strcpy(insn[i],"TGEU"); type=NI; break;
7306           case 0x32: strcpy(insn[i],"TLT"); type=NI; break;
7307           case 0x33: strcpy(insn[i],"TLTU"); type=NI; break;
7308           case 0x34: strcpy(insn[i],"TEQ"); type=NI; break;
7309           case 0x36: strcpy(insn[i],"TNE"); type=NI; break;
7310 #if 0
7311           case 0x14: strcpy(insn[i],"DSLLV"); type=SHIFT; break;
7312           case 0x16: strcpy(insn[i],"DSRLV"); type=SHIFT; break;
7313           case 0x17: strcpy(insn[i],"DSRAV"); type=SHIFT; break;
7314           case 0x1C: strcpy(insn[i],"DMULT"); type=MULTDIV; break;
7315           case 0x1D: strcpy(insn[i],"DMULTU"); type=MULTDIV; break;
7316           case 0x1E: strcpy(insn[i],"DDIV"); type=MULTDIV; break;
7317           case 0x1F: strcpy(insn[i],"DDIVU"); type=MULTDIV; break;
7318           case 0x2C: strcpy(insn[i],"DADD"); type=ALU; break;
7319           case 0x2D: strcpy(insn[i],"DADDU"); type=ALU; break;
7320           case 0x2E: strcpy(insn[i],"DSUB"); type=ALU; break;
7321           case 0x2F: strcpy(insn[i],"DSUBU"); type=ALU; break;
7322           case 0x38: strcpy(insn[i],"DSLL"); type=SHIFTIMM; break;
7323           case 0x3A: strcpy(insn[i],"DSRL"); type=SHIFTIMM; break;
7324           case 0x3B: strcpy(insn[i],"DSRA"); type=SHIFTIMM; break;
7325           case 0x3C: strcpy(insn[i],"DSLL32"); type=SHIFTIMM; break;
7326           case 0x3E: strcpy(insn[i],"DSRL32"); type=SHIFTIMM; break;
7327           case 0x3F: strcpy(insn[i],"DSRA32"); type=SHIFTIMM; break;
7328 #endif
7329         }
7330         break;
7331       case 0x01: strcpy(insn[i],"regimm"); type=NI;
7332         op2=(source[i]>>16)&0x1f;
7333         switch(op2)
7334         {
7335           case 0x00: strcpy(insn[i],"BLTZ"); type=SJUMP; break;
7336           case 0x01: strcpy(insn[i],"BGEZ"); type=SJUMP; break;
7337           //case 0x02: strcpy(insn[i],"BLTZL"); type=SJUMP; break;
7338           //case 0x03: strcpy(insn[i],"BGEZL"); type=SJUMP; break;
7339           //case 0x08: strcpy(insn[i],"TGEI"); type=NI; break;
7340           //case 0x09: strcpy(insn[i],"TGEIU"); type=NI; break;
7341           //case 0x0A: strcpy(insn[i],"TLTI"); type=NI; break;
7342           //case 0x0B: strcpy(insn[i],"TLTIU"); type=NI; break;
7343           //case 0x0C: strcpy(insn[i],"TEQI"); type=NI; break;
7344           //case 0x0E: strcpy(insn[i],"TNEI"); type=NI; break;
7345           case 0x10: strcpy(insn[i],"BLTZAL"); type=SJUMP; break;
7346           case 0x11: strcpy(insn[i],"BGEZAL"); type=SJUMP; break;
7347           //case 0x12: strcpy(insn[i],"BLTZALL"); type=SJUMP; break;
7348           //case 0x13: strcpy(insn[i],"BGEZALL"); type=SJUMP; break;
7349         }
7350         break;
7351       case 0x02: strcpy(insn[i],"J"); type=UJUMP; break;
7352       case 0x03: strcpy(insn[i],"JAL"); type=UJUMP; break;
7353       case 0x04: strcpy(insn[i],"BEQ"); type=CJUMP; break;
7354       case 0x05: strcpy(insn[i],"BNE"); type=CJUMP; break;
7355       case 0x06: strcpy(insn[i],"BLEZ"); type=CJUMP; break;
7356       case 0x07: strcpy(insn[i],"BGTZ"); type=CJUMP; break;
7357       case 0x08: strcpy(insn[i],"ADDI"); type=IMM16; break;
7358       case 0x09: strcpy(insn[i],"ADDIU"); type=IMM16; break;
7359       case 0x0A: strcpy(insn[i],"SLTI"); type=IMM16; break;
7360       case 0x0B: strcpy(insn[i],"SLTIU"); type=IMM16; break;
7361       case 0x0C: strcpy(insn[i],"ANDI"); type=IMM16; break;
7362       case 0x0D: strcpy(insn[i],"ORI"); type=IMM16; break;
7363       case 0x0E: strcpy(insn[i],"XORI"); type=IMM16; break;
7364       case 0x0F: strcpy(insn[i],"LUI"); type=IMM16; break;
7365       case 0x10: strcpy(insn[i],"cop0"); type=NI;
7366         op2=(source[i]>>21)&0x1f;
7367         switch(op2)
7368         {
7369           case 0x00: strcpy(insn[i],"MFC0"); type=COP0; break;
7370           case 0x02: strcpy(insn[i],"CFC0"); type=COP0; break;
7371           case 0x04: strcpy(insn[i],"MTC0"); type=COP0; break;
7372           case 0x06: strcpy(insn[i],"CTC0"); type=COP0; break;
7373           case 0x10: strcpy(insn[i],"RFE"); type=COP0; break;
7374         }
7375         break;
7376       case 0x11: strcpy(insn[i],"cop1"); type=COP1;
7377         op2=(source[i]>>21)&0x1f;
7378         break;
7379 #if 0
7380       case 0x14: strcpy(insn[i],"BEQL"); type=CJUMP; break;
7381       case 0x15: strcpy(insn[i],"BNEL"); type=CJUMP; break;
7382       case 0x16: strcpy(insn[i],"BLEZL"); type=CJUMP; break;
7383       case 0x17: strcpy(insn[i],"BGTZL"); type=CJUMP; break;
7384       case 0x18: strcpy(insn[i],"DADDI"); type=IMM16; break;
7385       case 0x19: strcpy(insn[i],"DADDIU"); type=IMM16; break;
7386       case 0x1A: strcpy(insn[i],"LDL"); type=LOADLR; break;
7387       case 0x1B: strcpy(insn[i],"LDR"); type=LOADLR; break;
7388 #endif
7389       case 0x20: strcpy(insn[i],"LB"); type=LOAD; break;
7390       case 0x21: strcpy(insn[i],"LH"); type=LOAD; break;
7391       case 0x22: strcpy(insn[i],"LWL"); type=LOADLR; break;
7392       case 0x23: strcpy(insn[i],"LW"); type=LOAD; break;
7393       case 0x24: strcpy(insn[i],"LBU"); type=LOAD; break;
7394       case 0x25: strcpy(insn[i],"LHU"); type=LOAD; break;
7395       case 0x26: strcpy(insn[i],"LWR"); type=LOADLR; break;
7396 #if 0
7397       case 0x27: strcpy(insn[i],"LWU"); type=LOAD; break;
7398 #endif
7399       case 0x28: strcpy(insn[i],"SB"); type=STORE; break;
7400       case 0x29: strcpy(insn[i],"SH"); type=STORE; break;
7401       case 0x2A: strcpy(insn[i],"SWL"); type=STORELR; break;
7402       case 0x2B: strcpy(insn[i],"SW"); type=STORE; break;
7403 #if 0
7404       case 0x2C: strcpy(insn[i],"SDL"); type=STORELR; break;
7405       case 0x2D: strcpy(insn[i],"SDR"); type=STORELR; break;
7406 #endif
7407       case 0x2E: strcpy(insn[i],"SWR"); type=STORELR; break;
7408       case 0x2F: strcpy(insn[i],"CACHE"); type=NOP; break;
7409       case 0x30: strcpy(insn[i],"LL"); type=NI; break;
7410       case 0x31: strcpy(insn[i],"LWC1"); type=C1LS; break;
7411 #if 0
7412       case 0x34: strcpy(insn[i],"LLD"); type=NI; break;
7413       case 0x35: strcpy(insn[i],"LDC1"); type=C1LS; break;
7414       case 0x37: strcpy(insn[i],"LD"); type=LOAD; break;
7415 #endif
7416       case 0x38: strcpy(insn[i],"SC"); type=NI; break;
7417       case 0x39: strcpy(insn[i],"SWC1"); type=C1LS; break;
7418 #if 0
7419       case 0x3C: strcpy(insn[i],"SCD"); type=NI; break;
7420       case 0x3D: strcpy(insn[i],"SDC1"); type=C1LS; break;
7421       case 0x3F: strcpy(insn[i],"SD"); type=STORE; break;
7422 #endif
7423       case 0x12: strcpy(insn[i],"COP2"); type=NI;
7424         op2=(source[i]>>21)&0x1f;
7425         //if (op2 & 0x10)
7426         if (source[i]&0x3f) { // use this hack to support old savestates with patched gte insns
7427           if (gte_handlers[source[i]&0x3f]!=NULL) {
7428             if (gte_regnames[source[i]&0x3f]!=NULL)
7429               strcpy(insn[i],gte_regnames[source[i]&0x3f]);
7430             else
7431               snprintf(insn[i], sizeof(insn[i]), "COP2 %x", source[i]&0x3f);
7432             type=C2OP;
7433           }
7434         }
7435         else switch(op2)
7436         {
7437           case 0x00: strcpy(insn[i],"MFC2"); type=COP2; break;
7438           case 0x02: strcpy(insn[i],"CFC2"); type=COP2; break;
7439           case 0x04: strcpy(insn[i],"MTC2"); type=COP2; break;
7440           case 0x06: strcpy(insn[i],"CTC2"); type=COP2; break;
7441         }
7442         break;
7443       case 0x32: strcpy(insn[i],"LWC2"); type=C2LS; break;
7444       case 0x3A: strcpy(insn[i],"SWC2"); type=C2LS; break;
7445       case 0x3B: strcpy(insn[i],"HLECALL"); type=HLECALL; break;
7446       default: strcpy(insn[i],"???"); type=NI;
7447         SysPrintf("NI %08x @%08x (%08x)\n", source[i], addr + i*4, addr);
7448         break;
7449     }
7450     dops[i].itype=type;
7451     dops[i].opcode2=op2;
7452     /* Get registers/immediates */
7453     dops[i].lt1=0;
7454     gte_rs[i]=gte_rt[i]=0;
7455     switch(type) {
7456       case LOAD:
7457         dops[i].rs1=(source[i]>>21)&0x1f;
7458         dops[i].rs2=0;
7459         dops[i].rt1=(source[i]>>16)&0x1f;
7460         dops[i].rt2=0;
7461         imm[i]=(short)source[i];
7462         break;
7463       case STORE:
7464       case STORELR:
7465         dops[i].rs1=(source[i]>>21)&0x1f;
7466         dops[i].rs2=(source[i]>>16)&0x1f;
7467         dops[i].rt1=0;
7468         dops[i].rt2=0;
7469         imm[i]=(short)source[i];
7470         break;
7471       case LOADLR:
7472         // LWL/LWR only load part of the register,
7473         // therefore the target register must be treated as a source too
7474         dops[i].rs1=(source[i]>>21)&0x1f;
7475         dops[i].rs2=(source[i]>>16)&0x1f;
7476         dops[i].rt1=(source[i]>>16)&0x1f;
7477         dops[i].rt2=0;
7478         imm[i]=(short)source[i];
7479         break;
7480       case IMM16:
7481         if (op==0x0f) dops[i].rs1=0; // LUI instruction has no source register
7482         else dops[i].rs1=(source[i]>>21)&0x1f;
7483         dops[i].rs2=0;
7484         dops[i].rt1=(source[i]>>16)&0x1f;
7485         dops[i].rt2=0;
7486         if(op>=0x0c&&op<=0x0e) { // ANDI/ORI/XORI
7487           imm[i]=(unsigned short)source[i];
7488         }else{
7489           imm[i]=(short)source[i];
7490         }
7491         break;
7492       case UJUMP:
7493         dops[i].rs1=0;
7494         dops[i].rs2=0;
7495         dops[i].rt1=0;
7496         dops[i].rt2=0;
7497         // The JAL instruction writes to r31.
7498         if (op&1) {
7499           dops[i].rt1=31;
7500         }
7501         dops[i].rs2=CCREG;
7502         break;
7503       case RJUMP:
7504         dops[i].rs1=(source[i]>>21)&0x1f;
7505         dops[i].rs2=0;
7506         dops[i].rt1=0;
7507         dops[i].rt2=0;
7508         // The JALR instruction writes to rd.
7509         if (op2&1) {
7510           dops[i].rt1=(source[i]>>11)&0x1f;
7511         }
7512         dops[i].rs2=CCREG;
7513         break;
7514       case CJUMP:
7515         dops[i].rs1=(source[i]>>21)&0x1f;
7516         dops[i].rs2=(source[i]>>16)&0x1f;
7517         dops[i].rt1=0;
7518         dops[i].rt2=0;
7519         if(op&2) { // BGTZ/BLEZ
7520           dops[i].rs2=0;
7521         }
7522         break;
7523       case SJUMP:
7524         dops[i].rs1=(source[i]>>21)&0x1f;
7525         dops[i].rs2=CCREG;
7526         dops[i].rt1=0;
7527         dops[i].rt2=0;
7528         if(op2&0x10) { // BxxAL
7529           dops[i].rt1=31;
7530           // NOTE: If the branch is not taken, r31 is still overwritten
7531         }
7532         break;
7533       case ALU:
7534         dops[i].rs1=(source[i]>>21)&0x1f; // source
7535         dops[i].rs2=(source[i]>>16)&0x1f; // subtract amount
7536         dops[i].rt1=(source[i]>>11)&0x1f; // destination
7537         dops[i].rt2=0;
7538         break;
7539       case MULTDIV:
7540         dops[i].rs1=(source[i]>>21)&0x1f; // source
7541         dops[i].rs2=(source[i]>>16)&0x1f; // divisor
7542         dops[i].rt1=HIREG;
7543         dops[i].rt2=LOREG;
7544         break;
7545       case MOV:
7546         dops[i].rs1=0;
7547         dops[i].rs2=0;
7548         dops[i].rt1=0;
7549         dops[i].rt2=0;
7550         if(op2==0x10) dops[i].rs1=HIREG; // MFHI
7551         if(op2==0x11) dops[i].rt1=HIREG; // MTHI
7552         if(op2==0x12) dops[i].rs1=LOREG; // MFLO
7553         if(op2==0x13) dops[i].rt1=LOREG; // MTLO
7554         if((op2&0x1d)==0x10) dops[i].rt1=(source[i]>>11)&0x1f; // MFxx
7555         if((op2&0x1d)==0x11) dops[i].rs1=(source[i]>>21)&0x1f; // MTxx
7556         break;
7557       case SHIFT:
7558         dops[i].rs1=(source[i]>>16)&0x1f; // target of shift
7559         dops[i].rs2=(source[i]>>21)&0x1f; // shift amount
7560         dops[i].rt1=(source[i]>>11)&0x1f; // destination
7561         dops[i].rt2=0;
7562         break;
7563       case SHIFTIMM:
7564         dops[i].rs1=(source[i]>>16)&0x1f;
7565         dops[i].rs2=0;
7566         dops[i].rt1=(source[i]>>11)&0x1f;
7567         dops[i].rt2=0;
7568         imm[i]=(source[i]>>6)&0x1f;
7569         // DSxx32 instructions
7570         if(op2>=0x3c) imm[i]|=0x20;
7571         break;
7572       case COP0:
7573         dops[i].rs1=0;
7574         dops[i].rs2=0;
7575         dops[i].rt1=0;
7576         dops[i].rt2=0;
7577         if(op2==0||op2==2) dops[i].rt1=(source[i]>>16)&0x1F; // MFC0/CFC0
7578         if(op2==4||op2==6) dops[i].rs1=(source[i]>>16)&0x1F; // MTC0/CTC0
7579         if(op2==4&&((source[i]>>11)&0x1f)==12) dops[i].rt2=CSREG; // Status
7580         if(op2==16) if((source[i]&0x3f)==0x18) dops[i].rs2=CCREG; // ERET
7581         break;
7582       case COP1:
7583         dops[i].rs1=0;
7584         dops[i].rs2=0;
7585         dops[i].rt1=0;
7586         dops[i].rt2=0;
7587         if(op2<3) dops[i].rt1=(source[i]>>16)&0x1F; // MFC1/DMFC1/CFC1
7588         if(op2>3) dops[i].rs1=(source[i]>>16)&0x1F; // MTC1/DMTC1/CTC1
7589         dops[i].rs2=CSREG;
7590         break;
7591       case COP2:
7592         dops[i].rs1=0;
7593         dops[i].rs2=0;
7594         dops[i].rt1=0;
7595         dops[i].rt2=0;
7596         if(op2<3) dops[i].rt1=(source[i]>>16)&0x1F; // MFC2/CFC2
7597         if(op2>3) dops[i].rs1=(source[i]>>16)&0x1F; // MTC2/CTC2
7598         dops[i].rs2=CSREG;
7599         int gr=(source[i]>>11)&0x1F;
7600         switch(op2)
7601         {
7602           case 0x00: gte_rs[i]=1ll<<gr; break; // MFC2
7603           case 0x04: gte_rt[i]=1ll<<gr; break; // MTC2
7604           case 0x02: gte_rs[i]=1ll<<(gr+32); break; // CFC2
7605           case 0x06: gte_rt[i]=1ll<<(gr+32); break; // CTC2
7606         }
7607         break;
7608       case C1LS:
7609         dops[i].rs1=(source[i]>>21)&0x1F;
7610         dops[i].rs2=CSREG;
7611         dops[i].rt1=0;
7612         dops[i].rt2=0;
7613         imm[i]=(short)source[i];
7614         break;
7615       case C2LS:
7616         dops[i].rs1=(source[i]>>21)&0x1F;
7617         dops[i].rs2=0;
7618         dops[i].rt1=0;
7619         dops[i].rt2=0;
7620         imm[i]=(short)source[i];
7621         if(op==0x32) gte_rt[i]=1ll<<((source[i]>>16)&0x1F); // LWC2
7622         else gte_rs[i]=1ll<<((source[i]>>16)&0x1F); // SWC2
7623         break;
7624       case C2OP:
7625         dops[i].rs1=0;
7626         dops[i].rs2=0;
7627         dops[i].rt1=0;
7628         dops[i].rt2=0;
7629         gte_rs[i]=gte_reg_reads[source[i]&0x3f];
7630         gte_rt[i]=gte_reg_writes[source[i]&0x3f];
7631         gte_rt[i]|=1ll<<63; // every op changes flags
7632         if((source[i]&0x3f)==GTE_MVMVA) {
7633           int v = (source[i] >> 15) & 3;
7634           gte_rs[i]&=~0xe3fll;
7635           if(v==3) gte_rs[i]|=0xe00ll;
7636           else gte_rs[i]|=3ll<<(v*2);
7637         }
7638         break;
7639       case SYSCALL:
7640       case HLECALL:
7641       case INTCALL:
7642         dops[i].rs1=CCREG;
7643         dops[i].rs2=0;
7644         dops[i].rt1=0;
7645         dops[i].rt2=0;
7646         break;
7647       default:
7648         dops[i].rs1=0;
7649         dops[i].rs2=0;
7650         dops[i].rt1=0;
7651         dops[i].rt2=0;
7652     }
7653     /* Calculate branch target addresses */
7654     if(type==UJUMP)
7655       ba[i]=((start+i*4+4)&0xF0000000)|(((unsigned int)source[i]<<6)>>4);
7656     else if(type==CJUMP&&dops[i].rs1==dops[i].rs2&&(op&1))
7657       ba[i]=start+i*4+8; // Ignore never taken branch
7658     else if(type==SJUMP&&dops[i].rs1==0&&!(op2&1))
7659       ba[i]=start+i*4+8; // Ignore never taken branch
7660     else if(type==CJUMP||type==SJUMP)
7661       ba[i]=start+i*4+4+((signed int)((unsigned int)source[i]<<16)>>14);
7662     else ba[i]=-1;
7663
7664     /* simplify always (not)taken branches */
7665     if (type == CJUMP && dops[i].rs1 == dops[i].rs2) {
7666       dops[i].rs1 = dops[i].rs2 = 0;
7667       if (!(op & 1)) {
7668         dops[i].itype = type = UJUMP;
7669         dops[i].rs2 = CCREG;
7670       }
7671     }
7672     else if (type == SJUMP && dops[i].rs1 == 0 && (op2 & 1))
7673       dops[i].itype = type = UJUMP;
7674
7675     dops[i].is_jump = (dops[i].itype == RJUMP || dops[i].itype == UJUMP || dops[i].itype == CJUMP || dops[i].itype == SJUMP);
7676     dops[i].is_ujump = (dops[i].itype == RJUMP || dops[i].itype == UJUMP); // || (source[i] >> 16) == 0x1000 // beq r0,r0
7677     dops[i].is_load = (dops[i].itype == LOAD || dops[i].itype == LOADLR || op == 0x32); // LWC2
7678     dops[i].is_store = (dops[i].itype == STORE || dops[i].itype == STORELR || op == 0x3a); // SWC2
7679
7680     /* messy cases to just pass over to the interpreter */
7681     if (i > 0 && dops[i-1].is_jump) {
7682       int do_in_intrp=0;
7683       // branch in delay slot?
7684       if (dops[i].is_jump) {
7685         // don't handle first branch and call interpreter if it's hit
7686         SysPrintf("branch in delay slot @%08x (%08x)\n", addr + i*4, addr);
7687         do_in_intrp=1;
7688       }
7689       // basic load delay detection
7690       else if((type==LOAD||type==LOADLR||type==COP0||type==COP2||type==C2LS)&&dops[i].rt1!=0) {
7691         int t=(ba[i-1]-start)/4;
7692         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) {
7693           // jump target wants DS result - potential load delay effect
7694           SysPrintf("load delay @%08x (%08x)\n", addr + i*4, addr);
7695           do_in_intrp=1;
7696           dops[t+1].bt=1; // expected return from interpreter
7697         }
7698         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&&
7699               !(i>=3&&dops[i-3].is_jump)) {
7700           // v0 overwrite like this is a sign of trouble, bail out
7701           SysPrintf("v0 overwrite @%08x (%08x)\n", addr + i*4, addr);
7702           do_in_intrp=1;
7703         }
7704       }
7705       if (do_in_intrp) {
7706         memset(&dops[i-1], 0, sizeof(dops[i-1]));
7707         dops[i-1].itype = INTCALL;
7708         dops[i-1].rs1 = CCREG;
7709         ba[i-1] = -1;
7710         done = 2;
7711         i--; // don't compile the DS
7712       }
7713     }
7714
7715     /* Is this the end of the block? */
7716     if (i > 0 && dops[i-1].is_ujump) {
7717       if(dops[i-1].rt1==0) { // Continue past subroutine call (JAL)
7718         done=2;
7719       }
7720       else {
7721         if(stop_after_jal) done=1;
7722         // Stop on BREAK
7723         if((source[i+1]&0xfc00003f)==0x0d) done=1;
7724       }
7725       // Don't recompile stuff that's already compiled
7726       if(check_addr(start+i*4+4)) done=1;
7727       // Don't get too close to the limit
7728       if(i>MAXBLOCK/2) done=1;
7729     }
7730     if (dops[i].itype == SYSCALL || dops[i].itype == HLECALL || dops[i].itype == INTCALL)
7731       done = stop_after_jal ? 1 : 2;
7732     if (done == 2) {
7733       // Does the block continue due to a branch?
7734       for(j=i-1;j>=0;j--)
7735       {
7736         if(ba[j]==start+i*4) done=j=0; // Branch into delay slot
7737         if(ba[j]==start+i*4+4) done=j=0;
7738         if(ba[j]==start+i*4+8) done=j=0;
7739       }
7740     }
7741     //assert(i<MAXBLOCK-1);
7742     if(start+i*4==pagelimit-4) done=1;
7743     assert(start+i*4<pagelimit);
7744     if (i==MAXBLOCK-1) done=1;
7745     // Stop if we're compiling junk
7746     if(dops[i].itype == NI && (++ni_count > 8 || dops[i].opcode == 0x11)) {
7747       done=stop_after_jal=1;
7748       SysPrintf("Disabled speculative precompilation\n");
7749     }
7750   }
7751   slen=i;
7752   if (dops[i-1].is_jump) {
7753     if(start+i*4==pagelimit) {
7754       dops[i-1].itype=SPAN;
7755     }
7756   }
7757   assert(slen>0);
7758
7759   int clear_hack_addr = apply_hacks();
7760
7761   /* Pass 2 - Register dependencies and branch targets */
7762
7763   unneeded_registers(0,slen-1,0);
7764
7765   /* Pass 3 - Register allocation */
7766
7767   struct regstat current; // Current register allocations/status
7768   clear_all_regs(current.regmap_entry);
7769   clear_all_regs(current.regmap);
7770   current.wasdirty = current.dirty = 0;
7771   current.u = unneeded_reg[0];
7772   alloc_reg(&current, 0, CCREG);
7773   dirty_reg(&current, CCREG);
7774   current.wasconst = 0;
7775   current.isconst = 0;
7776   current.loadedconst = 0;
7777   current.waswritten = 0;
7778   int ds=0;
7779   int cc=0;
7780   int hr=-1;
7781
7782   if((u_int)addr&1) {
7783     // First instruction is delay slot
7784     cc=-1;
7785     dops[1].bt=1;
7786     ds=1;
7787     unneeded_reg[0]=1;
7788     current.regmap[HOST_BTREG]=BTREG;
7789   }
7790
7791   for(i=0;i<slen;i++)
7792   {
7793     if(dops[i].bt)
7794     {
7795       int hr;
7796       for(hr=0;hr<HOST_REGS;hr++)
7797       {
7798         // Is this really necessary?
7799         if(current.regmap[hr]==0) current.regmap[hr]=-1;
7800       }
7801       current.isconst=0;
7802       current.waswritten=0;
7803     }
7804
7805     memcpy(regmap_pre[i],current.regmap,sizeof(current.regmap));
7806     regs[i].wasconst=current.isconst;
7807     regs[i].wasdirty=current.dirty;
7808     regs[i].dirty=0;
7809     regs[i].u=0;
7810     regs[i].isconst=0;
7811     regs[i].loadedconst=0;
7812     if (!dops[i].is_jump) {
7813       if(i+1<slen) {
7814         current.u=unneeded_reg[i+1]&~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
7815         current.u|=1;
7816       } else {
7817         current.u=1;
7818       }
7819     } else {
7820       if(i+1<slen) {
7821         current.u=branch_unneeded_reg[i]&~((1LL<<dops[i+1].rs1)|(1LL<<dops[i+1].rs2));
7822         current.u&=~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
7823         current.u|=1;
7824       } else {
7825         SysPrintf("oops, branch at end of block with no delay slot @%08x\n", start + i*4);
7826         abort();
7827       }
7828     }
7829     dops[i].is_ds=ds;
7830     if(ds) {
7831       ds=0; // Skip delay slot, already allocated as part of branch
7832       // ...but we need to alloc it in case something jumps here
7833       if(i+1<slen) {
7834         current.u=branch_unneeded_reg[i-1]&unneeded_reg[i+1];
7835       }else{
7836         current.u=branch_unneeded_reg[i-1];
7837       }
7838       current.u&=~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
7839       current.u|=1;
7840       struct regstat temp;
7841       memcpy(&temp,&current,sizeof(current));
7842       temp.wasdirty=temp.dirty;
7843       // TODO: Take into account unconditional branches, as below
7844       delayslot_alloc(&temp,i);
7845       memcpy(regs[i].regmap,temp.regmap,sizeof(temp.regmap));
7846       regs[i].wasdirty=temp.wasdirty;
7847       regs[i].dirty=temp.dirty;
7848       regs[i].isconst=0;
7849       regs[i].wasconst=0;
7850       current.isconst=0;
7851       // Create entry (branch target) regmap
7852       for(hr=0;hr<HOST_REGS;hr++)
7853       {
7854         int r=temp.regmap[hr];
7855         if(r>=0) {
7856           if(r!=regmap_pre[i][hr]) {
7857             regs[i].regmap_entry[hr]=-1;
7858           }
7859           else
7860           {
7861               assert(r < 64);
7862               if((current.u>>r)&1) {
7863                 regs[i].regmap_entry[hr]=-1;
7864                 regs[i].regmap[hr]=-1;
7865                 //Don't clear regs in the delay slot as the branch might need them
7866                 //current.regmap[hr]=-1;
7867               }else
7868                 regs[i].regmap_entry[hr]=r;
7869           }
7870         } else {
7871           // First instruction expects CCREG to be allocated
7872           if(i==0&&hr==HOST_CCREG)
7873             regs[i].regmap_entry[hr]=CCREG;
7874           else
7875             regs[i].regmap_entry[hr]=-1;
7876         }
7877       }
7878     }
7879     else { // Not delay slot
7880       switch(dops[i].itype) {
7881         case UJUMP:
7882           //current.isconst=0; // DEBUG
7883           //current.wasconst=0; // DEBUG
7884           //regs[i].wasconst=0; // DEBUG
7885           clear_const(&current,dops[i].rt1);
7886           alloc_cc(&current,i);
7887           dirty_reg(&current,CCREG);
7888           if (dops[i].rt1==31) {
7889             alloc_reg(&current,i,31);
7890             dirty_reg(&current,31);
7891             //assert(dops[i+1].rs1!=31&&dops[i+1].rs2!=31);
7892             //assert(dops[i+1].rt1!=dops[i].rt1);
7893             #ifdef REG_PREFETCH
7894             alloc_reg(&current,i,PTEMP);
7895             #endif
7896           }
7897           dops[i].ooo=1;
7898           delayslot_alloc(&current,i+1);
7899           //current.isconst=0; // DEBUG
7900           ds=1;
7901           //printf("i=%d, isconst=%x\n",i,current.isconst);
7902           break;
7903         case RJUMP:
7904           //current.isconst=0;
7905           //current.wasconst=0;
7906           //regs[i].wasconst=0;
7907           clear_const(&current,dops[i].rs1);
7908           clear_const(&current,dops[i].rt1);
7909           alloc_cc(&current,i);
7910           dirty_reg(&current,CCREG);
7911           if (!ds_writes_rjump_rs(i)) {
7912             alloc_reg(&current,i,dops[i].rs1);
7913             if (dops[i].rt1!=0) {
7914               alloc_reg(&current,i,dops[i].rt1);
7915               dirty_reg(&current,dops[i].rt1);
7916               assert(dops[i+1].rs1!=dops[i].rt1&&dops[i+1].rs2!=dops[i].rt1);
7917               assert(dops[i+1].rt1!=dops[i].rt1);
7918               #ifdef REG_PREFETCH
7919               alloc_reg(&current,i,PTEMP);
7920               #endif
7921             }
7922             #ifdef USE_MINI_HT
7923             if(dops[i].rs1==31) { // JALR
7924               alloc_reg(&current,i,RHASH);
7925               alloc_reg(&current,i,RHTBL);
7926             }
7927             #endif
7928             delayslot_alloc(&current,i+1);
7929           } else {
7930             // The delay slot overwrites our source register,
7931             // allocate a temporary register to hold the old value.
7932             current.isconst=0;
7933             current.wasconst=0;
7934             regs[i].wasconst=0;
7935             delayslot_alloc(&current,i+1);
7936             current.isconst=0;
7937             alloc_reg(&current,i,RTEMP);
7938           }
7939           //current.isconst=0; // DEBUG
7940           dops[i].ooo=1;
7941           ds=1;
7942           break;
7943         case CJUMP:
7944           //current.isconst=0;
7945           //current.wasconst=0;
7946           //regs[i].wasconst=0;
7947           clear_const(&current,dops[i].rs1);
7948           clear_const(&current,dops[i].rs2);
7949           if((dops[i].opcode&0x3E)==4) // BEQ/BNE
7950           {
7951             alloc_cc(&current,i);
7952             dirty_reg(&current,CCREG);
7953             if(dops[i].rs1) alloc_reg(&current,i,dops[i].rs1);
7954             if(dops[i].rs2) alloc_reg(&current,i,dops[i].rs2);
7955             if((dops[i].rs1&&(dops[i].rs1==dops[i+1].rt1||dops[i].rs1==dops[i+1].rt2))||
7956                (dops[i].rs2&&(dops[i].rs2==dops[i+1].rt1||dops[i].rs2==dops[i+1].rt2))) {
7957               // The delay slot overwrites one of our conditions.
7958               // Allocate the branch condition registers instead.
7959               current.isconst=0;
7960               current.wasconst=0;
7961               regs[i].wasconst=0;
7962               if(dops[i].rs1) alloc_reg(&current,i,dops[i].rs1);
7963               if(dops[i].rs2) alloc_reg(&current,i,dops[i].rs2);
7964             }
7965             else
7966             {
7967               dops[i].ooo=1;
7968               delayslot_alloc(&current,i+1);
7969             }
7970           }
7971           else
7972           if((dops[i].opcode&0x3E)==6) // BLEZ/BGTZ
7973           {
7974             alloc_cc(&current,i);
7975             dirty_reg(&current,CCREG);
7976             alloc_reg(&current,i,dops[i].rs1);
7977             if(dops[i].rs1&&(dops[i].rs1==dops[i+1].rt1||dops[i].rs1==dops[i+1].rt2)) {
7978               // The delay slot overwrites one of our conditions.
7979               // Allocate the branch condition registers instead.
7980               current.isconst=0;
7981               current.wasconst=0;
7982               regs[i].wasconst=0;
7983               if(dops[i].rs1) alloc_reg(&current,i,dops[i].rs1);
7984             }
7985             else
7986             {
7987               dops[i].ooo=1;
7988               delayslot_alloc(&current,i+1);
7989             }
7990           }
7991           else
7992           // Don't alloc the delay slot yet because we might not execute it
7993           if((dops[i].opcode&0x3E)==0x14) // BEQL/BNEL
7994           {
7995             current.isconst=0;
7996             current.wasconst=0;
7997             regs[i].wasconst=0;
7998             alloc_cc(&current,i);
7999             dirty_reg(&current,CCREG);
8000             alloc_reg(&current,i,dops[i].rs1);
8001             alloc_reg(&current,i,dops[i].rs2);
8002           }
8003           else
8004           if((dops[i].opcode&0x3E)==0x16) // BLEZL/BGTZL
8005           {
8006             current.isconst=0;
8007             current.wasconst=0;
8008             regs[i].wasconst=0;
8009             alloc_cc(&current,i);
8010             dirty_reg(&current,CCREG);
8011             alloc_reg(&current,i,dops[i].rs1);
8012           }
8013           ds=1;
8014           //current.isconst=0;
8015           break;
8016         case SJUMP:
8017           //current.isconst=0;
8018           //current.wasconst=0;
8019           //regs[i].wasconst=0;
8020           clear_const(&current,dops[i].rs1);
8021           clear_const(&current,dops[i].rt1);
8022           //if((dops[i].opcode2&0x1E)==0x0) // BLTZ/BGEZ
8023           if((dops[i].opcode2&0x0E)==0x0) // BLTZ/BGEZ
8024           {
8025             alloc_cc(&current,i);
8026             dirty_reg(&current,CCREG);
8027             alloc_reg(&current,i,dops[i].rs1);
8028             if (dops[i].rt1==31) { // BLTZAL/BGEZAL
8029               alloc_reg(&current,i,31);
8030               dirty_reg(&current,31);
8031               //#ifdef REG_PREFETCH
8032               //alloc_reg(&current,i,PTEMP);
8033               //#endif
8034             }
8035             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.
8036                ||(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
8037               // Allocate the branch condition registers instead.
8038               current.isconst=0;
8039               current.wasconst=0;
8040               regs[i].wasconst=0;
8041               if(dops[i].rs1) alloc_reg(&current,i,dops[i].rs1);
8042             }
8043             else
8044             {
8045               dops[i].ooo=1;
8046               delayslot_alloc(&current,i+1);
8047             }
8048           }
8049           else
8050           // Don't alloc the delay slot yet because we might not execute it
8051           if((dops[i].opcode2&0x1E)==0x2) // BLTZL/BGEZL
8052           {
8053             current.isconst=0;
8054             current.wasconst=0;
8055             regs[i].wasconst=0;
8056             alloc_cc(&current,i);
8057             dirty_reg(&current,CCREG);
8058             alloc_reg(&current,i,dops[i].rs1);
8059           }
8060           ds=1;
8061           //current.isconst=0;
8062           break;
8063         case IMM16:
8064           imm16_alloc(&current,i);
8065           break;
8066         case LOAD:
8067         case LOADLR:
8068           load_alloc(&current,i);
8069           break;
8070         case STORE:
8071         case STORELR:
8072           store_alloc(&current,i);
8073           break;
8074         case ALU:
8075           alu_alloc(&current,i);
8076           break;
8077         case SHIFT:
8078           shift_alloc(&current,i);
8079           break;
8080         case MULTDIV:
8081           multdiv_alloc(&current,i);
8082           break;
8083         case SHIFTIMM:
8084           shiftimm_alloc(&current,i);
8085           break;
8086         case MOV:
8087           mov_alloc(&current,i);
8088           break;
8089         case COP0:
8090           cop0_alloc(&current,i);
8091           break;
8092         case COP1:
8093           break;
8094         case COP2:
8095           cop2_alloc(&current,i);
8096           break;
8097         case C1LS:
8098           c1ls_alloc(&current,i);
8099           break;
8100         case C2LS:
8101           c2ls_alloc(&current,i);
8102           break;
8103         case C2OP:
8104           c2op_alloc(&current,i);
8105           break;
8106         case SYSCALL:
8107         case HLECALL:
8108         case INTCALL:
8109           syscall_alloc(&current,i);
8110           break;
8111         case SPAN:
8112           pagespan_alloc(&current,i);
8113           break;
8114       }
8115
8116       // Create entry (branch target) regmap
8117       for(hr=0;hr<HOST_REGS;hr++)
8118       {
8119         int r,or;
8120         r=current.regmap[hr];
8121         if(r>=0) {
8122           if(r!=regmap_pre[i][hr]) {
8123             // TODO: delay slot (?)
8124             or=get_reg(regmap_pre[i],r); // Get old mapping for this register
8125             if(or<0||r>=TEMPREG){
8126               regs[i].regmap_entry[hr]=-1;
8127             }
8128             else
8129             {
8130               // Just move it to a different register
8131               regs[i].regmap_entry[hr]=r;
8132               // If it was dirty before, it's still dirty
8133               if((regs[i].wasdirty>>or)&1) dirty_reg(&current,r);
8134             }
8135           }
8136           else
8137           {
8138             // Unneeded
8139             if(r==0){
8140               regs[i].regmap_entry[hr]=0;
8141             }
8142             else
8143             {
8144               assert(r<64);
8145               if((current.u>>r)&1) {
8146                 regs[i].regmap_entry[hr]=-1;
8147                 //regs[i].regmap[hr]=-1;
8148                 current.regmap[hr]=-1;
8149               }else
8150                 regs[i].regmap_entry[hr]=r;
8151             }
8152           }
8153         } else {
8154           // Branches expect CCREG to be allocated at the target
8155           if(regmap_pre[i][hr]==CCREG)
8156             regs[i].regmap_entry[hr]=CCREG;
8157           else
8158             regs[i].regmap_entry[hr]=-1;
8159         }
8160       }
8161       memcpy(regs[i].regmap,current.regmap,sizeof(current.regmap));
8162     }
8163
8164     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)
8165       current.waswritten|=1<<dops[i-1].rs1;
8166     current.waswritten&=~(1<<dops[i].rt1);
8167     current.waswritten&=~(1<<dops[i].rt2);
8168     if((dops[i].itype==STORE||dops[i].itype==STORELR||(dops[i].itype==C2LS&&dops[i].opcode==0x3a))&&(u_int)imm[i]>=0x800)
8169       current.waswritten&=~(1<<dops[i].rs1);
8170
8171     /* Branch post-alloc */
8172     if(i>0)
8173     {
8174       current.wasdirty=current.dirty;
8175       switch(dops[i-1].itype) {
8176         case UJUMP:
8177           memcpy(&branch_regs[i-1],&current,sizeof(current));
8178           branch_regs[i-1].isconst=0;
8179           branch_regs[i-1].wasconst=0;
8180           branch_regs[i-1].u=branch_unneeded_reg[i-1]&~((1LL<<dops[i-1].rs1)|(1LL<<dops[i-1].rs2));
8181           alloc_cc(&branch_regs[i-1],i-1);
8182           dirty_reg(&branch_regs[i-1],CCREG);
8183           if(dops[i-1].rt1==31) { // JAL
8184             alloc_reg(&branch_regs[i-1],i-1,31);
8185             dirty_reg(&branch_regs[i-1],31);
8186           }
8187           memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
8188           memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
8189           break;
8190         case RJUMP:
8191           memcpy(&branch_regs[i-1],&current,sizeof(current));
8192           branch_regs[i-1].isconst=0;
8193           branch_regs[i-1].wasconst=0;
8194           branch_regs[i-1].u=branch_unneeded_reg[i-1]&~((1LL<<dops[i-1].rs1)|(1LL<<dops[i-1].rs2));
8195           alloc_cc(&branch_regs[i-1],i-1);
8196           dirty_reg(&branch_regs[i-1],CCREG);
8197           alloc_reg(&branch_regs[i-1],i-1,dops[i-1].rs1);
8198           if(dops[i-1].rt1!=0) { // JALR
8199             alloc_reg(&branch_regs[i-1],i-1,dops[i-1].rt1);
8200             dirty_reg(&branch_regs[i-1],dops[i-1].rt1);
8201           }
8202           #ifdef USE_MINI_HT
8203           if(dops[i-1].rs1==31) { // JALR
8204             alloc_reg(&branch_regs[i-1],i-1,RHASH);
8205             alloc_reg(&branch_regs[i-1],i-1,RHTBL);
8206           }
8207           #endif
8208           memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
8209           memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
8210           break;
8211         case CJUMP:
8212           if((dops[i-1].opcode&0x3E)==4) // BEQ/BNE
8213           {
8214             alloc_cc(&current,i-1);
8215             dirty_reg(&current,CCREG);
8216             if((dops[i-1].rs1&&(dops[i-1].rs1==dops[i].rt1||dops[i-1].rs1==dops[i].rt2))||
8217                (dops[i-1].rs2&&(dops[i-1].rs2==dops[i].rt1||dops[i-1].rs2==dops[i].rt2))) {
8218               // The delay slot overwrote one of our conditions
8219               // Delay slot goes after the test (in order)
8220               current.u=branch_unneeded_reg[i-1]&~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
8221               current.u|=1;
8222               delayslot_alloc(&current,i);
8223               current.isconst=0;
8224             }
8225             else
8226             {
8227               current.u=branch_unneeded_reg[i-1]&~((1LL<<dops[i-1].rs1)|(1LL<<dops[i-1].rs2));
8228               // Alloc the branch condition registers
8229               if(dops[i-1].rs1) alloc_reg(&current,i-1,dops[i-1].rs1);
8230               if(dops[i-1].rs2) alloc_reg(&current,i-1,dops[i-1].rs2);
8231             }
8232             memcpy(&branch_regs[i-1],&current,sizeof(current));
8233             branch_regs[i-1].isconst=0;
8234             branch_regs[i-1].wasconst=0;
8235             memcpy(&branch_regs[i-1].regmap_entry,&current.regmap,sizeof(current.regmap));
8236             memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
8237           }
8238           else
8239           if((dops[i-1].opcode&0x3E)==6) // BLEZ/BGTZ
8240           {
8241             alloc_cc(&current,i-1);
8242             dirty_reg(&current,CCREG);
8243             if(dops[i-1].rs1==dops[i].rt1||dops[i-1].rs1==dops[i].rt2) {
8244               // The delay slot overwrote the branch condition
8245               // Delay slot goes after the test (in order)
8246               current.u=branch_unneeded_reg[i-1]&~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
8247               current.u|=1;
8248               delayslot_alloc(&current,i);
8249               current.isconst=0;
8250             }
8251             else
8252             {
8253               current.u=branch_unneeded_reg[i-1]&~(1LL<<dops[i-1].rs1);
8254               // Alloc the branch condition register
8255               alloc_reg(&current,i-1,dops[i-1].rs1);
8256             }
8257             memcpy(&branch_regs[i-1],&current,sizeof(current));
8258             branch_regs[i-1].isconst=0;
8259             branch_regs[i-1].wasconst=0;
8260             memcpy(&branch_regs[i-1].regmap_entry,&current.regmap,sizeof(current.regmap));
8261             memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
8262           }
8263           else
8264           // Alloc the delay slot in case the branch is taken
8265           if((dops[i-1].opcode&0x3E)==0x14) // BEQL/BNEL
8266           {
8267             memcpy(&branch_regs[i-1],&current,sizeof(current));
8268             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;
8269             alloc_cc(&branch_regs[i-1],i);
8270             dirty_reg(&branch_regs[i-1],CCREG);
8271             delayslot_alloc(&branch_regs[i-1],i);
8272             branch_regs[i-1].isconst=0;
8273             alloc_reg(&current,i,CCREG); // Not taken path
8274             dirty_reg(&current,CCREG);
8275             memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
8276           }
8277           else
8278           if((dops[i-1].opcode&0x3E)==0x16) // BLEZL/BGTZL
8279           {
8280             memcpy(&branch_regs[i-1],&current,sizeof(current));
8281             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;
8282             alloc_cc(&branch_regs[i-1],i);
8283             dirty_reg(&branch_regs[i-1],CCREG);
8284             delayslot_alloc(&branch_regs[i-1],i);
8285             branch_regs[i-1].isconst=0;
8286             alloc_reg(&current,i,CCREG); // Not taken path
8287             dirty_reg(&current,CCREG);
8288             memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
8289           }
8290           break;
8291         case SJUMP:
8292           //if((dops[i-1].opcode2&0x1E)==0) // BLTZ/BGEZ
8293           if((dops[i-1].opcode2&0x0E)==0) // BLTZ/BGEZ
8294           {
8295             alloc_cc(&current,i-1);
8296             dirty_reg(&current,CCREG);
8297             if(dops[i-1].rs1==dops[i].rt1||dops[i-1].rs1==dops[i].rt2) {
8298               // The delay slot overwrote the branch condition
8299               // Delay slot goes after the test (in order)
8300               current.u=branch_unneeded_reg[i-1]&~((1LL<<dops[i].rs1)|(1LL<<dops[i].rs2));
8301               current.u|=1;
8302               delayslot_alloc(&current,i);
8303               current.isconst=0;
8304             }
8305             else
8306             {
8307               current.u=branch_unneeded_reg[i-1]&~(1LL<<dops[i-1].rs1);
8308               // Alloc the branch condition register
8309               alloc_reg(&current,i-1,dops[i-1].rs1);
8310             }
8311             memcpy(&branch_regs[i-1],&current,sizeof(current));
8312             branch_regs[i-1].isconst=0;
8313             branch_regs[i-1].wasconst=0;
8314             memcpy(&branch_regs[i-1].regmap_entry,&current.regmap,sizeof(current.regmap));
8315             memcpy(constmap[i],constmap[i-1],sizeof(constmap[i]));
8316           }
8317           else
8318           // Alloc the delay slot in case the branch is taken
8319           if((dops[i-1].opcode2&0x1E)==2) // BLTZL/BGEZL
8320           {
8321             memcpy(&branch_regs[i-1],&current,sizeof(current));
8322             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;
8323             alloc_cc(&branch_regs[i-1],i);
8324             dirty_reg(&branch_regs[i-1],CCREG);
8325             delayslot_alloc(&branch_regs[i-1],i);
8326             branch_regs[i-1].isconst=0;
8327             alloc_reg(&current,i,CCREG); // Not taken path
8328             dirty_reg(&current,CCREG);
8329             memcpy(&branch_regs[i-1].regmap_entry,&branch_regs[i-1].regmap,sizeof(current.regmap));
8330           }
8331           // FIXME: BLTZAL/BGEZAL
8332           if(dops[i-1].opcode2&0x10) { // BxxZAL
8333             alloc_reg(&branch_regs[i-1],i-1,31);
8334             dirty_reg(&branch_regs[i-1],31);
8335           }
8336           break;
8337       }
8338
8339       if (dops[i-1].is_ujump)
8340       {
8341         if(dops[i-1].rt1==31) // JAL/JALR
8342         {
8343           // Subroutine call will return here, don't alloc any registers
8344           current.dirty=0;
8345           clear_all_regs(current.regmap);
8346           alloc_reg(&current,i,CCREG);
8347           dirty_reg(&current,CCREG);
8348         }
8349         else if(i+1<slen)
8350         {
8351           // Internal branch will jump here, match registers to caller
8352           current.dirty=0;
8353           clear_all_regs(current.regmap);
8354           alloc_reg(&current,i,CCREG);
8355           dirty_reg(&current,CCREG);
8356           for(j=i-1;j>=0;j--)
8357           {
8358             if(ba[j]==start+i*4+4) {
8359               memcpy(current.regmap,branch_regs[j].regmap,sizeof(current.regmap));
8360               current.dirty=branch_regs[j].dirty;
8361               break;
8362             }
8363           }
8364           while(j>=0) {
8365             if(ba[j]==start+i*4+4) {
8366               for(hr=0;hr<HOST_REGS;hr++) {
8367                 if(current.regmap[hr]!=branch_regs[j].regmap[hr]) {
8368                   current.regmap[hr]=-1;
8369                 }
8370                 current.dirty&=branch_regs[j].dirty;
8371               }
8372             }
8373             j--;
8374           }
8375         }
8376       }
8377     }
8378
8379     // Count cycles in between branches
8380     ccadj[i] = CLOCK_ADJUST(cc);
8381     if (i > 0 && (dops[i-1].is_jump || dops[i].itype == SYSCALL || dops[i].itype == HLECALL))
8382     {
8383       cc=0;
8384     }
8385 #if !defined(DRC_DBG)
8386     else if(dops[i].itype==C2OP&&gte_cycletab[source[i]&0x3f]>2)
8387     {
8388       // this should really be removed since the real stalls have been implemented,
8389       // but doing so causes sizeable perf regression against the older version
8390       u_int gtec = gte_cycletab[source[i] & 0x3f];
8391       cc += HACK_ENABLED(NDHACK_NO_STALLS) ? gtec/2 : 2;
8392     }
8393     else if(i>1&&dops[i].itype==STORE&&dops[i-1].itype==STORE&&dops[i-2].itype==STORE&&!dops[i].bt)
8394     {
8395       cc+=4;
8396     }
8397     else if(dops[i].itype==C2LS)
8398     {
8399       // same as with C2OP
8400       cc += HACK_ENABLED(NDHACK_NO_STALLS) ? 4 : 2;
8401     }
8402 #endif
8403     else
8404     {
8405       cc++;
8406     }
8407
8408     if(!dops[i].is_ds) {
8409       regs[i].dirty=current.dirty;
8410       regs[i].isconst=current.isconst;
8411       memcpy(constmap[i],current_constmap,sizeof(constmap[i]));
8412     }
8413     for(hr=0;hr<HOST_REGS;hr++) {
8414       if(hr!=EXCLUDE_REG&&regs[i].regmap[hr]>=0) {
8415         if(regmap_pre[i][hr]!=regs[i].regmap[hr]) {
8416           regs[i].wasconst&=~(1<<hr);
8417         }
8418       }
8419     }
8420     if(current.regmap[HOST_BTREG]==BTREG) current.regmap[HOST_BTREG]=-1;
8421     regs[i].waswritten=current.waswritten;
8422   }
8423
8424   /* Pass 4 - Cull unused host registers */
8425
8426   uint64_t nr=0;
8427
8428   for (i=slen-1;i>=0;i--)
8429   {
8430     int hr;
8431     if(dops[i].is_jump)
8432     {
8433       if(ba[i]<start || ba[i]>=(start+slen*4))
8434       {
8435         // Branch out of this block, don't need anything
8436         nr=0;
8437       }
8438       else
8439       {
8440         // Internal branch
8441         // Need whatever matches the target
8442         nr=0;
8443         int t=(ba[i]-start)>>2;
8444         for(hr=0;hr<HOST_REGS;hr++)
8445         {
8446           if(regs[i].regmap_entry[hr]>=0) {
8447             if(regs[i].regmap_entry[hr]==regs[t].regmap_entry[hr]) nr|=1<<hr;
8448           }
8449         }
8450       }
8451       // Conditional branch may need registers for following instructions
8452       if (!dops[i].is_ujump)
8453       {
8454         if(i<slen-2) {
8455           nr|=needed_reg[i+2];
8456           for(hr=0;hr<HOST_REGS;hr++)
8457           {
8458             if(regmap_pre[i+2][hr]>=0&&get_reg(regs[i+2].regmap_entry,regmap_pre[i+2][hr])<0) nr&=~(1<<hr);
8459             //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]);
8460           }
8461         }
8462       }
8463       // Don't need stuff which is overwritten
8464       //if(regs[i].regmap[hr]!=regmap_pre[i][hr]) nr&=~(1<<hr);
8465       //if(regs[i].regmap[hr]<0) nr&=~(1<<hr);
8466       // Merge in delay slot
8467       for(hr=0;hr<HOST_REGS;hr++)
8468       {
8469         if(dops[i+1].rt1&&dops[i+1].rt1==regs[i].regmap[hr]) nr&=~(1<<hr);
8470         if(dops[i+1].rt2&&dops[i+1].rt2==regs[i].regmap[hr]) nr&=~(1<<hr);
8471         if(dops[i+1].rs1==regmap_pre[i][hr]) nr|=1<<hr;
8472         if(dops[i+1].rs2==regmap_pre[i][hr]) nr|=1<<hr;
8473         if(dops[i+1].rs1==regs[i].regmap_entry[hr]) nr|=1<<hr;
8474         if(dops[i+1].rs2==regs[i].regmap_entry[hr]) nr|=1<<hr;
8475         if(ram_offset && (dops[i+1].is_load || dops[i+1].is_store)) {
8476           if(regmap_pre[i][hr]==ROREG) nr|=1<<hr;
8477           if(regs[i].regmap_entry[hr]==ROREG) nr|=1<<hr;
8478         }
8479         if(dops[i+1].is_store) {
8480           if(regmap_pre[i][hr]==INVCP) nr|=1<<hr;
8481           if(regs[i].regmap_entry[hr]==INVCP) nr|=1<<hr;
8482         }
8483       }
8484     }
8485     else if(dops[i].itype==SYSCALL||dops[i].itype==HLECALL||dops[i].itype==INTCALL)
8486     {
8487       // SYSCALL instruction (software interrupt)
8488       nr=0;
8489     }
8490     else if(dops[i].itype==COP0 && (source[i]&0x3f)==0x18)
8491     {
8492       // ERET instruction (return from interrupt)
8493       nr=0;
8494     }
8495     else // Non-branch
8496     {
8497       if(i<slen-1) {
8498         for(hr=0;hr<HOST_REGS;hr++) {
8499           if(regmap_pre[i+1][hr]>=0&&get_reg(regs[i+1].regmap_entry,regmap_pre[i+1][hr])<0) nr&=~(1<<hr);
8500           if(regs[i].regmap[hr]!=regmap_pre[i+1][hr]) nr&=~(1<<hr);
8501           if(regs[i].regmap[hr]!=regmap_pre[i][hr]) nr&=~(1<<hr);
8502           if(regs[i].regmap[hr]<0) nr&=~(1<<hr);
8503         }
8504       }
8505     }
8506     for(hr=0;hr<HOST_REGS;hr++)
8507     {
8508       // Overwritten registers are not needed
8509       if(dops[i].rt1&&dops[i].rt1==regs[i].regmap[hr]) nr&=~(1<<hr);
8510       if(dops[i].rt2&&dops[i].rt2==regs[i].regmap[hr]) nr&=~(1<<hr);
8511       if(FTEMP==regs[i].regmap[hr]) nr&=~(1<<hr);
8512       // Source registers are needed
8513       if(dops[i].rs1==regmap_pre[i][hr]) nr|=1<<hr;
8514       if(dops[i].rs2==regmap_pre[i][hr]) nr|=1<<hr;
8515       if(dops[i].rs1==regs[i].regmap_entry[hr]) nr|=1<<hr;
8516       if(dops[i].rs2==regs[i].regmap_entry[hr]) nr|=1<<hr;
8517       if(ram_offset && (dops[i].is_load || dops[i].is_store)) {
8518         if(regmap_pre[i][hr]==ROREG) nr|=1<<hr;
8519         if(regs[i].regmap_entry[hr]==ROREG) nr|=1<<hr;
8520       }
8521       if(dops[i].is_store) {
8522         if(regmap_pre[i][hr]==INVCP) nr|=1<<hr;
8523         if(regs[i].regmap_entry[hr]==INVCP) nr|=1<<hr;
8524       }
8525       // Don't store a register immediately after writing it,
8526       // may prevent dual-issue.
8527       // But do so if this is a branch target, otherwise we
8528       // might have to load the register before the branch.
8529       if(i>0&&!dops[i].bt&&((regs[i].wasdirty>>hr)&1)) {
8530         if((regmap_pre[i][hr]>0&&!((unneeded_reg[i]>>regmap_pre[i][hr])&1))) {
8531           if(dops[i-1].rt1==regmap_pre[i][hr]) nr|=1<<hr;
8532           if(dops[i-1].rt2==regmap_pre[i][hr]) nr|=1<<hr;
8533         }
8534         if((regs[i].regmap_entry[hr]>0&&!((unneeded_reg[i]>>regs[i].regmap_entry[hr])&1))) {
8535           if(dops[i-1].rt1==regs[i].regmap_entry[hr]) nr|=1<<hr;
8536           if(dops[i-1].rt2==regs[i].regmap_entry[hr]) nr|=1<<hr;
8537         }
8538       }
8539     }
8540     // Cycle count is needed at branches.  Assume it is needed at the target too.
8541     if(i==0||dops[i].bt||dops[i].itype==CJUMP||dops[i].itype==SPAN) {
8542       if(regmap_pre[i][HOST_CCREG]==CCREG) nr|=1<<HOST_CCREG;
8543       if(regs[i].regmap_entry[HOST_CCREG]==CCREG) nr|=1<<HOST_CCREG;
8544     }
8545     // Save it
8546     needed_reg[i]=nr;
8547
8548     // Deallocate unneeded registers
8549     for(hr=0;hr<HOST_REGS;hr++)
8550     {
8551       if(!((nr>>hr)&1)) {
8552         if(regs[i].regmap_entry[hr]!=CCREG) regs[i].regmap_entry[hr]=-1;
8553         if(dops[i].is_jump)
8554         {
8555           int map1 = 0, map2 = 0, temp = 0; // or -1 ??
8556           if (dops[i+1].is_load || dops[i+1].is_store)
8557             map1 = ROREG;
8558           if (dops[i+1].is_store)
8559             map2 = INVCP;
8560           if(dops[i+1].itype==LOADLR || dops[i+1].itype==STORELR || dops[i+1].itype==C2LS)
8561             temp = FTEMP;
8562           if(regs[i].regmap[hr]!=dops[i].rs1 && regs[i].regmap[hr]!=dops[i].rs2 &&
8563              regs[i].regmap[hr]!=dops[i].rt1 && regs[i].regmap[hr]!=dops[i].rt2 &&
8564              regs[i].regmap[hr]!=dops[i+1].rt1 && regs[i].regmap[hr]!=dops[i+1].rt2 &&
8565              regs[i].regmap[hr]!=dops[i+1].rs1 && regs[i].regmap[hr]!=dops[i+1].rs2 &&
8566              regs[i].regmap[hr]!=temp && regs[i].regmap[hr]!=PTEMP &&
8567              regs[i].regmap[hr]!=RHASH && regs[i].regmap[hr]!=RHTBL &&
8568              regs[i].regmap[hr]!=RTEMP && regs[i].regmap[hr]!=CCREG &&
8569              regs[i].regmap[hr]!=map1 && regs[i].regmap[hr]!=map2)
8570           {
8571             regs[i].regmap[hr]=-1;
8572             regs[i].isconst&=~(1<<hr);
8573             regs[i].dirty&=~(1<<hr);
8574             regs[i+1].wasdirty&=~(1<<hr);
8575             if(branch_regs[i].regmap[hr]!=dops[i].rs1 && branch_regs[i].regmap[hr]!=dops[i].rs2 &&
8576                branch_regs[i].regmap[hr]!=dops[i].rt1 && branch_regs[i].regmap[hr]!=dops[i].rt2 &&
8577                branch_regs[i].regmap[hr]!=dops[i+1].rt1 && branch_regs[i].regmap[hr]!=dops[i+1].rt2 &&
8578                branch_regs[i].regmap[hr]!=dops[i+1].rs1 && branch_regs[i].regmap[hr]!=dops[i+1].rs2 &&
8579                branch_regs[i].regmap[hr]!=temp && branch_regs[i].regmap[hr]!=PTEMP &&
8580                branch_regs[i].regmap[hr]!=RHASH && branch_regs[i].regmap[hr]!=RHTBL &&
8581                branch_regs[i].regmap[hr]!=RTEMP && branch_regs[i].regmap[hr]!=CCREG &&
8582                branch_regs[i].regmap[hr]!=map1 && branch_regs[i].regmap[hr]!=map2)
8583             {
8584               branch_regs[i].regmap[hr]=-1;
8585               branch_regs[i].regmap_entry[hr]=-1;
8586               if (!dops[i].is_ujump)
8587               {
8588                 if (i < slen-2) {
8589                   regmap_pre[i+2][hr]=-1;
8590                   regs[i+2].wasconst&=~(1<<hr);
8591                 }
8592               }
8593             }
8594           }
8595         }
8596         else
8597         {
8598           // Non-branch
8599           if(i>0)
8600           {
8601             int map1 = -1, map2 = -1, temp=-1;
8602             if (dops[i].is_load || dops[i].is_store)
8603               map1 = ROREG;
8604             if (dops[i].is_store)
8605               map2 = INVCP;
8606             if (dops[i].itype==LOADLR || dops[i].itype==STORELR || dops[i].itype==C2LS)
8607               temp = FTEMP;
8608             if(regs[i].regmap[hr]!=dops[i].rt1 && regs[i].regmap[hr]!=dops[i].rt2 &&
8609                regs[i].regmap[hr]!=dops[i].rs1 && regs[i].regmap[hr]!=dops[i].rs2 &&
8610                regs[i].regmap[hr]!=temp && regs[i].regmap[hr]!=map1 && regs[i].regmap[hr]!=map2 &&
8611                //(dops[i].itype!=SPAN||regs[i].regmap[hr]!=CCREG)
8612                regs[i].regmap[hr] != CCREG)
8613             {
8614               if(i<slen-1&&!dops[i].is_ds) {
8615                 assert(regs[i].regmap[hr]<64);
8616                 if(regmap_pre[i+1][hr]!=-1 || regs[i].regmap[hr]>0)
8617                 if(regmap_pre[i+1][hr]!=regs[i].regmap[hr])
8618                 {
8619                   SysPrintf("fail: %x (%d %d!=%d)\n",start+i*4,hr,regmap_pre[i+1][hr],regs[i].regmap[hr]);
8620                   assert(regmap_pre[i+1][hr]==regs[i].regmap[hr]);
8621                 }
8622                 regmap_pre[i+1][hr]=-1;
8623                 if(regs[i+1].regmap_entry[hr]==CCREG) regs[i+1].regmap_entry[hr]=-1;
8624                 regs[i+1].wasconst&=~(1<<hr);
8625               }
8626               regs[i].regmap[hr]=-1;
8627               regs[i].isconst&=~(1<<hr);
8628               regs[i].dirty&=~(1<<hr);
8629               regs[i+1].wasdirty&=~(1<<hr);
8630             }
8631           }
8632         }
8633       } // if needed
8634     } // for hr
8635   }
8636
8637   /* Pass 5 - Pre-allocate registers */
8638
8639   // If a register is allocated during a loop, try to allocate it for the
8640   // entire loop, if possible.  This avoids loading/storing registers
8641   // inside of the loop.
8642
8643   signed char f_regmap[HOST_REGS];
8644   clear_all_regs(f_regmap);
8645   for(i=0;i<slen-1;i++)
8646   {
8647     if(dops[i].itype==UJUMP||dops[i].itype==CJUMP||dops[i].itype==SJUMP)
8648     {
8649       if(ba[i]>=start && ba[i]<(start+i*4))
8650       if(dops[i+1].itype==NOP||dops[i+1].itype==MOV||dops[i+1].itype==ALU
8651       ||dops[i+1].itype==SHIFTIMM||dops[i+1].itype==IMM16||dops[i+1].itype==LOAD
8652       ||dops[i+1].itype==STORE||dops[i+1].itype==STORELR||dops[i+1].itype==C1LS
8653       ||dops[i+1].itype==SHIFT||dops[i+1].itype==COP1
8654       ||dops[i+1].itype==COP2||dops[i+1].itype==C2LS||dops[i+1].itype==C2OP)
8655       {
8656         int t=(ba[i]-start)>>2;
8657         if(t > 0 && !dops[t-1].is_jump) // loop_preload can't handle jumps into delay slots
8658         if(t<2||(dops[t-2].itype!=UJUMP&&dops[t-2].itype!=RJUMP)||dops[t-2].rt1!=31) // call/ret assumes no registers allocated
8659         for(hr=0;hr<HOST_REGS;hr++)
8660         {
8661           if(regs[i].regmap[hr]>=0) {
8662             if(f_regmap[hr]!=regs[i].regmap[hr]) {
8663               // dealloc old register
8664               int n;
8665               for(n=0;n<HOST_REGS;n++)
8666               {
8667                 if(f_regmap[n]==regs[i].regmap[hr]) {f_regmap[n]=-1;}
8668               }
8669               // and alloc new one
8670               f_regmap[hr]=regs[i].regmap[hr];
8671             }
8672           }
8673           if(branch_regs[i].regmap[hr]>=0) {
8674             if(f_regmap[hr]!=branch_regs[i].regmap[hr]) {
8675               // dealloc old register
8676               int n;
8677               for(n=0;n<HOST_REGS;n++)
8678               {
8679                 if(f_regmap[n]==branch_regs[i].regmap[hr]) {f_regmap[n]=-1;}
8680               }
8681               // and alloc new one
8682               f_regmap[hr]=branch_regs[i].regmap[hr];
8683             }
8684           }
8685           if(dops[i].ooo) {
8686             if(count_free_regs(regs[i].regmap)<=minimum_free_regs[i+1])
8687               f_regmap[hr]=branch_regs[i].regmap[hr];
8688           }else{
8689             if(count_free_regs(branch_regs[i].regmap)<=minimum_free_regs[i+1])
8690               f_regmap[hr]=branch_regs[i].regmap[hr];
8691           }
8692           // Avoid dirty->clean transition
8693           #ifdef DESTRUCTIVE_WRITEBACK
8694           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;
8695           #endif
8696           // This check is only strictly required in the DESTRUCTIVE_WRITEBACK
8697           // case above, however it's always a good idea.  We can't hoist the
8698           // load if the register was already allocated, so there's no point
8699           // wasting time analyzing most of these cases.  It only "succeeds"
8700           // when the mapping was different and the load can be replaced with
8701           // a mov, which is of negligible benefit.  So such cases are
8702           // skipped below.
8703           if(f_regmap[hr]>0) {
8704             if(regs[t].regmap[hr]==f_regmap[hr]||(regs[t].regmap_entry[hr]<0&&get_reg(regmap_pre[t],f_regmap[hr])<0)) {
8705               int r=f_regmap[hr];
8706               for(j=t;j<=i;j++)
8707               {
8708                 //printf("Test %x -> %x, %x %d/%d\n",start+i*4,ba[i],start+j*4,hr,r);
8709                 if(r<34&&((unneeded_reg[j]>>r)&1)) break;
8710                 assert(r < 64);
8711                 if(regs[j].regmap[hr]==f_regmap[hr]&&f_regmap[hr]<TEMPREG) {
8712                   //printf("Hit %x -> %x, %x %d/%d\n",start+i*4,ba[i],start+j*4,hr,r);
8713                   int k;
8714                   if(regs[i].regmap[hr]==-1&&branch_regs[i].regmap[hr]==-1) {
8715                     if(get_reg(regs[i].regmap,f_regmap[hr])>=0) break;
8716                     if(get_reg(regs[i+2].regmap,f_regmap[hr])>=0) break;
8717                     k=i;
8718                     while(k>1&&regs[k-1].regmap[hr]==-1) {
8719                       if(count_free_regs(regs[k-1].regmap)<=minimum_free_regs[k-1]) {
8720                         //printf("no free regs for store %x\n",start+(k-1)*4);
8721                         break;
8722                       }
8723                       if(get_reg(regs[k-1].regmap,f_regmap[hr])>=0) {
8724                         //printf("no-match due to different register\n");
8725                         break;
8726                       }
8727                       if (dops[k-2].is_jump) {
8728                         //printf("no-match due to branch\n");
8729                         break;
8730                       }
8731                       // call/ret fast path assumes no registers allocated
8732                       if(k>2&&(dops[k-3].itype==UJUMP||dops[k-3].itype==RJUMP)&&dops[k-3].rt1==31) {
8733                         break;
8734                       }
8735                       k--;
8736                     }
8737                     if(regs[k-1].regmap[hr]==f_regmap[hr]&&regmap_pre[k][hr]==f_regmap[hr]) {
8738                       //printf("Extend r%d, %x ->\n",hr,start+k*4);
8739                       while(k<i) {
8740                         regs[k].regmap_entry[hr]=f_regmap[hr];
8741                         regs[k].regmap[hr]=f_regmap[hr];
8742                         regmap_pre[k+1][hr]=f_regmap[hr];
8743                         regs[k].wasdirty&=~(1<<hr);
8744                         regs[k].dirty&=~(1<<hr);
8745                         regs[k].wasdirty|=(1<<hr)&regs[k-1].dirty;
8746                         regs[k].dirty|=(1<<hr)&regs[k].wasdirty;
8747                         regs[k].wasconst&=~(1<<hr);
8748                         regs[k].isconst&=~(1<<hr);
8749                         k++;
8750                       }
8751                     }
8752                     else {
8753                       //printf("Fail Extend r%d, %x ->\n",hr,start+k*4);
8754                       break;
8755                     }
8756                     assert(regs[i-1].regmap[hr]==f_regmap[hr]);
8757                     if(regs[i-1].regmap[hr]==f_regmap[hr]&&regmap_pre[i][hr]==f_regmap[hr]) {
8758                       //printf("OK fill %x (r%d)\n",start+i*4,hr);
8759                       regs[i].regmap_entry[hr]=f_regmap[hr];
8760                       regs[i].regmap[hr]=f_regmap[hr];
8761                       regs[i].wasdirty&=~(1<<hr);
8762                       regs[i].dirty&=~(1<<hr);
8763                       regs[i].wasdirty|=(1<<hr)&regs[i-1].dirty;
8764                       regs[i].dirty|=(1<<hr)&regs[i-1].dirty;
8765                       regs[i].wasconst&=~(1<<hr);
8766                       regs[i].isconst&=~(1<<hr);
8767                       branch_regs[i].regmap_entry[hr]=f_regmap[hr];
8768                       branch_regs[i].wasdirty&=~(1<<hr);
8769                       branch_regs[i].wasdirty|=(1<<hr)&regs[i].dirty;
8770                       branch_regs[i].regmap[hr]=f_regmap[hr];
8771                       branch_regs[i].dirty&=~(1<<hr);
8772                       branch_regs[i].dirty|=(1<<hr)&regs[i].dirty;
8773                       branch_regs[i].wasconst&=~(1<<hr);
8774                       branch_regs[i].isconst&=~(1<<hr);
8775                       if (!dops[i].is_ujump) {
8776                         regmap_pre[i+2][hr]=f_regmap[hr];
8777                         regs[i+2].wasdirty&=~(1<<hr);
8778                         regs[i+2].wasdirty|=(1<<hr)&regs[i].dirty;
8779                       }
8780                     }
8781                   }
8782                   for(k=t;k<j;k++) {
8783                     // Alloc register clean at beginning of loop,
8784                     // but may dirty it in pass 6
8785                     regs[k].regmap_entry[hr]=f_regmap[hr];
8786                     regs[k].regmap[hr]=f_regmap[hr];
8787                     regs[k].dirty&=~(1<<hr);
8788                     regs[k].wasconst&=~(1<<hr);
8789                     regs[k].isconst&=~(1<<hr);
8790                     if (dops[k].is_jump) {
8791                       branch_regs[k].regmap_entry[hr]=f_regmap[hr];
8792                       branch_regs[k].regmap[hr]=f_regmap[hr];
8793                       branch_regs[k].dirty&=~(1<<hr);
8794                       branch_regs[k].wasconst&=~(1<<hr);
8795                       branch_regs[k].isconst&=~(1<<hr);
8796                       if (!dops[k].is_ujump) {
8797                         regmap_pre[k+2][hr]=f_regmap[hr];
8798                         regs[k+2].wasdirty&=~(1<<hr);
8799                       }
8800                     }
8801                     else
8802                     {
8803                       regmap_pre[k+1][hr]=f_regmap[hr];
8804                       regs[k+1].wasdirty&=~(1<<hr);
8805                     }
8806                   }
8807                   if(regs[j].regmap[hr]==f_regmap[hr])
8808                     regs[j].regmap_entry[hr]=f_regmap[hr];
8809                   break;
8810                 }
8811                 if(j==i) break;
8812                 if(regs[j].regmap[hr]>=0)
8813                   break;
8814                 if(get_reg(regs[j].regmap,f_regmap[hr])>=0) {
8815                   //printf("no-match due to different register\n");
8816                   break;
8817                 }
8818                 if (dops[j].is_ujump)
8819                 {
8820                   // Stop on unconditional branch
8821                   break;
8822                 }
8823                 if(dops[j].itype==CJUMP||dops[j].itype==SJUMP)
8824                 {
8825                   if(dops[j].ooo) {
8826                     if(count_free_regs(regs[j].regmap)<=minimum_free_regs[j+1])
8827                       break;
8828                   }else{
8829                     if(count_free_regs(branch_regs[j].regmap)<=minimum_free_regs[j+1])
8830                       break;
8831                   }
8832                   if(get_reg(branch_regs[j].regmap,f_regmap[hr])>=0) {
8833                     //printf("no-match due to different register (branch)\n");
8834                     break;
8835                   }
8836                 }
8837                 if(count_free_regs(regs[j].regmap)<=minimum_free_regs[j]) {
8838                   //printf("No free regs for store %x\n",start+j*4);
8839                   break;
8840                 }
8841                 assert(f_regmap[hr]<64);
8842               }
8843             }
8844           }
8845         }
8846       }
8847     }else{
8848       // Non branch or undetermined branch target
8849       for(hr=0;hr<HOST_REGS;hr++)
8850       {
8851         if(hr!=EXCLUDE_REG) {
8852           if(regs[i].regmap[hr]>=0) {
8853             if(f_regmap[hr]!=regs[i].regmap[hr]) {
8854               // dealloc old register
8855               int n;
8856               for(n=0;n<HOST_REGS;n++)
8857               {
8858                 if(f_regmap[n]==regs[i].regmap[hr]) {f_regmap[n]=-1;}
8859               }
8860               // and alloc new one
8861               f_regmap[hr]=regs[i].regmap[hr];
8862             }
8863           }
8864         }
8865       }
8866       // Try to restore cycle count at branch targets
8867       if(dops[i].bt) {
8868         for(j=i;j<slen-1;j++) {
8869           if(regs[j].regmap[HOST_CCREG]!=-1) break;
8870           if(count_free_regs(regs[j].regmap)<=minimum_free_regs[j]) {
8871             //printf("no free regs for store %x\n",start+j*4);
8872             break;
8873           }
8874         }
8875         if(regs[j].regmap[HOST_CCREG]==CCREG) {
8876           int k=i;
8877           //printf("Extend CC, %x -> %x\n",start+k*4,start+j*4);
8878           while(k<j) {
8879             regs[k].regmap_entry[HOST_CCREG]=CCREG;
8880             regs[k].regmap[HOST_CCREG]=CCREG;
8881             regmap_pre[k+1][HOST_CCREG]=CCREG;
8882             regs[k+1].wasdirty|=1<<HOST_CCREG;
8883             regs[k].dirty|=1<<HOST_CCREG;
8884             regs[k].wasconst&=~(1<<HOST_CCREG);
8885             regs[k].isconst&=~(1<<HOST_CCREG);
8886             k++;
8887           }
8888           regs[j].regmap_entry[HOST_CCREG]=CCREG;
8889         }
8890         // Work backwards from the branch target
8891         if(j>i&&f_regmap[HOST_CCREG]==CCREG)
8892         {
8893           //printf("Extend backwards\n");
8894           int k;
8895           k=i;
8896           while(regs[k-1].regmap[HOST_CCREG]==-1) {
8897             if(count_free_regs(regs[k-1].regmap)<=minimum_free_regs[k-1]) {
8898               //printf("no free regs for store %x\n",start+(k-1)*4);
8899               break;
8900             }
8901             k--;
8902           }
8903           if(regs[k-1].regmap[HOST_CCREG]==CCREG) {
8904             //printf("Extend CC, %x ->\n",start+k*4);
8905             while(k<=i) {
8906               regs[k].regmap_entry[HOST_CCREG]=CCREG;
8907               regs[k].regmap[HOST_CCREG]=CCREG;
8908               regmap_pre[k+1][HOST_CCREG]=CCREG;
8909               regs[k+1].wasdirty|=1<<HOST_CCREG;
8910               regs[k].dirty|=1<<HOST_CCREG;
8911               regs[k].wasconst&=~(1<<HOST_CCREG);
8912               regs[k].isconst&=~(1<<HOST_CCREG);
8913               k++;
8914             }
8915           }
8916           else {
8917             //printf("Fail Extend CC, %x ->\n",start+k*4);
8918           }
8919         }
8920       }
8921       if(dops[i].itype!=STORE&&dops[i].itype!=STORELR&&dops[i].itype!=C1LS&&dops[i].itype!=SHIFT&&
8922          dops[i].itype!=NOP&&dops[i].itype!=MOV&&dops[i].itype!=ALU&&dops[i].itype!=SHIFTIMM&&
8923          dops[i].itype!=IMM16&&dops[i].itype!=LOAD&&dops[i].itype!=COP1)
8924       {
8925         memcpy(f_regmap,regs[i].regmap,sizeof(f_regmap));
8926       }
8927     }
8928   }
8929
8930   // This allocates registers (if possible) one instruction prior
8931   // to use, which can avoid a load-use penalty on certain CPUs.
8932   for(i=0;i<slen-1;i++)
8933   {
8934     if (!i || !dops[i-1].is_jump)
8935     {
8936       if(!dops[i+1].bt)
8937       {
8938         if(dops[i].itype==ALU||dops[i].itype==MOV||dops[i].itype==LOAD||dops[i].itype==SHIFTIMM||dops[i].itype==IMM16
8939            ||((dops[i].itype==COP1||dops[i].itype==COP2)&&dops[i].opcode2<3))
8940         {
8941           if(dops[i+1].rs1) {
8942             if((hr=get_reg(regs[i+1].regmap,dops[i+1].rs1))>=0)
8943             {
8944               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
8945               {
8946                 regs[i].regmap[hr]=regs[i+1].regmap[hr];
8947                 regmap_pre[i+1][hr]=regs[i+1].regmap[hr];
8948                 regs[i+1].regmap_entry[hr]=regs[i+1].regmap[hr];
8949                 regs[i].isconst&=~(1<<hr);
8950                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
8951                 constmap[i][hr]=constmap[i+1][hr];
8952                 regs[i+1].wasdirty&=~(1<<hr);
8953                 regs[i].dirty&=~(1<<hr);
8954               }
8955             }
8956           }
8957           if(dops[i+1].rs2) {
8958             if((hr=get_reg(regs[i+1].regmap,dops[i+1].rs2))>=0)
8959             {
8960               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
8961               {
8962                 regs[i].regmap[hr]=regs[i+1].regmap[hr];
8963                 regmap_pre[i+1][hr]=regs[i+1].regmap[hr];
8964                 regs[i+1].regmap_entry[hr]=regs[i+1].regmap[hr];
8965                 regs[i].isconst&=~(1<<hr);
8966                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
8967                 constmap[i][hr]=constmap[i+1][hr];
8968                 regs[i+1].wasdirty&=~(1<<hr);
8969                 regs[i].dirty&=~(1<<hr);
8970               }
8971             }
8972           }
8973           // Preload target address for load instruction (non-constant)
8974           if(dops[i+1].itype==LOAD&&dops[i+1].rs1&&get_reg(regs[i+1].regmap,dops[i+1].rs1)<0) {
8975             if((hr=get_reg(regs[i+1].regmap,dops[i+1].rt1))>=0)
8976             {
8977               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
8978               {
8979                 regs[i].regmap[hr]=dops[i+1].rs1;
8980                 regmap_pre[i+1][hr]=dops[i+1].rs1;
8981                 regs[i+1].regmap_entry[hr]=dops[i+1].rs1;
8982                 regs[i].isconst&=~(1<<hr);
8983                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
8984                 constmap[i][hr]=constmap[i+1][hr];
8985                 regs[i+1].wasdirty&=~(1<<hr);
8986                 regs[i].dirty&=~(1<<hr);
8987               }
8988             }
8989           }
8990           // Load source into target register
8991           if(dops[i+1].lt1&&get_reg(regs[i+1].regmap,dops[i+1].rs1)<0) {
8992             if((hr=get_reg(regs[i+1].regmap,dops[i+1].rt1))>=0)
8993             {
8994               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
8995               {
8996                 regs[i].regmap[hr]=dops[i+1].rs1;
8997                 regmap_pre[i+1][hr]=dops[i+1].rs1;
8998                 regs[i+1].regmap_entry[hr]=dops[i+1].rs1;
8999                 regs[i].isconst&=~(1<<hr);
9000                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
9001                 constmap[i][hr]=constmap[i+1][hr];
9002                 regs[i+1].wasdirty&=~(1<<hr);
9003                 regs[i].dirty&=~(1<<hr);
9004               }
9005             }
9006           }
9007           // Address for store instruction (non-constant)
9008           if(dops[i+1].itype==STORE||dops[i+1].itype==STORELR
9009              ||(dops[i+1].opcode&0x3b)==0x39||(dops[i+1].opcode&0x3b)==0x3a) { // SB/SH/SW/SD/SWC1/SDC1/SWC2/SDC2
9010             if(get_reg(regs[i+1].regmap,dops[i+1].rs1)<0) {
9011               hr=get_reg2(regs[i].regmap,regs[i+1].regmap,-1);
9012               if(hr<0) hr=get_reg_temp(regs[i+1].regmap);
9013               else {
9014                 regs[i+1].regmap[hr]=AGEN1+((i+1)&1);
9015                 regs[i+1].isconst&=~(1<<hr);
9016               }
9017               assert(hr>=0);
9018               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
9019               {
9020                 regs[i].regmap[hr]=dops[i+1].rs1;
9021                 regmap_pre[i+1][hr]=dops[i+1].rs1;
9022                 regs[i+1].regmap_entry[hr]=dops[i+1].rs1;
9023                 regs[i].isconst&=~(1<<hr);
9024                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
9025                 constmap[i][hr]=constmap[i+1][hr];
9026                 regs[i+1].wasdirty&=~(1<<hr);
9027                 regs[i].dirty&=~(1<<hr);
9028               }
9029             }
9030           }
9031           if(dops[i+1].itype==LOADLR||(dops[i+1].opcode&0x3b)==0x31||(dops[i+1].opcode&0x3b)==0x32) { // LWC1/LDC1, LWC2/LDC2
9032             if(get_reg(regs[i+1].regmap,dops[i+1].rs1)<0) {
9033               int nr;
9034               hr=get_reg(regs[i+1].regmap,FTEMP);
9035               assert(hr>=0);
9036               if(regs[i].regmap[hr]<0&&regs[i+1].regmap_entry[hr]<0)
9037               {
9038                 regs[i].regmap[hr]=dops[i+1].rs1;
9039                 regmap_pre[i+1][hr]=dops[i+1].rs1;
9040                 regs[i+1].regmap_entry[hr]=dops[i+1].rs1;
9041                 regs[i].isconst&=~(1<<hr);
9042                 regs[i].isconst|=regs[i+1].isconst&(1<<hr);
9043                 constmap[i][hr]=constmap[i+1][hr];
9044                 regs[i+1].wasdirty&=~(1<<hr);
9045                 regs[i].dirty&=~(1<<hr);
9046               }
9047               else if((nr=get_reg2(regs[i].regmap,regs[i+1].regmap,-1))>=0)
9048               {
9049                 // move it to another register
9050                 regs[i+1].regmap[hr]=-1;
9051                 regmap_pre[i+2][hr]=-1;
9052                 regs[i+1].regmap[nr]=FTEMP;
9053                 regmap_pre[i+2][nr]=FTEMP;
9054                 regs[i].regmap[nr]=dops[i+1].rs1;
9055                 regmap_pre[i+1][nr]=dops[i+1].rs1;
9056                 regs[i+1].regmap_entry[nr]=dops[i+1].rs1;
9057                 regs[i].isconst&=~(1<<nr);
9058                 regs[i+1].isconst&=~(1<<nr);
9059                 regs[i].dirty&=~(1<<nr);
9060                 regs[i+1].wasdirty&=~(1<<nr);
9061                 regs[i+1].dirty&=~(1<<nr);
9062                 regs[i+2].wasdirty&=~(1<<nr);
9063               }
9064             }
9065           }
9066           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*/) {
9067             if(dops[i+1].itype==LOAD)
9068               hr=get_reg(regs[i+1].regmap,dops[i+1].rt1);
9069             if(dops[i+1].itype==LOADLR||(dops[i+1].opcode&0x3b)==0x31||(dops[i+1].opcode&0x3b)==0x32) // LWC1/LDC1, LWC2/LDC2
9070               hr=get_reg(regs[i+1].regmap,FTEMP);
9071             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
9072               hr=get_reg(regs[i+1].regmap,AGEN1+((i+1)&1));
9073               if(hr<0) hr=get_reg_temp(regs[i+1].regmap);
9074             }
9075             if(hr>=0&&regs[i].regmap[hr]<0) {
9076               int rs=get_reg(regs[i+1].regmap,dops[i+1].rs1);
9077               if(rs>=0&&((regs[i+1].wasconst>>rs)&1)) {
9078                 regs[i].regmap[hr]=AGEN1+((i+1)&1);
9079                 regmap_pre[i+1][hr]=AGEN1+((i+1)&1);
9080                 regs[i+1].regmap_entry[hr]=AGEN1+((i+1)&1);
9081                 regs[i].isconst&=~(1<<hr);
9082                 regs[i+1].wasdirty&=~(1<<hr);
9083                 regs[i].dirty&=~(1<<hr);
9084               }
9085             }
9086           }
9087         }
9088       }
9089     }
9090   }
9091
9092   /* Pass 6 - Optimize clean/dirty state */
9093   clean_registers(0,slen-1,1);
9094
9095   /* Pass 7 - Identify 32-bit registers */
9096   for (i=slen-1;i>=0;i--)
9097   {
9098     if(dops[i].itype==CJUMP||dops[i].itype==SJUMP)
9099     {
9100       // Conditional branch
9101       if((source[i]>>16)!=0x1000&&i<slen-2) {
9102         // Mark this address as a branch target since it may be called
9103         // upon return from interrupt
9104         dops[i+2].bt=1;
9105       }
9106     }
9107   }
9108
9109   if(dops[slen-1].itype==SPAN) {
9110     dops[slen-1].bt=1; // Mark as a branch target so instruction can restart after exception
9111   }
9112
9113 #ifdef REG_ALLOC_PRINT
9114   /* Debug/disassembly */
9115   for(i=0;i<slen;i++)
9116   {
9117     printf("U:");
9118     int r;
9119     for(r=1;r<=CCREG;r++) {
9120       if((unneeded_reg[i]>>r)&1) {
9121         if(r==HIREG) printf(" HI");
9122         else if(r==LOREG) printf(" LO");
9123         else printf(" r%d",r);
9124       }
9125     }
9126     printf("\n");
9127     #if defined(__i386__) || defined(__x86_64__)
9128     printf("pre: eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",regmap_pre[i][0],regmap_pre[i][1],regmap_pre[i][2],regmap_pre[i][3],regmap_pre[i][5],regmap_pre[i][6],regmap_pre[i][7]);
9129     #endif
9130     #ifdef __arm__
9131     printf("pre: r0=%d r1=%d r2=%d r3=%d r4=%d r5=%d r6=%d r7=%d r8=%d r9=%d r10=%d r12=%d\n",regmap_pre[i][0],regmap_pre[i][1],regmap_pre[i][2],regmap_pre[i][3],regmap_pre[i][4],regmap_pre[i][5],regmap_pre[i][6],regmap_pre[i][7],regmap_pre[i][8],regmap_pre[i][9],regmap_pre[i][10],regmap_pre[i][12]);
9132     #endif
9133     #if defined(__i386__) || defined(__x86_64__)
9134     printf("needs: ");
9135     if(needed_reg[i]&1) printf("eax ");
9136     if((needed_reg[i]>>1)&1) printf("ecx ");
9137     if((needed_reg[i]>>2)&1) printf("edx ");
9138     if((needed_reg[i]>>3)&1) printf("ebx ");
9139     if((needed_reg[i]>>5)&1) printf("ebp ");
9140     if((needed_reg[i]>>6)&1) printf("esi ");
9141     if((needed_reg[i]>>7)&1) printf("edi ");
9142     printf("\n");
9143     printf("entry: eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d\n",regs[i].regmap_entry[0],regs[i].regmap_entry[1],regs[i].regmap_entry[2],regs[i].regmap_entry[3],regs[i].regmap_entry[5],regs[i].regmap_entry[6],regs[i].regmap_entry[7]);
9144     printf("dirty: ");
9145     if(regs[i].wasdirty&1) printf("eax ");
9146     if((regs[i].wasdirty>>1)&1) printf("ecx ");
9147     if((regs[i].wasdirty>>2)&1) printf("edx ");
9148     if((regs[i].wasdirty>>3)&1) printf("ebx ");
9149     if((regs[i].wasdirty>>5)&1) printf("ebp ");
9150     if((regs[i].wasdirty>>6)&1) printf("esi ");
9151     if((regs[i].wasdirty>>7)&1) printf("edi ");
9152     #endif
9153     #ifdef __arm__
9154     printf("entry: r0=%d r1=%d r2=%d r3=%d r4=%d r5=%d r6=%d r7=%d r8=%d r9=%d r10=%d r12=%d\n",regs[i].regmap_entry[0],regs[i].regmap_entry[1],regs[i].regmap_entry[2],regs[i].regmap_entry[3],regs[i].regmap_entry[4],regs[i].regmap_entry[5],regs[i].regmap_entry[6],regs[i].regmap_entry[7],regs[i].regmap_entry[8],regs[i].regmap_entry[9],regs[i].regmap_entry[10],regs[i].regmap_entry[12]);
9155     printf("dirty: ");
9156     if(regs[i].wasdirty&1) printf("r0 ");
9157     if((regs[i].wasdirty>>1)&1) printf("r1 ");
9158     if((regs[i].wasdirty>>2)&1) printf("r2 ");
9159     if((regs[i].wasdirty>>3)&1) printf("r3 ");
9160     if((regs[i].wasdirty>>4)&1) printf("r4 ");
9161     if((regs[i].wasdirty>>5)&1) printf("r5 ");
9162     if((regs[i].wasdirty>>6)&1) printf("r6 ");
9163     if((regs[i].wasdirty>>7)&1) printf("r7 ");
9164     if((regs[i].wasdirty>>8)&1) printf("r8 ");
9165     if((regs[i].wasdirty>>9)&1) printf("r9 ");
9166     if((regs[i].wasdirty>>10)&1) printf("r10 ");
9167     if((regs[i].wasdirty>>12)&1) printf("r12 ");
9168     #endif
9169     printf("\n");
9170     disassemble_inst(i);
9171     //printf ("ccadj[%d] = %d\n",i,ccadj[i]);
9172     #if defined(__i386__) || defined(__x86_64__)
9173     printf("eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d dirty: ",regs[i].regmap[0],regs[i].regmap[1],regs[i].regmap[2],regs[i].regmap[3],regs[i].regmap[5],regs[i].regmap[6],regs[i].regmap[7]);
9174     if(regs[i].dirty&1) printf("eax ");
9175     if((regs[i].dirty>>1)&1) printf("ecx ");
9176     if((regs[i].dirty>>2)&1) printf("edx ");
9177     if((regs[i].dirty>>3)&1) printf("ebx ");
9178     if((regs[i].dirty>>5)&1) printf("ebp ");
9179     if((regs[i].dirty>>6)&1) printf("esi ");
9180     if((regs[i].dirty>>7)&1) printf("edi ");
9181     #endif
9182     #ifdef __arm__
9183     printf("r0=%d r1=%d r2=%d r3=%d r4=%d r5=%d r6=%d r7=%d r8=%d r9=%d r10=%d r12=%d dirty: ",regs[i].regmap[0],regs[i].regmap[1],regs[i].regmap[2],regs[i].regmap[3],regs[i].regmap[4],regs[i].regmap[5],regs[i].regmap[6],regs[i].regmap[7],regs[i].regmap[8],regs[i].regmap[9],regs[i].regmap[10],regs[i].regmap[12]);
9184     if(regs[i].dirty&1) printf("r0 ");
9185     if((regs[i].dirty>>1)&1) printf("r1 ");
9186     if((regs[i].dirty>>2)&1) printf("r2 ");
9187     if((regs[i].dirty>>3)&1) printf("r3 ");
9188     if((regs[i].dirty>>4)&1) printf("r4 ");
9189     if((regs[i].dirty>>5)&1) printf("r5 ");
9190     if((regs[i].dirty>>6)&1) printf("r6 ");
9191     if((regs[i].dirty>>7)&1) printf("r7 ");
9192     if((regs[i].dirty>>8)&1) printf("r8 ");
9193     if((regs[i].dirty>>9)&1) printf("r9 ");
9194     if((regs[i].dirty>>10)&1) printf("r10 ");
9195     if((regs[i].dirty>>12)&1) printf("r12 ");
9196     #endif
9197     printf("\n");
9198     if(regs[i].isconst) {
9199       printf("constants: ");
9200       #if defined(__i386__) || defined(__x86_64__)
9201       if(regs[i].isconst&1) printf("eax=%x ",(u_int)constmap[i][0]);
9202       if((regs[i].isconst>>1)&1) printf("ecx=%x ",(u_int)constmap[i][1]);
9203       if((regs[i].isconst>>2)&1) printf("edx=%x ",(u_int)constmap[i][2]);
9204       if((regs[i].isconst>>3)&1) printf("ebx=%x ",(u_int)constmap[i][3]);
9205       if((regs[i].isconst>>5)&1) printf("ebp=%x ",(u_int)constmap[i][5]);
9206       if((regs[i].isconst>>6)&1) printf("esi=%x ",(u_int)constmap[i][6]);
9207       if((regs[i].isconst>>7)&1) printf("edi=%x ",(u_int)constmap[i][7]);
9208       #endif
9209       #if defined(__arm__) || defined(__aarch64__)
9210       int r;
9211       for (r = 0; r < ARRAY_SIZE(constmap[i]); r++)
9212         if ((regs[i].isconst >> r) & 1)
9213           printf(" r%d=%x", r, (u_int)constmap[i][r]);
9214       #endif
9215       printf("\n");
9216     }
9217     if(dops[i].is_jump) {
9218       #if defined(__i386__) || defined(__x86_64__)
9219       printf("branch(%d): eax=%d ecx=%d edx=%d ebx=%d ebp=%d esi=%d edi=%d dirty: ",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]);
9220       if(branch_regs[i].dirty&1) printf("eax ");
9221       if((branch_regs[i].dirty>>1)&1) printf("ecx ");
9222       if((branch_regs[i].dirty>>2)&1) printf("edx ");
9223       if((branch_regs[i].dirty>>3)&1) printf("ebx ");
9224       if((branch_regs[i].dirty>>5)&1) printf("ebp ");
9225       if((branch_regs[i].dirty>>6)&1) printf("esi ");
9226       if((branch_regs[i].dirty>>7)&1) printf("edi ");
9227       #endif
9228       #ifdef __arm__
9229       printf("branch(%d): r0=%d r1=%d r2=%d r3=%d r4=%d r5=%d r6=%d r7=%d r8=%d r9=%d r10=%d r12=%d dirty: ",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[4],branch_regs[i].regmap[5],branch_regs[i].regmap[6],branch_regs[i].regmap[7],branch_regs[i].regmap[8],branch_regs[i].regmap[9],branch_regs[i].regmap[10],branch_regs[i].regmap[12]);
9230       if(branch_regs[i].dirty&1) printf("r0 ");
9231       if((branch_regs[i].dirty>>1)&1) printf("r1 ");
9232       if((branch_regs[i].dirty>>2)&1) printf("r2 ");
9233       if((branch_regs[i].dirty>>3)&1) printf("r3 ");
9234       if((branch_regs[i].dirty>>4)&1) printf("r4 ");
9235       if((branch_regs[i].dirty>>5)&1) printf("r5 ");
9236       if((branch_regs[i].dirty>>6)&1) printf("r6 ");
9237       if((branch_regs[i].dirty>>7)&1) printf("r7 ");
9238       if((branch_regs[i].dirty>>8)&1) printf("r8 ");
9239       if((branch_regs[i].dirty>>9)&1) printf("r9 ");
9240       if((branch_regs[i].dirty>>10)&1) printf("r10 ");
9241       if((branch_regs[i].dirty>>12)&1) printf("r12 ");
9242       #endif
9243     }
9244   }
9245 #endif // REG_ALLOC_PRINT
9246
9247   /* Pass 8 - Assembly */
9248   linkcount=0;stubcount=0;
9249   ds=0;is_delayslot=0;
9250   u_int dirty_pre=0;
9251   void *beginning=start_block();
9252   if((u_int)addr&1) {
9253     ds=1;
9254     pagespan_ds();
9255   }
9256   void *instr_addr0_override = NULL;
9257
9258   if (start == 0x80030000) {
9259     // nasty hack for the fastbios thing
9260     // override block entry to this code
9261     instr_addr0_override = out;
9262     emit_movimm(start,0);
9263     // abuse io address var as a flag that we
9264     // have already returned here once
9265     emit_readword(&address,1);
9266     emit_writeword(0,&pcaddr);
9267     emit_writeword(0,&address);
9268     emit_cmp(0,1);
9269     #ifdef __aarch64__
9270     emit_jeq(out + 4*2);
9271     emit_far_jump(new_dyna_leave);
9272     #else
9273     emit_jne(new_dyna_leave);
9274     #endif
9275   }
9276   for(i=0;i<slen;i++)
9277   {
9278     __builtin_prefetch(regs[i+1].regmap);
9279     check_regmap(regmap_pre[i]);
9280     check_regmap(regs[i].regmap_entry);
9281     check_regmap(regs[i].regmap);
9282     //if(ds) printf("ds: ");
9283     disassemble_inst(i);
9284     if(ds) {
9285       ds=0; // Skip delay slot
9286       if(dops[i].bt) assem_debug("OOPS - branch into delay slot\n");
9287       instr_addr[i] = NULL;
9288     } else {
9289       speculate_register_values(i);
9290       #ifndef DESTRUCTIVE_WRITEBACK
9291       if (i < 2 || !dops[i-2].is_ujump)
9292       {
9293         wb_valid(regmap_pre[i],regs[i].regmap_entry,dirty_pre,regs[i].wasdirty,unneeded_reg[i]);
9294       }
9295       if((dops[i].itype==CJUMP||dops[i].itype==SJUMP)) {
9296         dirty_pre=branch_regs[i].dirty;
9297       }else{
9298         dirty_pre=regs[i].dirty;
9299       }
9300       #endif
9301       // write back
9302       if (i < 2 || !dops[i-2].is_ujump)
9303       {
9304         wb_invalidate(regmap_pre[i],regs[i].regmap_entry,regs[i].wasdirty,unneeded_reg[i]);
9305         loop_preload(regmap_pre[i],regs[i].regmap_entry);
9306       }
9307       // branch target entry point
9308       instr_addr[i] = out;
9309       assem_debug("<->\n");
9310       drc_dbg_emit_do_cmp(i, ccadj[i]);
9311       if (clear_hack_addr) {
9312         emit_movimm(0, 0);
9313         emit_writeword(0, &hack_addr);
9314         clear_hack_addr = 0;
9315       }
9316
9317       // load regs
9318       if(regs[i].regmap_entry[HOST_CCREG]==CCREG&&regs[i].regmap[HOST_CCREG]!=CCREG)
9319         wb_register(CCREG,regs[i].regmap_entry,regs[i].wasdirty);
9320       load_regs(regs[i].regmap_entry,regs[i].regmap,dops[i].rs1,dops[i].rs2);
9321       address_generation(i,&regs[i],regs[i].regmap_entry);
9322       load_consts(regmap_pre[i],regs[i].regmap,i);
9323       if(dops[i].is_jump)
9324       {
9325         // Load the delay slot registers if necessary
9326         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))
9327           load_regs(regs[i].regmap_entry,regs[i].regmap,dops[i+1].rs1,dops[i+1].rs1);
9328         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))
9329           load_regs(regs[i].regmap_entry,regs[i].regmap,dops[i+1].rs2,dops[i+1].rs2);
9330         if (ram_offset && (dops[i+1].is_load || dops[i+1].is_store))
9331           load_regs(regs[i].regmap_entry,regs[i].regmap,ROREG,ROREG);
9332         if (dops[i+1].is_store)
9333           load_regs(regs[i].regmap_entry,regs[i].regmap,INVCP,INVCP);
9334       }
9335       else if(i+1<slen)
9336       {
9337         // Preload registers for following instruction
9338         if(dops[i+1].rs1!=dops[i].rs1&&dops[i+1].rs1!=dops[i].rs2)
9339           if(dops[i+1].rs1!=dops[i].rt1&&dops[i+1].rs1!=dops[i].rt2)
9340             load_regs(regs[i].regmap_entry,regs[i].regmap,dops[i+1].rs1,dops[i+1].rs1);
9341         if(dops[i+1].rs2!=dops[i+1].rs1&&dops[i+1].rs2!=dops[i].rs1&&dops[i+1].rs2!=dops[i].rs2)
9342           if(dops[i+1].rs2!=dops[i].rt1&&dops[i+1].rs2!=dops[i].rt2)
9343             load_regs(regs[i].regmap_entry,regs[i].regmap,dops[i+1].rs2,dops[i+1].rs2);
9344       }
9345       // TODO: if(is_ooo(i)) address_generation(i+1);
9346       if (!dops[i].is_jump || dops[i].itype == CJUMP)
9347         load_regs(regs[i].regmap_entry,regs[i].regmap,CCREG,CCREG);
9348       if (ram_offset && (dops[i].is_load || dops[i].is_store))
9349         load_regs(regs[i].regmap_entry,regs[i].regmap,ROREG,ROREG);
9350       if (dops[i].is_store)
9351         load_regs(regs[i].regmap_entry,regs[i].regmap,INVCP,INVCP);
9352
9353       ds = assemble(i, &regs[i], ccadj[i]);
9354
9355       if (dops[i].is_ujump)
9356         literal_pool(1024);
9357       else
9358         literal_pool_jumpover(256);
9359     }
9360   }
9361
9362   assert(slen > 0);
9363   if (slen > 0 && dops[slen-1].itype == INTCALL) {
9364     // no ending needed for this block since INTCALL never returns
9365   }
9366   // If the block did not end with an unconditional branch,
9367   // add a jump to the next instruction.
9368   else if (i > 1) {
9369     if (!dops[i-2].is_ujump && dops[i-1].itype != SPAN) {
9370       assert(!dops[i-1].is_jump);
9371       assert(i==slen);
9372       if(dops[i-2].itype!=CJUMP&&dops[i-2].itype!=SJUMP) {
9373         store_regs_bt(regs[i-1].regmap,regs[i-1].dirty,start+i*4);
9374         if(regs[i-1].regmap[HOST_CCREG]!=CCREG)
9375           emit_loadreg(CCREG,HOST_CCREG);
9376         emit_addimm(HOST_CCREG, ccadj[i-1] + CLOCK_ADJUST(1), HOST_CCREG);
9377       }
9378       else
9379       {
9380         store_regs_bt(branch_regs[i-2].regmap,branch_regs[i-2].dirty,start+i*4);
9381         assert(branch_regs[i-2].regmap[HOST_CCREG]==CCREG);
9382       }
9383       add_to_linker(out,start+i*4,0);
9384       emit_jmp(0);
9385     }
9386   }
9387   else
9388   {
9389     assert(i>0);
9390     assert(!dops[i-1].is_jump);
9391     store_regs_bt(regs[i-1].regmap,regs[i-1].dirty,start+i*4);
9392     if(regs[i-1].regmap[HOST_CCREG]!=CCREG)
9393       emit_loadreg(CCREG,HOST_CCREG);
9394     emit_addimm(HOST_CCREG, ccadj[i-1] + CLOCK_ADJUST(1), HOST_CCREG);
9395     add_to_linker(out,start+i*4,0);
9396     emit_jmp(0);
9397   }
9398
9399   // TODO: delay slot stubs?
9400   // Stubs
9401   for(i=0;i<stubcount;i++)
9402   {
9403     switch(stubs[i].type)
9404     {
9405       case LOADB_STUB:
9406       case LOADH_STUB:
9407       case LOADW_STUB:
9408       case LOADD_STUB:
9409       case LOADBU_STUB:
9410       case LOADHU_STUB:
9411         do_readstub(i);break;
9412       case STOREB_STUB:
9413       case STOREH_STUB:
9414       case STOREW_STUB:
9415       case STORED_STUB:
9416         do_writestub(i);break;
9417       case CC_STUB:
9418         do_ccstub(i);break;
9419       case INVCODE_STUB:
9420         do_invstub(i);break;
9421       case FP_STUB:
9422         do_cop1stub(i);break;
9423       case STORELR_STUB:
9424         do_unalignedwritestub(i);break;
9425     }
9426   }
9427
9428   if (instr_addr0_override)
9429     instr_addr[0] = instr_addr0_override;
9430
9431   /* Pass 9 - Linker */
9432   for(i=0;i<linkcount;i++)
9433   {
9434     assem_debug("%p -> %8x\n",link_addr[i].addr,link_addr[i].target);
9435     literal_pool(64);
9436     if (!link_addr[i].ext)
9437     {
9438       void *stub = out;
9439       void *addr = check_addr(link_addr[i].target);
9440       emit_extjump(link_addr[i].addr, link_addr[i].target);
9441       if (addr) {
9442         set_jump_target(link_addr[i].addr, addr);
9443         add_jump_out(link_addr[i].target,stub);
9444       }
9445       else
9446         set_jump_target(link_addr[i].addr, stub);
9447     }
9448     else
9449     {
9450       // Internal branch
9451       int target=(link_addr[i].target-start)>>2;
9452       assert(target>=0&&target<slen);
9453       assert(instr_addr[target]);
9454       //#ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
9455       //set_jump_target_fillslot(link_addr[i].addr,instr_addr[target],link_addr[i].ext>>1);
9456       //#else
9457       set_jump_target(link_addr[i].addr, instr_addr[target]);
9458       //#endif
9459     }
9460   }
9461
9462   u_int source_len = slen*4;
9463   if (dops[slen-1].itype == INTCALL && source_len > 4)
9464     // no need to treat the last instruction as compiled
9465     // as interpreter fully handles it
9466     source_len -= 4;
9467
9468   if ((u_char *)copy + source_len > (u_char *)shadow + sizeof(shadow))
9469     copy = shadow;
9470
9471   // External Branch Targets (jump_in)
9472   for(i=0;i<slen;i++)
9473   {
9474     if(dops[i].bt||i==0)
9475     {
9476       if(instr_addr[i]) // TODO - delay slots (=null)
9477       {
9478         u_int vaddr=start+i*4;
9479         u_int page=get_page(vaddr);
9480         u_int vpage=get_vpage(vaddr);
9481         literal_pool(256);
9482         {
9483           assem_debug("%p (%d) <- %8x\n",instr_addr[i],i,start+i*4);
9484           assem_debug("jump_in: %x\n",start+i*4);
9485           ll_add(jump_dirty+vpage,vaddr,out);
9486           void *entry_point = do_dirty_stub(i, source_len);
9487           ll_add_flags(jump_in+page,vaddr,state_rflags,entry_point);
9488           // If there was an existing entry in the hash table,
9489           // replace it with the new address.
9490           // Don't add new entries.  We'll insert the
9491           // ones that actually get used in check_addr().
9492           struct ht_entry *ht_bin = hash_table_get(vaddr);
9493           if (ht_bin->vaddr[0] == vaddr)
9494             ht_bin->tcaddr[0] = entry_point;
9495           if (ht_bin->vaddr[1] == vaddr)
9496             ht_bin->tcaddr[1] = entry_point;
9497         }
9498       }
9499     }
9500   }
9501   // Write out the literal pool if necessary
9502   literal_pool(0);
9503   #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
9504   // Align code
9505   if(((u_int)out)&7) emit_addnop(13);
9506   #endif
9507   assert(out - (u_char *)beginning < MAX_OUTPUT_BLOCK_SIZE);
9508   //printf("shadow buffer: %p-%p\n",copy,(u_char *)copy+slen*4);
9509   memcpy(copy, source, source_len);
9510   copy += source_len;
9511
9512   end_block(beginning);
9513
9514   // If we're within 256K of the end of the buffer,
9515   // start over from the beginning. (Is 256K enough?)
9516   if (out > ndrc->translation_cache + sizeof(ndrc->translation_cache) - MAX_OUTPUT_BLOCK_SIZE)
9517     out = ndrc->translation_cache;
9518
9519   // Trap writes to any of the pages we compiled
9520   for(i=start>>12;i<=(start+slen*4)>>12;i++) {
9521     invalid_code[i]=0;
9522   }
9523   inv_code_start=inv_code_end=~0;
9524
9525   // for PCSX we need to mark all mirrors too
9526   if(get_page(start)<(RAM_SIZE>>12))
9527     for(i=start>>12;i<=(start+slen*4)>>12;i++)
9528       invalid_code[((u_int)0x00000000>>12)|(i&0x1ff)]=
9529       invalid_code[((u_int)0x80000000>>12)|(i&0x1ff)]=
9530       invalid_code[((u_int)0xa0000000>>12)|(i&0x1ff)]=0;
9531
9532   /* Pass 10 - Free memory by expiring oldest blocks */
9533
9534   int end=(((out-ndrc->translation_cache)>>(TARGET_SIZE_2-16))+16384)&65535;
9535   while(expirep!=end)
9536   {
9537     int shift=TARGET_SIZE_2-3; // Divide into 8 blocks
9538     uintptr_t base_offs = ((uintptr_t)(expirep >> 13) << shift); // Base offset of this block
9539     uintptr_t base_offs_s = base_offs >> shift;
9540     inv_debug("EXP: Phase %d\n",expirep);
9541     switch((expirep>>11)&3)
9542     {
9543       case 0:
9544         // Clear jump_in and jump_dirty
9545         ll_remove_matching_addrs(jump_in+(expirep&2047),base_offs_s,shift);
9546         ll_remove_matching_addrs(jump_dirty+(expirep&2047),base_offs_s,shift);
9547         ll_remove_matching_addrs(jump_in+2048+(expirep&2047),base_offs_s,shift);
9548         ll_remove_matching_addrs(jump_dirty+2048+(expirep&2047),base_offs_s,shift);
9549         break;
9550       case 1:
9551         // Clear pointers
9552         ll_kill_pointers(jump_out[expirep&2047],base_offs_s,shift);
9553         ll_kill_pointers(jump_out[(expirep&2047)+2048],base_offs_s,shift);
9554         break;
9555       case 2:
9556         // Clear hash table
9557         for(i=0;i<32;i++) {
9558           struct ht_entry *ht_bin = &hash_table[((expirep&2047)<<5)+i];
9559           uintptr_t o1 = (u_char *)ht_bin->tcaddr[1] - ndrc->translation_cache;
9560           uintptr_t o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
9561           if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s) {
9562             inv_debug("EXP: Remove hash %x -> %p\n",ht_bin->vaddr[1],ht_bin->tcaddr[1]);
9563             ht_bin->vaddr[1] = -1;
9564             ht_bin->tcaddr[1] = NULL;
9565           }
9566           o1 = (u_char *)ht_bin->tcaddr[0] - ndrc->translation_cache;
9567           o2 = o1 - MAX_OUTPUT_BLOCK_SIZE;
9568           if ((o1 >> shift) == base_offs_s || (o2 >> shift) == base_offs_s) {
9569             inv_debug("EXP: Remove hash %x -> %p\n",ht_bin->vaddr[0],ht_bin->tcaddr[0]);
9570             ht_bin->vaddr[0] = ht_bin->vaddr[1];
9571             ht_bin->tcaddr[0] = ht_bin->tcaddr[1];
9572             ht_bin->vaddr[1] = -1;
9573             ht_bin->tcaddr[1] = NULL;
9574           }
9575         }
9576         break;
9577       case 3:
9578         // Clear jump_out
9579         if((expirep&2047)==0)
9580           do_clear_cache();
9581         ll_remove_matching_addrs(jump_out+(expirep&2047),base_offs_s,shift);
9582         ll_remove_matching_addrs(jump_out+2048+(expirep&2047),base_offs_s,shift);
9583         break;
9584     }
9585     expirep=(expirep+1)&65535;
9586   }
9587 #ifdef ASSEM_PRINT
9588   fflush(stdout);
9589 #endif
9590   return 0;
9591 }
9592
9593 // vim:shiftwidth=2:expandtab