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