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