cb6a88b9920854eb9ea13ca4b209ecb77303cd6d
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / assem_arm.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   Mupen64plus/PCSX - assem_arm.c                                        *
3  *   Copyright (C) 2009-2011 Ari64                                         *
4  *   Copyright (C) 2010-2011 GraÅžvydas "notaz" Ignotas                     *
5  *                                                                         *
6  *   This program is free software; you can redistribute it and/or modify  *
7  *   it under the terms of the GNU General Public License as published by  *
8  *   the Free Software Foundation; either version 2 of the License, or     *
9  *   (at your option) any later version.                                   *
10  *                                                                         *
11  *   This program is distributed in the hope that it will be useful,       *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14  *   GNU General Public License for more details.                          *
15  *                                                                         *
16  *   You should have received a copy of the GNU General Public License     *
17  *   along with this program; if not, write to the                         *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
20  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22 #ifdef PCSX
23 #include "../gte.h"
24 #define FLAGLESS
25 #include "../gte.h"
26 #undef FLAGLESS
27 #include "../gte_arm.h"
28 #include "../gte_neon.h"
29 #include "pcnt.h"
30 #endif
31 #include "arm_features.h"
32
33 #if !BASE_ADDR_FIXED
34 char translation_cache[1 << TARGET_SIZE_2] __attribute__((aligned(4096)));
35 #endif
36
37 extern int cycle_count;
38 extern int last_count;
39 extern int pcaddr;
40 extern int pending_exception;
41 extern int branch_target;
42 extern uint64_t readmem_dword;
43 #ifdef MUPEN64
44 extern precomp_instr fake_pc;
45 #endif
46 extern void *dynarec_local;
47 extern u_int memory_map[1048576];
48 extern u_int mini_ht[32][2];
49 extern u_int rounding_modes[4];
50
51 void indirect_jump_indexed();
52 void indirect_jump();
53 void do_interrupt();
54 void jump_vaddr_r0();
55 void jump_vaddr_r1();
56 void jump_vaddr_r2();
57 void jump_vaddr_r3();
58 void jump_vaddr_r4();
59 void jump_vaddr_r5();
60 void jump_vaddr_r6();
61 void jump_vaddr_r7();
62 void jump_vaddr_r8();
63 void jump_vaddr_r9();
64 void jump_vaddr_r10();
65 void jump_vaddr_r12();
66
67 const u_int jump_vaddr_reg[16] = {
68   (int)jump_vaddr_r0,
69   (int)jump_vaddr_r1,
70   (int)jump_vaddr_r2,
71   (int)jump_vaddr_r3,
72   (int)jump_vaddr_r4,
73   (int)jump_vaddr_r5,
74   (int)jump_vaddr_r6,
75   (int)jump_vaddr_r7,
76   (int)jump_vaddr_r8,
77   (int)jump_vaddr_r9,
78   (int)jump_vaddr_r10,
79   0,
80   (int)jump_vaddr_r12,
81   0,
82   0,
83   0};
84
85 void invalidate_addr_r0();
86 void invalidate_addr_r1();
87 void invalidate_addr_r2();
88 void invalidate_addr_r3();
89 void invalidate_addr_r4();
90 void invalidate_addr_r5();
91 void invalidate_addr_r6();
92 void invalidate_addr_r7();
93 void invalidate_addr_r8();
94 void invalidate_addr_r9();
95 void invalidate_addr_r10();
96 void invalidate_addr_r12();
97
98 const u_int invalidate_addr_reg[16] = {
99   (int)invalidate_addr_r0,
100   (int)invalidate_addr_r1,
101   (int)invalidate_addr_r2,
102   (int)invalidate_addr_r3,
103   (int)invalidate_addr_r4,
104   (int)invalidate_addr_r5,
105   (int)invalidate_addr_r6,
106   (int)invalidate_addr_r7,
107   (int)invalidate_addr_r8,
108   (int)invalidate_addr_r9,
109   (int)invalidate_addr_r10,
110   0,
111   (int)invalidate_addr_r12,
112   0,
113   0,
114   0};
115
116 #include "fpu.h"
117
118 unsigned int needs_clear_cache[1<<(TARGET_SIZE_2-17)];
119
120 /* Linker */
121
122 void set_jump_target(int addr,u_int target)
123 {
124   u_char *ptr=(u_char *)addr;
125   u_int *ptr2=(u_int *)ptr;
126   if(ptr[3]==0xe2) {
127     assert((target-(u_int)ptr2-8)<1024);
128     assert((addr&3)==0);
129     assert((target&3)==0);
130     *ptr2=(*ptr2&0xFFFFF000)|((target-(u_int)ptr2-8)>>2)|0xF00;
131     //printf("target=%x addr=%x insn=%x\n",target,addr,*ptr2);
132   }
133   else if(ptr[3]==0x72) {
134     // generated by emit_jno_unlikely
135     if((target-(u_int)ptr2-8)<1024) {
136       assert((addr&3)==0);
137       assert((target&3)==0);
138       *ptr2=(*ptr2&0xFFFFF000)|((target-(u_int)ptr2-8)>>2)|0xF00;
139     }
140     else if((target-(u_int)ptr2-8)<4096&&!((target-(u_int)ptr2-8)&15)) {
141       assert((addr&3)==0);
142       assert((target&3)==0);
143       *ptr2=(*ptr2&0xFFFFF000)|((target-(u_int)ptr2-8)>>4)|0xE00;
144     }
145     else *ptr2=(0x7A000000)|(((target-(u_int)ptr2-8)<<6)>>8);
146   }
147   else {
148     assert((ptr[3]&0x0e)==0xa);
149     *ptr2=(*ptr2&0xFF000000)|(((target-(u_int)ptr2-8)<<6)>>8);
150   }
151 }
152
153 // This optionally copies the instruction from the target of the branch into
154 // the space before the branch.  Works, but the difference in speed is
155 // usually insignificant.
156 void set_jump_target_fillslot(int addr,u_int target,int copy)
157 {
158   u_char *ptr=(u_char *)addr;
159   u_int *ptr2=(u_int *)ptr;
160   assert(!copy||ptr2[-1]==0xe28dd000);
161   if(ptr[3]==0xe2) {
162     assert(!copy);
163     assert((target-(u_int)ptr2-8)<4096);
164     *ptr2=(*ptr2&0xFFFFF000)|(target-(u_int)ptr2-8);
165   }
166   else {
167     assert((ptr[3]&0x0e)==0xa);
168     u_int target_insn=*(u_int *)target;
169     if((target_insn&0x0e100000)==0) { // ALU, no immediate, no flags
170       copy=0;
171     }
172     if((target_insn&0x0c100000)==0x04100000) { // Load
173       copy=0;
174     }
175     if(target_insn&0x08000000) {
176       copy=0;
177     }
178     if(copy) {
179       ptr2[-1]=target_insn;
180       target+=4;
181     }
182     *ptr2=(*ptr2&0xFF000000)|(((target-(u_int)ptr2-8)<<6)>>8);
183   }
184 }
185
186 /* Literal pool */
187 add_literal(int addr,int val)
188 {
189   assert(literalcount<sizeof(literals)/sizeof(literals[0]));
190   literals[literalcount][0]=addr;
191   literals[literalcount][1]=val;
192   literalcount++; 
193
194
195 void *kill_pointer(void *stub)
196 {
197   int *ptr=(int *)(stub+4);
198   assert((*ptr&0x0ff00000)==0x05900000);
199   u_int offset=*ptr&0xfff;
200   int **l_ptr=(void *)ptr+offset+8;
201   int *i_ptr=*l_ptr;
202   set_jump_target((int)i_ptr,(int)stub);
203   return i_ptr;
204 }
205
206 // find where external branch is liked to using addr of it's stub:
207 // get address that insn one after stub loads (dyna_linker arg1),
208 // treat it as a pointer to branch insn,
209 // return addr where that branch jumps to
210 int get_pointer(void *stub)
211 {
212   //printf("get_pointer(%x)\n",(int)stub);
213   int *ptr=(int *)(stub+4);
214   assert((*ptr&0x0fff0000)==0x059f0000);
215   u_int offset=*ptr&0xfff;
216   int **l_ptr=(void *)ptr+offset+8;
217   int *i_ptr=*l_ptr;
218   assert((*i_ptr&0x0f000000)==0x0a000000);
219   return (int)i_ptr+((*i_ptr<<8)>>6)+8;
220 }
221
222 // Find the "clean" entry point from a "dirty" entry point
223 // by skipping past the call to verify_code
224 u_int get_clean_addr(int addr)
225 {
226   int *ptr=(int *)addr;
227   #ifndef HAVE_ARMV7
228   ptr+=4;
229   #else
230   ptr+=6;
231   #endif
232   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
233   assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
234   ptr++;
235   if((*ptr&0xFF000000)==0xea000000) {
236     return (int)ptr+((*ptr<<8)>>6)+8; // follow jump
237   }
238   return (u_int)ptr;
239 }
240
241 int verify_dirty(int addr)
242 {
243   u_int *ptr=(u_int *)addr;
244   #ifndef HAVE_ARMV7
245   // get from literal pool
246   assert((*ptr&0xFFFF0000)==0xe59f0000);
247   u_int offset=*ptr&0xfff;
248   u_int *l_ptr=(void *)ptr+offset+8;
249   u_int source=l_ptr[0];
250   u_int copy=l_ptr[1];
251   u_int len=l_ptr[2];
252   ptr+=4;
253   #else
254   // ARMv7 movw/movt
255   assert((*ptr&0xFFF00000)==0xe3000000);
256   u_int source=(ptr[0]&0xFFF)+((ptr[0]>>4)&0xF000)+((ptr[2]<<16)&0xFFF0000)+((ptr[2]<<12)&0xF0000000);
257   u_int copy=(ptr[1]&0xFFF)+((ptr[1]>>4)&0xF000)+((ptr[3]<<16)&0xFFF0000)+((ptr[3]<<12)&0xF0000000);
258   u_int len=(ptr[4]&0xFFF)+((ptr[4]>>4)&0xF000);
259   ptr+=6;
260   #endif
261   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
262   assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
263 #ifndef DISABLE_TLB
264   u_int verifier=(int)ptr+((signed int)(*ptr<<8)>>6)+8; // get target of bl
265   if(verifier==(u_int)verify_code_vm||verifier==(u_int)verify_code_ds) {
266     unsigned int page=source>>12;
267     unsigned int map_value=memory_map[page];
268     if(map_value>=0x80000000) return 0;
269     while(page<((source+len-1)>>12)) {
270       if((memory_map[++page]<<2)!=(map_value<<2)) return 0;
271     }
272     source = source+(map_value<<2);
273   }
274 #endif
275   //printf("verify_dirty: %x %x %x\n",source,copy,len);
276   return !memcmp((void *)source,(void *)copy,len);
277 }
278
279 // This doesn't necessarily find all clean entry points, just
280 // guarantees that it's not dirty
281 int isclean(int addr)
282 {
283   #ifndef HAVE_ARMV7
284   int *ptr=((u_int *)addr)+4;
285   #else
286   int *ptr=((u_int *)addr)+6;
287   #endif
288   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
289   if((*ptr&0xFF000000)!=0xeb000000) return 1; // bl instruction
290   if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code) return 0;
291   if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code_vm) return 0;
292   if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code_ds) return 0;
293   return 1;
294 }
295
296 // get source that block at addr was compiled from (host pointers)
297 void get_bounds(int addr,u_int *start,u_int *end)
298 {
299   u_int *ptr=(u_int *)addr;
300   #ifndef HAVE_ARMV7
301   // get from literal pool
302   assert((*ptr&0xFFFF0000)==0xe59f0000);
303   u_int offset=*ptr&0xfff;
304   u_int *l_ptr=(void *)ptr+offset+8;
305   u_int source=l_ptr[0];
306   //u_int copy=l_ptr[1];
307   u_int len=l_ptr[2];
308   ptr+=4;
309   #else
310   // ARMv7 movw/movt
311   assert((*ptr&0xFFF00000)==0xe3000000);
312   u_int source=(ptr[0]&0xFFF)+((ptr[0]>>4)&0xF000)+((ptr[2]<<16)&0xFFF0000)+((ptr[2]<<12)&0xF0000000);
313   //u_int copy=(ptr[1]&0xFFF)+((ptr[1]>>4)&0xF000)+((ptr[3]<<16)&0xFFF0000)+((ptr[3]<<12)&0xF0000000);
314   u_int len=(ptr[4]&0xFFF)+((ptr[4]>>4)&0xF000);
315   ptr+=6;
316   #endif
317   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
318   assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
319 #ifndef DISABLE_TLB
320   u_int verifier=(int)ptr+((signed int)(*ptr<<8)>>6)+8; // get target of bl
321   if(verifier==(u_int)verify_code_vm||verifier==(u_int)verify_code_ds) {
322     if(memory_map[source>>12]>=0x80000000) source = 0;
323     else source = source+(memory_map[source>>12]<<2);
324   }
325 #endif
326   *start=source;
327   *end=source+len;
328 }
329
330 /* Register allocation */
331
332 // Note: registers are allocated clean (unmodified state)
333 // if you intend to modify the register, you must call dirty_reg().
334 void alloc_reg(struct regstat *cur,int i,signed char reg)
335 {
336   int r,hr;
337   int preferred_reg = (reg&7);
338   if(reg==CCREG) preferred_reg=HOST_CCREG;
339   if(reg==PTEMP||reg==FTEMP) preferred_reg=12;
340   
341   // Don't allocate unused registers
342   if((cur->u>>reg)&1) return;
343   
344   // see if it's already allocated
345   for(hr=0;hr<HOST_REGS;hr++)
346   {
347     if(cur->regmap[hr]==reg) return;
348   }
349   
350   // Keep the same mapping if the register was already allocated in a loop
351   preferred_reg = loop_reg(i,reg,preferred_reg);
352   
353   // Try to allocate the preferred register
354   if(cur->regmap[preferred_reg]==-1) {
355     cur->regmap[preferred_reg]=reg;
356     cur->dirty&=~(1<<preferred_reg);
357     cur->isconst&=~(1<<preferred_reg);
358     return;
359   }
360   r=cur->regmap[preferred_reg];
361   if(r<64&&((cur->u>>r)&1)) {
362     cur->regmap[preferred_reg]=reg;
363     cur->dirty&=~(1<<preferred_reg);
364     cur->isconst&=~(1<<preferred_reg);
365     return;
366   }
367   if(r>=64&&((cur->uu>>(r&63))&1)) {
368     cur->regmap[preferred_reg]=reg;
369     cur->dirty&=~(1<<preferred_reg);
370     cur->isconst&=~(1<<preferred_reg);
371     return;
372   }
373   
374   // Clear any unneeded registers
375   // We try to keep the mapping consistent, if possible, because it
376   // makes branches easier (especially loops).  So we try to allocate
377   // first (see above) before removing old mappings.  If this is not
378   // possible then go ahead and clear out the registers that are no
379   // longer needed.
380   for(hr=0;hr<HOST_REGS;hr++)
381   {
382     r=cur->regmap[hr];
383     if(r>=0) {
384       if(r<64) {
385         if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
386       }
387       else
388       {
389         if((cur->uu>>(r&63))&1) {cur->regmap[hr]=-1;break;}
390       }
391     }
392   }
393   // Try to allocate any available register, but prefer
394   // registers that have not been used recently.
395   if(i>0) {
396     for(hr=0;hr<HOST_REGS;hr++) {
397       if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
398         if(regs[i-1].regmap[hr]!=rs1[i-1]&&regs[i-1].regmap[hr]!=rs2[i-1]&&regs[i-1].regmap[hr]!=rt1[i-1]&&regs[i-1].regmap[hr]!=rt2[i-1]) {
399           cur->regmap[hr]=reg;
400           cur->dirty&=~(1<<hr);
401           cur->isconst&=~(1<<hr);
402           return;
403         }
404       }
405     }
406   }
407   // Try to allocate any available register
408   for(hr=0;hr<HOST_REGS;hr++) {
409     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
410       cur->regmap[hr]=reg;
411       cur->dirty&=~(1<<hr);
412       cur->isconst&=~(1<<hr);
413       return;
414     }
415   }
416   
417   // Ok, now we have to evict someone
418   // Pick a register we hopefully won't need soon
419   u_char hsn[MAXREG+1];
420   memset(hsn,10,sizeof(hsn));
421   int j;
422   lsn(hsn,i,&preferred_reg);
423   //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]);
424   //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]);
425   if(i>0) {
426     // Don't evict the cycle count at entry points, otherwise the entry
427     // stub will have to write it.
428     if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
429     if(i>1&&hsn[CCREG]>2&&(itype[i-2]==RJUMP||itype[i-2]==UJUMP||itype[i-2]==CJUMP||itype[i-2]==SJUMP||itype[i-2]==FJUMP)) hsn[CCREG]=2;
430     for(j=10;j>=3;j--)
431     {
432       // Alloc preferred register if available
433       if(hsn[r=cur->regmap[preferred_reg]&63]==j) {
434         for(hr=0;hr<HOST_REGS;hr++) {
435           // Evict both parts of a 64-bit register
436           if((cur->regmap[hr]&63)==r) {
437             cur->regmap[hr]=-1;
438             cur->dirty&=~(1<<hr);
439             cur->isconst&=~(1<<hr);
440           }
441         }
442         cur->regmap[preferred_reg]=reg;
443         return;
444       }
445       for(r=1;r<=MAXREG;r++)
446       {
447         if(hsn[r]==j&&r!=rs1[i-1]&&r!=rs2[i-1]&&r!=rt1[i-1]&&r!=rt2[i-1]) {
448           for(hr=0;hr<HOST_REGS;hr++) {
449             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
450               if(cur->regmap[hr]==r+64) {
451                 cur->regmap[hr]=reg;
452                 cur->dirty&=~(1<<hr);
453                 cur->isconst&=~(1<<hr);
454                 return;
455               }
456             }
457           }
458           for(hr=0;hr<HOST_REGS;hr++) {
459             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
460               if(cur->regmap[hr]==r) {
461                 cur->regmap[hr]=reg;
462                 cur->dirty&=~(1<<hr);
463                 cur->isconst&=~(1<<hr);
464                 return;
465               }
466             }
467           }
468         }
469       }
470     }
471   }
472   for(j=10;j>=0;j--)
473   {
474     for(r=1;r<=MAXREG;r++)
475     {
476       if(hsn[r]==j) {
477         for(hr=0;hr<HOST_REGS;hr++) {
478           if(cur->regmap[hr]==r+64) {
479             cur->regmap[hr]=reg;
480             cur->dirty&=~(1<<hr);
481             cur->isconst&=~(1<<hr);
482             return;
483           }
484         }
485         for(hr=0;hr<HOST_REGS;hr++) {
486           if(cur->regmap[hr]==r) {
487             cur->regmap[hr]=reg;
488             cur->dirty&=~(1<<hr);
489             cur->isconst&=~(1<<hr);
490             return;
491           }
492         }
493       }
494     }
495   }
496   SysPrintf("This shouldn't happen (alloc_reg)");exit(1);
497 }
498
499 void alloc_reg64(struct regstat *cur,int i,signed char reg)
500 {
501   int preferred_reg = 8+(reg&1);
502   int r,hr;
503   
504   // allocate the lower 32 bits
505   alloc_reg(cur,i,reg);
506   
507   // Don't allocate unused registers
508   if((cur->uu>>reg)&1) return;
509   
510   // see if the upper half is already allocated
511   for(hr=0;hr<HOST_REGS;hr++)
512   {
513     if(cur->regmap[hr]==reg+64) return;
514   }
515   
516   // Keep the same mapping if the register was already allocated in a loop
517   preferred_reg = loop_reg(i,reg,preferred_reg);
518   
519   // Try to allocate the preferred register
520   if(cur->regmap[preferred_reg]==-1) {
521     cur->regmap[preferred_reg]=reg|64;
522     cur->dirty&=~(1<<preferred_reg);
523     cur->isconst&=~(1<<preferred_reg);
524     return;
525   }
526   r=cur->regmap[preferred_reg];
527   if(r<64&&((cur->u>>r)&1)) {
528     cur->regmap[preferred_reg]=reg|64;
529     cur->dirty&=~(1<<preferred_reg);
530     cur->isconst&=~(1<<preferred_reg);
531     return;
532   }
533   if(r>=64&&((cur->uu>>(r&63))&1)) {
534     cur->regmap[preferred_reg]=reg|64;
535     cur->dirty&=~(1<<preferred_reg);
536     cur->isconst&=~(1<<preferred_reg);
537     return;
538   }
539   
540   // Clear any unneeded registers
541   // We try to keep the mapping consistent, if possible, because it
542   // makes branches easier (especially loops).  So we try to allocate
543   // first (see above) before removing old mappings.  If this is not
544   // possible then go ahead and clear out the registers that are no
545   // longer needed.
546   for(hr=HOST_REGS-1;hr>=0;hr--)
547   {
548     r=cur->regmap[hr];
549     if(r>=0) {
550       if(r<64) {
551         if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
552       }
553       else
554       {
555         if((cur->uu>>(r&63))&1) {cur->regmap[hr]=-1;break;}
556       }
557     }
558   }
559   // Try to allocate any available register, but prefer
560   // registers that have not been used recently.
561   if(i>0) {
562     for(hr=0;hr<HOST_REGS;hr++) {
563       if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
564         if(regs[i-1].regmap[hr]!=rs1[i-1]&&regs[i-1].regmap[hr]!=rs2[i-1]&&regs[i-1].regmap[hr]!=rt1[i-1]&&regs[i-1].regmap[hr]!=rt2[i-1]) {
565           cur->regmap[hr]=reg|64;
566           cur->dirty&=~(1<<hr);
567           cur->isconst&=~(1<<hr);
568           return;
569         }
570       }
571     }
572   }
573   // Try to allocate any available register
574   for(hr=0;hr<HOST_REGS;hr++) {
575     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
576       cur->regmap[hr]=reg|64;
577       cur->dirty&=~(1<<hr);
578       cur->isconst&=~(1<<hr);
579       return;
580     }
581   }
582   
583   // Ok, now we have to evict someone
584   // Pick a register we hopefully won't need soon
585   u_char hsn[MAXREG+1];
586   memset(hsn,10,sizeof(hsn));
587   int j;
588   lsn(hsn,i,&preferred_reg);
589   //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]);
590   //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]);
591   if(i>0) {
592     // Don't evict the cycle count at entry points, otherwise the entry
593     // stub will have to write it.
594     if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
595     if(i>1&&hsn[CCREG]>2&&(itype[i-2]==RJUMP||itype[i-2]==UJUMP||itype[i-2]==CJUMP||itype[i-2]==SJUMP||itype[i-2]==FJUMP)) hsn[CCREG]=2;
596     for(j=10;j>=3;j--)
597     {
598       // Alloc preferred register if available
599       if(hsn[r=cur->regmap[preferred_reg]&63]==j) {
600         for(hr=0;hr<HOST_REGS;hr++) {
601           // Evict both parts of a 64-bit register
602           if((cur->regmap[hr]&63)==r) {
603             cur->regmap[hr]=-1;
604             cur->dirty&=~(1<<hr);
605             cur->isconst&=~(1<<hr);
606           }
607         }
608         cur->regmap[preferred_reg]=reg|64;
609         return;
610       }
611       for(r=1;r<=MAXREG;r++)
612       {
613         if(hsn[r]==j&&r!=rs1[i-1]&&r!=rs2[i-1]&&r!=rt1[i-1]&&r!=rt2[i-1]) {
614           for(hr=0;hr<HOST_REGS;hr++) {
615             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
616               if(cur->regmap[hr]==r+64) {
617                 cur->regmap[hr]=reg|64;
618                 cur->dirty&=~(1<<hr);
619                 cur->isconst&=~(1<<hr);
620                 return;
621               }
622             }
623           }
624           for(hr=0;hr<HOST_REGS;hr++) {
625             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
626               if(cur->regmap[hr]==r) {
627                 cur->regmap[hr]=reg|64;
628                 cur->dirty&=~(1<<hr);
629                 cur->isconst&=~(1<<hr);
630                 return;
631               }
632             }
633           }
634         }
635       }
636     }
637   }
638   for(j=10;j>=0;j--)
639   {
640     for(r=1;r<=MAXREG;r++)
641     {
642       if(hsn[r]==j) {
643         for(hr=0;hr<HOST_REGS;hr++) {
644           if(cur->regmap[hr]==r+64) {
645             cur->regmap[hr]=reg|64;
646             cur->dirty&=~(1<<hr);
647             cur->isconst&=~(1<<hr);
648             return;
649           }
650         }
651         for(hr=0;hr<HOST_REGS;hr++) {
652           if(cur->regmap[hr]==r) {
653             cur->regmap[hr]=reg|64;
654             cur->dirty&=~(1<<hr);
655             cur->isconst&=~(1<<hr);
656             return;
657           }
658         }
659       }
660     }
661   }
662   SysPrintf("This shouldn't happen");exit(1);
663 }
664
665 // Allocate a temporary register.  This is done without regard to
666 // dirty status or whether the register we request is on the unneeded list
667 // Note: This will only allocate one register, even if called multiple times
668 void alloc_reg_temp(struct regstat *cur,int i,signed char reg)
669 {
670   int r,hr;
671   int preferred_reg = -1;
672   
673   // see if it's already allocated
674   for(hr=0;hr<HOST_REGS;hr++)
675   {
676     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==reg) return;
677   }
678   
679   // Try to allocate any available register
680   for(hr=HOST_REGS-1;hr>=0;hr--) {
681     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
682       cur->regmap[hr]=reg;
683       cur->dirty&=~(1<<hr);
684       cur->isconst&=~(1<<hr);
685       return;
686     }
687   }
688   
689   // Find an unneeded register
690   for(hr=HOST_REGS-1;hr>=0;hr--)
691   {
692     r=cur->regmap[hr];
693     if(r>=0) {
694       if(r<64) {
695         if((cur->u>>r)&1) {
696           if(i==0||((unneeded_reg[i-1]>>r)&1)) {
697             cur->regmap[hr]=reg;
698             cur->dirty&=~(1<<hr);
699             cur->isconst&=~(1<<hr);
700             return;
701           }
702         }
703       }
704       else
705       {
706         if((cur->uu>>(r&63))&1) {
707           if(i==0||((unneeded_reg_upper[i-1]>>(r&63))&1)) {
708             cur->regmap[hr]=reg;
709             cur->dirty&=~(1<<hr);
710             cur->isconst&=~(1<<hr);
711             return;
712           }
713         }
714       }
715     }
716   }
717   
718   // Ok, now we have to evict someone
719   // Pick a register we hopefully won't need soon
720   // TODO: we might want to follow unconditional jumps here
721   // TODO: get rid of dupe code and make this into a function
722   u_char hsn[MAXREG+1];
723   memset(hsn,10,sizeof(hsn));
724   int j;
725   lsn(hsn,i,&preferred_reg);
726   //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]);
727   if(i>0) {
728     // Don't evict the cycle count at entry points, otherwise the entry
729     // stub will have to write it.
730     if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
731     if(i>1&&hsn[CCREG]>2&&(itype[i-2]==RJUMP||itype[i-2]==UJUMP||itype[i-2]==CJUMP||itype[i-2]==SJUMP||itype[i-2]==FJUMP)) hsn[CCREG]=2;
732     for(j=10;j>=3;j--)
733     {
734       for(r=1;r<=MAXREG;r++)
735       {
736         if(hsn[r]==j&&r!=rs1[i-1]&&r!=rs2[i-1]&&r!=rt1[i-1]&&r!=rt2[i-1]) {
737           for(hr=0;hr<HOST_REGS;hr++) {
738             if(hr!=HOST_CCREG||hsn[CCREG]>2) {
739               if(cur->regmap[hr]==r+64) {
740                 cur->regmap[hr]=reg;
741                 cur->dirty&=~(1<<hr);
742                 cur->isconst&=~(1<<hr);
743                 return;
744               }
745             }
746           }
747           for(hr=0;hr<HOST_REGS;hr++) {
748             if(hr!=HOST_CCREG||hsn[CCREG]>2) {
749               if(cur->regmap[hr]==r) {
750                 cur->regmap[hr]=reg;
751                 cur->dirty&=~(1<<hr);
752                 cur->isconst&=~(1<<hr);
753                 return;
754               }
755             }
756           }
757         }
758       }
759     }
760   }
761   for(j=10;j>=0;j--)
762   {
763     for(r=1;r<=MAXREG;r++)
764     {
765       if(hsn[r]==j) {
766         for(hr=0;hr<HOST_REGS;hr++) {
767           if(cur->regmap[hr]==r+64) {
768             cur->regmap[hr]=reg;
769             cur->dirty&=~(1<<hr);
770             cur->isconst&=~(1<<hr);
771             return;
772           }
773         }
774         for(hr=0;hr<HOST_REGS;hr++) {
775           if(cur->regmap[hr]==r) {
776             cur->regmap[hr]=reg;
777             cur->dirty&=~(1<<hr);
778             cur->isconst&=~(1<<hr);
779             return;
780           }
781         }
782       }
783     }
784   }
785   SysPrintf("This shouldn't happen");exit(1);
786 }
787 // Allocate a specific ARM register.
788 void alloc_arm_reg(struct regstat *cur,int i,signed char reg,char hr)
789 {
790   int n;
791   int dirty=0;
792   
793   // see if it's already allocated (and dealloc it)
794   for(n=0;n<HOST_REGS;n++)
795   {
796     if(n!=EXCLUDE_REG&&cur->regmap[n]==reg) {
797       dirty=(cur->dirty>>n)&1;
798       cur->regmap[n]=-1;
799     }
800   }
801   
802   cur->regmap[hr]=reg;
803   cur->dirty&=~(1<<hr);
804   cur->dirty|=dirty<<hr;
805   cur->isconst&=~(1<<hr);
806 }
807
808 // Alloc cycle count into dedicated register
809 alloc_cc(struct regstat *cur,int i)
810 {
811   alloc_arm_reg(cur,i,CCREG,HOST_CCREG);
812 }
813
814 /* Special alloc */
815
816
817 /* Assembler */
818
819 char regname[16][4] = {
820  "r0",
821  "r1",
822  "r2",
823  "r3",
824  "r4",
825  "r5",
826  "r6",
827  "r7",
828  "r8",
829  "r9",
830  "r10",
831  "fp",
832  "r12",
833  "sp",
834  "lr",
835  "pc"};
836
837 void output_byte(u_char byte)
838 {
839   *(out++)=byte;
840 }
841 void output_modrm(u_char mod,u_char rm,u_char ext)
842 {
843   assert(mod<4);
844   assert(rm<8);
845   assert(ext<8);
846   u_char byte=(mod<<6)|(ext<<3)|rm;
847   *(out++)=byte;
848 }
849 void output_sib(u_char scale,u_char index,u_char base)
850 {
851   assert(scale<4);
852   assert(index<8);
853   assert(base<8);
854   u_char byte=(scale<<6)|(index<<3)|base;
855   *(out++)=byte;
856 }
857 void output_w32(u_int word)
858 {
859   *((u_int *)out)=word;
860   out+=4;
861 }
862 u_int rd_rn_rm(u_int rd, u_int rn, u_int rm)
863 {
864   assert(rd<16);
865   assert(rn<16);
866   assert(rm<16);
867   return((rn<<16)|(rd<<12)|rm);
868 }
869 u_int rd_rn_imm_shift(u_int rd, u_int rn, u_int imm, u_int shift)
870 {
871   assert(rd<16);
872   assert(rn<16);
873   assert(imm<256);
874   assert((shift&1)==0);
875   return((rn<<16)|(rd<<12)|(((32-shift)&30)<<7)|imm);
876 }
877 u_int genimm(u_int imm,u_int *encoded)
878 {
879   *encoded=0;
880   if(imm==0) return 1;
881   int i=32;
882   while(i>0)
883   {
884     if(imm<256) {
885       *encoded=((i&30)<<7)|imm;
886       return 1;
887     }
888     imm=(imm>>2)|(imm<<30);i-=2;
889   }
890   return 0;
891 }
892 void genimm_checked(u_int imm,u_int *encoded)
893 {
894   u_int ret=genimm(imm,encoded);
895   assert(ret);
896 }
897 u_int genjmp(u_int addr)
898 {
899   int offset=addr-(int)out-8;
900   if(offset<-33554432||offset>=33554432) {
901     if (addr>2) {
902       SysPrintf("genjmp: out of range: %08x\n", offset);
903       exit(1);
904     }
905     return 0;
906   }
907   return ((u_int)offset>>2)&0xffffff;
908 }
909
910 void emit_mov(int rs,int rt)
911 {
912   assem_debug("mov %s,%s\n",regname[rt],regname[rs]);
913   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs));
914 }
915
916 void emit_movs(int rs,int rt)
917 {
918   assem_debug("movs %s,%s\n",regname[rt],regname[rs]);
919   output_w32(0xe1b00000|rd_rn_rm(rt,0,rs));
920 }
921
922 void emit_add(int rs1,int rs2,int rt)
923 {
924   assem_debug("add %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
925   output_w32(0xe0800000|rd_rn_rm(rt,rs1,rs2));
926 }
927
928 void emit_adds(int rs1,int rs2,int rt)
929 {
930   assem_debug("adds %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
931   output_w32(0xe0900000|rd_rn_rm(rt,rs1,rs2));
932 }
933
934 void emit_adcs(int rs1,int rs2,int rt)
935 {
936   assem_debug("adcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
937   output_w32(0xe0b00000|rd_rn_rm(rt,rs1,rs2));
938 }
939
940 void emit_sbc(int rs1,int rs2,int rt)
941 {
942   assem_debug("sbc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
943   output_w32(0xe0c00000|rd_rn_rm(rt,rs1,rs2));
944 }
945
946 void emit_sbcs(int rs1,int rs2,int rt)
947 {
948   assem_debug("sbcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
949   output_w32(0xe0d00000|rd_rn_rm(rt,rs1,rs2));
950 }
951
952 void emit_neg(int rs, int rt)
953 {
954   assem_debug("rsb %s,%s,#0\n",regname[rt],regname[rs]);
955   output_w32(0xe2600000|rd_rn_rm(rt,rs,0));
956 }
957
958 void emit_negs(int rs, int rt)
959 {
960   assem_debug("rsbs %s,%s,#0\n",regname[rt],regname[rs]);
961   output_w32(0xe2700000|rd_rn_rm(rt,rs,0));
962 }
963
964 void emit_sub(int rs1,int rs2,int rt)
965 {
966   assem_debug("sub %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
967   output_w32(0xe0400000|rd_rn_rm(rt,rs1,rs2));
968 }
969
970 void emit_subs(int rs1,int rs2,int rt)
971 {
972   assem_debug("subs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
973   output_w32(0xe0500000|rd_rn_rm(rt,rs1,rs2));
974 }
975
976 void emit_zeroreg(int rt)
977 {
978   assem_debug("mov %s,#0\n",regname[rt]);
979   output_w32(0xe3a00000|rd_rn_rm(rt,0,0));
980 }
981
982 void emit_loadlp(u_int imm,u_int rt)
983 {
984   add_literal((int)out,imm);
985   assem_debug("ldr %s,pc+? [=%x]\n",regname[rt],imm);
986   output_w32(0xe5900000|rd_rn_rm(rt,15,0));
987 }
988 void emit_movw(u_int imm,u_int rt)
989 {
990   assert(imm<65536);
991   assem_debug("movw %s,#%d (0x%x)\n",regname[rt],imm,imm);
992   output_w32(0xe3000000|rd_rn_rm(rt,0,0)|(imm&0xfff)|((imm<<4)&0xf0000));
993 }
994 void emit_movt(u_int imm,u_int rt)
995 {
996   assem_debug("movt %s,#%d (0x%x)\n",regname[rt],imm&0xffff0000,imm&0xffff0000);
997   output_w32(0xe3400000|rd_rn_rm(rt,0,0)|((imm>>16)&0xfff)|((imm>>12)&0xf0000));
998 }
999 void emit_movimm(u_int imm,u_int rt)
1000 {
1001   u_int armval;
1002   if(genimm(imm,&armval)) {
1003     assem_debug("mov %s,#%d\n",regname[rt],imm);
1004     output_w32(0xe3a00000|rd_rn_rm(rt,0,0)|armval);
1005   }else if(genimm(~imm,&armval)) {
1006     assem_debug("mvn %s,#%d\n",regname[rt],imm);
1007     output_w32(0xe3e00000|rd_rn_rm(rt,0,0)|armval);
1008   }else if(imm<65536) {
1009     #ifndef HAVE_ARMV7
1010     assem_debug("mov %s,#%d\n",regname[rt],imm&0xFF00);
1011     output_w32(0xe3a00000|rd_rn_imm_shift(rt,0,imm>>8,8));
1012     assem_debug("add %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF);
1013     output_w32(0xe2800000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1014     #else
1015     emit_movw(imm,rt);
1016     #endif
1017   }else{
1018     #ifndef HAVE_ARMV7
1019     emit_loadlp(imm,rt);
1020     #else
1021     emit_movw(imm&0x0000FFFF,rt);
1022     emit_movt(imm&0xFFFF0000,rt);
1023     #endif
1024   }
1025 }
1026 void emit_pcreladdr(u_int rt)
1027 {
1028   assem_debug("add %s,pc,#?\n",regname[rt]);
1029   output_w32(0xe2800000|rd_rn_rm(rt,15,0));
1030 }
1031
1032 void emit_loadreg(int r, int hr)
1033 {
1034 #ifdef FORCE32
1035   if(r&64) {
1036     SysPrintf("64bit load in 32bit mode!\n");
1037     assert(0);
1038     return;
1039   }
1040 #endif
1041   if((r&63)==0)
1042     emit_zeroreg(hr);
1043   else {
1044     int addr=((int)reg)+((r&63)<<REG_SHIFT)+((r&64)>>4);
1045     if((r&63)==HIREG) addr=(int)&hi+((r&64)>>4);
1046     if((r&63)==LOREG) addr=(int)&lo+((r&64)>>4);
1047     if(r==CCREG) addr=(int)&cycle_count;
1048     if(r==CSREG) addr=(int)&Status;
1049     if(r==FSREG) addr=(int)&FCR31;
1050     if(r==INVCP) addr=(int)&invc_ptr;
1051     u_int offset = addr-(u_int)&dynarec_local;
1052     assert(offset<4096);
1053     assem_debug("ldr %s,fp+%d\n",regname[hr],offset);
1054     output_w32(0xe5900000|rd_rn_rm(hr,FP,0)|offset);
1055   }
1056 }
1057 void emit_storereg(int r, int hr)
1058 {
1059 #ifdef FORCE32
1060   if(r&64) {
1061     SysPrintf("64bit store in 32bit mode!\n");
1062     assert(0);
1063     return;
1064   }
1065 #endif
1066   int addr=((int)reg)+((r&63)<<REG_SHIFT)+((r&64)>>4);
1067   if((r&63)==HIREG) addr=(int)&hi+((r&64)>>4);
1068   if((r&63)==LOREG) addr=(int)&lo+((r&64)>>4);
1069   if(r==CCREG) addr=(int)&cycle_count;
1070   if(r==FSREG) addr=(int)&FCR31;
1071   u_int offset = addr-(u_int)&dynarec_local;
1072   assert(offset<4096);
1073   assem_debug("str %s,fp+%d\n",regname[hr],offset);
1074   output_w32(0xe5800000|rd_rn_rm(hr,FP,0)|offset);
1075 }
1076
1077 void emit_test(int rs, int rt)
1078 {
1079   assem_debug("tst %s,%s\n",regname[rs],regname[rt]);
1080   output_w32(0xe1100000|rd_rn_rm(0,rs,rt));
1081 }
1082
1083 void emit_testimm(int rs,int imm)
1084 {
1085   u_int armval;
1086   assem_debug("tst %s,#%d\n",regname[rs],imm);
1087   genimm_checked(imm,&armval);
1088   output_w32(0xe3100000|rd_rn_rm(0,rs,0)|armval);
1089 }
1090
1091 void emit_testeqimm(int rs,int imm)
1092 {
1093   u_int armval;
1094   assem_debug("tsteq %s,$%d\n",regname[rs],imm);
1095   genimm_checked(imm,&armval);
1096   output_w32(0x03100000|rd_rn_rm(0,rs,0)|armval);
1097 }
1098
1099 void emit_not(int rs,int rt)
1100 {
1101   assem_debug("mvn %s,%s\n",regname[rt],regname[rs]);
1102   output_w32(0xe1e00000|rd_rn_rm(rt,0,rs));
1103 }
1104
1105 void emit_mvnmi(int rs,int rt)
1106 {
1107   assem_debug("mvnmi %s,%s\n",regname[rt],regname[rs]);
1108   output_w32(0x41e00000|rd_rn_rm(rt,0,rs));
1109 }
1110
1111 void emit_and(u_int rs1,u_int rs2,u_int rt)
1112 {
1113   assem_debug("and %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1114   output_w32(0xe0000000|rd_rn_rm(rt,rs1,rs2));
1115 }
1116
1117 void emit_or(u_int rs1,u_int rs2,u_int rt)
1118 {
1119   assem_debug("orr %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1120   output_w32(0xe1800000|rd_rn_rm(rt,rs1,rs2));
1121 }
1122 void emit_or_and_set_flags(int rs1,int rs2,int rt)
1123 {
1124   assem_debug("orrs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1125   output_w32(0xe1900000|rd_rn_rm(rt,rs1,rs2));
1126 }
1127
1128 void emit_orrshl_imm(u_int rs,u_int imm,u_int rt)
1129 {
1130   assert(rs<16);
1131   assert(rt<16);
1132   assert(imm<32);
1133   assem_debug("orr %s,%s,%s,lsl #%d\n",regname[rt],regname[rt],regname[rs],imm);
1134   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs)|(imm<<7));
1135 }
1136
1137 void emit_orrshr_imm(u_int rs,u_int imm,u_int rt)
1138 {
1139   assert(rs<16);
1140   assert(rt<16);
1141   assert(imm<32);
1142   assem_debug("orr %s,%s,%s,lsr #%d\n",regname[rt],regname[rt],regname[rs],imm);
1143   output_w32(0xe1800020|rd_rn_rm(rt,rt,rs)|(imm<<7));
1144 }
1145
1146 void emit_xor(u_int rs1,u_int rs2,u_int rt)
1147 {
1148   assem_debug("eor %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1149   output_w32(0xe0200000|rd_rn_rm(rt,rs1,rs2));
1150 }
1151
1152 void emit_addimm(u_int rs,int imm,u_int rt)
1153 {
1154   assert(rs<16);
1155   assert(rt<16);
1156   if(imm!=0) {
1157     u_int armval;
1158     if(genimm(imm,&armval)) {
1159       assem_debug("add %s,%s,#%d\n",regname[rt],regname[rs],imm);
1160       output_w32(0xe2800000|rd_rn_rm(rt,rs,0)|armval);
1161     }else if(genimm(-imm,&armval)) {
1162       assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rs],-imm);
1163       output_w32(0xe2400000|rd_rn_rm(rt,rs,0)|armval);
1164     }else if(imm<0) {
1165       assert(imm>-65536);
1166       assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rs],(-imm)&0xFF00);
1167       assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rt],(-imm)&0xFF);
1168       output_w32(0xe2400000|rd_rn_imm_shift(rt,rs,(-imm)>>8,8));
1169       output_w32(0xe2400000|rd_rn_imm_shift(rt,rt,(-imm)&0xff,0));
1170     }else{
1171       assert(imm<65536);
1172       assem_debug("add %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF00);
1173       assem_debug("add %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF);
1174       output_w32(0xe2800000|rd_rn_imm_shift(rt,rs,imm>>8,8));
1175       output_w32(0xe2800000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1176     }
1177   }
1178   else if(rs!=rt) emit_mov(rs,rt);
1179 }
1180
1181 void emit_addimm_and_set_flags(int imm,int rt)
1182 {
1183   assert(imm>-65536&&imm<65536);
1184   u_int armval;
1185   if(genimm(imm,&armval)) {
1186     assem_debug("adds %s,%s,#%d\n",regname[rt],regname[rt],imm);
1187     output_w32(0xe2900000|rd_rn_rm(rt,rt,0)|armval);
1188   }else if(genimm(-imm,&armval)) {
1189     assem_debug("subs %s,%s,#%d\n",regname[rt],regname[rt],imm);
1190     output_w32(0xe2500000|rd_rn_rm(rt,rt,0)|armval);
1191   }else if(imm<0) {
1192     assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rt],(-imm)&0xFF00);
1193     assem_debug("subs %s,%s,#%d\n",regname[rt],regname[rt],(-imm)&0xFF);
1194     output_w32(0xe2400000|rd_rn_imm_shift(rt,rt,(-imm)>>8,8));
1195     output_w32(0xe2500000|rd_rn_imm_shift(rt,rt,(-imm)&0xff,0));
1196   }else{
1197     assem_debug("add %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF00);
1198     assem_debug("adds %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF);
1199     output_w32(0xe2800000|rd_rn_imm_shift(rt,rt,imm>>8,8));
1200     output_w32(0xe2900000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1201   }
1202 }
1203 void emit_addimm_no_flags(u_int imm,u_int rt)
1204 {
1205   emit_addimm(rt,imm,rt);
1206 }
1207
1208 void emit_addnop(u_int r)
1209 {
1210   assert(r<16);
1211   assem_debug("add %s,%s,#0 (nop)\n",regname[r],regname[r]);
1212   output_w32(0xe2800000|rd_rn_rm(r,r,0));
1213 }
1214
1215 void emit_adcimm(u_int rs,int imm,u_int rt)
1216 {
1217   u_int armval;
1218   genimm_checked(imm,&armval);
1219   assem_debug("adc %s,%s,#%d\n",regname[rt],regname[rs],imm);
1220   output_w32(0xe2a00000|rd_rn_rm(rt,rs,0)|armval);
1221 }
1222 /*void emit_sbcimm(int imm,u_int rt)
1223 {
1224   u_int armval;
1225   genimm_checked(imm,&armval);
1226   assem_debug("sbc %s,%s,#%d\n",regname[rt],regname[rt],imm);
1227   output_w32(0xe2c00000|rd_rn_rm(rt,rt,0)|armval);
1228 }*/
1229 void emit_sbbimm(int imm,u_int rt)
1230 {
1231   assem_debug("sbb $%d,%%%s\n",imm,regname[rt]);
1232   assert(rt<8);
1233   if(imm<128&&imm>=-128) {
1234     output_byte(0x83);
1235     output_modrm(3,rt,3);
1236     output_byte(imm);
1237   }
1238   else
1239   {
1240     output_byte(0x81);
1241     output_modrm(3,rt,3);
1242     output_w32(imm);
1243   }
1244 }
1245 void emit_rscimm(int rs,int imm,u_int rt)
1246 {
1247   assert(0);
1248   u_int armval;
1249   genimm_checked(imm,&armval);
1250   assem_debug("rsc %s,%s,#%d\n",regname[rt],regname[rs],imm);
1251   output_w32(0xe2e00000|rd_rn_rm(rt,rs,0)|armval);
1252 }
1253
1254 void emit_addimm64_32(int rsh,int rsl,int imm,int rth,int rtl)
1255 {
1256   // TODO: if(genimm(imm,&armval)) ...
1257   // else
1258   emit_movimm(imm,HOST_TEMPREG);
1259   emit_adds(HOST_TEMPREG,rsl,rtl);
1260   emit_adcimm(rsh,0,rth);
1261 }
1262
1263 void emit_sbb(int rs1,int rs2)
1264 {
1265   assem_debug("sbb %%%s,%%%s\n",regname[rs2],regname[rs1]);
1266   output_byte(0x19);
1267   output_modrm(3,rs1,rs2);
1268 }
1269
1270 void emit_andimm(int rs,int imm,int rt)
1271 {
1272   u_int armval;
1273   if(imm==0) {
1274     emit_zeroreg(rt);
1275   }else if(genimm(imm,&armval)) {
1276     assem_debug("and %s,%s,#%d\n",regname[rt],regname[rs],imm);
1277     output_w32(0xe2000000|rd_rn_rm(rt,rs,0)|armval);
1278   }else if(genimm(~imm,&armval)) {
1279     assem_debug("bic %s,%s,#%d\n",regname[rt],regname[rs],imm);
1280     output_w32(0xe3c00000|rd_rn_rm(rt,rs,0)|armval);
1281   }else if(imm==65535) {
1282     #ifndef HAVE_ARMV7
1283     assem_debug("bic %s,%s,#FF000000\n",regname[rt],regname[rs]);
1284     output_w32(0xe3c00000|rd_rn_rm(rt,rs,0)|0x4FF);
1285     assem_debug("bic %s,%s,#00FF0000\n",regname[rt],regname[rt]);
1286     output_w32(0xe3c00000|rd_rn_rm(rt,rt,0)|0x8FF);
1287     #else
1288     assem_debug("uxth %s,%s\n",regname[rt],regname[rs]);
1289     output_w32(0xe6ff0070|rd_rn_rm(rt,0,rs));
1290     #endif
1291   }else{
1292     assert(imm>0&&imm<65535);
1293     #ifndef HAVE_ARMV7
1294     assem_debug("mov r14,#%d\n",imm&0xFF00);
1295     output_w32(0xe3a00000|rd_rn_imm_shift(HOST_TEMPREG,0,imm>>8,8));
1296     assem_debug("add r14,r14,#%d\n",imm&0xFF);
1297     output_w32(0xe2800000|rd_rn_imm_shift(HOST_TEMPREG,HOST_TEMPREG,imm&0xff,0));
1298     #else
1299     emit_movw(imm,HOST_TEMPREG);
1300     #endif
1301     assem_debug("and %s,%s,r14\n",regname[rt],regname[rs]);
1302     output_w32(0xe0000000|rd_rn_rm(rt,rs,HOST_TEMPREG));
1303   }
1304 }
1305
1306 void emit_orimm(int rs,int imm,int rt)
1307 {
1308   u_int armval;
1309   if(imm==0) {
1310     if(rs!=rt) emit_mov(rs,rt);
1311   }else if(genimm(imm,&armval)) {
1312     assem_debug("orr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1313     output_w32(0xe3800000|rd_rn_rm(rt,rs,0)|armval);
1314   }else{
1315     assert(imm>0&&imm<65536);
1316     assem_debug("orr %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF00);
1317     assem_debug("orr %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF);
1318     output_w32(0xe3800000|rd_rn_imm_shift(rt,rs,imm>>8,8));
1319     output_w32(0xe3800000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1320   }
1321 }
1322
1323 void emit_xorimm(int rs,int imm,int rt)
1324 {
1325   u_int armval;
1326   if(imm==0) {
1327     if(rs!=rt) emit_mov(rs,rt);
1328   }else if(genimm(imm,&armval)) {
1329     assem_debug("eor %s,%s,#%d\n",regname[rt],regname[rs],imm);
1330     output_w32(0xe2200000|rd_rn_rm(rt,rs,0)|armval);
1331   }else{
1332     assert(imm>0&&imm<65536);
1333     assem_debug("eor %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF00);
1334     assem_debug("eor %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF);
1335     output_w32(0xe2200000|rd_rn_imm_shift(rt,rs,imm>>8,8));
1336     output_w32(0xe2200000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1337   }
1338 }
1339
1340 void emit_shlimm(int rs,u_int imm,int rt)
1341 {
1342   assert(imm>0);
1343   assert(imm<32);
1344   //if(imm==1) ...
1345   assem_debug("lsl %s,%s,#%d\n",regname[rt],regname[rs],imm);
1346   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|(imm<<7));
1347 }
1348
1349 void emit_lsls_imm(int rs,int imm,int rt)
1350 {
1351   assert(imm>0);
1352   assert(imm<32);
1353   assem_debug("lsls %s,%s,#%d\n",regname[rt],regname[rs],imm);
1354   output_w32(0xe1b00000|rd_rn_rm(rt,0,rs)|(imm<<7));
1355 }
1356
1357 void emit_lslpls_imm(int rs,int imm,int rt)
1358 {
1359   assert(imm>0);
1360   assert(imm<32);
1361   assem_debug("lslpls %s,%s,#%d\n",regname[rt],regname[rs],imm);
1362   output_w32(0x51b00000|rd_rn_rm(rt,0,rs)|(imm<<7));
1363 }
1364
1365 void emit_shrimm(int rs,u_int imm,int rt)
1366 {
1367   assert(imm>0);
1368   assert(imm<32);
1369   assem_debug("lsr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1370   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x20|(imm<<7));
1371 }
1372
1373 void emit_sarimm(int rs,u_int imm,int rt)
1374 {
1375   assert(imm>0);
1376   assert(imm<32);
1377   assem_debug("asr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1378   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x40|(imm<<7));
1379 }
1380
1381 void emit_rorimm(int rs,u_int imm,int rt)
1382 {
1383   assert(imm>0);
1384   assert(imm<32);
1385   assem_debug("ror %s,%s,#%d\n",regname[rt],regname[rs],imm);
1386   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x60|(imm<<7));
1387 }
1388
1389 void emit_shldimm(int rs,int rs2,u_int imm,int rt)
1390 {
1391   assem_debug("shld %%%s,%%%s,%d\n",regname[rt],regname[rs2],imm);
1392   assert(imm>0);
1393   assert(imm<32);
1394   //if(imm==1) ...
1395   assem_debug("lsl %s,%s,#%d\n",regname[rt],regname[rs],imm);
1396   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|(imm<<7));
1397   assem_debug("orr %s,%s,%s,lsr #%d\n",regname[rt],regname[rt],regname[rs2],32-imm);
1398   output_w32(0xe1800020|rd_rn_rm(rt,rt,rs2)|((32-imm)<<7));
1399 }
1400
1401 void emit_shrdimm(int rs,int rs2,u_int imm,int rt)
1402 {
1403   assem_debug("shrd %%%s,%%%s,%d\n",regname[rt],regname[rs2],imm);
1404   assert(imm>0);
1405   assert(imm<32);
1406   //if(imm==1) ...
1407   assem_debug("lsr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1408   output_w32(0xe1a00020|rd_rn_rm(rt,0,rs)|(imm<<7));
1409   assem_debug("orr %s,%s,%s,lsl #%d\n",regname[rt],regname[rt],regname[rs2],32-imm);
1410   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs2)|((32-imm)<<7));
1411 }
1412
1413 void emit_signextend16(int rs,int rt)
1414 {
1415   #ifndef HAVE_ARMV7
1416   emit_shlimm(rs,16,rt);
1417   emit_sarimm(rt,16,rt);
1418   #else
1419   assem_debug("sxth %s,%s\n",regname[rt],regname[rs]);
1420   output_w32(0xe6bf0070|rd_rn_rm(rt,0,rs));
1421   #endif
1422 }
1423
1424 void emit_signextend8(int rs,int rt)
1425 {
1426   #ifndef HAVE_ARMV7
1427   emit_shlimm(rs,24,rt);
1428   emit_sarimm(rt,24,rt);
1429   #else
1430   assem_debug("sxtb %s,%s\n",regname[rt],regname[rs]);
1431   output_w32(0xe6af0070|rd_rn_rm(rt,0,rs));
1432   #endif
1433 }
1434
1435 void emit_shl(u_int rs,u_int shift,u_int rt)
1436 {
1437   assert(rs<16);
1438   assert(rt<16);
1439   assert(shift<16);
1440   //if(imm==1) ...
1441   assem_debug("lsl %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
1442   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x10|(shift<<8));
1443 }
1444 void emit_shr(u_int rs,u_int shift,u_int rt)
1445 {
1446   assert(rs<16);
1447   assert(rt<16);
1448   assert(shift<16);
1449   assem_debug("lsr %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
1450   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x30|(shift<<8));
1451 }
1452 void emit_sar(u_int rs,u_int shift,u_int rt)
1453 {
1454   assert(rs<16);
1455   assert(rt<16);
1456   assert(shift<16);
1457   assem_debug("asr %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
1458   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x50|(shift<<8));
1459 }
1460 void emit_shlcl(int r)
1461 {
1462   assem_debug("shl %%%s,%%cl\n",regname[r]);
1463   assert(0);
1464 }
1465 void emit_shrcl(int r)
1466 {
1467   assem_debug("shr %%%s,%%cl\n",regname[r]);
1468   assert(0);
1469 }
1470 void emit_sarcl(int r)
1471 {
1472   assem_debug("sar %%%s,%%cl\n",regname[r]);
1473   assert(0);
1474 }
1475
1476 void emit_shldcl(int r1,int r2)
1477 {
1478   assem_debug("shld %%%s,%%%s,%%cl\n",regname[r1],regname[r2]);
1479   assert(0);
1480 }
1481 void emit_shrdcl(int r1,int r2)
1482 {
1483   assem_debug("shrd %%%s,%%%s,%%cl\n",regname[r1],regname[r2]);
1484   assert(0);
1485 }
1486 void emit_orrshl(u_int rs,u_int shift,u_int rt)
1487 {
1488   assert(rs<16);
1489   assert(rt<16);
1490   assert(shift<16);
1491   assem_debug("orr %s,%s,%s,lsl %s\n",regname[rt],regname[rt],regname[rs],regname[shift]);
1492   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs)|0x10|(shift<<8));
1493 }
1494 void emit_orrshr(u_int rs,u_int shift,u_int rt)
1495 {
1496   assert(rs<16);
1497   assert(rt<16);
1498   assert(shift<16);
1499   assem_debug("orr %s,%s,%s,lsr %s\n",regname[rt],regname[rt],regname[rs],regname[shift]);
1500   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs)|0x30|(shift<<8));
1501 }
1502
1503 void emit_cmpimm(int rs,int imm)
1504 {
1505   u_int armval;
1506   if(genimm(imm,&armval)) {
1507     assem_debug("cmp %s,#%d\n",regname[rs],imm);
1508     output_w32(0xe3500000|rd_rn_rm(0,rs,0)|armval);
1509   }else if(genimm(-imm,&armval)) {
1510     assem_debug("cmn %s,#%d\n",regname[rs],imm);
1511     output_w32(0xe3700000|rd_rn_rm(0,rs,0)|armval);
1512   }else if(imm>0) {
1513     assert(imm<65536);
1514     emit_movimm(imm,HOST_TEMPREG);
1515     assem_debug("cmp %s,r14\n",regname[rs]);
1516     output_w32(0xe1500000|rd_rn_rm(0,rs,HOST_TEMPREG));
1517   }else{
1518     assert(imm>-65536);
1519     emit_movimm(-imm,HOST_TEMPREG);
1520     assem_debug("cmn %s,r14\n",regname[rs]);
1521     output_w32(0xe1700000|rd_rn_rm(0,rs,HOST_TEMPREG));
1522   }
1523 }
1524
1525 void emit_cmovne(u_int *addr,int rt)
1526 {
1527   assem_debug("cmovne %x,%%%s",(int)addr,regname[rt]);
1528   assert(0);
1529 }
1530 void emit_cmovl(u_int *addr,int rt)
1531 {
1532   assem_debug("cmovl %x,%%%s",(int)addr,regname[rt]);
1533   assert(0);
1534 }
1535 void emit_cmovs(u_int *addr,int rt)
1536 {
1537   assem_debug("cmovs %x,%%%s",(int)addr,regname[rt]);
1538   assert(0);
1539 }
1540 void emit_cmovne_imm(int imm,int rt)
1541 {
1542   assem_debug("movne %s,#%d\n",regname[rt],imm);
1543   u_int armval;
1544   genimm_checked(imm,&armval);
1545   output_w32(0x13a00000|rd_rn_rm(rt,0,0)|armval);
1546 }
1547 void emit_cmovl_imm(int imm,int rt)
1548 {
1549   assem_debug("movlt %s,#%d\n",regname[rt],imm);
1550   u_int armval;
1551   genimm_checked(imm,&armval);
1552   output_w32(0xb3a00000|rd_rn_rm(rt,0,0)|armval);
1553 }
1554 void emit_cmovb_imm(int imm,int rt)
1555 {
1556   assem_debug("movcc %s,#%d\n",regname[rt],imm);
1557   u_int armval;
1558   genimm_checked(imm,&armval);
1559   output_w32(0x33a00000|rd_rn_rm(rt,0,0)|armval);
1560 }
1561 void emit_cmovs_imm(int imm,int rt)
1562 {
1563   assem_debug("movmi %s,#%d\n",regname[rt],imm);
1564   u_int armval;
1565   genimm_checked(imm,&armval);
1566   output_w32(0x43a00000|rd_rn_rm(rt,0,0)|armval);
1567 }
1568 void emit_cmove_reg(int rs,int rt)
1569 {
1570   assem_debug("moveq %s,%s\n",regname[rt],regname[rs]);
1571   output_w32(0x01a00000|rd_rn_rm(rt,0,rs));
1572 }
1573 void emit_cmovne_reg(int rs,int rt)
1574 {
1575   assem_debug("movne %s,%s\n",regname[rt],regname[rs]);
1576   output_w32(0x11a00000|rd_rn_rm(rt,0,rs));
1577 }
1578 void emit_cmovl_reg(int rs,int rt)
1579 {
1580   assem_debug("movlt %s,%s\n",regname[rt],regname[rs]);
1581   output_w32(0xb1a00000|rd_rn_rm(rt,0,rs));
1582 }
1583 void emit_cmovs_reg(int rs,int rt)
1584 {
1585   assem_debug("movmi %s,%s\n",regname[rt],regname[rs]);
1586   output_w32(0x41a00000|rd_rn_rm(rt,0,rs));
1587 }
1588
1589 void emit_slti32(int rs,int imm,int rt)
1590 {
1591   if(rs!=rt) emit_zeroreg(rt);
1592   emit_cmpimm(rs,imm);
1593   if(rs==rt) emit_movimm(0,rt);
1594   emit_cmovl_imm(1,rt);
1595 }
1596 void emit_sltiu32(int rs,int imm,int rt)
1597 {
1598   if(rs!=rt) emit_zeroreg(rt);
1599   emit_cmpimm(rs,imm);
1600   if(rs==rt) emit_movimm(0,rt);
1601   emit_cmovb_imm(1,rt);
1602 }
1603 void emit_slti64_32(int rsh,int rsl,int imm,int rt)
1604 {
1605   assert(rsh!=rt);
1606   emit_slti32(rsl,imm,rt);
1607   if(imm>=0)
1608   {
1609     emit_test(rsh,rsh);
1610     emit_cmovne_imm(0,rt);
1611     emit_cmovs_imm(1,rt);
1612   }
1613   else
1614   {
1615     emit_cmpimm(rsh,-1);
1616     emit_cmovne_imm(0,rt);
1617     emit_cmovl_imm(1,rt);
1618   }
1619 }
1620 void emit_sltiu64_32(int rsh,int rsl,int imm,int rt)
1621 {
1622   assert(rsh!=rt);
1623   emit_sltiu32(rsl,imm,rt);
1624   if(imm>=0)
1625   {
1626     emit_test(rsh,rsh);
1627     emit_cmovne_imm(0,rt);
1628   }
1629   else
1630   {
1631     emit_cmpimm(rsh,-1);
1632     emit_cmovne_imm(1,rt);
1633   }
1634 }
1635
1636 void emit_cmp(int rs,int rt)
1637 {
1638   assem_debug("cmp %s,%s\n",regname[rs],regname[rt]);
1639   output_w32(0xe1500000|rd_rn_rm(0,rs,rt));
1640 }
1641 void emit_set_gz32(int rs, int rt)
1642 {
1643   //assem_debug("set_gz32\n");
1644   emit_cmpimm(rs,1);
1645   emit_movimm(1,rt);
1646   emit_cmovl_imm(0,rt);
1647 }
1648 void emit_set_nz32(int rs, int rt)
1649 {
1650   //assem_debug("set_nz32\n");
1651   if(rs!=rt) emit_movs(rs,rt);
1652   else emit_test(rs,rs);
1653   emit_cmovne_imm(1,rt);
1654 }
1655 void emit_set_gz64_32(int rsh, int rsl, int rt)
1656 {
1657   //assem_debug("set_gz64\n");
1658   emit_set_gz32(rsl,rt);
1659   emit_test(rsh,rsh);
1660   emit_cmovne_imm(1,rt);
1661   emit_cmovs_imm(0,rt);
1662 }
1663 void emit_set_nz64_32(int rsh, int rsl, int rt)
1664 {
1665   //assem_debug("set_nz64\n");
1666   emit_or_and_set_flags(rsh,rsl,rt);
1667   emit_cmovne_imm(1,rt);
1668 }
1669 void emit_set_if_less32(int rs1, int rs2, int rt)
1670 {
1671   //assem_debug("set if less (%%%s,%%%s),%%%s\n",regname[rs1],regname[rs2],regname[rt]);
1672   if(rs1!=rt&&rs2!=rt) emit_zeroreg(rt);
1673   emit_cmp(rs1,rs2);
1674   if(rs1==rt||rs2==rt) emit_movimm(0,rt);
1675   emit_cmovl_imm(1,rt);
1676 }
1677 void emit_set_if_carry32(int rs1, int rs2, int rt)
1678 {
1679   //assem_debug("set if carry (%%%s,%%%s),%%%s\n",regname[rs1],regname[rs2],regname[rt]);
1680   if(rs1!=rt&&rs2!=rt) emit_zeroreg(rt);
1681   emit_cmp(rs1,rs2);
1682   if(rs1==rt||rs2==rt) emit_movimm(0,rt);
1683   emit_cmovb_imm(1,rt);
1684 }
1685 void emit_set_if_less64_32(int u1, int l1, int u2, int l2, int rt)
1686 {
1687   //assem_debug("set if less64 (%%%s,%%%s,%%%s,%%%s),%%%s\n",regname[u1],regname[l1],regname[u2],regname[l2],regname[rt]);
1688   assert(u1!=rt);
1689   assert(u2!=rt);
1690   emit_cmp(l1,l2);
1691   emit_movimm(0,rt);
1692   emit_sbcs(u1,u2,HOST_TEMPREG);
1693   emit_cmovl_imm(1,rt);
1694 }
1695 void emit_set_if_carry64_32(int u1, int l1, int u2, int l2, int rt)
1696 {
1697   //assem_debug("set if carry64 (%%%s,%%%s,%%%s,%%%s),%%%s\n",regname[u1],regname[l1],regname[u2],regname[l2],regname[rt]);
1698   assert(u1!=rt);
1699   assert(u2!=rt);
1700   emit_cmp(l1,l2);
1701   emit_movimm(0,rt);
1702   emit_sbcs(u1,u2,HOST_TEMPREG);
1703   emit_cmovb_imm(1,rt);
1704 }
1705
1706 void emit_call(int a)
1707 {
1708   assem_debug("bl %x (%x+%x)\n",a,(int)out,a-(int)out-8);
1709   u_int offset=genjmp(a);
1710   output_w32(0xeb000000|offset);
1711 }
1712 void emit_jmp(int a)
1713 {
1714   assem_debug("b %x (%x+%x)\n",a,(int)out,a-(int)out-8);
1715   u_int offset=genjmp(a);
1716   output_w32(0xea000000|offset);
1717 }
1718 void emit_jne(int a)
1719 {
1720   assem_debug("bne %x\n",a);
1721   u_int offset=genjmp(a);
1722   output_w32(0x1a000000|offset);
1723 }
1724 void emit_jeq(int a)
1725 {
1726   assem_debug("beq %x\n",a);
1727   u_int offset=genjmp(a);
1728   output_w32(0x0a000000|offset);
1729 }
1730 void emit_js(int a)
1731 {
1732   assem_debug("bmi %x\n",a);
1733   u_int offset=genjmp(a);
1734   output_w32(0x4a000000|offset);
1735 }
1736 void emit_jns(int a)
1737 {
1738   assem_debug("bpl %x\n",a);
1739   u_int offset=genjmp(a);
1740   output_w32(0x5a000000|offset);
1741 }
1742 void emit_jl(int a)
1743 {
1744   assem_debug("blt %x\n",a);
1745   u_int offset=genjmp(a);
1746   output_w32(0xba000000|offset);
1747 }
1748 void emit_jge(int a)
1749 {
1750   assem_debug("bge %x\n",a);
1751   u_int offset=genjmp(a);
1752   output_w32(0xaa000000|offset);
1753 }
1754 void emit_jno(int a)
1755 {
1756   assem_debug("bvc %x\n",a);
1757   u_int offset=genjmp(a);
1758   output_w32(0x7a000000|offset);
1759 }
1760 void emit_jc(int a)
1761 {
1762   assem_debug("bcs %x\n",a);
1763   u_int offset=genjmp(a);
1764   output_w32(0x2a000000|offset);
1765 }
1766 void emit_jcc(int a)
1767 {
1768   assem_debug("bcc %x\n",a);
1769   u_int offset=genjmp(a);
1770   output_w32(0x3a000000|offset);
1771 }
1772
1773 void emit_pushimm(int imm)
1774 {
1775   assem_debug("push $%x\n",imm);
1776   assert(0);
1777 }
1778 void emit_pusha()
1779 {
1780   assem_debug("pusha\n");
1781   assert(0);
1782 }
1783 void emit_popa()
1784 {
1785   assem_debug("popa\n");
1786   assert(0);
1787 }
1788 void emit_pushreg(u_int r)
1789 {
1790   assem_debug("push %%%s\n",regname[r]);
1791   assert(0);
1792 }
1793 void emit_popreg(u_int r)
1794 {
1795   assem_debug("pop %%%s\n",regname[r]);
1796   assert(0);
1797 }
1798 void emit_callreg(u_int r)
1799 {
1800   assert(r<15);
1801   assem_debug("blx %s\n",regname[r]);
1802   output_w32(0xe12fff30|r);
1803 }
1804 void emit_jmpreg(u_int r)
1805 {
1806   assem_debug("mov pc,%s\n",regname[r]);
1807   output_w32(0xe1a00000|rd_rn_rm(15,0,r));
1808 }
1809
1810 void emit_readword_indexed(int offset, int rs, int rt)
1811 {
1812   assert(offset>-4096&&offset<4096);
1813   assem_debug("ldr %s,%s+%d\n",regname[rt],regname[rs],offset);
1814   if(offset>=0) {
1815     output_w32(0xe5900000|rd_rn_rm(rt,rs,0)|offset);
1816   }else{
1817     output_w32(0xe5100000|rd_rn_rm(rt,rs,0)|(-offset));
1818   }
1819 }
1820 void emit_readword_dualindexedx4(int rs1, int rs2, int rt)
1821 {
1822   assem_debug("ldr %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
1823   output_w32(0xe7900000|rd_rn_rm(rt,rs1,rs2)|0x100);
1824 }
1825 void emit_ldrcc_dualindexed(int rs1, int rs2, int rt)
1826 {
1827   assem_debug("ldrcc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1828   output_w32(0x37900000|rd_rn_rm(rt,rs1,rs2));
1829 }
1830 void emit_ldrccb_dualindexed(int rs1, int rs2, int rt)
1831 {
1832   assem_debug("ldrccb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1833   output_w32(0x37d00000|rd_rn_rm(rt,rs1,rs2));
1834 }
1835 void emit_ldrccsb_dualindexed(int rs1, int rs2, int rt)
1836 {
1837   assem_debug("ldrccsb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1838   output_w32(0x319000d0|rd_rn_rm(rt,rs1,rs2));
1839 }
1840 void emit_ldrcch_dualindexed(int rs1, int rs2, int rt)
1841 {
1842   assem_debug("ldrcch %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1843   output_w32(0x319000b0|rd_rn_rm(rt,rs1,rs2));
1844 }
1845 void emit_ldrccsh_dualindexed(int rs1, int rs2, int rt)
1846 {
1847   assem_debug("ldrccsh %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1848   output_w32(0x319000f0|rd_rn_rm(rt,rs1,rs2));
1849 }
1850 void emit_readword_indexed_tlb(int addr, int rs, int map, int rt)
1851 {
1852   if(map<0) emit_readword_indexed(addr, rs, rt);
1853   else {
1854     assert(addr==0);
1855     emit_readword_dualindexedx4(rs, map, rt);
1856   }
1857 }
1858 void emit_readdword_indexed_tlb(int addr, int rs, int map, int rh, int rl)
1859 {
1860   if(map<0) {
1861     if(rh>=0) emit_readword_indexed(addr, rs, rh);
1862     emit_readword_indexed(addr+4, rs, rl);
1863   }else{
1864     assert(rh!=rs);
1865     if(rh>=0) emit_readword_indexed_tlb(addr, rs, map, rh);
1866     emit_addimm(map,1,map);
1867     emit_readword_indexed_tlb(addr, rs, map, rl);
1868   }
1869 }
1870 void emit_movsbl_indexed(int offset, int rs, int rt)
1871 {
1872   assert(offset>-256&&offset<256);
1873   assem_debug("ldrsb %s,%s+%d\n",regname[rt],regname[rs],offset);
1874   if(offset>=0) {
1875     output_w32(0xe1d000d0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1876   }else{
1877     output_w32(0xe15000d0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1878   }
1879 }
1880 void emit_movsbl_indexed_tlb(int addr, int rs, int map, int rt)
1881 {
1882   if(map<0) emit_movsbl_indexed(addr, rs, rt);
1883   else {
1884     if(addr==0) {
1885       emit_shlimm(map,2,map);
1886       assem_debug("ldrsb %s,%s+%s\n",regname[rt],regname[rs],regname[map]);
1887       output_w32(0xe19000d0|rd_rn_rm(rt,rs,map));
1888     }else{
1889       assert(addr>-256&&addr<256);
1890       assem_debug("add %s,%s,%s,lsl #2\n",regname[rt],regname[rs],regname[map]);
1891       output_w32(0xe0800000|rd_rn_rm(rt,rs,map)|(2<<7));
1892       emit_movsbl_indexed(addr, rt, rt);
1893     }
1894   }
1895 }
1896 void emit_movswl_indexed(int offset, int rs, int rt)
1897 {
1898   assert(offset>-256&&offset<256);
1899   assem_debug("ldrsh %s,%s+%d\n",regname[rt],regname[rs],offset);
1900   if(offset>=0) {
1901     output_w32(0xe1d000f0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1902   }else{
1903     output_w32(0xe15000f0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1904   }
1905 }
1906 void emit_movzbl_indexed(int offset, int rs, int rt)
1907 {
1908   assert(offset>-4096&&offset<4096);
1909   assem_debug("ldrb %s,%s+%d\n",regname[rt],regname[rs],offset);
1910   if(offset>=0) {
1911     output_w32(0xe5d00000|rd_rn_rm(rt,rs,0)|offset);
1912   }else{
1913     output_w32(0xe5500000|rd_rn_rm(rt,rs,0)|(-offset));
1914   }
1915 }
1916 void emit_movzbl_dualindexedx4(int rs1, int rs2, int rt)
1917 {
1918   assem_debug("ldrb %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
1919   output_w32(0xe7d00000|rd_rn_rm(rt,rs1,rs2)|0x100);
1920 }
1921 void emit_movzbl_indexed_tlb(int addr, int rs, int map, int rt)
1922 {
1923   if(map<0) emit_movzbl_indexed(addr, rs, rt);
1924   else {
1925     if(addr==0) {
1926       emit_movzbl_dualindexedx4(rs, map, rt);
1927     }else{
1928       emit_addimm(rs,addr,rt);
1929       emit_movzbl_dualindexedx4(rt, map, rt);
1930     }
1931   }
1932 }
1933 void emit_movzwl_indexed(int offset, int rs, int rt)
1934 {
1935   assert(offset>-256&&offset<256);
1936   assem_debug("ldrh %s,%s+%d\n",regname[rt],regname[rs],offset);
1937   if(offset>=0) {
1938     output_w32(0xe1d000b0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1939   }else{
1940     output_w32(0xe15000b0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1941   }
1942 }
1943 static void emit_ldrd(int offset, int rs, int rt)
1944 {
1945   assert(offset>-256&&offset<256);
1946   assem_debug("ldrd %s,%s+%d\n",regname[rt],regname[rs],offset);
1947   if(offset>=0) {
1948     output_w32(0xe1c000d0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1949   }else{
1950     output_w32(0xe14000d0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1951   }
1952 }
1953 void emit_readword(int addr, int rt)
1954 {
1955   u_int offset = addr-(u_int)&dynarec_local;
1956   assert(offset<4096);
1957   assem_debug("ldr %s,fp+%d\n",regname[rt],offset);
1958   output_w32(0xe5900000|rd_rn_rm(rt,FP,0)|offset);
1959 }
1960 void emit_movsbl(int addr, int rt)
1961 {
1962   u_int offset = addr-(u_int)&dynarec_local;
1963   assert(offset<256);
1964   assem_debug("ldrsb %s,fp+%d\n",regname[rt],offset);
1965   output_w32(0xe1d000d0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
1966 }
1967 void emit_movswl(int addr, int rt)
1968 {
1969   u_int offset = addr-(u_int)&dynarec_local;
1970   assert(offset<256);
1971   assem_debug("ldrsh %s,fp+%d\n",regname[rt],offset);
1972   output_w32(0xe1d000f0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
1973 }
1974 void emit_movzbl(int addr, int rt)
1975 {
1976   u_int offset = addr-(u_int)&dynarec_local;
1977   assert(offset<4096);
1978   assem_debug("ldrb %s,fp+%d\n",regname[rt],offset);
1979   output_w32(0xe5d00000|rd_rn_rm(rt,FP,0)|offset);
1980 }
1981 void emit_movzwl(int addr, int rt)
1982 {
1983   u_int offset = addr-(u_int)&dynarec_local;
1984   assert(offset<256);
1985   assem_debug("ldrh %s,fp+%d\n",regname[rt],offset);
1986   output_w32(0xe1d000b0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
1987 }
1988 void emit_movzwl_reg(int rs, int rt)
1989 {
1990   assem_debug("movzwl %%%s,%%%s\n",regname[rs]+1,regname[rt]);
1991   assert(0);
1992 }
1993
1994 void emit_xchg(int rs, int rt)
1995 {
1996   assem_debug("xchg %%%s,%%%s\n",regname[rs],regname[rt]);
1997   assert(0);
1998 }
1999 void emit_writeword_indexed(int rt, int offset, int rs)
2000 {
2001   assert(offset>-4096&&offset<4096);
2002   assem_debug("str %s,%s+%d\n",regname[rt],regname[rs],offset);
2003   if(offset>=0) {
2004     output_w32(0xe5800000|rd_rn_rm(rt,rs,0)|offset);
2005   }else{
2006     output_w32(0xe5000000|rd_rn_rm(rt,rs,0)|(-offset));
2007   }
2008 }
2009 void emit_writeword_dualindexedx4(int rt, int rs1, int rs2)
2010 {
2011   assem_debug("str %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
2012   output_w32(0xe7800000|rd_rn_rm(rt,rs1,rs2)|0x100);
2013 }
2014 void emit_writeword_indexed_tlb(int rt, int addr, int rs, int map, int temp)
2015 {
2016   if(map<0) emit_writeword_indexed(rt, addr, rs);
2017   else {
2018     assert(addr==0);
2019     emit_writeword_dualindexedx4(rt, rs, map);
2020   }
2021 }
2022 void emit_writedword_indexed_tlb(int rh, int rl, int addr, int rs, int map, int temp)
2023 {
2024   if(map<0) {
2025     if(rh>=0) emit_writeword_indexed(rh, addr, rs);
2026     emit_writeword_indexed(rl, addr+4, rs);
2027   }else{
2028     assert(rh>=0);
2029     if(temp!=rs) emit_addimm(map,1,temp);
2030     emit_writeword_indexed_tlb(rh, addr, rs, map, temp);
2031     if(temp!=rs) emit_writeword_indexed_tlb(rl, addr, rs, temp, temp);
2032     else {
2033       emit_addimm(rs,4,rs);
2034       emit_writeword_indexed_tlb(rl, addr, rs, map, temp);
2035     }
2036   }
2037 }
2038 void emit_writehword_indexed(int rt, int offset, int rs)
2039 {
2040   assert(offset>-256&&offset<256);
2041   assem_debug("strh %s,%s+%d\n",regname[rt],regname[rs],offset);
2042   if(offset>=0) {
2043     output_w32(0xe1c000b0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
2044   }else{
2045     output_w32(0xe14000b0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
2046   }
2047 }
2048 void emit_writebyte_indexed(int rt, int offset, int rs)
2049 {
2050   assert(offset>-4096&&offset<4096);
2051   assem_debug("strb %s,%s+%d\n",regname[rt],regname[rs],offset);
2052   if(offset>=0) {
2053     output_w32(0xe5c00000|rd_rn_rm(rt,rs,0)|offset);
2054   }else{
2055     output_w32(0xe5400000|rd_rn_rm(rt,rs,0)|(-offset));
2056   }
2057 }
2058 void emit_writebyte_dualindexedx4(int rt, int rs1, int rs2)
2059 {
2060   assem_debug("strb %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
2061   output_w32(0xe7c00000|rd_rn_rm(rt,rs1,rs2)|0x100);
2062 }
2063 void emit_writebyte_indexed_tlb(int rt, int addr, int rs, int map, int temp)
2064 {
2065   if(map<0) emit_writebyte_indexed(rt, addr, rs);
2066   else {
2067     if(addr==0) {
2068       emit_writebyte_dualindexedx4(rt, rs, map);
2069     }else{
2070       emit_addimm(rs,addr,temp);
2071       emit_writebyte_dualindexedx4(rt, temp, map);
2072     }
2073   }
2074 }
2075 void emit_strcc_dualindexed(int rs1, int rs2, int rt)
2076 {
2077   assem_debug("strcc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2078   output_w32(0x37800000|rd_rn_rm(rt,rs1,rs2));
2079 }
2080 void emit_strccb_dualindexed(int rs1, int rs2, int rt)
2081 {
2082   assem_debug("strccb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2083   output_w32(0x37c00000|rd_rn_rm(rt,rs1,rs2));
2084 }
2085 void emit_strcch_dualindexed(int rs1, int rs2, int rt)
2086 {
2087   assem_debug("strcch %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2088   output_w32(0x318000b0|rd_rn_rm(rt,rs1,rs2));
2089 }
2090 void emit_writeword(int rt, int addr)
2091 {
2092   u_int offset = addr-(u_int)&dynarec_local;
2093   assert(offset<4096);
2094   assem_debug("str %s,fp+%d\n",regname[rt],offset);
2095   output_w32(0xe5800000|rd_rn_rm(rt,FP,0)|offset);
2096 }
2097 void emit_writehword(int rt, int addr)
2098 {
2099   u_int offset = addr-(u_int)&dynarec_local;
2100   assert(offset<256);
2101   assem_debug("strh %s,fp+%d\n",regname[rt],offset);
2102   output_w32(0xe1c000b0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
2103 }
2104 void emit_writebyte(int rt, int addr)
2105 {
2106   u_int offset = addr-(u_int)&dynarec_local;
2107   assert(offset<4096);
2108   assem_debug("strb %s,fp+%d\n",regname[rt],offset);
2109   output_w32(0xe5c00000|rd_rn_rm(rt,FP,0)|offset);
2110 }
2111 void emit_writeword_imm(int imm, int addr)
2112 {
2113   assem_debug("movl $%x,%x\n",imm,addr);
2114   assert(0);
2115 }
2116 void emit_writebyte_imm(int imm, int addr)
2117 {
2118   assem_debug("movb $%x,%x\n",imm,addr);
2119   assert(0);
2120 }
2121
2122 void emit_mul(int rs)
2123 {
2124   assem_debug("mul %%%s\n",regname[rs]);
2125   assert(0);
2126 }
2127 void emit_imul(int rs)
2128 {
2129   assem_debug("imul %%%s\n",regname[rs]);
2130   assert(0);
2131 }
2132 void emit_umull(u_int rs1, u_int rs2, u_int hi, u_int lo)
2133 {
2134   assem_debug("umull %s, %s, %s, %s\n",regname[lo],regname[hi],regname[rs1],regname[rs2]);
2135   assert(rs1<16);
2136   assert(rs2<16);
2137   assert(hi<16);
2138   assert(lo<16);
2139   output_w32(0xe0800090|(hi<<16)|(lo<<12)|(rs2<<8)|rs1);
2140 }
2141 void emit_smull(u_int rs1, u_int rs2, u_int hi, u_int lo)
2142 {
2143   assem_debug("smull %s, %s, %s, %s\n",regname[lo],regname[hi],regname[rs1],regname[rs2]);
2144   assert(rs1<16);
2145   assert(rs2<16);
2146   assert(hi<16);
2147   assert(lo<16);
2148   output_w32(0xe0c00090|(hi<<16)|(lo<<12)|(rs2<<8)|rs1);
2149 }
2150
2151 void emit_div(int rs)
2152 {
2153   assem_debug("div %%%s\n",regname[rs]);
2154   assert(0);
2155 }
2156 void emit_idiv(int rs)
2157 {
2158   assem_debug("idiv %%%s\n",regname[rs]);
2159   assert(0);
2160 }
2161 void emit_cdq()
2162 {
2163   assem_debug("cdq\n");
2164   assert(0);
2165 }
2166
2167 void emit_clz(int rs,int rt)
2168 {
2169   assem_debug("clz %s,%s\n",regname[rt],regname[rs]);
2170   output_w32(0xe16f0f10|rd_rn_rm(rt,0,rs));
2171 }
2172
2173 void emit_subcs(int rs1,int rs2,int rt)
2174 {
2175   assem_debug("subcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2176   output_w32(0x20400000|rd_rn_rm(rt,rs1,rs2));
2177 }
2178
2179 void emit_shrcc_imm(int rs,u_int imm,int rt)
2180 {
2181   assert(imm>0);
2182   assert(imm<32);
2183   assem_debug("lsrcc %s,%s,#%d\n",regname[rt],regname[rs],imm);
2184   output_w32(0x31a00000|rd_rn_rm(rt,0,rs)|0x20|(imm<<7));
2185 }
2186
2187 void emit_shrne_imm(int rs,u_int imm,int rt)
2188 {
2189   assert(imm>0);
2190   assert(imm<32);
2191   assem_debug("lsrne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2192   output_w32(0x11a00000|rd_rn_rm(rt,0,rs)|0x20|(imm<<7));
2193 }
2194
2195 void emit_negmi(int rs, int rt)
2196 {
2197   assem_debug("rsbmi %s,%s,#0\n",regname[rt],regname[rs]);
2198   output_w32(0x42600000|rd_rn_rm(rt,rs,0));
2199 }
2200
2201 void emit_negsmi(int rs, int rt)
2202 {
2203   assem_debug("rsbsmi %s,%s,#0\n",regname[rt],regname[rs]);
2204   output_w32(0x42700000|rd_rn_rm(rt,rs,0));
2205 }
2206
2207 void emit_orreq(u_int rs1,u_int rs2,u_int rt)
2208 {
2209   assem_debug("orreq %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2210   output_w32(0x01800000|rd_rn_rm(rt,rs1,rs2));
2211 }
2212
2213 void emit_orrne(u_int rs1,u_int rs2,u_int rt)
2214 {
2215   assem_debug("orrne %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2216   output_w32(0x11800000|rd_rn_rm(rt,rs1,rs2));
2217 }
2218
2219 void emit_bic_lsl(u_int rs1,u_int rs2,u_int shift,u_int rt)
2220 {
2221   assem_debug("bic %s,%s,%s lsl %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2222   output_w32(0xe1C00000|rd_rn_rm(rt,rs1,rs2)|0x10|(shift<<8));
2223 }
2224
2225 void emit_biceq_lsl(u_int rs1,u_int rs2,u_int shift,u_int rt)
2226 {
2227   assem_debug("biceq %s,%s,%s lsl %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2228   output_w32(0x01C00000|rd_rn_rm(rt,rs1,rs2)|0x10|(shift<<8));
2229 }
2230
2231 void emit_bicne_lsl(u_int rs1,u_int rs2,u_int shift,u_int rt)
2232 {
2233   assem_debug("bicne %s,%s,%s lsl %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2234   output_w32(0x11C00000|rd_rn_rm(rt,rs1,rs2)|0x10|(shift<<8));
2235 }
2236
2237 void emit_bic_lsr(u_int rs1,u_int rs2,u_int shift,u_int rt)
2238 {
2239   assem_debug("bic %s,%s,%s lsr %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2240   output_w32(0xe1C00000|rd_rn_rm(rt,rs1,rs2)|0x30|(shift<<8));
2241 }
2242
2243 void emit_biceq_lsr(u_int rs1,u_int rs2,u_int shift,u_int rt)
2244 {
2245   assem_debug("biceq %s,%s,%s lsr %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2246   output_w32(0x01C00000|rd_rn_rm(rt,rs1,rs2)|0x30|(shift<<8));
2247 }
2248
2249 void emit_bicne_lsr(u_int rs1,u_int rs2,u_int shift,u_int rt)
2250 {
2251   assem_debug("bicne %s,%s,%s lsr %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2252   output_w32(0x11C00000|rd_rn_rm(rt,rs1,rs2)|0x30|(shift<<8));
2253 }
2254
2255 void emit_teq(int rs, int rt)
2256 {
2257   assem_debug("teq %s,%s\n",regname[rs],regname[rt]);
2258   output_w32(0xe1300000|rd_rn_rm(0,rs,rt));
2259 }
2260
2261 void emit_rsbimm(int rs, int imm, int rt)
2262 {
2263   u_int armval;
2264   genimm_checked(imm,&armval);
2265   assem_debug("rsb %s,%s,#%d\n",regname[rt],regname[rs],imm);
2266   output_w32(0xe2600000|rd_rn_rm(rt,rs,0)|armval);
2267 }
2268
2269 // Load 2 immediates optimizing for small code size
2270 void emit_mov2imm_compact(int imm1,u_int rt1,int imm2,u_int rt2)
2271 {
2272   emit_movimm(imm1,rt1);
2273   u_int armval;
2274   if(genimm(imm2-imm1,&armval)) {
2275     assem_debug("add %s,%s,#%d\n",regname[rt2],regname[rt1],imm2-imm1);
2276     output_w32(0xe2800000|rd_rn_rm(rt2,rt1,0)|armval);
2277   }else if(genimm(imm1-imm2,&armval)) {
2278     assem_debug("sub %s,%s,#%d\n",regname[rt2],regname[rt1],imm1-imm2);
2279     output_w32(0xe2400000|rd_rn_rm(rt2,rt1,0)|armval);
2280   }
2281   else emit_movimm(imm2,rt2);
2282 }
2283
2284 // Conditionally select one of two immediates, optimizing for small code size
2285 // This will only be called if HAVE_CMOV_IMM is defined
2286 void emit_cmov2imm_e_ne_compact(int imm1,int imm2,u_int rt)
2287 {
2288   u_int armval;
2289   if(genimm(imm2-imm1,&armval)) {
2290     emit_movimm(imm1,rt);
2291     assem_debug("addne %s,%s,#%d\n",regname[rt],regname[rt],imm2-imm1);
2292     output_w32(0x12800000|rd_rn_rm(rt,rt,0)|armval);
2293   }else if(genimm(imm1-imm2,&armval)) {
2294     emit_movimm(imm1,rt);
2295     assem_debug("subne %s,%s,#%d\n",regname[rt],regname[rt],imm1-imm2);
2296     output_w32(0x12400000|rd_rn_rm(rt,rt,0)|armval);
2297   }
2298   else {
2299     #ifndef HAVE_ARMV7
2300     emit_movimm(imm1,rt);
2301     add_literal((int)out,imm2);
2302     assem_debug("ldrne %s,pc+? [=%x]\n",regname[rt],imm2);
2303     output_w32(0x15900000|rd_rn_rm(rt,15,0));
2304     #else
2305     emit_movw(imm1&0x0000FFFF,rt);
2306     if((imm1&0xFFFF)!=(imm2&0xFFFF)) {
2307       assem_debug("movwne %s,#%d (0x%x)\n",regname[rt],imm2&0xFFFF,imm2&0xFFFF);
2308       output_w32(0x13000000|rd_rn_rm(rt,0,0)|(imm2&0xfff)|((imm2<<4)&0xf0000));
2309     }
2310     emit_movt(imm1&0xFFFF0000,rt);
2311     if((imm1&0xFFFF0000)!=(imm2&0xFFFF0000)) {
2312       assem_debug("movtne %s,#%d (0x%x)\n",regname[rt],imm2&0xffff0000,imm2&0xffff0000);
2313       output_w32(0x13400000|rd_rn_rm(rt,0,0)|((imm2>>16)&0xfff)|((imm2>>12)&0xf0000));
2314     }
2315     #endif
2316   }
2317 }
2318
2319 // special case for checking invalid_code
2320 void emit_cmpmem_indexedsr12_imm(int addr,int r,int imm)
2321 {
2322   assert(0);
2323 }
2324
2325 // special case for checking invalid_code
2326 void emit_cmpmem_indexedsr12_reg(int base,int r,int imm)
2327 {
2328   assert(imm<128&&imm>=0);
2329   assert(r>=0&&r<16);
2330   assem_debug("ldrb lr,%s,%s lsr #12\n",regname[base],regname[r]);
2331   output_w32(0xe7d00000|rd_rn_rm(HOST_TEMPREG,base,r)|0x620);
2332   emit_cmpimm(HOST_TEMPREG,imm);
2333 }
2334
2335 // special case for tlb mapping
2336 void emit_addsr12(int rs1,int rs2,int rt)
2337 {
2338   assem_debug("add %s,%s,%s lsr #12\n",regname[rt],regname[rs1],regname[rs2]);
2339   output_w32(0xe0800620|rd_rn_rm(rt,rs1,rs2));
2340 }
2341
2342 void emit_callne(int a)
2343 {
2344   assem_debug("blne %x\n",a);
2345   u_int offset=genjmp(a);
2346   output_w32(0x1b000000|offset);
2347 }
2348
2349 // Used to preload hash table entries
2350 void emit_prefetch(void *addr)
2351 {
2352   assem_debug("prefetch %x\n",(int)addr);
2353   output_byte(0x0F);
2354   output_byte(0x18);
2355   output_modrm(0,5,1);
2356   output_w32((int)addr);
2357 }
2358 void emit_prefetchreg(int r)
2359 {
2360   assem_debug("pld %s\n",regname[r]);
2361   output_w32(0xf5d0f000|rd_rn_rm(0,r,0));
2362 }
2363
2364 // Special case for mini_ht
2365 void emit_ldreq_indexed(int rs, u_int offset, int rt)
2366 {
2367   assert(offset<4096);
2368   assem_debug("ldreq %s,[%s, #%d]\n",regname[rt],regname[rs],offset);
2369   output_w32(0x05900000|rd_rn_rm(rt,rs,0)|offset);
2370 }
2371
2372 void emit_flds(int r,int sr)
2373 {
2374   assem_debug("flds s%d,[%s]\n",sr,regname[r]);
2375   output_w32(0xed900a00|((sr&14)<<11)|((sr&1)<<22)|(r<<16));
2376
2377
2378 void emit_vldr(int r,int vr)
2379 {
2380   assem_debug("vldr d%d,[%s]\n",vr,regname[r]);
2381   output_w32(0xed900b00|(vr<<12)|(r<<16));
2382
2383
2384 void emit_fsts(int sr,int r)
2385 {
2386   assem_debug("fsts s%d,[%s]\n",sr,regname[r]);
2387   output_w32(0xed800a00|((sr&14)<<11)|((sr&1)<<22)|(r<<16));
2388
2389
2390 void emit_vstr(int vr,int r)
2391 {
2392   assem_debug("vstr d%d,[%s]\n",vr,regname[r]);
2393   output_w32(0xed800b00|(vr<<12)|(r<<16));
2394
2395
2396 void emit_ftosizs(int s,int d)
2397 {
2398   assem_debug("ftosizs s%d,s%d\n",d,s);
2399   output_w32(0xeebd0ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2400
2401
2402 void emit_ftosizd(int s,int d)
2403 {
2404   assem_debug("ftosizd s%d,d%d\n",d,s);
2405   output_w32(0xeebd0bc0|((d&14)<<11)|((d&1)<<22)|(s&7));
2406
2407
2408 void emit_fsitos(int s,int d)
2409 {
2410   assem_debug("fsitos s%d,s%d\n",d,s);
2411   output_w32(0xeeb80ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2412
2413
2414 void emit_fsitod(int s,int d)
2415 {
2416   assem_debug("fsitod d%d,s%d\n",d,s);
2417   output_w32(0xeeb80bc0|((d&7)<<12)|((s&14)>>1)|((s&1)<<5));
2418
2419
2420 void emit_fcvtds(int s,int d)
2421 {
2422   assem_debug("fcvtds d%d,s%d\n",d,s);
2423   output_w32(0xeeb70ac0|((d&7)<<12)|((s&14)>>1)|((s&1)<<5));
2424
2425
2426 void emit_fcvtsd(int s,int d)
2427 {
2428   assem_debug("fcvtsd s%d,d%d\n",d,s);
2429   output_w32(0xeeb70bc0|((d&14)<<11)|((d&1)<<22)|(s&7));
2430
2431
2432 void emit_fsqrts(int s,int d)
2433 {
2434   assem_debug("fsqrts d%d,s%d\n",d,s);
2435   output_w32(0xeeb10ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2436
2437
2438 void emit_fsqrtd(int s,int d)
2439 {
2440   assem_debug("fsqrtd s%d,d%d\n",d,s);
2441   output_w32(0xeeb10bc0|((d&7)<<12)|(s&7));
2442
2443
2444 void emit_fabss(int s,int d)
2445 {
2446   assem_debug("fabss d%d,s%d\n",d,s);
2447   output_w32(0xeeb00ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2448
2449
2450 void emit_fabsd(int s,int d)
2451 {
2452   assem_debug("fabsd s%d,d%d\n",d,s);
2453   output_w32(0xeeb00bc0|((d&7)<<12)|(s&7));
2454
2455
2456 void emit_fnegs(int s,int d)
2457 {
2458   assem_debug("fnegs d%d,s%d\n",d,s);
2459   output_w32(0xeeb10a40|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2460
2461
2462 void emit_fnegd(int s,int d)
2463 {
2464   assem_debug("fnegd s%d,d%d\n",d,s);
2465   output_w32(0xeeb10b40|((d&7)<<12)|(s&7));
2466
2467
2468 void emit_fadds(int s1,int s2,int d)
2469 {
2470   assem_debug("fadds s%d,s%d,s%d\n",d,s1,s2);
2471   output_w32(0xee300a00|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2472
2473
2474 void emit_faddd(int s1,int s2,int d)
2475 {
2476   assem_debug("faddd d%d,d%d,d%d\n",d,s1,s2);
2477   output_w32(0xee300b00|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2478
2479
2480 void emit_fsubs(int s1,int s2,int d)
2481 {
2482   assem_debug("fsubs s%d,s%d,s%d\n",d,s1,s2);
2483   output_w32(0xee300a40|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2484
2485
2486 void emit_fsubd(int s1,int s2,int d)
2487 {
2488   assem_debug("fsubd d%d,d%d,d%d\n",d,s1,s2);
2489   output_w32(0xee300b40|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2490
2491
2492 void emit_fmuls(int s1,int s2,int d)
2493 {
2494   assem_debug("fmuls s%d,s%d,s%d\n",d,s1,s2);
2495   output_w32(0xee200a00|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2496
2497
2498 void emit_fmuld(int s1,int s2,int d)
2499 {
2500   assem_debug("fmuld d%d,d%d,d%d\n",d,s1,s2);
2501   output_w32(0xee200b00|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2502
2503
2504 void emit_fdivs(int s1,int s2,int d)
2505 {
2506   assem_debug("fdivs s%d,s%d,s%d\n",d,s1,s2);
2507   output_w32(0xee800a00|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2508
2509
2510 void emit_fdivd(int s1,int s2,int d)
2511 {
2512   assem_debug("fdivd d%d,d%d,d%d\n",d,s1,s2);
2513   output_w32(0xee800b00|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2514
2515
2516 void emit_fcmps(int x,int y)
2517 {
2518   assem_debug("fcmps s14, s15\n");
2519   output_w32(0xeeb47a67);
2520
2521
2522 void emit_fcmpd(int x,int y)
2523 {
2524   assem_debug("fcmpd d6, d7\n");
2525   output_w32(0xeeb46b47);
2526
2527
2528 void emit_fmstat()
2529 {
2530   assem_debug("fmstat\n");
2531   output_w32(0xeef1fa10);
2532
2533
2534 void emit_bicne_imm(int rs,int imm,int rt)
2535 {
2536   u_int armval;
2537   genimm_checked(imm,&armval);
2538   assem_debug("bicne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2539   output_w32(0x13c00000|rd_rn_rm(rt,rs,0)|armval);
2540 }
2541
2542 void emit_biccs_imm(int rs,int imm,int rt)
2543 {
2544   u_int armval;
2545   genimm_checked(imm,&armval);
2546   assem_debug("biccs %s,%s,#%d\n",regname[rt],regname[rs],imm);
2547   output_w32(0x23c00000|rd_rn_rm(rt,rs,0)|armval);
2548 }
2549
2550 void emit_bicvc_imm(int rs,int imm,int rt)
2551 {
2552   u_int armval;
2553   genimm_checked(imm,&armval);
2554   assem_debug("bicvc %s,%s,#%d\n",regname[rt],regname[rs],imm);
2555   output_w32(0x73c00000|rd_rn_rm(rt,rs,0)|armval);
2556 }
2557
2558 void emit_bichi_imm(int rs,int imm,int rt)
2559 {
2560   u_int armval;
2561   genimm_checked(imm,&armval);
2562   assem_debug("bichi %s,%s,#%d\n",regname[rt],regname[rs],imm);
2563   output_w32(0x83c00000|rd_rn_rm(rt,rs,0)|armval);
2564 }
2565
2566 void emit_orrvs_imm(int rs,int imm,int rt)
2567 {
2568   u_int armval;
2569   genimm_checked(imm,&armval);
2570   assem_debug("orrvs %s,%s,#%d\n",regname[rt],regname[rs],imm);
2571   output_w32(0x63800000|rd_rn_rm(rt,rs,0)|armval);
2572 }
2573
2574 void emit_orrne_imm(int rs,int imm,int rt)
2575 {
2576   u_int armval;
2577   genimm_checked(imm,&armval);
2578   assem_debug("orrne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2579   output_w32(0x13800000|rd_rn_rm(rt,rs,0)|armval);
2580 }
2581
2582 void emit_andne_imm(int rs,int imm,int rt)
2583 {
2584   u_int armval;
2585   genimm_checked(imm,&armval);
2586   assem_debug("andne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2587   output_w32(0x12000000|rd_rn_rm(rt,rs,0)|armval);
2588 }
2589
2590 void emit_addpl_imm(int rs,int imm,int rt)
2591 {
2592   u_int armval;
2593   genimm_checked(imm,&armval);
2594   assem_debug("addpl %s,%s,#%d\n",regname[rt],regname[rs],imm);
2595   output_w32(0x52800000|rd_rn_rm(rt,rs,0)|armval);
2596 }
2597
2598 void emit_jno_unlikely(int a)
2599 {
2600   //emit_jno(a);
2601   assem_debug("addvc pc,pc,#? (%x)\n",/*a-(int)out-8,*/a);
2602   output_w32(0x72800000|rd_rn_rm(15,15,0));
2603 }
2604
2605 static void save_regs_all(u_int reglist)
2606 {
2607   int i;
2608   if(!reglist) return;
2609   assem_debug("stmia fp,{");
2610   for(i=0;i<16;i++)
2611     if(reglist&(1<<i))
2612       assem_debug("r%d,",i);
2613   assem_debug("}\n");
2614   output_w32(0xe88b0000|reglist);
2615 }
2616 static void restore_regs_all(u_int reglist)
2617 {
2618   int i;
2619   if(!reglist) return;
2620   assem_debug("ldmia fp,{");
2621   for(i=0;i<16;i++)
2622     if(reglist&(1<<i))
2623       assem_debug("r%d,",i);
2624   assem_debug("}\n");
2625   output_w32(0xe89b0000|reglist);
2626 }
2627 // Save registers before function call
2628 static void save_regs(u_int reglist)
2629 {
2630   reglist&=0x100f; // only save the caller-save registers, r0-r3, r12
2631   save_regs_all(reglist);
2632 }
2633 // Restore registers after function call
2634 static void restore_regs(u_int reglist)
2635 {
2636   reglist&=0x100f; // only restore the caller-save registers, r0-r3, r12
2637   restore_regs_all(reglist);
2638 }
2639
2640 // Write back consts using r14 so we don't disturb the other registers
2641 void wb_consts(signed char i_regmap[],uint64_t i_is32,u_int i_dirty,int i)
2642 {
2643   int hr;
2644   for(hr=0;hr<HOST_REGS;hr++) {
2645     if(hr!=EXCLUDE_REG&&i_regmap[hr]>=0&&((i_dirty>>hr)&1)) {
2646       if(((regs[i].isconst>>hr)&1)&&i_regmap[hr]>0) {
2647         if(i_regmap[hr]<64 || !((i_is32>>(i_regmap[hr]&63))&1) ) {
2648           int value=constmap[i][hr];
2649           if(value==0) {
2650             emit_zeroreg(HOST_TEMPREG);
2651           }
2652           else {
2653             emit_movimm(value,HOST_TEMPREG);
2654           }
2655           emit_storereg(i_regmap[hr],HOST_TEMPREG);
2656 #ifndef FORCE32
2657           if((i_is32>>i_regmap[hr])&1) {
2658             if(value!=-1&&value!=0) emit_sarimm(HOST_TEMPREG,31,HOST_TEMPREG);
2659             emit_storereg(i_regmap[hr]|64,HOST_TEMPREG);
2660           }
2661 #endif
2662         }
2663       }
2664     }
2665   }
2666 }
2667
2668 /* Stubs/epilogue */
2669
2670 void literal_pool(int n)
2671 {
2672   if(!literalcount) return;
2673   if(n) {
2674     if((int)out-literals[0][0]<4096-n) return;
2675   }
2676   u_int *ptr;
2677   int i;
2678   for(i=0;i<literalcount;i++)
2679   {
2680     u_int l_addr=(u_int)out;
2681     int j;
2682     for(j=0;j<i;j++) {
2683       if(literals[j][1]==literals[i][1]) {
2684         //printf("dup %08x\n",literals[i][1]);
2685         l_addr=literals[j][0];
2686         break;
2687       }
2688     }
2689     ptr=(u_int *)literals[i][0];
2690     u_int offset=l_addr-(u_int)ptr-8;
2691     assert(offset<4096);
2692     assert(!(offset&3));
2693     *ptr|=offset;
2694     if(l_addr==(u_int)out) {
2695       literals[i][0]=l_addr; // remember for dupes
2696       output_w32(literals[i][1]);
2697     }
2698   }
2699   literalcount=0;
2700 }
2701
2702 void literal_pool_jumpover(int n)
2703 {
2704   if(!literalcount) return;
2705   if(n) {
2706     if((int)out-literals[0][0]<4096-n) return;
2707   }
2708   int jaddr=(int)out;
2709   emit_jmp(0);
2710   literal_pool(0);
2711   set_jump_target(jaddr,(int)out);
2712 }
2713
2714 emit_extjump2(u_int addr, int target, int linker)
2715 {
2716   u_char *ptr=(u_char *)addr;
2717   assert((ptr[3]&0x0e)==0xa);
2718   emit_loadlp(target,0);
2719   emit_loadlp(addr,1);
2720   assert(addr>=BASE_ADDR&&addr<(BASE_ADDR+(1<<TARGET_SIZE_2)));
2721   //assert((target>=0x80000000&&target<0x80800000)||(target>0xA4000000&&target<0xA4001000));
2722 //DEBUG >
2723 #ifdef DEBUG_CYCLE_COUNT
2724   emit_readword((int)&last_count,ECX);
2725   emit_add(HOST_CCREG,ECX,HOST_CCREG);
2726   emit_readword((int)&next_interupt,ECX);
2727   emit_writeword(HOST_CCREG,(int)&Count);
2728   emit_sub(HOST_CCREG,ECX,HOST_CCREG);
2729   emit_writeword(ECX,(int)&last_count);
2730 #endif
2731 //DEBUG <
2732   emit_jmp(linker);
2733 }
2734
2735 emit_extjump(int addr, int target)
2736 {
2737   emit_extjump2(addr, target, (int)dyna_linker);
2738 }
2739 emit_extjump_ds(int addr, int target)
2740 {
2741   emit_extjump2(addr, target, (int)dyna_linker_ds);
2742 }
2743
2744 // put rt_val into rt, potentially making use of rs with value rs_val
2745 static void emit_movimm_from(u_int rs_val,int rs,u_int rt_val,int rt)
2746 {
2747   u_int armval;
2748   int diff;
2749   if(genimm(rt_val,&armval)) {
2750     assem_debug("mov %s,#%d\n",regname[rt],rt_val);
2751     output_w32(0xe3a00000|rd_rn_rm(rt,0,0)|armval);
2752     return;
2753   }
2754   if(genimm(~rt_val,&armval)) {
2755     assem_debug("mvn %s,#%d\n",regname[rt],rt_val);
2756     output_w32(0xe3e00000|rd_rn_rm(rt,0,0)|armval);
2757     return;
2758   }
2759   diff=rt_val-rs_val;
2760   if(genimm(diff,&armval)) {
2761     assem_debug("add %s,%s,#%d\n",regname[rt],regname[rs],diff);
2762     output_w32(0xe2800000|rd_rn_rm(rt,rs,0)|armval);
2763     return;
2764   }else if(genimm(-diff,&armval)) {
2765     assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rs],-diff);
2766     output_w32(0xe2400000|rd_rn_rm(rt,rs,0)|armval);
2767     return;
2768   }
2769   emit_movimm(rt_val,rt);
2770 }
2771
2772 // return 1 if above function can do it's job cheaply
2773 static int is_similar_value(u_int v1,u_int v2)
2774 {
2775   u_int xs;
2776   int diff;
2777   if(v1==v2) return 1;
2778   diff=v2-v1;
2779   for(xs=diff;xs!=0&&(xs&3)==0;xs>>=2)
2780     ;
2781   if(xs<0x100) return 1;
2782   for(xs=-diff;xs!=0&&(xs&3)==0;xs>>=2)
2783     ;
2784   if(xs<0x100) return 1;
2785   return 0;
2786 }
2787
2788 // trashes r2
2789 static void pass_args(int a0, int a1)
2790 {
2791   if(a0==1&&a1==0) {
2792     // must swap
2793     emit_mov(a0,2); emit_mov(a1,1); emit_mov(2,0);
2794   }
2795   else if(a0!=0&&a1==0) {
2796     emit_mov(a1,1);
2797     if (a0>=0) emit_mov(a0,0);
2798   }
2799   else {
2800     if(a0>=0&&a0!=0) emit_mov(a0,0);
2801     if(a1>=0&&a1!=1) emit_mov(a1,1);
2802   }
2803 }
2804
2805 static void mov_loadtype_adj(int type,int rs,int rt)
2806 {
2807   switch(type) {
2808     case LOADB_STUB:  emit_signextend8(rs,rt); break;
2809     case LOADBU_STUB: emit_andimm(rs,0xff,rt); break;
2810     case LOADH_STUB:  emit_signextend16(rs,rt); break;
2811     case LOADHU_STUB: emit_andimm(rs,0xffff,rt); break;
2812     case LOADW_STUB:  if(rs!=rt) emit_mov(rs,rt); break;
2813     default: assert(0);
2814   }
2815 }
2816
2817 #ifdef PCSX
2818 #include "pcsxmem.h"
2819 #include "pcsxmem_inline.c"
2820 #endif
2821
2822 do_readstub(int n)
2823 {
2824   assem_debug("do_readstub %x\n",start+stubs[n][3]*4);
2825   literal_pool(256);
2826   set_jump_target(stubs[n][1],(int)out);
2827   int type=stubs[n][0];
2828   int i=stubs[n][3];
2829   int rs=stubs[n][4];
2830   struct regstat *i_regs=(struct regstat *)stubs[n][5];
2831   u_int reglist=stubs[n][7];
2832   signed char *i_regmap=i_regs->regmap;
2833   int addr=get_reg(i_regmap,AGEN1+(i&1));
2834   int rth,rt;
2835   int ds;
2836   if(itype[i]==C1LS||itype[i]==C2LS||itype[i]==LOADLR) {
2837     rth=get_reg(i_regmap,FTEMP|64);
2838     rt=get_reg(i_regmap,FTEMP);
2839   }else{
2840     rth=get_reg(i_regmap,rt1[i]|64);
2841     rt=get_reg(i_regmap,rt1[i]);
2842   }
2843   assert(rs>=0);
2844 #ifdef PCSX
2845   int r,temp=-1,temp2=HOST_TEMPREG,regs_saved=0,restore_jump=0;
2846   reglist|=(1<<rs);
2847   for(r=0;r<=12;r++) {
2848     if(((1<<r)&0x13ff)&&((1<<r)&reglist)==0) {
2849       temp=r; break;
2850     }
2851   }
2852   if(rt>=0&&rt1[i]!=0)
2853     reglist&=~(1<<rt);
2854   if(temp==-1) {
2855     save_regs(reglist);
2856     regs_saved=1;
2857     temp=(rs==0)?2:0;
2858   }
2859   if((regs_saved||(reglist&2)==0)&&temp!=1&&rs!=1)
2860     temp2=1;
2861   emit_readword((int)&mem_rtab,temp);
2862   emit_shrimm(rs,12,temp2);
2863   emit_readword_dualindexedx4(temp,temp2,temp2);
2864   emit_lsls_imm(temp2,1,temp2);
2865   if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
2866     switch(type) {
2867       case LOADB_STUB:  emit_ldrccsb_dualindexed(temp2,rs,rt); break;
2868       case LOADBU_STUB: emit_ldrccb_dualindexed(temp2,rs,rt); break;
2869       case LOADH_STUB:  emit_ldrccsh_dualindexed(temp2,rs,rt); break;
2870       case LOADHU_STUB: emit_ldrcch_dualindexed(temp2,rs,rt); break;
2871       case LOADW_STUB:  emit_ldrcc_dualindexed(temp2,rs,rt); break;
2872     }
2873   }
2874   if(regs_saved) {
2875     restore_jump=(int)out;
2876     emit_jcc(0); // jump to reg restore
2877   }
2878   else
2879     emit_jcc(stubs[n][2]); // return address
2880
2881   if(!regs_saved)
2882     save_regs(reglist);
2883   int handler=0;
2884   if(type==LOADB_STUB||type==LOADBU_STUB)
2885     handler=(int)jump_handler_read8;
2886   if(type==LOADH_STUB||type==LOADHU_STUB)
2887     handler=(int)jump_handler_read16;
2888   if(type==LOADW_STUB)
2889     handler=(int)jump_handler_read32;
2890   assert(handler!=0);
2891   pass_args(rs,temp2);
2892   int cc=get_reg(i_regmap,CCREG);
2893   if(cc<0)
2894     emit_loadreg(CCREG,2);
2895   emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
2896   emit_call(handler);
2897   if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
2898     mov_loadtype_adj(type,0,rt);
2899   }
2900   if(restore_jump)
2901     set_jump_target(restore_jump,(int)out);
2902   restore_regs(reglist);
2903   emit_jmp(stubs[n][2]); // return address
2904 #else // !PCSX
2905   if(addr<0) addr=rt;
2906   if(addr<0&&itype[i]!=C1LS&&itype[i]!=C2LS&&itype[i]!=LOADLR) addr=get_reg(i_regmap,-1);
2907   assert(addr>=0);
2908   int ftable=0;
2909   if(type==LOADB_STUB||type==LOADBU_STUB)
2910     ftable=(int)readmemb;
2911   if(type==LOADH_STUB||type==LOADHU_STUB)
2912     ftable=(int)readmemh;
2913   if(type==LOADW_STUB)
2914     ftable=(int)readmem;
2915 #ifndef FORCE32
2916   if(type==LOADD_STUB)
2917     ftable=(int)readmemd;
2918 #endif
2919   assert(ftable!=0);
2920   emit_writeword(rs,(int)&address);
2921   //emit_pusha();
2922   save_regs(reglist);
2923 #ifndef PCSX
2924   ds=i_regs!=&regs[i];
2925   int real_rs=(itype[i]==LOADLR)?-1:get_reg(i_regmap,rs1[i]);
2926   u_int cmask=ds?-1:(0x100f|~i_regs->wasconst);
2927   if(!ds) load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs))&0x100f,i);
2928   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty&cmask&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs)));
2929   if(!ds) wb_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs))&~0x100f,i);
2930 #endif
2931   emit_shrimm(rs,16,1);
2932   int cc=get_reg(i_regmap,CCREG);
2933   if(cc<0) {
2934     emit_loadreg(CCREG,2);
2935   }
2936   emit_movimm(ftable,0);
2937   emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
2938 #ifndef PCSX
2939   emit_movimm(start+stubs[n][3]*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
2940 #endif
2941   //emit_readword((int)&last_count,temp);
2942   //emit_add(cc,temp,cc);
2943   //emit_writeword(cc,(int)&Count);
2944   //emit_mov(15,14);
2945   emit_call((int)&indirect_jump_indexed);
2946   //emit_callreg(rs);
2947   //emit_readword_dualindexedx4(rs,HOST_TEMPREG,15);
2948 #ifndef PCSX
2949   // We really shouldn't need to update the count here,
2950   // but not doing so causes random crashes...
2951   emit_readword((int)&Count,HOST_TEMPREG);
2952   emit_readword((int)&next_interupt,2);
2953   emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
2954   emit_writeword(2,(int)&last_count);
2955   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
2956   if(cc<0) {
2957     emit_storereg(CCREG,HOST_TEMPREG);
2958   }
2959 #endif
2960   //emit_popa();
2961   restore_regs(reglist);
2962   //if((cc=get_reg(regmap,CCREG))>=0) {
2963   //  emit_loadreg(CCREG,cc);
2964   //}
2965   if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
2966     assert(rt>=0);
2967     if(type==LOADB_STUB)
2968       emit_movsbl((int)&readmem_dword,rt);
2969     if(type==LOADBU_STUB)
2970       emit_movzbl((int)&readmem_dword,rt);
2971     if(type==LOADH_STUB)
2972       emit_movswl((int)&readmem_dword,rt);
2973     if(type==LOADHU_STUB)
2974       emit_movzwl((int)&readmem_dword,rt);
2975     if(type==LOADW_STUB)
2976       emit_readword((int)&readmem_dword,rt);
2977     if(type==LOADD_STUB) {
2978       emit_readword((int)&readmem_dword,rt);
2979       if(rth>=0) emit_readword(((int)&readmem_dword)+4,rth);
2980     }
2981   }
2982   emit_jmp(stubs[n][2]); // return address
2983 #endif // !PCSX
2984 }
2985
2986 #ifdef PCSX
2987 // return memhandler, or get directly accessable address and return 0
2988 u_int get_direct_memhandler(void *table,u_int addr,int type,u_int *addr_host)
2989 {
2990   u_int l1,l2=0;
2991   l1=((u_int *)table)[addr>>12];
2992   if((l1&(1<<31))==0) {
2993     u_int v=l1<<1;
2994     *addr_host=v+addr;
2995     return 0;
2996   }
2997   else {
2998     l1<<=1;
2999     if(type==LOADB_STUB||type==LOADBU_STUB||type==STOREB_STUB)
3000       l2=((u_int *)l1)[0x1000/4 + 0x1000/2 + (addr&0xfff)];
3001     else if(type==LOADH_STUB||type==LOADHU_STUB||type==STOREH_STUB)
3002       l2=((u_int *)l1)[0x1000/4 + (addr&0xfff)/2];
3003     else
3004       l2=((u_int *)l1)[(addr&0xfff)/4];
3005     if((l2&(1<<31))==0) {
3006       u_int v=l2<<1;
3007       *addr_host=v+(addr&0xfff);
3008       return 0;
3009     }
3010     return l2<<1;
3011   }
3012 }
3013 #endif
3014
3015 inline_readstub(int type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
3016 {
3017   int rs=get_reg(regmap,target);
3018   int rth=get_reg(regmap,target|64);
3019   int rt=get_reg(regmap,target);
3020   if(rs<0) rs=get_reg(regmap,-1);
3021   assert(rs>=0);
3022 #ifdef PCSX
3023   u_int handler,host_addr=0,is_dynamic,far_call=0;
3024   int cc=get_reg(regmap,CCREG);
3025   if(pcsx_direct_read(type,addr,CLOCK_ADJUST(adj+1),cc,target?rs:-1,rt))
3026     return;
3027   handler=get_direct_memhandler(mem_rtab,addr,type,&host_addr);
3028   if (handler==0) {
3029     if(rt<0||rt1[i]==0)
3030       return;
3031     if(addr!=host_addr)
3032       emit_movimm_from(addr,rs,host_addr,rs);
3033     switch(type) {
3034       case LOADB_STUB:  emit_movsbl_indexed(0,rs,rt); break;
3035       case LOADBU_STUB: emit_movzbl_indexed(0,rs,rt); break;
3036       case LOADH_STUB:  emit_movswl_indexed(0,rs,rt); break;
3037       case LOADHU_STUB: emit_movzwl_indexed(0,rs,rt); break;
3038       case LOADW_STUB:  emit_readword_indexed(0,rs,rt); break;
3039       default:          assert(0);
3040     }
3041     return;
3042   }
3043   is_dynamic=pcsxmem_is_handler_dynamic(addr);
3044   if(is_dynamic) {
3045     if(type==LOADB_STUB||type==LOADBU_STUB)
3046       handler=(int)jump_handler_read8;
3047     if(type==LOADH_STUB||type==LOADHU_STUB)
3048       handler=(int)jump_handler_read16;
3049     if(type==LOADW_STUB)
3050       handler=(int)jump_handler_read32;
3051   }
3052
3053   // call a memhandler
3054   if(rt>=0&&rt1[i]!=0)
3055     reglist&=~(1<<rt);
3056   save_regs(reglist);
3057   if(target==0)
3058     emit_movimm(addr,0);
3059   else if(rs!=0)
3060     emit_mov(rs,0);
3061   int offset=(int)handler-(int)out-8;
3062   if(offset<-33554432||offset>=33554432) {
3063     // unreachable memhandler, a plugin func perhaps
3064     emit_movimm(handler,12);
3065     far_call=1;
3066   }
3067   if(cc<0)
3068     emit_loadreg(CCREG,2);
3069   if(is_dynamic) {
3070     emit_movimm(((u_int *)mem_rtab)[addr>>12]<<1,1);
3071     emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3072   }
3073   else {
3074     emit_readword((int)&last_count,3);
3075     emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3076     emit_add(2,3,2);
3077     emit_writeword(2,(int)&Count);
3078   }
3079
3080   if(far_call)
3081     emit_callreg(12);
3082   else
3083     emit_call(handler);
3084
3085   if(rt>=0&&rt1[i]!=0) {
3086     switch(type) {
3087       case LOADB_STUB:  emit_signextend8(0,rt); break;
3088       case LOADBU_STUB: emit_andimm(0,0xff,rt); break;
3089       case LOADH_STUB:  emit_signextend16(0,rt); break;
3090       case LOADHU_STUB: emit_andimm(0,0xffff,rt); break;
3091       case LOADW_STUB:  if(rt!=0) emit_mov(0,rt); break;
3092       default:          assert(0);
3093     }
3094   }
3095   restore_regs(reglist);
3096 #else // if !PCSX
3097   int ftable=0;
3098   if(type==LOADB_STUB||type==LOADBU_STUB)
3099     ftable=(int)readmemb;
3100   if(type==LOADH_STUB||type==LOADHU_STUB)
3101     ftable=(int)readmemh;
3102   if(type==LOADW_STUB)
3103     ftable=(int)readmem;
3104 #ifndef FORCE32
3105   if(type==LOADD_STUB)
3106     ftable=(int)readmemd;
3107 #endif
3108   assert(ftable!=0);
3109   if(target==0)
3110     emit_movimm(addr,rs);
3111   emit_writeword(rs,(int)&address);
3112   //emit_pusha();
3113   save_regs(reglist);
3114 #ifndef PCSX
3115   if((signed int)addr>=(signed int)0xC0000000) {
3116     // Theoretically we can have a pagefault here, if the TLB has never
3117     // been enabled and the address is outside the range 80000000..BFFFFFFF
3118     // Write out the registers so the pagefault can be handled.  This is
3119     // a very rare case and likely represents a bug.
3120     int ds=regmap!=regs[i].regmap;
3121     if(!ds) load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
3122     if(!ds) wb_dirtys(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty);
3123     else wb_dirtys(branch_regs[i-1].regmap_entry,branch_regs[i-1].was32,branch_regs[i-1].wasdirty);
3124   }
3125 #endif
3126   //emit_shrimm(rs,16,1);
3127   int cc=get_reg(regmap,CCREG);
3128   if(cc<0) {
3129     emit_loadreg(CCREG,2);
3130   }
3131   //emit_movimm(ftable,0);
3132   emit_movimm(((u_int *)ftable)[addr>>16],0);
3133   //emit_readword((int)&last_count,12);
3134   emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3135 #ifndef PCSX
3136   if((signed int)addr>=(signed int)0xC0000000) {
3137     // Pagefault address
3138     int ds=regmap!=regs[i].regmap;
3139     emit_movimm(start+i*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3140   }
3141 #endif
3142   //emit_add(12,2,2);
3143   //emit_writeword(2,(int)&Count);
3144   //emit_call(((u_int *)ftable)[addr>>16]);
3145   emit_call((int)&indirect_jump);
3146 #ifndef PCSX
3147   // We really shouldn't need to update the count here,
3148   // but not doing so causes random crashes...
3149   emit_readword((int)&Count,HOST_TEMPREG);
3150   emit_readword((int)&next_interupt,2);
3151   emit_addimm(HOST_TEMPREG,-CLOCK_ADJUST(adj+1),HOST_TEMPREG);
3152   emit_writeword(2,(int)&last_count);
3153   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3154   if(cc<0) {
3155     emit_storereg(CCREG,HOST_TEMPREG);
3156   }
3157 #endif
3158   //emit_popa();
3159   restore_regs(reglist);
3160   if(rt>=0) {
3161     if(type==LOADB_STUB)
3162       emit_movsbl((int)&readmem_dword,rt);
3163     if(type==LOADBU_STUB)
3164       emit_movzbl((int)&readmem_dword,rt);
3165     if(type==LOADH_STUB)
3166       emit_movswl((int)&readmem_dword,rt);
3167     if(type==LOADHU_STUB)
3168       emit_movzwl((int)&readmem_dword,rt);
3169     if(type==LOADW_STUB)
3170       emit_readword((int)&readmem_dword,rt);
3171     if(type==LOADD_STUB) {
3172       emit_readword((int)&readmem_dword,rt);
3173       if(rth>=0) emit_readword(((int)&readmem_dword)+4,rth);
3174     }
3175   }
3176 #endif // !PCSX
3177 }
3178
3179 do_writestub(int n)
3180 {
3181   assem_debug("do_writestub %x\n",start+stubs[n][3]*4);
3182   literal_pool(256);
3183   set_jump_target(stubs[n][1],(int)out);
3184   int type=stubs[n][0];
3185   int i=stubs[n][3];
3186   int rs=stubs[n][4];
3187   struct regstat *i_regs=(struct regstat *)stubs[n][5];
3188   u_int reglist=stubs[n][7];
3189   signed char *i_regmap=i_regs->regmap;
3190   int addr=get_reg(i_regmap,AGEN1+(i&1));
3191   int rth,rt,r;
3192   int ds;
3193   if(itype[i]==C1LS||itype[i]==C2LS) {
3194     rth=get_reg(i_regmap,FTEMP|64);
3195     rt=get_reg(i_regmap,r=FTEMP);
3196   }else{
3197     rth=get_reg(i_regmap,rs2[i]|64);
3198     rt=get_reg(i_regmap,r=rs2[i]);
3199   }
3200   assert(rs>=0);
3201   assert(rt>=0);
3202 #ifdef PCSX
3203   int rtmp,temp=-1,temp2=HOST_TEMPREG,regs_saved=0,restore_jump=0,ra;
3204   int reglist2=reglist|(1<<rs)|(1<<rt);
3205   for(rtmp=0;rtmp<=12;rtmp++) {
3206     if(((1<<rtmp)&0x13ff)&&((1<<rtmp)&reglist2)==0) {
3207       temp=rtmp; break;
3208     }
3209   }
3210   if(temp==-1) {
3211     save_regs(reglist);
3212     regs_saved=1;
3213     for(rtmp=0;rtmp<=3;rtmp++)
3214       if(rtmp!=rs&&rtmp!=rt)
3215         {temp=rtmp;break;}
3216   }
3217   if((regs_saved||(reglist2&8)==0)&&temp!=3&&rs!=3&&rt!=3)
3218     temp2=3;
3219   emit_readword((int)&mem_wtab,temp);
3220   emit_shrimm(rs,12,temp2);
3221   emit_readword_dualindexedx4(temp,temp2,temp2);
3222   emit_lsls_imm(temp2,1,temp2);
3223   switch(type) {
3224     case STOREB_STUB: emit_strccb_dualindexed(temp2,rs,rt); break;
3225     case STOREH_STUB: emit_strcch_dualindexed(temp2,rs,rt); break;
3226     case STOREW_STUB: emit_strcc_dualindexed(temp2,rs,rt); break;
3227     default:          assert(0);
3228   }
3229   if(regs_saved) {
3230     restore_jump=(int)out;
3231     emit_jcc(0); // jump to reg restore
3232   }
3233   else
3234     emit_jcc(stubs[n][2]); // return address (invcode check)
3235
3236   if(!regs_saved)
3237     save_regs(reglist);
3238   int handler=0;
3239   switch(type) {
3240     case STOREB_STUB: handler=(int)jump_handler_write8; break;
3241     case STOREH_STUB: handler=(int)jump_handler_write16; break;
3242     case STOREW_STUB: handler=(int)jump_handler_write32; break;
3243   }
3244   assert(handler!=0);
3245   pass_args(rs,rt);
3246   if(temp2!=3)
3247     emit_mov(temp2,3);
3248   int cc=get_reg(i_regmap,CCREG);
3249   if(cc<0)
3250     emit_loadreg(CCREG,2);
3251   emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
3252   // returns new cycle_count
3253   emit_call(handler);
3254   emit_addimm(0,-CLOCK_ADJUST((int)stubs[n][6]+1),cc<0?2:cc);
3255   if(cc<0)
3256     emit_storereg(CCREG,2);
3257   if(restore_jump)
3258     set_jump_target(restore_jump,(int)out);
3259   restore_regs(reglist);
3260   ra=stubs[n][2];
3261   emit_jmp(ra);
3262 #else // if !PCSX
3263   if(addr<0) addr=get_reg(i_regmap,-1);
3264   assert(addr>=0);
3265   int ftable=0;
3266   if(type==STOREB_STUB)
3267     ftable=(int)writememb;
3268   if(type==STOREH_STUB)
3269     ftable=(int)writememh;
3270   if(type==STOREW_STUB)
3271     ftable=(int)writemem;
3272 #ifndef FORCE32
3273   if(type==STORED_STUB)
3274     ftable=(int)writememd;
3275 #endif
3276   assert(ftable!=0);
3277   emit_writeword(rs,(int)&address);
3278   //emit_shrimm(rs,16,rs);
3279   //emit_movmem_indexedx4(ftable,rs,rs);
3280   if(type==STOREB_STUB)
3281     emit_writebyte(rt,(int)&byte);
3282   if(type==STOREH_STUB)
3283     emit_writehword(rt,(int)&hword);
3284   if(type==STOREW_STUB)
3285     emit_writeword(rt,(int)&word);
3286   if(type==STORED_STUB) {
3287 #ifndef FORCE32
3288     emit_writeword(rt,(int)&dword);
3289     emit_writeword(r?rth:rt,(int)&dword+4);
3290 #else
3291     SysPrintf("STORED_STUB\n");
3292 #endif
3293   }
3294   //emit_pusha();
3295   save_regs(reglist);
3296 #ifndef PCSX
3297   ds=i_regs!=&regs[i];
3298   int real_rs=get_reg(i_regmap,rs1[i]);
3299   u_int cmask=ds?-1:(0x100f|~i_regs->wasconst);
3300   if(!ds) load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs))&0x100f,i);
3301   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty&cmask&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs)));
3302   if(!ds) wb_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs))&~0x100f,i);
3303 #endif
3304   emit_shrimm(rs,16,1);
3305   int cc=get_reg(i_regmap,CCREG);
3306   if(cc<0) {
3307     emit_loadreg(CCREG,2);
3308   }
3309   emit_movimm(ftable,0);
3310   emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
3311 #ifndef PCSX
3312   emit_movimm(start+stubs[n][3]*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3313 #endif
3314   //emit_readword((int)&last_count,temp);
3315   //emit_addimm(cc,2*stubs[n][5]+2,cc);
3316   //emit_add(cc,temp,cc);
3317   //emit_writeword(cc,(int)&Count);
3318   emit_call((int)&indirect_jump_indexed);
3319   //emit_callreg(rs);
3320   emit_readword((int)&Count,HOST_TEMPREG);
3321   emit_readword((int)&next_interupt,2);
3322   emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
3323   emit_writeword(2,(int)&last_count);
3324   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3325   if(cc<0) {
3326     emit_storereg(CCREG,HOST_TEMPREG);
3327   }
3328   //emit_popa();
3329   restore_regs(reglist);
3330   //if((cc=get_reg(regmap,CCREG))>=0) {
3331   //  emit_loadreg(CCREG,cc);
3332   //}
3333   emit_jmp(stubs[n][2]); // return address
3334 #endif // !PCSX
3335 }
3336
3337 inline_writestub(int type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
3338 {
3339   int rs=get_reg(regmap,-1);
3340   int rth=get_reg(regmap,target|64);
3341   int rt=get_reg(regmap,target);
3342   assert(rs>=0);
3343   assert(rt>=0);
3344 #ifdef PCSX
3345   u_int handler,host_addr=0;
3346   handler=get_direct_memhandler(mem_wtab,addr,type,&host_addr);
3347   if (handler==0) {
3348     if(addr!=host_addr)
3349       emit_movimm_from(addr,rs,host_addr,rs);
3350     switch(type) {
3351       case STOREB_STUB: emit_writebyte_indexed(rt,0,rs); break;
3352       case STOREH_STUB: emit_writehword_indexed(rt,0,rs); break;
3353       case STOREW_STUB: emit_writeword_indexed(rt,0,rs); break;
3354       default:          assert(0);
3355     }
3356     return;
3357   }
3358
3359   // call a memhandler
3360   save_regs(reglist);
3361   pass_args(rs,rt);
3362   int cc=get_reg(regmap,CCREG);
3363   if(cc<0)
3364     emit_loadreg(CCREG,2);
3365   emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3366   emit_movimm(handler,3);
3367   // returns new cycle_count
3368   emit_call((int)jump_handler_write_h);
3369   emit_addimm(0,-CLOCK_ADJUST(adj+1),cc<0?2:cc);
3370   if(cc<0)
3371     emit_storereg(CCREG,2);
3372   restore_regs(reglist);
3373 #else // if !pcsx
3374   int ftable=0;
3375   if(type==STOREB_STUB)
3376     ftable=(int)writememb;
3377   if(type==STOREH_STUB)
3378     ftable=(int)writememh;
3379   if(type==STOREW_STUB)
3380     ftable=(int)writemem;
3381 #ifndef FORCE32
3382   if(type==STORED_STUB)
3383     ftable=(int)writememd;
3384 #endif
3385   assert(ftable!=0);
3386   emit_writeword(rs,(int)&address);
3387   //emit_shrimm(rs,16,rs);
3388   //emit_movmem_indexedx4(ftable,rs,rs);
3389   if(type==STOREB_STUB)
3390     emit_writebyte(rt,(int)&byte);
3391   if(type==STOREH_STUB)
3392     emit_writehword(rt,(int)&hword);
3393   if(type==STOREW_STUB)
3394     emit_writeword(rt,(int)&word);
3395   if(type==STORED_STUB) {
3396 #ifndef FORCE32
3397     emit_writeword(rt,(int)&dword);
3398     emit_writeword(target?rth:rt,(int)&dword+4);
3399 #else
3400     SysPrintf("STORED_STUB\n");
3401 #endif
3402   }
3403   //emit_pusha();
3404   save_regs(reglist);
3405 #ifndef PCSX
3406   // rearmed note: load_all_consts prevents BIOS boot, some bug?
3407   if((signed int)addr>=(signed int)0xC0000000) {
3408     // Theoretically we can have a pagefault here, if the TLB has never
3409     // been enabled and the address is outside the range 80000000..BFFFFFFF
3410     // Write out the registers so the pagefault can be handled.  This is
3411     // a very rare case and likely represents a bug.
3412     int ds=regmap!=regs[i].regmap;
3413     if(!ds) load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
3414     if(!ds) wb_dirtys(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty);
3415     else wb_dirtys(branch_regs[i-1].regmap_entry,branch_regs[i-1].was32,branch_regs[i-1].wasdirty);
3416   }
3417 #endif
3418   //emit_shrimm(rs,16,1);
3419   int cc=get_reg(regmap,CCREG);
3420   if(cc<0) {
3421     emit_loadreg(CCREG,2);
3422   }
3423   //emit_movimm(ftable,0);
3424   emit_movimm(((u_int *)ftable)[addr>>16],0);
3425   //emit_readword((int)&last_count,12);
3426   emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3427 #ifndef PCSX
3428   if((signed int)addr>=(signed int)0xC0000000) {
3429     // Pagefault address
3430     int ds=regmap!=regs[i].regmap;
3431     emit_movimm(start+i*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3432   }
3433 #endif
3434   //emit_add(12,2,2);
3435   //emit_writeword(2,(int)&Count);
3436   //emit_call(((u_int *)ftable)[addr>>16]);
3437   emit_call((int)&indirect_jump);
3438   emit_readword((int)&Count,HOST_TEMPREG);
3439   emit_readword((int)&next_interupt,2);
3440   emit_addimm(HOST_TEMPREG,-CLOCK_ADJUST(adj+1),HOST_TEMPREG);
3441   emit_writeword(2,(int)&last_count);
3442   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3443   if(cc<0) {
3444     emit_storereg(CCREG,HOST_TEMPREG);
3445   }
3446   //emit_popa();
3447   restore_regs(reglist);
3448 #endif
3449 }
3450
3451 do_unalignedwritestub(int n)
3452 {
3453   assem_debug("do_unalignedwritestub %x\n",start+stubs[n][3]*4);
3454   literal_pool(256);
3455   set_jump_target(stubs[n][1],(int)out);
3456
3457   int i=stubs[n][3];
3458   struct regstat *i_regs=(struct regstat *)stubs[n][4];
3459   int addr=stubs[n][5];
3460   u_int reglist=stubs[n][7];
3461   signed char *i_regmap=i_regs->regmap;
3462   int temp2=get_reg(i_regmap,FTEMP);
3463   int rt;
3464   int ds, real_rs;
3465   rt=get_reg(i_regmap,rs2[i]);
3466   assert(rt>=0);
3467   assert(addr>=0);
3468   assert(opcode[i]==0x2a||opcode[i]==0x2e); // SWL/SWR only implemented
3469   reglist|=(1<<addr);
3470   reglist&=~(1<<temp2);
3471
3472 #if 1
3473   // don't bother with it and call write handler
3474   save_regs(reglist);
3475   pass_args(addr,rt);
3476   int cc=get_reg(i_regmap,CCREG);
3477   if(cc<0)
3478     emit_loadreg(CCREG,2);
3479   emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
3480   emit_call((int)(opcode[i]==0x2a?jump_handle_swl:jump_handle_swr));
3481   emit_addimm(0,-CLOCK_ADJUST((int)stubs[n][6]+1),cc<0?2:cc);
3482   if(cc<0)
3483     emit_storereg(CCREG,2);
3484   restore_regs(reglist);
3485   emit_jmp(stubs[n][2]); // return address
3486 #else
3487   emit_andimm(addr,0xfffffffc,temp2);
3488   emit_writeword(temp2,(int)&address);
3489
3490   save_regs(reglist);
3491 #ifndef PCSX
3492   ds=i_regs!=&regs[i];
3493   real_rs=get_reg(i_regmap,rs1[i]);
3494   u_int cmask=ds?-1:(0x100f|~i_regs->wasconst);
3495   if(!ds) load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs))&0x100f,i);
3496   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty&cmask&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs)));
3497   if(!ds) wb_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs))&~0x100f,i);
3498 #endif
3499   emit_shrimm(addr,16,1);
3500   int cc=get_reg(i_regmap,CCREG);
3501   if(cc<0) {
3502     emit_loadreg(CCREG,2);
3503   }
3504   emit_movimm((u_int)readmem,0);
3505   emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
3506 #ifndef PCSX
3507   // pagefault address
3508   emit_movimm(start+stubs[n][3]*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3509 #endif
3510   emit_call((int)&indirect_jump_indexed);
3511   restore_regs(reglist);
3512
3513   emit_readword((int)&readmem_dword,temp2);
3514   int temp=addr; //hmh
3515   emit_shlimm(addr,3,temp);
3516   emit_andimm(temp,24,temp);
3517 #ifdef BIG_ENDIAN_MIPS
3518   if (opcode[i]==0x2e) // SWR
3519 #else
3520   if (opcode[i]==0x2a) // SWL
3521 #endif
3522     emit_xorimm(temp,24,temp);
3523   emit_movimm(-1,HOST_TEMPREG);
3524   if (opcode[i]==0x2a) { // SWL
3525     emit_bic_lsr(temp2,HOST_TEMPREG,temp,temp2);
3526     emit_orrshr(rt,temp,temp2);
3527   }else{
3528     emit_bic_lsl(temp2,HOST_TEMPREG,temp,temp2);
3529     emit_orrshl(rt,temp,temp2);
3530   }
3531   emit_readword((int)&address,addr);
3532   emit_writeword(temp2,(int)&word);
3533   //save_regs(reglist); // don't need to, no state changes
3534   emit_shrimm(addr,16,1);
3535   emit_movimm((u_int)writemem,0);
3536   //emit_call((int)&indirect_jump_indexed);
3537   emit_mov(15,14);
3538   emit_readword_dualindexedx4(0,1,15);
3539   emit_readword((int)&Count,HOST_TEMPREG);
3540   emit_readword((int)&next_interupt,2);
3541   emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
3542   emit_writeword(2,(int)&last_count);
3543   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3544   if(cc<0) {
3545     emit_storereg(CCREG,HOST_TEMPREG);
3546   }
3547   restore_regs(reglist);
3548   emit_jmp(stubs[n][2]); // return address
3549 #endif
3550 }
3551
3552 void printregs(int edi,int esi,int ebp,int esp,int b,int d,int c,int a)
3553 {
3554   printf("regs: %x %x %x %x %x %x %x (%x)\n",a,b,c,d,ebp,esi,edi,(&edi)[-1]);
3555 }
3556
3557 do_invstub(int n)
3558 {
3559   literal_pool(20);
3560   u_int reglist=stubs[n][3];
3561   set_jump_target(stubs[n][1],(int)out);
3562   save_regs(reglist);
3563   if(stubs[n][4]!=0) emit_mov(stubs[n][4],0);
3564   emit_call((int)&invalidate_addr);
3565   restore_regs(reglist);
3566   emit_jmp(stubs[n][2]); // return address
3567 }
3568
3569 int do_dirty_stub(int i)
3570 {
3571   assem_debug("do_dirty_stub %x\n",start+i*4);
3572   u_int addr=(int)start<(int)0xC0000000?(u_int)source:(u_int)start;
3573   #ifdef PCSX
3574   addr=(u_int)source;
3575   #endif
3576   // Careful about the code output here, verify_dirty needs to parse it.
3577   #ifndef HAVE_ARMV7
3578   emit_loadlp(addr,1);
3579   emit_loadlp((int)copy,2);
3580   emit_loadlp(slen*4,3);
3581   #else
3582   emit_movw(addr&0x0000FFFF,1);
3583   emit_movw(((u_int)copy)&0x0000FFFF,2);
3584   emit_movt(addr&0xFFFF0000,1);
3585   emit_movt(((u_int)copy)&0xFFFF0000,2);
3586   emit_movw(slen*4,3);
3587   #endif
3588   emit_movimm(start+i*4,0);
3589   emit_call((int)start<(int)0xC0000000?(int)&verify_code:(int)&verify_code_vm);
3590   int entry=(int)out;
3591   load_regs_entry(i);
3592   if(entry==(int)out) entry=instr_addr[i];
3593   emit_jmp(instr_addr[i]);
3594   return entry;
3595 }
3596
3597 void do_dirty_stub_ds()
3598 {
3599   // Careful about the code output here, verify_dirty needs to parse it.
3600   #ifndef HAVE_ARMV7
3601   emit_loadlp((int)start<(int)0xC0000000?(int)source:(int)start,1);
3602   emit_loadlp((int)copy,2);
3603   emit_loadlp(slen*4,3);
3604   #else
3605   emit_movw(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0x0000FFFF,1);
3606   emit_movw(((u_int)copy)&0x0000FFFF,2);
3607   emit_movt(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0xFFFF0000,1);
3608   emit_movt(((u_int)copy)&0xFFFF0000,2);
3609   emit_movw(slen*4,3);
3610   #endif
3611   emit_movimm(start+1,0);
3612   emit_call((int)&verify_code_ds);
3613 }
3614
3615 do_cop1stub(int n)
3616 {
3617   literal_pool(256);
3618   assem_debug("do_cop1stub %x\n",start+stubs[n][3]*4);
3619   set_jump_target(stubs[n][1],(int)out);
3620   int i=stubs[n][3];
3621 //  int rs=stubs[n][4];
3622   struct regstat *i_regs=(struct regstat *)stubs[n][5];
3623   int ds=stubs[n][6];
3624   if(!ds) {
3625     load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
3626     //if(i_regs!=&regs[i]) printf("oops: regs[i]=%x i_regs=%x",(int)&regs[i],(int)i_regs);
3627   }
3628   //else {printf("fp exception in delay slot\n");}
3629   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty);
3630   if(regs[i].regmap_entry[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
3631   emit_movimm(start+(i-ds)*4,EAX); // Get PC
3632   emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG); // CHECK: is this right?  There should probably be an extra cycle...
3633   emit_jmp(ds?(int)fp_exception_ds:(int)fp_exception);
3634 }
3635
3636 #ifndef DISABLE_TLB
3637
3638 /* TLB */
3639
3640 int do_tlb_r(int s,int ar,int map,int x,int a,int shift,int c,u_int addr)
3641 {
3642   if(c) {
3643     if((signed int)addr>=(signed int)0xC0000000) {
3644       // address_generation already loaded the const
3645       emit_readword_dualindexedx4(FP,map,map);
3646     }
3647     else
3648       return -1; // No mapping
3649   }
3650   else {
3651     assert(s!=map);
3652     emit_movimm(((int)memory_map-(int)&dynarec_local)>>2,map);
3653     emit_addsr12(map,s,map);
3654     // Schedule this while we wait on the load
3655     //if(x) emit_xorimm(s,x,ar);
3656     if(shift>=0) emit_shlimm(s,3,shift);
3657     if(~a) emit_andimm(s,a,ar);
3658     emit_readword_dualindexedx4(FP,map,map);
3659   }
3660   return map;
3661 }
3662 int do_tlb_r_branch(int map, int c, u_int addr, int *jaddr)
3663 {
3664   if(!c||(signed int)addr>=(signed int)0xC0000000) {
3665     emit_test(map,map);
3666     *jaddr=(int)out;
3667     emit_js(0);
3668   }
3669   return map;
3670 }
3671
3672 int gen_tlb_addr_r(int ar, int map) {
3673   if(map>=0) {
3674     assem_debug("add %s,%s,%s lsl #2\n",regname[ar],regname[ar],regname[map]);
3675     output_w32(0xe0800100|rd_rn_rm(ar,ar,map));
3676   }
3677 }
3678
3679 int do_tlb_w(int s,int ar,int map,int x,int c,u_int addr)
3680 {
3681   if(c) {
3682     if(addr<0x80800000||addr>=0xC0000000) {
3683       // address_generation already loaded the const
3684       emit_readword_dualindexedx4(FP,map,map);
3685     }
3686     else
3687       return -1; // No mapping
3688   }
3689   else {
3690     assert(s!=map);
3691     emit_movimm(((int)memory_map-(int)&dynarec_local)>>2,map);
3692     emit_addsr12(map,s,map);
3693     // Schedule this while we wait on the load
3694     //if(x) emit_xorimm(s,x,ar);
3695     emit_readword_dualindexedx4(FP,map,map);
3696   }
3697   return map;
3698 }
3699 int do_tlb_w_branch(int map, int c, u_int addr, int *jaddr)
3700 {
3701   if(!c||addr<0x80800000||addr>=0xC0000000) {
3702     emit_testimm(map,0x40000000);
3703     *jaddr=(int)out;
3704     emit_jne(0);
3705   }
3706 }
3707
3708 int gen_tlb_addr_w(int ar, int map) {
3709   if(map>=0) {
3710     assem_debug("add %s,%s,%s lsl #2\n",regname[ar],regname[ar],regname[map]);
3711     output_w32(0xe0800100|rd_rn_rm(ar,ar,map));
3712   }
3713 }
3714
3715 // Generate the address of the memory_map entry, relative to dynarec_local
3716 generate_map_const(u_int addr,int reg) {
3717   //printf("generate_map_const(%x,%s)\n",addr,regname[reg]);
3718   emit_movimm((addr>>12)+(((u_int)memory_map-(u_int)&dynarec_local)>>2),reg);
3719 }
3720
3721 #else
3722
3723 static int do_tlb_r() { return 0; }
3724 static int do_tlb_r_branch() { return 0; }
3725 static int gen_tlb_addr_r() { return 0; }
3726 static int do_tlb_w() { return 0; }
3727 static int do_tlb_w_branch() { return 0; }
3728 static int gen_tlb_addr_w() { return 0; }
3729
3730 #endif // DISABLE_TLB
3731
3732 /* Special assem */
3733
3734 void shift_assemble_arm(int i,struct regstat *i_regs)
3735 {
3736   if(rt1[i]) {
3737     if(opcode2[i]<=0x07) // SLLV/SRLV/SRAV
3738     {
3739       signed char s,t,shift;
3740       t=get_reg(i_regs->regmap,rt1[i]);
3741       s=get_reg(i_regs->regmap,rs1[i]);
3742       shift=get_reg(i_regs->regmap,rs2[i]);
3743       if(t>=0){
3744         if(rs1[i]==0)
3745         {
3746           emit_zeroreg(t);
3747         }
3748         else if(rs2[i]==0)
3749         {
3750           assert(s>=0);
3751           if(s!=t) emit_mov(s,t);
3752         }
3753         else
3754         {
3755           emit_andimm(shift,31,HOST_TEMPREG);
3756           if(opcode2[i]==4) // SLLV
3757           {
3758             emit_shl(s,HOST_TEMPREG,t);
3759           }
3760           if(opcode2[i]==6) // SRLV
3761           {
3762             emit_shr(s,HOST_TEMPREG,t);
3763           }
3764           if(opcode2[i]==7) // SRAV
3765           {
3766             emit_sar(s,HOST_TEMPREG,t);
3767           }
3768         }
3769       }
3770     } else { // DSLLV/DSRLV/DSRAV
3771       signed char sh,sl,th,tl,shift;
3772       th=get_reg(i_regs->regmap,rt1[i]|64);
3773       tl=get_reg(i_regs->regmap,rt1[i]);
3774       sh=get_reg(i_regs->regmap,rs1[i]|64);
3775       sl=get_reg(i_regs->regmap,rs1[i]);
3776       shift=get_reg(i_regs->regmap,rs2[i]);
3777       if(tl>=0){
3778         if(rs1[i]==0)
3779         {
3780           emit_zeroreg(tl);
3781           if(th>=0) emit_zeroreg(th);
3782         }
3783         else if(rs2[i]==0)
3784         {
3785           assert(sl>=0);
3786           if(sl!=tl) emit_mov(sl,tl);
3787           if(th>=0&&sh!=th) emit_mov(sh,th);
3788         }
3789         else
3790         {
3791           // FIXME: What if shift==tl ?
3792           assert(shift!=tl);
3793           int temp=get_reg(i_regs->regmap,-1);
3794           int real_th=th;
3795           if(th<0&&opcode2[i]!=0x14) {th=temp;} // DSLLV doesn't need a temporary register
3796           assert(sl>=0);
3797           assert(sh>=0);
3798           emit_andimm(shift,31,HOST_TEMPREG);
3799           if(opcode2[i]==0x14) // DSLLV
3800           {
3801             if(th>=0) emit_shl(sh,HOST_TEMPREG,th);
3802             emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
3803             emit_orrshr(sl,HOST_TEMPREG,th);
3804             emit_andimm(shift,31,HOST_TEMPREG);
3805             emit_testimm(shift,32);
3806             emit_shl(sl,HOST_TEMPREG,tl);
3807             if(th>=0) emit_cmovne_reg(tl,th);
3808             emit_cmovne_imm(0,tl);
3809           }
3810           if(opcode2[i]==0x16) // DSRLV
3811           {
3812             assert(th>=0);
3813             emit_shr(sl,HOST_TEMPREG,tl);
3814             emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
3815             emit_orrshl(sh,HOST_TEMPREG,tl);
3816             emit_andimm(shift,31,HOST_TEMPREG);
3817             emit_testimm(shift,32);
3818             emit_shr(sh,HOST_TEMPREG,th);
3819             emit_cmovne_reg(th,tl);
3820             if(real_th>=0) emit_cmovne_imm(0,th);
3821           }
3822           if(opcode2[i]==0x17) // DSRAV
3823           {
3824             assert(th>=0);
3825             emit_shr(sl,HOST_TEMPREG,tl);
3826             emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
3827             if(real_th>=0) {
3828               assert(temp>=0);
3829               emit_sarimm(th,31,temp);
3830             }
3831             emit_orrshl(sh,HOST_TEMPREG,tl);
3832             emit_andimm(shift,31,HOST_TEMPREG);
3833             emit_testimm(shift,32);
3834             emit_sar(sh,HOST_TEMPREG,th);
3835             emit_cmovne_reg(th,tl);
3836             if(real_th>=0) emit_cmovne_reg(temp,th);
3837           }
3838         }
3839       }
3840     }
3841   }
3842 }
3843
3844 #ifdef PCSX
3845 static void speculate_mov(int rs,int rt)
3846 {
3847   if(rt!=0) {
3848     smrv_strong_next|=1<<rt;
3849     smrv[rt]=smrv[rs];
3850   }
3851 }
3852
3853 static void speculate_mov_weak(int rs,int rt)
3854 {
3855   if(rt!=0) {
3856     smrv_weak_next|=1<<rt;
3857     smrv[rt]=smrv[rs];
3858   }
3859 }
3860
3861 static void speculate_register_values(int i)
3862 {
3863   if(i==0) {
3864     memcpy(smrv,psxRegs.GPR.r,sizeof(smrv));
3865     // gp,sp are likely to stay the same throughout the block
3866     smrv_strong_next=(1<<28)|(1<<29)|(1<<30);
3867     smrv_weak_next=~smrv_strong_next;
3868     //printf(" llr %08x\n", smrv[4]);
3869   }
3870   smrv_strong=smrv_strong_next;
3871   smrv_weak=smrv_weak_next;
3872   switch(itype[i]) {
3873     case ALU:
3874       if     ((smrv_strong>>rs1[i])&1) speculate_mov(rs1[i],rt1[i]);
3875       else if((smrv_strong>>rs2[i])&1) speculate_mov(rs2[i],rt1[i]);
3876       else if((smrv_weak>>rs1[i])&1) speculate_mov_weak(rs1[i],rt1[i]);
3877       else if((smrv_weak>>rs2[i])&1) speculate_mov_weak(rs2[i],rt1[i]);
3878       else {
3879         smrv_strong_next&=~(1<<rt1[i]);
3880         smrv_weak_next&=~(1<<rt1[i]);
3881       }
3882       break;
3883     case SHIFTIMM:
3884       smrv_strong_next&=~(1<<rt1[i]);
3885       smrv_weak_next&=~(1<<rt1[i]);
3886       // fallthrough
3887     case IMM16:
3888       if(rt1[i]&&is_const(&regs[i],rt1[i])) {
3889         int value,hr=get_reg(regs[i].regmap,rt1[i]);
3890         if(hr>=0) {
3891           if(get_final_value(hr,i,&value))
3892                smrv[rt1[i]]=value;
3893           else smrv[rt1[i]]=constmap[i][hr];
3894           smrv_strong_next|=1<<rt1[i];
3895         }
3896       }
3897       else {
3898         if     ((smrv_strong>>rs1[i])&1) speculate_mov(rs1[i],rt1[i]);
3899         else if((smrv_weak>>rs1[i])&1) speculate_mov_weak(rs1[i],rt1[i]);
3900       }
3901       break;
3902     case LOAD:
3903       if(start<0x2000&&(rt1[i]==26||(smrv[rt1[i]]>>24)==0xa0)) {
3904         // special case for BIOS
3905         smrv[rt1[i]]=0xa0000000;
3906         smrv_strong_next|=1<<rt1[i];
3907         break;
3908       }
3909       // fallthrough
3910     case SHIFT:
3911     case LOADLR:
3912     case MOV:
3913       smrv_strong_next&=~(1<<rt1[i]);
3914       smrv_weak_next&=~(1<<rt1[i]);
3915       break;
3916     case COP0:
3917     case COP2:
3918       if(opcode2[i]==0||opcode2[i]==2) { // MFC/CFC
3919         smrv_strong_next&=~(1<<rt1[i]);
3920         smrv_weak_next&=~(1<<rt1[i]);
3921       }
3922       break;
3923     case C2LS:
3924       if (opcode[i]==0x32) { // LWC2
3925         smrv_strong_next&=~(1<<rt1[i]);
3926         smrv_weak_next&=~(1<<rt1[i]);
3927       }
3928       break;
3929   }
3930 #if 0
3931   int r=4;
3932   printf("x %08x %08x %d %d c %08x %08x\n",smrv[r],start+i*4,
3933     ((smrv_strong>>r)&1),(smrv_weak>>r)&1,regs[i].isconst,regs[i].wasconst);
3934 #endif
3935 }
3936
3937 enum {
3938   MTYPE_8000 = 0,
3939   MTYPE_8020,
3940   MTYPE_0000,
3941   MTYPE_A000,
3942   MTYPE_1F80,
3943 };
3944
3945 static int get_ptr_mem_type(u_int a)
3946 {
3947   if(a < 0x00200000) {
3948     if(a<0x1000&&((start>>20)==0xbfc||(start>>24)==0xa0))
3949       // return wrong, must use memhandler for BIOS self-test to pass
3950       // 007 does similar stuff from a00 mirror, weird stuff
3951       return MTYPE_8000;
3952     return MTYPE_0000;
3953   }
3954   if(0x1f800000 <= a && a < 0x1f801000)
3955     return MTYPE_1F80;
3956   if(0x80200000 <= a && a < 0x80800000)
3957     return MTYPE_8020;
3958   if(0xa0000000 <= a && a < 0xa0200000)
3959     return MTYPE_A000;
3960   return MTYPE_8000;
3961 }
3962 #endif
3963
3964 static int emit_fastpath_cmp_jump(int i,int addr,int *addr_reg_override)
3965 {
3966   int jaddr,type=0;
3967
3968 #ifdef PCSX
3969   int mr=rs1[i];
3970   if(((smrv_strong|smrv_weak)>>mr)&1) {
3971     type=get_ptr_mem_type(smrv[mr]);
3972     //printf("set %08x @%08x r%d %d\n", smrv[mr], start+i*4, mr, type);
3973   }
3974   else {
3975     // use the mirror we are running on
3976     type=get_ptr_mem_type(start);
3977     //printf("set nospec   @%08x r%d %d\n", start+i*4, mr, type);
3978   }
3979
3980   if(type==MTYPE_8020) { // RAM 80200000+ mirror
3981     emit_andimm(addr,~0x00e00000,HOST_TEMPREG);
3982     addr=*addr_reg_override=HOST_TEMPREG;
3983     type=0;
3984   }
3985   else if(type==MTYPE_0000) { // RAM 0 mirror
3986     emit_orimm(addr,0x80000000,HOST_TEMPREG);
3987     addr=*addr_reg_override=HOST_TEMPREG;
3988     type=0;
3989   }
3990   else if(type==MTYPE_A000) { // RAM A mirror
3991     emit_andimm(addr,~0x20000000,HOST_TEMPREG);
3992     addr=*addr_reg_override=HOST_TEMPREG;
3993     type=0;
3994   }
3995   else if(type==MTYPE_1F80) { // scratchpad
3996     emit_addimm(addr,-0x1f800000,HOST_TEMPREG);
3997     emit_cmpimm(HOST_TEMPREG,0x1000);
3998     jaddr=(int)out;
3999     emit_jc(0);
4000   }
4001 #endif
4002
4003   if(type==0)
4004   {
4005     emit_cmpimm(addr,RAM_SIZE);
4006     jaddr=(int)out;
4007     #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
4008     // Hint to branch predictor that the branch is unlikely to be taken
4009     if(rs1[i]>=28)
4010       emit_jno_unlikely(0);
4011     else
4012     #endif
4013       emit_jno(0);
4014     if(ram_offset!=0) {
4015       emit_addimm(addr,ram_offset,HOST_TEMPREG);
4016       addr=*addr_reg_override=HOST_TEMPREG;
4017     }
4018   }
4019
4020   return jaddr;
4021 }
4022
4023 #define shift_assemble shift_assemble_arm
4024
4025 void loadlr_assemble_arm(int i,struct regstat *i_regs)
4026 {
4027   int s,th,tl,temp,temp2,addr,map=-1;
4028   int offset;
4029   int jaddr=0;
4030   int memtarget=0,c=0;
4031   int fastload_reg_override=0;
4032   u_int hr,reglist=0;
4033   th=get_reg(i_regs->regmap,rt1[i]|64);
4034   tl=get_reg(i_regs->regmap,rt1[i]);
4035   s=get_reg(i_regs->regmap,rs1[i]);
4036   temp=get_reg(i_regs->regmap,-1);
4037   temp2=get_reg(i_regs->regmap,FTEMP);
4038   addr=get_reg(i_regs->regmap,AGEN1+(i&1));
4039   assert(addr<0);
4040   offset=imm[i];
4041   for(hr=0;hr<HOST_REGS;hr++) {
4042     if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
4043   }
4044   reglist|=1<<temp;
4045   if(offset||s<0||c) addr=temp2;
4046   else addr=s;
4047   if(s>=0) {
4048     c=(i_regs->wasconst>>s)&1;
4049     if(c) {
4050       memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE;
4051       if(using_tlb&&((signed int)(constmap[i][s]+offset))>=(signed int)0xC0000000) memtarget=1;
4052     }
4053   }
4054   if(!using_tlb) {
4055     if(!c) {
4056       #ifdef RAM_OFFSET
4057       map=get_reg(i_regs->regmap,ROREG);
4058       if(map<0) emit_loadreg(ROREG,map=HOST_TEMPREG);
4059       #endif
4060       emit_shlimm(addr,3,temp);
4061       if (opcode[i]==0x22||opcode[i]==0x26) {
4062         emit_andimm(addr,0xFFFFFFFC,temp2); // LWL/LWR
4063       }else{
4064         emit_andimm(addr,0xFFFFFFF8,temp2); // LDL/LDR
4065       }
4066       jaddr=emit_fastpath_cmp_jump(i,temp2,&fastload_reg_override);
4067     }
4068     else {
4069       if(ram_offset&&memtarget) {
4070         emit_addimm(temp2,ram_offset,HOST_TEMPREG);
4071         fastload_reg_override=HOST_TEMPREG;
4072       }
4073       if (opcode[i]==0x22||opcode[i]==0x26) {
4074         emit_movimm(((constmap[i][s]+offset)<<3)&24,temp); // LWL/LWR
4075       }else{
4076         emit_movimm(((constmap[i][s]+offset)<<3)&56,temp); // LDL/LDR
4077       }
4078     }
4079   }else{ // using tlb
4080     int a;
4081     if(c) {
4082       a=-1;
4083     }else if (opcode[i]==0x22||opcode[i]==0x26) {
4084       a=0xFFFFFFFC; // LWL/LWR
4085     }else{
4086       a=0xFFFFFFF8; // LDL/LDR
4087     }
4088     map=get_reg(i_regs->regmap,TLREG);
4089     assert(map>=0);
4090     reglist&=~(1<<map);
4091     map=do_tlb_r(addr,temp2,map,0,a,c?-1:temp,c,constmap[i][s]+offset);
4092     if(c) {
4093       if (opcode[i]==0x22||opcode[i]==0x26) {
4094         emit_movimm(((constmap[i][s]+offset)<<3)&24,temp); // LWL/LWR
4095       }else{
4096         emit_movimm(((constmap[i][s]+offset)<<3)&56,temp); // LDL/LDR
4097       }
4098     }
4099     do_tlb_r_branch(map,c,constmap[i][s]+offset,&jaddr);
4100   }
4101   if (opcode[i]==0x22||opcode[i]==0x26) { // LWL/LWR
4102     if(!c||memtarget) {
4103       int a=temp2;
4104       if(fastload_reg_override) a=fastload_reg_override;
4105       //emit_readword_indexed((int)rdram-0x80000000,temp2,temp2);
4106       emit_readword_indexed_tlb(0,a,map,temp2);
4107       if(jaddr) add_stub(LOADW_STUB,jaddr,(int)out,i,temp2,(int)i_regs,ccadj[i],reglist);
4108     }
4109     else
4110       inline_readstub(LOADW_STUB,i,(constmap[i][s]+offset)&0xFFFFFFFC,i_regs->regmap,FTEMP,ccadj[i],reglist);
4111     if(rt1[i]) {
4112       assert(tl>=0);
4113       emit_andimm(temp,24,temp);
4114 #ifdef BIG_ENDIAN_MIPS
4115       if (opcode[i]==0x26) // LWR
4116 #else
4117       if (opcode[i]==0x22) // LWL
4118 #endif
4119         emit_xorimm(temp,24,temp);
4120       emit_movimm(-1,HOST_TEMPREG);
4121       if (opcode[i]==0x26) {
4122         emit_shr(temp2,temp,temp2);
4123         emit_bic_lsr(tl,HOST_TEMPREG,temp,tl);
4124       }else{
4125         emit_shl(temp2,temp,temp2);
4126         emit_bic_lsl(tl,HOST_TEMPREG,temp,tl);
4127       }
4128       emit_or(temp2,tl,tl);
4129     }
4130     //emit_storereg(rt1[i],tl); // DEBUG
4131   }
4132   if (opcode[i]==0x1A||opcode[i]==0x1B) { // LDL/LDR
4133     // FIXME: little endian, fastload_reg_override
4134     int temp2h=get_reg(i_regs->regmap,FTEMP|64);
4135     if(!c||memtarget) {
4136       //if(th>=0) emit_readword_indexed((int)rdram-0x80000000,temp2,temp2h);
4137       //emit_readword_indexed((int)rdram-0x7FFFFFFC,temp2,temp2);
4138       emit_readdword_indexed_tlb(0,temp2,map,temp2h,temp2);
4139       if(jaddr) add_stub(LOADD_STUB,jaddr,(int)out,i,temp2,(int)i_regs,ccadj[i],reglist);
4140     }
4141     else
4142       inline_readstub(LOADD_STUB,i,(constmap[i][s]+offset)&0xFFFFFFF8,i_regs->regmap,FTEMP,ccadj[i],reglist);
4143     if(rt1[i]) {
4144       assert(th>=0);
4145       assert(tl>=0);
4146       emit_testimm(temp,32);
4147       emit_andimm(temp,24,temp);
4148       if (opcode[i]==0x1A) { // LDL
4149         emit_rsbimm(temp,32,HOST_TEMPREG);
4150         emit_shl(temp2h,temp,temp2h);
4151         emit_orrshr(temp2,HOST_TEMPREG,temp2h);
4152         emit_movimm(-1,HOST_TEMPREG);
4153         emit_shl(temp2,temp,temp2);
4154         emit_cmove_reg(temp2h,th);
4155         emit_biceq_lsl(tl,HOST_TEMPREG,temp,tl);
4156         emit_bicne_lsl(th,HOST_TEMPREG,temp,th);
4157         emit_orreq(temp2,tl,tl);
4158         emit_orrne(temp2,th,th);
4159       }
4160       if (opcode[i]==0x1B) { // LDR
4161         emit_xorimm(temp,24,temp);
4162         emit_rsbimm(temp,32,HOST_TEMPREG);
4163         emit_shr(temp2,temp,temp2);
4164         emit_orrshl(temp2h,HOST_TEMPREG,temp2);
4165         emit_movimm(-1,HOST_TEMPREG);
4166         emit_shr(temp2h,temp,temp2h);
4167         emit_cmovne_reg(temp2,tl);
4168         emit_bicne_lsr(th,HOST_TEMPREG,temp,th);
4169         emit_biceq_lsr(tl,HOST_TEMPREG,temp,tl);
4170         emit_orrne(temp2h,th,th);
4171         emit_orreq(temp2h,tl,tl);
4172       }
4173     }
4174   }
4175 }
4176 #define loadlr_assemble loadlr_assemble_arm
4177
4178 void cop0_assemble(int i,struct regstat *i_regs)
4179 {
4180   if(opcode2[i]==0) // MFC0
4181   {