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