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