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