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