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