4af1566d2db08464feca06a0256c9da6cc54e3f2
[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           if((i_is32>>i_regmap[hr])&1) {
2420             if(value!=-1&&value!=0) emit_sarimm(HOST_TEMPREG,31,HOST_TEMPREG);
2421             emit_storereg(i_regmap[hr]|64,HOST_TEMPREG);
2422           }
2423         }
2424       }
2425     }
2426   }
2427 }
2428
2429 /* Stubs/epilogue */
2430
2431 void literal_pool(int n)
2432 {
2433   if(!literalcount) return;
2434   if(n) {
2435     if((int)out-literals[0][0]<4096-n) return;
2436   }
2437   u_int *ptr;
2438   int i;
2439   for(i=0;i<literalcount;i++)
2440   {
2441     ptr=(u_int *)literals[i][0];
2442     u_int offset=(u_int)out-(u_int)ptr-8;
2443     assert(offset<4096);
2444     assert(!(offset&3));
2445     *ptr|=offset;
2446     output_w32(literals[i][1]);
2447   }
2448   literalcount=0;
2449 }
2450
2451 void literal_pool_jumpover(int n)
2452 {
2453   if(!literalcount) return;
2454   if(n) {
2455     if((int)out-literals[0][0]<4096-n) return;
2456   }
2457   int jaddr=(int)out;
2458   emit_jmp(0);
2459   literal_pool(0);
2460   set_jump_target(jaddr,(int)out);
2461 }
2462
2463 emit_extjump2(int addr, int target, int linker)
2464 {
2465   u_char *ptr=(u_char *)addr;
2466   assert((ptr[3]&0x0e)==0xa);
2467   emit_loadlp(target,0);
2468   emit_loadlp(addr,1);
2469   assert(addr>=0x7000000&&addr<0x7FFFFFF);
2470   //assert((target>=0x80000000&&target<0x80800000)||(target>0xA4000000&&target<0xA4001000));
2471 //DEBUG >
2472 #ifdef DEBUG_CYCLE_COUNT
2473   emit_readword((int)&last_count,ECX);
2474   emit_add(HOST_CCREG,ECX,HOST_CCREG);
2475   emit_readword((int)&next_interupt,ECX);
2476   emit_writeword(HOST_CCREG,(int)&Count);
2477   emit_sub(HOST_CCREG,ECX,HOST_CCREG);
2478   emit_writeword(ECX,(int)&last_count);
2479 #endif
2480 //DEBUG <
2481   emit_jmp(linker);
2482 }
2483
2484 emit_extjump(int addr, int target)
2485 {
2486   emit_extjump2(addr, target, (int)dyna_linker);
2487 }
2488 emit_extjump_ds(int addr, int target)
2489 {
2490   emit_extjump2(addr, target, (int)dyna_linker_ds);
2491 }
2492
2493 do_readstub(int n)
2494 {
2495   assem_debug("do_readstub %x\n",start+stubs[n][3]*4);
2496   literal_pool(256);
2497   set_jump_target(stubs[n][1],(int)out);
2498   int type=stubs[n][0];
2499   int i=stubs[n][3];
2500   int rs=stubs[n][4];
2501   struct regstat *i_regs=(struct regstat *)stubs[n][5];
2502   u_int reglist=stubs[n][7];
2503   signed char *i_regmap=i_regs->regmap;
2504   int addr=get_reg(i_regmap,AGEN1+(i&1));
2505   int rth,rt;
2506   int ds;
2507   if(itype[i]==C1LS||itype[i]==LOADLR) {
2508     rth=get_reg(i_regmap,FTEMP|64);
2509     rt=get_reg(i_regmap,FTEMP);
2510   }else{
2511     rth=get_reg(i_regmap,rt1[i]|64);
2512     rt=get_reg(i_regmap,rt1[i]);
2513   }
2514   assert(rs>=0);
2515   assert(rt>=0);
2516   if(addr<0) addr=rt;
2517   assert(addr>=0);
2518   int ftable=0;
2519   if(type==LOADB_STUB||type==LOADBU_STUB)
2520     ftable=(int)readmemb;
2521   if(type==LOADH_STUB||type==LOADHU_STUB)
2522     ftable=(int)readmemh;
2523   if(type==LOADW_STUB)
2524     ftable=(int)readmem;
2525   if(type==LOADD_STUB)
2526     ftable=(int)readmemd;
2527   emit_writeword(rs,(int)&address);
2528   //emit_pusha();
2529   save_regs(reglist);
2530   ds=i_regs!=&regs[i];
2531   int real_rs=(itype[i]==LOADLR)?-1:get_reg(i_regmap,rs1[i]);
2532   u_int cmask=ds?-1:(0x100f|~i_regs->wasconst);
2533   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);
2534   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty&cmask&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs)));
2535   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);
2536   emit_shrimm(rs,16,1);
2537   int cc=get_reg(i_regmap,CCREG);
2538   if(cc<0) {
2539     emit_loadreg(CCREG,2);
2540   }
2541   emit_movimm(ftable,0);
2542   emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
2543   emit_movimm(start+stubs[n][3]*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
2544   //emit_readword((int)&last_count,temp);
2545   //emit_add(cc,temp,cc);
2546   //emit_writeword(cc,(int)&Count);
2547   //emit_mov(15,14);
2548   emit_call((int)&indirect_jump_indexed);
2549   //emit_callreg(rs);
2550   //emit_readword_dualindexedx4(rs,HOST_TEMPREG,15);
2551   // We really shouldn't need to update the count here,
2552   // but not doing so causes random crashes...
2553   emit_readword((int)&Count,HOST_TEMPREG);
2554   emit_readword((int)&next_interupt,2);
2555   emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
2556   emit_writeword(2,(int)&last_count);
2557   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
2558   if(cc<0) {
2559     emit_storereg(CCREG,HOST_TEMPREG);
2560   }
2561   //emit_popa();
2562   restore_regs(reglist);
2563   //if((cc=get_reg(regmap,CCREG))>=0) {
2564   //  emit_loadreg(CCREG,cc);
2565   //}
2566   if(type==LOADB_STUB)
2567     emit_movsbl((int)&readmem_dword,rt);
2568   if(type==LOADBU_STUB)
2569     emit_movzbl((int)&readmem_dword,rt);
2570   if(type==LOADH_STUB)
2571     emit_movswl((int)&readmem_dword,rt);
2572   if(type==LOADHU_STUB)
2573     emit_movzwl((int)&readmem_dword,rt);
2574   if(type==LOADW_STUB)
2575     emit_readword((int)&readmem_dword,rt);
2576   if(type==LOADD_STUB) {
2577     emit_readword((int)&readmem_dword,rt);
2578     if(rth>=0) emit_readword(((int)&readmem_dword)+4,rth);
2579   }
2580   emit_jmp(stubs[n][2]); // return address
2581 }
2582
2583 inline_readstub(int type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
2584 {
2585   int rs=get_reg(regmap,target);
2586   int rth=get_reg(regmap,target|64);
2587   int rt=get_reg(regmap,target);
2588   assert(rs>=0);
2589   assert(rt>=0);
2590   int ftable=0;
2591   if(type==LOADB_STUB||type==LOADBU_STUB)
2592     ftable=(int)readmemb;
2593   if(type==LOADH_STUB||type==LOADHU_STUB)
2594     ftable=(int)readmemh;
2595   if(type==LOADW_STUB)
2596     ftable=(int)readmem;
2597   if(type==LOADD_STUB)
2598     ftable=(int)readmemd;
2599   emit_writeword(rs,(int)&address);
2600   //emit_pusha();
2601   save_regs(reglist);
2602   //emit_shrimm(rs,16,1);
2603   int cc=get_reg(regmap,CCREG);
2604   if(cc<0) {
2605     emit_loadreg(CCREG,2);
2606   }
2607   //emit_movimm(ftable,0);
2608   emit_movimm(((u_int *)ftable)[addr>>16],0);
2609   //emit_readword((int)&last_count,12);
2610   emit_addimm(cc<0?2:cc,CLOCK_DIVIDER*(adj+1),2);
2611   if((signed int)addr>=(signed int)0xC0000000) {
2612     // Pagefault address
2613     int ds=regmap!=regs[i].regmap;
2614     emit_movimm(start+i*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
2615   }
2616   //emit_add(12,2,2);
2617   //emit_writeword(2,(int)&Count);
2618   //emit_call(((u_int *)ftable)[addr>>16]);
2619   emit_call((int)&indirect_jump);
2620   // We really shouldn't need to update the count here,
2621   // but not doing so causes random crashes...
2622   emit_readword((int)&Count,HOST_TEMPREG);
2623   emit_readword((int)&next_interupt,2);
2624   emit_addimm(HOST_TEMPREG,-CLOCK_DIVIDER*(adj+1),HOST_TEMPREG);
2625   emit_writeword(2,(int)&last_count);
2626   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
2627   if(cc<0) {
2628     emit_storereg(CCREG,HOST_TEMPREG);
2629   }
2630   //emit_popa();
2631   restore_regs(reglist);
2632   if(type==LOADB_STUB)
2633     emit_movsbl((int)&readmem_dword,rt);
2634   if(type==LOADBU_STUB)
2635     emit_movzbl((int)&readmem_dword,rt);
2636   if(type==LOADH_STUB)
2637     emit_movswl((int)&readmem_dword,rt);
2638   if(type==LOADHU_STUB)
2639     emit_movzwl((int)&readmem_dword,rt);
2640   if(type==LOADW_STUB)
2641     emit_readword((int)&readmem_dword,rt);
2642   if(type==LOADD_STUB) {
2643     emit_readword((int)&readmem_dword,rt);
2644     if(rth>=0) emit_readword(((int)&readmem_dword)+4,rth);
2645   }
2646 }
2647
2648 do_writestub(int n)
2649 {
2650   assem_debug("do_writestub %x\n",start+stubs[n][3]*4);
2651   literal_pool(256);
2652   set_jump_target(stubs[n][1],(int)out);
2653   int type=stubs[n][0];
2654   int i=stubs[n][3];
2655   int rs=stubs[n][4];
2656   struct regstat *i_regs=(struct regstat *)stubs[n][5];
2657   u_int reglist=stubs[n][7];
2658   signed char *i_regmap=i_regs->regmap;
2659   int addr=get_reg(i_regmap,AGEN1+(i&1));
2660   int rth,rt,r;
2661   int ds;
2662   if(itype[i]==C1LS) {
2663     rth=get_reg(i_regmap,FTEMP|64);
2664     rt=get_reg(i_regmap,r=FTEMP);
2665   }else{
2666     rth=get_reg(i_regmap,rs2[i]|64);
2667     rt=get_reg(i_regmap,r=rs2[i]);
2668   }
2669   assert(rs>=0);
2670   assert(rt>=0);
2671   if(addr<0) addr=get_reg(i_regmap,-1);
2672   assert(addr>=0);
2673   int ftable=0;
2674   if(type==STOREB_STUB)
2675     ftable=(int)writememb;
2676   if(type==STOREH_STUB)
2677     ftable=(int)writememh;
2678   if(type==STOREW_STUB)
2679     ftable=(int)writemem;
2680   if(type==STORED_STUB)
2681     ftable=(int)writememd;
2682   emit_writeword(rs,(int)&address);
2683   //emit_shrimm(rs,16,rs);
2684   //emit_movmem_indexedx4(ftable,rs,rs);
2685   if(type==STOREB_STUB)
2686     emit_writebyte(rt,(int)&byte);
2687   if(type==STOREH_STUB)
2688     emit_writehword(rt,(int)&hword);
2689   if(type==STOREW_STUB)
2690     emit_writeword(rt,(int)&word);
2691   if(type==STORED_STUB) {
2692 #ifndef FORCE32
2693     emit_writeword(rt,(int)&dword);
2694     emit_writeword(r?rth:rt,(int)&dword+4);
2695 #else
2696     printf("STORED_STUB\n");
2697 #endif
2698   }
2699   //emit_pusha();
2700   save_regs(reglist);
2701   ds=i_regs!=&regs[i];
2702   int real_rs=get_reg(i_regmap,rs1[i]);
2703   u_int cmask=ds?-1:(0x100f|~i_regs->wasconst);
2704   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);
2705   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty&cmask&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs)));
2706   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);
2707   emit_shrimm(rs,16,1);
2708   int cc=get_reg(i_regmap,CCREG);
2709   if(cc<0) {
2710     emit_loadreg(CCREG,2);
2711   }
2712   emit_movimm(ftable,0);
2713   emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
2714   emit_movimm(start+stubs[n][3]*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
2715   //emit_readword((int)&last_count,temp);
2716   //emit_addimm(cc,2*stubs[n][5]+2,cc);
2717   //emit_add(cc,temp,cc);
2718   //emit_writeword(cc,(int)&Count);
2719   emit_call((int)&indirect_jump_indexed);
2720   //emit_callreg(rs);
2721   emit_readword((int)&Count,HOST_TEMPREG);
2722   emit_readword((int)&next_interupt,2);
2723   emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
2724   emit_writeword(2,(int)&last_count);
2725   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
2726   if(cc<0) {
2727     emit_storereg(CCREG,HOST_TEMPREG);
2728   }
2729   //emit_popa();
2730   restore_regs(reglist);
2731   //if((cc=get_reg(regmap,CCREG))>=0) {
2732   //  emit_loadreg(CCREG,cc);
2733   //}
2734   emit_jmp(stubs[n][2]); // return address
2735 }
2736
2737 inline_writestub(int type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
2738 {
2739   int rs=get_reg(regmap,-1);
2740   int rth=get_reg(regmap,target|64);
2741   int rt=get_reg(regmap,target);
2742   assert(rs>=0);
2743   assert(rt>=0);
2744   int ftable=0;
2745   if(type==STOREB_STUB)
2746     ftable=(int)writememb;
2747   if(type==STOREH_STUB)
2748     ftable=(int)writememh;
2749   if(type==STOREW_STUB)
2750     ftable=(int)writemem;
2751   if(type==STORED_STUB)
2752     ftable=(int)writememd;
2753   emit_writeword(rs,(int)&address);
2754   //emit_shrimm(rs,16,rs);
2755   //emit_movmem_indexedx4(ftable,rs,rs);
2756   if(type==STOREB_STUB)
2757     emit_writebyte(rt,(int)&byte);
2758   if(type==STOREH_STUB)
2759     emit_writehword(rt,(int)&hword);
2760   if(type==STOREW_STUB)
2761     emit_writeword(rt,(int)&word);
2762   if(type==STORED_STUB) {
2763 #ifndef FORCE32
2764     emit_writeword(rt,(int)&dword);
2765     emit_writeword(target?rth:rt,(int)&dword+4);
2766 #else
2767     printf("STORED_STUB\n");
2768 #endif
2769   }
2770   //emit_pusha();
2771   save_regs(reglist);
2772   //emit_shrimm(rs,16,1);
2773   int cc=get_reg(regmap,CCREG);
2774   if(cc<0) {
2775     emit_loadreg(CCREG,2);
2776   }
2777   //emit_movimm(ftable,0);
2778   emit_movimm(((u_int *)ftable)[addr>>16],0);
2779   //emit_readword((int)&last_count,12);
2780   emit_addimm(cc<0?2:cc,CLOCK_DIVIDER*(adj+1),2);
2781   if((signed int)addr>=(signed int)0xC0000000) {
2782     // Pagefault address
2783     int ds=regmap!=regs[i].regmap;
2784     emit_movimm(start+i*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
2785   }
2786   //emit_add(12,2,2);
2787   //emit_writeword(2,(int)&Count);
2788   //emit_call(((u_int *)ftable)[addr>>16]);
2789   emit_call((int)&indirect_jump);
2790   emit_readword((int)&Count,HOST_TEMPREG);
2791   emit_readword((int)&next_interupt,2);
2792   emit_addimm(HOST_TEMPREG,-CLOCK_DIVIDER*(adj+1),HOST_TEMPREG);
2793   emit_writeword(2,(int)&last_count);
2794   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
2795   if(cc<0) {
2796     emit_storereg(CCREG,HOST_TEMPREG);
2797   }
2798   //emit_popa();
2799   restore_regs(reglist);
2800 }
2801
2802 do_unalignedwritestub(int n)
2803 {
2804   set_jump_target(stubs[n][1],(int)out);
2805   output_w32(0xef000000);
2806   emit_jmp(stubs[n][2]); // return address
2807 }
2808
2809 void printregs(int edi,int esi,int ebp,int esp,int b,int d,int c,int a)
2810 {
2811   printf("regs: %x %x %x %x %x %x %x (%x)\n",a,b,c,d,ebp,esi,edi,(&edi)[-1]);
2812 }
2813
2814 do_invstub(int n)
2815 {
2816   literal_pool(20);
2817   u_int reglist=stubs[n][3];
2818   set_jump_target(stubs[n][1],(int)out);
2819   save_regs(reglist);
2820   if(stubs[n][4]!=0) emit_mov(stubs[n][4],0);
2821   emit_call((int)&invalidate_addr);
2822   restore_regs(reglist);
2823   emit_jmp(stubs[n][2]); // return address
2824 }
2825
2826 int do_dirty_stub(int i)
2827 {
2828   assem_debug("do_dirty_stub %x\n",start+i*4);
2829   // Careful about the code output here, verify_dirty needs to parse it.
2830   #ifdef ARMv5_ONLY
2831   emit_loadlp((int)start<(int)0xC0000000?(int)source:(int)start,1);
2832   emit_loadlp((int)copy,2);
2833   emit_loadlp(slen*4,3);
2834   #else
2835   emit_movw(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0x0000FFFF,1);
2836   emit_movw(((u_int)copy)&0x0000FFFF,2);
2837   emit_movt(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0xFFFF0000,1);
2838   emit_movt(((u_int)copy)&0xFFFF0000,2);
2839   emit_movw(slen*4,3);
2840   #endif
2841   emit_movimm(start+i*4,0);
2842   emit_call((int)start<(int)0xC0000000?(int)&verify_code:(int)&verify_code_vm);
2843   int entry=(int)out;
2844   load_regs_entry(i);
2845   if(entry==(int)out) entry=instr_addr[i];
2846   emit_jmp(instr_addr[i]);
2847   return entry;
2848 }
2849
2850 void do_dirty_stub_ds()
2851 {
2852   // Careful about the code output here, verify_dirty needs to parse it.
2853   #ifdef ARMv5_ONLY
2854   emit_loadlp((int)start<(int)0xC0000000?(int)source:(int)start,1);
2855   emit_loadlp((int)copy,2);
2856   emit_loadlp(slen*4,3);
2857   #else
2858   emit_movw(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0x0000FFFF,1);
2859   emit_movw(((u_int)copy)&0x0000FFFF,2);
2860   emit_movt(((int)start<(int)0xC0000000?(u_int)source:(u_int)start)&0xFFFF0000,1);
2861   emit_movt(((u_int)copy)&0xFFFF0000,2);
2862   emit_movw(slen*4,3);
2863   #endif
2864   emit_movimm(start+1,0);
2865   emit_call((int)&verify_code_ds);
2866 }
2867
2868 do_cop1stub(int n)
2869 {
2870   literal_pool(256);
2871   assem_debug("do_cop1stub %x\n",start+stubs[n][3]*4);
2872   set_jump_target(stubs[n][1],(int)out);
2873   int i=stubs[n][3];
2874 //  int rs=stubs[n][4];
2875   struct regstat *i_regs=(struct regstat *)stubs[n][5];
2876   int ds=stubs[n][6];
2877   if(!ds) {
2878     load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
2879     //if(i_regs!=&regs[i]) printf("oops: regs[i]=%x i_regs=%x",(int)&regs[i],(int)i_regs);
2880   }
2881   //else {printf("fp exception in delay slot\n");}
2882   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty);
2883   if(regs[i].regmap_entry[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
2884   emit_movimm(start+(i-ds)*4,EAX); // Get PC
2885   emit_addimm(HOST_CCREG,CLOCK_DIVIDER*ccadj[i],HOST_CCREG); // CHECK: is this right?  There should probably be an extra cycle...
2886   emit_jmp(ds?(int)fp_exception_ds:(int)fp_exception);
2887 }
2888
2889 /* TLB */
2890
2891 int do_tlb_r(int s,int ar,int map,int x,int a,int shift,int c,u_int addr)
2892 {
2893   if(c) {
2894     if((signed int)addr>=(signed int)0xC0000000) {
2895       // address_generation already loaded the const
2896       emit_readword_dualindexedx4(FP,map,map);
2897     }
2898     else
2899       return -1; // No mapping
2900   }
2901   else {
2902     assert(s!=map);
2903     emit_movimm(((int)memory_map-(int)&dynarec_local)>>2,map);
2904     emit_addsr12(map,s,map);
2905     // Schedule this while we wait on the load
2906     //if(x) emit_xorimm(s,x,ar);
2907     if(shift>=0) emit_shlimm(s,3,shift);
2908     if(~a) emit_andimm(s,a,ar);
2909     emit_readword_dualindexedx4(FP,map,map);
2910   }
2911   return map;
2912 }
2913 int do_tlb_r_branch(int map, int c, u_int addr, int *jaddr)
2914 {
2915   if(!c||(signed int)addr>=(signed int)0xC0000000) {
2916     emit_test(map,map);
2917     *jaddr=(int)out;
2918     emit_js(0);
2919   }
2920   return map;
2921 }
2922
2923 int gen_tlb_addr_r(int ar, int map) {
2924   if(map>=0) {
2925     assem_debug("add %s,%s,%s lsl #2\n",regname[ar],regname[ar],regname[map]);
2926     output_w32(0xe0800100|rd_rn_rm(ar,ar,map));
2927   }
2928 }
2929
2930 int do_tlb_w(int s,int ar,int map,int x,int c,u_int addr)
2931 {
2932   if(c) {
2933     if(addr<0x80800000||addr>=0xC0000000) {
2934       // address_generation already loaded the const
2935       emit_readword_dualindexedx4(FP,map,map);
2936     }
2937     else
2938       return -1; // No mapping
2939   }
2940   else {
2941     assert(s!=map);
2942     emit_movimm(((int)memory_map-(int)&dynarec_local)>>2,map);
2943     emit_addsr12(map,s,map);
2944     // Schedule this while we wait on the load
2945     //if(x) emit_xorimm(s,x,ar);
2946     emit_readword_dualindexedx4(FP,map,map);
2947   }
2948   return map;
2949 }
2950 int do_tlb_w_branch(int map, int c, u_int addr, int *jaddr)
2951 {
2952   if(!c||addr<0x80800000||addr>=0xC0000000) {
2953     emit_testimm(map,0x40000000);
2954     *jaddr=(int)out;
2955     emit_jne(0);
2956   }
2957 }
2958
2959 int gen_tlb_addr_w(int ar, int map) {
2960   if(map>=0) {
2961     assem_debug("add %s,%s,%s lsl #2\n",regname[ar],regname[ar],regname[map]);
2962     output_w32(0xe0800100|rd_rn_rm(ar,ar,map));
2963   }
2964 }
2965
2966 // Generate the address of the memory_map entry, relative to dynarec_local
2967 generate_map_const(u_int addr,int reg) {
2968   //printf("generate_map_const(%x,%s)\n",addr,regname[reg]);
2969   emit_movimm((addr>>12)+(((u_int)memory_map-(u_int)&dynarec_local)>>2),reg);
2970 }
2971
2972 /* Special assem */
2973
2974 void shift_assemble_arm(int i,struct regstat *i_regs)
2975 {
2976   if(rt1[i]) {
2977     if(opcode2[i]<=0x07) // SLLV/SRLV/SRAV
2978     {
2979       signed char s,t,shift;
2980       t=get_reg(i_regs->regmap,rt1[i]);
2981       s=get_reg(i_regs->regmap,rs1[i]);
2982       shift=get_reg(i_regs->regmap,rs2[i]);
2983       if(t>=0){
2984         if(rs1[i]==0)
2985         {
2986           emit_zeroreg(t);
2987         }
2988         else if(rs2[i]==0)
2989         {
2990           assert(s>=0);
2991           if(s!=t) emit_mov(s,t);
2992         }
2993         else
2994         {
2995           emit_andimm(shift,31,HOST_TEMPREG);
2996           if(opcode2[i]==4) // SLLV
2997           {
2998             emit_shl(s,HOST_TEMPREG,t);
2999           }
3000           if(opcode2[i]==6) // SRLV
3001           {
3002             emit_shr(s,HOST_TEMPREG,t);
3003           }
3004           if(opcode2[i]==7) // SRAV
3005           {
3006             emit_sar(s,HOST_TEMPREG,t);
3007           }
3008         }
3009       }
3010     } else { // DSLLV/DSRLV/DSRAV
3011       signed char sh,sl,th,tl,shift;
3012       th=get_reg(i_regs->regmap,rt1[i]|64);
3013       tl=get_reg(i_regs->regmap,rt1[i]);
3014       sh=get_reg(i_regs->regmap,rs1[i]|64);
3015       sl=get_reg(i_regs->regmap,rs1[i]);
3016       shift=get_reg(i_regs->regmap,rs2[i]);
3017       if(tl>=0){
3018         if(rs1[i]==0)
3019         {
3020           emit_zeroreg(tl);
3021           if(th>=0) emit_zeroreg(th);
3022         }
3023         else if(rs2[i]==0)
3024         {
3025           assert(sl>=0);
3026           if(sl!=tl) emit_mov(sl,tl);
3027           if(th>=0&&sh!=th) emit_mov(sh,th);
3028         }
3029         else
3030         {
3031           // FIXME: What if shift==tl ?
3032           assert(shift!=tl);
3033           int temp=get_reg(i_regs->regmap,-1);
3034           int real_th=th;
3035           if(th<0&&opcode2[i]!=0x14) {th=temp;} // DSLLV doesn't need a temporary register
3036           assert(sl>=0);
3037           assert(sh>=0);
3038           emit_andimm(shift,31,HOST_TEMPREG);
3039           if(opcode2[i]==0x14) // DSLLV
3040           {
3041             if(th>=0) emit_shl(sh,HOST_TEMPREG,th);
3042             emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
3043             emit_orrshr(sl,HOST_TEMPREG,th);
3044             emit_andimm(shift,31,HOST_TEMPREG);
3045             emit_testimm(shift,32);
3046             emit_shl(sl,HOST_TEMPREG,tl);
3047             if(th>=0) emit_cmovne_reg(tl,th);
3048             emit_cmovne_imm(0,tl);
3049           }
3050           if(opcode2[i]==0x16) // DSRLV
3051           {
3052             assert(th>=0);
3053             emit_shr(sl,HOST_TEMPREG,tl);
3054             emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
3055             emit_orrshl(sh,HOST_TEMPREG,tl);
3056             emit_andimm(shift,31,HOST_TEMPREG);
3057             emit_testimm(shift,32);
3058             emit_shr(sh,HOST_TEMPREG,th);
3059             emit_cmovne_reg(th,tl);
3060             if(real_th>=0) emit_cmovne_imm(0,th);
3061           }
3062           if(opcode2[i]==0x17) // DSRAV
3063           {
3064             assert(th>=0);
3065             emit_shr(sl,HOST_TEMPREG,tl);
3066             emit_rsbimm(HOST_TEMPREG,32,HOST_TEMPREG);
3067             if(real_th>=0) {
3068               assert(temp>=0);
3069               emit_sarimm(th,31,temp);
3070             }
3071             emit_orrshl(sh,HOST_TEMPREG,tl);
3072             emit_andimm(shift,31,HOST_TEMPREG);
3073             emit_testimm(shift,32);
3074             emit_sar(sh,HOST_TEMPREG,th);
3075             emit_cmovne_reg(th,tl);
3076             if(real_th>=0) emit_cmovne_reg(temp,th);
3077           }
3078         }
3079       }
3080     }
3081   }
3082 }
3083 #define shift_assemble shift_assemble_arm
3084
3085 void loadlr_assemble_arm(int i,struct regstat *i_regs)
3086 {
3087   int s,th,tl,temp,temp2,addr,map=-1;
3088   int offset;
3089   int jaddr=0;
3090   int memtarget,c=0;
3091   u_int hr,reglist=0;
3092   th=get_reg(i_regs->regmap,rt1[i]|64);
3093   tl=get_reg(i_regs->regmap,rt1[i]);
3094   s=get_reg(i_regs->regmap,rs1[i]);
3095   temp=get_reg(i_regs->regmap,-1);
3096   temp2=get_reg(i_regs->regmap,FTEMP);
3097   addr=get_reg(i_regs->regmap,AGEN1+(i&1));
3098   assert(addr<0);
3099   offset=imm[i];
3100   for(hr=0;hr<HOST_REGS;hr++) {
3101     if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
3102   }
3103   reglist|=1<<temp;
3104   if(offset||s<0||c) addr=temp2;
3105   else addr=s;
3106   if(s>=0) {
3107     c=(i_regs->wasconst>>s)&1;
3108     memtarget=((signed int)(constmap[i][s]+offset))<(signed int)0x80800000;
3109     if(using_tlb&&((signed int)(constmap[i][s]+offset))>=(signed int)0xC0000000) memtarget=1;
3110   }
3111   if(tl>=0) {
3112     //assert(tl>=0);
3113     //assert(rt1[i]);
3114     if(!using_tlb) {
3115       if(!c) {
3116         emit_shlimm(addr,3,temp);
3117         if (opcode[i]==0x22||opcode[i]==0x26) {
3118           emit_andimm(addr,0xFFFFFFFC,temp2); // LWL/LWR
3119         }else{
3120           emit_andimm(addr,0xFFFFFFF8,temp2); // LDL/LDR
3121         }
3122         emit_cmpimm(addr,0x800000);
3123         jaddr=(int)out;
3124         emit_jno(0);
3125       }
3126       else {
3127         if (opcode[i]==0x22||opcode[i]==0x26) {
3128           emit_movimm(((constmap[i][s]+offset)<<3)&24,temp); // LWL/LWR
3129         }else{
3130           emit_movimm(((constmap[i][s]+offset)<<3)&56,temp); // LDL/LDR
3131         }
3132       }
3133     }else{ // using tlb
3134       int a;
3135       if(c) {
3136         a=-1;
3137       }else if (opcode[i]==0x22||opcode[i]==0x26) {
3138         a=0xFFFFFFFC; // LWL/LWR
3139       }else{
3140         a=0xFFFFFFF8; // LDL/LDR
3141       }
3142       map=get_reg(i_regs->regmap,TLREG);
3143       assert(map>=0);
3144       map=do_tlb_r(addr,temp2,map,0,a,c?-1:temp,c,constmap[i][s]+offset);
3145       if(c) {
3146         if (opcode[i]==0x22||opcode[i]==0x26) {
3147           emit_movimm(((constmap[i][s]+offset)<<3)&24,temp); // LWL/LWR
3148         }else{
3149           emit_movimm(((constmap[i][s]+offset)<<3)&56,temp); // LDL/LDR
3150         }
3151       }
3152       do_tlb_r_branch(map,c,constmap[i][s]+offset,&jaddr);
3153     }
3154     if (opcode[i]==0x22||opcode[i]==0x26) { // LWL/LWR
3155       if(!c||memtarget) {
3156         //emit_readword_indexed((int)rdram-0x80000000,temp2,temp2);
3157         emit_readword_indexed_tlb((int)rdram-0x80000000,temp2,map,temp2);
3158         if(jaddr) add_stub(LOADW_STUB,jaddr,(int)out,i,temp2,(int)i_regs,ccadj[i],reglist);
3159       }
3160       else
3161         inline_readstub(LOADW_STUB,i,(constmap[i][s]+offset)&0xFFFFFFFC,i_regs->regmap,FTEMP,ccadj[i],reglist);
3162       emit_andimm(temp,24,temp);
3163       if (opcode[i]==0x26) emit_xorimm(temp,24,temp); // LWR
3164       emit_movimm(-1,HOST_TEMPREG);
3165       if (opcode[i]==0x26) {
3166         emit_shr(temp2,temp,temp2);
3167         emit_bic_lsr(tl,HOST_TEMPREG,temp,tl);
3168       }else{
3169         emit_shl(temp2,temp,temp2);
3170         emit_bic_lsl(tl,HOST_TEMPREG,temp,tl);
3171       }
3172       emit_or(temp2,tl,tl);
3173       //emit_storereg(rt1[i],tl); // DEBUG
3174     }
3175     if (opcode[i]==0x1A||opcode[i]==0x1B) { // LDL/LDR
3176       int temp2h=get_reg(i_regs->regmap,FTEMP|64);
3177       if(!c||memtarget) {
3178         //if(th>=0) emit_readword_indexed((int)rdram-0x80000000,temp2,temp2h);
3179         //emit_readword_indexed((int)rdram-0x7FFFFFFC,temp2,temp2);
3180         emit_readdword_indexed_tlb((int)rdram-0x80000000,temp2,map,temp2h,temp2);
3181         if(jaddr) add_stub(LOADD_STUB,jaddr,(int)out,i,temp2,(int)i_regs,ccadj[i],reglist);
3182       }
3183       else
3184         inline_readstub(LOADD_STUB,i,(constmap[i][s]+offset)&0xFFFFFFF8,i_regs->regmap,FTEMP,ccadj[i],reglist);
3185       emit_testimm(temp,32);
3186       emit_andimm(temp,24,temp);
3187       if (opcode[i]==0x1A) { // LDL
3188         emit_rsbimm(temp,32,HOST_TEMPREG);
3189         emit_shl(temp2h,temp,temp2h);
3190         emit_orrshr(temp2,HOST_TEMPREG,temp2h);
3191         emit_movimm(-1,HOST_TEMPREG);
3192         emit_shl(temp2,temp,temp2);
3193         emit_cmove_reg(temp2h,th);
3194         emit_biceq_lsl(tl,HOST_TEMPREG,temp,tl);
3195         emit_bicne_lsl(th,HOST_TEMPREG,temp,th);
3196         emit_orreq(temp2,tl,tl);
3197         emit_orrne(temp2,th,th);
3198       }
3199       if (opcode[i]==0x1B) { // LDR
3200         emit_xorimm(temp,24,temp);
3201         emit_rsbimm(temp,32,HOST_TEMPREG);
3202         emit_shr(temp2,temp,temp2);
3203         emit_orrshl(temp2h,HOST_TEMPREG,temp2);
3204         emit_movimm(-1,HOST_TEMPREG);
3205         emit_shr(temp2h,temp,temp2h);
3206         emit_cmovne_reg(temp2,tl);
3207         emit_bicne_lsr(th,HOST_TEMPREG,temp,th);
3208         emit_biceq_lsr(tl,HOST_TEMPREG,temp,tl);
3209         emit_orrne(temp2h,th,th);
3210         emit_orreq(temp2h,tl,tl);
3211       }
3212     }
3213   }
3214 }
3215 #define loadlr_assemble loadlr_assemble_arm
3216
3217 void cop0_assemble(int i,struct regstat *i_regs)
3218 {
3219   if(opcode2[i]==0) // MFC0
3220   {
3221     signed char t=get_reg(i_regs->regmap,rt1[i]);
3222     char copr=(source[i]>>11)&0x1f;
3223     //assert(t>=0); // Why does this happen?  OOT is weird
3224     if(t>=0) {
3225 #ifdef MUPEN64 /// FIXME
3226       emit_addimm(FP,(int)&fake_pc-(int)&dynarec_local,0);
3227       emit_movimm((source[i]>>11)&0x1f,1);
3228       emit_writeword(0,(int)&PC);
3229       emit_writebyte(1,(int)&(fake_pc.f.r.nrd));
3230 #endif
3231       if(copr==9) {
3232         emit_readword((int)&last_count,ECX);
3233         emit_loadreg(CCREG,HOST_CCREG); // TODO: do proper reg alloc
3234         emit_add(HOST_CCREG,ECX,HOST_CCREG);
3235         emit_addimm(HOST_CCREG,CLOCK_DIVIDER*ccadj[i],HOST_CCREG);
3236         emit_writeword(HOST_CCREG,(int)&Count);
3237       }
3238       emit_call((int)MFC0);
3239       emit_readword((int)&readmem_dword,t);
3240     }
3241   }
3242   else if(opcode2[i]==4) // MTC0
3243   {
3244     signed char s=get_reg(i_regs->regmap,rs1[i]);
3245     char copr=(source[i]>>11)&0x1f;
3246     assert(s>=0);
3247     emit_writeword(s,(int)&readmem_dword);
3248     wb_register(rs1[i],i_regs->regmap,i_regs->dirty,i_regs->is32);
3249 #ifdef MUPEN64 /// FIXME
3250     emit_addimm(FP,(int)&fake_pc-(int)&dynarec_local,0);
3251     emit_movimm((source[i]>>11)&0x1f,1);
3252     emit_writeword(0,(int)&PC);
3253     emit_writebyte(1,(int)&(fake_pc.f.r.nrd));
3254 #endif
3255     if(copr==9||copr==11||copr==12) {
3256       emit_readword((int)&last_count,ECX);
3257       emit_loadreg(CCREG,HOST_CCREG); // TODO: do proper reg alloc
3258       emit_add(HOST_CCREG,ECX,HOST_CCREG);
3259       emit_addimm(HOST_CCREG,CLOCK_DIVIDER*ccadj[i],HOST_CCREG);
3260       emit_writeword(HOST_CCREG,(int)&Count);
3261     }
3262     // What a mess.  The status register (12) can enable interrupts,
3263     // so needs a special case to handle a pending interrupt.
3264     // The interrupt must be taken immediately, because a subsequent
3265     // instruction might disable interrupts again.
3266     if(copr==12&&!is_delayslot) {
3267       emit_movimm(start+i*4+4,0);
3268       emit_movimm(0,1);
3269       emit_writeword(0,(int)&pcaddr);
3270       emit_writeword(1,(int)&pending_exception);
3271     }
3272     //else if(copr==12&&is_delayslot) emit_call((int)MTC0_R12);
3273     //else
3274     emit_call((int)MTC0);
3275     if(copr==9||copr==11||copr==12) {
3276       emit_readword((int)&Count,HOST_CCREG);
3277       emit_readword((int)&next_interupt,ECX);
3278       emit_addimm(HOST_CCREG,-CLOCK_DIVIDER*ccadj[i],HOST_CCREG);
3279       emit_sub(HOST_CCREG,ECX,HOST_CCREG);
3280       emit_writeword(ECX,(int)&last_count);
3281       emit_storereg(CCREG,HOST_CCREG);
3282     }
3283     if(copr==12) {
3284       assert(!is_delayslot);
3285       emit_readword((int)&pending_exception,14);
3286     }
3287     emit_loadreg(rs1[i],s);
3288     if(get_reg(i_regs->regmap,rs1[i]|64)>=0)
3289       emit_loadreg(rs1[i]|64,get_reg(i_regs->regmap,rs1[i]|64));
3290     if(copr==12) {
3291       emit_test(14,14);
3292       emit_jne((int)&do_interrupt);
3293     }
3294     cop1_usable=0;
3295   }
3296   else
3297   {
3298     assert(opcode2[i]==0x10);
3299 #ifndef DISABLE_TLB
3300     if((source[i]&0x3f)==0x01) // TLBR
3301       emit_call((int)TLBR);
3302     if((source[i]&0x3f)==0x02) // TLBWI
3303       emit_call((int)TLBWI_new);
3304     if((source[i]&0x3f)==0x06) { // TLBWR
3305       // The TLB entry written by TLBWR is dependent on the count,
3306       // so update the cycle count
3307       emit_readword((int)&last_count,ECX);
3308       if(i_regs->regmap[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
3309       emit_add(HOST_CCREG,ECX,HOST_CCREG);
3310       emit_addimm(HOST_CCREG,CLOCK_DIVIDER*ccadj[i],HOST_CCREG);
3311       emit_writeword(HOST_CCREG,(int)&Count);
3312       emit_call((int)TLBWR_new);
3313     }
3314     if((source[i]&0x3f)==0x08) // TLBP
3315       emit_call((int)TLBP);
3316 #endif
3317     if((source[i]&0x3f)==0x18) // ERET
3318     {
3319       int count=ccadj[i];
3320       if(i_regs->regmap[HOST_CCREG]!=CCREG) emit_loadreg(CCREG,HOST_CCREG);
3321       emit_addimm(HOST_CCREG,CLOCK_DIVIDER*count,HOST_CCREG); // TODO: Should there be an extra cycle here?
3322       emit_jmp((int)jump_eret);
3323     }
3324   }
3325 }
3326
3327 void cop1_unusable(int i, struct regstat *i_regs)
3328 {
3329   // XXX: should just just do the exception instead
3330   if(!cop1_usable) {
3331     int jaddr=(int)out;
3332     emit_jmp(0);
3333     add_stub(FP_STUB,jaddr,(int)out,i,0,(int)i_regs,is_delayslot,0);
3334     cop1_usable=1;
3335   }
3336 }
3337
3338 void cop1_assemble(int i,struct regstat *i_regs)
3339 {
3340 #ifndef DISABLE_COP1
3341   // Check cop1 unusable
3342   if(!cop1_usable) {
3343     signed char rs=get_reg(i_regs->regmap,CSREG);
3344     assert(rs>=0);
3345     emit_testimm(rs,0x20000000);
3346     int jaddr=(int)out;
3347     emit_jeq(0);
3348     add_stub(FP_STUB,jaddr,(int)out,i,rs,(int)i_regs,is_delayslot,0);
3349     cop1_usable=1;
3350   }
3351   if (opcode2[i]==0) { // MFC1
3352     signed char tl=get_reg(i_regs->regmap,rt1[i]);
3353     if(tl>=0) {
3354       emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],tl);
3355       emit_readword_indexed(0,tl,tl);
3356     }
3357   }
3358   else if (opcode2[i]==1) { // DMFC1
3359     signed char tl=get_reg(i_regs->regmap,rt1[i]);
3360     signed char th=get_reg(i_regs->regmap,rt1[i]|64);
3361     if(tl>=0) {
3362       emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],tl);
3363       if(th>=0) emit_readword_indexed(4,tl,th);
3364       emit_readword_indexed(0,tl,tl);
3365     }
3366   }
3367   else if (opcode2[i]==4) { // MTC1
3368     signed char sl=get_reg(i_regs->regmap,rs1[i]);
3369     signed char temp=get_reg(i_regs->regmap,-1);
3370     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
3371     emit_writeword_indexed(sl,0,temp);
3372   }
3373   else if (opcode2[i]==5) { // DMTC1
3374     signed char sl=get_reg(i_regs->regmap,rs1[i]);
3375     signed char sh=rs1[i]>0?get_reg(i_regs->regmap,rs1[i]|64):sl;
3376     signed char temp=get_reg(i_regs->regmap,-1);
3377     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],temp);
3378     emit_writeword_indexed(sh,4,temp);
3379     emit_writeword_indexed(sl,0,temp);
3380   }
3381   else if (opcode2[i]==2) // CFC1
3382   {
3383     signed char tl=get_reg(i_regs->regmap,rt1[i]);
3384     if(tl>=0) {
3385       u_int copr=(source[i]>>11)&0x1f;
3386       if(copr==0) emit_readword((int)&FCR0,tl);
3387       if(copr==31) emit_readword((int)&FCR31,tl);
3388     }
3389   }
3390   else if (opcode2[i]==6) // CTC1
3391   {
3392     signed char sl=get_reg(i_regs->regmap,rs1[i]);
3393     u_int copr=(source[i]>>11)&0x1f;
3394     assert(sl>=0);
3395     if(copr==31)
3396     {
3397       emit_writeword(sl,(int)&FCR31);
3398       // Set the rounding mode
3399       //FIXME
3400       //char temp=get_reg(i_regs->regmap,-1);
3401       //emit_andimm(sl,3,temp);
3402       //emit_fldcw_indexed((int)&rounding_modes,temp);
3403     }
3404   }
3405 #else
3406   cop1_unusable(i, i_regs);
3407 #endif
3408 }
3409
3410 void fconv_assemble_arm(int i,struct regstat *i_regs)
3411 {
3412 #ifndef DISABLE_COP1
3413   signed char temp=get_reg(i_regs->regmap,-1);
3414   assert(temp>=0);
3415   // Check cop1 unusable
3416   if(!cop1_usable) {
3417     signed char rs=get_reg(i_regs->regmap,CSREG);
3418     assert(rs>=0);
3419     emit_testimm(rs,0x20000000);
3420     int jaddr=(int)out;
3421     emit_jeq(0);
3422     add_stub(FP_STUB,jaddr,(int)out,i,rs,(int)i_regs,is_delayslot,0);
3423     cop1_usable=1;
3424   }
3425   
3426   #if(defined(__VFP_FP__) && !defined(__SOFTFP__)) 
3427   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x0d) { // trunc_w_s
3428     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
3429     emit_flds(temp,15);
3430     emit_ftosizs(15,15); // float->int, truncate
3431     if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f))
3432       emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],temp);
3433     emit_fsts(15,temp);
3434     return;
3435   }
3436   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x0d) { // trunc_w_d
3437     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],temp);
3438     emit_vldr(temp,7);
3439     emit_ftosizd(7,13); // double->int, truncate
3440     emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],temp);
3441     emit_fsts(13,temp);
3442     return;
3443   }
3444   
3445   if(opcode2[i]==0x14&&(source[i]&0x3f)==0x20) { // cvt_s_w
3446     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
3447     emit_flds(temp,13);
3448     if(((source[i]>>11)&0x1f)!=((source[i]>>6)&0x1f))
3449       emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],temp);
3450     emit_fsitos(13,15);
3451     emit_fsts(15,temp);
3452     return;
3453   }
3454   if(opcode2[i]==0x14&&(source[i]&0x3f)==0x21) { // cvt_d_w
3455     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
3456     emit_flds(temp,13);
3457     emit_readword((int)&reg_cop1_double[(source[i]>>6)&0x1f],temp);
3458     emit_fsitod(13,7);
3459     emit_vstr(7,temp);
3460     return;
3461   }
3462   
3463   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x21) { // cvt_d_s
3464     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],temp);
3465     emit_flds(temp,13);
3466     emit_readword((int)&reg_cop1_double[(source[i]>>6)&0x1f],temp);
3467     emit_fcvtds(13,7);
3468     emit_vstr(7,temp);
3469     return;
3470   }
3471   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x20) { // cvt_s_d
3472     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],temp);
3473     emit_vldr(temp,7);
3474     emit_readword((int)&reg_cop1_simple[(source[i]>>6)&0x1f],temp);
3475     emit_fcvtsd(7,13);
3476     emit_fsts(13,temp);
3477     return;
3478   }
3479   #endif
3480   
3481   // C emulation code
3482   
3483   u_int hr,reglist=0;
3484   for(hr=0;hr<HOST_REGS;hr++) {
3485     if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
3486   }
3487   save_regs(reglist);
3488   
3489   if(opcode2[i]==0x14&&(source[i]&0x3f)==0x20) {
3490     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
3491     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
3492     emit_call((int)cvt_s_w);
3493   }
3494   if(opcode2[i]==0x14&&(source[i]&0x3f)==0x21) {
3495     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
3496     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
3497     emit_call((int)cvt_d_w);
3498   }
3499   if(opcode2[i]==0x15&&(source[i]&0x3f)==0x20) {
3500     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
3501     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
3502     emit_call((int)cvt_s_l);
3503   }
3504   if(opcode2[i]==0x15&&(source[i]&0x3f)==0x21) {
3505     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
3506     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
3507     emit_call((int)cvt_d_l);
3508   }
3509   
3510   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x21) {
3511     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
3512     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
3513     emit_call((int)cvt_d_s);
3514   }
3515   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x24) {
3516     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
3517     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
3518     emit_call((int)cvt_w_s);
3519   }
3520   if(opcode2[i]==0x10&&(source[i]&0x3f)==0x25) {
3521     emit_readword((int)&reg_cop1_simple[(source[i]>>11)&0x1f],ARG1_REG);
3522     emit_readword((int)&reg_cop1_double[(source[i]>> 6)&0x1f],ARG2_REG);
3523     emit_call((int)cvt_l_s);
3524   }
3525   
3526   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x20) {
3527     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
3528     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
3529     emit_call((int)cvt_s_d);
3530   }
3531   if(opcode2[i]==0x11&&(source[i]&0x3f)==0x24) {
3532     emit_readword((int)&reg_cop1_double[(source[i]>>11)&0x1f],ARG1_REG);
3533     emit_readword((int)&reg_cop1_simple[(source[i]>> 6)&0x1f],ARG2_REG);
3534     emit_call((int)cvt_w_d);