drc: inv: fix ram ofset and mirror handling
[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
32 #if !BASE_ADDR_FIXED
33 char translation_cache[1 << TARGET_SIZE_2] __attribute__((aligned(4096)));
34 #endif
35
36 extern int cycle_count;
37 extern int last_count;
38 extern int pcaddr;
39 extern int pending_exception;
40 extern int branch_target;
41 extern uint64_t readmem_dword;
42 #ifdef MUPEN64
43 extern precomp_instr fake_pc;
44 #endif
45 extern void *dynarec_local;
46 extern u_int memory_map[1048576];
47 extern u_int mini_ht[32][2];
48 extern u_int rounding_modes[4];
49
50 void indirect_jump_indexed();
51 void indirect_jump();
52 void do_interrupt();
53 void jump_vaddr_r0();
54 void jump_vaddr_r1();
55 void jump_vaddr_r2();
56 void jump_vaddr_r3();
57 void jump_vaddr_r4();
58 void jump_vaddr_r5();
59 void jump_vaddr_r6();
60 void jump_vaddr_r7();
61 void jump_vaddr_r8();
62 void jump_vaddr_r9();
63 void jump_vaddr_r10();
64 void jump_vaddr_r12();
65
66 const u_int jump_vaddr_reg[16] = {
67   (int)jump_vaddr_r0,
68   (int)jump_vaddr_r1,
69   (int)jump_vaddr_r2,
70   (int)jump_vaddr_r3,
71   (int)jump_vaddr_r4,
72   (int)jump_vaddr_r5,
73   (int)jump_vaddr_r6,
74   (int)jump_vaddr_r7,
75   (int)jump_vaddr_r8,
76   (int)jump_vaddr_r9,
77   (int)jump_vaddr_r10,
78   0,
79   (int)jump_vaddr_r12,
80   0,
81   0,
82   0};
83
84 void invalidate_addr_r0();
85 void invalidate_addr_r1();
86 void invalidate_addr_r2();
87 void invalidate_addr_r3();
88 void invalidate_addr_r4();
89 void invalidate_addr_r5();
90 void invalidate_addr_r6();
91 void invalidate_addr_r7();
92 void invalidate_addr_r8();
93 void invalidate_addr_r9();
94 void invalidate_addr_r10();
95 void invalidate_addr_r12();
96
97 const u_int invalidate_addr_reg[16] = {
98   (int)invalidate_addr_r0,
99   (int)invalidate_addr_r1,
100   (int)invalidate_addr_r2,
101   (int)invalidate_addr_r3,
102   (int)invalidate_addr_r4,
103   (int)invalidate_addr_r5,
104   (int)invalidate_addr_r6,
105   (int)invalidate_addr_r7,
106   (int)invalidate_addr_r8,
107   (int)invalidate_addr_r9,
108   (int)invalidate_addr_r10,
109   0,
110   (int)invalidate_addr_r12,
111   0,
112   0,
113   0};
114
115 #include "fpu.h"
116
117 unsigned int needs_clear_cache[1<<(TARGET_SIZE_2-17)];
118
119 /* Linker */
120
121 void set_jump_target(int addr,u_int target)
122 {
123   u_char *ptr=(u_char *)addr;
124   u_int *ptr2=(u_int *)ptr;
125   if(ptr[3]==0xe2) {
126     assert((target-(u_int)ptr2-8)<1024);
127     assert((addr&3)==0);
128     assert((target&3)==0);
129     *ptr2=(*ptr2&0xFFFFF000)|((target-(u_int)ptr2-8)>>2)|0xF00;
130     //printf("target=%x addr=%x insn=%x\n",target,addr,*ptr2);
131   }
132   else if(ptr[3]==0x72) {
133     // generated by emit_jno_unlikely
134     if((target-(u_int)ptr2-8)<1024) {
135       assert((addr&3)==0);
136       assert((target&3)==0);
137       *ptr2=(*ptr2&0xFFFFF000)|((target-(u_int)ptr2-8)>>2)|0xF00;
138     }
139     else if((target-(u_int)ptr2-8)<4096&&!((target-(u_int)ptr2-8)&15)) {
140       assert((addr&3)==0);
141       assert((target&3)==0);
142       *ptr2=(*ptr2&0xFFFFF000)|((target-(u_int)ptr2-8)>>4)|0xE00;
143     }
144     else *ptr2=(0x7A000000)|(((target-(u_int)ptr2-8)<<6)>>8);
145   }
146   else {
147     assert((ptr[3]&0x0e)==0xa);
148     *ptr2=(*ptr2&0xFF000000)|(((target-(u_int)ptr2-8)<<6)>>8);
149   }
150 }
151
152 // This optionally copies the instruction from the target of the branch into
153 // the space before the branch.  Works, but the difference in speed is
154 // usually insignificant.
155 void set_jump_target_fillslot(int addr,u_int target,int copy)
156 {
157   u_char *ptr=(u_char *)addr;
158   u_int *ptr2=(u_int *)ptr;
159   assert(!copy||ptr2[-1]==0xe28dd000);
160   if(ptr[3]==0xe2) {
161     assert(!copy);
162     assert((target-(u_int)ptr2-8)<4096);
163     *ptr2=(*ptr2&0xFFFFF000)|(target-(u_int)ptr2-8);
164   }
165   else {
166     assert((ptr[3]&0x0e)==0xa);
167     u_int target_insn=*(u_int *)target;
168     if((target_insn&0x0e100000)==0) { // ALU, no immediate, no flags
169       copy=0;
170     }
171     if((target_insn&0x0c100000)==0x04100000) { // Load
172       copy=0;
173     }
174     if(target_insn&0x08000000) {
175       copy=0;
176     }
177     if(copy) {
178       ptr2[-1]=target_insn;
179       target+=4;
180     }
181     *ptr2=(*ptr2&0xFF000000)|(((target-(u_int)ptr2-8)<<6)>>8);
182   }
183 }
184
185 /* Literal pool */
186 add_literal(int addr,int val)
187 {
188   assert(literalcount<sizeof(literals)/sizeof(literals[0]));
189   literals[literalcount][0]=addr;
190   literals[literalcount][1]=val;
191   literalcount++; 
192
193
194 void *kill_pointer(void *stub)
195 {
196   int *ptr=(int *)(stub+4);
197   assert((*ptr&0x0ff00000)==0x05900000);
198   u_int offset=*ptr&0xfff;
199   int **l_ptr=(void *)ptr+offset+8;
200   int *i_ptr=*l_ptr;
201   set_jump_target((int)i_ptr,(int)stub);
202   return i_ptr;
203 }
204
205 // find where external branch is liked to using addr of it's stub:
206 // get address that insn one after stub loads (dyna_linker arg1),
207 // treat it as a pointer to branch insn,
208 // return addr where that branch jumps to
209 int get_pointer(void *stub)
210 {
211   //printf("get_pointer(%x)\n",(int)stub);
212   int *ptr=(int *)(stub+4);
213   assert((*ptr&0x0fff0000)==0x059f0000);
214   u_int offset=*ptr&0xfff;
215   int **l_ptr=(void *)ptr+offset+8;
216   int *i_ptr=*l_ptr;
217   assert((*i_ptr&0x0f000000)==0x0a000000);
218   return (int)i_ptr+((*i_ptr<<8)>>6)+8;
219 }
220
221 // Find the "clean" entry point from a "dirty" entry point
222 // by skipping past the call to verify_code
223 u_int get_clean_addr(int addr)
224 {
225   int *ptr=(int *)addr;
226   #ifdef ARMv5_ONLY
227   ptr+=4;
228   #else
229   ptr+=6;
230   #endif
231   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
232   assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
233   ptr++;
234   if((*ptr&0xFF000000)==0xea000000) {
235     return (int)ptr+((*ptr<<8)>>6)+8; // follow jump
236   }
237   return (u_int)ptr;
238 }
239
240 int verify_dirty(int addr)
241 {
242   u_int *ptr=(u_int *)addr;
243   #ifdef ARMv5_ONLY
244   // get from literal pool
245   assert((*ptr&0xFFFF0000)==0xe59f0000);
246   u_int offset=*ptr&0xfff;
247   u_int *l_ptr=(void *)ptr+offset+8;
248   u_int source=l_ptr[0];
249   u_int copy=l_ptr[1];
250   u_int len=l_ptr[2];
251   ptr+=4;
252   #else
253   // ARMv7 movw/movt
254   assert((*ptr&0xFFF00000)==0xe3000000);
255   u_int source=(ptr[0]&0xFFF)+((ptr[0]>>4)&0xF000)+((ptr[2]<<16)&0xFFF0000)+((ptr[2]<<12)&0xF0000000);
256   u_int copy=(ptr[1]&0xFFF)+((ptr[1]>>4)&0xF000)+((ptr[3]<<16)&0xFFF0000)+((ptr[3]<<12)&0xF0000000);
257   u_int len=(ptr[4]&0xFFF)+((ptr[4]>>4)&0xF000);
258   ptr+=6;
259   #endif
260   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
261   assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
262 #ifndef DISABLE_TLB
263   u_int verifier=(int)ptr+((signed int)(*ptr<<8)>>6)+8; // get target of bl
264   if(verifier==(u_int)verify_code_vm||verifier==(u_int)verify_code_ds) {
265     unsigned int page=source>>12;
266     unsigned int map_value=memory_map[page];
267     if(map_value>=0x80000000) return 0;
268     while(page<((source+len-1)>>12)) {
269       if((memory_map[++page]<<2)!=(map_value<<2)) return 0;
270     }
271     source = source+(map_value<<2);
272   }
273 #endif
274   //printf("verify_dirty: %x %x %x\n",source,copy,len);
275   return !memcmp((void *)source,(void *)copy,len);
276 }
277
278 // This doesn't necessarily find all clean entry points, just
279 // guarantees that it's not dirty
280 int isclean(int addr)
281 {
282   #ifdef ARMv5_ONLY
283   int *ptr=((u_int *)addr)+4;
284   #else
285   int *ptr=((u_int *)addr)+6;
286   #endif
287   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
288   if((*ptr&0xFF000000)!=0xeb000000) return 1; // bl instruction
289   if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code) return 0;
290   if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code_vm) return 0;
291   if((int)ptr+((*ptr<<8)>>6)+8==(int)verify_code_ds) return 0;
292   return 1;
293 }
294
295 // get source that block at addr was compiled from (host pointers)
296 void get_bounds(int addr,u_int *start,u_int *end)
297 {
298   u_int *ptr=(u_int *)addr;
299   #ifdef ARMv5_ONLY
300   // get from literal pool
301   assert((*ptr&0xFFFF0000)==0xe59f0000);
302   u_int offset=*ptr&0xfff;
303   u_int *l_ptr=(void *)ptr+offset+8;
304   u_int source=l_ptr[0];
305   //u_int copy=l_ptr[1];
306   u_int len=l_ptr[2];
307   ptr+=4;
308   #else
309   // ARMv7 movw/movt
310   assert((*ptr&0xFFF00000)==0xe3000000);
311   u_int source=(ptr[0]&0xFFF)+((ptr[0]>>4)&0xF000)+((ptr[2]<<16)&0xFFF0000)+((ptr[2]<<12)&0xF0000000);
312   //u_int copy=(ptr[1]&0xFFF)+((ptr[1]>>4)&0xF000)+((ptr[3]<<16)&0xFFF0000)+((ptr[3]<<12)&0xF0000000);
313   u_int len=(ptr[4]&0xFFF)+((ptr[4]>>4)&0xF000);
314   ptr+=6;
315   #endif
316   if((*ptr&0xFF000000)!=0xeb000000) ptr++;
317   assert((*ptr&0xFF000000)==0xeb000000); // bl instruction
318 #ifndef DISABLE_TLB
319   u_int verifier=(int)ptr+((signed int)(*ptr<<8)>>6)+8; // get target of bl
320   if(verifier==(u_int)verify_code_vm||verifier==(u_int)verify_code_ds) {
321     if(memory_map[source>>12]>=0x80000000) source = 0;
322     else source = source+(memory_map[source>>12]<<2);
323   }
324 #endif
325   *start=source;
326   *end=source+len;
327 }
328
329 /* Register allocation */
330
331 // Note: registers are allocated clean (unmodified state)
332 // if you intend to modify the register, you must call dirty_reg().
333 void alloc_reg(struct regstat *cur,int i,signed char reg)
334 {
335   int r,hr;
336   int preferred_reg = (reg&7);
337   if(reg==CCREG) preferred_reg=HOST_CCREG;
338   if(reg==PTEMP||reg==FTEMP) preferred_reg=12;
339   
340   // Don't allocate unused registers
341   if((cur->u>>reg)&1) return;
342   
343   // see if it's already allocated
344   for(hr=0;hr<HOST_REGS;hr++)
345   {
346     if(cur->regmap[hr]==reg) return;
347   }
348   
349   // Keep the same mapping if the register was already allocated in a loop
350   preferred_reg = loop_reg(i,reg,preferred_reg);
351   
352   // Try to allocate the preferred register
353   if(cur->regmap[preferred_reg]==-1) {
354     cur->regmap[preferred_reg]=reg;
355     cur->dirty&=~(1<<preferred_reg);
356     cur->isconst&=~(1<<preferred_reg);
357     return;
358   }
359   r=cur->regmap[preferred_reg];
360   if(r<64&&((cur->u>>r)&1)) {
361     cur->regmap[preferred_reg]=reg;
362     cur->dirty&=~(1<<preferred_reg);
363     cur->isconst&=~(1<<preferred_reg);
364     return;
365   }
366   if(r>=64&&((cur->uu>>(r&63))&1)) {
367     cur->regmap[preferred_reg]=reg;
368     cur->dirty&=~(1<<preferred_reg);
369     cur->isconst&=~(1<<preferred_reg);
370     return;
371   }
372   
373   // Clear any unneeded registers
374   // We try to keep the mapping consistent, if possible, because it
375   // makes branches easier (especially loops).  So we try to allocate
376   // first (see above) before removing old mappings.  If this is not
377   // possible then go ahead and clear out the registers that are no
378   // longer needed.
379   for(hr=0;hr<HOST_REGS;hr++)
380   {
381     r=cur->regmap[hr];
382     if(r>=0) {
383       if(r<64) {
384         if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
385       }
386       else
387       {
388         if((cur->uu>>(r&63))&1) {cur->regmap[hr]=-1;break;}
389       }
390     }
391   }
392   // Try to allocate any available register, but prefer
393   // registers that have not been used recently.
394   if(i>0) {
395     for(hr=0;hr<HOST_REGS;hr++) {
396       if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
397         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]) {
398           cur->regmap[hr]=reg;
399           cur->dirty&=~(1<<hr);
400           cur->isconst&=~(1<<hr);
401           return;
402         }
403       }
404     }
405   }
406   // Try to allocate any available register
407   for(hr=0;hr<HOST_REGS;hr++) {
408     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
409       cur->regmap[hr]=reg;
410       cur->dirty&=~(1<<hr);
411       cur->isconst&=~(1<<hr);
412       return;
413     }
414   }
415   
416   // Ok, now we have to evict someone
417   // Pick a register we hopefully won't need soon
418   u_char hsn[MAXREG+1];
419   memset(hsn,10,sizeof(hsn));
420   int j;
421   lsn(hsn,i,&preferred_reg);
422   //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]);
423   //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]);
424   if(i>0) {
425     // Don't evict the cycle count at entry points, otherwise the entry
426     // stub will have to write it.
427     if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
428     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;
429     for(j=10;j>=3;j--)
430     {
431       // Alloc preferred register if available
432       if(hsn[r=cur->regmap[preferred_reg]&63]==j) {
433         for(hr=0;hr<HOST_REGS;hr++) {
434           // Evict both parts of a 64-bit register
435           if((cur->regmap[hr]&63)==r) {
436             cur->regmap[hr]=-1;
437             cur->dirty&=~(1<<hr);
438             cur->isconst&=~(1<<hr);
439           }
440         }
441         cur->regmap[preferred_reg]=reg;
442         return;
443       }
444       for(r=1;r<=MAXREG;r++)
445       {
446         if(hsn[r]==j&&r!=rs1[i-1]&&r!=rs2[i-1]&&r!=rt1[i-1]&&r!=rt2[i-1]) {
447           for(hr=0;hr<HOST_REGS;hr++) {
448             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
449               if(cur->regmap[hr]==r+64) {
450                 cur->regmap[hr]=reg;
451                 cur->dirty&=~(1<<hr);
452                 cur->isconst&=~(1<<hr);
453                 return;
454               }
455             }
456           }
457           for(hr=0;hr<HOST_REGS;hr++) {
458             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
459               if(cur->regmap[hr]==r) {
460                 cur->regmap[hr]=reg;
461                 cur->dirty&=~(1<<hr);
462                 cur->isconst&=~(1<<hr);
463                 return;
464               }
465             }
466           }
467         }
468       }
469     }
470   }
471   for(j=10;j>=0;j--)
472   {
473     for(r=1;r<=MAXREG;r++)
474     {
475       if(hsn[r]==j) {
476         for(hr=0;hr<HOST_REGS;hr++) {
477           if(cur->regmap[hr]==r+64) {
478             cur->regmap[hr]=reg;
479             cur->dirty&=~(1<<hr);
480             cur->isconst&=~(1<<hr);
481             return;
482           }
483         }
484         for(hr=0;hr<HOST_REGS;hr++) {
485           if(cur->regmap[hr]==r) {
486             cur->regmap[hr]=reg;
487             cur->dirty&=~(1<<hr);
488             cur->isconst&=~(1<<hr);
489             return;
490           }
491         }
492       }
493     }
494   }
495   printf("This shouldn't happen (alloc_reg)");exit(1);
496 }
497
498 void alloc_reg64(struct regstat *cur,int i,signed char reg)
499 {
500   int preferred_reg = 8+(reg&1);
501   int r,hr;
502   
503   // allocate the lower 32 bits
504   alloc_reg(cur,i,reg);
505   
506   // Don't allocate unused registers
507   if((cur->uu>>reg)&1) return;
508   
509   // see if the upper half is already allocated
510   for(hr=0;hr<HOST_REGS;hr++)
511   {
512     if(cur->regmap[hr]==reg+64) return;
513   }
514   
515   // Keep the same mapping if the register was already allocated in a loop
516   preferred_reg = loop_reg(i,reg,preferred_reg);
517   
518   // Try to allocate the preferred register
519   if(cur->regmap[preferred_reg]==-1) {
520     cur->regmap[preferred_reg]=reg|64;
521     cur->dirty&=~(1<<preferred_reg);
522     cur->isconst&=~(1<<preferred_reg);
523     return;
524   }
525   r=cur->regmap[preferred_reg];
526   if(r<64&&((cur->u>>r)&1)) {
527     cur->regmap[preferred_reg]=reg|64;
528     cur->dirty&=~(1<<preferred_reg);
529     cur->isconst&=~(1<<preferred_reg);
530     return;
531   }
532   if(r>=64&&((cur->uu>>(r&63))&1)) {
533     cur->regmap[preferred_reg]=reg|64;
534     cur->dirty&=~(1<<preferred_reg);
535     cur->isconst&=~(1<<preferred_reg);
536     return;
537   }
538   
539   // Clear any unneeded registers
540   // We try to keep the mapping consistent, if possible, because it
541   // makes branches easier (especially loops).  So we try to allocate
542   // first (see above) before removing old mappings.  If this is not
543   // possible then go ahead and clear out the registers that are no
544   // longer needed.
545   for(hr=HOST_REGS-1;hr>=0;hr--)
546   {
547     r=cur->regmap[hr];
548     if(r>=0) {
549       if(r<64) {
550         if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;}
551       }
552       else
553       {
554         if((cur->uu>>(r&63))&1) {cur->regmap[hr]=-1;break;}
555       }
556     }
557   }
558   // Try to allocate any available register, but prefer
559   // registers that have not been used recently.
560   if(i>0) {
561     for(hr=0;hr<HOST_REGS;hr++) {
562       if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
563         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]) {
564           cur->regmap[hr]=reg|64;
565           cur->dirty&=~(1<<hr);
566           cur->isconst&=~(1<<hr);
567           return;
568         }
569       }
570     }
571   }
572   // Try to allocate any available register
573   for(hr=0;hr<HOST_REGS;hr++) {
574     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
575       cur->regmap[hr]=reg|64;
576       cur->dirty&=~(1<<hr);
577       cur->isconst&=~(1<<hr);
578       return;
579     }
580   }
581   
582   // Ok, now we have to evict someone
583   // Pick a register we hopefully won't need soon
584   u_char hsn[MAXREG+1];
585   memset(hsn,10,sizeof(hsn));
586   int j;
587   lsn(hsn,i,&preferred_reg);
588   //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]);
589   //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]);
590   if(i>0) {
591     // Don't evict the cycle count at entry points, otherwise the entry
592     // stub will have to write it.
593     if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
594     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;
595     for(j=10;j>=3;j--)
596     {
597       // Alloc preferred register if available
598       if(hsn[r=cur->regmap[preferred_reg]&63]==j) {
599         for(hr=0;hr<HOST_REGS;hr++) {
600           // Evict both parts of a 64-bit register
601           if((cur->regmap[hr]&63)==r) {
602             cur->regmap[hr]=-1;
603             cur->dirty&=~(1<<hr);
604             cur->isconst&=~(1<<hr);
605           }
606         }
607         cur->regmap[preferred_reg]=reg|64;
608         return;
609       }
610       for(r=1;r<=MAXREG;r++)
611       {
612         if(hsn[r]==j&&r!=rs1[i-1]&&r!=rs2[i-1]&&r!=rt1[i-1]&&r!=rt2[i-1]) {
613           for(hr=0;hr<HOST_REGS;hr++) {
614             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
615               if(cur->regmap[hr]==r+64) {
616                 cur->regmap[hr]=reg|64;
617                 cur->dirty&=~(1<<hr);
618                 cur->isconst&=~(1<<hr);
619                 return;
620               }
621             }
622           }
623           for(hr=0;hr<HOST_REGS;hr++) {
624             if(hr!=HOST_CCREG||j<hsn[CCREG]) {
625               if(cur->regmap[hr]==r) {
626                 cur->regmap[hr]=reg|64;
627                 cur->dirty&=~(1<<hr);
628                 cur->isconst&=~(1<<hr);
629                 return;
630               }
631             }
632           }
633         }
634       }
635     }
636   }
637   for(j=10;j>=0;j--)
638   {
639     for(r=1;r<=MAXREG;r++)
640     {
641       if(hsn[r]==j) {
642         for(hr=0;hr<HOST_REGS;hr++) {
643           if(cur->regmap[hr]==r+64) {
644             cur->regmap[hr]=reg|64;
645             cur->dirty&=~(1<<hr);
646             cur->isconst&=~(1<<hr);
647             return;
648           }
649         }
650         for(hr=0;hr<HOST_REGS;hr++) {
651           if(cur->regmap[hr]==r) {
652             cur->regmap[hr]=reg|64;
653             cur->dirty&=~(1<<hr);
654             cur->isconst&=~(1<<hr);
655             return;
656           }
657         }
658       }
659     }
660   }
661   printf("This shouldn't happen");exit(1);
662 }
663
664 // Allocate a temporary register.  This is done without regard to
665 // dirty status or whether the register we request is on the unneeded list
666 // Note: This will only allocate one register, even if called multiple times
667 void alloc_reg_temp(struct regstat *cur,int i,signed char reg)
668 {
669   int r,hr;
670   int preferred_reg = -1;
671   
672   // see if it's already allocated
673   for(hr=0;hr<HOST_REGS;hr++)
674   {
675     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==reg) return;
676   }
677   
678   // Try to allocate any available register
679   for(hr=HOST_REGS-1;hr>=0;hr--) {
680     if(hr!=EXCLUDE_REG&&cur->regmap[hr]==-1) {
681       cur->regmap[hr]=reg;
682       cur->dirty&=~(1<<hr);
683       cur->isconst&=~(1<<hr);
684       return;
685     }
686   }
687   
688   // Find an unneeded register
689   for(hr=HOST_REGS-1;hr>=0;hr--)
690   {
691     r=cur->regmap[hr];
692     if(r>=0) {
693       if(r<64) {
694         if((cur->u>>r)&1) {
695           if(i==0||((unneeded_reg[i-1]>>r)&1)) {
696             cur->regmap[hr]=reg;
697             cur->dirty&=~(1<<hr);
698             cur->isconst&=~(1<<hr);
699             return;
700           }
701         }
702       }
703       else
704       {
705         if((cur->uu>>(r&63))&1) {
706           if(i==0||((unneeded_reg_upper[i-1]>>(r&63))&1)) {
707             cur->regmap[hr]=reg;
708             cur->dirty&=~(1<<hr);
709             cur->isconst&=~(1<<hr);
710             return;
711           }
712         }
713       }
714     }
715   }
716   
717   // Ok, now we have to evict someone
718   // Pick a register we hopefully won't need soon
719   // TODO: we might want to follow unconditional jumps here
720   // TODO: get rid of dupe code and make this into a function
721   u_char hsn[MAXREG+1];
722   memset(hsn,10,sizeof(hsn));
723   int j;
724   lsn(hsn,i,&preferred_reg);
725   //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]);
726   if(i>0) {
727     // Don't evict the cycle count at entry points, otherwise the entry
728     // stub will have to write it.
729     if(bt[i]&&hsn[CCREG]>2) hsn[CCREG]=2;
730     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;
731     for(j=10;j>=3;j--)
732     {
733       for(r=1;r<=MAXREG;r++)
734       {
735         if(hsn[r]==j&&r!=rs1[i-1]&&r!=rs2[i-1]&&r!=rt1[i-1]&&r!=rt2[i-1]) {
736           for(hr=0;hr<HOST_REGS;hr++) {
737             if(hr!=HOST_CCREG||hsn[CCREG]>2) {
738               if(cur->regmap[hr]==r+64) {
739                 cur->regmap[hr]=reg;
740                 cur->dirty&=~(1<<hr);
741                 cur->isconst&=~(1<<hr);
742                 return;
743               }
744             }
745           }
746           for(hr=0;hr<HOST_REGS;hr++) {
747             if(hr!=HOST_CCREG||hsn[CCREG]>2) {
748               if(cur->regmap[hr]==r) {
749                 cur->regmap[hr]=reg;
750                 cur->dirty&=~(1<<hr);
751                 cur->isconst&=~(1<<hr);
752                 return;
753               }
754             }
755           }
756         }
757       }
758     }
759   }
760   for(j=10;j>=0;j--)
761   {
762     for(r=1;r<=MAXREG;r++)
763     {
764       if(hsn[r]==j) {
765         for(hr=0;hr<HOST_REGS;hr++) {
766           if(cur->regmap[hr]==r+64) {
767             cur->regmap[hr]=reg;
768             cur->dirty&=~(1<<hr);
769             cur->isconst&=~(1<<hr);
770             return;
771           }
772         }
773         for(hr=0;hr<HOST_REGS;hr++) {
774           if(cur->regmap[hr]==r) {
775             cur->regmap[hr]=reg;
776             cur->dirty&=~(1<<hr);
777             cur->isconst&=~(1<<hr);
778             return;
779           }
780         }
781       }
782     }
783   }
784   printf("This shouldn't happen");exit(1);
785 }
786 // Allocate a specific ARM register.
787 void alloc_arm_reg(struct regstat *cur,int i,signed char reg,char hr)
788 {
789   int n;
790   int dirty=0;
791   
792   // see if it's already allocated (and dealloc it)
793   for(n=0;n<HOST_REGS;n++)
794   {
795     if(n!=EXCLUDE_REG&&cur->regmap[n]==reg) {
796       dirty=(cur->dirty>>n)&1;
797       cur->regmap[n]=-1;
798     }
799   }
800   
801   cur->regmap[hr]=reg;
802   cur->dirty&=~(1<<hr);
803   cur->dirty|=dirty<<hr;
804   cur->isconst&=~(1<<hr);
805 }
806
807 // Alloc cycle count into dedicated register
808 alloc_cc(struct regstat *cur,int i)
809 {
810   alloc_arm_reg(cur,i,CCREG,HOST_CCREG);
811 }
812
813 /* Special alloc */
814
815
816 /* Assembler */
817
818 char regname[16][4] = {
819  "r0",
820  "r1",
821  "r2",
822  "r3",
823  "r4",
824  "r5",
825  "r6",
826  "r7",
827  "r8",
828  "r9",
829  "r10",
830  "fp",
831  "r12",
832  "sp",
833  "lr",
834  "pc"};
835
836 void output_byte(u_char byte)
837 {
838   *(out++)=byte;
839 }
840 void output_modrm(u_char mod,u_char rm,u_char ext)
841 {
842   assert(mod<4);
843   assert(rm<8);
844   assert(ext<8);
845   u_char byte=(mod<<6)|(ext<<3)|rm;
846   *(out++)=byte;
847 }
848 void output_sib(u_char scale,u_char index,u_char base)
849 {
850   assert(scale<4);
851   assert(index<8);
852   assert(base<8);
853   u_char byte=(scale<<6)|(index<<3)|base;
854   *(out++)=byte;
855 }
856 void output_w32(u_int word)
857 {
858   *((u_int *)out)=word;
859   out+=4;
860 }
861 u_int rd_rn_rm(u_int rd, u_int rn, u_int rm)
862 {
863   assert(rd<16);
864   assert(rn<16);
865   assert(rm<16);
866   return((rn<<16)|(rd<<12)|rm);
867 }
868 u_int rd_rn_imm_shift(u_int rd, u_int rn, u_int imm, u_int shift)
869 {
870   assert(rd<16);
871   assert(rn<16);
872   assert(imm<256);
873   assert((shift&1)==0);
874   return((rn<<16)|(rd<<12)|(((32-shift)&30)<<7)|imm);
875 }
876 u_int genimm(u_int imm,u_int *encoded)
877 {
878   *encoded=0;
879   if(imm==0) return 1;
880   int i=32;
881   while(i>0)
882   {
883     if(imm<256) {
884       *encoded=((i&30)<<7)|imm;
885       return 1;
886     }
887     imm=(imm>>2)|(imm<<30);i-=2;
888   }
889   return 0;
890 }
891 void genimm_checked(u_int imm,u_int *encoded)
892 {
893   u_int ret=genimm(imm,encoded);
894   assert(ret);
895 }
896 u_int genjmp(u_int addr)
897 {
898   int offset=addr-(int)out-8;
899   if(offset<-33554432||offset>=33554432) {
900     if (addr>2) {
901       printf("genjmp: out of range: %08x\n", offset);
902       exit(1);
903     }
904     return 0;
905   }
906   return ((u_int)offset>>2)&0xffffff;
907 }
908
909 void emit_mov(int rs,int rt)
910 {
911   assem_debug("mov %s,%s\n",regname[rt],regname[rs]);
912   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs));
913 }
914
915 void emit_movs(int rs,int rt)
916 {
917   assem_debug("movs %s,%s\n",regname[rt],regname[rs]);
918   output_w32(0xe1b00000|rd_rn_rm(rt,0,rs));
919 }
920
921 void emit_add(int rs1,int rs2,int rt)
922 {
923   assem_debug("add %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
924   output_w32(0xe0800000|rd_rn_rm(rt,rs1,rs2));
925 }
926
927 void emit_adds(int rs1,int rs2,int rt)
928 {
929   assem_debug("adds %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
930   output_w32(0xe0900000|rd_rn_rm(rt,rs1,rs2));
931 }
932
933 void emit_adcs(int rs1,int rs2,int rt)
934 {
935   assem_debug("adcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
936   output_w32(0xe0b00000|rd_rn_rm(rt,rs1,rs2));
937 }
938
939 void emit_sbc(int rs1,int rs2,int rt)
940 {
941   assem_debug("sbc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
942   output_w32(0xe0c00000|rd_rn_rm(rt,rs1,rs2));
943 }
944
945 void emit_sbcs(int rs1,int rs2,int rt)
946 {
947   assem_debug("sbcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
948   output_w32(0xe0d00000|rd_rn_rm(rt,rs1,rs2));
949 }
950
951 void emit_neg(int rs, int rt)
952 {
953   assem_debug("rsb %s,%s,#0\n",regname[rt],regname[rs]);
954   output_w32(0xe2600000|rd_rn_rm(rt,rs,0));
955 }
956
957 void emit_negs(int rs, int rt)
958 {
959   assem_debug("rsbs %s,%s,#0\n",regname[rt],regname[rs]);
960   output_w32(0xe2700000|rd_rn_rm(rt,rs,0));
961 }
962
963 void emit_sub(int rs1,int rs2,int rt)
964 {
965   assem_debug("sub %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
966   output_w32(0xe0400000|rd_rn_rm(rt,rs1,rs2));
967 }
968
969 void emit_subs(int rs1,int rs2,int rt)
970 {
971   assem_debug("subs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
972   output_w32(0xe0500000|rd_rn_rm(rt,rs1,rs2));
973 }
974
975 void emit_zeroreg(int rt)
976 {
977   assem_debug("mov %s,#0\n",regname[rt]);
978   output_w32(0xe3a00000|rd_rn_rm(rt,0,0));
979 }
980
981 void emit_loadlp(u_int imm,u_int rt)
982 {
983   add_literal((int)out,imm);
984   assem_debug("ldr %s,pc+? [=%x]\n",regname[rt],imm);
985   output_w32(0xe5900000|rd_rn_rm(rt,15,0));
986 }
987 void emit_movw(u_int imm,u_int rt)
988 {
989   assert(imm<65536);
990   assem_debug("movw %s,#%d (0x%x)\n",regname[rt],imm,imm);
991   output_w32(0xe3000000|rd_rn_rm(rt,0,0)|(imm&0xfff)|((imm<<4)&0xf0000));
992 }
993 void emit_movt(u_int imm,u_int rt)
994 {
995   assem_debug("movt %s,#%d (0x%x)\n",regname[rt],imm&0xffff0000,imm&0xffff0000);
996   output_w32(0xe3400000|rd_rn_rm(rt,0,0)|((imm>>16)&0xfff)|((imm>>12)&0xf0000));
997 }
998 void emit_movimm(u_int imm,u_int rt)
999 {
1000   u_int armval;
1001   if(genimm(imm,&armval)) {
1002     assem_debug("mov %s,#%d\n",regname[rt],imm);
1003     output_w32(0xe3a00000|rd_rn_rm(rt,0,0)|armval);
1004   }else if(genimm(~imm,&armval)) {
1005     assem_debug("mvn %s,#%d\n",regname[rt],imm);
1006     output_w32(0xe3e00000|rd_rn_rm(rt,0,0)|armval);
1007   }else if(imm<65536) {
1008     #ifdef ARMv5_ONLY
1009     assem_debug("mov %s,#%d\n",regname[rt],imm&0xFF00);
1010     output_w32(0xe3a00000|rd_rn_imm_shift(rt,0,imm>>8,8));
1011     assem_debug("add %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF);
1012     output_w32(0xe2800000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1013     #else
1014     emit_movw(imm,rt);
1015     #endif
1016   }else{
1017     #ifdef ARMv5_ONLY
1018     emit_loadlp(imm,rt);
1019     #else
1020     emit_movw(imm&0x0000FFFF,rt);
1021     emit_movt(imm&0xFFFF0000,rt);
1022     #endif
1023   }
1024 }
1025 void emit_pcreladdr(u_int rt)
1026 {
1027   assem_debug("add %s,pc,#?\n",regname[rt]);
1028   output_w32(0xe2800000|rd_rn_rm(rt,15,0));
1029 }
1030
1031 void emit_loadreg(int r, int hr)
1032 {
1033 #ifdef FORCE32
1034   if(r&64) {
1035     printf("64bit load in 32bit mode!\n");
1036     assert(0);
1037     return;
1038   }
1039 #endif
1040   if((r&63)==0)
1041     emit_zeroreg(hr);
1042   else {
1043     int addr=((int)reg)+((r&63)<<REG_SHIFT)+((r&64)>>4);
1044     if((r&63)==HIREG) addr=(int)&hi+((r&64)>>4);
1045     if((r&63)==LOREG) addr=(int)&lo+((r&64)>>4);
1046     if(r==CCREG) addr=(int)&cycle_count;
1047     if(r==CSREG) addr=(int)&Status;
1048     if(r==FSREG) addr=(int)&FCR31;
1049     if(r==INVCP) addr=(int)&invc_ptr;
1050     u_int offset = addr-(u_int)&dynarec_local;
1051     assert(offset<4096);
1052     assem_debug("ldr %s,fp+%d\n",regname[hr],offset);
1053     output_w32(0xe5900000|rd_rn_rm(hr,FP,0)|offset);
1054   }
1055 }
1056 void emit_storereg(int r, int hr)
1057 {
1058 #ifdef FORCE32
1059   if(r&64) {
1060     printf("64bit store in 32bit mode!\n");
1061     assert(0);
1062     return;
1063   }
1064 #endif
1065   int addr=((int)reg)+((r&63)<<REG_SHIFT)+((r&64)>>4);
1066   if((r&63)==HIREG) addr=(int)&hi+((r&64)>>4);
1067   if((r&63)==LOREG) addr=(int)&lo+((r&64)>>4);
1068   if(r==CCREG) addr=(int)&cycle_count;
1069   if(r==FSREG) addr=(int)&FCR31;
1070   u_int offset = addr-(u_int)&dynarec_local;
1071   assert(offset<4096);
1072   assem_debug("str %s,fp+%d\n",regname[hr],offset);
1073   output_w32(0xe5800000|rd_rn_rm(hr,FP,0)|offset);
1074 }
1075
1076 void emit_test(int rs, int rt)
1077 {
1078   assem_debug("tst %s,%s\n",regname[rs],regname[rt]);
1079   output_w32(0xe1100000|rd_rn_rm(0,rs,rt));
1080 }
1081
1082 void emit_testimm(int rs,int imm)
1083 {
1084   u_int armval;
1085   assem_debug("tst %s,#%d\n",regname[rs],imm);
1086   genimm_checked(imm,&armval);
1087   output_w32(0xe3100000|rd_rn_rm(0,rs,0)|armval);
1088 }
1089
1090 void emit_testeqimm(int rs,int imm)
1091 {
1092   u_int armval;
1093   assem_debug("tsteq %s,$%d\n",regname[rs],imm);
1094   genimm_checked(imm,&armval);
1095   output_w32(0x03100000|rd_rn_rm(0,rs,0)|armval);
1096 }
1097
1098 void emit_not(int rs,int rt)
1099 {
1100   assem_debug("mvn %s,%s\n",regname[rt],regname[rs]);
1101   output_w32(0xe1e00000|rd_rn_rm(rt,0,rs));
1102 }
1103
1104 void emit_mvnmi(int rs,int rt)
1105 {
1106   assem_debug("mvnmi %s,%s\n",regname[rt],regname[rs]);
1107   output_w32(0x41e00000|rd_rn_rm(rt,0,rs));
1108 }
1109
1110 void emit_and(u_int rs1,u_int rs2,u_int rt)
1111 {
1112   assem_debug("and %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1113   output_w32(0xe0000000|rd_rn_rm(rt,rs1,rs2));
1114 }
1115
1116 void emit_or(u_int rs1,u_int rs2,u_int rt)
1117 {
1118   assem_debug("orr %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1119   output_w32(0xe1800000|rd_rn_rm(rt,rs1,rs2));
1120 }
1121 void emit_or_and_set_flags(int rs1,int rs2,int rt)
1122 {
1123   assem_debug("orrs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1124   output_w32(0xe1900000|rd_rn_rm(rt,rs1,rs2));
1125 }
1126
1127 void emit_orrshl_imm(u_int rs,u_int imm,u_int rt)
1128 {
1129   assert(rs<16);
1130   assert(rt<16);
1131   assert(imm<32);
1132   assem_debug("orr %s,%s,%s,lsl #%d\n",regname[rt],regname[rt],regname[rs],imm);
1133   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs)|(imm<<7));
1134 }
1135
1136 void emit_orrshr_imm(u_int rs,u_int imm,u_int rt)
1137 {
1138   assert(rs<16);
1139   assert(rt<16);
1140   assert(imm<32);
1141   assem_debug("orr %s,%s,%s,lsr #%d\n",regname[rt],regname[rt],regname[rs],imm);
1142   output_w32(0xe1800020|rd_rn_rm(rt,rt,rs)|(imm<<7));
1143 }
1144
1145 void emit_xor(u_int rs1,u_int rs2,u_int rt)
1146 {
1147   assem_debug("eor %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1148   output_w32(0xe0200000|rd_rn_rm(rt,rs1,rs2));
1149 }
1150
1151 void emit_addimm(u_int rs,int imm,u_int rt)
1152 {
1153   assert(rs<16);
1154   assert(rt<16);
1155   if(imm!=0) {
1156     u_int armval;
1157     if(genimm(imm,&armval)) {
1158       assem_debug("add %s,%s,#%d\n",regname[rt],regname[rs],imm);
1159       output_w32(0xe2800000|rd_rn_rm(rt,rs,0)|armval);
1160     }else if(genimm(-imm,&armval)) {
1161       assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rs],-imm);
1162       output_w32(0xe2400000|rd_rn_rm(rt,rs,0)|armval);
1163     }else if(imm<0) {
1164       assert(imm>-65536);
1165       assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rs],(-imm)&0xFF00);
1166       assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rt],(-imm)&0xFF);
1167       output_w32(0xe2400000|rd_rn_imm_shift(rt,rs,(-imm)>>8,8));
1168       output_w32(0xe2400000|rd_rn_imm_shift(rt,rt,(-imm)&0xff,0));
1169     }else{
1170       assert(imm<65536);
1171       assem_debug("add %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF00);
1172       assem_debug("add %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF);
1173       output_w32(0xe2800000|rd_rn_imm_shift(rt,rs,imm>>8,8));
1174       output_w32(0xe2800000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1175     }
1176   }
1177   else if(rs!=rt) emit_mov(rs,rt);
1178 }
1179
1180 void emit_addimm_and_set_flags(int imm,int rt)
1181 {
1182   assert(imm>-65536&&imm<65536);
1183   u_int armval;
1184   if(genimm(imm,&armval)) {
1185     assem_debug("adds %s,%s,#%d\n",regname[rt],regname[rt],imm);
1186     output_w32(0xe2900000|rd_rn_rm(rt,rt,0)|armval);
1187   }else if(genimm(-imm,&armval)) {
1188     assem_debug("subs %s,%s,#%d\n",regname[rt],regname[rt],imm);
1189     output_w32(0xe2500000|rd_rn_rm(rt,rt,0)|armval);
1190   }else if(imm<0) {
1191     assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rt],(-imm)&0xFF00);
1192     assem_debug("subs %s,%s,#%d\n",regname[rt],regname[rt],(-imm)&0xFF);
1193     output_w32(0xe2400000|rd_rn_imm_shift(rt,rt,(-imm)>>8,8));
1194     output_w32(0xe2500000|rd_rn_imm_shift(rt,rt,(-imm)&0xff,0));
1195   }else{
1196     assem_debug("add %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF00);
1197     assem_debug("adds %s,%s,#%d\n",regname[rt],regname[rt],imm&0xFF);
1198     output_w32(0xe2800000|rd_rn_imm_shift(rt,rt,imm>>8,8));
1199     output_w32(0xe2900000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1200   }
1201 }
1202 void emit_addimm_no_flags(u_int imm,u_int rt)
1203 {
1204   emit_addimm(rt,imm,rt);
1205 }
1206
1207 void emit_addnop(u_int r)
1208 {
1209   assert(r<16);
1210   assem_debug("add %s,%s,#0 (nop)\n",regname[r],regname[r]);
1211   output_w32(0xe2800000|rd_rn_rm(r,r,0));
1212 }
1213
1214 void emit_adcimm(u_int rs,int imm,u_int rt)
1215 {
1216   u_int armval;
1217   genimm_checked(imm,&armval);
1218   assem_debug("adc %s,%s,#%d\n",regname[rt],regname[rs],imm);
1219   output_w32(0xe2a00000|rd_rn_rm(rt,rs,0)|armval);
1220 }
1221 /*void emit_sbcimm(int imm,u_int rt)
1222 {
1223   u_int armval;
1224   genimm_checked(imm,&armval);
1225   assem_debug("sbc %s,%s,#%d\n",regname[rt],regname[rt],imm);
1226   output_w32(0xe2c00000|rd_rn_rm(rt,rt,0)|armval);
1227 }*/
1228 void emit_sbbimm(int imm,u_int rt)
1229 {
1230   assem_debug("sbb $%d,%%%s\n",imm,regname[rt]);
1231   assert(rt<8);
1232   if(imm<128&&imm>=-128) {
1233     output_byte(0x83);
1234     output_modrm(3,rt,3);
1235     output_byte(imm);
1236   }
1237   else
1238   {
1239     output_byte(0x81);
1240     output_modrm(3,rt,3);
1241     output_w32(imm);
1242   }
1243 }
1244 void emit_rscimm(int rs,int imm,u_int rt)
1245 {
1246   assert(0);
1247   u_int armval;
1248   genimm_checked(imm,&armval);
1249   assem_debug("rsc %s,%s,#%d\n",regname[rt],regname[rs],imm);
1250   output_w32(0xe2e00000|rd_rn_rm(rt,rs,0)|armval);
1251 }
1252
1253 void emit_addimm64_32(int rsh,int rsl,int imm,int rth,int rtl)
1254 {
1255   // TODO: if(genimm(imm,&armval)) ...
1256   // else
1257   emit_movimm(imm,HOST_TEMPREG);
1258   emit_adds(HOST_TEMPREG,rsl,rtl);
1259   emit_adcimm(rsh,0,rth);
1260 }
1261
1262 void emit_sbb(int rs1,int rs2)
1263 {
1264   assem_debug("sbb %%%s,%%%s\n",regname[rs2],regname[rs1]);
1265   output_byte(0x19);
1266   output_modrm(3,rs1,rs2);
1267 }
1268
1269 void emit_andimm(int rs,int imm,int rt)
1270 {
1271   u_int armval;
1272   if(imm==0) {
1273     emit_zeroreg(rt);
1274   }else if(genimm(imm,&armval)) {
1275     assem_debug("and %s,%s,#%d\n",regname[rt],regname[rs],imm);
1276     output_w32(0xe2000000|rd_rn_rm(rt,rs,0)|armval);
1277   }else if(genimm(~imm,&armval)) {
1278     assem_debug("bic %s,%s,#%d\n",regname[rt],regname[rs],imm);
1279     output_w32(0xe3c00000|rd_rn_rm(rt,rs,0)|armval);
1280   }else if(imm==65535) {
1281     #ifdef ARMv5_ONLY
1282     assem_debug("bic %s,%s,#FF000000\n",regname[rt],regname[rs]);
1283     output_w32(0xe3c00000|rd_rn_rm(rt,rs,0)|0x4FF);
1284     assem_debug("bic %s,%s,#00FF0000\n",regname[rt],regname[rt]);
1285     output_w32(0xe3c00000|rd_rn_rm(rt,rt,0)|0x8FF);
1286     #else
1287     assem_debug("uxth %s,%s\n",regname[rt],regname[rs]);
1288     output_w32(0xe6ff0070|rd_rn_rm(rt,0,rs));
1289     #endif
1290   }else{
1291     assert(imm>0&&imm<65535);
1292     #ifdef ARMv5_ONLY
1293     assem_debug("mov r14,#%d\n",imm&0xFF00);
1294     output_w32(0xe3a00000|rd_rn_imm_shift(HOST_TEMPREG,0,imm>>8,8));
1295     assem_debug("add r14,r14,#%d\n",imm&0xFF);
1296     output_w32(0xe2800000|rd_rn_imm_shift(HOST_TEMPREG,HOST_TEMPREG,imm&0xff,0));
1297     #else
1298     emit_movw(imm,HOST_TEMPREG);
1299     #endif
1300     assem_debug("and %s,%s,r14\n",regname[rt],regname[rs]);
1301     output_w32(0xe0000000|rd_rn_rm(rt,rs,HOST_TEMPREG));
1302   }
1303 }
1304
1305 void emit_orimm(int rs,int imm,int rt)
1306 {
1307   u_int armval;
1308   if(imm==0) {
1309     if(rs!=rt) emit_mov(rs,rt);
1310   }else if(genimm(imm,&armval)) {
1311     assem_debug("orr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1312     output_w32(0xe3800000|rd_rn_rm(rt,rs,0)|armval);
1313   }else{
1314     assert(imm>0&&imm<65536);
1315     assem_debug("orr %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF00);
1316     assem_debug("orr %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF);
1317     output_w32(0xe3800000|rd_rn_imm_shift(rt,rs,imm>>8,8));
1318     output_w32(0xe3800000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1319   }
1320 }
1321
1322 void emit_xorimm(int rs,int imm,int rt)
1323 {
1324   u_int armval;
1325   if(imm==0) {
1326     if(rs!=rt) emit_mov(rs,rt);
1327   }else if(genimm(imm,&armval)) {
1328     assem_debug("eor %s,%s,#%d\n",regname[rt],regname[rs],imm);
1329     output_w32(0xe2200000|rd_rn_rm(rt,rs,0)|armval);
1330   }else{
1331     assert(imm>0&&imm<65536);
1332     assem_debug("eor %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF00);
1333     assem_debug("eor %s,%s,#%d\n",regname[rt],regname[rs],imm&0xFF);
1334     output_w32(0xe2200000|rd_rn_imm_shift(rt,rs,imm>>8,8));
1335     output_w32(0xe2200000|rd_rn_imm_shift(rt,rt,imm&0xff,0));
1336   }
1337 }
1338
1339 void emit_shlimm(int rs,u_int imm,int rt)
1340 {
1341   assert(imm>0);
1342   assert(imm<32);
1343   //if(imm==1) ...
1344   assem_debug("lsl %s,%s,#%d\n",regname[rt],regname[rs],imm);
1345   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|(imm<<7));
1346 }
1347
1348 void emit_lsls_imm(int rs,int imm,int rt)
1349 {
1350   assert(imm>0);
1351   assert(imm<32);
1352   assem_debug("lsls %s,%s,#%d\n",regname[rt],regname[rs],imm);
1353   output_w32(0xe1b00000|rd_rn_rm(rt,0,rs)|(imm<<7));
1354 }
1355
1356 void emit_shrimm(int rs,u_int imm,int rt)
1357 {
1358   assert(imm>0);
1359   assert(imm<32);
1360   assem_debug("lsr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1361   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x20|(imm<<7));
1362 }
1363
1364 void emit_sarimm(int rs,u_int imm,int rt)
1365 {
1366   assert(imm>0);
1367   assert(imm<32);
1368   assem_debug("asr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1369   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x40|(imm<<7));
1370 }
1371
1372 void emit_rorimm(int rs,u_int imm,int rt)
1373 {
1374   assert(imm>0);
1375   assert(imm<32);
1376   assem_debug("ror %s,%s,#%d\n",regname[rt],regname[rs],imm);
1377   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x60|(imm<<7));
1378 }
1379
1380 void emit_shldimm(int rs,int rs2,u_int imm,int rt)
1381 {
1382   assem_debug("shld %%%s,%%%s,%d\n",regname[rt],regname[rs2],imm);
1383   assert(imm>0);
1384   assert(imm<32);
1385   //if(imm==1) ...
1386   assem_debug("lsl %s,%s,#%d\n",regname[rt],regname[rs],imm);
1387   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|(imm<<7));
1388   assem_debug("orr %s,%s,%s,lsr #%d\n",regname[rt],regname[rt],regname[rs2],32-imm);
1389   output_w32(0xe1800020|rd_rn_rm(rt,rt,rs2)|((32-imm)<<7));
1390 }
1391
1392 void emit_shrdimm(int rs,int rs2,u_int imm,int rt)
1393 {
1394   assem_debug("shrd %%%s,%%%s,%d\n",regname[rt],regname[rs2],imm);
1395   assert(imm>0);
1396   assert(imm<32);
1397   //if(imm==1) ...
1398   assem_debug("lsr %s,%s,#%d\n",regname[rt],regname[rs],imm);
1399   output_w32(0xe1a00020|rd_rn_rm(rt,0,rs)|(imm<<7));
1400   assem_debug("orr %s,%s,%s,lsl #%d\n",regname[rt],regname[rt],regname[rs2],32-imm);
1401   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs2)|((32-imm)<<7));
1402 }
1403
1404 void emit_signextend16(int rs,int rt)
1405 {
1406   #ifdef ARMv5_ONLY
1407   emit_shlimm(rs,16,rt);
1408   emit_sarimm(rt,16,rt);
1409   #else
1410   assem_debug("sxth %s,%s\n",regname[rt],regname[rs]);
1411   output_w32(0xe6bf0070|rd_rn_rm(rt,0,rs));
1412   #endif
1413 }
1414
1415 void emit_signextend8(int rs,int rt)
1416 {
1417   #ifdef ARMv5_ONLY
1418   emit_shlimm(rs,24,rt);
1419   emit_sarimm(rt,24,rt);
1420   #else
1421   assem_debug("sxtb %s,%s\n",regname[rt],regname[rs]);
1422   output_w32(0xe6af0070|rd_rn_rm(rt,0,rs));
1423   #endif
1424 }
1425
1426 void emit_shl(u_int rs,u_int shift,u_int rt)
1427 {
1428   assert(rs<16);
1429   assert(rt<16);
1430   assert(shift<16);
1431   //if(imm==1) ...
1432   assem_debug("lsl %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
1433   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x10|(shift<<8));
1434 }
1435 void emit_shr(u_int rs,u_int shift,u_int rt)
1436 {
1437   assert(rs<16);
1438   assert(rt<16);
1439   assert(shift<16);
1440   assem_debug("lsr %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
1441   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x30|(shift<<8));
1442 }
1443 void emit_sar(u_int rs,u_int shift,u_int rt)
1444 {
1445   assert(rs<16);
1446   assert(rt<16);
1447   assert(shift<16);
1448   assem_debug("asr %s,%s,%s\n",regname[rt],regname[rs],regname[shift]);
1449   output_w32(0xe1a00000|rd_rn_rm(rt,0,rs)|0x50|(shift<<8));
1450 }
1451 void emit_shlcl(int r)
1452 {
1453   assem_debug("shl %%%s,%%cl\n",regname[r]);
1454   assert(0);
1455 }
1456 void emit_shrcl(int r)
1457 {
1458   assem_debug("shr %%%s,%%cl\n",regname[r]);
1459   assert(0);
1460 }
1461 void emit_sarcl(int r)
1462 {
1463   assem_debug("sar %%%s,%%cl\n",regname[r]);
1464   assert(0);
1465 }
1466
1467 void emit_shldcl(int r1,int r2)
1468 {
1469   assem_debug("shld %%%s,%%%s,%%cl\n",regname[r1],regname[r2]);
1470   assert(0);
1471 }
1472 void emit_shrdcl(int r1,int r2)
1473 {
1474   assem_debug("shrd %%%s,%%%s,%%cl\n",regname[r1],regname[r2]);
1475   assert(0);
1476 }
1477 void emit_orrshl(u_int rs,u_int shift,u_int rt)
1478 {
1479   assert(rs<16);
1480   assert(rt<16);
1481   assert(shift<16);
1482   assem_debug("orr %s,%s,%s,lsl %s\n",regname[rt],regname[rt],regname[rs],regname[shift]);
1483   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs)|0x10|(shift<<8));
1484 }
1485 void emit_orrshr(u_int rs,u_int shift,u_int rt)
1486 {
1487   assert(rs<16);
1488   assert(rt<16);
1489   assert(shift<16);
1490   assem_debug("orr %s,%s,%s,lsr %s\n",regname[rt],regname[rt],regname[rs],regname[shift]);
1491   output_w32(0xe1800000|rd_rn_rm(rt,rt,rs)|0x30|(shift<<8));
1492 }
1493
1494 void emit_cmpimm(int rs,int imm)
1495 {
1496   u_int armval;
1497   if(genimm(imm,&armval)) {
1498     assem_debug("cmp %s,#%d\n",regname[rs],imm);
1499     output_w32(0xe3500000|rd_rn_rm(0,rs,0)|armval);
1500   }else if(genimm(-imm,&armval)) {
1501     assem_debug("cmn %s,#%d\n",regname[rs],imm);
1502     output_w32(0xe3700000|rd_rn_rm(0,rs,0)|armval);
1503   }else if(imm>0) {
1504     assert(imm<65536);
1505     #ifdef ARMv5_ONLY
1506     emit_movimm(imm,HOST_TEMPREG);
1507     #else
1508     emit_movw(imm,HOST_TEMPREG);
1509     #endif
1510     assem_debug("cmp %s,r14\n",regname[rs]);
1511     output_w32(0xe1500000|rd_rn_rm(0,rs,HOST_TEMPREG));
1512   }else{
1513     assert(imm>-65536);
1514     #ifdef ARMv5_ONLY
1515     emit_movimm(-imm,HOST_TEMPREG);
1516     #else
1517     emit_movw(-imm,HOST_TEMPREG);
1518     #endif
1519     assem_debug("cmn %s,r14\n",regname[rs]);
1520     output_w32(0xe1700000|rd_rn_rm(0,rs,HOST_TEMPREG));
1521   }
1522 }
1523
1524 void emit_cmovne(u_int *addr,int rt)
1525 {
1526   assem_debug("cmovne %x,%%%s",(int)addr,regname[rt]);
1527   assert(0);
1528 }
1529 void emit_cmovl(u_int *addr,int rt)
1530 {
1531   assem_debug("cmovl %x,%%%s",(int)addr,regname[rt]);
1532   assert(0);
1533 }
1534 void emit_cmovs(u_int *addr,int rt)
1535 {
1536   assem_debug("cmovs %x,%%%s",(int)addr,regname[rt]);
1537   assert(0);
1538 }
1539 void emit_cmovne_imm(int imm,int rt)
1540 {
1541   assem_debug("movne %s,#%d\n",regname[rt],imm);
1542   u_int armval;
1543   genimm_checked(imm,&armval);
1544   output_w32(0x13a00000|rd_rn_rm(rt,0,0)|armval);
1545 }
1546 void emit_cmovl_imm(int imm,int rt)
1547 {
1548   assem_debug("movlt %s,#%d\n",regname[rt],imm);
1549   u_int armval;
1550   genimm_checked(imm,&armval);
1551   output_w32(0xb3a00000|rd_rn_rm(rt,0,0)|armval);
1552 }
1553 void emit_cmovb_imm(int imm,int rt)
1554 {
1555   assem_debug("movcc %s,#%d\n",regname[rt],imm);
1556   u_int armval;
1557   genimm_checked(imm,&armval);
1558   output_w32(0x33a00000|rd_rn_rm(rt,0,0)|armval);
1559 }
1560 void emit_cmovs_imm(int imm,int rt)
1561 {
1562   assem_debug("movmi %s,#%d\n",regname[rt],imm);
1563   u_int armval;
1564   genimm_checked(imm,&armval);
1565   output_w32(0x43a00000|rd_rn_rm(rt,0,0)|armval);
1566 }
1567 void emit_cmove_reg(int rs,int rt)
1568 {
1569   assem_debug("moveq %s,%s\n",regname[rt],regname[rs]);
1570   output_w32(0x01a00000|rd_rn_rm(rt,0,rs));
1571 }
1572 void emit_cmovne_reg(int rs,int rt)
1573 {
1574   assem_debug("movne %s,%s\n",regname[rt],regname[rs]);
1575   output_w32(0x11a00000|rd_rn_rm(rt,0,rs));
1576 }
1577 void emit_cmovl_reg(int rs,int rt)
1578 {
1579   assem_debug("movlt %s,%s\n",regname[rt],regname[rs]);
1580   output_w32(0xb1a00000|rd_rn_rm(rt,0,rs));
1581 }
1582 void emit_cmovs_reg(int rs,int rt)
1583 {
1584   assem_debug("movmi %s,%s\n",regname[rt],regname[rs]);
1585   output_w32(0x41a00000|rd_rn_rm(rt,0,rs));
1586 }
1587
1588 void emit_slti32(int rs,int imm,int rt)
1589 {
1590   if(rs!=rt) emit_zeroreg(rt);
1591   emit_cmpimm(rs,imm);
1592   if(rs==rt) emit_movimm(0,rt);
1593   emit_cmovl_imm(1,rt);
1594 }
1595 void emit_sltiu32(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_cmovb_imm(1,rt);
1601 }
1602 void emit_slti64_32(int rsh,int rsl,int imm,int rt)
1603 {
1604   assert(rsh!=rt);
1605   emit_slti32(rsl,imm,rt);
1606   if(imm>=0)
1607   {
1608     emit_test(rsh,rsh);
1609     emit_cmovne_imm(0,rt);
1610     emit_cmovs_imm(1,rt);
1611   }
1612   else
1613   {
1614     emit_cmpimm(rsh,-1);
1615     emit_cmovne_imm(0,rt);
1616     emit_cmovl_imm(1,rt);
1617   }
1618 }
1619 void emit_sltiu64_32(int rsh,int rsl,int imm,int rt)
1620 {
1621   assert(rsh!=rt);
1622   emit_sltiu32(rsl,imm,rt);
1623   if(imm>=0)
1624   {
1625     emit_test(rsh,rsh);
1626     emit_cmovne_imm(0,rt);
1627   }
1628   else
1629   {
1630     emit_cmpimm(rsh,-1);
1631     emit_cmovne_imm(1,rt);
1632   }
1633 }
1634
1635 void emit_cmp(int rs,int rt)
1636 {
1637   assem_debug("cmp %s,%s\n",regname[rs],regname[rt]);
1638   output_w32(0xe1500000|rd_rn_rm(0,rs,rt));
1639 }
1640 void emit_set_gz32(int rs, int rt)
1641 {
1642   //assem_debug("set_gz32\n");
1643   emit_cmpimm(rs,1);
1644   emit_movimm(1,rt);
1645   emit_cmovl_imm(0,rt);
1646 }
1647 void emit_set_nz32(int rs, int rt)
1648 {
1649   //assem_debug("set_nz32\n");
1650   if(rs!=rt) emit_movs(rs,rt);
1651   else emit_test(rs,rs);
1652   emit_cmovne_imm(1,rt);
1653 }
1654 void emit_set_gz64_32(int rsh, int rsl, int rt)
1655 {
1656   //assem_debug("set_gz64\n");
1657   emit_set_gz32(rsl,rt);
1658   emit_test(rsh,rsh);
1659   emit_cmovne_imm(1,rt);
1660   emit_cmovs_imm(0,rt);
1661 }
1662 void emit_set_nz64_32(int rsh, int rsl, int rt)
1663 {
1664   //assem_debug("set_nz64\n");
1665   emit_or_and_set_flags(rsh,rsl,rt);
1666   emit_cmovne_imm(1,rt);
1667 }
1668 void emit_set_if_less32(int rs1, int rs2, int rt)
1669 {
1670   //assem_debug("set if less (%%%s,%%%s),%%%s\n",regname[rs1],regname[rs2],regname[rt]);
1671   if(rs1!=rt&&rs2!=rt) emit_zeroreg(rt);
1672   emit_cmp(rs1,rs2);
1673   if(rs1==rt||rs2==rt) emit_movimm(0,rt);
1674   emit_cmovl_imm(1,rt);
1675 }
1676 void emit_set_if_carry32(int rs1, int rs2, int rt)
1677 {
1678   //assem_debug("set if carry (%%%s,%%%s),%%%s\n",regname[rs1],regname[rs2],regname[rt]);
1679   if(rs1!=rt&&rs2!=rt) emit_zeroreg(rt);
1680   emit_cmp(rs1,rs2);
1681   if(rs1==rt||rs2==rt) emit_movimm(0,rt);
1682   emit_cmovb_imm(1,rt);
1683 }
1684 void emit_set_if_less64_32(int u1, int l1, int u2, int l2, int rt)
1685 {
1686   //assem_debug("set if less64 (%%%s,%%%s,%%%s,%%%s),%%%s\n",regname[u1],regname[l1],regname[u2],regname[l2],regname[rt]);
1687   assert(u1!=rt);
1688   assert(u2!=rt);
1689   emit_cmp(l1,l2);
1690   emit_movimm(0,rt);
1691   emit_sbcs(u1,u2,HOST_TEMPREG);
1692   emit_cmovl_imm(1,rt);
1693 }
1694 void emit_set_if_carry64_32(int u1, int l1, int u2, int l2, int rt)
1695 {
1696   //assem_debug("set if carry64 (%%%s,%%%s,%%%s,%%%s),%%%s\n",regname[u1],regname[l1],regname[u2],regname[l2],regname[rt]);
1697   assert(u1!=rt);
1698   assert(u2!=rt);
1699   emit_cmp(l1,l2);
1700   emit_movimm(0,rt);
1701   emit_sbcs(u1,u2,HOST_TEMPREG);
1702   emit_cmovb_imm(1,rt);
1703 }
1704
1705 void emit_call(int a)
1706 {
1707   assem_debug("bl %x (%x+%x)\n",a,(int)out,a-(int)out-8);
1708   u_int offset=genjmp(a);
1709   output_w32(0xeb000000|offset);
1710 }
1711 void emit_jmp(int a)
1712 {
1713   assem_debug("b %x (%x+%x)\n",a,(int)out,a-(int)out-8);
1714   u_int offset=genjmp(a);
1715   output_w32(0xea000000|offset);
1716 }
1717 void emit_jne(int a)
1718 {
1719   assem_debug("bne %x\n",a);
1720   u_int offset=genjmp(a);
1721   output_w32(0x1a000000|offset);
1722 }
1723 void emit_jeq(int a)
1724 {
1725   assem_debug("beq %x\n",a);
1726   u_int offset=genjmp(a);
1727   output_w32(0x0a000000|offset);
1728 }
1729 void emit_js(int a)
1730 {
1731   assem_debug("bmi %x\n",a);
1732   u_int offset=genjmp(a);
1733   output_w32(0x4a000000|offset);
1734 }
1735 void emit_jns(int a)
1736 {
1737   assem_debug("bpl %x\n",a);
1738   u_int offset=genjmp(a);
1739   output_w32(0x5a000000|offset);
1740 }
1741 void emit_jl(int a)
1742 {
1743   assem_debug("blt %x\n",a);
1744   u_int offset=genjmp(a);
1745   output_w32(0xba000000|offset);
1746 }
1747 void emit_jge(int a)
1748 {
1749   assem_debug("bge %x\n",a);
1750   u_int offset=genjmp(a);
1751   output_w32(0xaa000000|offset);
1752 }
1753 void emit_jno(int a)
1754 {
1755   assem_debug("bvc %x\n",a);
1756   u_int offset=genjmp(a);
1757   output_w32(0x7a000000|offset);
1758 }
1759 void emit_jc(int a)
1760 {
1761   assem_debug("bcs %x\n",a);
1762   u_int offset=genjmp(a);
1763   output_w32(0x2a000000|offset);
1764 }
1765 void emit_jcc(int a)
1766 {
1767   assem_debug("bcc %x\n",a);
1768   u_int offset=genjmp(a);
1769   output_w32(0x3a000000|offset);
1770 }
1771
1772 void emit_pushimm(int imm)
1773 {
1774   assem_debug("push $%x\n",imm);
1775   assert(0);
1776 }
1777 void emit_pusha()
1778 {
1779   assem_debug("pusha\n");
1780   assert(0);
1781 }
1782 void emit_popa()
1783 {
1784   assem_debug("popa\n");
1785   assert(0);
1786 }
1787 void emit_pushreg(u_int r)
1788 {
1789   assem_debug("push %%%s\n",regname[r]);
1790   assert(0);
1791 }
1792 void emit_popreg(u_int r)
1793 {
1794   assem_debug("pop %%%s\n",regname[r]);
1795   assert(0);
1796 }
1797 void emit_callreg(u_int r)
1798 {
1799   assert(r<15);
1800   assem_debug("blx %s\n",regname[r]);
1801   output_w32(0xe12fff30|r);
1802 }
1803 void emit_jmpreg(u_int r)
1804 {
1805   assem_debug("mov pc,%s\n",regname[r]);
1806   output_w32(0xe1a00000|rd_rn_rm(15,0,r));
1807 }
1808
1809 void emit_readword_indexed(int offset, int rs, int rt)
1810 {
1811   assert(offset>-4096&&offset<4096);
1812   assem_debug("ldr %s,%s+%d\n",regname[rt],regname[rs],offset);
1813   if(offset>=0) {
1814     output_w32(0xe5900000|rd_rn_rm(rt,rs,0)|offset);
1815   }else{
1816     output_w32(0xe5100000|rd_rn_rm(rt,rs,0)|(-offset));
1817   }
1818 }
1819 void emit_readword_dualindexedx4(int rs1, int rs2, int rt)
1820 {
1821   assem_debug("ldr %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
1822   output_w32(0xe7900000|rd_rn_rm(rt,rs1,rs2)|0x100);
1823 }
1824 void emit_ldrcc_dualindexed(int rs1, int rs2, int rt)
1825 {
1826   assem_debug("ldrcc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1827   output_w32(0x37900000|rd_rn_rm(rt,rs1,rs2));
1828 }
1829 void emit_ldrccb_dualindexed(int rs1, int rs2, int rt)
1830 {
1831   assem_debug("ldrccb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1832   output_w32(0x37d00000|rd_rn_rm(rt,rs1,rs2));
1833 }
1834 void emit_ldrccsb_dualindexed(int rs1, int rs2, int rt)
1835 {
1836   assem_debug("ldrccsb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1837   output_w32(0x319000d0|rd_rn_rm(rt,rs1,rs2));
1838 }
1839 void emit_ldrcch_dualindexed(int rs1, int rs2, int rt)
1840 {
1841   assem_debug("ldrcch %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1842   output_w32(0x319000b0|rd_rn_rm(rt,rs1,rs2));
1843 }
1844 void emit_ldrccsh_dualindexed(int rs1, int rs2, int rt)
1845 {
1846   assem_debug("ldrccsh %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
1847   output_w32(0x319000f0|rd_rn_rm(rt,rs1,rs2));
1848 }
1849 void emit_readword_indexed_tlb(int addr, int rs, int map, int rt)
1850 {
1851   if(map<0) emit_readword_indexed(addr, rs, rt);
1852   else {
1853     assert(addr==0);
1854     emit_readword_dualindexedx4(rs, map, rt);
1855   }
1856 }
1857 void emit_readdword_indexed_tlb(int addr, int rs, int map, int rh, int rl)
1858 {
1859   if(map<0) {
1860     if(rh>=0) emit_readword_indexed(addr, rs, rh);
1861     emit_readword_indexed(addr+4, rs, rl);
1862   }else{
1863     assert(rh!=rs);
1864     if(rh>=0) emit_readword_indexed_tlb(addr, rs, map, rh);
1865     emit_addimm(map,1,map);
1866     emit_readword_indexed_tlb(addr, rs, map, rl);
1867   }
1868 }
1869 void emit_movsbl_indexed(int offset, int rs, int rt)
1870 {
1871   assert(offset>-256&&offset<256);
1872   assem_debug("ldrsb %s,%s+%d\n",regname[rt],regname[rs],offset);
1873   if(offset>=0) {
1874     output_w32(0xe1d000d0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1875   }else{
1876     output_w32(0xe15000d0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1877   }
1878 }
1879 void emit_movsbl_indexed_tlb(int addr, int rs, int map, int rt)
1880 {
1881   if(map<0) emit_movsbl_indexed(addr, rs, rt);
1882   else {
1883     if(addr==0) {
1884       emit_shlimm(map,2,map);
1885       assem_debug("ldrsb %s,%s+%s\n",regname[rt],regname[rs],regname[map]);
1886       output_w32(0xe19000d0|rd_rn_rm(rt,rs,map));
1887     }else{
1888       assert(addr>-256&&addr<256);
1889       assem_debug("add %s,%s,%s,lsl #2\n",regname[rt],regname[rs],regname[map]);
1890       output_w32(0xe0800000|rd_rn_rm(rt,rs,map)|(2<<7));
1891       emit_movsbl_indexed(addr, rt, rt);
1892     }
1893   }
1894 }
1895 void emit_movswl_indexed(int offset, int rs, int rt)
1896 {
1897   assert(offset>-256&&offset<256);
1898   assem_debug("ldrsh %s,%s+%d\n",regname[rt],regname[rs],offset);
1899   if(offset>=0) {
1900     output_w32(0xe1d000f0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1901   }else{
1902     output_w32(0xe15000f0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1903   }
1904 }
1905 void emit_movzbl_indexed(int offset, int rs, int rt)
1906 {
1907   assert(offset>-4096&&offset<4096);
1908   assem_debug("ldrb %s,%s+%d\n",regname[rt],regname[rs],offset);
1909   if(offset>=0) {
1910     output_w32(0xe5d00000|rd_rn_rm(rt,rs,0)|offset);
1911   }else{
1912     output_w32(0xe5500000|rd_rn_rm(rt,rs,0)|(-offset));
1913   }
1914 }
1915 void emit_movzbl_dualindexedx4(int rs1, int rs2, int rt)
1916 {
1917   assem_debug("ldrb %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
1918   output_w32(0xe7d00000|rd_rn_rm(rt,rs1,rs2)|0x100);
1919 }
1920 void emit_movzbl_indexed_tlb(int addr, int rs, int map, int rt)
1921 {
1922   if(map<0) emit_movzbl_indexed(addr, rs, rt);
1923   else {
1924     if(addr==0) {
1925       emit_movzbl_dualindexedx4(rs, map, rt);
1926     }else{
1927       emit_addimm(rs,addr,rt);
1928       emit_movzbl_dualindexedx4(rt, map, rt);
1929     }
1930   }
1931 }
1932 void emit_movzwl_indexed(int offset, int rs, int rt)
1933 {
1934   assert(offset>-256&&offset<256);
1935   assem_debug("ldrh %s,%s+%d\n",regname[rt],regname[rs],offset);
1936   if(offset>=0) {
1937     output_w32(0xe1d000b0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1938   }else{
1939     output_w32(0xe15000b0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1940   }
1941 }
1942 static void emit_ldrd(int offset, int rs, int rt)
1943 {
1944   assert(offset>-256&&offset<256);
1945   assem_debug("ldrd %s,%s+%d\n",regname[rt],regname[rs],offset);
1946   if(offset>=0) {
1947     output_w32(0xe1c000d0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
1948   }else{
1949     output_w32(0xe14000d0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
1950   }
1951 }
1952 void emit_readword(int addr, int rt)
1953 {
1954   u_int offset = addr-(u_int)&dynarec_local;
1955   assert(offset<4096);
1956   assem_debug("ldr %s,fp+%d\n",regname[rt],offset);
1957   output_w32(0xe5900000|rd_rn_rm(rt,FP,0)|offset);
1958 }
1959 void emit_movsbl(int addr, int rt)
1960 {
1961   u_int offset = addr-(u_int)&dynarec_local;
1962   assert(offset<256);
1963   assem_debug("ldrsb %s,fp+%d\n",regname[rt],offset);
1964   output_w32(0xe1d000d0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
1965 }
1966 void emit_movswl(int addr, int rt)
1967 {
1968   u_int offset = addr-(u_int)&dynarec_local;
1969   assert(offset<256);
1970   assem_debug("ldrsh %s,fp+%d\n",regname[rt],offset);
1971   output_w32(0xe1d000f0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
1972 }
1973 void emit_movzbl(int addr, int rt)
1974 {
1975   u_int offset = addr-(u_int)&dynarec_local;
1976   assert(offset<4096);
1977   assem_debug("ldrb %s,fp+%d\n",regname[rt],offset);
1978   output_w32(0xe5d00000|rd_rn_rm(rt,FP,0)|offset);
1979 }
1980 void emit_movzwl(int addr, int rt)
1981 {
1982   u_int offset = addr-(u_int)&dynarec_local;
1983   assert(offset<256);
1984   assem_debug("ldrh %s,fp+%d\n",regname[rt],offset);
1985   output_w32(0xe1d000b0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
1986 }
1987 void emit_movzwl_reg(int rs, int rt)
1988 {
1989   assem_debug("movzwl %%%s,%%%s\n",regname[rs]+1,regname[rt]);
1990   assert(0);
1991 }
1992
1993 void emit_xchg(int rs, int rt)
1994 {
1995   assem_debug("xchg %%%s,%%%s\n",regname[rs],regname[rt]);
1996   assert(0);
1997 }
1998 void emit_writeword_indexed(int rt, int offset, int rs)
1999 {
2000   assert(offset>-4096&&offset<4096);
2001   assem_debug("str %s,%s+%d\n",regname[rt],regname[rs],offset);
2002   if(offset>=0) {
2003     output_w32(0xe5800000|rd_rn_rm(rt,rs,0)|offset);
2004   }else{
2005     output_w32(0xe5000000|rd_rn_rm(rt,rs,0)|(-offset));
2006   }
2007 }
2008 void emit_writeword_dualindexedx4(int rt, int rs1, int rs2)
2009 {
2010   assem_debug("str %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
2011   output_w32(0xe7800000|rd_rn_rm(rt,rs1,rs2)|0x100);
2012 }
2013 void emit_writeword_indexed_tlb(int rt, int addr, int rs, int map, int temp)
2014 {
2015   if(map<0) emit_writeword_indexed(rt, addr, rs);
2016   else {
2017     assert(addr==0);
2018     emit_writeword_dualindexedx4(rt, rs, map);
2019   }
2020 }
2021 void emit_writedword_indexed_tlb(int rh, int rl, int addr, int rs, int map, int temp)
2022 {
2023   if(map<0) {
2024     if(rh>=0) emit_writeword_indexed(rh, addr, rs);
2025     emit_writeword_indexed(rl, addr+4, rs);
2026   }else{
2027     assert(rh>=0);
2028     if(temp!=rs) emit_addimm(map,1,temp);
2029     emit_writeword_indexed_tlb(rh, addr, rs, map, temp);
2030     if(temp!=rs) emit_writeword_indexed_tlb(rl, addr, rs, temp, temp);
2031     else {
2032       emit_addimm(rs,4,rs);
2033       emit_writeword_indexed_tlb(rl, addr, rs, map, temp);
2034     }
2035   }
2036 }
2037 void emit_writehword_indexed(int rt, int offset, int rs)
2038 {
2039   assert(offset>-256&&offset<256);
2040   assem_debug("strh %s,%s+%d\n",regname[rt],regname[rs],offset);
2041   if(offset>=0) {
2042     output_w32(0xe1c000b0|rd_rn_rm(rt,rs,0)|((offset<<4)&0xf00)|(offset&0xf));
2043   }else{
2044     output_w32(0xe14000b0|rd_rn_rm(rt,rs,0)|(((-offset)<<4)&0xf00)|((-offset)&0xf));
2045   }
2046 }
2047 void emit_writebyte_indexed(int rt, int offset, int rs)
2048 {
2049   assert(offset>-4096&&offset<4096);
2050   assem_debug("strb %s,%s+%d\n",regname[rt],regname[rs],offset);
2051   if(offset>=0) {
2052     output_w32(0xe5c00000|rd_rn_rm(rt,rs,0)|offset);
2053   }else{
2054     output_w32(0xe5400000|rd_rn_rm(rt,rs,0)|(-offset));
2055   }
2056 }
2057 void emit_writebyte_dualindexedx4(int rt, int rs1, int rs2)
2058 {
2059   assem_debug("strb %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
2060   output_w32(0xe7c00000|rd_rn_rm(rt,rs1,rs2)|0x100);
2061 }
2062 void emit_writebyte_indexed_tlb(int rt, int addr, int rs, int map, int temp)
2063 {
2064   if(map<0) emit_writebyte_indexed(rt, addr, rs);
2065   else {
2066     if(addr==0) {
2067       emit_writebyte_dualindexedx4(rt, rs, map);
2068     }else{
2069       emit_addimm(rs,addr,temp);
2070       emit_writebyte_dualindexedx4(rt, temp, map);
2071     }
2072   }
2073 }
2074 void emit_strcc_dualindexed(int rs1, int rs2, int rt)
2075 {
2076   assem_debug("strcc %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2077   output_w32(0x37800000|rd_rn_rm(rt,rs1,rs2));
2078 }
2079 void emit_strccb_dualindexed(int rs1, int rs2, int rt)
2080 {
2081   assem_debug("strccb %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2082   output_w32(0x37c00000|rd_rn_rm(rt,rs1,rs2));
2083 }
2084 void emit_strcch_dualindexed(int rs1, int rs2, int rt)
2085 {
2086   assem_debug("strcch %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2087   output_w32(0x318000b0|rd_rn_rm(rt,rs1,rs2));
2088 }
2089 void emit_writeword(int rt, int addr)
2090 {
2091   u_int offset = addr-(u_int)&dynarec_local;
2092   assert(offset<4096);
2093   assem_debug("str %s,fp+%d\n",regname[rt],offset);
2094   output_w32(0xe5800000|rd_rn_rm(rt,FP,0)|offset);
2095 }
2096 void emit_writehword(int rt, int addr)
2097 {
2098   u_int offset = addr-(u_int)&dynarec_local;
2099   assert(offset<256);
2100   assem_debug("strh %s,fp+%d\n",regname[rt],offset);
2101   output_w32(0xe1c000b0|rd_rn_rm(rt,FP,0)|((offset<<4)&0xf00)|(offset&0xf));
2102 }
2103 void emit_writebyte(int rt, int addr)
2104 {
2105   u_int offset = addr-(u_int)&dynarec_local;
2106   assert(offset<4096);
2107   assem_debug("strb %s,fp+%d\n",regname[rt],offset);
2108   output_w32(0xe5c00000|rd_rn_rm(rt,FP,0)|offset);
2109 }
2110 void emit_writeword_imm(int imm, int addr)
2111 {
2112   assem_debug("movl $%x,%x\n",imm,addr);
2113   assert(0);
2114 }
2115 void emit_writebyte_imm(int imm, int addr)
2116 {
2117   assem_debug("movb $%x,%x\n",imm,addr);
2118   assert(0);
2119 }
2120
2121 void emit_mul(int rs)
2122 {
2123   assem_debug("mul %%%s\n",regname[rs]);
2124   assert(0);
2125 }
2126 void emit_imul(int rs)
2127 {
2128   assem_debug("imul %%%s\n",regname[rs]);
2129   assert(0);
2130 }
2131 void emit_umull(u_int rs1, u_int rs2, u_int hi, u_int lo)
2132 {
2133   assem_debug("umull %s, %s, %s, %s\n",regname[lo],regname[hi],regname[rs1],regname[rs2]);
2134   assert(rs1<16);
2135   assert(rs2<16);
2136   assert(hi<16);
2137   assert(lo<16);
2138   output_w32(0xe0800090|(hi<<16)|(lo<<12)|(rs2<<8)|rs1);
2139 }
2140 void emit_smull(u_int rs1, u_int rs2, u_int hi, u_int lo)
2141 {
2142   assem_debug("smull %s, %s, %s, %s\n",regname[lo],regname[hi],regname[rs1],regname[rs2]);
2143   assert(rs1<16);
2144   assert(rs2<16);
2145   assert(hi<16);
2146   assert(lo<16);
2147   output_w32(0xe0c00090|(hi<<16)|(lo<<12)|(rs2<<8)|rs1);
2148 }
2149
2150 void emit_div(int rs)
2151 {
2152   assem_debug("div %%%s\n",regname[rs]);
2153   assert(0);
2154 }
2155 void emit_idiv(int rs)
2156 {
2157   assem_debug("idiv %%%s\n",regname[rs]);
2158   assert(0);
2159 }
2160 void emit_cdq()
2161 {
2162   assem_debug("cdq\n");
2163   assert(0);
2164 }
2165
2166 void emit_clz(int rs,int rt)
2167 {
2168   assem_debug("clz %s,%s\n",regname[rt],regname[rs]);
2169   output_w32(0xe16f0f10|rd_rn_rm(rt,0,rs));
2170 }
2171
2172 void emit_subcs(int rs1,int rs2,int rt)
2173 {
2174   assem_debug("subcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2175   output_w32(0x20400000|rd_rn_rm(rt,rs1,rs2));
2176 }
2177
2178 void emit_shrcc_imm(int rs,u_int imm,int rt)
2179 {
2180   assert(imm>0);
2181   assert(imm<32);
2182   assem_debug("lsrcc %s,%s,#%d\n",regname[rt],regname[rs],imm);
2183   output_w32(0x31a00000|rd_rn_rm(rt,0,rs)|0x20|(imm<<7));
2184 }
2185
2186 void emit_shrne_imm(int rs,u_int imm,int rt)
2187 {
2188   assert(imm>0);
2189   assert(imm<32);
2190   assem_debug("lsrne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2191   output_w32(0x11a00000|rd_rn_rm(rt,0,rs)|0x20|(imm<<7));
2192 }
2193
2194 void emit_negmi(int rs, int rt)
2195 {
2196   assem_debug("rsbmi %s,%s,#0\n",regname[rt],regname[rs]);
2197   output_w32(0x42600000|rd_rn_rm(rt,rs,0));
2198 }
2199
2200 void emit_negsmi(int rs, int rt)
2201 {
2202   assem_debug("rsbsmi %s,%s,#0\n",regname[rt],regname[rs]);
2203   output_w32(0x42700000|rd_rn_rm(rt,rs,0));
2204 }
2205
2206 void emit_orreq(u_int rs1,u_int rs2,u_int rt)
2207 {
2208   assem_debug("orreq %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2209   output_w32(0x01800000|rd_rn_rm(rt,rs1,rs2));
2210 }
2211
2212 void emit_orrne(u_int rs1,u_int rs2,u_int rt)
2213 {
2214   assem_debug("orrne %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
2215   output_w32(0x11800000|rd_rn_rm(rt,rs1,rs2));
2216 }
2217
2218 void emit_bic_lsl(u_int rs1,u_int rs2,u_int shift,u_int rt)
2219 {
2220   assem_debug("bic %s,%s,%s lsl %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2221   output_w32(0xe1C00000|rd_rn_rm(rt,rs1,rs2)|0x10|(shift<<8));
2222 }
2223
2224 void emit_biceq_lsl(u_int rs1,u_int rs2,u_int shift,u_int rt)
2225 {
2226   assem_debug("biceq %s,%s,%s lsl %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2227   output_w32(0x01C00000|rd_rn_rm(rt,rs1,rs2)|0x10|(shift<<8));
2228 }
2229
2230 void emit_bicne_lsl(u_int rs1,u_int rs2,u_int shift,u_int rt)
2231 {
2232   assem_debug("bicne %s,%s,%s lsl %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2233   output_w32(0x11C00000|rd_rn_rm(rt,rs1,rs2)|0x10|(shift<<8));
2234 }
2235
2236 void emit_bic_lsr(u_int rs1,u_int rs2,u_int shift,u_int rt)
2237 {
2238   assem_debug("bic %s,%s,%s lsr %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2239   output_w32(0xe1C00000|rd_rn_rm(rt,rs1,rs2)|0x30|(shift<<8));
2240 }
2241
2242 void emit_biceq_lsr(u_int rs1,u_int rs2,u_int shift,u_int rt)
2243 {
2244   assem_debug("biceq %s,%s,%s lsr %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2245   output_w32(0x01C00000|rd_rn_rm(rt,rs1,rs2)|0x30|(shift<<8));
2246 }
2247
2248 void emit_bicne_lsr(u_int rs1,u_int rs2,u_int shift,u_int rt)
2249 {
2250   assem_debug("bicne %s,%s,%s lsr %s\n",regname[rt],regname[rs1],regname[rs2],regname[shift]);
2251   output_w32(0x11C00000|rd_rn_rm(rt,rs1,rs2)|0x30|(shift<<8));
2252 }
2253
2254 void emit_teq(int rs, int rt)
2255 {
2256   assem_debug("teq %s,%s\n",regname[rs],regname[rt]);
2257   output_w32(0xe1300000|rd_rn_rm(0,rs,rt));
2258 }
2259
2260 void emit_rsbimm(int rs, int imm, int rt)
2261 {
2262   u_int armval;
2263   genimm_checked(imm,&armval);
2264   assem_debug("rsb %s,%s,#%d\n",regname[rt],regname[rs],imm);
2265   output_w32(0xe2600000|rd_rn_rm(rt,rs,0)|armval);
2266 }
2267
2268 // Load 2 immediates optimizing for small code size
2269 void emit_mov2imm_compact(int imm1,u_int rt1,int imm2,u_int rt2)
2270 {
2271   emit_movimm(imm1,rt1);
2272   u_int armval;
2273   if(genimm(imm2-imm1,&armval)) {
2274     assem_debug("add %s,%s,#%d\n",regname[rt2],regname[rt1],imm2-imm1);
2275     output_w32(0xe2800000|rd_rn_rm(rt2,rt1,0)|armval);
2276   }else if(genimm(imm1-imm2,&armval)) {
2277     assem_debug("sub %s,%s,#%d\n",regname[rt2],regname[rt1],imm1-imm2);
2278     output_w32(0xe2400000|rd_rn_rm(rt2,rt1,0)|armval);
2279   }
2280   else emit_movimm(imm2,rt2);
2281 }
2282
2283 // Conditionally select one of two immediates, optimizing for small code size
2284 // This will only be called if HAVE_CMOV_IMM is defined
2285 void emit_cmov2imm_e_ne_compact(int imm1,int imm2,u_int rt)
2286 {
2287   u_int armval;
2288   if(genimm(imm2-imm1,&armval)) {
2289     emit_movimm(imm1,rt);
2290     assem_debug("addne %s,%s,#%d\n",regname[rt],regname[rt],imm2-imm1);
2291     output_w32(0x12800000|rd_rn_rm(rt,rt,0)|armval);
2292   }else if(genimm(imm1-imm2,&armval)) {
2293     emit_movimm(imm1,rt);
2294     assem_debug("subne %s,%s,#%d\n",regname[rt],regname[rt],imm1-imm2);
2295     output_w32(0x12400000|rd_rn_rm(rt,rt,0)|armval);
2296   }
2297   else {
2298     #ifdef ARMv5_ONLY
2299     emit_movimm(imm1,rt);
2300     add_literal((int)out,imm2);
2301     assem_debug("ldrne %s,pc+? [=%x]\n",regname[rt],imm2);
2302     output_w32(0x15900000|rd_rn_rm(rt,15,0));
2303     #else
2304     emit_movw(imm1&0x0000FFFF,rt);
2305     if((imm1&0xFFFF)!=(imm2&0xFFFF)) {
2306       assem_debug("movwne %s,#%d (0x%x)\n",regname[rt],imm2&0xFFFF,imm2&0xFFFF);
2307       output_w32(0x13000000|rd_rn_rm(rt,0,0)|(imm2&0xfff)|((imm2<<4)&0xf0000));
2308     }
2309     emit_movt(imm1&0xFFFF0000,rt);
2310     if((imm1&0xFFFF0000)!=(imm2&0xFFFF0000)) {
2311       assem_debug("movtne %s,#%d (0x%x)\n",regname[rt],imm2&0xffff0000,imm2&0xffff0000);
2312       output_w32(0x13400000|rd_rn_rm(rt,0,0)|((imm2>>16)&0xfff)|((imm2>>12)&0xf0000));
2313     }
2314     #endif
2315   }
2316 }
2317
2318 // special case for checking invalid_code
2319 void emit_cmpmem_indexedsr12_imm(int addr,int r,int imm)
2320 {
2321   assert(0);
2322 }
2323
2324 // special case for checking invalid_code
2325 void emit_cmpmem_indexedsr12_reg(int base,int r,int imm)
2326 {
2327   assert(imm<128&&imm>=0);
2328   assert(r>=0&&r<16);
2329   assem_debug("ldrb lr,%s,%s lsr #12\n",regname[base],regname[r]);
2330   output_w32(0xe7d00000|rd_rn_rm(HOST_TEMPREG,base,r)|0x620);
2331   emit_cmpimm(HOST_TEMPREG,imm);
2332 }
2333
2334 // special case for tlb mapping
2335 void emit_addsr12(int rs1,int rs2,int rt)
2336 {
2337   assem_debug("add %s,%s,%s lsr #12\n",regname[rt],regname[rs1],regname[rs2]);
2338   output_w32(0xe0800620|rd_rn_rm(rt,rs1,rs2));
2339 }
2340
2341 void emit_callne(int a)
2342 {
2343   assem_debug("blne %x\n",a);
2344   u_int offset=genjmp(a);
2345   output_w32(0x1b000000|offset);
2346 }
2347
2348 // Used to preload hash table entries
2349 void emit_prefetch(void *addr)
2350 {
2351   assem_debug("prefetch %x\n",(int)addr);
2352   output_byte(0x0F);
2353   output_byte(0x18);
2354   output_modrm(0,5,1);
2355   output_w32((int)addr);
2356 }
2357 void emit_prefetchreg(int r)
2358 {
2359   assem_debug("pld %s\n",regname[r]);
2360   output_w32(0xf5d0f000|rd_rn_rm(0,r,0));
2361 }
2362
2363 // Special case for mini_ht
2364 void emit_ldreq_indexed(int rs, u_int offset, int rt)
2365 {
2366   assert(offset<4096);
2367   assem_debug("ldreq %s,[%s, #%d]\n",regname[rt],regname[rs],offset);
2368   output_w32(0x05900000|rd_rn_rm(rt,rs,0)|offset);
2369 }
2370
2371 void emit_flds(int r,int sr)
2372 {
2373   assem_debug("flds s%d,[%s]\n",sr,regname[r]);
2374   output_w32(0xed900a00|((sr&14)<<11)|((sr&1)<<22)|(r<<16));
2375
2376
2377 void emit_vldr(int r,int vr)
2378 {
2379   assem_debug("vldr d%d,[%s]\n",vr,regname[r]);
2380   output_w32(0xed900b00|(vr<<12)|(r<<16));
2381
2382
2383 void emit_fsts(int sr,int r)
2384 {
2385   assem_debug("fsts s%d,[%s]\n",sr,regname[r]);
2386   output_w32(0xed800a00|((sr&14)<<11)|((sr&1)<<22)|(r<<16));
2387
2388
2389 void emit_vstr(int vr,int r)
2390 {
2391   assem_debug("vstr d%d,[%s]\n",vr,regname[r]);
2392   output_w32(0xed800b00|(vr<<12)|(r<<16));
2393
2394
2395 void emit_ftosizs(int s,int d)
2396 {
2397   assem_debug("ftosizs s%d,s%d\n",d,s);
2398   output_w32(0xeebd0ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2399
2400
2401 void emit_ftosizd(int s,int d)
2402 {
2403   assem_debug("ftosizd s%d,d%d\n",d,s);
2404   output_w32(0xeebd0bc0|((d&14)<<11)|((d&1)<<22)|(s&7));
2405
2406
2407 void emit_fsitos(int s,int d)
2408 {
2409   assem_debug("fsitos s%d,s%d\n",d,s);
2410   output_w32(0xeeb80ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2411
2412
2413 void emit_fsitod(int s,int d)
2414 {
2415   assem_debug("fsitod d%d,s%d\n",d,s);
2416   output_w32(0xeeb80bc0|((d&7)<<12)|((s&14)>>1)|((s&1)<<5));
2417
2418
2419 void emit_fcvtds(int s,int d)
2420 {
2421   assem_debug("fcvtds d%d,s%d\n",d,s);
2422   output_w32(0xeeb70ac0|((d&7)<<12)|((s&14)>>1)|((s&1)<<5));
2423
2424
2425 void emit_fcvtsd(int s,int d)
2426 {
2427   assem_debug("fcvtsd s%d,d%d\n",d,s);
2428   output_w32(0xeeb70bc0|((d&14)<<11)|((d&1)<<22)|(s&7));
2429
2430
2431 void emit_fsqrts(int s,int d)
2432 {
2433   assem_debug("fsqrts d%d,s%d\n",d,s);
2434   output_w32(0xeeb10ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2435
2436
2437 void emit_fsqrtd(int s,int d)
2438 {
2439   assem_debug("fsqrtd s%d,d%d\n",d,s);
2440   output_w32(0xeeb10bc0|((d&7)<<12)|(s&7));
2441
2442
2443 void emit_fabss(int s,int d)
2444 {
2445   assem_debug("fabss d%d,s%d\n",d,s);
2446   output_w32(0xeeb00ac0|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2447
2448
2449 void emit_fabsd(int s,int d)
2450 {
2451   assem_debug("fabsd s%d,d%d\n",d,s);
2452   output_w32(0xeeb00bc0|((d&7)<<12)|(s&7));
2453
2454
2455 void emit_fnegs(int s,int d)
2456 {
2457   assem_debug("fnegs d%d,s%d\n",d,s);
2458   output_w32(0xeeb10a40|((d&14)<<11)|((d&1)<<22)|((s&14)>>1)|((s&1)<<5));
2459
2460
2461 void emit_fnegd(int s,int d)
2462 {
2463   assem_debug("fnegd s%d,d%d\n",d,s);
2464   output_w32(0xeeb10b40|((d&7)<<12)|(s&7));
2465
2466
2467 void emit_fadds(int s1,int s2,int d)
2468 {
2469   assem_debug("fadds s%d,s%d,s%d\n",d,s1,s2);
2470   output_w32(0xee300a00|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2471
2472
2473 void emit_faddd(int s1,int s2,int d)
2474 {
2475   assem_debug("faddd d%d,d%d,d%d\n",d,s1,s2);
2476   output_w32(0xee300b00|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2477
2478
2479 void emit_fsubs(int s1,int s2,int d)
2480 {
2481   assem_debug("fsubs s%d,s%d,s%d\n",d,s1,s2);
2482   output_w32(0xee300a40|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2483
2484
2485 void emit_fsubd(int s1,int s2,int d)
2486 {
2487   assem_debug("fsubd d%d,d%d,d%d\n",d,s1,s2);
2488   output_w32(0xee300b40|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2489
2490
2491 void emit_fmuls(int s1,int s2,int d)
2492 {
2493   assem_debug("fmuls s%d,s%d,s%d\n",d,s1,s2);
2494   output_w32(0xee200a00|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2495
2496
2497 void emit_fmuld(int s1,int s2,int d)
2498 {
2499   assem_debug("fmuld d%d,d%d,d%d\n",d,s1,s2);
2500   output_w32(0xee200b00|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2501
2502
2503 void emit_fdivs(int s1,int s2,int d)
2504 {
2505   assem_debug("fdivs s%d,s%d,s%d\n",d,s1,s2);
2506   output_w32(0xee800a00|((d&14)<<11)|((d&1)<<22)|((s1&14)<<15)|((s1&1)<<7)|((s2&14)>>1)|((s2&1)<<5));
2507
2508
2509 void emit_fdivd(int s1,int s2,int d)
2510 {
2511   assem_debug("fdivd d%d,d%d,d%d\n",d,s1,s2);
2512   output_w32(0xee800b00|((d&7)<<12)|((s1&7)<<16)|(s2&7));
2513
2514
2515 void emit_fcmps(int x,int y)
2516 {
2517   assem_debug("fcmps s14, s15\n");
2518   output_w32(0xeeb47a67);
2519
2520
2521 void emit_fcmpd(int x,int y)
2522 {
2523   assem_debug("fcmpd d6, d7\n");
2524   output_w32(0xeeb46b47);
2525
2526
2527 void emit_fmstat()
2528 {
2529   assem_debug("fmstat\n");
2530   output_w32(0xeef1fa10);
2531
2532
2533 void emit_bicne_imm(int rs,int imm,int rt)
2534 {
2535   u_int armval;
2536   genimm_checked(imm,&armval);
2537   assem_debug("bicne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2538   output_w32(0x13c00000|rd_rn_rm(rt,rs,0)|armval);
2539 }
2540
2541 void emit_biccs_imm(int rs,int imm,int rt)
2542 {
2543   u_int armval;
2544   genimm_checked(imm,&armval);
2545   assem_debug("biccs %s,%s,#%d\n",regname[rt],regname[rs],imm);
2546   output_w32(0x23c00000|rd_rn_rm(rt,rs,0)|armval);
2547 }
2548
2549 void emit_bicvc_imm(int rs,int imm,int rt)
2550 {
2551   u_int armval;
2552   genimm_checked(imm,&armval);
2553   assem_debug("bicvc %s,%s,#%d\n",regname[rt],regname[rs],imm);
2554   output_w32(0x73c00000|rd_rn_rm(rt,rs,0)|armval);
2555 }
2556
2557 void emit_bichi_imm(int rs,int imm,int rt)
2558 {
2559   u_int armval;
2560   genimm_checked(imm,&armval);
2561   assem_debug("bichi %s,%s,#%d\n",regname[rt],regname[rs],imm);
2562   output_w32(0x83c00000|rd_rn_rm(rt,rs,0)|armval);
2563 }
2564
2565 void emit_orrvs_imm(int rs,int imm,int rt)
2566 {
2567   u_int armval;
2568   genimm_checked(imm,&armval);
2569   assem_debug("orrvs %s,%s,#%d\n",regname[rt],regname[rs],imm);
2570   output_w32(0x63800000|rd_rn_rm(rt,rs,0)|armval);
2571 }
2572
2573 void emit_orrne_imm(int rs,int imm,int rt)
2574 {
2575   u_int armval;
2576   genimm_checked(imm,&armval);
2577   assem_debug("orrne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2578   output_w32(0x13800000|rd_rn_rm(rt,rs,0)|armval);
2579 }
2580
2581 void emit_andne_imm(int rs,int imm,int rt)
2582 {
2583   u_int armval;
2584   genimm_checked(imm,&armval);
2585   assem_debug("andne %s,%s,#%d\n",regname[rt],regname[rs],imm);
2586   output_w32(0x12000000|rd_rn_rm(rt,rs,0)|armval);
2587 }
2588
2589 void emit_jno_unlikely(int a)
2590 {
2591   //emit_jno(a);
2592   assem_debug("addvc pc,pc,#? (%x)\n",/*a-(int)out-8,*/a);
2593   output_w32(0x72800000|rd_rn_rm(15,15,0));
2594 }
2595
2596 static void save_regs_all(u_int reglist)
2597 {
2598   int i;
2599   if(!reglist) return;
2600   assem_debug("stmia fp,{");
2601   for(i=0;i<16;i++)
2602     if(reglist&(1<<i))
2603       assem_debug("r%d,",i);
2604   assem_debug("}\n");
2605   output_w32(0xe88b0000|reglist);
2606 }
2607 static void restore_regs_all(u_int reglist)
2608 {
2609   int i;
2610   if(!reglist) return;
2611   assem_debug("ldmia fp,{");
2612   for(i=0;i<16;i++)
2613     if(reglist&(1<<i))
2614       assem_debug("r%d,",i);
2615   assem_debug("}\n");
2616   output_w32(0xe89b0000|reglist);
2617 }
2618 // Save registers before function call
2619 static void save_regs(u_int reglist)
2620 {
2621   reglist&=0x100f; // only save the caller-save registers, r0-r3, r12
2622   save_regs_all(reglist);
2623 }
2624 // Restore registers after function call
2625 static void restore_regs(u_int reglist)
2626 {
2627   reglist&=0x100f; // only restore the caller-save registers, r0-r3, r12
2628   restore_regs_all(reglist);
2629 }
2630
2631 // Write back consts using r14 so we don't disturb the other registers
2632 void wb_consts(signed char i_regmap[],uint64_t i_is32,u_int i_dirty,int i)
2633 {
2634   int hr;
2635   for(hr=0;hr<HOST_REGS;hr++) {
2636     if(hr!=EXCLUDE_REG&&i_regmap[hr]>=0&&((i_dirty>>hr)&1)) {
2637       if(((regs[i].isconst>>hr)&1)&&i_regmap[hr]>0) {
2638         if(i_regmap[hr]<64 || !((i_is32>>(i_regmap[hr]&63))&1) ) {
2639           int value=constmap[i][hr];
2640           if(value==0) {
2641             emit_zeroreg(HOST_TEMPREG);
2642           }
2643           else {
2644             emit_movimm(value,HOST_TEMPREG);
2645           }
2646           emit_storereg(i_regmap[hr],HOST_TEMPREG);
2647 #ifndef FORCE32
2648           if((i_is32>>i_regmap[hr])&1) {
2649             if(value!=-1&&value!=0) emit_sarimm(HOST_TEMPREG,31,HOST_TEMPREG);
2650             emit_storereg(i_regmap[hr]|64,HOST_TEMPREG);
2651           }
2652 #endif
2653         }
2654       }
2655     }
2656   }
2657 }
2658
2659 /* Stubs/epilogue */
2660
2661 void literal_pool(int n)
2662 {
2663   if(!literalcount) return;
2664   if(n) {
2665     if((int)out-literals[0][0]<4096-n) return;
2666   }
2667   u_int *ptr;
2668   int i;
2669   for(i=0;i<literalcount;i++)
2670   {
2671     u_int l_addr=(u_int)out;
2672     int j;
2673     for(j=0;j<i;j++) {
2674       if(literals[j][1]==literals[i][1]) {
2675         //printf("dup %08x\n",literals[i][1]);
2676         l_addr=literals[j][0];
2677         break;
2678       }
2679     }
2680     ptr=(u_int *)literals[i][0];
2681     u_int offset=l_addr-(u_int)ptr-8;
2682     assert(offset<4096);
2683     assert(!(offset&3));
2684     *ptr|=offset;
2685     if(l_addr==(u_int)out) {
2686       literals[i][0]=l_addr; // remember for dupes
2687       output_w32(literals[i][1]);
2688     }
2689   }
2690   literalcount=0;
2691 }
2692
2693 void literal_pool_jumpover(int n)
2694 {
2695   if(!literalcount) return;
2696   if(n) {
2697     if((int)out-literals[0][0]<4096-n) return;
2698   }
2699   int jaddr=(int)out;
2700   emit_jmp(0);
2701   literal_pool(0);
2702   set_jump_target(jaddr,(int)out);
2703 }
2704
2705 emit_extjump2(int addr, int target, int linker)
2706 {
2707   u_char *ptr=(u_char *)addr;
2708   assert((ptr[3]&0x0e)==0xa);
2709   emit_loadlp(target,0);
2710   emit_loadlp(addr,1);
2711   assert(addr>=BASE_ADDR&&addr<(BASE_ADDR+(1<<TARGET_SIZE_2)));
2712   //assert((target>=0x80000000&&target<0x80800000)||(target>0xA4000000&&target<0xA4001000));
2713 //DEBUG >
2714 #ifdef DEBUG_CYCLE_COUNT
2715   emit_readword((int)&last_count,ECX);
2716   emit_add(HOST_CCREG,ECX,HOST_CCREG);
2717   emit_readword((int)&next_interupt,ECX);
2718   emit_writeword(HOST_CCREG,(int)&Count);
2719   emit_sub(HOST_CCREG,ECX,HOST_CCREG);
2720   emit_writeword(ECX,(int)&last_count);
2721 #endif
2722 //DEBUG <
2723   emit_jmp(linker);
2724 }
2725
2726 emit_extjump(int addr, int target)
2727 {
2728   emit_extjump2(addr, target, (int)dyna_linker);
2729 }
2730 emit_extjump_ds(int addr, int target)
2731 {
2732   emit_extjump2(addr, target, (int)dyna_linker_ds);
2733 }
2734
2735 // put rt_val into rt, potentially making use of rs with value rs_val
2736 static void emit_movimm_from(u_int rs_val,int rs,u_int rt_val,int rt)
2737 {
2738   u_int armval;
2739   int diff;
2740   if(genimm(rt_val,&armval)) {
2741     assem_debug("mov %s,#%d\n",regname[rt],rt_val);
2742     output_w32(0xe3a00000|rd_rn_rm(rt,0,0)|armval);
2743     return;
2744   }
2745   if(genimm(~rt_val,&armval)) {
2746     assem_debug("mvn %s,#%d\n",regname[rt],rt_val);
2747     output_w32(0xe3e00000|rd_rn_rm(rt,0,0)|armval);
2748     return;
2749   }
2750   diff=rt_val-rs_val;
2751   if(genimm(diff,&armval)) {
2752     assem_debug("add %s,%s,#%d\n",regname[rt],regname[rs],diff);
2753     output_w32(0xe2800000|rd_rn_rm(rt,rs,0)|armval);
2754     return;
2755   }else if(genimm(-diff,&armval)) {
2756     assem_debug("sub %s,%s,#%d\n",regname[rt],regname[rs],-diff);
2757     output_w32(0xe2400000|rd_rn_rm(rt,rs,0)|armval);
2758     return;
2759   }
2760   emit_movimm(rt_val,rt);
2761 }
2762
2763 // return 1 if above function can do it's job cheaply
2764 static int is_similar_value(u_int v1,u_int v2)
2765 {
2766   u_int xs;
2767   int diff;
2768   if(v1==v2) return 1;
2769   diff=v2-v1;
2770   for(xs=diff;xs!=0&&(xs&3)==0;xs>>=2)
2771     ;
2772   if(xs<0x100) return 1;
2773   for(xs=-diff;xs!=0&&(xs&3)==0;xs>>=2)
2774     ;
2775   if(xs<0x100) return 1;
2776   return 0;
2777 }
2778
2779 // trashes r2
2780 static void pass_args(int a0, int a1)
2781 {
2782   if(a0==1&&a1==0) {
2783     // must swap
2784     emit_mov(a0,2); emit_mov(a1,1); emit_mov(2,0);
2785   }
2786   else if(a0!=0&&a1==0) {
2787     emit_mov(a1,1);
2788     if (a0>=0) emit_mov(a0,0);
2789   }
2790   else {
2791     if(a0>=0&&a0!=0) emit_mov(a0,0);
2792     if(a1>=0&&a1!=1) emit_mov(a1,1);
2793   }
2794 }
2795
2796 static void mov_loadtype_adj(int type,int rs,int rt)
2797 {
2798   switch(type) {
2799     case LOADB_STUB:  emit_signextend8(rs,rt); break;
2800     case LOADBU_STUB: emit_andimm(rs,0xff,rt); break;
2801     case LOADH_STUB:  emit_signextend16(rs,rt); break;
2802     case LOADHU_STUB: emit_andimm(rs,0xffff,rt); break;
2803     case LOADW_STUB:  if(rs!=rt) emit_mov(rs,rt); break;
2804     default: assert(0);
2805   }
2806 }
2807
2808 #ifdef PCSX
2809 #include "pcsxmem.h"
2810 #include "pcsxmem_inline.c"
2811 #endif
2812
2813 do_readstub(int n)
2814 {
2815   assem_debug("do_readstub %x\n",start+stubs[n][3]*4);
2816   literal_pool(256);
2817   set_jump_target(stubs[n][1],(int)out);
2818   int type=stubs[n][0];
2819   int i=stubs[n][3];
2820   int rs=stubs[n][4];
2821   struct regstat *i_regs=(struct regstat *)stubs[n][5];
2822   u_int reglist=stubs[n][7];
2823   signed char *i_regmap=i_regs->regmap;
2824   int addr=get_reg(i_regmap,AGEN1+(i&1));
2825   int rth,rt;
2826   int ds;
2827   if(itype[i]==C1LS||itype[i]==C2LS||itype[i]==LOADLR) {
2828     rth=get_reg(i_regmap,FTEMP|64);
2829     rt=get_reg(i_regmap,FTEMP);
2830   }else{
2831     rth=get_reg(i_regmap,rt1[i]|64);
2832     rt=get_reg(i_regmap,rt1[i]);
2833   }
2834   assert(rs>=0);
2835 #ifdef PCSX
2836   int r,temp=-1,temp2=HOST_TEMPREG,regs_saved=0,restore_jump=0;
2837   reglist|=(1<<rs);
2838   for(r=0;r<=12;r++) {
2839     if(((1<<r)&0x13ff)&&((1<<r)&reglist)==0) {
2840       temp=r; break;
2841     }
2842   }
2843   if(rt>=0&&rt1[i]!=0)
2844     reglist&=~(1<<rt);
2845   if(temp==-1) {
2846     save_regs(reglist);
2847     regs_saved=1;
2848     temp=(rs==0)?2:0;
2849   }
2850   if((regs_saved||(reglist&2)==0)&&temp!=1&&rs!=1)
2851     temp2=1;
2852   emit_readword((int)&mem_rtab,temp);
2853   emit_shrimm(rs,12,temp2);
2854   emit_readword_dualindexedx4(temp,temp2,temp2);
2855   emit_lsls_imm(temp2,1,temp2);
2856   if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
2857     switch(type) {
2858       case LOADB_STUB:  emit_ldrccsb_dualindexed(temp2,rs,rt); break;
2859       case LOADBU_STUB: emit_ldrccb_dualindexed(temp2,rs,rt); break;
2860       case LOADH_STUB:  emit_ldrccsh_dualindexed(temp2,rs,rt); break;
2861       case LOADHU_STUB: emit_ldrcch_dualindexed(temp2,rs,rt); break;
2862       case LOADW_STUB:  emit_ldrcc_dualindexed(temp2,rs,rt); break;
2863     }
2864   }
2865   if(regs_saved) {
2866     restore_jump=(int)out;
2867     emit_jcc(0); // jump to reg restore
2868   }
2869   else
2870     emit_jcc(stubs[n][2]); // return address
2871
2872   if(!regs_saved)
2873     save_regs(reglist);
2874   int handler=0;
2875   if(type==LOADB_STUB||type==LOADBU_STUB)
2876     handler=(int)jump_handler_read8;
2877   if(type==LOADH_STUB||type==LOADHU_STUB)
2878     handler=(int)jump_handler_read16;
2879   if(type==LOADW_STUB)
2880     handler=(int)jump_handler_read32;
2881   assert(handler!=0);
2882   pass_args(rs,temp2);
2883   int cc=get_reg(i_regmap,CCREG);
2884   if(cc<0)
2885     emit_loadreg(CCREG,2);
2886   emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
2887   emit_call(handler);
2888   if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
2889     mov_loadtype_adj(type,0,rt);
2890   }
2891   if(restore_jump)
2892     set_jump_target(restore_jump,(int)out);
2893   restore_regs(reglist);
2894   emit_jmp(stubs[n][2]); // return address
2895 #else // !PCSX
2896   if(addr<0) addr=rt;
2897   if(addr<0&&itype[i]!=C1LS&&itype[i]!=C2LS&&itype[i]!=LOADLR) addr=get_reg(i_regmap,-1);
2898   assert(addr>=0);
2899   int ftable=0;
2900   if(type==LOADB_STUB||type==LOADBU_STUB)
2901     ftable=(int)readmemb;
2902   if(type==LOADH_STUB||type==LOADHU_STUB)
2903     ftable=(int)readmemh;
2904   if(type==LOADW_STUB)
2905     ftable=(int)readmem;
2906 #ifndef FORCE32
2907   if(type==LOADD_STUB)
2908     ftable=(int)readmemd;
2909 #endif
2910   assert(ftable!=0);
2911   emit_writeword(rs,(int)&address);
2912   //emit_pusha();
2913   save_regs(reglist);
2914 #ifndef PCSX
2915   ds=i_regs!=&regs[i];
2916   int real_rs=(itype[i]==LOADLR)?-1:get_reg(i_regmap,rs1[i]);
2917   u_int cmask=ds?-1:(0x100f|~i_regs->wasconst);
2918   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);
2919   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty&cmask&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs)));
2920   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);
2921 #endif
2922   emit_shrimm(rs,16,1);
2923   int cc=get_reg(i_regmap,CCREG);
2924   if(cc<0) {
2925     emit_loadreg(CCREG,2);
2926   }
2927   emit_movimm(ftable,0);
2928   emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
2929 #ifndef PCSX
2930   emit_movimm(start+stubs[n][3]*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
2931 #endif
2932   //emit_readword((int)&last_count,temp);
2933   //emit_add(cc,temp,cc);
2934   //emit_writeword(cc,(int)&Count);
2935   //emit_mov(15,14);
2936   emit_call((int)&indirect_jump_indexed);
2937   //emit_callreg(rs);
2938   //emit_readword_dualindexedx4(rs,HOST_TEMPREG,15);
2939 #ifndef PCSX
2940   // We really shouldn't need to update the count here,
2941   // but not doing so causes random crashes...
2942   emit_readword((int)&Count,HOST_TEMPREG);
2943   emit_readword((int)&next_interupt,2);
2944   emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
2945   emit_writeword(2,(int)&last_count);
2946   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
2947   if(cc<0) {
2948     emit_storereg(CCREG,HOST_TEMPREG);
2949   }
2950 #endif
2951   //emit_popa();
2952   restore_regs(reglist);
2953   //if((cc=get_reg(regmap,CCREG))>=0) {
2954   //  emit_loadreg(CCREG,cc);
2955   //}
2956   if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
2957     assert(rt>=0);
2958     if(type==LOADB_STUB)
2959       emit_movsbl((int)&readmem_dword,rt);
2960     if(type==LOADBU_STUB)
2961       emit_movzbl((int)&readmem_dword,rt);
2962     if(type==LOADH_STUB)
2963       emit_movswl((int)&readmem_dword,rt);
2964     if(type==LOADHU_STUB)
2965       emit_movzwl((int)&readmem_dword,rt);
2966     if(type==LOADW_STUB)
2967       emit_readword((int)&readmem_dword,rt);
2968     if(type==LOADD_STUB) {
2969       emit_readword((int)&readmem_dword,rt);
2970       if(rth>=0) emit_readword(((int)&readmem_dword)+4,rth);
2971     }
2972   }
2973   emit_jmp(stubs[n][2]); // return address
2974 #endif // !PCSX
2975 }
2976
2977 #ifdef PCSX
2978 // return memhandler, or get directly accessable address and return 0
2979 u_int get_direct_memhandler(void *table,u_int addr,int type,u_int *addr_host)
2980 {
2981   u_int l1,l2=0;
2982   l1=((u_int *)table)[addr>>12];
2983   if((l1&(1<<31))==0) {
2984     u_int v=l1<<1;
2985     *addr_host=v+addr;
2986     return 0;
2987   }
2988   else {
2989     l1<<=1;
2990     if(type==LOADB_STUB||type==LOADBU_STUB||type==STOREB_STUB)
2991       l2=((u_int *)l1)[0x1000/4 + 0x1000/2 + (addr&0xfff)];
2992     else if(type==LOADH_STUB||type==LOADHU_STUB||type==STOREH_STUB)
2993       l2=((u_int *)l1)[0x1000/4 + (addr&0xfff)/2];
2994     else
2995       l2=((u_int *)l1)[(addr&0xfff)/4];
2996     if((l2&(1<<31))==0) {
2997       u_int v=l2<<1;
2998       *addr_host=v+(addr&0xfff);
2999       return 0;
3000     }
3001     return l2<<1;
3002   }
3003 }
3004 #endif
3005
3006 inline_readstub(int type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
3007 {
3008   int rs=get_reg(regmap,target);
3009   int rth=get_reg(regmap,target|64);
3010   int rt=get_reg(regmap,target);
3011   if(rs<0) rs=get_reg(regmap,-1);
3012   assert(rs>=0);
3013 #ifdef PCSX
3014   u_int handler,host_addr=0,is_dynamic,far_call=0;
3015   int cc=get_reg(regmap,CCREG);
3016   if(pcsx_direct_read(type,addr,CLOCK_ADJUST(adj+1),cc,target?rs:-1,rt))
3017     return;
3018   handler=get_direct_memhandler(mem_rtab,addr,type,&host_addr);
3019   if (handler==0) {
3020     if(rt<0||rt1[i]==0)
3021       return;
3022     if(addr!=host_addr)
3023       emit_movimm_from(addr,rs,host_addr,rs);
3024     switch(type) {
3025       case LOADB_STUB:  emit_movsbl_indexed(0,rs,rt); break;
3026       case LOADBU_STUB: emit_movzbl_indexed(0,rs,rt); break;
3027       case LOADH_STUB:  emit_movswl_indexed(0,rs,rt); break;
3028       case LOADHU_STUB: emit_movzwl_indexed(0,rs,rt); break;
3029       case LOADW_STUB:  emit_readword_indexed(0,rs,rt); break;
3030       default:          assert(0);
3031     }
3032     return;
3033   }
3034   is_dynamic=pcsxmem_is_handler_dynamic(addr);
3035   if(is_dynamic) {
3036     if(type==LOADB_STUB||type==LOADBU_STUB)
3037       handler=(int)jump_handler_read8;
3038     if(type==LOADH_STUB||type==LOADHU_STUB)
3039       handler=(int)jump_handler_read16;
3040     if(type==LOADW_STUB)
3041       handler=(int)jump_handler_read32;
3042   }
3043
3044   // call a memhandler
3045   if(rt>=0&&rt1[i]!=0)
3046     reglist&=~(1<<rt);
3047   save_regs(reglist);
3048   if(target==0)
3049     emit_movimm(addr,0);
3050   else if(rs!=0)
3051     emit_mov(rs,0);
3052   int offset=(int)handler-(int)out-8;
3053   if(offset<-33554432||offset>=33554432) {
3054     // unreachable memhandler, a plugin func perhaps
3055     emit_movimm(handler,12);
3056     far_call=1;
3057   }
3058   if(cc<0)
3059     emit_loadreg(CCREG,2);
3060   if(is_dynamic) {
3061     emit_movimm(((u_int *)mem_rtab)[addr>>12]<<1,1);
3062     emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3063   }
3064   else {
3065     emit_readword((int)&last_count,3);
3066     emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3067     emit_add(2,3,2);
3068     emit_writeword(2,(int)&Count);
3069   }
3070
3071   if(far_call)
3072     emit_callreg(12);
3073   else
3074     emit_call(handler);
3075
3076   if(rt>=0&&rt1[i]!=0) {
3077     switch(type) {
3078       case LOADB_STUB:  emit_signextend8(0,rt); break;
3079       case LOADBU_STUB: emit_andimm(0,0xff,rt); break;
3080       case LOADH_STUB:  emit_signextend16(0,rt); break;
3081       case LOADHU_STUB: emit_andimm(0,0xffff,rt); break;
3082       case LOADW_STUB:  if(rt!=0) emit_mov(0,rt); break;
3083       default:          assert(0);
3084     }
3085   }
3086   restore_regs(reglist);
3087 #else // if !PCSX
3088   int ftable=0;
3089   if(type==LOADB_STUB||type==LOADBU_STUB)
3090     ftable=(int)readmemb;
3091   if(type==LOADH_STUB||type==LOADHU_STUB)
3092     ftable=(int)readmemh;
3093   if(type==LOADW_STUB)
3094     ftable=(int)readmem;
3095 #ifndef FORCE32
3096   if(type==LOADD_STUB)
3097     ftable=(int)readmemd;
3098 #endif
3099   assert(ftable!=0);
3100   if(target==0)
3101     emit_movimm(addr,rs);
3102   emit_writeword(rs,(int)&address);
3103   //emit_pusha();
3104   save_regs(reglist);
3105 #ifndef PCSX
3106   if((signed int)addr>=(signed int)0xC0000000) {
3107     // Theoretically we can have a pagefault here, if the TLB has never
3108     // been enabled and the address is outside the range 80000000..BFFFFFFF
3109     // Write out the registers so the pagefault can be handled.  This is
3110     // a very rare case and likely represents a bug.
3111     int ds=regmap!=regs[i].regmap;
3112     if(!ds) load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
3113     if(!ds) wb_dirtys(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty);
3114     else wb_dirtys(branch_regs[i-1].regmap_entry,branch_regs[i-1].was32,branch_regs[i-1].wasdirty);
3115   }
3116 #endif
3117   //emit_shrimm(rs,16,1);
3118   int cc=get_reg(regmap,CCREG);
3119   if(cc<0) {
3120     emit_loadreg(CCREG,2);
3121   }
3122   //emit_movimm(ftable,0);
3123   emit_movimm(((u_int *)ftable)[addr>>16],0);
3124   //emit_readword((int)&last_count,12);
3125   emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3126 #ifndef PCSX
3127   if((signed int)addr>=(signed int)0xC0000000) {
3128     // Pagefault address
3129     int ds=regmap!=regs[i].regmap;
3130     emit_movimm(start+i*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3131   }
3132 #endif
3133   //emit_add(12,2,2);
3134   //emit_writeword(2,(int)&Count);
3135   //emit_call(((u_int *)ftable)[addr>>16]);
3136   emit_call((int)&indirect_jump);
3137 #ifndef PCSX
3138   // We really shouldn't need to update the count here,
3139   // but not doing so causes random crashes...
3140   emit_readword((int)&Count,HOST_TEMPREG);
3141   emit_readword((int)&next_interupt,2);
3142   emit_addimm(HOST_TEMPREG,-CLOCK_ADJUST(adj+1),HOST_TEMPREG);
3143   emit_writeword(2,(int)&last_count);
3144   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3145   if(cc<0) {
3146     emit_storereg(CCREG,HOST_TEMPREG);
3147   }
3148 #endif
3149   //emit_popa();
3150   restore_regs(reglist);
3151   if(rt>=0) {
3152     if(type==LOADB_STUB)
3153       emit_movsbl((int)&readmem_dword,rt);
3154     if(type==LOADBU_STUB)
3155       emit_movzbl((int)&readmem_dword,rt);
3156     if(type==LOADH_STUB)
3157       emit_movswl((int)&readmem_dword,rt);
3158     if(type==LOADHU_STUB)
3159       emit_movzwl((int)&readmem_dword,rt);
3160     if(type==LOADW_STUB)
3161       emit_readword((int)&readmem_dword,rt);
3162     if(type==LOADD_STUB) {
3163       emit_readword((int)&readmem_dword,rt);
3164       if(rth>=0) emit_readword(((int)&readmem_dword)+4,rth);
3165     }
3166   }
3167 #endif // !PCSX
3168 }
3169
3170 do_writestub(int n)
3171 {
3172   assem_debug("do_writestub %x\n",start+stubs[n][3]*4);
3173   literal_pool(256);
3174   set_jump_target(stubs[n][1],(int)out);
3175   int type=stubs[n][0];
3176   int i=stubs[n][3];
3177   int rs=stubs[n][4];
3178   struct regstat *i_regs=(struct regstat *)stubs[n][5];
3179   u_int reglist=stubs[n][7];
3180   signed char *i_regmap=i_regs->regmap;
3181   int addr=get_reg(i_regmap,AGEN1+(i&1));
3182   int rth,rt,r;
3183   int ds;
3184   if(itype[i]==C1LS||itype[i]==C2LS) {
3185     rth=get_reg(i_regmap,FTEMP|64);
3186     rt=get_reg(i_regmap,r=FTEMP);
3187   }else{
3188     rth=get_reg(i_regmap,rs2[i]|64);
3189     rt=get_reg(i_regmap,r=rs2[i]);
3190   }
3191   assert(rs>=0);
3192   assert(rt>=0);
3193 #ifdef PCSX
3194   int rtmp,temp=-1,temp2=HOST_TEMPREG,regs_saved=0,restore_jump=0,ra;
3195   int reglist2=reglist|(1<<rs)|(1<<rt);
3196   for(rtmp=0;rtmp<=12;rtmp++) {
3197     if(((1<<rtmp)&0x13ff)&&((1<<rtmp)&reglist2)==0) {
3198       temp=rtmp; break;
3199     }
3200   }
3201   if(temp==-1) {
3202     save_regs(reglist);
3203     regs_saved=1;
3204     for(rtmp=0;rtmp<=3;rtmp++)
3205       if(rtmp!=rs&&rtmp!=rt)
3206         {temp=rtmp;break;}
3207   }
3208   if((regs_saved||(reglist2&8)==0)&&temp!=3&&rs!=3&&rt!=3)
3209     temp2=3;
3210   emit_readword((int)&mem_wtab,temp);
3211   emit_shrimm(rs,12,temp2);
3212   emit_readword_dualindexedx4(temp,temp2,temp2);
3213   emit_lsls_imm(temp2,1,temp2);
3214   switch(type) {
3215     case STOREB_STUB: emit_strccb_dualindexed(temp2,rs,rt); break;
3216     case STOREH_STUB: emit_strcch_dualindexed(temp2,rs,rt); break;
3217     case STOREW_STUB: emit_strcc_dualindexed(temp2,rs,rt); break;
3218     default:          assert(0);
3219   }
3220   if(regs_saved) {
3221     restore_jump=(int)out;
3222     emit_jcc(0); // jump to reg restore
3223   }
3224   else
3225     emit_jcc(stubs[n][2]); // return address (invcode check)
3226
3227   if(!regs_saved)
3228     save_regs(reglist);
3229   int handler=0;
3230   switch(type) {
3231     case STOREB_STUB: handler=(int)jump_handler_write8; break;
3232     case STOREH_STUB: handler=(int)jump_handler_write16; break;
3233     case STOREW_STUB: handler=(int)jump_handler_write32; break;
3234   }
3235   assert(handler!=0);
3236   pass_args(rs,rt);
3237   if(temp2!=3)
3238     emit_mov(temp2,3);
3239   int cc=get_reg(i_regmap,CCREG);
3240   if(cc<0)
3241     emit_loadreg(CCREG,2);
3242   emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
3243   // returns new cycle_count
3244   emit_call(handler);
3245   emit_addimm(0,-CLOCK_ADJUST((int)stubs[n][6]+1),cc<0?2:cc);
3246   if(cc<0)
3247     emit_storereg(CCREG,2);
3248   if(restore_jump)
3249     set_jump_target(restore_jump,(int)out);
3250   restore_regs(reglist);
3251   ra=stubs[n][2];
3252   emit_jmp(ra);
3253 #else // if !PCSX
3254   if(addr<0) addr=get_reg(i_regmap,-1);
3255   assert(addr>=0);
3256   int ftable=0;
3257   if(type==STOREB_STUB)
3258     ftable=(int)writememb;
3259   if(type==STOREH_STUB)
3260     ftable=(int)writememh;
3261   if(type==STOREW_STUB)
3262     ftable=(int)writemem;
3263 #ifndef FORCE32
3264   if(type==STORED_STUB)
3265     ftable=(int)writememd;
3266 #endif
3267   assert(ftable!=0);
3268   emit_writeword(rs,(int)&address);
3269   //emit_shrimm(rs,16,rs);
3270   //emit_movmem_indexedx4(ftable,rs,rs);
3271   if(type==STOREB_STUB)
3272     emit_writebyte(rt,(int)&byte);
3273   if(type==STOREH_STUB)
3274     emit_writehword(rt,(int)&hword);
3275   if(type==STOREW_STUB)
3276     emit_writeword(rt,(int)&word);
3277   if(type==STORED_STUB) {
3278 #ifndef FORCE32
3279     emit_writeword(rt,(int)&dword);
3280     emit_writeword(r?rth:rt,(int)&dword+4);
3281 #else
3282     printf("STORED_STUB\n");
3283 #endif
3284   }
3285   //emit_pusha();
3286   save_regs(reglist);
3287 #ifndef PCSX
3288   ds=i_regs!=&regs[i];
3289   int real_rs=get_reg(i_regmap,rs1[i]);
3290   u_int cmask=ds?-1:(0x100f|~i_regs->wasconst);
3291   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);
3292   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty&cmask&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs)));
3293   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);
3294 #endif
3295   emit_shrimm(rs,16,1);
3296   int cc=get_reg(i_regmap,CCREG);
3297   if(cc<0) {
3298     emit_loadreg(CCREG,2);
3299   }
3300   emit_movimm(ftable,0);
3301   emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
3302 #ifndef PCSX
3303   emit_movimm(start+stubs[n][3]*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3304 #endif
3305   //emit_readword((int)&last_count,temp);
3306   //emit_addimm(cc,2*stubs[n][5]+2,cc);
3307   //emit_add(cc,temp,cc);
3308   //emit_writeword(cc,(int)&Count);
3309   emit_call((int)&indirect_jump_indexed);
3310   //emit_callreg(rs);
3311   emit_readword((int)&Count,HOST_TEMPREG);
3312   emit_readword((int)&next_interupt,2);
3313   emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
3314   emit_writeword(2,(int)&last_count);
3315   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3316   if(cc<0) {
3317     emit_storereg(CCREG,HOST_TEMPREG);
3318   }
3319   //emit_popa();
3320   restore_regs(reglist);
3321   //if((cc=get_reg(regmap,CCREG))>=0) {
3322   //  emit_loadreg(CCREG,cc);
3323   //}
3324   emit_jmp(stubs[n][2]); // return address
3325 #endif // !PCSX
3326 }
3327
3328 inline_writestub(int type, int i, u_int addr, signed char regmap[], int target, int adj, u_int reglist)
3329 {
3330   int rs=get_reg(regmap,-1);
3331   int rth=get_reg(regmap,target|64);
3332   int rt=get_reg(regmap,target);
3333   assert(rs>=0);
3334   assert(rt>=0);
3335 #ifdef PCSX
3336   u_int handler,host_addr=0;
3337   handler=get_direct_memhandler(mem_wtab,addr,type,&host_addr);
3338   if (handler==0) {
3339     if(addr!=host_addr)
3340       emit_movimm_from(addr,rs,host_addr,rs);
3341     switch(type) {
3342       case STOREB_STUB: emit_writebyte_indexed(rt,0,rs); break;
3343       case STOREH_STUB: emit_writehword_indexed(rt,0,rs); break;
3344       case STOREW_STUB: emit_writeword_indexed(rt,0,rs); break;
3345       default:          assert(0);
3346     }
3347     return;
3348   }
3349
3350   // call a memhandler
3351   save_regs(reglist);
3352   pass_args(rs,rt);
3353   int cc=get_reg(regmap,CCREG);
3354   if(cc<0)
3355     emit_loadreg(CCREG,2);
3356   emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3357   emit_movimm(handler,3);
3358   // returns new cycle_count
3359   emit_call((int)jump_handler_write_h);
3360   emit_addimm(0,-CLOCK_ADJUST(adj+1),cc<0?2:cc);
3361   if(cc<0)
3362     emit_storereg(CCREG,2);
3363   restore_regs(reglist);
3364 #else // if !pcsx
3365   int ftable=0;
3366   if(type==STOREB_STUB)
3367     ftable=(int)writememb;
3368   if(type==STOREH_STUB)
3369     ftable=(int)writememh;
3370   if(type==STOREW_STUB)
3371     ftable=(int)writemem;
3372 #ifndef FORCE32
3373   if(type==STORED_STUB)
3374     ftable=(int)writememd;
3375 #endif
3376   assert(ftable!=0);
3377   emit_writeword(rs,(int)&address);
3378   //emit_shrimm(rs,16,rs);
3379   //emit_movmem_indexedx4(ftable,rs,rs);
3380   if(type==STOREB_STUB)
3381     emit_writebyte(rt,(int)&byte);
3382   if(type==STOREH_STUB)
3383     emit_writehword(rt,(int)&hword);
3384   if(type==STOREW_STUB)
3385     emit_writeword(rt,(int)&word);
3386   if(type==STORED_STUB) {
3387 #ifndef FORCE32
3388     emit_writeword(rt,(int)&dword);
3389     emit_writeword(target?rth:rt,(int)&dword+4);
3390 #else
3391     printf("STORED_STUB\n");
3392 #endif
3393   }
3394   //emit_pusha();
3395   save_regs(reglist);
3396 #ifndef PCSX
3397   // rearmed note: load_all_consts prevents BIOS boot, some bug?
3398   if((signed int)addr>=(signed int)0xC0000000) {
3399     // Theoretically we can have a pagefault here, if the TLB has never
3400     // been enabled and the address is outside the range 80000000..BFFFFFFF
3401     // Write out the registers so the pagefault can be handled.  This is
3402     // a very rare case and likely represents a bug.
3403     int ds=regmap!=regs[i].regmap;
3404     if(!ds) load_all_consts(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty,i);
3405     if(!ds) wb_dirtys(regs[i].regmap_entry,regs[i].was32,regs[i].wasdirty);
3406     else wb_dirtys(branch_regs[i-1].regmap_entry,branch_regs[i-1].was32,branch_regs[i-1].wasdirty);
3407   }
3408 #endif
3409   //emit_shrimm(rs,16,1);
3410   int cc=get_reg(regmap,CCREG);
3411   if(cc<0) {
3412     emit_loadreg(CCREG,2);
3413   }
3414   //emit_movimm(ftable,0);
3415   emit_movimm(((u_int *)ftable)[addr>>16],0);
3416   //emit_readword((int)&last_count,12);
3417   emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
3418 #ifndef PCSX
3419   if((signed int)addr>=(signed int)0xC0000000) {
3420     // Pagefault address
3421     int ds=regmap!=regs[i].regmap;
3422     emit_movimm(start+i*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3423   }
3424 #endif
3425   //emit_add(12,2,2);
3426   //emit_writeword(2,(int)&Count);
3427   //emit_call(((u_int *)ftable)[addr>>16]);
3428   emit_call((int)&indirect_jump);
3429   emit_readword((int)&Count,HOST_TEMPREG);
3430   emit_readword((int)&next_interupt,2);
3431   emit_addimm(HOST_TEMPREG,-CLOCK_ADJUST(adj+1),HOST_TEMPREG);
3432   emit_writeword(2,(int)&last_count);
3433   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3434   if(cc<0) {
3435     emit_storereg(CCREG,HOST_TEMPREG);
3436   }
3437   //emit_popa();
3438   restore_regs(reglist);
3439 #endif
3440 }
3441
3442 do_unalignedwritestub(int n)
3443 {
3444   assem_debug("do_unalignedwritestub %x\n",start+stubs[n][3]*4);
3445   literal_pool(256);
3446   set_jump_target(stubs[n][1],(int)out);
3447
3448   int i=stubs[n][3];
3449   struct regstat *i_regs=(struct regstat *)stubs[n][4];
3450   int addr=stubs[n][5];
3451   u_int reglist=stubs[n][7];
3452   signed char *i_regmap=i_regs->regmap;
3453   int temp2=get_reg(i_regmap,FTEMP);
3454   int rt;
3455   int ds, real_rs;
3456   rt=get_reg(i_regmap,rs2[i]);
3457   assert(rt>=0);
3458   assert(addr>=0);
3459   assert(opcode[i]==0x2a||opcode[i]==0x2e); // SWL/SWR only implemented
3460   reglist|=(1<<addr);
3461   reglist&=~(1<<temp2);
3462
3463 #if 1
3464   // don't bother with it and call write handler
3465   save_regs(reglist);
3466   pass_args(addr,rt);
3467   int cc=get_reg(i_regmap,CCREG);
3468   if(cc<0)
3469     emit_loadreg(CCREG,2);
3470   emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
3471   emit_call((int)(opcode[i]==0x2a?jump_handle_swl:jump_handle_swr));
3472   emit_addimm(0,-CLOCK_ADJUST((int)stubs[n][6]+1),cc<0?2:cc);
3473   if(cc<0)
3474     emit_storereg(CCREG,2);
3475   restore_regs(reglist);
3476   emit_jmp(stubs[n][2]); // return address
3477 #else
3478   emit_andimm(addr,0xfffffffc,temp2);
3479   emit_writeword(temp2,(int)&address);
3480
3481   save_regs(reglist);
3482 #ifndef PCSX
3483   ds=i_regs!=&regs[i];
3484   real_rs=get_reg(i_regmap,rs1[i]);
3485   u_int cmask=ds?-1:(0x100f|~i_regs->wasconst);
3486   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);
3487   wb_dirtys(i_regs->regmap_entry,i_regs->was32,i_regs->wasdirty&cmask&~(1<<addr)&(real_rs<0?-1:~(1<<real_rs)));
3488   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);
3489 #endif
3490   emit_shrimm(addr,16,1);
3491   int cc=get_reg(i_regmap,CCREG);
3492   if(cc<0) {
3493     emit_loadreg(CCREG,2);
3494   }
3495   emit_movimm((u_int)readmem,0);
3496   emit_addimm(cc<0?2:cc,2*stubs[n][6]+2,2);
3497 #ifndef PCSX
3498   // pagefault address
3499   emit_movimm(start+stubs[n][3]*4+(((regs[i].was32>>rs1[i])&1)<<1)+ds,3);
3500 #endif
3501   emit_call((int)&indirect_jump_indexed);
3502   restore_regs(reglist);
3503
3504   emit_readword((int)&readmem_dword,temp2);
3505   int temp=addr; //hmh
3506   emit_shlimm(addr,3,temp);
3507   emit_andimm(temp,24,temp);
3508 #ifdef BIG_ENDIAN_MIPS
3509   if (opcode[i]==0x2e) // SWR
3510 #else
3511   if (opcode[i]==0x2a) // SWL
3512 #endif
3513     emit_xorimm(temp,24,temp);
3514   emit_movimm(-1,HOST_TEMPREG);
3515   if (opcode[i]==0x2a) { // SWL
3516     emit_bic_lsr(temp2,HOST_TEMPREG,temp,temp2);
3517     emit_orrshr(rt,temp,temp2);
3518   }else{
3519     emit_bic_lsl(temp2,HOST_TEMPREG,temp,temp2);
3520     emit_orrshl(rt,temp,temp2);
3521   }
3522   emit_readword((int)&address,addr);
3523   emit_writeword(temp2,(int)&word);
3524   //save_regs(reglist); // don't need to, no state changes
3525   emit_shrimm(addr,16,1);
3526   emit_movimm((u_int)writemem,0);
3527   //emit_call((int)&indirect_jump_indexed);
3528   emit_mov(15,14);
3529   emit_readword_dualindexedx4(0,1,15);
3530   emit_readword((int)&Count,HOST_TEMPREG);
3531   emit_readword((int)&next_interupt,2);
3532   emit_addimm(HOST_TEMPREG,-2*stubs[n][6]-2,HOST_TEMPREG);
3533   emit_writeword(2,(int)&last_count);
3534   emit_sub(HOST_TEMPREG,2,cc<0?HOST_TEMPREG:cc);
3535   if(cc<0) {
3536     emit_storereg(CCREG,HOST_TEMPREG);
3537   }
3538   restore_regs(reglist);
3539   emit_jmp(stubs[n][2]); // return address
3540 #endif
3541 }
3542
3543 void printregs(int edi,int esi,int ebp,int esp,int b,int d,int c,int a)
3544 {
3545   printf("regs: %x %x %x %x %x %x %x (%x)\n",a,b,c,d,ebp,esi,edi,(&edi)[-1]);
3546 }
3547
3548 do_invstub(int n)
3549 {
3550   literal_pool(20);
3551   u_int reglist=stubs[n][3];
3552   set_jump_target(stubs[n][1],(int)out);
3553   save_regs(reglist);
3554   if(stubs[n][4]!=0) emit_mov(stubs[n][4],0);
3555   emit_call((int)&invalidate_addr);
3556   restore_regs(reglist);
3557   emit_jmp(stubs[n][2]); // return address
3558 }
3559
3560 int do_dirty_stub(int i)
3561 {
3562   assem_debug("do_dirty_stub %x\n",start+i*4);
3563   u_int addr=(int)start<(int)0xC0000000?(u_int)source:(u_int)start;
3564   #ifdef PCSX
3565   addr=(u_int)source;
3566   #endif
3567   // Careful about the code output here, verify_dirty needs to parse it.