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