8e0c634c2491fb725b7c588983c656a64cdf5329
[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 #ifdef VITA
34 char* translation_cache = 0;
35 #elif !BASE_ADDR_FIXED
36 char translation_cache[1 << TARGET_SIZE_2] __attribute__((aligned(4096)));
37 #endif
38
39 #ifndef __MACH__
40 #define CALLER_SAVE_REGS 0x100f
41 #else
42 #define CALLER_SAVE_REGS 0x120f
43 #endif
44
45 extern int cycle_count;
46 extern int last_count;
47 extern int pcaddr;
48 extern int pending_exception;
49 extern int branch_target;
50 extern uint64_t readmem_dword;
51 #ifdef MUPEN64
52 extern precomp_instr fake_pc;
53 #endif
54 extern void *dynarec_local;
55 extern u_int memory_map[1048576];
56 extern u_int mini_ht[32][2];
57 extern u_int rounding_modes[4];
58
59 void indirect_jump_indexed();
60 void indirect_jump();
61 void do_interrupt();
62 void jump_vaddr_r0();
63 void jump_vaddr_r1();
64 void jump_vaddr_r2();
65 void jump_vaddr_r3();
66 void jump_vaddr_r4();
67 void jump_vaddr_r5();
68 void jump_vaddr_r6();
69 void jump_vaddr_r7();
70 void jump_vaddr_r8();
71 void jump_vaddr_r9();
72 void jump_vaddr_r10();
73 void jump_vaddr_r12();
74
75 const u_int jump_vaddr_reg[16] = {
76   (int)jump_vaddr_r0,
77   (int)jump_vaddr_r1,
78   (int)jump_vaddr_r2,
79   (int)jump_vaddr_r3,
80   (int)jump_vaddr_r4,
81   (int)jump_vaddr_r5,
82   (int)jump_vaddr_r6,
83   (int)jump_vaddr_r7,
84   (int)jump_vaddr_r8,
85   (int)jump_vaddr_r9,
86   (int)jump_vaddr_r10,
87   0,
88   (int)jump_vaddr_r12,
89   0,
90   0,
91   0};
92
93 void invalidate_addr_r0();
94 void invalidate_addr_r1();
95 void invalidate_addr_r2();
96 void invalidate_addr_r3();
97 void invalidate_addr_r4();
98 void invalidate_addr_r5();
99 void invalidate_addr_r6();
100 void invalidate_addr_r7();
101 void invalidate_addr_r8();
102 void invalidate_addr_r9();
103 void invalidate_addr_r10();
104 void invalidate_addr_r12();
105
106 const u_int invalidate_addr_reg[16] = {
107   (int)invalidate_addr_r0,
108   (int)invalidate_addr_r1,
109   (int)invalidate_addr_r2,
110   (int)invalidate_addr_r3,
111   (int)invalidate_addr_r4,
112   (int)invalidate_addr_r5,
113   (int)invalidate_addr_r6,
114   (int)invalidate_addr_r7,
115   (int)invalidate_addr_r8,
116   (int)invalidate_addr_r9,
117   (int)invalidate_addr_r10,
118   0,
119   (int)invalidate_addr_r12,
120   0,
121   0,
122   0};
123
124 #include "fpu.h"
125
126 unsigned int needs_clear_cache[1<<(TARGET_SIZE_2-17)];
127
128 /* Linker */
129
130 void set_jump_target(int addr,u_int target)
131 {
132   u_char *ptr=(u_char *)addr;
133   u_int *ptr2=(u_int *)ptr;
134   if(ptr[3]==0xe2) {
135     assert((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     //printf("target=%x addr=%x insn=%x\n",target,addr,*ptr2);
140   }
141   else if(ptr[3]==0x72) {
142     // generated by emit_jno_unlikely
143     if((target-(u_int)ptr2-8)<1024) {
144       assert((addr&3)==0);
145       assert((target&3)==0);
146       *ptr2=(*ptr2&0xFFFFF000)|((target-(u_int)ptr2-8)>>2)|0xF00;
147     }
148     else if((target-(u_int)ptr2-8)<4096&&!((target-(u_int)ptr2-8)&15)) {
149       assert((addr&3)==0);
150       assert((target&3)==0);
151       *ptr2=(*ptr2&0xFFFFF000)|((target-(u_int)ptr2-8)>>4)|0xE00;
152     }
153     else *ptr2=(0x7A000000)|(((target-(u_int)ptr2-8)<<6)>>8);
154   }
155   else {
156     assert((ptr[3]&0x0e)==0xa);
157     *ptr2=(*ptr2&0xFF000000)|(((target-(u_int)ptr2-8)<<6)>>8);
158   }
159 }
160
161 // This optionally copies the instruction from the target of the branch into
162 // the space before the branch.  Works, but the difference in speed is
163 // usually insignificant.
164 void set_jump_target_fillslot(int addr,u_int target,int copy)
165 {
166   u_char *ptr=(u_char *)addr;
167   u_int *ptr2=(u_int *)ptr;
168   assert(!copy||ptr2[-1]==0xe28dd000);
169   if(ptr[3]==0xe2) {
170     assert(!copy);
171     assert((target-(u_int)ptr2-8)<4096);
172     *ptr2=(*ptr2&0xFFFFF000)|(target-(u_int)ptr2-8);
173   }
174   else {
175     assert((ptr[3]&0x0e)==0xa);
176     u_int target_insn=*(u_int *)target;
177     if((target_insn&0x0e100000)==0) { // ALU, no immediate, no flags
178       copy=0;
179     }
180     if((target_insn&0x0c100000)==0x04100000) { // Load
181       copy=0;
182     }
183     if(target_insn&0x08000000) {
184       copy=0;
185     }
186     if(copy) {
187       ptr2[-1]=target_insn;
188       target+=4;
189     }
190     *ptr2=(*ptr2&0xFF000000)|(((target-(u_int)ptr2-8)<<6)>>8);
191   }
192 }
193
194 /* Literal pool */
195 add_literal(int addr,int val)
196 {
197   assert(literalcount<sizeof(literals)/sizeof(literals[0]));
198   literals[literalcount][0]=addr;
199   literals[literalcount][1]=val;
200   literalcount++; 
201
202
203 void *kill_pointer(void *stub)
204 {
205   int *ptr=(int *)(stub+4);
206   assert((*ptr&0x0ff00000)==0x05900000);
207   u_int offset=*ptr&0xfff;
208   int **l_ptr=(void *)ptr+offset+8;
209   int *i_ptr=*l_ptr;
210   set_jump_target((int)i_ptr,(int)stub);
211   return i_ptr;
212 }
213
214 // find where external branch is liked to using addr of it's stub:
215 // get address that insn one after stub loads (dyna_linker arg1),
216 // treat it as a pointer to branch insn,
217 // return addr where that branch jumps to
218 int get_pointer(void *stub)
219 {
220   //printf("get_pointer(%x)\n",(int)stub);
221   int *ptr=(int *)(stub+4);
222   assert((*ptr&0x0fff0000)==0x059f0000);
223   u_int offset=*ptr&0xfff;
224   int **l_ptr=(void *)ptr+offset+8;
225   int *i_ptr=*l_ptr;
226   assert((*i_ptr&0x0f000000)==0x0a000000);
227   return (int)i_ptr+((*i_ptr<<8)>>6)+8;
228 }
229
230 // Find the "clean" entry point from a "dirty" entry point
231 // by skipping past the call to verify_code
232 u_int get_clean_addr(int addr)
233 {
234   int *ptr=(int *)addr;
235   #ifndef HAVE_ARMV7
236   ptr+=4;
237   #else
238   ptr+=6;
239   #endif
240   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
241   assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
242   ptr++;
243   if((*ptr&0xFF000000)==0xea000000) {
244     return (int)ptr+((*ptr<<8)>>6)+8; // follow jump
245   }
246   return (u_int)ptr;
247 }
248
249 int verify_dirty(int addr)
250 {
251   u_int *ptr=(u_int *)addr;
252   #ifndef HAVE_ARMV7
253   // get from literal pool
254   assert((*ptr&0xFFFF0000)==0xe59f0000);
255   u_int offset=*ptr&0xfff;
256   u_int *l_ptr=(void *)ptr+offset+8;
257   u_int source=l_ptr[0];
258   u_int copy=l_ptr[1];
259   u_int len=l_ptr[2];
260   ptr+=4;
261   #else
262   // ARMv7 movw/movt
263   assert((*ptr&0xFFF00000)==0xe3000000);
264   u_int source=(ptr[0]&0xFFF)+((ptr[0]>>4)&0xF000)+((ptr[2]<<16)&0xFFF0000)+((ptr[2]<<12)&0xF0000000);
265   u_int copy=(ptr[1]&0xFFF)+((ptr[1]>>4)&0xF000)+((ptr[3]<<16)&0xFFF0000)+((ptr[3]<<12)&0xF0000000);
266   u_int len=(ptr[4]&0xFFF)+((ptr[4]>>4)&0xF000);
267   ptr+=6;
268   #endif
269   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
270   assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
271 #ifndef DISABLE_TLB
272   u_int verifier=(int)ptr+((signed int)(*ptr<<8)>>6)+8; // get target of bl
273   if(verifier==(u_int)verify_code_vm||verifier==(u_int)verify_code_ds) {
274     unsigned int page=source>>12;
275     unsigned int map_value=memory_map[page];
276     if(map_value>=0x80000000) return 0;
277     while(page<((source+len-1)>>12)) {
278       if((memory_map[++page]<<2)!=(map_value<<2)) return 0;
279     }
280     source = source+(map_value<<2);
281   }
282 #endif
283   //printf("verify_dirty: %x %x %x\n",source,copy,len);
284   return !memcmp((void *)source,(void *)copy,len);
285 }
286
287 // This doesn't necessarily find all clean entry points, just
288 // guarantees that it's not dirty
289 int isclean(int addr)
290 {
291   #ifndef HAVE_ARMV7
292   int *ptr=((u_int *)addr)+4;
293   #else
294   int *ptr=((u_int *)addr)+6;
295   #endif
296   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
297   if((*ptr&0xFF000000)!=0xeb000000) return 1; // bl instruction
298   if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code) return 0;
299   if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code_vm) return 0;
300   if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code_ds) return 0;
301   return 1;
302 }
303
304 // get source that block at addr was compiled from (host pointers)
305 void get_bounds(int addr,u_int *start,u_int *end)
306 {
307   u_int *ptr=(u_int *)addr;
308   #ifndef HAVE_ARMV7
309   // get from literal pool
310   assert((*ptr&0xFFFF0000)==0xe59f0000);
311   u_int offset=*ptr&0xfff;
312   u_int *l_ptr=(void *)ptr+offset+8;
313   u_int source=l_ptr[0];
314   //u_int copy=l_ptr[1];
315   u_int len=l_ptr[2];
316   ptr+=4;
317   #else
318   // ARMv7 movw/movt
319   assert((*ptr&0xFFF00000)==0xe3000000);
320   u_int source=(ptr[0]&0xFFF)+((ptr[0]>>4)&0xF000)+((ptr[2]<<16)&0xFFF0000)+((ptr[2]<<12)&0xF0000000);
321   //u_int copy=(ptr[1]&0xFFF)+((ptr[1]>>4)&0xF000)+((ptr[3]<<16)&0xFFF0000)+((ptr[3]<<12)&0xF0000000);
322   u_int len=(ptr[4]&0xFFF)+((ptr[4]>>4)&0xF000);
323   ptr+=6;
324   #endif
325   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
326   assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
327 #ifndef DISABLE_TLB
328   u_int verifier=(int)ptr+((signed int)(*ptr<<8)>>6)+8; // get target of bl
329   if(verifier==(u_int)verify_code_vm||verifier==(u_int)verify_code_ds) {
330     if(memory_map[source>>12]>=0x80000000) source = 0;
331     else source = source+(memory_map[source>>12]<<2);
332   }
333 #endif
334   *start=source;
335   *end=source+len;
336 }
337
338 /* Register allocation */
339
340 // Note: registers are allocated clean (unmodified state)
341 // if you intend to modify the register, you must call dirty_reg().
342 void alloc_reg(struct regstat *cur,int i,signed char reg)
343 {
344   int r,hr;
345   int preferred_reg = (reg&7);
346   if(reg==CCREG) preferred_reg=HOST_CCREG;
347   if(reg==PTEMP||reg==FTEMP) preferred_reg=12;
348   
349   // Don't allocate unused registers
350   if((cur->u>>reg)&1) return;
351   
352   // see if it's already allocated
353   for(hr=0;hr<HOST_REGS;hr++)
354   {
355     if(cur->regmap[hr]==reg) return;
356   }
357   
358   // Keep the same mapping if the register was already allocated in a loop
359   preferred_reg = loop_reg(i,reg,preferred_reg);
360   
361   // Try to allocate the preferred register
362   if(cur->regmap[preferred_reg]==-1) {
363     cur->regmap[preferred_reg]=reg;
364     cur->dirty&=~(1<<preferred_reg);
365     cur->isconst&=~(1<<preferred_reg);
366     return;
367   }
368   r=cur->regmap[preferred_reg];
369   if(r<64&&((cur->u>>r)&1)) {
370     cur->regmap[preferred_reg]=reg;
371     cur->dirty&=~(1<<preferred_reg);
372     cur->isconst&=~(1<<preferred_reg);
373     return;
374   }
375   if(r>=64&&((cur->uu>>(r&63))&1)) {
376     cur->regmap[preferred_reg]=reg;
377     cur->dirty&=~(1<<preferred_reg);
378     cur->isconst&=~(1<<preferred_reg);
379     return;
380   }
381   
382   // Clear any unneeded registers
383   // We try to keep the mapping consistent, if possible, because it
384   // makes branches easier (especially loops).  So we try to allocate
385   // first (see above) before removing old mappings.  If this is not
386   // possible then go ahead and clear out the registers that are no
387   // longer needed.
388   for(hr=0;hr<HOST_REGS;hr++)
389   {
390     r=cur->regmap[hr];
391     if(r>=0) {
392       if(r<64) {
393         if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
394       }
395       else
396       {
397         if((cur->uu>>(r&63))&1) {cur->regmap[hr]=-1;break;}
398       }
399     }
400   }
401   // Try to allocate any available register, but prefer
402   // registers that have not been used recently.
403   if(i>0) {
404     for(hr=0;hr<HOST_REGS;hr++) {
405       if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
406         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]) {
407           cur->regmap[hr]=reg;
408           cur->dirty&=~(1<<hr);
409           cur->isconst&=~(1<<hr);
410           return;
411         }
412       }
413     }
414   }
415   // Try to allocate any available register
416   for(hr=0;hr<HOST_REGS;hr++) {
417     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
418       cur->regmap[hr]=reg;
419       cur->dirty&=~(1<<hr);
420       cur->isconst&=~(1<<hr);
421       return;
422     }
423   }
424   
425   // Ok, now we have to evict someone
426   // Pick a register we hopefully won't need soon
427   u_char hsn[MAXREG+1];
428   memset(hsn,10,sizeof(hsn));
429   int j;
430   lsn(hsn,i,&preferred_reg);
431   //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]);
432   //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]);
433   if(i>0) {
434     // Don't evict the cycle count at entry points, otherwise the entry
435     // stub will have to write it.
436     if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
437     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;
438     for(j=10;j>=3;j--)
439     {
440       // Alloc preferred register if available
441       if(hsn[r=cur->regmap[preferred_reg]&63]==j) {
442         for(hr=0;hr<HOST_REGS;hr++) {
443           // Evict both parts of a 64-bit register
444           if((cur->regmap[hr]&63)==r) {
445             cur->regmap[hr]=-1;
446             cur->dirty&=~(1<<hr);
447             cur->isconst&=~(1<<hr);
448           }
449         }
450         cur->regmap[preferred_reg]=reg;
451         return;
452       }
453       for(r=1;r<=MAXREG;r++)
454       {
455         if(hsn[r]==j&&r!=rs1[i-1]&&r!=rs2[i-1]&&r!=rt1[i-1]&&r!=rt2[i-1]) {
456           for(hr=0;hr<HOST_REGS;hr++) {
457             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
458               if(cur->regmap[hr]==r+64) {
459                 cur->regmap[hr]=reg;
460                 cur->dirty&=~(1<<hr);
461                 cur->isconst&=~(1<<hr);
462                 return;
463               }
464             }
465           }
466           for(hr=0;hr<HOST_REGS;hr++) {
467             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
468               if(cur->regmap[hr]==r) {
469                 cur->regmap[hr]=reg;
470                 cur->dirty&=~(1<<hr);
471                 cur->isconst&=~(1<<hr);
472                 return;
473               }
474             }
475           }
476         }
477       }
478     }
479   }
480   for(j=10;j>=0;j--)
481   {
482     for(r=1;r<=MAXREG;r++)
483     {
484       if(hsn[r]==j) {
485         for(hr=0;hr<HOST_REGS;hr++) {
486           if(cur->regmap[hr]==r+64) {
487             cur->regmap[hr]=reg;
488             cur->dirty&=~(1<<hr);
489             cur->isconst&=~(1<<hr);
490             return;
491           }
492         }
493         for(hr=0;hr<HOST_REGS;hr++) {
494           if(cur->regmap[hr]==r) {
495             cur->regmap[hr]=reg;
496             cur->dirty&=~(1<<hr);
497             cur->isconst&=~(1<<hr);
498             return;
499           }
500         }
501       }
502     }
503   }
504   SysPrintf("This shouldn't happen (alloc_reg)");exit(1);
505 }
506
507 void alloc_reg64(struct regstat *cur,int i,signed char reg)
508 {
509   int preferred_reg = 8+(reg&1);
510   int r,hr;
511   
512   // allocate the lower 32 bits
513   alloc_reg(cur,i,reg);
514   
515   // Don't allocate unused registers
516   if((cur->uu>>reg)&1) return;
517   
518   // see if the upper half is already allocated
519   for(hr=0;hr<HOST_REGS;hr++)
520   {
521     if(cur->regmap[hr]==reg+64) return;
522   }
523   
524   // Keep the same mapping if the register was already allocated in a loop
525   preferred_reg = loop_reg(i,reg,preferred_reg);
526   
527   // Try to allocate the preferred register
528   if(cur->regmap[preferred_reg]==-1) {
529     cur->regmap[preferred_reg]=reg|64;
530     cur->dirty&=~(1<<preferred_reg);
531     cur->isconst&=~(1<<preferred_reg);
532     return;
533   }
534   r=cur->regmap[preferred_reg];
535   if(r<64&&((cur->u>>r)&1)) {
536     cur->regmap[preferred_reg]=reg|64;
537     cur->dirty&=~(1<<preferred_reg);
538     cur->isconst&=~(1<<preferred_reg);
539     return;
540   }
541   if(r>=64&&((cur->uu>>(r&63))&1)) {
542     cur->regmap[preferred_reg]=reg|64;
543     cur->dirty&=~(1<<preferred_reg);
544     cur->isconst&=~(1<<preferred_reg);
545     return;
546   }
547   
548   // Clear any unneeded registers
549   // We try to keep the mapping consistent, if possible, because it
550   // makes branches easier (especially loops).  So we try to allocate
551   // first (see above) before removing old mappings.  If this is not
552   // possible then go ahead and clear out the registers that are no
553   // longer needed.
554   for(hr=HOST_REGS-1;hr>=0;hr--)
555   {
556     r=cur->regmap[hr];
557     if(r>=0) {
558       if(r<64) {
559         if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
560       }
561       else
562       {
563         if((cur->uu>>(r&63))&1) {cur->regmap[hr]=-1;break;}
564       }
565     }
566   }
567   // Try to allocate any available register, but prefer
568   // registers that have not been used recently.
569   if(i>0) {
570     for(hr=0;hr<HOST_REGS;hr++) {
571       if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
572         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]) {
573           cur->regmap[hr]=reg|64;
574           cur->dirty&=~(1<<hr);
575           cur->isconst&=~(1<<hr);
576           return;
577         }
578       }
579     }
580   }
581   // Try to allocate any available register
582   for(hr=0;hr<HOST_REGS;hr++) {
583     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
584       cur->regmap[hr]=reg|64;
585       cur->dirty&=~(1<<hr);
586       cur->isconst&=~(1<<hr);
587       return;
588     }
589   }
590   
591   // Ok, now we have to evict someone
592   // Pick a register we hopefully won't need soon
593   u_char hsn[MAXREG+1];
594   memset(hsn,10,sizeof(hsn));
595   int j;
596   lsn(hsn,i,&preferred_reg);
597   //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]);
598   //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]);
599   if(i>0) {
600     // Don't evict the cycle count at entry points, otherwise the entry
601     // stub will have to write it.
602     if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
603     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;
604     for(j=10;j>=3;j--)
605     {
606       // Alloc preferred register if available
607       if(hsn[r=cur->regmap[preferred_reg]&63]==j) {
608         for(hr=0;hr<HOST_REGS;hr++) {
609           // Evict both parts of a 64-bit register
610           if((cur->regmap[hr]&63)==r) {
611             cur->regmap[hr]=-1;
612             cur->dirty&=~(1<<hr);
613             cur->isconst&=~(1<<hr);
614           }
615         }
616         cur->regmap[preferred_reg]=reg|64;
617         return;
618       }
619       for(r=1;r<=MAXREG;r++)
620       {
621         if(hsn[r]==j&&r!=rs1[i-1]&&r!=rs2[i-1]&&r!=rt1[i-1]&&r!=rt2[i-1]) {
622           for(hr=0;hr<HOST_REGS;hr++) {
623             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
624               if(cur->regmap[hr]==r+64) {
625                 cur->regmap[hr]=reg|64;
626                 cur->dirty&=~(1<<hr);
627                 cur->isconst&=~(1<<hr);
628                 return;
629               }
630             }
631           }
632           for(hr=0;hr<HOST_REGS;hr++) {
633             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
634               if(cur->regmap[hr]==r) {
635                 cur->regmap[hr]=reg|64;
636                 cur->dirty&=~(1<<hr);
637                 cur->isconst&=~(1<<hr);
638                 return;
639               }
640             }
641           }
642         }
643       }
644     }
645   }
646   for(j=10;j>=0;j--)
647   {
648     for(r=1;r<=MAXREG;r++)
649     {
650       if(hsn[r]==j) {
651         for(hr=0;hr<HOST_REGS;hr++) {
652           if(cur->regmap[hr]==r+64) {
653             cur->regmap[hr]=reg|64;
654             cur->dirty&=~(1<<hr);
655             cur->isconst&=~(1<<hr);
656             return;
657           }
658         }
659         for(hr=0;hr<HOST_REGS;hr++) {
660           if(cur->regmap[hr]==r) {
661             cur->regmap[hr]=reg|64;
662             cur->dirty&=~(1<<hr);
663             cur->isconst&=~(1<<hr);
664             return;
665           }
666         }
667       }
668     }
669   }
670   SysPrintf("This shouldn't happen");exit(1);
671 }
672
673 // Allocate a temporary register.  This is done without regard to
674 // dirty status or whether the register we request is on the unneeded list
675 // Note: This will only allocate one register, even if called multiple times
676 void alloc_reg_temp(struct regstat *cur,int i,signed char reg)
677 {
678   int r,hr;
679   int preferred_reg = -1;
680   
681   // see if it's already allocated
682   for(hr=0;hr<HOST_REGS;hr++)
683   {
684     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==reg) return;
685   }
686   
687   // Try to allocate any available register
688   for(hr=HOST_REGS-1;hr>=0;hr--) {
689     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
690       cur->regmap[hr]=reg;
691       cur->dirty&=~(1<<hr);
692       cur->isconst&=~(1<<hr);
693       return;
694     }
695   }
696   
697   // Find an unneeded register
698   for(hr=HOST_REGS-1;hr>=0;hr--)
699   {
700     r=cur->regmap[hr];
701     if(r>=0) {
702       if(r<64) {
703         if((cur->u>>r)&1) {
704           if(i==0||((unneeded_reg[i-1]>>r)&1)) {
705             cur->regmap[hr]=reg;
706             cur->dirty&=~(1<<hr);
707             cur->isconst&=~(1<<hr);
708             return;
709           }
710         }
711       }
712       else
713       {
714         if((cur->uu>>(r&63))&1) {
715           if(i==0||((unneeded_reg_upper[i-1]>>(r&63))&1)) {
716             cur->regmap[hr]=reg;
717             cur->dirty&=~(1<<hr);
718             cur->isconst&=~(1<<hr);
719             return;
720           }
721         }
722       }
723     }
724   }
725   
726   // Ok, now we have to evict someone
727   // Pick a register we hopefully won't need soon
728   // TODO: we might want to follow unconditional jumps here
729   // TODO: get rid of dupe code and make this into a function
730   u_char hsn[MAXREG+1];
731   memset(hsn,10,sizeof(hsn));
732   int j;
733   lsn(hsn,i,&preferred_reg);
734   //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]);
735   if(i>0) {
736     // Don't evict the cycle count at entry points, otherwise the entry
737     // stub will have to write it.
738     if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
739     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;
740     for(j=10;j>=3;j--)
741     {
742       for(r=1;r<=MAXREG;r++)
743       {
744         if(hsn[r]==j&&r!=rs1[i-1]&&r!=rs2[i-1]&&r!=rt1[i-1]&&r!=rt2[i-1]) {
745           for(hr=0;hr<HOST_REGS;hr++) {
746             if(hr!=HOST_CCREG||hsn[CCREG]>2) {
747               if(cur->regmap[hr]==r+64) {
748                 cur->regmap[hr]=reg;
749                 cur->dirty&=~(1<<hr);
750                 cur->isconst&=~(1<<hr);
751                 return;
752               }
753             }
754           }
755           for(hr=0;hr<HOST_REGS;hr++) {
756             if(hr!=HOST_CCREG||hsn[CCREG]>2) {
757               if(cur->regmap[hr]==r) {
758                 cur->regmap[hr]=reg;
759                 cur->dirty&=~(1<<hr);
760                 cur->isconst&=~(1<<hr);
761                 return;
762               }
763             }
764           }
765         }
766       }
767     }
768   }
769   for(j=10;j>=0;j--)
770   {
771     for(r=1;r<=MAXREG;r++)
772     {
773       if(hsn[r]==j) {
774         for(hr=0;hr<HOST_REGS;hr++) {
775           if(cur->regmap[hr]==r+64) {
776             cur->regmap[hr]=reg;
777             cur->dirty&=~(1<<hr);
778             cur->isconst&=~(1<<hr);
779             return;
780           }
781         }
782         for(hr=0;hr<HOST_REGS;hr++) {
783           if(cur->regmap[hr]==r) {
784             cur->regmap[hr]=reg;
785             cur->dirty&=~(1<<hr);
786             cur->isconst&=~(1<<hr);
787             return;
788           }
789         }
790       }
791     }
792   }
793   SysPrintf("This shouldn't happen");exit(1);
794 }
795 // Allocate a specific ARM register.
796 void alloc_arm_reg(struct regstat *cur,int i,signed char reg,char hr)
797 {
798   int n;
799   int dirty=0;
800   
801   // see if it's already allocated (and dealloc it)
802   for(n=0;n<HOST_REGS;n++)
803   {
804     if(n!=EXCLUDE_REG&&cur->regmap[n]==reg) {
805       dirty=(cur->dirty>>n)&1;
806       cur->regmap[n]=-1;
807     }
808   }
809   
810   cur->regmap[hr]=reg;
811   cur->dirty&=~(1<<hr);
812   cur->dirty|=dirty<<hr;
813   cur->isconst&=~(1<<hr);
814 }
815
816 // Alloc cycle count into dedicated register
817 alloc_cc(struct regstat *cur,int i)
818 {
819   alloc_arm_reg(cur,i,CCREG,HOST_CCREG);
820 }
821
822 /* Special alloc */
823
824
825 /* Assembler */
826
827 char regname[16][4] = {
828  "r0",
829  "r1",
830  "r2",
831  "r3",
832  "r4",
833  "r5",
834  "r6",
835  "r7",
836  "r8",
837  "r9",
838  "r10",
839  "fp",
840  "r12",
841  "sp",
842  "lr",
843  "pc"};
844
845 void output_byte(u_char byte)
846 {
847   *(out++)=byte;
848 }
849 void output_modrm(u_char mod,u_char rm,u_char ext)
850 {
851   assert(mod<4);
852   assert(rm<8);
853   assert(ext<8);
854   u_char byte=(mod<<6)|(ext<<3)|rm;
855   *(out++)=byte;
856 }
857 void output_sib(u_char scale,u_char index,u_char base)
858 {
859   assert(scale<4);
860   assert(index<8);
861   assert(base<8);
862   u_char byte=(scale<<6)|(index<<3)|base;
863   *(out++)=byte;
864 }
865 void output_w32(u_int word)
866 {
867   *((u_int *)out)=word;
868   out+=4;
869 }
870 u_int rd_rn_rm(u_int rd, u_int rn, u_int rm)
871 {
872   assert(rd<16);
873   assert(rn<16);
874   assert(rm<16);
875   return((rn<<16)|(rd<<12)|rm);
876 }
877 u_int rd_rn_imm_shift(u_int rd, u_int rn, u_int imm, u_int shift)
878 {
879   assert(rd<16);
880   assert(rn<16);
881   assert(imm<256);
882   assert((shift&1)==0);
883   return((rn<<16)|(rd<<12)|(((32-shift)&30)<<7)|imm);
884 }
885 u_int genimm(u_int imm,u_int *encoded)
886 {
887   *encoded=0;
888   if(imm==0) return 1;
889   int i=32;
890   while(i>0)
891   {
892     if(imm<256) {
893       *encoded=((i&30)<<7)|imm;
894       return 1;
895     }
896     imm=(imm>>2)|(imm<<30);i-=2;
897   }
898   return 0;
899 }
900 void genimm_checked(u_int imm,u_int *encoded)
901 {
902   u_int ret=genimm(imm,encoded);
903   assert(ret);
904 }
905 u_int genjmp(u_int addr)
906 {
907   int offset=addr-(int)out-8;
908   if(offset<-33554432||offset>=33554432) {
909     if (addr>2) {
910       SysPrintf("genjmp: out of range: %08x\n", offset);
911       exit(1);
912     }
913     return 0;
914   }
915   return ((u_int)offset>>2)&0xffffff;
916 }
917
918 void emit_mov(int rs,int rt)
919 {
920   assem_debug("mov %s,%s\n",regname[rt],regname[rs]);
921   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs));
922 }
923
924 void emit_movs(int rs,int rt)
925 {
926   assem_debug("movs %s,%s\n",regname[rt],regname[rs]);
927   output_w32(0xe1b00000|rd_rn_rm(rt,0,rs));
928 }
929
930 void emit_add(int rs1,int rs2,int rt)
931 {
932   assem_debug("add %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
933   output_w32(0xe0800000|rd_rn_rm(rt,rs1,rs2));
934 }
935
936 void emit_adds(int rs1,int rs2,int rt)
937 {
938   assem_debug("adds %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
939   output_w32(0xe0900000|rd_rn_rm(rt,rs1,rs2));
940 }
941
942 void emit_adcs(int rs1,int rs2,int rt)
943 {
944   assem_debug("adcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
945   output_w32(0xe0b00000|rd_rn_rm(rt,rs1,rs2));
946 }
947
948 void emit_sbc(int rs1,int rs2,int rt)
949 {
950   assem_debug("sbc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
951   output_w32(0xe0c00000|rd_rn_rm(rt,rs1,rs2));
952 }
953
954 void emit_sbcs(int rs1,int rs2,int rt)
955 {
956   assem_debug("sbcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
957   output_w32(0xe0d00000|rd_rn_rm(rt,rs1,rs2));
958 }
959
960 void emit_neg(int rs, int rt)
961 {
962   assem_debug("rsb %s,%s,#0\n",regname[rt],regname[rs]);
963   output_w32(0xe2600000|rd_rn_rm(rt,rs,0));
964 }
965
966 void emit_negs(int rs, int rt)
967 {
968   assem_debug("rsbs %s,%s,#0\n",regname[rt],regname[rs]);
969   output_w32(0xe2700000|rd_rn_rm(rt,rs,0));
970 }
971
972 void emit_sub(int rs1,int rs2,int rt)
973 {
974   assem_debug("sub %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
975   output_w32(0xe0400000|rd_rn_rm(rt,rs1,rs2));
976 }
977
978 void emit_subs(int rs1,int rs2,int rt)
979 {
980   assem_debug("subs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
981   output_w32(0xe0500000|rd_rn_rm(rt,rs1,rs2));
982 }
983
984 void emit_zeroreg(int rt)
985 {
986   assem_debug("mov %s,#0\n",regname[rt]);
987   output_w32(0xe3a00000|rd_rn_rm(rt,0,0));
988 }
989
990 void emit_loadlp(u_int imm,u_int rt)
991 {
992   add_literal((int)out,imm);
993   assem_debug("ldr %s,pc+? [=%x]\n",regname[rt],imm);
994   output_w32(0xe5900000|rd_rn_rm(rt,15,0));
995 }
996 void emit_movw(u_int imm,u_int rt)
997 {
998   assert(imm<65536);
999   assem_debug("movw %s,#%d (0x%x)\n",regname[rt],imm,imm);
1000   output_w32(0xe3000000|rd_rn_rm(rt,0,0)|(imm&0xfff)|((imm<<4)&0xf0000));
1001 }
1002 void emit_movt(u_int imm,u_int rt)
1003 {
1004   assem_debug("movt %s,#%d (0x%x)\n",regname[rt],imm&0xffff0000,imm&0xffff0000);
1005   output_w32(0xe3400000|rd_rn_rm(rt,0,0)|((imm>>16)&0xfff)|((imm>>12)&0xf0000));
1006 }
1007 void emit_movimm(u_int imm,u_int rt)
1008 {
1009   u_int armval;
1010   if(genimm(imm,&armval)) {
1011     assem_debug("mov %s,#%d\n",regname[rt],imm);
1012     output_w32(0xe3a00000|rd_rn_rm(rt,0,0)|armval);
1013   }else if(genimm(~imm,&armval)) {
1014     assem_debug("mvn %s,#%d\n",regname[rt],imm);
1015     output_w32(0xe3e00000|rd_rn_rm(rt,0,0)|armval);
1016   }else if(imm<65536) {
1017     #ifndef HAVE_ARMV7
1018     assem_debug("mov %s,#%d\n",regname[rt],imm&0xFF00);
1019     output_w32(0xe3a00000|rd_rn_imm_shift(rt,0,imm>>8,8));
1020     assem_debug("add %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF);
1021     output_w32(0xe2800000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1022     #else
1023     emit_movw(imm,rt);
1024     #endif
1025   }else{
1026     #ifndef HAVE_ARMV7
1027     emit_loadlp(imm,rt);
1028     #else
1029     emit_movw(imm&0x0000FFFF,rt);
1030     emit_movt(imm&0xFFFF0000,rt);
1031     #endif
1032   }
1033 }
1034 void emit_pcreladdr(u_int rt)
1035 {
1036   assem_debug("add %s,pc,#?\n",regname[rt]);
1037   output_w32(0xe2800000|rd_rn_rm(rt,15,0));
1038 }
1039
1040 void emit_loadreg(int r, int hr)
1041 {
1042 #ifdef FORCE32
1043   if(r&64) {
1044     SysPrintf("64bit load in 32bit mode!\n");
1045     assert(0);
1046     return;
1047   }
1048 #endif
1049   if((r&63)==0)
1050     emit_zeroreg(hr);
1051   else {
1052     int addr=((int)reg)+((r&63)<<REG_SHIFT)+((r&64)>>4);
1053     if((r&63)==HIREG) addr=(int)&hi+((r&64)>>4);
1054     if((r&63)==LOREG) addr=(int)&lo+((r&64)>>4);
1055     if(r==CCREG) addr=(int)&cycle_count;
1056     if(r==CSREG) addr=(int)&Status;
1057     if(r==FSREG) addr=(int)&FCR31;
1058     if(r==INVCP) addr=(int)&invc_ptr;
1059     u_int offset = addr-(u_int)&dynarec_local;
1060     assert(offset<4096);
1061     assem_debug("ldr %s,fp+%d\n",regname[hr],offset);
1062     output_w32(0xe5900000|rd_rn_rm(hr,FP,0)|offset);
1063   }
1064 }
1065 void emit_storereg(int r, int hr)
1066 {
1067 #ifdef FORCE32
1068   if(r&64) {
1069     SysPrintf("64bit store in 32bit mode!\n");
1070     assert(0);
1071     return;
1072   }
1073 #endif
1074   int addr=((int)reg)+((r&63)<<REG_SHIFT)+((r&64)>>4);
1075   if((r&63)==HIREG) addr=(int)&hi+((r&64)>>4);
1076   if((r&63)==LOREG) addr=(int)&lo+((r&64)>>4);
1077   if(r==CCREG) addr=(int)&cycle_count;
1078   if(r==FSREG) addr=(int)&FCR31;
1079   u_int offset = addr-(u_int)&dynarec_local;
1080   assert(offset<4096);
1081   assem_debug("str %s,fp+%d\n",regname[hr],offset);
1082   output_w32(0xe5800000|rd_rn_rm(hr,FP,0)|offset);
1083 }
1084
1085 void emit_test(int rs, int rt)
1086 {
1087   assem_debug("tst %s,%s\n",regname[rs],regname[rt]);
1088   output_w32(0xe1100000|rd_rn_rm(0,rs,rt));
1089 }
1090
1091 void emit_testimm(int rs,int imm)
1092 {
1093   u_int armval;
1094   assem_debug("tst %s,#%d\n",regname[rs],imm);
1095   genimm_checked(imm,&armval);
1096   output_w32(0xe3100000|rd_rn_rm(0,rs,0)|armval);
1097 }
1098
1099 void emit_testeqimm(int rs,int imm)
1100 {
1101   u_int armval;
1102   assem_debug("tsteq %s,$%d\n",regname[rs],imm);
1103   genimm_checked(imm,&armval);
1104   output_w32(0x03100000|rd_rn_rm(0,rs,0)|armval);
1105 }
1106
1107 void emit_not(int rs,int rt)
1108 {
1109   assem_debug("mvn %s,%s\n",regname[rt],regname[rs]);
1110   output_w32(0xe1e00000|rd_rn_rm(rt,0,rs));
1111 }
1112
1113 void emit_mvnmi(int rs,int rt)
1114 {
1115   assem_debug("mvnmi %s,%s\n",regname[rt],regname[rs]);
1116   output_w32(0x41e00000|rd_rn_rm(rt,0,rs));
1117 }
1118
1119 void emit_and(u_int rs1,u_int rs2,u_int rt)
1120 {
1121   assem_debug("and %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1122   output_w32(0xe0000000|rd_rn_rm(rt,rs1,rs2));
1123 }
1124
1125 void emit_or(u_int rs1,u_int rs2,u_int rt)
1126 {
1127   assem_debug("orr %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1128   output_w32(0xe1800000|rd_rn_rm(rt,rs1,rs2));
1129 }
1130 void emit_or_and_set_flags(int rs1,int rs2,int rt)
1131 {
1132   assem_debug("orrs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1133   output_w32(0xe1900000|rd_rn_rm(rt,rs1,rs2));
1134 }
1135
1136 void emit_orrshl_imm(u_int rs,u_int imm,u_int rt)
1137 {
1138   assert(rs<16);
1139   assert(rt<16);
1140   assert(imm<32);
1141   assem_debug("orr %s,%s,%s,lsl #%d\n",regname[rt],regname[rt],regname[rs],imm);
1142   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs)|(imm<<7));
1143 }
1144
1145 void emit_orrshr_imm(u_int rs,u_int imm,u_int rt)
1146 {
1147   assert(rs<16);
1148   assert(rt<16);
1149   assert(imm<32);
1150   assem_debug("orr %s,%s,%s,lsr #%d\n",regname[rt],regname[rt],regname[rs],imm);
1151   output_w32(0xe1800020|rd_rn_rm(rt,rt,rs)|(imm<<7));
1152 }
1153
1154 void emit_xor(u_int rs1,u_int rs2,u_int rt)
1155 {
1156   assem_debug("eor %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1157   output_w32(0xe0200000|rd_rn_rm(rt,rs1,rs2));
1158 }
1159
1160 void emit_addimm(u_int rs,int imm,u_int rt)
1161 {
1162   assert(rs<16);
1163   assert(rt<16);
1164   if(imm!=0) {
1165     u_int armval;
1166     if(genimm(imm,&armval)) {
1167       assem_debug("add %s,%s,#%d\n",regname[rt],regname[rs],imm);
1168       output_w32(0xe2800000|rd_rn_rm(rt,rs,0)|armval);
1169     }else if(genimm(-imm,&armval)) {
1170       assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rs],-imm);
1171       output_w32(0xe2400000|rd_rn_rm(rt,rs,0)|armval);
1172     }else if(imm<0) {
1173       assert(imm>-65536);
1174       assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rs],(-imm)&0xFF00);
1175       assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rt],(-imm)&0xFF);
1176       output_w32(0xe2400000|rd_rn_imm_shift(rt,rs,(-imm)>>8,8));
1177       output_w32(0xe2400000|rd_rn_imm_shift(rt,rt,(-imm)&0xff,0));
1178     }else{
1179       assert(imm<65536);
1180       assem_debug("add %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF00);
1181       assem_debug("add %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF);
1182       output_w32(0xe2800000|rd_rn_imm_shift(rt,rs,imm>>8,8));
1183       output_w32(0xe2800000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1184     }
1185   }
1186   else if(rs!=rt) emit_mov(rs,rt);
1187 }
1188
1189 void emit_addimm_and_set_flags(int imm,int rt)
1190 {
1191   assert(imm>-65536&&imm<65536);
1192   u_int armval;
1193   if(genimm(imm,&armval)) {
1194     assem_debug("adds %s,%s,#%d\n",regname[rt],regname[rt],imm);
1195     output_w32(0xe2900000|rd_rn_rm(rt,rt,0)|armval);
1196   }else if(genimm(-imm,&armval)) {
1197     assem_debug("subs %s,%s,#%d\n",regname[rt],regname[rt],imm);
1198     output_w32(0xe2500000|rd_rn_rm(rt,rt,0)|armval);
1199   }else if(imm<0) {
1200     assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rt],(-imm)&0xFF00);
1201     assem_debug("subs %s,%s,#%d\n",regname[rt],regname[rt],(-imm)&0xFF);
1202     output_w32(0xe2400000|rd_rn_imm_shift(rt,rt,(-imm)>>8,8));
1203     output_w32(0xe2500000|rd_rn_imm_shift(rt,rt,(-imm)&0xff,0));
1204   }else{
1205     assem_debug("add %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF00);
1206     assem_debug("adds %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF);
1207     output_w32(0xe2800000|rd_rn_imm_shift(rt,rt,imm>>8,8));
1208     output_w32(0xe2900000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1209   }
1210 }
1211 void emit_addimm_no_flags(u_int imm,u_int rt)
1212 {
1213   emit_addimm(rt,imm,rt);
1214 }
1215
1216 void emit_addnop(u_int r)
1217 {
1218   assert(r<16);
1219   assem_debug("add %s,%s,#0 (nop)\n",regname[r],regname[r]);
1220   output_w32(0xe2800000|rd_rn_rm(r,r,0));
1221 }
1222
1223 void emit_adcimm(u_int rs,int imm,u_int rt)
1224 {
1225   u_int armval;
1226   genimm_checked(imm,&armval);
1227   assem_debug("adc %s,%s,#%d\n",regname[rt],regname[rs],imm);
1228   output_w32(0xe2a00000|rd_rn_rm(rt,rs,0)|armval);
1229 }
1230 /*void emit_sbcimm(int imm,u_int rt)
1231 {
1232   u_int armval;
1233   genimm_checked(imm,&armval);
1234   assem_debug("sbc %s,%s,#%d\n",regname[rt],regname[rt],imm);
1235   output_w32(0xe2c00000|rd_rn_rm(rt,rt,0)|armval);
1236 }*/
1237 void emit_sbbimm(int imm,u_int rt)
1238 {
1239   assem_debug("sbb $%d,%%%s\n",imm,regname[rt]);
1240   assert(rt<8);
1241   if(imm<128&&imm>=-128) {
1242     output_byte(0x83);
1243     output_modrm(3,rt,3);
1244     output_byte(imm);
1245   }
1246   else
1247   {
1248     output_byte(0x81);
1249     output_modrm(3,rt,3);
1250     output_w32(imm);
1251   }
1252 }
1253 void emit_rscimm(int rs,int imm,u_int rt)
1254 {
1255   assert(0);
1256   u_int armval;
1257   genimm_checked(imm,&armval);
1258   assem_debug("rsc %s,%s,#%d\n",regname[rt],regname[rs],imm);
1259   output_w32(0xe2e00000|rd_rn_rm(rt,rs,0)|armval);
1260 }
1261
1262 void emit_addimm64_32(int rsh,int rsl,int imm,int rth,int rtl)
1263 {
1264   // TODO: if(genimm(imm,&armval)) ...
1265   // else
1266   emit_movimm(imm,HOST_TEMPREG);
1267   emit_adds(HOST_TEMPREG,rsl,rtl);
1268   emit_adcimm(rsh,0,rth);
1269 }
1270
1271 void emit_sbb(int rs1,int rs2)
1272 {
1273   assem_debug("sbb %%%s,%%%s\n",regname[rs2],regname[rs1]);
1274   output_byte(0x19);
1275   output_modrm(3,rs1,rs2);
1276 }
1277
1278 void emit_andimm(int rs,int imm,int rt)
1279 {
1280   u_int armval;
1281   if(imm==0) {
1282     emit_zeroreg(rt);
1283   }else if(genimm(imm,&armval)) {
1284     assem_debug("and %s,%s,#%d\n",regname[rt],regname[rs],imm);
1285     output_w32(0xe2000000|rd_rn_rm(rt,rs,0)|armval);
1286   }else if(genimm(~imm,&armval)) {
1287     assem_debug("bic %s,%s,#%d\n",regname[rt],regname[rs],imm);
1288     output_w32(0xe3c00000|rd_rn_rm(rt,rs,0)|armval);
1289   }else if(imm==65535) {
1290     #ifndef HAVE_ARMV6
1291     assem_debug("bic %s,%s,#FF000000\n",regname[rt],regname[rs]);
1292     output_w32(0xe3c00000|rd_rn_rm(rt,rs,0)|0x4FF);
1293     assem_debug("bic %s,%s,#00FF0000\n",regname[rt],regname[rt]);
1294     output_w32(0xe3c00000|rd_rn_rm(rt,rt,0)|0x8FF);
1295     #else
1296     assem_debug("uxth %s,%s\n",regname[rt],regname[rs]);
1297     output_w32(0xe6ff0070|rd_rn_rm(rt,0,rs));
1298     #endif
1299   }else{
1300     assert(imm>0&&imm<65535);
1301     #ifndef HAVE_ARMV7
1302     assem_debug("mov r14,#%d\n",imm&0xFF00);
1303     output_w32(0xe3a00000|rd_rn_imm_shift(HOST_TEMPREG,0,imm>>8,8));
1304     assem_debug("add r14,r14,#%d\n",imm&0xFF);
1305     output_w32(0xe2800000|rd_rn_imm_shift(HOST_TEMPREG,HOST_TEMPREG,imm&0xff,0));
1306     #else
1307     emit_movw(imm,HOST_TEMPREG);
1308     #endif
1309     assem_debug("and %s,%s,r14\n",regname[rt],regname[rs]);
1310     output_w32(0xe0000000|rd_rn_rm(rt,rs,HOST_TEMPREG));
1311   }
1312 }
1313
1314 void emit_orimm(int rs,int imm,int rt)
1315 {
1316   u_int armval;
1317   if(imm==0) {
1318     if(rs!=rt) emit_mov(rs,rt);
1319   }else if(genimm(imm,&armval)) {
1320     assem_debug("orr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1321     output_w32(0xe3800000|rd_rn_rm(rt,rs,0)|armval);
1322   }else{
1323     assert(imm>0&&imm<65536);
1324     assem_debug("orr %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF00);
1325     assem_debug("orr %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF);
1326     output_w32(0xe3800000|rd_rn_imm_shift(rt,rs,imm>>8,8));
1327     output_w32(0xe3800000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1328   }
1329 }
1330
1331 void emit_xorimm(int rs,int imm,int rt)
1332 {
1333   u_int armval;
1334   if(imm==0) {
1335     if(rs!=rt) emit_mov(rs,rt);
1336   }else if(genimm(imm,&armval)) {
1337     assem_debug("eor %s,%s,#%d\n",regname[rt],regname[rs],imm);
1338     output_w32(0xe2200000|rd_rn_rm(rt,rs,0)|armval);
1339   }else{
1340     assert(imm>0&&imm<65536);
1341     assem_debug("eor %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF00);
1342     assem_debug("eor %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF);
1343     output_w32(0xe2200000|rd_rn_imm_shift(rt,rs,imm>>8,8));
1344     output_w32(0xe2200000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1345   }
1346 }
1347
1348 void emit_shlimm(int rs,u_int imm,int rt)
1349 {
1350   assert(imm>0);
1351   assert(imm<32);
1352   //if(imm==1) ...
1353   assem_debug("lsl %s,%s,#%d\n",regname[rt],regname[rs],imm);
1354   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|(imm<<7));
1355 }
1356
1357 void emit_lsls_imm(int rs,int imm,int rt)
1358 {
1359   assert(imm>0);
1360   assert(imm<32);
1361   assem_debug("lsls %s,%s,#%d\n",regname[rt],regname[rs],imm);
1362   output_w32(0xe1b00000|rd_rn_rm(rt,0,rs)|(imm<<7));
1363 }
1364
1365 void emit_lslpls_imm(int rs,int imm,int rt)
1366 {
1367   assert(imm>0);
1368   assert(imm<32);
1369   assem_debug("lslpls %s,%s,#%d\n",regname[rt],regname[rs],imm);
1370   output_w32(0x51b00000|rd_rn_rm(rt,0,rs)|(imm<<7));
1371 }
1372
1373 void emit_shrimm(int rs,u_int imm,int rt)
1374 {
1375   assert(imm>0);
1376   assert(imm<32);
1377   assem_debug("lsr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1378   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x20|(imm<<7));
1379 }
1380
1381 void emit_sarimm(int rs,u_int imm,int rt)
1382 {
1383   assert(imm>0);
1384   assert(imm<32);
1385   assem_debug("asr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1386   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x40|(imm<<7));
1387 }
1388
1389 void emit_rorimm(int rs,u_int imm,int rt)
1390 {
1391   assert(imm>0);
1392   assert(imm<32);
1393   assem_debug("ror %s,%s,#%d\n",regname[rt],regname[rs],imm);
1394   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x60|(imm<<7));
1395 }
1396
1397 void emit_shldimm(int rs,int rs2,u_int imm,int rt)
1398 {
1399   assem_debug("shld %%%s,%%%s,%d\n",regname[rt],regname[rs2],imm);
1400   assert(imm>0);
1401   assert(imm<32);
1402   //if(imm==1) ...
1403   assem_debug("lsl %s,%s,#%d\n",regname[rt],regname[rs],imm);
1404   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|(imm<<7));
1405   assem_debug("orr %s,%s,%s,lsr #%d\n",regname[rt],regname[rt],regname[rs2],32-imm);
1406   output_w32(0xe1800020|rd_rn_rm(rt,rt,rs2)|((32-imm)<<7));
1407 }
1408
1409 void emit_shrdimm(int rs,int rs2,u_int imm,int rt)
1410 {
1411   assem_debug("shrd %%%s,%%%s,%d\n",regname[rt],regname[rs2],imm);
1412   assert(imm>0);
1413   assert(imm<32);
1414   //if(imm==1) ...
1415   assem_debug("lsr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1416   output_w32(0xe1a00020|rd_rn_rm(rt,0,rs)|(imm<<7));
1417   assem_debug("orr %s,%s,%s,lsl #%d\n",regname[rt],regname[rt],regname[rs2],32-imm);
1418   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs2)|((32-imm)<<7));
1419 }
1420
1421 void emit_signextend16(int rs,int rt)
1422 {
1423   #ifndef HAVE_ARMV6
1424   emit_shlimm(rs,16,rt);
1425   emit_sarimm(rt,16,rt);
1426   #else
1427   assem_debug("sxth %s,%s\n",regname[rt],regname[rs]);
1428   output_w32(0xe6bf0070|rd_rn_rm(rt,0,rs));
1429   #endif
1430 }
1431
1432 void emit_signextend8(int rs,int rt)
1433 {
1434   #ifndef HAVE_ARMV6
1435   emit_shlimm(rs,24,rt);
1436   emit_sarimm(rt,24,rt);
1437   #else
1438   assem_debug("sxtb %s,%s\n",regname[rt],regname[rs]);
1439   output_w32(0xe6af0070|rd_rn_rm(rt,0,rs));
1440   #endif
1441 }
1442
1443 void emit_shl(u_int rs,u_int shift,u_int rt)
1444 {
1445   assert(rs<16);
1446   assert(rt<16);
1447   assert(shift<16);
1448   //if(imm==1) ...
1449   assem_debug("lsl %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
1450   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x10|(shift<<8));
1451 }
1452 void emit_shr(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("lsr %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
1458   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x30|(shift<<8));
1459 }
1460 void emit_sar(u_int rs,u_int shift,u_int rt)
1461 {
1462   assert(rs<16);
1463   assert(rt<16);
1464   assert(shift<16);
1465   assem_debug("asr %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
1466   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x50|(shift<<8));
1467 }
1468 void emit_shlcl(int r)
1469 {
1470   assem_debug("shl %%%s,%%cl\n",regname[r]);
1471   assert(0);
1472 }
1473 void emit_shrcl(int r)
1474 {
1475   assem_debug("shr %%%s,%%cl\n",regname[r]);
1476   assert(0);
1477 }
1478 void emit_sarcl(int r)
1479 {
1480   assem_debug("sar %%%s,%%cl\n",regname[r]);
1481   assert(0);
1482 }
1483
1484 void emit_shldcl(int r1,int r2)
1485 {
1486   assem_debug("shld %%%s,%%%s,%%cl\n",regname[r1],regname[r2]);
1487   assert(0);
1488 }
1489 void emit_shrdcl(int r1,int r2)
1490 {
1491   assem_debug("shrd %%%s,%%%s,%%cl\n",regname[r1],regname[r2]);
1492   assert(0);
1493 }
1494 void emit_orrshl(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,lsl %s\n",regname[rt],regname[rt],regname[rs],regname[shift]);
1500   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs)|0x10|(shift<<8));
1501 }
1502 void emit_orrshr(u_int rs,u_int shift,u_int rt)
1503 {
1504   assert(rs<16);
1505   assert(rt<16);
1506   assert(shift<16);
1507   assem_debug("orr %s,%s,%s,lsr %s\n",regname[rt],regname[rt],regname[rs],regname[shift]);
1508   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs)|0x30|(shift<<8));
1509 }
1510
1511 void emit_cmpimm(int rs,int imm)
1512 {
1513   u_int armval;
1514   if(genimm(imm,&armval)) {
1515     assem_debug("cmp %s,#%d\n",regname[rs],imm);
1516     output_w32(0xe3500000|rd_rn_rm(0,rs,0)|armval);
1517   }else if(genimm(-imm,&armval)) {
1518     assem_debug("cmn %s,#%d\n",regname[rs],imm);
1519     output_w32(0xe3700000|rd_rn_rm(0,rs,0)|armval);
1520   }else if(imm>0) {
1521     assert(imm<65536);
1522     emit_movimm(imm,HOST_TEMPREG);
1523     assem_debug("cmp %s,r14\n",regname[rs]);
1524     output_w32(0xe1500000|rd_rn_rm(0,rs,HOST_TEMPREG));
1525   }else{
1526     assert(imm>-65536);
1527     emit_movimm(-imm,HOST_TEMPREG);
1528     assem_debug("cmn %s,r14\n",regname[rs]);
1529     output_w32(0xe1700000|rd_rn_rm(0,rs,HOST_TEMPREG));
1530   }
1531 }
1532
1533 void emit_cmovne(u_int *addr,int rt)
1534 {
1535   assem_debug("cmovne %x,%%%s",(int)addr,regname[rt]);
1536   assert(0);
1537 }
1538 void emit_cmovl(u_int *addr,int rt)
1539 {
1540   assem_debug("cmovl %x,%%%s",(int)addr,regname[rt]);
1541   assert(0);
1542 }
1543 void emit_cmovs(u_int *addr,int rt)
1544 {
1545   assem_debug("cmovs %x,%%%s",(int)addr,regname[rt]);
1546   assert(0);
1547 }
1548 void emit_cmovne_imm(int imm,int rt)
1549 {
1550   assem_debug("movne %s,#%d\n",regname[rt],imm);
1551   u_int armval;
1552   genimm_checked(imm,&armval);
1553   output_w32(0x13a00000|rd_rn_rm(rt,0,0)|armval);
1554 }
1555 void emit_cmovl_imm(int imm,int rt)
1556 {
1557   assem_debug("movlt %s,#%d\n",regname[rt],imm);
1558   u_int armval;
1559   genimm_checked(imm,&armval);
1560   output_w32(0xb3a00000|rd_rn_rm(rt,0,0)|armval);
1561 }
1562 void emit_cmovb_imm(int imm,int rt)
1563 {
1564   assem_debug("movcc %s,#%d\n",regname[rt],imm);
1565   u_int armval;
1566   genimm_checked(imm,&armval);
1567   output_w32(0x33a00000|rd_rn_rm(rt,0,0)|armval);
1568 }
1569 void emit_cmovs_imm(int imm,int rt)
1570 {
1571   assem_debug("movmi %s,#%d\n",regname[rt],imm);
1572   u_int armval;
1573   genimm_checked(imm,&armval);
1574   output_w32(0x43a00000|rd_rn_rm(rt,0,0)|armval);
1575 }
1576 void emit_cmove_reg(int rs,int rt)
1577 {
1578   assem_debug("moveq %s,%s\n",regname[rt],regname[rs]);
1579   output_w32(0x01a00000|rd_rn_rm(rt,0,rs));
1580 }
1581 void emit_cmovne_reg(int rs,int rt)
1582 {
1583   assem_debug("movne %s,%s\n",regname[rt],regname[rs]);
1584   output_w32(0x11a00000|rd_rn_rm(rt,0,rs));
1585 }
1586 void emit_cmovl_reg(int rs,int rt)
1587 {
1588   assem_debug("movlt %s,%s\n",regname[rt],regname[rs]);
1589   output_w32(0xb1a00000|rd_rn_rm(rt,0,rs));
1590 }
1591 void emit_cmovs_reg(int rs,int rt)
1592 {
1593   assem_debug("movmi %s,%s\n",regname[rt],regname[rs]);
1594   output_w32(0x41a00000|rd_rn_rm(rt,0,rs));
1595 }
1596
1597 void emit_slti32(int rs,int imm,int rt)
1598 {
1599   if(rs!=rt) emit_zeroreg(rt);
1600   emit_cmpimm(rs,imm);
1601   if(rs==rt) emit_movimm(0,rt);
1602   emit_cmovl_imm(1,rt);
1603 }
1604 void emit_sltiu32(int rs,int imm,int rt)
1605 {
1606   if(rs!=rt) emit_zeroreg(rt);
1607   emit_cmpimm(rs,imm);
1608   if(rs==rt) emit_movimm(0,rt);
1609   emit_cmovb_imm(1,rt);
1610 }
1611 void emit_slti64_32(int rsh,int rsl,int imm,int rt)
1612 {
1613   assert(rsh!=rt);
1614   emit_slti32(rsl,imm,rt);
1615   if(imm>=0)
1616   {
1617     emit_test(rsh,rsh);
1618     emit_cmovne_imm(0,rt);
1619     emit_cmovs_imm(1,rt);
1620   }
1621   else
1622   {
1623     emit_cmpimm(rsh,-1);
1624     emit_cmovne_imm(0,rt);
1625     emit_cmovl_imm(1,rt);
1626   }
1627 }
1628 void emit_sltiu64_32(int rsh,int rsl,int imm,int rt)
1629 {
1630   assert(rsh!=rt);
1631   emit_sltiu32(rsl,imm,rt);
1632   if(imm>=0)
1633   {
1634     emit_test(rsh,rsh);
1635     emit_cmovne_imm(0,rt);
1636   }
1637   else
1638   {
1639     emit_cmpimm(rsh,-1);
1640     emit_cmovne_imm(1,rt);
1641   }
1642 }
1643
1644 void emit_cmp(int rs,int rt)
1645 {
1646   assem_debug("cmp %s,%s\n",regname[rs],regname[rt]);
1647   output_w32(0xe1500000|rd_rn_rm(0,rs,rt));
1648 }
1649 void emit_set_gz32(int rs, int rt)
1650 {
1651   //assem_debug("set_gz32\n");
1652   emit_cmpimm(rs,1);
1653   emit_movimm(1,rt);
1654   emit_cmovl_imm(0,rt);
1655 }
1656 void emit_set_nz32(int rs, int rt)
1657 {
1658   //assem_debug("set_nz32\n");
1659   if(rs!=rt) emit_movs(rs,rt);
1660   else emit_test(rs,rs);
1661   emit_cmovne_imm(1,rt);
1662 }
1663 void emit_set_gz64_32(int rsh, int rsl, int rt)
1664 {
1665   //assem_debug("set_gz64\n");
1666   emit_set_gz32(rsl,rt);
1667   emit_test(rsh,rsh);
1668   emit_cmovne_imm(1,rt);
1669   emit_cmovs_imm(0,rt);
1670 }
1671 void emit_set_nz64_32(int rsh, int rsl, int rt)
1672 {
1673   //assem_debug("set_nz64\n");
1674   emit_or_and_set_flags(rsh,rsl,rt);
1675   emit_cmovne_imm(1,rt);
1676 }
1677 void emit_set_if_less32(int rs1, int rs2, int rt)
1678 {
1679   //assem_debug("set if less (%%%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_cmovl_imm(1,rt);
1684 }
1685 void emit_set_if_carry32(int rs1, int rs2, int rt)
1686 {
1687   //assem_debug("set if carry (%%%s,%%%s),%%%s\n",regname[rs1],regname[rs2],regname[rt]);
1688   if(rs1!=rt&&rs2!=rt) emit_zeroreg(rt);
1689   emit_cmp(rs1,rs2);
1690   if(rs1==rt||rs2==rt) emit_movimm(0,rt);
1691   emit_cmovb_imm(1,rt);
1692 }
1693 void emit_set_if_less64_32(int u1, int l1, int u2, int l2, int rt)
1694 {
1695   //assem_debug("set if less64 (%%%s,%%%s,%%%s,%%%s),%%%s\n",regname[u1],regname[l1],regname[u2],regname[l2],regname[rt]);
1696   assert(u1!=rt);
1697   assert(u2!=rt);
1698   emit_cmp(l1,l2);
1699   emit_movimm(0,rt);
1700   emit_sbcs(u1,u2,HOST_TEMPREG);
1701   emit_cmovl_imm(1,rt);
1702 }
1703 void emit_set_if_carry64_32(int u1, int l1, int u2, int l2, int rt)
1704 {
1705   //assem_debug("set if carry64 (%%%s,%%%s,%%%s,%%%s),%%%s\n",regname[u1],regname[l1],regname[u2],regname[l2],regname[rt]);
1706   assert(u1!=rt);
1707   assert(u2!=rt);
1708   emit_cmp(l1,l2);
1709   emit_movimm(0,rt);
1710   emit_sbcs(u1,u2,HOST_TEMPREG);
1711   emit_cmovb_imm(1,rt);
1712 }
1713
1714 void emit_call(int a)
1715 {
1716   assem_debug("bl %x (%x+%x)\n",a,(int)out,a-(int)out-8);
1717   u_int offset=genjmp(a);
1718   output_w32(0xeb000000|offset);
1719 }
1720 void emit_jmp(int a)
1721 {
1722   assem_debug("b %x (%x+%x)\n",a,(int)out,a-(int)out-8);
1723   u_int offset=genjmp(a);
1724   output_w32(0xea000000|offset);
1725 }
1726 void emit_jne(int a)
1727 {
1728   assem_debug("bne %x\n",a);
1729   u_int offset=genjmp(a);
1730   output_w32(0x1a000000|offset);
1731 }
1732 void emit_jeq(int a)
1733 {
1734   assem_debug("beq %x\n",a);
1735   u_int offset=genjmp(a);
1736   output_w32(0x0a000000|offset);
1737 }
1738 void emit_js(int a)
1739 {
1740   assem_debug("bmi %x\n",a);
1741   u_int offset=genjmp(a);
1742   output_w32(0x4a000000|offset);
1743 }
1744 void emit_jns(int a)
1745 {
1746   assem_debug("bpl %x\n",a);
1747   u_int offset=genjmp(a);
1748   output_w32(0x5a000000|offset);
1749 }
1750 void emit_jl(int a)
1751 {
1752   assem_debug("blt %x\n",a);
1753   u_int offset=genjmp(a);
1754   output_w32(0xba000000|offset);
1755 }
1756 void emit_jge(int a)
1757 {
1758   assem_debug("bge %x\n",a);
1759   u_int offset=genjmp(a);
1760   output_w32(0xaa000000|offset);
1761 }
1762 void emit_jno(int a)
1763 {
1764   assem_debug("bvc %x\n",a);
1765   u_int offset=genjmp(a);
1766   output_w32(0x7a000000|offset);
1767 }
1768 void emit_jc(int a)
1769 {
1770   assem_debug("bcs %x\n",a);
1771   u_int offset=genjmp(a);
1772   output_w32(0x2a000000|offset);
1773 }
1774 void emit_jcc(int a)
1775 {
1776   assem_debug("bcc %x\n",a);
1777   u_int offset=genjmp(a);
1778   output_w32(0x3a000000|offset);
1779 }
1780
1781 void emit_pushimm(int imm)
1782 {
1783   assem_debug("push $%x\n",imm);
1784   assert(0);
1785 }
1786 void emit_pusha()
1787 {
1788   assem_debug("pusha\n");
1789   assert(0);
1790 }
1791 void emit_popa()
1792 {
1793   assem_debug("popa\n");
1794   assert(0);
1795 }
1796 void emit_pushreg(u_int r)
1797 {
1798   assem_debug("push %%%s\n",regname[r]);
1799   assert(0);
1800 }
1801 void emit_popreg(u_int r)
1802 {
1803   assem_debug("pop %%%s\n",regname[r]);
1804   assert(0);
1805 }
1806 void emit_callreg(u_int r)
1807 {
1808   assert(r<15);
1809   assem_debug("blx %s\n",regname[r]);
1810   output_w32(0xe12fff30|r);
1811 }
1812 void emit_jmpreg(u_int r)
1813 {
1814   assem_debug("mov pc,%s\n",regname[r]);
1815   output_w32(0xe1a00000|rd_rn_rm(15,0,r));
1816 }
1817
1818 void emit_readword_indexed(int offset, int rs, int rt)
1819 {
1820   assert(offset>-4096&&offset<4096);
1821   assem_debug("ldr %s,%s+%d\n",regname[rt],regname[rs],offset);
1822   if(offset>=0) {
1823     output_w32(0xe5900000|rd_rn_rm(rt,rs,0)|offset);
1824   }else{
1825     output_w32(0xe5100000|rd_rn_rm(rt,rs,0)|(-offset));
1826   }
1827 }
1828 void emit_readword_dualindexedx4(int rs1, int rs2, int rt)
1829 {
1830   assem_debug("ldr %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
1831   output_w32(0xe7900000|rd_rn_rm(rt,rs1,rs2)|0x100);
1832 }
1833 void emit_ldrcc_dualindexed(int rs1, int rs2, int rt)
1834 {
1835   assem_debug("ldrcc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1836   output_w32(0x37900000|rd_rn_rm(rt,rs1,rs2));
1837 }
1838 void emit_ldrccb_dualindexed(int rs1, int rs2, int rt)
1839 {
1840   assem_debug("ldrccb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1841   output_w32(0x37d00000|rd_rn_rm(rt,rs1,rs2));
1842 }
1843 void emit_ldrccsb_dualindexed(int rs1, int rs2, int rt)
1844 {
1845   assem_debug("ldrccsb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1846   output_w32(0x319000d0|rd_rn_rm(rt,rs1,rs2));
1847 }
1848 void emit_ldrcch_dualindexed(int rs1, int rs2, int rt)
1849 {
1850   assem_debug("ldrcch %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1851   output_w32(0x319000b0|rd_rn_rm(rt,rs1,rs2));
1852 }
1853 void emit_ldrccsh_dualindexed(int rs1, int rs2, int rt)
1854 {
1855   assem_debug("ldrccsh %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1856   output_w32(0x319000f0|rd_rn_rm(rt,rs1,rs2));
1857 }
1858 void emit_readword_indexed_tlb(int addr, int rs, int map, int rt)
1859 {
1860   if(map<0) emit_readword_indexed(addr, rs, rt);
1861   else {
1862     assert(addr==0);
1863     emit_readword_dualindexedx4(rs, map, rt);
1864   }
1865 }
1866 void emit_readdword_indexed_tlb(int addr, int rs, int map, int rh, int rl)
1867 {
1868   if(map<0) {
1869     if(rh>=0) emit_readword_indexed(addr, rs, rh);
1870     emit_readword_indexed(addr+4, rs, rl);
1871   }else{
1872     assert(rh!=rs);
1873     if(rh>=0) emit_readword_indexed_tlb(addr, rs, map, rh);
1874     emit_addimm(map,1,map);
1875     emit_readword_indexed_tlb(addr, rs, map, rl);
1876   }
1877 }
1878 void emit_movsbl_indexed(int offset, int rs, int rt)
1879 {
1880   assert(offset>-256&&offset<256);
1881   assem_debug("ldrsb %s,%s+%d\n",regname[rt],regname[rs],offset);
1882   if(offset>=0) {
1883     output_w32(0xe1d000d0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1884   }else{
1885     output_w32(0xe15000d0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1886   }
1887 }
1888 void emit_movsbl_indexed_tlb(int addr, int rs, int map, int rt)
1889 {
1890   if(map<0) emit_movsbl_indexed(addr, rs, rt);
1891   else {
1892     if(addr==0) {
1893       emit_shlimm(map,2,map);
1894       assem_debug("ldrsb %s,%s+%s\n",regname[rt],regname[rs],regname[map]);
1895       output_w32(0xe19000d0|rd_rn_rm(rt,rs,map));
1896     }else{
1897       assert(addr>-256&&addr<256);
1898       assem_debug("add %s,%s,%s,lsl #2\n",regname[rt],regname[rs],regname[map]);
1899       output_w32(0xe0800000|rd_rn_rm(rt,rs,map)|(2<<7));
1900       emit_movsbl_indexed(addr, rt, rt);
1901     }
1902   }
1903 }
1904 void emit_movswl_indexed(int offset, int rs, int rt)
1905 {
1906   assert(offset>-256&&offset<256);
1907   assem_debug("ldrsh %s,%s+%d\n",regname[rt],regname[rs],offset);
1908   if(offset>=0) {
1909     output_w32(0xe1d000f0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1910   }else{
1911     output_w32(0xe15000f0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1912   }
1913 }
1914 void emit_movzbl_indexed(int offset, int rs, int rt)
1915 {
1916   assert(offset>-4096&&offset<4096);
1917   assem_debug("ldrb %s,%s+%d\n",regname[rt],regname[rs],offset);
1918   if(offset>=0) {
1919     output_w32(0xe5d00000|rd_rn_rm(rt,rs,0)|offset);
1920   }else{
1921     output_w32(0xe5500000|rd_rn_rm(rt,rs,0)|(-offset));
1922   }
1923 }
1924 void emit_movzbl_dualindexedx4(int rs1, int rs2, int rt)
1925 {
1926   assem_debug("ldrb %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
1927   output_w32(0xe7d00000|rd_rn_rm(rt,rs1,rs2)|0x100);
1928 }
1929 void emit_movzbl_indexed_tlb(int addr, int rs, int map, int rt)
1930 {
1931   if(map<0) emit_movzbl_indexed(addr, rs, rt);
1932   else {
1933     if(addr==0) {
1934       emit_movzbl_dualindexedx4(rs, map, rt);
1935     }else{
1936       emit_addimm(rs,addr,rt);
1937       emit_movzbl_dualindexedx4(rt, map, rt);
1938     }
1939   }
1940 }
1941 void emit_movzwl_indexed(int offset, int rs, int rt)
1942 {
1943   assert(offset>-256&&offset<256);
1944   assem_debug("ldrh %s,%s+%d\n",regname[rt],regname[rs],offset);
1945   if(offset>=0) {
1946     output_w32(0xe1d000b0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1947   }else{
1948     output_w32(0xe15000b0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1949   }
1950 }
1951 static void emit_ldrd(int offset, int rs, int rt)
1952 {
1953   assert(offset>-256&&offset<256);
1954   assem_debug("ldrd %s,%s+%d\n",regname[rt],regname[rs],offset);
1955   if(offset>=0) {
1956     output_w32(0xe1c000d0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1957   }else{
1958     output_w32(0xe14000d0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1959   }
1960 }
1961 void emit_readword(int addr, int rt)
1962 {
1963   u_int offset = addr-(u_int)&dynarec_local;
1964   assert(offset<4096);
1965   assem_debug("ldr %s,fp+%d\n",regname[rt],offset);
1966   output_w32(0xe5900000|rd_rn_rm(rt,FP,0)|offset);
1967 }
1968 void emit_movsbl(int addr, int rt)
1969 {
1970   u_int offset = addr-(u_int)&dynarec_local;
1971   assert(offset<256);
1972   assem_debug("ldrsb %s,fp+%d\n",regname[rt],offset);
1973   output_w32(0xe1d000d0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
1974 }
1975 void emit_movswl(int addr, int rt)
1976 {
1977   u_int offset = addr-(u_int)&dynarec_local;
1978   assert(offset<256);
1979   assem_debug("ldrsh %s,fp+%d\n",regname[rt],offset);
1980   output_w32(0xe1d000f0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
1981 }
1982 void emit_movzbl(int addr, int rt)
1983 {
1984   u_int offset = addr-(u_int)&dynarec_local;
1985   assert(offset<4096);
1986   assem_debug("ldrb %s,fp+%d\n",regname[rt],offset);
1987   output_w32(0xe5d00000|rd_rn_rm(rt,FP,0)|offset);
1988 }
1989 void emit_movzwl(int addr, int rt)
1990 {
1991   u_int offset = addr-(u_int)&dynarec_local;
1992   assert(offset<256);
1993   assem_debug("ldrh %s,fp+%d\n",regname[rt],offset);
1994   output_w32(0xe1d000b0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
1995 }
1996 void emit_movzwl_reg(int rs, int rt)
1997 {
1998   assem_debug("movzwl %%%s,%%%s\n",regname[rs]+1,regname[rt]);
1999   assert(0);
2000 }
2001
2002 void emit_xchg(int rs, int rt)
2003 {
2004   assem_debug("xchg %%%s,%%%s\n",regname[rs],regname[rt]);
2005   assert(0);
2006 }
2007 void emit_writeword_indexed(int rt, int offset, int rs)
2008 {
2009   assert(offset>-4096&&offset<4096);
2010   assem_debug("str %s,%s+%d\n",regname[rt],regname[rs],offset);
2011   if(offset>=0) {
2012     output_w32(0xe5800000|rd_rn_rm(rt,rs,0)|offset);
2013   }else{
2014     output_w32(0xe5000000|rd_rn_rm(rt,rs,0)|(-offset));
2015   }
2016 }
2017 void emit_writeword_dualindexedx4(int rt, int rs1, int rs2)
2018 {
2019   assem_debug("str %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
2020   output_w32(0xe7800000|rd_rn_rm(rt,rs1,rs2)|0x100);
2021 }
2022 void emit_writeword_indexed_tlb(int rt, int addr, int rs, int map, int temp)
2023 {
2024   if(map<0) emit_writeword_indexed(rt, addr, rs);
2025   else {
2026     assert(addr==0);
2027     emit_writeword_dualindexedx4(rt, rs, map);
2028   }
2029 }
2030 void emit_writedword_indexed_tlb(int rh, int rl, int addr, int rs, int map, int temp)
2031 {
2032   if(map<0) {
2033     if(rh>=0) emit_writeword_indexed(rh, addr, rs);
2034     emit_writeword_indexed(rl, addr+4, rs);
2035   }else{
2036     assert(rh>=0);
2037     if(temp!=rs) emit_addimm(map,1,temp);
2038     emit_writeword_indexed_tlb(rh, addr, rs, map, temp);
2039     if(temp!=rs) emit_writeword_indexed_tlb(rl, addr, rs, temp, temp);
2040     else {
2041       emit_addimm(rs,4,rs);
2042       emit_writeword_indexed_tlb(rl, addr, rs, map, temp);
2043     }
2044   }
2045 }
2046 void emit_writehword_indexed(int rt, int offset, int rs)
2047 {
2048   assert(offset>-256&&offset<256);
2049   assem_debug("strh %s,%s+%d\n",regname[rt],regname[rs],offset);
2050   if(offset>=0) {
2051     output_w32(0xe1c000b0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
2052   }else{
2053     output_w32(0xe14000b0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
2054   }
2055 }
2056 void emit_writebyte_indexed(int rt, int offset, int rs)
2057 {
2058   assert(offset>-4096&&offset<4096);
2059   assem_debug("strb %s,%s+%d\n",regname[rt],regname[rs],offset);
2060   if(offset>=0) {
2061     output_w32(0xe5c00000|rd_rn_rm(rt,rs,0)|offset);
2062   }else{
2063     output_w32(0xe5400000|rd_rn_rm(rt,rs,0)|(-offset));
2064   }
2065 }
2066 void emit_writebyte_dualindexedx4(int rt, int rs1, int rs2)
2067 {
2068   assem_debug("strb %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
2069   output_w32(0xe7c00000|rd_rn_rm(rt,rs1,rs2)|0x100);
2070 }
2071 void emit_writebyte_indexed_tlb(int rt, int addr, int rs, int map, int temp)
2072 {
2073   if(map<0) emit_writebyte_indexed(rt, addr, rs);
2074   else {
2075     if(addr==0) {
2076       emit_writebyte_dualindexedx4(rt, rs, map);
2077     }else{
2078       emit_addimm(rs,addr,temp);
2079       emit_writebyte_dualindexedx4(rt, temp, map);
2080     }
2081   }
2082 }
2083 void emit_strcc_dualindexed(int rs1, int rs2, int rt)
2084 {
2085   assem_debug("strcc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2086   output_w32(0x37800000|rd_rn_rm(rt,rs1,rs2));
2087 }
2088 void emit_strccb_dualindexed(int rs1, int rs2, int rt)
2089 {
2090   assem_debug("strccb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2091   output_w32(0x37c00000|rd_rn_rm(rt,rs1,rs2));
2092 }
2093 void emit_strcch_dualindexed(int rs1, int rs2, int rt)
2094 {
2095   assem_debug("strcch %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2096   output_w32(0x318000b0|rd_rn_rm(rt,rs1,rs2));
2097 }
2098 void emit_writeword(int rt, int addr)
2099 {
2100   u_int offset = addr-(u_int)&dynarec_local;
2101   assert(offset<4096);
2102   assem_debug("str %s,fp+%d\n",regname[rt],offset);
2103   output_w32(0xe5800000|rd_rn_rm(rt,FP,0)|offset);
2104 }
2105 void emit_writehword(int rt, int addr)
2106 {
2107   u_int offset = addr-(u_int)&dynarec_local;
2108   assert(offset<256);
2109   assem_debug("strh %s,fp+%d\n",regname[rt],offset);
2110   output_w32(0xe1c000b0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
2111 }
2112 void emit_writebyte(int rt, int addr)
2113 {
2114   u_int offset = addr-(u_int)&dynarec_local;
2115   assert(offset<4096);
2116   assem_debug("strb %s,fp+%d\n",regname[rt],offset);
2117   output_w32(0xe5c00000|rd_rn_rm(rt,FP,0)|offset);
2118 }
2119 void emit_writeword_imm(int imm, int addr)
2120 {
2121   assem_debug("movl $%x,%x\n",imm,addr);
2122   assert(0);
2123 }
2124 void emit_writebyte_imm(int imm, int addr)
2125 {
2126   assem_debug("movb $%x,%x\n",imm,addr);
2127   assert(0);
2128 }
2129
2130 void emit_mul(int rs)
2131 {
2132   assem_debug("mul %%%s\n",regname[rs]);
2133   assert(0);
2134 }
2135 void emit_imul(int rs)
2136 {
2137   assem_debug("imul %%%s\n",regname[rs]);
2138   assert(0);
2139 }
2140 void emit_umull(u_int rs1, u_int rs2, u_int hi, u_int lo)
2141 {
2142   assem_debug("umull %s, %s, %s, %s\n",regname[lo],regname[hi],regname[rs1],regname[rs2]);
2143   assert(rs1<16);
2144   assert(rs2<16);
2145   assert(hi<16);
2146   assert(lo<16);
2147   output_w32(0xe0800090|(hi<<16)|(lo<<12)|(rs2<<8)|rs1);
2148 }
2149 void emit_smull(u_int rs1, u_int rs2, u_int hi, u_int lo)
2150 {
2151   assem_debug("smull %s, %s, %s, %s\n",regname[lo],regname[hi],regname[rs1],regname[rs2]);
2152   assert(rs1<16);
2153   assert(rs2<16);
2154   assert(hi<16);
2155   assert(lo<16);
2156   output_w32(0xe0c00090|(hi<<16)|(lo<<12)|(rs2<<8)|rs1);
2157 }
2158
2159 void emit_div(int rs)
2160 {
2161   assem_debug("div %%%s\n",regname[rs]);
2162   assert(0);
2163 }
2164 void emit_idiv(int rs)
2165 {
2166   assem_debug("idiv %%%s\n",regname[rs]);
2167   assert(0);
2168 }
2169 void emit_cdq()
2170 {
2171   assem_debug("cdq\n");
2172   assert(0);
2173 }
2174
2175 void emit_clz(int rs,int rt)
2176 {
2177   assem_debug("clz %s,%s\n",regname[rt],regname[rs]);
2178   output_w32(0xe16f0f10|rd_rn_rm(rt,0,rs));
2179 }
2180
2181 void emit_subcs(int rs1,int rs2,int rt)
2182 {
2183   assem_debug("subcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2184   output_w32(0x20400000|rd_rn_rm(rt,rs1,rs2));
2185 }
2186
2187 void emit_shrcc_imm(int rs,u_int imm,int rt)
2188 {
2189   assert(imm>0);
2190   assert(imm<32);
2191   assem_debug("lsrcc %s,%s,#%d\n",regname[rt],regname[rs],imm);
2192   output_w32(0x31a00000|rd_rn_rm(rt,0,rs)|0x20|(imm<<7));
2193 }
2194
2195 void emit_shrne_imm(int rs,u_int imm,int rt)
2196 {
2197   assert(imm>0);
2198   assert(imm<32);
2199   assem_debug("lsrne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2200   output_w32(0x11a00000|rd_rn_rm(rt,0,rs)|0x20|(imm<<7));
2201 }
2202
2203 void emit_negmi(int rs, int rt)
2204 {
2205   assem_debug("rsbmi %s,%s,#0\n",regname[rt],regname[rs]);
2206   output_w32(0x42600000|rd_rn_rm(rt,rs,0));
2207 }
2208
2209 void emit_negsmi(int rs, int rt)
2210 {
2211   assem_debug("rsbsmi %s,%s,#0\n",regname[rt],regname[rs]);
2212   output_w32(0x42700000|rd_rn_rm(rt,rs,0));
2213 }
2214
2215 void emit_orreq(u_int rs1,u_int rs2,u_int rt)
2216 {
2217   assem_debug("orreq %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2218   output_w32(0x01800000|rd_rn_rm(rt,rs1,rs2));
2219 }
2220
2221 void emit_orrne(u_int rs1,u_int rs2,u_int rt)
2222 {
2223   assem_debug("orrne %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2224   output_w32(0x11800000|rd_rn_rm(rt,rs1,rs2));
2225 }
2226
2227 void emit_bic_lsl(u_int rs1,u_int rs2,u_int shift,u_int rt)
2228 {
2229   assem_debug("bic %s,%s,%s lsl %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2230   output_w32(0xe1C00000|rd_rn_rm(rt,rs1,rs2)|0x10|(shift<<8));
2231 }
2232
2233 void emit_biceq_lsl(u_int rs1,u_int rs2,u_int shift,u_int rt)
2234 {
2235   assem_debug("biceq %s,%s,%s lsl %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2236   output_w32(0x01C00000|rd_rn_rm(rt,rs1,rs2)|0x10|(shift<<8));
2237 }
2238
2239 void emit_bicne_lsl(u_int rs1,u_int rs2,u_int shift,u_int rt)
2240 {
2241   assem_debug("bicne %s,%s,%s lsl %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2242   output_w32(0x11C00000|rd_rn_rm(rt,rs1,rs2)|0x10|(shift<<8));
2243 }
2244
2245 void emit_bic_lsr(u_int rs1,u_int rs2,u_int shift,u_int rt)
2246 {
2247   assem_debug("bic %s,%s,%s lsr %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2248   output_w32(0xe1C00000|rd_rn_rm(rt,rs1,rs2)|0x30|(shift<<8));
2249 }
2250
2251 void emit_biceq_lsr(u_int rs1,u_int rs2,u_int shift,u_int rt)
2252 {
2253   assem_debug("biceq %s,%s,%s lsr %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2254   output_w32(0x01C00000|rd_rn_rm(rt,rs1,rs2)|0x30|(shift<<8));
2255 }
2256
2257 void emit_bicne_lsr(u_int rs1,u_int rs2,u_int shift,u_int rt)
2258 {
2259   assem_debug("bicne %s,%s,%s lsr %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2260   output_w32(0x11C00000|rd_rn_rm(rt,rs1,rs2)|0x30|(shift<<8));
2261 }
2262
2263 void emit_teq(int rs, int rt)
2264 {
2265   assem_debug("teq %s,%s\n",regname[rs],regname[rt]);
2266   output_w32(0xe1300000|rd_rn_rm(0,rs,rt));
2267 }
2268
2269 void emit_rsbimm(int rs, int imm, int rt)
2270 {
2271   u_int armval;
2272   genimm_checked(imm,&armval);
2273   assem_debug("rsb %s,%s,#%d\n",regname[rt],regname[rs],imm);
2274   output_w32(0xe2600000|rd_rn_rm(rt,rs,0)|armval);
2275 }
2276
2277 // Load 2 immediates optimizing for small code size
2278 void emit_mov2imm_compact(int imm1,u_int rt1,int imm2,u_int rt2)
2279 {
2280   emit_movimm(imm1,rt1);
2281   u_int armval;
2282   if(genimm(imm2-imm1,&armval)) {
2283     assem_debug("add %s,%s,#%d\n",regname[rt2],regname[rt1],imm2-imm1);
2284     output_w32(0xe2800000|rd_rn_rm(rt2,rt1,0)|armval);
2285   }else if(genimm(imm1-imm2,&armval)) {
2286     assem_debug("sub %s,%s,#%d\n",regname[rt2],regname[rt1],imm1-imm2);
2287     output_w32(0xe2400000|rd_rn_rm(rt2,rt1,0)|armval);
2288   }
2289   else emit_movimm(imm2,rt2);
2290 }
2291
2292 // Conditionally select one of two immediates, optimizing for small code size
2293 // This will only be called if HAVE_CMOV_IMM is defined
2294 void emit_cmov2imm_e_ne_compact(int imm1,int imm2,u_int rt)
2295 {
2296   u_int armval;
2297   if(genimm(imm2-imm1,&armval)) {
2298     emit_movimm(imm1,rt);
2299     assem_debug("addne %s,%s,#%d\n",regname[rt],regname[rt],imm2-imm1);
2300     output_w32(0x12800000|rd_rn_rm(rt,rt,0)|armval);
2301   }else if(genimm(imm1-imm2,&armval)) {
2302     emit_movimm(imm1,rt);
2303     assem_debug("subne %s,%s,#%d\n",regname[rt],regname[rt],imm1-imm2);
2304     output_w32(0x12400000|rd_rn_rm(rt,rt,0)|armval);
2305   }
2306   else {
2307     #ifndef HAVE_ARMV7
2308     emit_movimm(imm1,rt);
2309     add_literal((int)out,imm2);
2310     assem_debug("ldrne %s,pc+? [=%x]\n",regname[rt],imm2);
2311     output_w32(0x15900000|rd_rn_rm(rt,15,0));
2312     #else
2313     emit_movw(imm1&0x0000FFFF,rt);
2314     if((imm1&0xFFFF)!=(imm2&0xFFFF)) {
2315       assem_debug("movwne %s,#%d (0x%x)\n",regname[rt],imm2&0xFFFF,imm2&0xFFFF);
2316       output_w32(0x13000000|rd_rn_rm(rt,0,0)|(imm2&0xfff)|((imm2<<4)&0xf0000));
2317     }
2318     emit_movt(imm1&0xFFFF0000,rt);
2319     if((imm1&0xFFFF0000)!=(imm2&0xFFFF0000)) {
2320       assem_debug("movtne %s,#%d (0x%x)\n",regname[rt],imm2&0xffff0000,imm2&0xffff0000);
2321       output_w32(0x13400000|rd_rn_rm(rt,0,0)|((imm2>>16)&0xfff)|((imm2>>12)&0xf0000));
2322     }
2323     #endif
2324   }
2325 }
2326
2327 // special case for checking invalid_code
2328 void emit_cmpmem_indexedsr12_imm(int addr,int r,int imm)
2329 {
2330   assert(0);
2331 }
2332
2333 // special case for checking invalid_code
2334 void emit_cmpmem_indexedsr12_reg(int base,int r,int imm)
2335 {
2336   assert(imm<128&&imm>=0);
2337   assert(r>=0&&r<16);
2338   assem_debug("ldrb lr,%s,%s lsr #12\n",regname[base],regname[r]);
2339   output_w32(0xe7d00000|rd_rn_rm(HOST_TEMPREG,base,r)|0x620);
2340   emit_cmpimm(HOST_TEMPREG,imm);
2341 }
2342
2343 // special case for tlb mapping
2344 void emit_addsr12(int rs1,int rs2,int rt)
2345 {
2346   assem_debug("add %s,%s,%s lsr #12\n",regname[rt],regname[rs1],regname[rs2]);
2347   output_w32(0xe0800620|rd_rn_rm(rt,rs1,rs2));
2348 }
2349
2350 void emit_callne(int a)
2351 {
2352   assem_debug("blne %x\n",a);
2353   u_int offset=genjmp(a);
2354   output_w32(0x1b000000|offset);
2355 }
2356
2357 // Used to preload hash table entries
2358 void emit_prefetch(void *addr)
2359 {
2360   assem_debug("prefetch %x\n",(int)addr);
2361   output_byte(0x0F);
2362   output_byte(0x18);
2363   output_modrm(0,5,1);
2364   output_w32((int)addr);
2365 }
2366 void emit_prefetchreg(int r)
2367 {
2368   assem_debug("pld %s\n",regname[r]);
2369   output_w32(0xf5d0f000|rd_rn_rm(0,r,0));
2370 }
2371
2372 // Special case for mini_ht
2373 void emit_ldreq_indexed(int rs, u_int offset, int rt)
2374 {
2375   assert(offset<4096);
2376   assem_debug("ldreq %s,[%s, #%d]\n",regname[rt],regname[rs],offset);
2377   output_w32(0x05900000|rd_rn_rm(rt,rs,0)|offset);
2378 }
2379
2380 void emit_flds(int r,int sr)
2381 {
2382   assem_debug("flds s%d,[%s]\n",sr,regname[r]);
2383   output_w32(0xed900a00|((sr&14)<<11)|((sr&1)<<22)|(r<<16));
2384
2385
2386 void emit_vldr(int r,int vr)
2387 {
2388   assem_debug("vldr d%d,[%s]\n",vr,regname[r]);
2389   output_w32(0xed900b00|(vr<<12)|(r<<16));
2390
2391
2392 void emit_fsts(int sr,int r)
2393 {
2394   assem_debug("fsts s%d,[%s]\n",sr,regname[r]);
2395   output_w32(0xed800a00|((sr&14)<<11)|((sr&1)<<22)|(r<<16));
2396
2397
2398 void emit_vstr(int vr,int r)
2399 {
2400   assem_debug("vstr d%d,[%s]\n",vr,regname[r]);
2401   output_w32(0xed800b00|(vr<<12)|(r<<16));
2402
2403
2404 void emit_ftosizs(int s,int d)
2405 {
2406   assem_debug("ftosizs s%d,s%d\n",d,s);
2407   output_w32(0xeebd0ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2408
2409
2410 void emit_ftosizd(int s,int d)
2411 {
2412   assem_debug("ftosizd s%d,d%d\n",d,s);
2413   output_w32(0xeebd0bc0|((d&14)<<11)|((d&1)<<22)|(s&7));
2414
2415
2416 void emit_fsitos(int s,int d)
2417 {
2418   assem_debug("fsitos s%d,s%d\n",d,s);
2419   output_w32(0xeeb80ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2420
2421
2422 void emit_fsitod(int s,int d)
2423 {
2424   assem_debug("fsitod d%d,s%d\n",d,s);
2425   output_w32(0xeeb80bc0|((d&7)<<12)|((s&14)>>1)|((s&1)<<5));
2426
2427
2428 void emit_fcvtds(int s,int d)
2429 {
2430   assem_debug("fcvtds d%d,s%d\n",d,s);
2431   output_w32(0xeeb70ac0|((d&7)<<12)|((s&14)>>1)|((s&1)<<5));
2432
2433
2434 void emit_fcvtsd(int s,int d)
2435 {
2436   assem_debug("fcvtsd s%d,d%d\n",d,s);
2437   output_w32(0xeeb70bc0|((d&14)<<11)|((d&1)<<22)|(s&7));
2438
2439
2440 void emit_fsqrts(int s,int d)
2441 {
2442   assem_debug("fsqrts d%d,s%d\n",d,s);
2443   output_w32(0xeeb10ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2444
2445
2446 void emit_fsqrtd(int s,int d)
2447 {
2448   assem_debug("fsqrtd s%d,d%d\n",d,s);
2449   output_w32(0xeeb10bc0|((d&7)<<12)|(s&7));
2450
2451
2452 void emit_fabss(int s,int d)
2453 {
2454   assem_debug("fabss d%d,s%d\n",d,s);
2455   output_w32(0xeeb00ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2456
2457
2458 void emit_fabsd(int s,int d)
2459 {
2460   assem_debug("fabsd s%d,d%d\n",d,s);
2461   output_w32(0xeeb00bc0|((d&7)<<12)|(s&7));
2462
2463
2464 void emit_fnegs(int s,int d)
2465 {
2466   assem_debug("fnegs d%d,s%d\n",d,s);
2467   output_w32(0xeeb10a40|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2468
2469
2470 void emit_fnegd(int s,int d)
2471 {
2472   assem_debug("fnegd s%d,d%d\n",d,s);
2473   output_w32(0xeeb10b40|((d&7)<<12)|(s&7));
2474
2475
2476 void emit_fadds(int s1,int s2,int d)
2477 {
2478   assem_debug("fadds s%d,s%d,s%d\n",d,s1,s2);
2479   output_w32(0xee300a00|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2480
2481
2482 void emit_faddd(int s1,int s2,int d)
2483 {
2484   assem_debug("faddd d%d,d%d,d%d\n",d,s1,s2);
2485   output_w32(0xee300b00|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2486
2487
2488 void emit_fsubs(int s1,int s2,int d)
2489 {
2490   assem_debug("fsubs s%d,s%d,s%d\n",d,s1,s2);
2491   output_w32(0xee300a40|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2492
2493
2494 void emit_fsubd(int s1,int s2,int d)
2495 {
2496   assem_debug("fsubd d%d,d%d,d%d\n",d,s1,s2);
2497   output_w32(0xee300b40|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2498
2499
2500 void emit_fmuls(int s1,int s2,int d)
2501 {
2502   assem_debug("fmuls s%d,s%d,s%d\n",d,s1,s2);
2503   output_w32(0xee200a00|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2504
2505
2506 void emit_fmuld(int s1,int s2,int d)
2507 {
2508   assem_debug("fmuld d%d,d%d,d%d\n",d,s1,s2);
2509   output_w32(0xee200b00|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2510
2511
2512 void emit_fdivs(int s1,int s2,int d)
2513 {
2514   assem_debug("fdivs s%d,s%d,s%d\n",d,s1,s2);
2515   output_w32(0xee800a00|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2516
2517
2518 void emit_fdivd(int s1,int s2,int d)
2519 {
2520   assem_debug("fdivd d%d,d%d,d%d\n",d,s1,s2);
2521   output_w32(0xee800b00|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2522
2523
2524 void emit_fcmps(int x,int y)
2525 {
2526   assem_debug("fcmps s14, s15\n");
2527   output_w32(0xeeb47a67);
2528
2529
2530 void emit_fcmpd(int x,int y)
2531 {
2532   assem_debug("fcmpd d6, d7\n");
2533   output_w32(0xeeb46b47);
2534
2535
2536 void emit_fmstat()
2537 {
2538   assem_debug("fmstat\n");
2539   output_w32(0xeef1fa10);
2540
2541
2542 void emit_bicne_imm(int rs,int imm,int rt)
2543 {
2544   u_int armval;
2545   genimm_checked(imm,&armval);
2546   assem_debug("bicne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2547   output_w32(0x13c00000|rd_rn_rm(rt,rs,0)|armval);
2548 }
2549
2550 void emit_biccs_imm(int rs,int imm,int rt)
2551 {
2552   u_int armval;
2553   genimm_checked(imm,&armval);
2554   assem_debug("biccs %s,%s,#%d\n",regname[rt],regname[rs],imm);
2555   output_w32(0x23c00000|rd_rn_rm(rt,rs,0)|armval);
2556 }
2557
2558 void emit_bicvc_imm(int rs,int imm,int rt)
2559 {
2560   u_int armval;
2561   genimm_checked(imm,&armval);
2562   assem_debug("bicvc %s,%s,#%d\n",regname[rt],regname[rs],imm);
2563   output_w32(0x73c00000|rd_rn_rm(rt,rs,0)|armval);
2564 }
2565
2566 void emit_bichi_imm(int rs,int imm,int rt)
2567 {
2568   u_int armval;
2569   genimm_checked(imm,&armval);
2570   assem_debug("bichi %s,%s,#%d\n",regname[rt],regname[rs],imm);
2571   output_w32(0x83c00000|rd_rn_rm(rt,rs,0)|armval);
2572 }
2573
2574 void emit_orrvs_imm(int rs,int imm,int rt)
2575 {
2576   u_int armval;
2577   genimm_checked(imm,&armval);
2578   assem_debug("orrvs %s,%s,#%d\n",regname[rt],regname[rs],imm);
2579   output_w32(0x63800000|rd_rn_rm(rt,rs,0)|armval);
2580 }
2581
2582 void emit_orrne_imm(int rs,int imm,int rt)
2583 {
2584   u_int armval;
2585   genimm_checked(imm,&armval);
2586   assem_debug("orrne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2587   output_w32(0x13800000|rd_rn_rm(rt,rs,0)|armval);
2588 }
2589
2590 void emit_andne_imm(int rs,int imm,int rt)
2591 {
2592   u_int armval;
2593   genimm_checked(imm,&armval);
2594   assem_debug("andne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2595   output_w32(0x12000000|rd_rn_rm(rt,rs,0)|armval);
2596 }
2597
2598 void emit_addpl_imm(int rs,int imm,int rt)
2599 {
2600   u_int armval;
2601   genimm_checked(imm,&armval);
2602   assem_debug("addpl %s,%s,#%d\n",regname[rt],regname[rs],imm);
2603   output_w32(0x52800000|rd_rn_rm(rt,rs,0)|armval);
2604 }
2605
2606 void emit_jno_unlikely(int a)
2607 {
2608   //emit_jno(a);
2609   assem_debug("addvc pc,pc,#? (%x)\n",/*a-(int)out-8,*/a);
2610   output_w32(0x72800000|rd_rn_rm(15,15,0));
2611 }
2612
2613 static void save_regs_all(u_int reglist)
2614 {
2615   int i;
2616   if(!reglist) return;
2617   assem_debug("stmia fp,{");
2618   for(i=0;i<16;i++)
2619     if(reglist&(1<<i))
2620       assem_debug("r%d,",i);
2621   assem_debug("}\n");
2622   output_w32(0xe88b0000|reglist);
2623 }
2624 static void restore_regs_all(u_int reglist)
2625 {
2626   int i;
2627   if(!reglist) return;
2628   assem_debug("ldmia fp,{");
2629   for(i=0;i<16;i++)
2630     if(reglist&(1<<i))
2631       assem_debug("r%d,",i);
2632   assem_debug("}\n");
2633   output_w32(0xe89b0000|reglist);
2634 }
2635 // Save registers before function call
2636 static void save_regs(u_int reglist)
2637 {
2638   reglist&=CALLER_SAVE_REGS; // only save the caller-save registers, r0-r3, r12
2639   save_regs_all(reglist);
2640 }
2641 // Restore registers after function call
2642 static void restore_regs(u_int reglist)
2643 {
2644   reglist&=CALLER_SAVE_REGS;
2645   restore_regs_all(reglist);
2646 }
2647
2648 // Write back consts using r14 so we don't disturb the other registers
2649 void wb_consts(signed char i_regmap[],uint64_t i_is32,u_int i_dirty,int i)
2650 {
2651   int hr;
2652   for(hr=0;hr<HOST_REGS;hr++) {
2653     if(hr!=EXCLUDE_REG&&i_regmap[hr]>=0&&((i_dirty>>hr)&1)) {
2654       if(((regs[i].isconst>>hr)&1)&&i_regmap[hr]>0) {
2655         if(i_regmap[hr]<64 || !((i_is32>>(i_regmap[hr]&63))&1) ) {
2656           int value=constmap[i][hr];
2657           if(value==0) {
2658             emit_zeroreg(HOST_TEMPREG);
2659           }
2660           else {
2661             emit_movimm(value,HOST_TEMPREG);
2662           }
2663           emit_storereg(i_regmap[hr],HOST_TEMPREG);
2664 #ifndef FORCE32
2665           if((i_is32>>i_regmap[hr])&1) {
2666             if(value!=-1&&value!=0) emit_sarimm(HOST_TEMPREG,31,HOST_TEMPREG);
2667             emit_storereg(i_regmap[hr]|64,HOST_TEMPREG);
2668           }
2669 #endif
2670         }
2671       }
2672     }
2673   }
2674 }
2675
2676 /* Stubs/epilogue */
2677
2678 void literal_pool(int n)
2679 {
2680   if(!literalcount) return;
2681   if(n) {
2682     if((int)out-literals[0][0]<4096-n) return;
2683   }
2684   u_int *ptr;
2685   int i;
2686   for(i=0;i<literalcount;i++)
2687   {
2688     u_int l_addr=(u_int)out;
2689     int j;
2690     for(j=0;j<i;j++) {
2691       if(literals[j][1]==literals[i][1]) {
2692         //printf("dup %08x\n",literals[i][1]);
2693         l_addr=literals[j][0];
2694         break;
2695       }
2696     }
2697     ptr=(u_int *)literals[i][0];
2698     u_int offset=l_addr-(u_int)ptr-8;
2699     assert(offset<4096);
2700     assert(!(offset&3));
2701     *ptr|=offset;
2702     if(l_addr==(u_int)out) {
2703       literals[i][0]=l_addr; // remember for dupes
2704       output_w32(literals[i][1]);
2705     }
2706   }
2707   literalcount=0;
2708 }
2709
2710 void literal_pool_jumpover(int n)
2711 {
2712   if(!literalcount) return;
2713   if(n) {
2714     if((int)out-literals[0][0]<4096-n) return;
2715   }
2716   int jaddr=(int)out;
2717   emit_jmp(0);
2718   literal_pool(0);
2719   set_jump_target(jaddr,(int)out);
2720 }
2721
2722 emit_extjump2(u_int addr, int target, int linker)
2723 {
2724   u_char *ptr=(u_char *)addr;
2725   assert((ptr[3]&0x0e)==0xa);
2726   emit_loadlp(target,0);
2727   emit_loadlp(addr,1);
2728   assert(addr>=BASE_ADDR&&addr<(BASE_ADDR+(1<<TARGET_SIZE_2)));
2729   //assert((target>=0x80000000&&target<0x80800000)||(target>0xA4000000&&target<0xA4001000));
2730 //DEBUG >
2731 #ifdef DEBUG_CYCLE_COUNT
2732   emit_readword((int)&last_count,ECX);
2733   emit_add(HOST_CCREG,ECX,HOST_CCREG);
2734   emit_readword((int)&next_interupt,ECX);
2735   emit_writeword(HOST_CCREG,(int)&Count);
2736   emit_sub(HOST_CCREG,ECX,HOST_CCREG);
2737   emit_writeword(ECX,(int)&last_count);
2738 #endif
2739 //DEBUG <
2740   emit_jmp(linker);
2741 }
2742
2743 emit_extjump(int addr, int target)
2744 {
2745   emit_extjump2(addr, target, (int)dyna_linker);
2746 }
2747 emit_extjump_ds(int addr, int target)
2748 {
2749   emit_extjump2(addr, target, (int)dyna_linker_ds);
2750 }
2751
2752 // put rt_val into rt, potentially making use of rs with value rs_val
2753 static void emit_movimm_from(u_int rs_val,int rs,u_int rt_val,int rt)
2754 {
2755   u_int armval;
2756   int diff;
2757   if(genimm(rt_val,&armval)) {
2758     assem_debug("mov %s,#%d\n",regname[rt],rt_val);
2759     output_w32(0xe3a00000|rd_rn_rm(rt,0,0)|armval);
2760     return;
2761   }
2762   if(genimm(~rt_val,&armval)) {
2763     assem_debug("mvn %s,#%d\n",regname[rt],rt_val);
2764     output_w32(0xe3e00000|rd_rn_rm(rt,0,0)|armval);
2765     return;
2766   }
2767   diff=rt_val-rs_val;
2768   if(genimm(diff,&armval)) {
2769     assem_debug("add %s,%s,#%d\n",regname[rt],regname[rs],diff);
2770     output_w32(0xe2800000|rd_rn_rm(rt,rs,0)|armval);
2771     return;
2772   }else if(genimm(-diff,&armval)) {
2773     assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rs],-diff);
2774     output_w32(0xe2400000|rd_rn_rm(rt,rs,0)|armval);
2775     return;
2776   }
2777   emit_movimm(rt_val,rt);
2778 }
2779
2780 // return 1 if above function can do it's job cheaply
2781 static int is_similar_value(u_int v1,u_int v2)
2782 {
2783   u_int xs;
2784   int diff;
2785   if(v1==v2) return 1;
2786   diff=v2-v1;
2787   for(xs=diff;xs!=0&&(xs&3)==0;xs>>=2)
2788     ;
2789   if(xs<0x100) return 1;
2790   for(xs=-diff;xs!=0&&(xs&3)==0;xs>>=2)
2791     ;
2792   if(xs<0x100) return 1;
2793   return 0;
2794 }
2795
2796 // trashes r2
2797 static void pass_args(int a0, int a1)
2798 {
2799   if(a0==1&&a1==0) {
2800     // must swap
2801     emit_mov(a0,2); emit_mov(a1,1); emit_mov(2,0);
2802   }
2803   else if(a0!=0&&a1==0) {
2804     emit_mov(a1,1);
2805     if (a0>=0) emit_mov(a0,0);
2806   }
2807   else {
2808     if(a0>=0&&a0!=0) emit_mov(a0,0);
2809     if(a1>=0&&a1!=1) emit_mov(a1,1);
2810   }
2811 }
2812
2813 static void mov_loadtype_adj(int type,int rs,int rt)
2814 {
2815   switch(type) {
2816     case LOADB_STUB:  emit_signextend8(rs,rt); break;
2817     case LOADBU_STUB: emit_andimm(rs,0xff,rt); break;
2818     case LOADH_STUB:  emit_signextend16(rs,rt); break;
2819     case LOADHU_STUB: emit_andimm(rs,0xffff,rt); break;
2820     case LOADW_STUB:  if(rs!=rt) emit_mov(rs,rt); break;
2821     default: assert(0);
2822   }
2823 }
2824
2825 #ifdef PCSX
2826 #include "pcsxmem.h"
2827 #include "pcsxmem_inline.c"
2828 #endif
2829
2830 do_readstub(int n)
2831 {
2832   assem_debug("do_readstub %x\n",start+stubs[n][3]*4);
2833   literal_pool(256);
2834   set_jump_target(stubs[n][1],(int)out);
2835   int type=stubs[n][0];
2836   int i=stubs[n][3];
2837   int rs=stubs[n][4];
2838   struct regstat *i_regs=(struct regstat *)stubs[n][5];
2839   u_int reglist=stubs[n][7];
2840   signed char *i_regmap=i_regs->regmap;
2841   int addr=get_reg(i_regmap,AGEN1+(i&1));
2842   int rth,rt;
2843   int ds;
2844   if(itype[i]==C1LS||itype[i]==C2LS||itype[i]==LOADLR) {
2845     rth=get_reg(i_regmap,FTEMP|64);
2846     rt=get_reg(i_regmap,FTEMP);
2847   }else{
2848     rth=get_reg(i_regmap,rt1[i]|64);
2849     rt=get_reg(i_regmap,rt1[i]);
2850   }
2851   assert(rs>=0);
2852 #ifdef PCSX
2853   int r,temp=-1,temp2=HOST_TEMPREG,regs_saved=0,restore_jump=0;
2854   reglist|=(1<<rs);
2855   for(r=0;r<=12;r++) {
2856     if(((1<<r)&0x13ff)&&((1<<r)&reglist)==0) {
2857       temp=r; break;
2858     }
2859   }
2860   if(rt>=0&&rt1[i]!=0)
2861     reglist&=~(1<<rt);
2862   if(temp==-1) {
2863     save_regs(reglist);
2864     regs_saved=1;
2865     temp=(rs==0)?2:0;
2866   }
2867   if((regs_saved||(reglist&2)==0)&&temp!=1&&rs!=1)
2868     temp2=1;
2869   emit_readword((int)&mem_rtab,temp);
2870   emit_shrimm(rs,12,temp2);
2871   emit_readword_dualindexedx4(temp,temp2,temp2);
2872   emit_lsls_imm(temp2,1,temp2);
2873   if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
2874     switch(type) {
2875       case LOADB_STUB:  emit_ldrccsb_dualindexed(temp2,rs,rt); break;
2876       case LOADBU_STUB: emit_ldrccb_dualindexed(temp2,rs,rt); break;
2877       case LOADH_STUB:  emit_ldrccsh_dualindexed(temp2,rs,rt); break;
2878       case LOADHU_STUB: emit_ldrcch_dualindexed(temp2,rs,rt); break;
2879       case LOADW_STUB:  emit_ldrcc_dualindexed(temp2,rs,rt); break;
2880     }
2881   }
2882   if(regs_saved) {
2883     restore_jump=(int)out;
2884     emit_jcc(0); // jump to reg restore
2885   }
2886   else
2887     emit_jcc(stubs[n][2]); // return address
2888
2889   if(!regs_saved)
2890     save_regs(reglist);
2891   int handler=0;
2892   if(type==LOADB_STUB||type==LOADBU_STUB)
2893     handler=(int)jump_handler_read8;
2894   if(type==LOADH_STUB||type==LOADHU_STUB)
2895     handler=(int)jump_handler_read16;
2896   if(type==LOADW_STUB)
2897     handler=(int)jump_handler_read32;
2898   assert(handler!=0);
2899   pass_args(rs,temp2);
2900   int cc=get_reg(i_regmap,CCREG);
2901   if(cc<0)
2902     emit_loadreg(CCREG,2);
2903   emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
2904   emit_call(handler);
2905   if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
2906     mov_loadtype_adj(type,0,rt);
2907   }
2908   if(restore_jump)
2909     set_jump_target(restore_jump,(int)out);
2910   restore_regs(reglist);
2911   emit_jmp(stubs[n][2]); // return address
2912 #else // !PCSX
2913   if(addr<0) addr=rt;
2914   if(addr<0&&itype[i]!=C1LS&&itype[i]!=C2LS&&itype[i]!=LOADLR) addr=get_reg(i_regmap,-1);
2915   assert(addr>=0);
2916   int ftable=0;
2917   if(type==LOADB_STUB||type==LOADBU_STUB)
2918     ftable=(int)readmemb;
2919   if(type==LOADH_STUB||type==LOADHU_STUB)
2920     ftable=(int)readmemh;
2921   if(type==LOADW_STUB)
2922     ftable=(int)readmem;
2923 #ifndef FORCE32
2924   if(type==LOADD_STUB)
2925     ftable=(int)readmemd;
2926 #endif
2927   assert(ftable!=0);
2928   emit_writeword(rs,(int)&address);
2929   //emit_pusha();
2930   save_regs(reglist);
2931 #ifndef PCSX
2932   ds=i_regs!=&regs[i];
2933   int real_rs=(itype[i]==LOADLR)?-1:get_reg(i_regmap,rs1[i]);
2934   u_int cmask=ds?-1:(0x100f|~i_regs->wasconst);
2935   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);
2936   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty&cmask&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs)));
2937   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);
2938 #endif
2939   emit_shrimm(rs,16,1);
2940   int cc=get_reg(i_regmap,CCREG);
2941   if(cc<0) {
2942     emit_loadreg(CCREG,2);
2943   }
2944   emit_movimm(ftable,0);
2945   emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
2946 #ifndef PCSX
2947   emit_movimm(start+stubs[n][3]*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
2948 #endif
2949   //emit_readword((int)&last_count,temp);
2950   //emit_add(cc,temp,cc);
2951   //emit_writeword(cc,(int)&Count);
2952   //emit_mov(15,14);
2953   emit_call((int)&indirect_jump_indexed);
2954   //emit_callreg(rs);
2955   //emit_readword_dualindexedx4(rs,HOST_TEMPREG,15);
2956 #ifndef PCSX
2957   // We really shouldn't need to update the count here,
2958   // but not doing so causes random crashes...
2959   emit_readword((int)&Count,HOST_TEMPREG);
2960   emit_readword((int)&next_interupt,2);
2961   emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
2962   emit_writeword(2,(int)&last_count);
2963   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
2964   if(cc<0) {
2965     emit_storereg(CCREG,HOST_TEMPREG);
2966   }
2967 #endif
2968   //emit_popa();
2969   restore_regs(reglist);
2970   //if((cc=get_reg(regmap,CCREG))>=0) {
2971   //  emit_loadreg(CCREG,cc);
2972   //}
2973   if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
2974     assert(rt>=0);
2975     if(type==LOADB_STUB)
2976       emit_movsbl((int)&readmem_dword,rt);
2977     if(type==LOADBU_STUB)
2978       emit_movzbl((int)&readmem_dword,rt);
2979     if(type==LOADH_STUB)
2980       emit_movswl((int)&readmem_dword,rt);
2981     if(type==LOADHU_STUB)
2982       emit_movzwl((int)&readmem_dword,rt);
2983     if(type==LOADW_STUB)
2984       emit_readword((int)&readmem_dword,rt);
2985     if(type==LOADD_STUB) {
2986       emit_readword((int)&readmem_dword,rt);
2987       if(rth>=0) emit_readword(((int)&readmem_dword)+4,rth);
2988     }
2989   }
2990   emit_jmp(stubs[n][2]); // return address
2991 #endif // !PCSX
2992 }
2993
2994 #ifdef PCSX
2995 // return memhandler, or get directly accessable address and return 0
2996 u_int get_direct_memhandler(void *table,u_int addr,int type,u_int *addr_host)
2997 {
2998   u_int l1,l2=0;
2999   l1=((u_int *)table)[addr>>12];
3000   if((l1&(1<<31))==0) {
3001     u_int v=l1<<1;
3002     *addr_host=v+addr;
3003     return 0;
3004   }
3005   else {
3006     l1<<=1;
3007     if(type==LOADB_STUB||type==LOADBU_STUB||type==STOREB_STUB)
3008       l2=((u_int *)l1)[0x1000/4 + 0x1000/2 + (addr&0xfff)];
3009     else if(type==LOADH_STUB||type==LOADHU_STUB||type==STOREH_STUB)
3010       l2=((u_int *)l1)[0x1000/4 + (addr&0xfff)/2];
3011     else
3012       l2=((u_int *)l1)[(addr&0xfff)/4];
3013     if((l2&(1<<31))==0) {
3014       u_int v=l2<<1;
3015       *addr_host=v+(addr&0xfff);
3016       return 0;
3017     }
3018     return l2<<1;
3019   }
3020 }
3021 #endif
3022
3023 inline_readstub(int type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
3024 {
3025   int rs=get_reg(regmap,target);
3026   int rth=get_reg(regmap,target|64);
3027   int rt=get_reg(regmap,target);
3028   if(rs<0) rs=get_reg(regmap,-1);
3029   assert(rs>=0);
3030 #ifdef PCSX
3031   u_int handler,host_addr=0,is_dynamic,far_call=0;
3032   int cc=get_reg(regmap,CCREG);
3033   if(pcsx_direct_read(type,addr,CLOCK_ADJUST(adj+1),cc,target?rs:-1,rt))
3034     return;
3035   handler=get_direct_memhandler(mem_rtab,addr,type,&host_addr);
3036   if (handler==0) {
3037     if(rt<0||rt1[i]==0)
3038       return;
3039     if(addr!=host_addr)
3040       emit_movimm_from(addr,rs,host_addr,rs);
3041     switch(type) {
3042       case LOADB_STUB:  emit_movsbl_indexed(0,rs,rt); break;
3043       case LOADBU_STUB: emit_movzbl_indexed(0,rs,rt); break;
3044       case LOADH_STUB:  emit_movswl_indexed(0,rs,rt); break;
3045       case LOADHU_STUB: emit_movzwl_indexed(0,rs,rt); break;
3046       case LOADW_STUB:  emit_readword_indexed(0,rs,rt); break;
3047       default:          assert(0);
3048     }
3049     return;
3050   }
3051   is_dynamic=pcsxmem_is_handler_dynamic(addr);
3052   if(is_dynamic) {
3053     if(type==LOADB_STUB||type==LOADBU_STUB)
3054       handler=(int)jump_handler_read8;
3055     if(type==LOADH_STUB||type==LOADHU_STUB)
3056       handler=(int)jump_handler_read16;
3057     if(type==LOADW_STUB)
3058       handler=(int)jump_handler_read32;
3059   }
3060
3061   // call a memhandler
3062   if(rt>=0&&rt1[i]!=0)
3063     reglist&=~(1<<rt);
3064   save_regs(reglist);
3065   if(target==0)
3066     emit_movimm(addr,0);
3067   else if(rs!=0)
3068     emit_mov(rs,0);
3069   int offset=(int)handler-(int)out-8;
3070   if(offset<-33554432||offset>=33554432) {
3071     // unreachable memhandler, a plugin func perhaps
3072     emit_movimm(handler,12);
3073     far_call=1;
3074   }
3075   if(cc<0)
3076     emit_loadreg(CCREG,2);
3077   if(is_dynamic) {
3078     emit_movimm(((u_int *)mem_rtab)[addr>>12]<<1,1);
3079     emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3080   }
3081   else {
3082     emit_readword((int)&last_count,3);
3083     emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3084     emit_add(2,3,2);
3085     emit_writeword(2,(int)&Count);
3086   }
3087
3088   if(far_call)
3089     emit_callreg(12);
3090   else
3091     emit_call(handler);
3092
3093   if(rt>=0&&rt1[i]!=0) {
3094     switch(type) {
3095       case LOADB_STUB:  emit_signextend8(0,rt); break;
3096       case LOADBU_STUB: emit_andimm(0,0xff,rt); break;
3097       case LOADH_STUB:  emit_signextend16(0,rt); break;
3098       case LOADHU_STUB: emit_andimm(0,0xffff,rt); break;
3099       case LOADW_STUB:  if(rt!=0) emit_mov(0,rt); break;
3100       default:          assert(0);
3101     }
3102   }
3103   restore_regs(reglist);
3104 #else // if !PCSX
3105   int ftable=0;
3106   if(type==LOADB_STUB||type==LOADBU_STUB)
3107     ftable=(int)readmemb;
3108   if(type==LOADH_STUB||type==LOADHU_STUB)
3109     ftable=(int)readmemh;
3110   if(type==LOADW_STUB)
3111     ftable=(int)readmem;
3112 #ifndef FORCE32
3113   if(type==LOADD_STUB)
3114     ftable=(int)readmemd;
3115 #endif
3116   assert(ftable!=0);
3117   if(target==0)
3118     emit_movimm(addr,rs);
3119   emit_writeword(rs,(int)&address);
3120   //emit_pusha();
3121   save_regs(reglist);
3122 #ifndef PCSX
3123   if((signed int)addr>=(signed int)0xC0000000) {
3124     // Theoretically we can have a pagefault here, if the TLB has never
3125     // been enabled and the address is outside the range 80000000..BFFFFFFF
3126     // Write out the registers so the pagefault can be handled.  This is
3127     // a very rare case and likely represents a bug.
3128     int ds=regmap!=regs[i].regmap;
3129     if(!ds) load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
3130     if(!ds) wb_dirtys(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty);
3131     else wb_dirtys(branch_regs[i-1].regmap_entry,branch_regs[i-1].was32,branch_regs[i-1].wasdirty);
3132   }
3133 #endif
3134   //emit_shrimm(rs,16,1);
3135   int cc=get_reg(regmap,CCREG);
3136   if(cc<0) {
3137     emit_loadreg(CCREG,2);
3138   }
3139   //emit_movimm(ftable,0);
3140   emit_movimm(((u_int *)ftable)[addr>>16],0);
3141   //emit_readword((int)&last_count,12);
3142   emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3143 #ifndef PCSX
3144   if((signed int)addr>=(signed int)0xC0000000) {
3145     // Pagefault address
3146     int ds=regmap!=regs[i].regmap;
3147     emit_movimm(start+i*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3148   }
3149 #endif
3150   //emit_add(12,2,2);
3151   //emit_writeword(2,(int)&Count);
3152   //emit_call(((u_int *)ftable)[addr>>16]);
3153   emit_call((int)&indirect_jump);
3154 #ifndef PCSX
3155   // We really shouldn't need to update the count here,
3156   // but not doing so causes random crashes...
3157   emit_readword((int)&Count,HOST_TEMPREG);
3158   emit_readword((int)&next_interupt,2);
3159   emit_addimm(HOST_TEMPREG,-CLOCK_ADJUST(adj+1),HOST_TEMPREG);
3160   emit_writeword(2,(int)&last_count);
3161   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3162   if(cc<0) {
3163     emit_storereg(CCREG,HOST_TEMPREG);
3164   }
3165 #endif
3166   //emit_popa();
3167   restore_regs(reglist);
3168   if(rt>=0) {
3169     if(type==LOADB_STUB)
3170       emit_movsbl((int)&readmem_dword,rt);
3171     if(type==LOADBU_STUB)
3172       emit_movzbl((int)&readmem_dword,rt);
3173     if(type==LOADH_STUB)
3174       emit_movswl((int)&readmem_dword,rt);
3175     if(type==LOADHU_STUB)
3176       emit_movzwl((int)&readmem_dword,rt);
3177     if(type==LOADW_STUB)
3178       emit_readword((int)&readmem_dword,rt);
3179     if(type==LOADD_STUB) {
3180       emit_readword((int)&readmem_dword,rt);
3181       if(rth>=0) emit_readword(((int)&readmem_dword)+4,rth);
3182     }
3183   }
3184 #endif // !PCSX
3185 }
3186
3187 do_writestub(int n)
3188 {
3189   assem_debug("do_writestub %x\n",start+stubs[n][3]*4);
3190   literal_pool(256);
3191   set_jump_target(stubs[n][1],(int)out);
3192   int type=stubs[n][0];
3193   int i=stubs[n][3];
3194   int rs=stubs[n][4];
3195   struct regstat *i_regs=(struct regstat *)stubs[n][5];
3196   u_int reglist=stubs[n][7];
3197   signed char *i_regmap=i_regs->regmap;
3198   int addr=get_reg(i_regmap,AGEN1+(i&1));
3199   int rth,rt,r;
3200   int ds;
3201   if(itype[i]==C1LS||itype[i]==C2LS) {
3202     rth=get_reg(i_regmap,FTEMP|64);
3203     rt=get_reg(i_regmap,r=FTEMP);
3204   }else{
3205     rth=get_reg(i_regmap,rs2[i]|64);
3206     rt=get_reg(i_regmap,r=rs2[i]);
3207   }
3208   assert(rs>=0);
3209   assert(rt>=0);
3210 #ifdef PCSX
3211   int rtmp,temp=-1,temp2=HOST_TEMPREG,regs_saved=0,restore_jump=0,ra;
3212   int reglist2=reglist|(1<<rs)|(1<<rt);
3213   for(rtmp=0;rtmp<=12;rtmp++) {
3214     if(((1<<rtmp)&0x13ff)&&((1<<rtmp)&reglist2)==0) {
3215       temp=rtmp; break;
3216     }
3217   }
3218   if(temp==-1) {
3219     save_regs(reglist);
3220     regs_saved=1;
3221     for(rtmp=0;rtmp<=3;rtmp++)
3222       if(rtmp!=rs&&rtmp!=rt)
3223         {temp=rtmp;break;}
3224   }
3225   if((regs_saved||(reglist2&8)==0)&&temp!=3&&rs!=3&&rt!=3)
3226     temp2=3;
3227   emit_readword((int)&mem_wtab,temp);
3228   emit_shrimm(rs,12,temp2);
3229   emit_readword_dualindexedx4(temp,temp2,temp2);
3230   emit_lsls_imm(temp2,1,temp2);
3231   switch(type) {
3232     case STOREB_STUB: emit_strccb_dualindexed(temp2,rs,rt); break;
3233     case STOREH_STUB: emit_strcch_dualindexed(temp2,rs,rt); break;
3234     case STOREW_STUB: emit_strcc_dualindexed(temp2,rs,rt); break;
3235     default:          assert(0);
3236   }
3237   if(regs_saved) {
3238     restore_jump=(int)out;
3239     emit_jcc(0); // jump to reg restore
3240   }
3241   else
3242     emit_jcc(stubs[n][2]); // return address (invcode check)
3243
3244   if(!regs_saved)
3245     save_regs(reglist);
3246   int handler=0;
3247   switch(type) {
3248     case STOREB_STUB: handler=(int)jump_handler_write8; break;
3249     case STOREH_STUB: handler=(int)jump_handler_write16; break;
3250     case STOREW_STUB: handler=(int)jump_handler_write32; break;
3251   }
3252   assert(handler!=0);
3253   pass_args(rs,rt);
3254   if(temp2!=3)
3255     emit_mov(temp2,3);
3256   int cc=get_reg(i_regmap,CCREG);
3257   if(cc<0)
3258     emit_loadreg(CCREG,2);
3259   emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
3260   // returns new cycle_count
3261   emit_call(handler);
3262   emit_addimm(0,-CLOCK_ADJUST((int)stubs[n][6]+1),cc<0?2:cc);
3263   if(cc<0)
3264     emit_storereg(CCREG,2);
3265   if(restore_jump)
3266     set_jump_target(restore_jump,(int)out);
3267   restore_regs(reglist);
3268   ra=stubs[n][2];
3269   emit_jmp(ra);
3270 #else // if !PCSX
3271   if(addr<0) addr=get_reg(i_regmap,-1);
3272   assert(addr>=0);
3273   int ftable=0;
3274   if(type==STOREB_STUB)
3275     ftable=(int)writememb;
3276   if(type==STOREH_STUB)
3277     ftable=(int)writememh;
3278   if(type==STOREW_STUB)
3279     ftable=(int)writemem;
3280 #ifndef FORCE32
3281   if(type==STORED_STUB)
3282     ftable=(int)writememd;
3283 #endif
3284   assert(ftable!=0);
3285   emit_writeword(rs,(int)&address);
3286   //emit_shrimm(rs,16,rs);
3287   //emit_movmem_indexedx4(ftable,rs,rs);
3288   if(type==STOREB_STUB)
3289     emit_writebyte(rt,(int)&byte);
3290   if(type==STOREH_STUB)
3291     emit_writehword(rt,(int)&hword);
3292   if(type==STOREW_STUB)
3293     emit_writeword(rt,(int)&word);
3294   if(type==STORED_STUB) {
3295 #ifndef FORCE32
3296     emit_writeword(rt,(int)&dword);
3297     emit_writeword(r?rth:rt,(int)&dword+4);
3298 #else
3299     SysPrintf("STORED_STUB\n");
3300 #endif
3301   }
3302   //emit_pusha();
3303   save_regs(reglist);
3304 #ifndef PCSX
3305   ds=i_regs!=&regs[i];
3306   int real_rs=get_reg(i_regmap,rs1[i]);
3307   u_int cmask=ds?-1:(0x100f|~i_regs->wasconst);
3308   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);
3309   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty&cmask&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs)));
3310   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);
3311 #endif
3312   emit_shrimm(rs,16,1);
3313   int cc=get_reg(i_regmap,CCREG);
3314   if(cc<0) {
3315     emit_loadreg(CCREG,2);
3316   }
3317   emit_movimm(ftable,0);
3318   emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
3319 #ifndef PCSX
3320   emit_movimm(start+stubs[n][3]*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3321 #endif
3322   //emit_readword((int)&last_count,temp);
3323   //emit_addimm(cc,2*stubs[n][5]+2,cc);
3324   //emit_add(cc,temp,cc);
3325   //emit_writeword(cc,(int)&Count);
3326   emit_call((int)&indirect_jump_indexed);
3327   //emit_callreg(rs);
3328   emit_readword((int)&Count,HOST_TEMPREG);
3329   emit_readword((int)&next_interupt,2);
3330   emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
3331   emit_writeword(2,(int)&last_count);
3332   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3333   if(cc<0) {
3334     emit_storereg(CCREG,HOST_TEMPREG);
3335   }
3336   //emit_popa();
3337   restore_regs(reglist);
3338   //if((cc=get_reg(regmap,CCREG))>=0) {
3339   //  emit_loadreg(CCREG,cc);
3340   //}
3341   emit_jmp(stubs[n][2]); // return address
3342 #endif // !PCSX
3343 }
3344
3345 inline_writestub(int type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
3346 {
3347   int rs=get_reg(regmap,-1);
3348   int rth=get_reg(regmap,target|64);
3349   int rt=get_reg(regmap,target);
3350   assert(rs>=0);
3351   assert(rt>=0);
3352 #ifdef PCSX
3353   u_int handler,host_addr=0;
3354   handler=get_direct_memhandler(mem_wtab,addr,type,&host_addr);
3355   if (handler==0) {
3356     if(addr!=host_addr)
3357       emit_movimm_from(addr,rs,host_addr,rs);
3358     switch(type) {
3359       case STOREB_STUB: emit_writebyte_indexed(rt,0,rs); break;
3360       case STOREH_STUB: emit_writehword_indexed(rt,0,rs); break;
3361       case STOREW_STUB: emit_writeword_indexed(rt,0,rs); break;
3362       default:          assert(0);
3363     }
3364     return;
3365   }
3366
3367   // call a memhandler
3368   save_regs(reglist);
3369   pass_args(rs,rt);
3370   int cc=get_reg(regmap,CCREG);
3371   if(cc<0)
3372     emit_loadreg(CCREG,2);
3373   emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3374   emit_movimm(handler,3);
3375   // returns new cycle_count
3376   emit_call((int)jump_handler_write_h);
3377   emit_addimm(0,-CLOCK_ADJUST(adj+1),cc<0?2:cc);
3378   if(cc<0)
3379     emit_storereg(CCREG,2);
3380   restore_regs(reglist);
3381 #else // if !pcsx
3382   int ftable=0;
3383   if(type==STOREB_STUB)
3384     ftable=(int)writememb;
3385   if(type==STOREH_STUB)
3386     ftable=(int)writememh;
3387   if(type==STOREW_STUB)
3388     ftable=(int)writemem;
3389 #ifndef FORCE32
3390   if(type==STORED_STUB)
3391     ftable=(int)writememd;
3392 #endif
3393   assert(ftable!=0);
3394   emit_writeword(rs,(int)&address);
3395   //emit_shrimm(rs,16,rs);
3396   //emit_movmem_indexedx4(ftable,rs,rs);
3397   if(type==STOREB_STUB)
3398     emit_writebyte(rt,(int)&byte);
3399   if(type==STOREH_STUB)
3400     emit_writehword(rt,(int)&hword);
3401   if(type==STOREW_STUB)
3402     emit_writeword(rt,(int)&word);
3403   if(type==STORED_STUB) {
3404 #ifndef FORCE32
3405     emit_writeword(rt,(int)&dword);
3406     emit_writeword(target?rth:rt,(int)&dword+4);
3407 #else
3408     SysPrintf("STORED_STUB\n");
3409 #endif
3410   }
3411   //emit_pusha();
3412   save_regs(reglist);
3413 #ifndef PCSX
3414   // rearmed note: load_all_consts prevents BIOS boot, some bug?
3415   if((signed int)addr>=(signed int)0xC0000000) {
3416     // Theoretically we can have a pagefault here, if the TLB has never
3417     // been enabled and the address is outside the range 80000000..BFFFFFFF
3418     // Write out the registers so the pagefault can be handled.  This is
3419     // a very rare case and likely represents a bug.
3420     int ds=regmap!=regs[i].regmap;
3421     if(!ds) load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
3422     if(!ds) wb_dirtys(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty);
3423     else wb_dirtys(branch_regs[i-1].regmap_entry,branch_regs[i-1].was32,branch_regs[i-1].wasdirty);
3424   }
3425 #endif
3426   //emit_shrimm(rs,16,1);
3427   int cc=get_reg(regmap,CCREG);
3428   if(cc<0) {
3429     emit_loadreg(CCREG,2);
3430   }
3431   //emit_movimm(ftable,0);
3432   emit_movimm(((u_int *)ftable)[addr>>16],0);
3433   //emit_readword((int)&last_count,12);
3434   emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3435 #ifndef PCSX
3436   if((signed int)addr>=(signed int)0xC0000000) {
3437     // Pagefault address
3438     int ds=regmap!=regs[i].regmap;
3439     emit_movimm(start+i*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3440   }
3441 #endif
3442   //emit_add(12,2,2);
3443   //emit_writeword(2,(int)&Count);
3444   //emit_call(((u_int *)ftable)[addr>>16]);
3445   emit_call((int)&indirect_jump);
3446   emit_readword((int)&Count,HOST_TEMPREG);
3447   emit_readword((int)&next_interupt,2);
3448   emit_addimm(HOST_TEMPREG,-CLOCK_ADJUST(adj+1),HOST_TEMPREG);
3449   emit_writeword(2,(int)&last_count);
3450   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3451   if(cc<0) {
3452     emit_storereg(CCREG,HOST_TEMPREG);
3453   }
3454   //emit_popa();
3455   restore_regs(reglist);
3456 #endif
3457 }
3458
3459 do_unalignedwritestub(int n)
3460 {
3461   assem_debug("do_unalignedwritestub %x\n",start+stubs[n][3]*4);
3462   literal_pool(256);
3463   set_jump_target(stubs[n][1],(int)out);
3464
3465   int i=stubs[n][3];
3466   struct regstat *i_regs=(struct regstat *)stubs[n][4];
3467   int addr=stubs[n][5];
3468   u_int reglist=stubs[n][7];
3469   signed char *i_regmap=i_regs->regmap;
3470   int temp2=get_reg(i_regmap,FTEMP);
3471   int rt;
3472   int ds, real_rs;
3473   rt=get_reg(i_regmap,rs2[i]);
3474   assert(rt>=0);
3475   assert(addr>=0);
3476   assert(opcode[i]==0x2a||opcode[i]==0x2e); // SWL/SWR only implemented
3477   reglist|=(1<<addr);
3478   reglist&=~(1<<temp2);
3479
3480 #if 1
3481   // don't bother with it and call write handler
3482   save_regs(reglist);
3483   pass_args(addr,rt);
3484   int cc=get_reg(i_regmap,CCREG);
3485   if(cc<0)
3486     emit_loadreg(CCREG,2);
3487   emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
3488   emit_call((int)(opcode[i]==0x2a?jump_handle_swl:jump_handle_swr));
3489   emit_addimm(0,-CLOCK_ADJUST((int)stubs[n][6]+1),cc<0?2:cc);
3490   if(cc<0)
3491     emit_storereg(CCREG,2);
3492   restore_regs(reglist);
3493   emit_jmp(stubs[n][2]); // return address
3494 #else
3495   emit_andimm(addr,0xfffffffc,temp2);
3496   emit_writeword(temp2,(int)&address);
3497
3498   save_regs(reglist);
3499 #ifndef PCSX
3500   ds=i_regs!=&regs[i];
3501   real_rs=get_reg(i_regmap,rs1[i]);
3502   u_int cmask=ds?-1:(0x100f|~i_regs->wasconst);
3503   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);
3504   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty&cmask&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs)));
3505   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);
3506 #endif
3507   emit_shrimm(addr,16,1);
3508   int cc=get_reg(i_regmap,CCREG);
3509   if(cc<0) {
3510     emit_loadreg(CCREG,2);
3511   }
3512   emit_movimm((u_int)readmem,0);
3513   emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
3514 #ifndef PCSX
3515   // pagefault address
3516   emit_movimm(start+stubs[n][3]*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3517 #endif
3518   emit_call((int)&indirect_jump_indexed);
3519   restore_regs(reglist);
3520
3521   emit_readword((int)&readmem_dword,temp2);
3522   int temp=addr; //hmh
3523   emit_shlimm(addr,3,temp);
3524   emit_andimm(temp,24,temp);
3525 #ifdef BIG_ENDIAN_MIPS
3526   if (opcode[i]==0x2e) // SWR
3527 #else
3528   if (opcode[i]==0x2a) // SWL
3529 #endif
3530     emit_xorimm(temp,24,temp);
3531   emit_movimm(-1,HOST_TEMPREG);
3532   if (opcode[i]==0x2a) { // SWL
3533     emit_bic_lsr(temp2,HOST_TEMPREG,temp,temp2);
3534     emit_orrshr(rt,temp,temp2);
3535   }else{
3536     emit_bic_lsl(temp2,HOST_TEMPREG,temp,temp2);
3537     emit_orrshl(rt,temp,temp2);
3538   }
3539   emit_readword((int)&address,addr);
3540   emit_writeword(temp2,(int)&word);
3541   //save_regs(reglist); // don't need to, no state changes
3542   emit_shrimm(addr,16,1);
3543   emit_movimm((u_int)writemem,0);
3544   //emit_call((int)&indirect_jump_indexed);
3545   emit_mov(15,14);
3546   emit_readword_dualindexedx4(0,1,15);
3547   emit_readword((int)&Count,HOST_TEMPREG);
3548   emit_readword((int)&next_interupt,2);
3549   emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
3550   emit_writeword(2,(int)&last_count);
3551   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3552   if(cc<0) {
3553     emit_storereg(CCREG,HOST_TEMPREG);
3554   }
3555   restore_regs(reglist);
3556   emit_jmp(stubs[n][2]); // return address
3557 #endif
3558 }
3559
3560 void printregs(int edi,int esi,int ebp,int esp,int b,int d,int c,int a)
3561 {
3562   printf("regs: %x %x %x %x %x %x %x (%x)\n",a,b,c,d,ebp,esi,edi,(&edi)[-1]);
3563 }
3564
3565 do_invstub(int n)
3566 {
3567   literal_pool(20);
3568   u_int reglist=stubs[n][3];
3569   set_jump_target(stubs[n][1],(int)out);
3570   save_regs(reglist);
3571   if(stubs[n][4]!=0) emit_mov(stubs[n][4],0);
3572   emit_call((int)&invalidate_addr);
3573   restore_regs(reglist);
3574   emit_jmp(stubs[n][2]); // return address
3575 }
3576
3577 int do_dirty_stub(int i)
3578 {
3579   assem_debug("do_dirty_stub %x\n",start+i*4);
3580   u_int addr=(int)start<(int)0xC0000000?(u_int)source:(u_int)start;
3581   #ifdef PCSX
3582   addr=(u_int)source;
3583   #endif
3584   // Careful about the code output here, verify_dirty needs to parse it.
3585   #ifndef HAVE_ARMV7
3586   emit_loadlp(addr,1);
3587   emit_loadlp((int)copy,2);
3588   emit_loadlp(slen*4,3);
3589   #else
3590   emit_movw(addr&0x0000FFFF,1);
3591   emit_movw(((u_int)copy)&0x0000FFFF,2);
3592   emit_movt(addr&0xFFFF0000,1);
3593   emit_movt(((u_int)copy)&0xFFFF0000,2);
3594   emit_movw(slen*4,3);
3595   #endif
3596   emit_movimm(start+i*4,0);
3597   emit_call((int)start<(int)0xC0000000?(int)&verify_code:(int)&verify_code_vm);
3598   int entry=(int)out;
3599   load_regs_entry(i);
3600   if(entry==(int)out) entry=instr_addr[i];
3601   emit_jmp(instr_addr[i]);
3602   return entry;
3603 }
3604
3605 void do_dirty_stub_ds()
3606 {
3607   // Careful about the code output here, verify_dirty needs to parse it.
3608   #ifndef HAVE_ARMV7
3609   emit_loadlp((int)start<(int)0xC0000000?(int)source:(int)start,1);
3610   emit_loadlp((int)copy,2);
3611   emit_loadlp(slen*4,3);
3612   #else
3613   emit_movw(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0x0000FFFF,1);
3614   emit_movw(((u_int)copy)&0x0000FFFF,2);
3615   emit_movt(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0xFFFF0000,1);
3616   emit_movt(((u_int)copy)&0xFFFF0000,2);
3617   emit_movw(slen*4,3);
3618   #endif
3619   emit_movimm(start+1,0);
3620   emit_call((int)&verify_code_ds);
3621 }
3622
3623 do_cop1stub(int n)
3624 {
3625   literal_pool(256);
3626   assem_debug("do_cop1stub %x\n",start+stubs[n][3]*4);
3627   set_jump_target(stubs[n][1],(int)out);
3628   int i=stubs[n][3];
3629 //  int rs=stubs[n][4];
3630   struct regstat *i_regs=(struct regstat *)stubs[n][5];
3631   int ds=stubs[n][6];
3632   if(!ds) {
3633     load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
3634     //if(i_regs!=&regs[i]) printf("oops: regs[i]=%x i_regs=%x",(int)&regs[i],(int)i_regs);
3635   }
3636   //else {printf("fp exception in delay slot\n");}
3637   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty);
3638   if(regs[i].regmap_entry[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
3639   emit_movimm(start+(i-ds)*4,EAX); // Get PC
3640   emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG); // CHECK: is this right?  There should probably be an extra cycle...
3641   emit_jmp(ds?(int)fp_exception_ds:(int)fp_exception);
3642 }
3643
3644 #ifndef DISABLE_TLB
3645
3646 /* TLB */
3647
3648 int do_tlb_r(int s,int ar,int map,int x,int a,int shift,int c,u_int addr)
3649 {
3650   if(c) {
3651     if((signed int)addr>=(signed int)0xC0000000) {
3652       // address_generation already loaded the const
3653       emit_readword_dualindexedx4(FP,map,map);
3654     }
3655     else
3656       return -1; // No mapping
3657   }
3658   else {
3659     assert(s!=map);
3660     emit_movimm(((int)memory_map-(int)&dynarec_local)>>2,map);
3661     emit_addsr12(map,s,map);
3662     // Schedule this while we wait on the load
3663     //if(x) emit_xorimm(s,x,ar);
3664     if(shift>=0) emit_shlimm(s,3,shift);
3665     if(~a) emit_andimm(s,a,ar);
3666     emit_readword_dualindexedx4(FP,map,map);
3667   }
3668   return map;
3669 }
3670 int do_tlb_r_branch(int map, int c, u_int addr, int *jaddr)
3671 {
3672   if(!c||(signed int)addr>=(signed int)0xC0000000) {
3673     emit_test(map,map);
3674     *jaddr=(int)out;
3675     emit_js(0);
3676   }
3677   return map;
3678 }
3679
3680 int gen_tlb_addr_r(int ar, int map) {
3681   if(map>=0) {
3682     assem_debug("add %s,%s,%s lsl #2\n",regname[ar],regname[ar],regname[map]);
3683     output_w32(0xe0800100|rd_rn_rm(ar,ar,map));
3684   }
3685 }
3686
3687 int do_tlb_w(int s,int ar,int map,int x,int c,u_int addr)
3688 {
3689   if(c) {
3690     if(addr<0x80800000||addr>=0xC0000000) {
3691       // address_generation already loaded the const
3692       emit_readword_dualindexedx4(FP,map,map);
3693     }
3694     else
3695       return -1; // No mapping
3696   }
3697   else {
3698     assert(s!=map);
3699     emit_movimm(((int)memory_map-(int)&dynarec_local)>>2,map);
3700     emit_addsr12(map,s,map);
3701     // Schedule this while we wait on the load
3702     //if(x) emit_xorimm(s,x,ar);
3703     emit_readword_dualindexedx4(FP,map,map);
3704   }
3705   return map;
3706 }
3707 int do_tlb_w_branch(int map, int c, u_int addr, int *jaddr)
3708 {
3709   if(!c||addr<0x80800000||addr>=0xC0000000) {
3710     emit_testimm(map,0x40000000);
3711     *jaddr=(int)out;
3712     emit_jne(0);
3713   }
3714 }
3715
3716 int gen_tlb_addr_w(int ar, int map) {
3717   if(map>=0) {
3718     assem_debug("add %s,%s,%s lsl #2\n",regname[ar],regname[ar],regname[map]);
3719     output_w32(0xe0800100|rd_rn_rm(ar,ar,map));
3720   }
3721 }
3722
3723 // Generate the address of the memory_map entry, relative to dynarec_local
3724 generate_map_const(u_int addr,int reg) {
3725   //printf("generate_map_const(%x,%s)\n",addr,regname[reg]);
3726   emit_movimm((addr>>12)+(((u_int)memory_map-(u_int)&dynarec_local)>>2),reg);
3727 }
3728
3729 #else
3730
3731 static int do_tlb_r(int a, ...) { return 0; }
3732 static int do_tlb_r_branch(int a, ...) { return 0; }
3733 static int gen_tlb_addr_r(int a, ...) { return 0; }
3734 static int do_tlb_w(int a, ...) { return 0; }
3735 static int do_tlb_w_branch(int a, ...) { return 0; }
3736 static int gen_tlb_addr_w(int a, ...) { return 0; }
3737
3738 #endif // DISABLE_TLB
3739
3740 /* Special assem */
3741
3742 void shift_assemble_arm(int i,struct regstat *i_regs)
3743 {
3744   if(rt1[i]) {
3745     if(opcode2[i]<=0x07) // SLLV/SRLV/SRAV
3746     {
3747       signed char s,t,shift;
3748       t=get_reg(i_regs->regmap,rt1[i]);
3749       s=get_reg(i_regs->regmap,rs1[i]);
3750       shift=get_reg(i_regs->regmap,rs2[i]);
3751       if(t>=0){
3752         if(rs1[i]==0)
3753         {
3754           emit_zeroreg(t);
3755         }
3756         else if(rs2[i]==0)
3757         {
3758           assert(s>=0);
3759           if(s!=t) emit_mov(s,t);
3760         }
3761         else
3762         {
3763           emit_andimm(shift,31,HOST_TEMPREG);
3764           if(opcode2[i]==4) // SLLV
3765           {
3766             emit_shl(s,HOST_TEMPREG,t);
3767           }
3768           if(opcode2[i]==6) // SRLV
3769           {
3770             emit_shr(s,HOST_TEMPREG,t);
3771           }
3772           if(opcode2[i]==7) // SRAV
3773           {
3774             emit_sar(s,HOST_TEMPREG,t);
3775           }
3776         }
3777       }
3778     } else { // DSLLV/DSRLV/DSRAV
3779       signed char sh,sl,th,tl,shift;
3780       th=get_reg(i_regs->regmap,rt1[i]|64);
3781       tl=get_reg(i_regs->regmap,rt1[i]);
3782       sh=get_reg(i_regs->regmap,rs1[i]|64);
3783       sl=get_reg(i_regs->regmap,rs1[i]);
3784       shift=get_reg(i_regs->regmap,rs2[i]);
3785       if(tl>=0){
3786         if(rs1[i]==0)
3787         {
3788           emit_zeroreg(tl);
3789           if(th>=0) emit_zeroreg(th);
3790         }
3791         else if(rs2[i]==0)
3792         {
3793           assert(sl>=0);
3794           if(sl!=tl) emit_mov(sl,tl);
3795           if(th>=0&&sh!=th) emit_mov(sh,th);
3796         }
3797         else
3798         {
3799           // FIXME: What if shift==tl ?
3800           assert(shift!=tl);
3801           int temp=get_reg(i_regs->regmap,-1);
3802           int real_th=th;
3803           if(th<0&&opcode2[i]!=0x14) {th=temp;} // DSLLV doesn't need a temporary register
3804           assert(sl>=0);
3805           assert(sh>=0);
3806           emit_andimm(shift,31,HOST_TEMPREG);
3807           if(opcode2[i]==0x14) // DSLLV
3808           {
3809             if(th>=0) emit_shl(sh,HOST_TEMPREG,th);
3810             emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
3811             emit_orrshr(sl,HOST_TEMPREG,th);
3812             emit_andimm(shift,31,HOST_TEMPREG);
3813             emit_testimm(shift,32);
3814             emit_shl(sl,HOST_TEMPREG,tl);
3815             if(th>=0) emit_cmovne_reg(tl,th);
3816             emit_cmovne_imm(0,tl);
3817           }
3818           if(opcode2[i]==0x16) // DSRLV
3819           {
3820             assert(th>=0);
3821             emit_shr(sl,HOST_TEMPREG,tl);
3822             emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
3823             emit_orrshl(sh,HOST_TEMPREG,tl);
3824             emit_andimm(shift,31,HOST_TEMPREG);
3825             emit_testimm(shift,32);
3826             emit_shr(sh,HOST_TEMPREG,th);
3827             emit_cmovne_reg(th,tl);
3828             if(real_th>=0) emit_cmovne_imm(0,th);
3829           }
3830           if(opcode2[i]==0x17) // DSRAV
3831           {
3832             assert(th>=0);
3833             emit_shr(sl,HOST_TEMPREG,tl);
3834             emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
3835             if(real_th>=0) {
3836               assert(temp>=0);
3837               emit_sarimm(th,31,temp);
3838             }
3839             emit_orrshl(sh,HOST_TEMPREG,tl);
3840             emit_andimm(shift,31,HOST_TEMPREG);
3841             emit_testimm(shift,32);
3842             emit_sar(sh,HOST_TEMPREG,th);
3843             emit_cmovne_reg(th,tl);
3844             if(real_th>=0) emit_cmovne_reg(temp,th);
3845           }
3846         }
3847       }
3848     }
3849   }
3850 }
3851
3852 #ifdef PCSX
3853 static void speculate_mov(int rs,int rt)
3854 {
3855   if(rt!=0) {
3856     smrv_strong_next|=1<<rt;
3857     smrv[rt]=smrv[rs];
3858   }
3859 }
3860
3861 static void speculate_mov_weak(int rs,int rt)
3862 {
3863   if(rt!=0) {
3864     smrv_weak_next|=1<<rt;
3865     smrv[rt]=smrv[rs];
3866   }
3867 }
3868
3869 static void speculate_register_values(int i)
3870 {
3871   if(i==0) {
3872     memcpy(smrv,psxRegs.GPR.r,sizeof(smrv));
3873     // gp,sp are likely to stay the same throughout the block
3874     smrv_strong_next=(1<<28)|(1<<29)|(1<<30);
3875     smrv_weak_next=~smrv_strong_next;
3876     //printf(" llr %08x\n", smrv[4]);
3877   }
3878   smrv_strong=smrv_strong_next;
3879   smrv_weak=smrv_weak_next;
3880   switch(itype[i]) {
3881     case ALU:
3882       if     ((smrv_strong>>rs1[i])&1) speculate_mov(rs1[i],rt1[i]);
3883       else if((smrv_strong>>rs2[i])&1) speculate_mov(rs2[i],rt1[i]);
3884       else if((smrv_weak>>rs1[i])&1) speculate_mov_weak(rs1[i],rt1[i]);
3885       else if((smrv_weak>>rs2[i])&1) speculate_mov_weak(rs2[i],rt1[i]);
3886       else {
3887         smrv_strong_next&=~(1<<rt1[i]);
3888         smrv_weak_next&=~(1<<rt1[i]);
3889       }
3890       break;
3891     case SHIFTIMM:
3892       smrv_strong_next&=~(1<<rt1[i]);
3893       smrv_weak_next&=~(1<<rt1[i]);
3894       // fallthrough
3895     case IMM16:
3896       if(rt1[i]&&is_const(&regs[i],rt1[i])) {
3897         int value,hr=get_reg(regs[i].regmap,rt1[i]);
3898         if(hr>=0) {
3899           if(get_final_value(hr,i,&value))
3900                smrv[rt1[i]]=value;
3901           else smrv[rt1[i]]=constmap[i][hr];
3902           smrv_strong_next|=1<<rt1[i];
3903         }
3904       }
3905       else {
3906         if     ((smrv_strong>>rs1[i])&1) speculate_mov(rs1[i],rt1[i]);
3907         else if((smrv_weak>>rs1[i])&1) speculate_mov_weak(rs1[i],rt1[i]);
3908       }
3909       break;
3910     case LOAD:
3911       if(start<0x2000&&(rt1[i]==26||(smrv[rt1[i]]>>24)==0xa0)) {
3912         // special case for BIOS
3913         smrv[rt1[i]]=0xa0000000;
3914         smrv_strong_next|=1<<rt1[i];
3915         break;
3916       }
3917       // fallthrough
3918     case SHIFT:
3919     case LOADLR:
3920     case MOV:
3921       smrv_strong_next&=~(1<<rt1[i]);
3922       smrv_weak_next&=~(1<<rt1[i]);
3923       break;
3924     case COP0:
3925     case COP2:
3926       if(opcode2[i]==0||opcode2[i]==2) { // MFC/CFC
3927         smrv_strong_next&=~(1<<rt1[i]);
3928         smrv_weak_next&=~(1<<rt1[i]);
3929       }
3930       break;
3931     case C2LS:
3932       if (opcode[i]==0x32) { // LWC2
3933         smrv_strong_next&=~(1<<rt1[i]);
3934         smrv_weak_next&=~(1<<rt1[i]);
3935       }
3936       break;
3937   }
3938 #if 0
3939   int r=4;
3940   printf("x %08x %08x %d %d c %08x %08x\n",smrv[r],start+i*4,
3941     ((smrv_strong>>r)&1),(smrv_weak>>r)&1,regs[i].isconst,regs[i].wasconst);
3942 #endif
3943 }
3944
3945 enum {
3946   MTYPE_8000 = 0,
3947   MTYPE_8020,
3948   MTYPE_0000,
3949   MTYPE_A000,
3950   MTYPE_1F80,
3951 };
3952
3953 static int get_ptr_mem_type(u_int a)
3954 {
3955   if(a < 0x00200000) {
3956     if(a<0x1000&&((start>>20)==0xbfc||(start>>24)==0xa0))
3957       // return wrong, must use memhandler for BIOS self-test to pass
3958       // 007 does similar stuff from a00 mirror, weird stuff
3959       return MTYPE_8000;
3960     return MTYPE_0000;
3961   }
3962   if(0x1f800000 <= a && a < 0x1f801000)
3963     return MTYPE_1F80;
3964   if(0x80200000 <= a && a < 0x80800000)
3965     return MTYPE_8020;
3966   if(0xa0000000 <= a && a < 0xa0200000)
3967     return MTYPE_A000;
3968   return MTYPE_8000;
3969 }
3970 #endif
3971
3972 static int emit_fastpath_cmp_jump(int i,int addr,int *addr_reg_override)
3973 {
3974   int jaddr,type=0;
3975
3976 #ifdef PCSX
3977   int mr=rs1[i];
3978   if(((smrv_strong|smrv_weak)>>mr)&1) {
3979     type=get_ptr_mem_type(smrv[mr]);
3980     //printf("set %08x @%08x r%d %d\n", smrv[mr], start+i*4, mr, type);
3981   }
3982   else {
3983     // use the mirror we are running on
3984     type=get_ptr_mem_type(start);
3985     //printf("set nospec   @%08x r%d %d\n", start+i*4, mr, type);
3986   }
3987
3988   if(type==MTYPE_8020) { // RAM 80200000+ mirror
3989     emit_andimm(addr,~0x00e00000,HOST_TEMPREG);
3990     addr=*addr_reg_override=HOST_TEMPREG;
3991     type=0;
3992   }
3993   else if(type==MTYPE_0000) { // RAM 0 mirror
3994     emit_orimm(addr,0x80000000,HOST_TEMPREG);
3995     addr=*addr_reg_override=HOST_TEMPREG;
3996     type=0;
3997   }
3998   else if(type==MTYPE_A000) { // RAM A mirror
3999     emit_andimm(addr,~0x20000000,HOST_TEMPREG);
4000     addr=*addr_reg_override=HOST_TEMPREG;
4001     type=0;
4002   }
4003   else if(type==MTYPE_1F80) { // scratchpad
4004     if (psxH == (void *)0x1f800000) {
4005       emit_addimm(addr,-0x1f800000,HOST_TEMPREG);
4006       emit_cmpimm(HOST_TEMPREG,0x1000);
4007       jaddr=(int)out;
4008       emit_jc(0);
4009     }
4010     else {
4011       // do usual RAM check, jump will go to the right handler
4012       type=0;
4013     }
4014   }
4015 #endif
4016
4017   if(type==0)
4018   {
4019     emit_cmpimm(addr,RAM_SIZE);
4020     jaddr=(int)out;
4021     #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
4022     // Hint to branch predictor that the branch is unlikely to be taken
4023     if(rs1[i]>=28)
4024       emit_jno_unlikely(0);
4025     else
4026     #endif
4027       emit_jno(0);
4028     if(ram_offset!=0) {
4029       emit_addimm(addr,ram_offset,HOST_TEMPREG);
4030       addr=*addr_reg_override=HOST_TEMPREG;
4031     }
4032   }
4033
4034   return jaddr;
4035 }
4036
4037 #define shift_assemble shift_assemble_arm
4038
4039 void loadlr_assemble_arm(int i,struct regstat *i_regs)
4040 {
4041   int s,th,tl,temp,temp2,addr,map=-1;
4042   int offset;
4043   int jaddr=0;
4044   int memtarget=0,c=0;
4045   int fastload_reg_override=0;
4046   u_int hr,reglist=0;
4047   th=get_reg(i_regs->regmap,rt1[i]|64);
4048   tl=get_reg(i_regs->regmap,rt1[i]);
4049   s=get_reg(i_regs->regmap,rs1[i]);
4050   temp=get_reg(i_regs->regmap,-1);
4051   temp2=get_reg(i_regs->regmap,FTEMP);
4052   addr=get_reg(i_regs->regmap,AGEN1+(i&1));
4053   assert(addr<0);
4054   offset=imm[i];
4055   for(hr=0;hr<HOST_REGS;hr++) {
4056     if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
4057   }
4058   reglist|=1<<temp;
4059   if(offset||s<0||c) addr=temp2;
4060   else addr=s;
4061   if(s>=0) {
4062     c=(i_regs->wasconst>>s)&1;
4063     if(c) {
4064       memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE;
4065       if(using_tlb&&((signed int)(constmap[i][s]+offset))>=(signed int)0xC0000000) memtarget=1;
4066     }
4067   }
4068   if(!using_tlb) {
4069     if(!c) {
4070       #ifdef RAM_OFFSET
4071       map=get_reg(i_regs->regmap,ROREG);
4072       if(map<0) emit_loadreg(ROREG,map=HOST_TEMPREG);
4073       #endif
4074       emit_shlimm(addr,3,temp);
4075       if (opcode[i]==0x22||opcode[i]==0x26) {
4076         emit_andimm(addr,0xFFFFFFFC,temp2); // LWL/LWR
4077       }else{
4078         emit_andimm(addr,0xFFFFFFF8,temp2); // LDL/LDR
4079       }
4080       jaddr=emit_fastpath_cmp_jump(i,temp2,&fastload_reg_override);
4081     }
4082     else {
4083       if(ram_offset&&memtarget) {
4084         emit_addimm(temp2,ram_offset,HOST_TEMPREG);
4085         fastload_reg_override=HOST_TEMPREG;
4086       }
4087       if (opcode[i]==0x22||opcode[i]==0x26) {
4088         emit_movimm(((constmap[i][s]+offset)<<3)&24,temp); // LWL/LWR
4089       }else{
4090         emit_movimm(((constmap[i][s]+offset)<<3)&56,temp); // LDL/LDR
4091       }
4092     }
4093   }else{ // using tlb
4094     int a;
4095     if(c) {
4096       a=-1;
4097     }else if (opcode[i]==0x22||opcode[i]==0x26) {
4098       a=0xFFFFFFFC; // LWL/LWR
4099     }else{
4100       a=0xFFFFFFF8; // LDL/LDR
4101     }
4102     map=get_reg(i_regs->regmap,TLREG);
4103     assert(map>=0);
4104     reglist&=~(1<<map);
4105     map=do_tlb_r(addr,temp2,map,0,a,c?-1:temp,c,constmap[i][s]+offset);
4106     if(c) {
4107       if (opcode[i]==0x22||opcode[i]==0x26) {
4108         emit_movimm(((constmap[i][s]+offset)<<3)&24,temp); // LWL/LWR
4109       }else{
4110         emit_movimm(((constmap[i][s]+offset)<<3)&56,temp); // LDL/LDR
4111       }
4112     }
4113     do_tlb_r_branch(map,c,constmap[i][s]+offset,&jaddr);
4114   }
4115   if (opcode[i]==0x22||opcode[i]==0x26) { // LWL/LWR
4116     if(!c||memtarget) {
4117       int a=temp2;
4118       if(fastload_reg_override) a=fastload_reg_override;
4119       //emit_readword_indexed((int)rdram-0x80000000,temp2,temp2);
4120       emit_readword_indexed_tlb(0,a,map,temp2);
4121       if(jaddr) add_stub(LOADW_STUB,jaddr,(int)out,i,temp2,(int)i_regs,ccadj[i],reglist);
4122     }
4123     else
4124       inline_readstub(LOADW_STUB,i,(constmap[i][s]+offset)&0xFFFFFFFC,i_regs->regmap,FTEMP,ccadj[i],reglist);
4125     if(rt1[i]) {
4126       assert(tl>=0);
4127       emit_andimm(temp,24,temp);
4128 #ifdef BIG_ENDIAN_MIPS
4129       if (opcode[i]==0x26) // LWR
4130 #else
4131       if (opcode[i]==0x22) // LWL
4132 #endif
4133         emit_xorimm(temp,24,temp);
4134       emit_movimm(-1,HOST_TEMPREG);
4135       if (opcode[i]==0x26) {
4136         emit_shr(temp2,temp,temp2);
4137         emit_bic_lsr(tl,HOST_TEMPREG,temp,tl);
4138       }else{
4139         emit_shl(temp2,temp,temp2);
4140         emit_bic_lsl(tl,HOST_TEMPREG,temp,tl);
4141       }
4142       emit_or(temp2,tl,tl);
4143     }
4144     //emit_storereg(rt1[i],tl); // DEBUG
4145   }
4146   if (opcode[i]==0x1A||opcode[i]==0x1B) { // LDL/LDR
4147     // FIXME: little endian, fastload_reg_override
4148     int temp2h=get_reg(i_regs->regmap,FTEMP|64);
4149     if(!c||memtarget) {
4150       //if(th>=0) emit_readword_indexed((int)rdram-0x80000000,temp2,temp2h);
4151       //emit_readword_indexed((int)rdram-0x7FFFFFFC,temp2,temp2);
4152       emit_readdword_indexed_tlb(0,temp2,map,temp2h,temp2);
4153       if(jaddr) add_stub(LOADD_STUB,jaddr,(int)out,i,temp2,(int)i_regs,ccadj[i],reglist);
4154     }
4155     else
4156       inline_readstub(LOADD_STUB,i,(constmap[i][s]+offset)&0xFFFFFFF8,i_regs->regmap,FTEMP,ccadj[i],reglist);
4157     if(rt1[i]) {
4158       assert(th>=0);
4159       assert(tl>=0);
4160       emit_testimm(temp,32);
4161       emit_andimm(temp,24,temp);
4162       if (opcode[i]==0x1A) { // LDL
4163         emit_rsbimm(temp,32,HOST_TEMPREG);
4164         emit_shl(temp2h,temp,temp2h);
4165         emit_orrshr(temp2,HOST_TEMPREG,temp2h);
4166         emit_movimm(-1,HOST_TEMPREG);
4167         emit_shl(temp2,temp,temp2);
4168         emit_cmove_reg(temp2h,th);
4169         emit_biceq_lsl(tl,HOST_TEMPREG,temp,tl);
4170         emit_bicne_lsl(th,HOST_TEMPREG,temp,th);
4171         emit_orreq(temp2,tl,tl);
4172         emit_orrne(temp2,th,th);
4173       }
4174       if (opcode[i]==0x1B) { // LDR
4175         emit_xorimm(temp,24,temp);
4176         emit_rsbimm(temp,32,HOST_TEMPREG);
4177         emit_shr(temp2,temp,temp2);
4178         emit_orrshl(temp2h,HOST_TEMPREG,temp2);
4179         emit_movimm(-1,HOST_TEMPREG);
4180         emit_shr(temp2h,temp,temp2h);
4181         emit_cmovne_reg(temp2,tl);
4182         emit_bicne_lsr(th,HOST_TEMPREG,temp,th);
4183         emit_biceq_lsr(tl,HOST_TEMPREG,temp,tl);
4184         emit_orrne(temp2h,th,th);
4185         emit_orreq(temp2h,tl,tl);
4186       }
4187     }
4188   }
4189 }
4190 #define loadlr_assemble loadlr_assemble_arm
4191
4192 void cop0_assemble(int i,struct regstat *i_regs)
4193 {
4194   if(opcode2[i]==0) // MFC0
4195   {
4196     signed char t=get_reg(i_regs->regmap,rt1[i]);
4197     char copr=(source[i]>>11)&0x1f;
4198     //assert(t>=0); // Why does this happen?  OOT is weird
4199     if(t>=0&&rt1[i]!=0) {
4200 #ifdef MUPEN64
4201       emit_addimm(FP,(int)&fake_pc-(int)&dynarec_local,0);
4202       emit_movimm((source[i]>>11)&0x1f,1);
4203       emit_writeword(0,(int)&PC);
4204       emit_writebyte(1,(int)&(fake_pc.f.r.nrd));
4205       if(copr==9) {
4206         emit_readword((int)&last_count,ECX);
4207         emit_loadreg(CCREG,HOST_CCREG); // TODO: do proper reg alloc
4208         emit_add(HOST_CCREG,ECX,HOST_CCREG);
4209         emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG);
4210         emit_writeword(HOST_CCREG,(int)&Count);
4211       }
4212       emit_call((int)MFC0);
4213       emit_readword((int)&readmem_dword,t);
4214 #else
4215       emit_readword((int)&reg_cop0+copr*4,t);
4216 #endif
4217     }
4218   }
4219   else if(opcode2[i]==4) // MTC0
4220   {
4221     signed char s=get_reg(i_regs->regmap,rs1[i]);
4222     char copr=(source[i]>>11)&0x1f;
4223     assert(s>=0);
4224 #ifdef MUPEN64
4225     emit_writeword(s,(int)&readmem_dword);
4226     wb_register(rs1[i],i_regs->regmap,i_regs->dirty,i_regs->is32);
4227     emit_addimm(FP,(int)&fake_pc-(int)&dynarec_local,0);
4228     emit_movimm((source[i]>>11)&0x1f,1);
4229     emit_writeword(0,(int)&PC);
4230     emit_writebyte(1,(int)&(fake_pc.f.r.nrd));
4231 #else
4232     wb_register(rs1[i],i_regs->regmap,i_regs->dirty,i_regs->is32);
4233 #endif
4234     if(copr==9||copr==11||copr==12||copr==13) {
4235       emit_readword((int)&last_count,HOST_TEMPREG);
4236       emit_loadreg(CCREG,HOST_CCREG); // TODO: do proper reg alloc
4237       emit_add(HOST_CCREG,HOST_TEMPREG,HOST_CCREG);
4238       emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG);
4239       emit_writeword(HOST_CCREG,(int)&Count);
4240     }
4241     // What a mess.  The status register (12) can enable interrupts,
4242     // so needs a special case to handle a pending interrupt.
4243     // The interrupt must be taken immediately, because a subsequent
4244     // instruction might disable interrupts again.
4245     if(copr==12||copr==13) {
4246 #ifdef PCSX
4247       if (is_delayslot) {
4248         // burn cycles to cause cc_interrupt, which will
4249         // reschedule next_interupt. Relies on CCREG from above.
4250         assem_debug("MTC0 DS %d\n", copr);
4251         emit_writeword(HOST_CCREG,(int)&last_count);
4252         emit_movimm(0,HOST_CCREG);
4253         emit_storereg(CCREG,HOST_CCREG);
4254         emit_loadreg(rs1[i],1);
4255         emit_movimm(copr,0);
4256         emit_call((int)pcsx_mtc0_ds);
4257         emit_loadreg(rs1[i],s);
4258         return;
4259       }
4260 #endif
4261       emit_movimm(start+i*4+4,HOST_TEMPREG);
4262       emit_writeword(HOST_TEMPREG,(int)&pcaddr);
4263       emit_movimm(0,HOST_TEMPREG);
4264       emit_writeword(HOST_TEMPREG,(int)&pending_exception);
4265     }
4266     //else if(copr==12&&is_delayslot) emit_call((int)MTC0_R12);
4267     //else
4268 #ifdef PCSX
4269     if(s==HOST_CCREG)
4270       emit_loadreg(rs1[i],1);
4271     else if(s!=1)
4272       emit_mov(s,1);
4273     emit_movimm(copr,0);
4274     emit_call((int)pcsx_mtc0);
4275 #else
4276     emit_call((int)MTC0);
4277 #endif
4278     if(copr==9||copr==11||copr==12||copr==13) {
4279       emit_readword((int)&Count,HOST_CCREG);
4280       emit_readword((int)&next_interupt,HOST_TEMPREG);
4281       emit_addimm(HOST_CCREG,-CLOCK_ADJUST(ccadj[i]),HOST_CCREG);
4282       emit_sub(HOST_CCREG,HOST_TEMPREG,HOST_CCREG);
4283       emit_writeword(HOST_TEMPREG,(int)&last_count);
4284       emit_storereg(CCREG,HOST_CCREG);
4285     }
4286     if(copr==12||copr==13) {
4287       assert(!is_delayslot);
4288       emit_readword((int)&pending_exception,14);
4289       emit_test(14,14);
4290       emit_jne((int)&do_interrupt);
4291     }
4292     emit_loadreg(rs1[i],s);
4293     if(get_reg(i_regs->regmap,rs1[i]|64)>=0)
4294       emit_loadreg(rs1[i]|64,get_reg(i_regs->regmap,rs1[i]|64));
4295     cop1_usable=0;
4296   }
4297   else
4298   {
4299     assert(opcode2[i]==0x10);
4300 #ifndef DISABLE_TLB
4301     if((source[i]&0x3f)==0x01) // TLBR
4302       emit_call((int)TLBR);
4303     if((source[i]&0x3f)==0x02) // TLBWI
4304       emit_call((int)TLBWI_new);
4305     if((source[i]&0x3f)==0x06) { // TLBWR
4306       // The TLB entry written by TLBWR is dependent on the count,
4307       // so update the cycle count
4308       emit_readword((int)&last_count,ECX);
4309       if(i_regs->regmap[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
4310       emit_add(HOST_CCREG,ECX,HOST_CCREG);
4311       emit_addimm(HOST_CCREG,CLOCK_ADJUST(ccadj[i]),HOST_CCREG);
4312       emit_writeword(HOST_CCREG,(int)&Count);
4313       emit_call((int)TLBWR_new);
4314     }
4315     if((source[i]&0x3f)==0x08) // TLBP
4316       emit_call((int)TLBP);
4317 #endif
4318 #ifdef PCSX
4319     if((source[i]&0x3f)==0x10) // RFE
4320     {
4321       emit_readword((int)&Status,0);
4322       emit_andimm(0,0x3c,1);
4323       emit_andimm(0,~0xf,0);
4324       emit_orrshr_imm(1,2,0);
4325       emit_writeword(0,(int)&Status);
4326     }
4327 #else
4328     if((source[i]&0x3f)==0x18) // ERET
4329     {
4330       int count=ccadj[i];
4331       if(i_regs->regmap[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
4332       emit_addimm(HOST_CCREG,CLOCK_ADJUST(count),HOST_CCREG); // TODO: Should there be an extra cycle here?
4333       emit_jmp((int)jump_eret);
4334     }
4335 #endif
4336   }
4337 }
4338
4339 static void cop2_get_dreg(u_int copr,signed char tl,signed char temp)
4340 {
4341   switch (copr) {
4342     case 1:
4343     case 3:
4344     case 5:
4345     case 8:
4346     case 9:
4347     case 10:
4348     case 11:
4349       emit_readword((int)&reg_cop2d[copr],tl);
4350       emit_signextend16(tl,tl);
4351       emit_writeword(tl,(int)&reg_cop2d[copr]); // hmh
4352       break;
4353     case 7:
4354     case 16:
4355     case 17:
4356     case 18:
4357     case 19:
4358       emit_readword((int)&reg_cop2d[copr],tl);
4359       emit_andimm(tl,0xffff,tl);
4360       emit_writeword(tl,(int)&reg_cop2d[copr]);
4361       break;
4362     case 15:
4363       emit_readword((int)&reg_cop2d[14],tl); // SXY2
4364       emit_writeword(tl,(int)&reg_cop2d[copr]);
4365       break;
4366     case 28:
4367     case 29:
4368       emit_readword((int)&reg_cop2d[9],temp);
4369       emit_testimm(temp,0x8000); // do we need this?
4370       emit_andimm(temp,0xf80,temp);
4371       emit_andne_imm(temp,0,temp);
4372       emit_shrimm(temp,7,tl);
4373       emit_readword((int)&reg_cop2d[10],temp);
4374       emit_testimm(temp,0x8000);
4375       emit_andimm(temp,0xf80,temp);
4376       emit_andne_imm(temp,0,temp);
4377       emit_orrshr_imm(temp,2,tl);
4378       emit_readword((int)&reg_cop2d[11],temp);
4379       emit_testimm(temp,0x8000);
4380       emit_andimm(temp,0xf80,temp);
4381       emit_andne_imm(temp,0,temp);
4382       emit_orrshl_imm(temp,3,tl);
4383       emit_writeword(tl,(int)&reg_cop2d[copr]);
4384       break;
4385     default:
4386       emit_readword((int)&reg_cop2d[copr],tl);
4387       break;
4388   }
4389 }
4390
4391 static void cop2_put_dreg(u_int copr,signed char sl,signed char temp)
4392 {
4393   switch (copr) {
4394     case 15:
4395       emit_readword((int)&reg_cop2d[13],temp);  // SXY1
4396       emit_writeword(sl,(int)&reg_cop2d[copr]);
4397       emit_writeword(temp,(int)&reg_cop2d[12]); // SXY0
4398       emit_readword((int)&reg_cop2d[14],temp);  // SXY2
4399       emit_writeword(sl,(int)&reg_cop2d[14]);
4400       emit_writeword(temp,(int)&reg_cop2d[13]); // SXY1
4401       break;
4402     case 28:
4403       emit_andimm(sl,0x001f,temp);
4404       emit_shlimm(temp,7,temp);
4405       emit_writeword(temp,(int)&reg_cop2d[9]);
4406       emit_andimm(sl,0x03e0,temp);
4407       emit_shlimm(temp,2,temp);
4408       emit_writeword(temp,(int)&reg_cop2d[10]);
4409       emit_andimm(sl,0x7c00,temp);
4410       emit_shrimm(temp,3,temp);
4411       emit_writeword(temp,(int)&reg_cop2d[11]);
4412       emit_writeword(sl,(int)&reg_cop2d[28]);
4413       break;
4414     case 30:
4415       emit_movs(sl,temp);
4416       emit_mvnmi(temp,temp);
4417 #ifdef HAVE_ARMV5
4418       emit_clz(temp,temp);
4419 #else
4420       emit_movs(temp,HOST_TEMPREG);
4421       emit_movimm(0,temp);
4422       emit_jeq((int)out+4*4);
4423       emit_addpl_imm(temp,1,temp);
4424       emit_lslpls_imm(HOST_TEMPREG,1,HOST_TEMPREG);
4425       emit_jns((int)out-2*4);
4426 #endif
4427       emit_writeword(sl,(int)&reg_cop2d[30]);
4428       emit_writeword(temp,(int)&reg_cop2d[31]);
4429       break;
4430     case 31:
4431       break;
4432     default:
4433       emit_writeword(sl,(int)&reg_cop2d[copr]);
4434       break;
4435   }
4436 }
4437
4438 void cop2_assemble(int i,struct regstat *i_regs)
4439 {
4440   u_int copr=(source[i]>>11)&0x1f;
4441   signed char temp=get_reg(i_regs->regmap,-1);
4442   if (opcode2[i]==0) { // MFC2
4443     signed char tl=get_reg(i_regs->regmap,rt1[i]);
4444     if(tl>=0&&rt1[i]!=0)
4445       cop2_get_dreg(copr,tl,temp);
4446   }
4447   else if (opcode2[i]==4) { // MTC2
4448     signed char sl=get_reg(i_regs->regmap,rs1[i]);
4449     cop2_put_dreg(copr,sl,temp);
4450   }
4451   else if (opcode2[i]==2) // CFC2
4452   {
4453     signed char tl=get_reg(i_regs->regmap,rt1[i]);
4454     if(tl>=0&&rt1[i]!=0)
4455       emit_readword((int)&reg_cop2c[copr],tl);
4456   }
4457   else if (opcode2[i]==6) // CTC2
4458   {
4459     signed char sl=get_reg(i_regs->regmap,rs1[i]);
4460     switch(copr) {
4461       case 4:
4462       case 12:
4463       case 20:
4464       case 26:
4465       case 27:
4466       case 29:
4467       case 30:
4468         emit_signextend16(sl,temp);
4469         break;
4470       case 31:
4471         //value = value & 0x7ffff000;
4472         //if (value & 0x7f87e000) value |= 0x80000000;
4473         emit_shrimm(sl,12,temp);
4474         emit_shlimm(temp,12,temp);
4475         emit_testimm(temp,0x7f000000);
4476         emit_testeqimm(temp,0x00870000);
4477         emit_testeqimm(temp,0x0000e000);
4478         emit_orrne_imm(temp,0x80000000,temp);
4479         break;
4480       default:
4481         temp=sl;
4482         break;
4483     }
4484     emit_writeword(temp,(int)&reg_cop2c[copr]);
4485     assert(sl>=0);
4486   }
4487 }
4488
4489 static void c2op_prologue(u_int op,u_int reglist)
4490 {
4491   save_regs_all(reglist);
4492 #ifdef PCNT
4493   emit_movimm(op,0);
4494   emit_call((int)pcnt_gte_start);
4495 #endif
4496   emit_addimm(FP,(int)&psxRegs.CP2D.r[0]-(int)&dynarec_local,0); // cop2 regs
4497 }
4498
4499 static void c2op_epilogue(u_int op,u_int reglist)
4500 {
4501 #ifdef PCNT
4502   emit_movimm(op,0);
4503   emit_call((int)pcnt_gte_end);
4504 #endif
4505   restore_regs_all(reglist);
4506 }
4507
4508 static void c2op_call_MACtoIR(int lm,int need_flags)
4509 {
4510   if(need_flags)
4511     emit_call((int)(lm?gteMACtoIR_lm1:gteMACtoIR_lm0));
4512   else
4513     emit_call((int)(lm?gteMACtoIR_lm1_nf:gteMACtoIR_lm0_nf));
4514 }
4515
4516 static void c2op_call_rgb_func(void *func,int lm,int need_ir,int need_flags)
4517 {
4518   emit_call((int)func);
4519   // func is C code and trashes r0
4520   emit_addimm(FP,(int)&psxRegs.CP2D.r[0]-(int)&dynarec_local,0);
4521   if(need_flags||need_ir)
4522     c2op_call_MACtoIR(lm,need_flags);
4523   emit_call((int)(need_flags?gteMACtoRGB:gteMACtoRGB_nf));
4524 }
4525
4526 static void c2op_assemble(int i,struct regstat *i_regs)
4527 {
4528   signed char temp=get_reg(i_regs->regmap,-1);
4529   u_int c2op=source[i]&0x3f;
4530   u_int hr,reglist_full=0,reglist;
4531   int need_flags,need_ir;
4532   for(hr=0;hr<HOST_REGS;hr++) {
4533     if(i_regs->regmap[hr]>=0) reglist_full|=1<<hr;
4534   }
4535   reglist=reglist_full&CALLER_SAVE_REGS;
4536
4537   if (gte_handlers[c2op]!=NULL) {
4538     need_flags=!(gte_unneeded[i+1]>>63); // +1 because of how liveness detection works
4539     need_ir=(gte_unneeded[i+1]&0xe00)!=0xe00;
4540     assem_debug("gte op %08x, unneeded %016llx, need_flags %d, need_ir %d\n",
4541       source[i],gte_unneeded[i+1],need_flags,need_ir);
4542     if(new_dynarec_hacks&NDHACK_GTE_NO_FLAGS)
4543       need_flags=0;
4544     int shift = (source[i] >> 19) & 1;
4545     int lm = (source[i] >> 10) & 1;
4546     switch(c2op) {
4547 #ifndef DRC_DBG
4548       case GTE_MVMVA: {
4549 #ifdef HAVE_ARMV5
4550         int v  = (source[i] >> 15) & 3;
4551         int cv = (source[i] >> 13) & 3;
4552         int mx = (source[i] >> 17) & 3;
4553         reglist=reglist_full&(CALLER_SAVE_REGS|0xf0); // +{r4-r7}
4554         c2op_prologue(c2op,reglist);
4555         /* r4,r5 = VXYZ(v) packed; r6 = &MX11(mx); r7 = &CV1(cv) */
4556         if(v<3)
4557           emit_ldrd(v*8,0,4);
4558         else {
4559           emit_movzwl_indexed(9*4,0,4);  // gteIR
4560           emit_movzwl_indexed(10*4,0,6);
4561           emit_movzwl_indexed(11*4,0,5);
4562           emit_orrshl_imm(6,16,4);
4563         }
4564         if(mx<3)
4565           emit_addimm(0,32*4+mx*8*4,6);
4566         else
4567           emit_readword((int)&zeromem_ptr,6);
4568         if(cv<3)
4569           emit_addimm(0,32*4+(cv*8+5)*4,7);
4570         else
4571           emit_readword((int)&zeromem_ptr,7);
4572 #ifdef __ARM_NEON__
4573         emit_movimm(source[i],1); // opcode
4574         emit_call((int)gteMVMVA_part_neon);
4575         if(need_flags) {
4576           emit_movimm(lm,1);
4577           emit_call((int)gteMACtoIR_flags_neon);
4578         }
4579 #else
4580         if(cv==3&&shift)
4581           emit_call((int)gteMVMVA_part_cv3sh12_arm);
4582         else {
4583           emit_movimm(shift,1);
4584           emit_call((int)(need_flags?gteMVMVA_part_arm:gteMVMVA_part_nf_arm));
4585         }
4586         if(need_flags||need_ir)
4587           c2op_call_MACtoIR(lm,need_flags);
4588 #endif
4589 #else /* if not HAVE_ARMV5 */
4590         c2op_prologue(c2op,reglist);
4591         emit_movimm(source[i],1); // opcode
4592         emit_writeword(1,(int)&psxRegs.code);
4593         emit_call((int)(need_flags?gte_handlers[c2op]:gte_handlers_nf[c2op]));
4594 #endif
4595         break;
4596       }
4597       case GTE_OP:
4598         c2op_prologue(c2op,reglist);
4599         emit_call((int)(shift?gteOP_part_shift:gteOP_part_noshift));
4600         if(need_flags||need_ir) {
4601           emit_addimm(FP,(int)&psxRegs.CP2D.r[0]-(int)&dynarec_local,0);
4602           c2op_call_MACtoIR(lm,need_flags);
4603         }
4604         break;
4605       case GTE_DPCS:
4606         c2op_prologue(c2op,reglist);
4607         c2op_call_rgb_func(shift?gteDPCS_part_shift:gteDPCS_part_noshift,lm,need_ir,need_flags);
4608         break;
4609       case GTE_INTPL:
4610         c2op_prologue(c2op,reglist);
4611         c2op_call_rgb_func(shift?gteINTPL_part_shift:gteINTPL_part_noshift,lm,need_ir,need_flags);
4612         break;
4613       case GTE_SQR:
4614         c2op_prologue(c2op,reglist);
4615         emit_call((int)(shift?gteSQR_part_shift:gteSQR_part_noshift));
4616         if(need_flags||need_ir) {
4617           emit_addimm(FP,(int)&psxRegs.CP2D.r[0]-(int)&dynarec_local,0);
4618           c2op_call_MACtoIR(lm,need_flags);
4619         }
4620         break;
4621       case GTE_DCPL:
4622         c2op_prologue(c2op,reglist);
4623         c2op_call_rgb_func(gteDCPL_part,lm,need_ir,need_flags);
4624         break;
4625       case GTE_GPF:
4626         c2op_prologue(c2op,reglist);
4627         c2op_call_rgb_func(shift?gteGPF_part_shift:gteGPF_part_noshift,lm,need_ir,need_flags);
4628         break;
4629       case GTE_GPL:
4630         c2op_prologue(c2op,reglist);
4631         c2op_call_rgb_func(shift?gteGPL_part_shift:gteGPL_part_noshift,lm,need_ir,need_flags);
4632         break;
4633 #endif
4634       default:
4635         c2op_prologue(c2op,reglist);
4636 #ifdef DRC_DBG
4637         emit_movimm(source[i],1); // opcode
4638         emit_writeword(1,(int)&psxRegs.code);
4639 #endif
4640         emit_call((int)(need_flags?gte_handlers[c2op]:gte_handlers_nf[c2op]));
4641         break;
4642     }
4643     c2op_epilogue(c2op,reglist);
4644   }
4645 }
4646
4647 void cop1_unusable(int i,struct regstat *i_regs)
4648 {
4649   // XXX: should just just do the exception instead
4650   if(!cop1_usable) {
4651     int jaddr=(int)out;
4652     emit_jmp(0);
4653     add_stub(FP_STUB,jaddr,(int)out,i,0,(int)i_regs,is_delayslot,0);
4654     cop1_usable=1;
4655   }
4656 }
4657
4658 void cop1_assemble(int i,struct regstat *i_regs)
4659 {
4660 #ifndef DISABLE_COP1
4661   // Check cop1 unusable
4662   if(!cop1_usable) {
4663     signed char rs=get_reg(i_regs->regmap,CSREG);
4664     assert(rs>=0);
4665     emit_testimm(rs,0x20000000);
4666     int jaddr=(int)out;
4667     emit_jeq(0);
4668     add_stub(FP_STUB,jaddr,(int)out,i,rs,(int)i_regs,is_delayslot,0);
4669     cop1_usable=1;
4670   }
4671   if (opcode2[i]==0) { // MFC1
4672     signed char tl=get_reg(i_regs->regmap,rt1[i]);
4673     if(tl>=0) {
4674       emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],tl);
4675       emit_readword_indexed(0,tl,tl);
4676     }
4677   }
4678   else if (opcode2[i]==1) { // DMFC1
4679     signed char tl=get_reg(i_regs->regmap,rt1[i]);
4680     signed char th=get_reg(i_regs->regmap,rt1[i]|64);
4681     if(tl>=0) {
4682       emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],tl);
4683       if(th>=0) emit_readword_indexed(4,tl,th);
4684       emit_readword_indexed(0,tl,tl);
4685     }
4686   }
4687   else if (opcode2[i]==4) { // MTC1
4688     signed char sl=get_reg(i_regs->regmap,rs1[i]);
4689     signed char temp=get_reg(i_regs->regmap,-1);
4690     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
4691     emit_writeword_indexed(sl,0,temp);
4692   }
4693   else if (opcode2[i]==5) { // DMTC1
4694     signed char sl=get_reg(i_regs->regmap,rs1[i]);
4695     signed char sh=rs1[i]>0?get_reg(i_regs->regmap,rs1[i]|64):sl;
4696     signed char temp=get_reg(i_regs->regmap,-1);
4697     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],temp);
4698     emit_writeword_indexed(sh,4,temp);
4699     emit_writeword_indexed(sl,0,temp);
4700   }
4701   else if (opcode2[i]==2) // CFC1
4702   {
4703     signed char tl=get_reg(i_regs->regmap,rt1[i]);
4704     if(tl>=0) {
4705       u_int copr=(source[i]>>11)&0x1f;
4706       if(copr==0) emit_readword((int)&FCR0,tl);
4707       if(copr==31) emit_readword((int)&FCR31,tl);
4708     }
4709   }
4710   else if (opcode2[i]==6) // CTC1
4711   {
4712     signed char sl=get_reg(i_regs->regmap,rs1[i]);
4713     u_int copr=(source[i]>>11)&0x1f;
4714     assert(sl>=0);
4715     if(copr==31)
4716     {
4717       emit_writeword(sl,(int)&FCR31);
4718       // Set the rounding mode
4719       //FIXME
4720       //char temp=get_reg(i_regs->regmap,-1);
4721       //emit_andimm(sl,3,temp);
4722       //emit_fldcw_indexed((int)&rounding_modes,temp);
4723     }
4724   }
4725 #else
4726   cop1_unusable(i, i_regs);
4727 #endif
4728 }
4729
4730 void fconv_assemble_arm(int i,struct regstat *i_regs)
4731 {
4732 #ifndef DISABLE_COP1
4733   signed char temp=get_reg(i_regs->regmap,-1);
4734   assert(temp>=0);
4735   // Check cop1 unusable
4736   if(!cop1_usable) {
4737     signed char rs=get_reg(i_regs->regmap,CSREG);
4738     assert(rs>=0);
4739     emit_testimm(rs,0x20000000);
4740     int jaddr=(int)out;
4741     emit_jeq(0);
4742     add_stub(FP_STUB,jaddr,(int)out,i,rs,(int)i_regs,is_delayslot,0);
4743     cop1_usable=1;
4744   }
4745   
4746   #if(defined(__VFP_FP__) && !defined(__SOFTFP__)) 
4747   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0d) { // trunc_w_s
4748     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
4749     emit_flds(temp,15);
4750     emit_ftosizs(15,15); // float->int, truncate
4751     if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f))
4752       emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],temp);
4753     emit_fsts(15,temp);
4754     return;
4755   }
4756   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0d) { // trunc_w_d
4757     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],temp);
4758     emit_vldr(temp,7);
4759     emit_ftosizd(7,13); // double->int, truncate
4760     emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],temp);
4761     emit_fsts(13,temp);
4762     return;
4763   }
4764   
4765   if(opcode2[i]==0x14&&(source[i]&0x3f)==0x20) { // cvt_s_w
4766     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
4767     emit_flds(temp,13);
4768     if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f))
4769       emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],temp);
4770     emit_fsitos(13,15);
4771     emit_fsts(15,temp);
4772     return;
4773   }
4774   if(opcode2[i]==0x14&&(source[i]&0x3f)==0x21) { // cvt_d_w
4775     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
4776     emit_flds(temp,13);
4777     emit_readword((int)&reg_cop1_double[(source[i]>>6)&0x1f],temp);
4778     emit_fsitod(13,7);
4779     emit_vstr(7,temp);
4780     return;
4781   }
4782   
4783   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x21) { // cvt_d_s
4784     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
4785     emit_flds(temp,13);
4786     emit_readword((int)&reg_cop1_double[(source[i]>>6)&0x1f],temp);
4787     emit_fcvtds(13,7);
4788     emit_vstr(7,temp);
4789     return;
4790   }
4791   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x20) { // cvt_s_d
4792     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],temp);
4793     emit_vldr(temp,7);
4794     emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],temp);
4795     emit_fcvtsd(7,13);
4796     emit_fsts(13,temp);
4797     return;
4798   }
4799   #endif
4800   
4801   // C emulation code
4802   
4803   u_int hr,reglist=0;
4804   for(hr=0;hr<HOST_REGS;hr++) {
4805     if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
4806   }
4807   save_regs(reglist);
4808   
4809   if(opcode2[i]==0x14&&(source[i]&0x3f)==0x20) {
4810     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4811     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4812     emit_call((int)cvt_s_w);
4813   }
4814   if(opcode2[i]==0x14&&(source[i]&0x3f)==0x21) {
4815     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4816     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4817     emit_call((int)cvt_d_w);
4818   }
4819   if(opcode2[i]==0x15&&(source[i]&0x3f)==0x20) {
4820     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4821     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4822     emit_call((int)cvt_s_l);
4823   }
4824   if(opcode2[i]==0x15&&(source[i]&0x3f)==0x21) {
4825     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4826     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4827     emit_call((int)cvt_d_l);
4828   }
4829   
4830   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x21) {
4831     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4832     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4833     emit_call((int)cvt_d_s);
4834   }
4835   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x24) {
4836     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4837     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4838     emit_call((int)cvt_w_s);
4839   }
4840   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x25) {
4841     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4842     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4843     emit_call((int)cvt_l_s);
4844   }
4845   
4846   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x20) {
4847     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4848     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4849     emit_call((int)cvt_s_d);
4850   }
4851   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x24) {
4852     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4853     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4854     emit_call((int)cvt_w_d);
4855   }
4856   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x25) {
4857     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4858     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4859     emit_call((int)cvt_l_d);
4860   }
4861   
4862   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x08) {
4863     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4864     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4865     emit_call((int)round_l_s);
4866   }
4867   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x09) {
4868     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4869     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4870     emit_call((int)trunc_l_s);
4871   }
4872   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0a) {
4873     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4874     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4875     emit_call((int)ceil_l_s);
4876   }
4877   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0b) {
4878     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4879     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4880     emit_call((int)floor_l_s);
4881   }
4882   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0c) {
4883     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4884     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4885     emit_call((int)round_w_s);
4886   }
4887   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0d) {
4888     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4889     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4890     emit_call((int)trunc_w_s);
4891   }
4892   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0e) {
4893     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4894     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4895     emit_call((int)ceil_w_s);
4896   }
4897   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0f) {
4898     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
4899     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4900     emit_call((int)floor_w_s);
4901   }
4902   
4903   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x08) {
4904     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4905     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4906     emit_call((int)round_l_d);
4907   }
4908   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x09) {
4909     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4910     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4911     emit_call((int)trunc_l_d);
4912   }
4913   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0a) {
4914     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4915     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4916     emit_call((int)ceil_l_d);
4917   }
4918   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0b) {
4919     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4920     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
4921     emit_call((int)floor_l_d);
4922   }
4923   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0c) {
4924     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4925     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4926     emit_call((int)round_w_d);
4927   }
4928   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0d) {
4929     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4930     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4931     emit_call((int)trunc_w_d);
4932   }
4933   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0e) {
4934     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4935     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4936     emit_call((int)ceil_w_d);
4937   }
4938   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0f) {
4939     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
4940     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
4941     emit_call((int)floor_w_d);
4942   }
4943   
4944   restore_regs(reglist);
4945 #else
4946   cop1_unusable(i, i_regs);
4947 #endif
4948 }
4949 #define fconv_assemble fconv_assemble_arm
4950
4951 void fcomp_assemble(int i,struct regstat *i_regs)
4952 {
4953 #ifndef DISABLE_COP1
4954   signed char fs=get_reg(i_regs->regmap,FSREG);
4955   signed char temp=get_reg(i_regs->regmap,-1);
4956   assert(temp>=0);
4957   // Check cop1 unusable
4958   if(!cop1_usable) {
4959     signed char cs=get_reg(i_regs->regmap,CSREG);
4960     assert(cs>=0);
4961     emit_testimm(cs,0x20000000);
4962     int jaddr=(int)out;
4963     emit_jeq(0);
4964     add_stub(FP_STUB,jaddr,(int)out,i,cs,(int)i_regs,is_delayslot,0);
4965     cop1_usable=1;
4966   }
4967   
4968   if((source[i]&0x3f)==0x30) {
4969     emit_andimm(fs,~0x800000,fs);
4970     return;
4971   }
4972   
4973   if((source[i]&0x3e)==0x38) {
4974     // sf/ngle - these should throw exceptions for NaNs
4975     emit_andimm(fs,~0x800000,fs);
4976     return;
4977   }
4978   
4979   #if(defined(__VFP_FP__) && !defined(__SOFTFP__)) 
4980   if(opcode2[i]==0x10) {
4981     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
4982     emit_readword((int)&reg_cop1_simple[(source[i]>>16)&0x1f],HOST_TEMPREG);
4983     emit_orimm(fs,0x800000,fs);
4984     emit_flds(temp,14);
4985     emit_flds(HOST_TEMPREG,15);
4986     emit_fcmps(14,15);
4987     emit_fmstat();
4988     if((source[i]&0x3f)==0x31) emit_bicvc_imm(fs,0x800000,fs); // c_un_s
4989     if((source[i]&0x3f)==0x32) emit_bicne_imm(fs,0x800000,fs); // c_eq_s
4990     if((source[i]&0x3f)==0x33) {emit_bicne_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ueq_s
4991     if((source[i]&0x3f)==0x34) emit_biccs_imm(fs,0x800000,fs); // c_olt_s
4992     if((source[i]&0x3f)==0x35) {emit_biccs_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ult_s 
4993     if((source[i]&0x3f)==0x36) emit_bichi_imm(fs,0x800000,fs); // c_ole_s
4994     if((source[i]&0x3f)==0x37) {emit_bichi_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ule_s
4995     if((source[i]&0x3f)==0x3a) emit_bicne_imm(fs,0x800000,fs); // c_seq_s
4996     if((source[i]&0x3f)==0x3b) emit_bicne_imm(fs,0x800000,fs); // c_ngl_s
4997     if((source[i]&0x3f)==0x3c) emit_biccs_imm(fs,0x800000,fs); // c_lt_s
4998     if((source[i]&0x3f)==0x3d) emit_biccs_imm(fs,0x800000,fs); // c_nge_s
4999     if((source[i]&0x3f)==0x3e) emit_bichi_imm(fs,0x800000,fs); // c_le_s
5000     if((source[i]&0x3f)==0x3f) emit_bichi_imm(fs,0x800000,fs); // c_ngt_s
5001     return;
5002   }
5003   if(opcode2[i]==0x11) {
5004     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],temp);
5005     emit_readword((int)&reg_cop1_double[(source[i]>>16)&0x1f],HOST_TEMPREG);
5006     emit_orimm(fs,0x800000,fs);
5007     emit_vldr(temp,6);
5008     emit_vldr(HOST_TEMPREG,7);
5009     emit_fcmpd(6,7);
5010     emit_fmstat();
5011     if((source[i]&0x3f)==0x31) emit_bicvc_imm(fs,0x800000,fs); // c_un_d
5012     if((source[i]&0x3f)==0x32) emit_bicne_imm(fs,0x800000,fs); // c_eq_d
5013     if((source[i]&0x3f)==0x33) {emit_bicne_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ueq_d
5014     if((source[i]&0x3f)==0x34) emit_biccs_imm(fs,0x800000,fs); // c_olt_d
5015     if((source[i]&0x3f)==0x35) {emit_biccs_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ult_d
5016     if((source[i]&0x3f)==0x36) emit_bichi_imm(fs,0x800000,fs); // c_ole_d
5017     if((source[i]&0x3f)==0x37) {emit_bichi_imm(fs,0x800000,fs);emit_orrvs_imm(fs,0x800000,fs);} // c_ule_d
5018     if((source[i]&0x3f)==0x3a) emit_bicne_imm(fs,0x800000,fs); // c_seq_d
5019     if((source[i]&0x3f)==0x3b) emit_bicne_imm(fs,0x800000,fs); // c_ngl_d
5020     if((source[i]&0x3f)==0x3c) emit_biccs_imm(fs,0x800000,fs); // c_lt_d
5021     if((source[i]&0x3f)==0x3d) emit_biccs_imm(fs,0x800000,fs); // c_nge_d
5022     if((source[i]&0x3f)==0x3e) emit_bichi_imm(fs,0x800000,fs); // c_le_d
5023     if((source[i]&0x3f)==0x3f) emit_bichi_imm(fs,0x800000,fs); // c_ngt_d
5024     return;
5025   }
5026   #endif
5027   
5028   // C only
5029   
5030   u_int hr,reglist=0;
5031   for(hr=0;hr<HOST_REGS;hr++) {
5032     if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
5033   }
5034   reglist&=~(1<<fs);
5035   save_regs(reglist);
5036   if(opcode2[i]==0x10) {
5037     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
5038     emit_readword((int)&reg_cop1_simple[(source[i]>>16)&0x1f],ARG2_REG);
5039     if((source[i]&0x3f)==0x30) emit_call((int)c_f_s);
5040     if((source[i]&0x3f)==0x31) emit_call((int)c_un_s);
5041     if((source[i]&0x3f)==0x32) emit_call((int)c_eq_s);
5042     if((source[i]&0x3f)==0x33) emit_call((int)c_ueq_s);
5043     if((source[i]&0x3f)==0x34) emit_call((int)c_olt_s);
5044     if((source[i]&0x3f)==0x35) emit_call((int)c_ult_s);
5045     if((source[i]&0x3f)==0x36) emit_call((int)c_ole_s);
5046     if((source[i]&0x3f)==0x37) emit_call((int)c_ule_s);
5047     if((source[i]&0x3f)==0x38) emit_call((int)c_sf_s);
5048     if((source[i]&0x3f)==0x39) emit_call((int)c_ngle_s);
5049     if((source[i]&0x3f)==0x3a) emit_call((int)c_seq_s);
5050     if((source[i]&0x3f)==0x3b) emit_call((int)c_ngl_s);
5051     if((source[i]&0x3f)==0x3c) emit_call((int)c_lt_s);
5052     if((source[i]&0x3f)==0x3d) emit_call((int)c_nge_s);
5053     if((source[i]&0x3f)==0x3e) emit_call((int)c_le_s);
5054     if((source[i]&0x3f)==0x3f) emit_call((int)c_ngt_s);
5055   }
5056   if(opcode2[i]==0x11) {
5057     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
5058     emit_readword((int)&reg_cop1_double[(source[i]>>16)&0x1f],ARG2_REG);
5059     if((source[i]&0x3f)==0x30) emit_call((int)c_f_d);
5060     if((source[i]&0x3f)==0x31) emit_call((int)c_un_d);
5061     if((source[i]&0x3f)==0x32) emit_call((int)c_eq_d);
5062     if((source[i]&0x3f)==0x33) emit_call((int)c_ueq_d);
5063     if((source[i]&0x3f)==0x34) emit_call((int)c_olt_d);
5064     if((source[i]&0x3f)==0x35) emit_call((int)c_ult_d);
5065     if((source[i]&0x3f)==0x36) emit_call((int)c_ole_d);
5066     if((source[i]&0x3f)==0x37) emit_call((int)c_ule_d);
5067     if((source[i]&0x3f)==0x38) emit_call((int)c_sf_d);
5068     if((source[i]&0x3f)==0x39) emit_call((int)c_ngle_d);
5069     if((source[i]&0x3f)==0x3a) emit_call((int)c_seq_d);
5070     if((source[i]&0x3f)==0x3b) emit_call((int)c_ngl_d);
5071     if((source[i]&0x3f)==0x3c) emit_call((int)c_lt_d);
5072     if((source[i]&0x3f)==0x3d) emit_call((int)c_nge_d);
5073     if((source[i]&0x3f)==0x3e) emit_call((int)c_le_d);
5074     if((source[i]&0x3f)==0x3f) emit_call((int)c_ngt_d);
5075   }
5076   restore_regs(reglist);
5077   emit_loadreg(FSREG,fs);
5078 #else
5079   cop1_unusable(i, i_regs);
5080 #endif
5081 }
5082
5083 void float_assemble(int i,struct regstat *i_regs)
5084 {
5085 #ifndef DISABLE_COP1
5086   signed char temp=get_reg(i_regs->regmap,-1);
5087   assert(temp>=0);
5088   // Check cop1 unusable
5089   if(!cop1_usable) {
5090     signed char cs=get_reg(i_regs->regmap,CSREG);
5091     assert(cs>=0);
5092     emit_testimm(cs,0x20000000);
5093     int jaddr=(int)out;
5094     emit_jeq(0);
5095     add_stub(FP_STUB,jaddr,(int)out,i,cs,(int)i_regs,is_delayslot,0);
5096     cop1_usable=1;
5097   }
5098   
5099   #if(defined(__VFP_FP__) && !defined(__SOFTFP__)) 
5100   if((source[i]&0x3f)==6) // mov
5101   {
5102     if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
5103       if(opcode2[i]==0x10) {
5104         emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
5105         emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],HOST_TEMPREG);
5106         emit_readword_indexed(0,temp,temp);
5107         emit_writeword_indexed(temp,0,HOST_TEMPREG);
5108       }
5109       if(opcode2[i]==0x11) {
5110         emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],temp);
5111         emit_readword((int)&reg_cop1_double[(source[i]>>6)&0x1f],HOST_TEMPREG);
5112         emit_vldr(temp,7);
5113         emit_vstr(7,HOST_TEMPREG);
5114       }
5115     }
5116     return;
5117   }
5118   
5119   if((source[i]&0x3f)>3)
5120   {
5121     if(opcode2[i]==0x10) {
5122       emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
5123       emit_flds(temp,15);
5124       if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
5125         emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],temp);
5126       }
5127       if((source[i]&0x3f)==4) // sqrt
5128         emit_fsqrts(15,15);
5129       if((source[i]&0x3f)==5) // abs
5130         emit_fabss(15,15);
5131       if((source[i]&0x3f)==7) // neg
5132         emit_fnegs(15,15);
5133       emit_fsts(15,temp);
5134     }
5135     if(opcode2[i]==0x11) {
5136       emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],temp);
5137       emit_vldr(temp,7);
5138       if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
5139         emit_readword((int)&reg_cop1_double[(source[i]>>6)&0x1f],temp);
5140       }
5141       if((source[i]&0x3f)==4) // sqrt
5142         emit_fsqrtd(7,7);
5143       if((source[i]&0x3f)==5) // abs
5144         emit_fabsd(7,7);
5145       if((source[i]&0x3f)==7) // neg
5146         emit_fnegd(7,7);
5147       emit_vstr(7,temp);
5148     }
5149     return;
5150   }
5151   if((source[i]&0x3f)<4)
5152   {
5153     if(opcode2[i]==0x10) {
5154       emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
5155     }
5156     if(opcode2[i]==0x11) {
5157       emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],temp);
5158     }
5159     if(((source[i]>>11)&0x1f)!=((source[i]>>16)&0x1f)) {
5160       if(opcode2[i]==0x10) {
5161         emit_readword((int)&reg_cop1_simple[(source[i]>>16)&0x1f],HOST_TEMPREG);
5162         emit_flds(temp,15);
5163         emit_flds(HOST_TEMPREG,13);
5164         if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
5165           if(((source[i]>>16)&0x1f)!=((source[i]>>6)&0x1f)) {
5166             emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],temp);
5167           }
5168         }
5169         if((source[i]&0x3f)==0) emit_fadds(15,13,15);
5170         if((source[i]&0x3f)==1) emit_fsubs(15,13,15);
5171         if((source[i]&0x3f)==2) emit_fmuls(15,13,15);
5172         if((source[i]&0x3f)==3) emit_fdivs(15,13,15);
5173         if(((source[i]>>16)&0x1f)==((source[i]>>6)&0x1f)) {
5174           emit_fsts(15,HOST_TEMPREG);
5175         }else{
5176           emit_fsts(15,temp);
5177         }
5178       }
5179       else if(opcode2[i]==0x11) {
5180         emit_readword((int)&reg_cop1_double[(source[i]>>16)&0x1f],HOST_TEMPREG);
5181         emit_vldr(temp,7);
5182         emit_vldr(HOST_TEMPREG,6);
5183         if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
5184           if(((source[i]>>16)&0x1f)!=((source[i]>>6)&0x1f)) {
5185             emit_readword((int)&reg_cop1_double[(source[i]>>6)&0x1f],temp);
5186           }
5187         }
5188         if((source[i]&0x3f)==0) emit_faddd(7,6,7);
5189         if((source[i]&0x3f)==1) emit_fsubd(7,6,7);
5190         if((source[i]&0x3f)==2) emit_fmuld(7,6,7);
5191         if((source[i]&0x3f)==3) emit_fdivd(7,6,7);
5192         if(((source[i]>>16)&0x1f)==((source[i]>>6)&0x1f)) {
5193           emit_vstr(7,HOST_TEMPREG);
5194         }else{
5195           emit_vstr(7,temp);
5196         }
5197       }
5198     }
5199     else {
5200       if(opcode2[i]==0x10) {
5201         emit_flds(temp,15);
5202         if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
5203           emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],temp);
5204         }
5205         if((source[i]&0x3f)==0) emit_fadds(15,15,15);
5206         if((source[i]&0x3f)==1) emit_fsubs(15,15,15);
5207         if((source[i]&0x3f)==2) emit_fmuls(15,15,15);
5208         if((source[i]&0x3f)==3) emit_fdivs(15,15,15);
5209         emit_fsts(15,temp);
5210       }
5211       else if(opcode2[i]==0x11) {
5212         emit_vldr(temp,7);
5213         if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f)) {
5214           emit_readword((int)&reg_cop1_double[(source[i]>>6)&0x1f],temp);
5215         }
5216         if((source[i]&0x3f)==0) emit_faddd(7,7,7);
5217         if((source[i]&0x3f)==1) emit_fsubd(7,7,7);
5218         if((source[i]&0x3f)==2) emit_fmuld(7,7,7);
5219         if((source[i]&0x3f)==3) emit_fdivd(7,7,7);
5220         emit_vstr(7,temp);
5221       }
5222     }
5223     return;
5224   }
5225   #endif
5226   
5227   u_int hr,reglist=0;
5228   for(hr=0;hr<HOST_REGS;hr++) {
5229     if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
5230   }
5231   if(opcode2[i]==0x10) { // Single precision
5232     save_regs(reglist);
5233     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
5234     if((source[i]&0x3f)<4) {
5235       emit_readword((int)&reg_cop1_simple[(source[i]>>16)&0x1f],ARG2_REG);
5236       emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG3_REG);
5237     }else{
5238       emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
5239     }
5240     switch(source[i]&0x3f)
5241     {
5242       case 0x00: emit_call((int)add_s);break;
5243       case 0x01: emit_call((int)sub_s);break;
5244       case 0x02: emit_call((int)mul_s);break;
5245       case 0x03: emit_call((int)div_s);break;
5246       case 0x04: emit_call((int)sqrt_s);break;
5247       case 0x05: emit_call((int)abs_s);break;
5248       case 0x06: emit_call((int)mov_s);break;
5249       case 0x07: emit_call((int)neg_s);break;
5250     }
5251     restore_regs(reglist);
5252   }
5253   if(opcode2[i]==0x11) { // Double precision
5254     save_regs(reglist);
5255     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
5256     if((source[i]&0x3f)<4) {
5257       emit_readword((int)&reg_cop1_double[(source[i]>>16)&0x1f],ARG2_REG);
5258       emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG3_REG);
5259     }else{
5260       emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
5261     }
5262     switch(source[i]&0x3f)
5263     {
5264       case 0x00: emit_call((int)add_d);break;
5265       case 0x01: emit_call((int)sub_d);break;
5266       case 0x02: emit_call((int)mul_d);break;
5267       case 0x03: emit_call((int)div_d);break;
5268       case 0x04: emit_call((int)sqrt_d);break;
5269       case 0x05: emit_call((int)abs_d);break;
5270       case 0x06: emit_call((int)mov_d);break;
5271       case 0x07: emit_call((int)neg_d);break;
5272     }
5273     restore_regs(reglist);
5274   }
5275 #else
5276   cop1_unusable(i, i_regs);
5277 #endif
5278 }
5279
5280 void multdiv_assemble_arm(int i,struct regstat *i_regs)
5281 {
5282   //  case 0x18: MULT
5283   //  case 0x19: MULTU
5284   //  case 0x1A: DIV
5285   //  case 0x1B: DIVU
5286   //  case 0x1C: DMULT
5287   //  case 0x1D: DMULTU
5288   //  case 0x1E: DDIV
5289   //  case 0x1F: DDIVU
5290   if(rs1[i]&&rs2[i])
5291   {
5292     if((opcode2[i]&4)==0) // 32-bit
5293     {
5294       if(opcode2[i]==0x18) // MULT
5295       {
5296         signed char m1=get_reg(i_regs->regmap,rs1[i]);
5297         signed char m2=get_reg(i_regs->regmap,rs2[i]);
5298         signed char hi=get_reg(i_regs->regmap,HIREG);
5299         signed char lo=get_reg(i_regs->regmap,LOREG);
5300         assert(m1>=0);
5301         assert(m2>=0);
5302         assert(hi>=0);
5303         assert(lo>=0);
5304         emit_smull(m1,m2,hi,lo);
5305       }
5306       if(opcode2[i]==0x19) // MULTU
5307       {
5308         signed char m1=get_reg(i_regs->regmap,rs1[i]);
5309         signed char m2=get_reg(i_regs->regmap,rs2[i]);
5310         signed char hi=get_reg(i_regs->regmap,HIREG);
5311         signed char lo=get_reg(i_regs->regmap,LOREG);
5312         assert(m1>=0);
5313         assert(m2>=0);
5314         assert(hi>=0);
5315         assert(lo>=0);
5316         emit_umull(m1,m2,hi,lo);
5317       }
5318       if(opcode2[i]==0x1A) // DIV
5319       {
5320         signed char d1=get_reg(i_regs->regmap,rs1[i]);
5321         signed char d2=get_reg(i_regs->regmap,rs2[i]);
5322         assert(d1>=0);
5323         assert(d2>=0);
5324         signed char quotient=get_reg(i_regs->regmap,LOREG);
5325         signed char remainder=get_reg(i_regs->regmap,HIREG);
5326         assert(quotient>=0);
5327         assert(remainder>=0);
5328         emit_movs(d1,remainder);
5329         emit_movimm(0xffffffff,quotient);
5330         emit_negmi(quotient,quotient); // .. quotient and ..
5331         emit_negmi(remainder,remainder); // .. remainder for div0 case (will be negated back after jump)
5332         emit_movs(d2,HOST_TEMPREG);
5333         emit_jeq((int)out+52); // Division by zero
5334         emit_negsmi(HOST_TEMPREG,HOST_TEMPREG);
5335 #ifdef HAVE_ARMV5
5336         emit_clz(HOST_TEMPREG,quotient);
5337         emit_shl(HOST_TEMPREG,quotient,HOST_TEMPREG);
5338 #else
5339         emit_movimm(0,quotient);
5340         emit_addpl_imm(quotient,1,quotient);
5341         emit_lslpls_imm(HOST_TEMPREG,1,HOST_TEMPREG);
5342         emit_jns((int)out-2*4);
5343 #endif
5344         emit_orimm(quotient,1<<31,quotient);
5345         emit_shr(quotient,quotient,quotient);
5346         emit_cmp(remainder,HOST_TEMPREG);
5347         emit_subcs(remainder,HOST_TEMPREG,remainder);
5348         emit_adcs(quotient,quotient,quotient);
5349         emit_shrimm(HOST_TEMPREG,1,HOST_TEMPREG);
5350         emit_jcc((int)out-16); // -4
5351         emit_teq(d1,d2);
5352         emit_negmi(quotient,quotient);
5353         emit_test(d1,d1);
5354         emit_negmi(remainder,remainder);
5355       }
5356       if(opcode2[i]==0x1B) // DIVU
5357       {
5358         signed char d1=get_reg(i_regs->regmap,rs1[i]); // dividend
5359         signed char d2=get_reg(i_regs->regmap,rs2[i]); // divisor
5360         assert(d1>=0);
5361         assert(d2>=0);
5362         signed char quotient=get_reg(i_regs->regmap,LOREG);
5363         signed char remainder=get_reg(i_regs->regmap,HIREG);
5364         assert(quotient>=0);
5365         assert(remainder>=0);
5366         emit_mov(d1,remainder);
5367         emit_movimm(0xffffffff,quotient); // div0 case
5368         emit_test(d2,d2);
5369         emit_jeq((int)out+40); // Division by zero
5370 #ifdef HAVE_ARMV5
5371         emit_clz(d2,HOST_TEMPREG);
5372         emit_movimm(1<<31,quotient);
5373         emit_shl(d2,HOST_TEMPREG,d2);
5374 #else
5375         emit_movimm(0,HOST_TEMPREG);
5376         emit_addpl_imm(HOST_TEMPREG,1,HOST_TEMPREG);
5377         emit_lslpls_imm(d2,1,d2);
5378         emit_jns((int)out-2*4);
5379         emit_movimm(1<<31,quotient);
5380 #endif
5381         emit_shr(quotient,HOST_TEMPREG,quotient);
5382         emit_cmp(remainder,d2);
5383         emit_subcs(remainder,d2,remainder);
5384         emit_adcs(quotient,quotient,quotient);
5385         emit_shrcc_imm(d2,1,d2);
5386         emit_jcc((int)out-16); // -4
5387       }
5388     }
5389     else // 64-bit
5390 #ifndef FORCE32
5391     {
5392       if(opcode2[i]==0x1C) // DMULT
5393       {
5394         assert(opcode2[i]!=0x1C);
5395         signed char m1h=get_reg(i_regs->regmap,rs1[i]|64);
5396         signed char m1l=get_reg(i_regs->regmap,rs1[i]);
5397         signed char m2h=get_reg(i_regs->regmap,rs2[i]|64);
5398         signed char m2l=get_reg(i_regs->regmap,rs2[i]);
5399         assert(m1h>=0);
5400         assert(m2h>=0);
5401         assert(m1l>=0);
5402         assert(m2l>=0);
5403         emit_pushreg(m2h);
5404         emit_pushreg(m2l);
5405         emit_pushreg(m1h);
5406         emit_pushreg(m1l);
5407         emit_call((int)&mult64);
5408         emit_popreg(m1l);
5409         emit_popreg(m1h);
5410         emit_popreg(m2l);
5411         emit_popreg(m2h);
5412         signed char hih=get_reg(i_regs->regmap,HIREG|64);
5413         signed char hil=get_reg(i_regs->regmap,HIREG);
5414         if(hih>=0) emit_loadreg(HIREG|64,hih);
5415         if(hil>=0) emit_loadreg(HIREG,hil);
5416         signed char loh=get_reg(i_regs->regmap,LOREG|64);
5417         signed char lol=get_reg(i_regs->regmap,LOREG);
5418         if(loh>=0) emit_loadreg(LOREG|64,loh);
5419         if(lol>=0) emit_loadreg(LOREG,lol);
5420       }
5421       if(opcode2[i]==0x1D) // DMULTU
5422       {
5423         signed char m1h=get_reg(i_regs->regmap,rs1[i]|64);
5424         signed char m1l=get_reg(i_regs->regmap,rs1[i]);
5425         signed char m2h=get_reg(i_regs->regmap,rs2[i]|64);
5426         signed char m2l=get_reg(i_regs->regmap,rs2[i]);
5427         assert(m1h>=0);
5428         assert(m2h>=0);
5429         assert(m1l>=0);
5430         assert(m2l>=0);
5431         save_regs(CALLER_SAVE_REGS);
5432         if(m1l!=0) emit_mov(m1l,0);
5433         if(m1h==0) emit_readword((int)&dynarec_local,1);
5434         else if(m1h>1) emit_mov(m1h,1);
5435         if(m2l<2) emit_readword((int)&dynarec_local+m2l*4,2);
5436         else if(m2l>2) emit_mov(m2l,2);
5437         if(m2h<3) emit_readword((int)&dynarec_local+m2h*4,3);
5438         else if(m2h>3) emit_mov(m2h,3);
5439         emit_call((int)&multu64);
5440         restore_regs(CALLER_SAVE_REGS);
5441         signed char hih=get_reg(i_regs->regmap,HIREG|64);
5442         signed char hil=get_reg(i_regs->regmap,HIREG);
5443         signed char loh=get_reg(i_regs->regmap,LOREG|64);
5444         signed char lol=get_reg(i_regs->regmap,LOREG);
5445         /*signed char temp=get_reg(i_regs->regmap,-1);
5446         signed char rh=get_reg(i_regs->regmap,HIREG|64);
5447         signed char rl=get_reg(i_regs->regmap,HIREG);
5448         assert(m1h>=0);
5449         assert(m2h>=0);
5450         assert(m1l>=0);
5451         assert(m2l>=0);
5452         assert(temp>=0);
5453         //emit_mov(m1l,EAX);
5454         //emit_mul(m2l);
5455         emit_umull(rl,rh,m1l,m2l);
5456         emit_storereg(LOREG,rl);
5457         emit_mov(rh,temp);
5458         //emit_mov(m1h,EAX);
5459         //emit_mul(m2l);
5460         emit_umull(rl,rh,m1h,m2l);
5461         emit_adds(rl,temp,temp);
5462         emit_adcimm(rh,0,rh);
5463         emit_storereg(HIREG,rh);
5464         //emit_mov(m2h,EAX);
5465         //emit_mul(m1l);
5466         emit_umull(rl,rh,m1l,m2h);
5467         emit_adds(rl,temp,temp);
5468         emit_adcimm(rh,0,rh);
5469         emit_storereg(LOREG|64,temp);
5470         emit_mov(rh,temp);
5471         //emit_mov(m2h,EAX);
5472         //emit_mul(m1h);
5473         emit_umull(rl,rh,m1h,m2h);
5474         emit_adds(rl,temp,rl);
5475         emit_loadreg(HIREG,temp);
5476         emit_adcimm(rh,0,rh);
5477         emit_adds(rl,temp,rl);
5478         emit_adcimm(rh,0,rh);
5479         // DEBUG
5480         /*
5481         emit_pushreg(m2h);
5482         emit_pushreg(m2l);
5483         emit_pushreg(m1h);
5484         emit_pushreg(m1l);
5485         emit_call((int)&multu64);
5486         emit_popreg(m1l);
5487         emit_popreg(m1h);
5488         emit_popreg(m2l);
5489         emit_popreg(m2h);
5490         signed char hih=get_reg(i_regs->regmap,HIREG|64);
5491         signed char hil=get_reg(i_regs->regmap,HIREG);
5492         if(hih>=0) emit_loadreg(HIREG|64,hih);  // DEBUG
5493         if(hil>=0) emit_loadreg(HIREG,hil);  // DEBUG
5494         */
5495         // Shouldn't be necessary
5496         //char loh=get_reg(i_regs->regmap,LOREG|64);
5497         //char lol=get_reg(i_regs->regmap,LOREG);
5498         //if(loh>=0) emit_loadreg(LOREG|64,loh);
5499         //if(lol>=0) emit_loadreg(LOREG,lol);
5500       }
5501       if(opcode2[i]==0x1E) // DDIV
5502       {
5503         signed char d1h=get_reg(i_regs->regmap,rs1[i]|64);
5504         signed char d1l=get_reg(i_regs->regmap,rs1[i]);
5505         signed char d2h=get_reg(i_regs->regmap,rs2[i]|64);
5506         signed char d2l=get_reg(i_regs->regmap,rs2[i]);
5507         assert(d1h>=0);
5508         assert(d2h>=0);
5509         assert(d1l>=0);
5510         assert(d2l>=0);
5511         save_regs(CALLER_SAVE_REGS);
5512         if(d1l!=0) emit_mov(d1l,0);
5513         if(d1h==0) emit_readword((int)&dynarec_local,1);
5514         else if(d1h>1) emit_mov(d1h,1);
5515         if(d2l<2) emit_readword((int)&dynarec_local+d2l*4,2);
5516         else if(d2l>2) emit_mov(d2l,2);
5517         if(d2h<3) emit_readword((int)&dynarec_local+d2h*4,3);
5518         else if(d2h>3) emit_mov(d2h,3);
5519         emit_call((int)&div64);
5520         restore_regs(CALLER_SAVE_REGS);
5521         signed char hih=get_reg(i_regs->regmap,HIREG|64);
5522         signed char hil=get_reg(i_regs->regmap,HIREG);
5523         signed char loh=get_reg(i_regs->regmap,LOREG|64);
5524         signed char lol=get_reg(i_regs->regmap,LOREG);
5525         if(hih>=0) emit_loadreg(HIREG|64,hih);
5526         if(hil>=0) emit_loadreg(HIREG,hil);
5527         if(loh>=0) emit_loadreg(LOREG|64,loh);
5528         if(lol>=0) emit_loadreg(LOREG,lol);
5529       }
5530       if(opcode2[i]==0x1F) // DDIVU
5531       {
5532       //u_int hr,reglist=0;
5533       //for(hr=0;hr<HOST_REGS;hr++) {
5534       //  if(i_regs->regmap[hr]>=0 && (i_regs->regmap[hr]&62)!=HIREG) reglist|=1<<hr;
5535       //}
5536         signed char d1h=get_reg(i_regs->regmap,rs1[i]|64);
5537         signed char d1l=get_reg(i_regs->regmap,rs1[i]);
5538         signed char d2h=get_reg(i_regs->regmap,rs2[i]|64);
5539         signed char d2l=get_reg(i_regs->regmap,rs2[i]);
5540         assert(d1h>=0);
5541         assert(d2h>=0);
5542         assert(d1l>=0);
5543         assert(d2l>=0);
5544         save_regs(CALLER_SAVE_REGS);
5545         if(d1l!=0) emit_mov(d1l,0);
5546         if(d1h==0) emit_readword((int)&dynarec_local,1);
5547         else if(d1h>1) emit_mov(d1h,1);
5548         if(d2l<2) emit_readword((int)&dynarec_local+d2l*4,2);
5549         else if(d2l>2) emit_mov(d2l,2);
5550         if(d2h<3) emit_readword((int)&dynarec_local+d2h*4,3);
5551         else if(d2h>3) emit_mov(d2h,3);
5552         emit_call((int)&divu64);
5553         restore_regs(CALLER_SAVE_REGS);
5554         signed char hih=get_reg(i_regs->regmap,HIREG|64);
5555         signed char hil=get_reg(i_regs->regmap,HIREG);
5556         signed char loh=get_reg(i_regs->regmap,LOREG|64);
5557         signed char lol=get_reg(i_regs->regmap,LOREG);
5558         if(hih>=0) emit_loadreg(HIREG|64,hih);
5559         if(hil>=0) emit_loadreg(HIREG,hil);
5560         if(loh>=0) emit_loadreg(LOREG|64,loh);
5561         if(lol>=0) emit_loadreg(LOREG,lol);
5562       }
5563     }
5564 #else
5565     assert(0);
5566 #endif
5567   }
5568   else
5569   {
5570     // Multiply by zero is zero.
5571     // MIPS does not have a divide by zero exception.
5572     // The result is undefined, we return zero.
5573     signed char hr=get_reg(i_regs->regmap,HIREG);
5574     signed char lr=get_reg(i_regs->regmap,LOREG);
5575     if(hr>=0) emit_zeroreg(hr);
5576     if(lr>=0) emit_zeroreg(lr);
5577   }
5578 }
5579 #define multdiv_assemble multdiv_assemble_arm
5580
5581 void do_preload_rhash(int r) {
5582   // Don't need this for ARM.  On x86, this puts the value 0xf8 into the
5583   // register.  On ARM the hash can be done with a single instruction (below)
5584 }
5585
5586 void do_preload_rhtbl(int ht) {
5587   emit_addimm(FP,(int)&mini_ht-(int)&dynarec_local,ht);
5588 }
5589
5590 void do_rhash(int rs,int rh) {
5591   emit_andimm(rs,0xf8,rh);
5592 }
5593
5594 void do_miniht_load(int ht,int rh) {
5595   assem_debug("ldr %s,[%s,%s]!\n",regname[rh],regname[ht],regname[rh]);
5596   output_w32(0xe7b00000|rd_rn_rm(rh,ht,rh));
5597 }
5598
5599 void do_miniht_jump(int rs,int rh,int ht) {
5600   emit_cmp(rh,rs);
5601   emit_ldreq_indexed(ht,4,15);
5602   #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
5603   emit_mov(rs,7);
5604   emit_jmp(jump_vaddr_reg[7]);
5605   #else
5606   emit_jmp(jump_vaddr_reg[rs]);
5607   #endif
5608 }
5609
5610 void do_miniht_insert(u_int return_address,int rt,int temp) {
5611   #ifndef HAVE_ARMV7
5612   emit_movimm(return_address,rt); // PC into link register
5613   add_to_linker((int)out,return_address,1);
5614   emit_pcreladdr(temp);
5615   emit_writeword(rt,(int)&mini_ht[(return_address&0xFF)>>3][0]);
5616   emit_writeword(temp,(int)&mini_ht[(return_address&0xFF)>>3][1]);
5617   #else
5618   emit_movw(return_address&0x0000FFFF,rt);
5619   add_to_linker((int)out,return_address,1);
5620   emit_pcreladdr(temp);
5621   emit_writeword(temp,(int)&mini_ht[(return_address&0xFF)>>3][1]);
5622   emit_movt(return_address&0xFFFF0000,rt);
5623   emit_writeword(rt,(int)&mini_ht[(return_address&0xFF)>>3][0]);
5624   #endif
5625 }
5626
5627 // Sign-extend to 64 bits and write out upper half of a register
5628 // This is useful where we have a 32-bit value in a register, and want to
5629 // keep it in a 32-bit register, but can't guarantee that it won't be read
5630 // as a 64-bit value later.
5631 void wb_sx(signed char pre[],signed char entry[],uint64_t dirty,uint64_t is32_pre,uint64_t is32,uint64_t u,uint64_t uu)
5632 {
5633 #ifndef FORCE32
5634   if(is32_pre==is32) return;
5635   int hr,reg;
5636   for(hr=0;hr<HOST_REGS;hr++) {
5637     if(hr!=EXCLUDE_REG) {
5638       //if(pre[hr]==entry[hr]) {
5639         if((reg=pre[hr])>=0) {
5640           if((dirty>>hr)&1) {
5641             if( ((is32_pre&~is32&~uu)>>reg)&1 ) {
5642               emit_sarimm(hr,31,HOST_TEMPREG);
5643               emit_storereg(reg|64,HOST_TEMPREG);
5644             }
5645           }
5646         }
5647       //}
5648     }
5649   }
5650 #endif
5651 }
5652
5653 void wb_valid(signed char pre[],signed char entry[],u_int dirty_pre,u_int dirty,uint64_t is32_pre,uint64_t u,uint64_t uu)
5654 {
5655   //if(dirty_pre==dirty) return;
5656   int hr,reg,new_hr;
5657   for(hr=0;hr<HOST_REGS;hr++) {
5658     if(hr!=EXCLUDE_REG) {
5659       reg=pre[hr];
5660       if(((~u)>>(reg&63))&1) {
5661         if(reg>0) {
5662           if(((dirty_pre&~dirty)>>hr)&1) {
5663             if(reg>0&&reg<34) {
5664               emit_storereg(reg,hr);
5665               if( ((is32_pre&~uu)>>reg)&1 ) {
5666                 emit_sarimm(hr,31,HOST_TEMPREG);
5667                 emit_storereg(reg|64,HOST_TEMPREG);
5668               }
5669             }
5670             else if(reg>=64) {
5671               emit_storereg(reg,hr);
5672             }
5673           }
5674         }
5675       }
5676     }
5677   }
5678 }
5679
5680
5681 /* using strd could possibly help but you'd have to allocate registers in pairs
5682 void wb_invalidate_arm(signed char pre[],signed char entry[],uint64_t dirty,uint64_t is32,uint64_t u,uint64_t uu)
5683 {
5684   int hr;
5685   int wrote=-1;
5686   for(hr=HOST_REGS-1;hr>=0;hr--) {
5687     if(hr!=EXCLUDE_REG) {
5688       if(pre[hr]!=entry[hr]) {
5689         if(pre[hr]>=0) {
5690           if((dirty>>hr)&1) {
5691             if(get_reg(entry,pre[hr])<0) {
5692               if(pre[hr]<64) {
5693                 if(!((u>>pre[hr])&1)) {
5694                   if(hr<10&&(~hr&1)&&(pre[hr+1]<0||wrote==hr+1)) {
5695                     if( ((is32>>pre[hr])&1) && !((uu>>pre[hr])&1) ) {
5696                       emit_sarimm(hr,31,hr+1);
5697                       emit_strdreg(pre[hr],hr);
5698                     }
5699                     else
5700                       emit_storereg(pre[hr],hr);
5701                   }else{
5702                     emit_storereg(pre[hr],hr);
5703                     if( ((is32>>pre[hr])&1) && !((uu>>pre[hr])&1) ) {
5704                       emit_sarimm(hr,31,hr);
5705                       emit_storereg(pre[hr]|64,hr);
5706                     }
5707                   }
5708                 }
5709               }else{
5710                 if(!((uu>>(pre[hr]&63))&1) && !((is32>>(pre[hr]&63))&1)) {
5711                   emit_storereg(pre[hr],hr);
5712                 }
5713               }
5714               wrote=hr;
5715             }
5716           }
5717         }
5718       }
5719     }
5720   }
5721   for(hr=0;hr<HOST_REGS;hr++) {
5722     if(hr!=EXCLUDE_REG) {
5723       if(pre[hr]!=entry[hr]) {
5724         if(pre[hr]>=0) {
5725           int nr;
5726           if((nr=get_reg(entry,pre[hr]))>=0) {
5727             emit_mov(hr,nr);
5728           }
5729         }
5730       }
5731     }
5732   }
5733 }
5734 #define wb_invalidate wb_invalidate_arm
5735 */
5736
5737 // Clearing the cache is rather slow on ARM Linux, so mark the areas
5738 // that need to be cleared, and then only clear these areas once.
5739 void do_clear_cache()
5740 {
5741   int i,j;
5742   for (i=0;i<(1<<(TARGET_SIZE_2-17));i++)
5743   {
5744     u_int bitmap=needs_clear_cache[i];
5745     if(bitmap) {
5746       u_int start,end;
5747       for(j=0;j<32;j++) 
5748       {
5749         if(bitmap&(1<<j)) {
5750           start=(u_int)BASE_ADDR+i*131072+j*4096;
5751           end=start+4095;
5752           j++;
5753           while(j<32) {
5754             if(bitmap&(1<<j)) {
5755               end+=4096;
5756               j++;
5757             }else{
5758               __clear_cache((void *)start,(void *)end);
5759               break;
5760             }
5761           }
5762         }
5763       }
5764       needs_clear_cache[i]=0;
5765     }
5766   }
5767 }
5768
5769 // CPU-architecture-specific initialization
5770 void arch_init() {
5771 #ifndef DISABLE_COP1
5772   rounding_modes[0]=0x0<<22; // round
5773   rounding_modes[1]=0x3<<22; // trunc
5774   rounding_modes[2]=0x1<<22; // ceil
5775   rounding_modes[3]=0x2<<22; // floor
5776 #endif
5777 }
5778
5779 // vim:shiftwidth=2:expandtab