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