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