Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / x86 / regcache.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   Mupen64plus - regcache.c                                              *
3  *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
4  *   Copyright (C) 2002 Hacktarux                                          *
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 #include <stdio.h>
23
24 #include "regcache.h"
25
26 #include "r4300/recomp.h"
27 #include "r4300/r4300.h"
28 #include "r4300/recomph.h"
29
30 static unsigned int* reg_content[8];
31 static precomp_instr* last_access[8];
32 static precomp_instr* free_since[8];
33 static int dirty[8];
34 static int r64[8];
35 static unsigned int* r0;
36
37 void init_cache(precomp_instr* start)
38 {
39    int i;
40    for (i=0; i<8; i++)
41      {
42     last_access[i] = NULL;
43     free_since[i] = start;
44      }
45      r0 = (unsigned int*)reg;
46 }
47
48 void free_all_registers(void)
49 {
50 #if defined(PROFILE_R4300)
51   int freestart = code_length;
52   int flushed = 0;
53 #endif
54
55    int i;
56    for (i=0; i<8; i++)
57      {
58 #if defined(PROFILE_R4300)
59     if (last_access[i] && dirty[i]) flushed = 1;
60 #endif
61     if (last_access[i]) free_register(i);
62     else
63       {
64          while (free_since[i] <= dst)
65            {
66           free_since[i]->reg_cache_infos.needed_registers[i] = NULL;
67           free_since[i]++;
68            }
69       }
70      }
71
72 #if defined(PROFILE_R4300)
73   if (flushed == 1)
74   {
75     long x86addr = (long) ((*inst_pointer) + freestart);
76     int mipsop = -5;
77     fwrite(&mipsop, 1, 4, pfProfile); /* -5 = regcache flushing */
78     fwrite(&x86addr, 1, sizeof(char *), pfProfile); // write pointer to start of register cache flushing instructions
79     x86addr = (long) ((*inst_pointer) + code_length);
80     fwrite(&src, 1, 4, pfProfile); // write 4-byte MIPS opcode for current instruction
81     fwrite(&x86addr, 1, sizeof(char *), pfProfile); // write pointer to dynamically generated x86 code for this MIPS instruction
82   }
83 #endif
84 }
85
86 // this function frees a specific X86 GPR
87 void free_register(int reg)
88 {
89    precomp_instr *last;
90    
91    if (last_access[reg] != NULL &&
92        r64[reg] != -1 && (int)reg_content[reg] != (int)reg_content[r64[reg]]-4)
93      {
94     free_register(r64[reg]);
95     return;
96      }
97    
98    if (last_access[reg] != NULL) last = last_access[reg]+1;
99    else last = free_since[reg];
100    
101    while (last <= dst)
102      {
103     if (last_access[reg] != NULL && dirty[reg])
104       last->reg_cache_infos.needed_registers[reg] = reg_content[reg];
105     else
106       last->reg_cache_infos.needed_registers[reg] = NULL;
107     
108     if (last_access[reg] != NULL && r64[reg] != -1)
109       {
110          if (dirty[r64[reg]])
111            last->reg_cache_infos.needed_registers[r64[reg]] = reg_content[r64[reg]];
112          else
113            last->reg_cache_infos.needed_registers[r64[reg]] = NULL;
114       }
115     
116     last++;
117      }
118    if (last_access[reg] == NULL) 
119      {
120     free_since[reg] = dst+1;
121     return;
122      }
123    
124    if (dirty[reg]) 
125      {
126     mov_m32_reg32(reg_content[reg], reg);
127     if (r64[reg] == -1)
128       {
129          sar_reg32_imm8(reg, 31);
130          mov_m32_reg32((unsigned int*)reg_content[reg]+1, reg);
131       }
132     else mov_m32_reg32(reg_content[r64[reg]], r64[reg]);
133      }
134    last_access[reg] = NULL;
135    free_since[reg] = dst+1;
136    if (r64[reg] != -1)
137      {
138     last_access[r64[reg]] = NULL;
139     free_since[r64[reg]] = dst+1;
140      }
141 }
142
143 int lru_register(void)
144 {
145    unsigned int oldest_access = 0xFFFFFFFF;
146    int i, reg = 0;
147    for (i=0; i<8; i++)
148      {
149     if (i != ESP && (unsigned int)last_access[i] < oldest_access)
150       {
151          oldest_access = (int)last_access[i];
152          reg = i;
153       }
154      }
155    return reg;
156 }
157
158 int lru_register_exc1(int exc1)
159 {
160    unsigned int oldest_access = 0xFFFFFFFF;
161    int i, reg = 0;
162    for (i=0; i<8; i++)
163      {
164     if (i != ESP && i != exc1 && (unsigned int)last_access[i] < oldest_access)
165       {
166          oldest_access = (int)last_access[i];
167          reg = i;
168       }
169      }
170    return reg;
171 }
172
173 // this function finds a register to put the data contained in addr,
174 // if there was another value before it's cleanly removed of the
175 // register cache. After that, the register number is returned.
176 // If data are already cached, the function only returns the register number
177 int allocate_register(unsigned int *addr)
178 {
179    unsigned int oldest_access = 0xFFFFFFFF;
180    int reg = 0, i;
181    
182    // is it already cached ?
183    if (addr != NULL)
184      {
185     for (i=0; i<8; i++)
186       {
187          if (last_access[i] != NULL && reg_content[i] == addr)
188            {
189           precomp_instr *last = last_access[i]+1;
190           
191           while (last <= dst)
192             {
193                last->reg_cache_infos.needed_registers[i] = reg_content[i];
194                last++;
195             }
196           last_access[i] = dst;
197           if (r64[i] != -1) 
198             {
199                last = last_access[r64[i]]+1;
200                
201                while (last <= dst)
202              {
203                 last->reg_cache_infos.needed_registers[r64[i]] = reg_content[r64[i]];
204                 last++;
205              }
206                last_access[r64[i]] = dst;
207             }
208           
209           return i;
210            }
211       }
212      }
213    
214    // if it's not cached, we take the least recently used register
215    for (i=0; i<8; i++)
216      {
217     if (i != ESP && (unsigned int)last_access[i] < oldest_access)
218       {
219          oldest_access = (int)last_access[i];
220          reg = i;
221       }
222      }
223    
224    if (last_access[reg]) free_register(reg);
225    else
226      {
227     while (free_since[reg] <= dst)
228       {
229          free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
230          free_since[reg]++;
231       }
232      }
233    
234    last_access[reg] = dst;
235    reg_content[reg] = addr;
236    dirty[reg] = 0;
237    r64[reg] = -1;
238    
239    if (addr != NULL)
240      {
241     if (addr == r0 || addr == r0+1)
242       xor_reg32_reg32(reg, reg);
243     else
244       mov_reg32_m32(reg, addr);
245      }
246    
247    return reg;
248 }
249
250 // this function is similar to allocate_register except it loads
251 // a 64 bits value, and return the register number of the LSB part
252 int allocate_64_register1(unsigned int *addr)
253 {
254    int reg1, reg2, i;
255    
256    // is it already cached as a 32 bits value ?
257    for (i=0; i<8; i++)
258      {
259     if (last_access[i] != NULL && reg_content[i] == addr)
260       {
261          if (r64[i] == -1)
262            {
263           allocate_register(addr);
264           reg2 = allocate_register(dirty[i] ? NULL : addr+1);
265           r64[i] = reg2;
266           r64[reg2] = i;
267           
268           if (dirty[i])
269             {
270                reg_content[reg2] = addr+1;
271                dirty[reg2] = 1;
272                mov_reg32_reg32(reg2, i);
273                sar_reg32_imm8(reg2, 31);
274             }
275           
276           return i;
277            }
278       }
279      }
280    
281    reg1 = allocate_register(addr);
282    reg2 = allocate_register(addr+1);
283    r64[reg1] = reg2;
284    r64[reg2] = reg1;
285    
286    return reg1;
287 }
288
289 // this function is similar to allocate_register except it loads
290 // a 64 bits value, and return the register number of the MSB part
291 int allocate_64_register2(unsigned int *addr)
292 {
293    int reg1, reg2, i;
294    
295    // is it already cached as a 32 bits value ?
296    for (i=0; i<8; i++)
297      {
298     if (last_access[i] != NULL && reg_content[i] == addr)
299       {
300          if (r64[i] == -1)
301            {
302           allocate_register(addr);
303           reg2 = allocate_register(dirty[i] ? NULL : addr+1);
304           r64[i] = reg2;
305           r64[reg2] = i;
306           
307           if (dirty[i])
308             {
309                reg_content[reg2] = addr+1;
310                dirty[reg2] = 1;
311                mov_reg32_reg32(reg2, i);
312                sar_reg32_imm8(reg2, 31);
313             }
314           
315           return reg2;
316            }
317       }
318      }
319    
320    reg1 = allocate_register(addr);
321    reg2 = allocate_register(addr+1);
322    r64[reg1] = reg2;
323    r64[reg2] = reg1;
324    
325    return reg2;
326 }
327
328 // this function checks if the data located at addr are cached in a register
329 // and then, it returns 1  if it's a 64 bit value
330 //                      0  if it's a 32 bit value
331 //                      -1 if it's not cached
332 int is64(unsigned int *addr)
333 {
334    int i;
335    for (i=0; i<8; i++)
336      {
337     if (last_access[i] != NULL && reg_content[i] == addr)
338       {
339          if (r64[i] == -1) return 0;
340          return 1;
341       }
342      }
343    return -1;
344 }
345
346 int allocate_register_w(unsigned int *addr)
347 {
348    unsigned int oldest_access = 0xFFFFFFFF;
349    int reg = 0, i;
350    
351    // is it already cached ?
352    for (i=0; i<8; i++)
353      {
354     if (last_access[i] != NULL && reg_content[i] == addr)
355       {
356          precomp_instr *last = last_access[i]+1;
357          
358          while (last <= dst)
359            {
360           last->reg_cache_infos.needed_registers[i] = NULL;
361           last++;
362            }
363          last_access[i] = dst;
364          dirty[i] = 1;
365          if (r64[i] != -1)
366            {
367           last = last_access[r64[i]]+1;
368           while (last <= dst)
369             {
370                last->reg_cache_infos.needed_registers[r64[i]] = NULL;
371                last++;
372             }
373           free_since[r64[i]] = dst+1;
374           last_access[r64[i]] = NULL;
375           r64[i] = -1;
376            }
377          
378          return i;
379       }
380      }
381    
382    // if it's not cached, we take the least recently used register
383    for (i=0; i<8; i++)
384      {
385     if (i != ESP && (unsigned int)last_access[i] < oldest_access)
386       {
387          oldest_access = (int)last_access[i];
388          reg = i;
389       }
390      }
391    
392    if (last_access[reg]) free_register(reg);
393    else
394      {
395     while (free_since[reg] <= dst)
396       {
397          free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
398          free_since[reg]++;
399       }
400      }
401    
402    last_access[reg] = dst;
403    reg_content[reg] = addr;
404    dirty[reg] = 1;
405    r64[reg] = -1;
406    
407    return reg;
408 }
409
410 int allocate_64_register1_w(unsigned int *addr)
411 {
412    int reg1, reg2, i;
413    
414    // is it already cached as a 32 bits value ?
415    for (i=0; i<8; i++)
416      {
417     if (last_access[i] != NULL && reg_content[i] == addr)
418       {
419          if (r64[i] == -1)
420            {
421           allocate_register_w(addr);
422           reg2 = lru_register();
423           if (last_access[reg2]) free_register(reg2);
424           else
425           {
426             while (free_since[reg2] <= dst)
427             {
428               free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL;
429               free_since[reg2]++;
430             }
431           }
432           r64[i] = reg2;
433           r64[reg2] = i;
434           last_access[reg2] = dst;
435           
436           reg_content[reg2] = addr+1;
437           dirty[reg2] = 1;
438           mov_reg32_reg32(reg2, i);
439           sar_reg32_imm8(reg2, 31);
440           
441           return i;
442            }
443          else
444            {
445           last_access[i] = dst;
446           last_access[r64[i]] = dst;
447           dirty[i] = dirty[r64[i]] = 1;
448           return i;
449            }
450       }
451      }
452    
453    reg1 = allocate_register_w(addr);
454    reg2 = lru_register();
455    if (last_access[reg2]) free_register(reg2);
456    else
457      {
458     while (free_since[reg2] <= dst)
459       {
460          free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL;
461          free_since[reg2]++;
462       }
463      }
464    r64[reg1] = reg2;
465    r64[reg2] = reg1;
466    last_access[reg2] = dst;
467    reg_content[reg2] = addr+1;
468    dirty[reg2] = 1;
469    
470    return reg1;
471 }
472
473 int allocate_64_register2_w(unsigned int *addr)
474 {
475    int reg1, reg2, i;
476    
477    // is it already cached as a 32 bits value ?
478    for (i=0; i<8; i++)
479      {
480     if (last_access[i] != NULL && reg_content[i] == addr)
481       {
482          if (r64[i] == -1)
483            {
484           allocate_register_w(addr);
485           reg2 = lru_register();
486           if (last_access[reg2]) free_register(reg2);
487           else
488           {
489             while (free_since[reg2] <= dst)
490             {
491               free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL;
492               free_since[reg2]++;
493             }
494           }
495           r64[i] = reg2;
496           r64[reg2] = i;
497           last_access[reg2] = dst;
498           
499           reg_content[reg2] = addr+1;
500           dirty[reg2] = 1;
501           mov_reg32_reg32(reg2, i);
502           sar_reg32_imm8(reg2, 31);
503           
504           return reg2;
505            }
506          else
507            {
508           last_access[i] = dst;
509           last_access[r64[i]] = dst;
510           dirty[i] = dirty[r64[i]] = 1;
511           return r64[i];
512            }
513       }
514      }
515    
516    reg1 = allocate_register_w(addr);
517    reg2 = lru_register();
518    if (last_access[reg2]) free_register(reg2);
519    else
520      {
521     while (free_since[reg2] <= dst)
522       {
523          free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL;
524          free_since[reg2]++;
525       }
526      }
527    r64[reg1] = reg2;
528    r64[reg2] = reg1;
529    last_access[reg2] = dst;
530    reg_content[reg2] = addr+1;
531    dirty[reg2] = 1;
532    
533    return reg2;
534 }
535
536 void set_register_state(int reg, unsigned int *addr, int d)
537 {
538    last_access[reg] = dst;
539    reg_content[reg] = addr;
540    r64[reg] = -1;
541    dirty[reg] = d;
542 }
543
544 void set_64_register_state(int reg1, int reg2, unsigned int *addr, int d)
545 {
546    last_access[reg1] = dst;
547    last_access[reg2] = dst;
548    reg_content[reg1] = addr;
549    reg_content[reg2] = addr+1;
550    r64[reg1] = reg2;
551    r64[reg2] = reg1;
552    dirty[reg1] = d;
553    dirty[reg2] = d;
554 }
555
556 void force_32(int reg)
557 {
558    if (r64[reg] != -1)
559      {
560     precomp_instr *last = last_access[reg]+1;
561     
562     while (last <= dst)
563       {
564          if (dirty[reg])
565            last->reg_cache_infos.needed_registers[reg] = reg_content[reg];
566          else
567            last->reg_cache_infos.needed_registers[reg] = NULL;
568          
569          if (dirty[r64[reg]])
570            last->reg_cache_infos.needed_registers[r64[reg]] = reg_content[r64[reg]];
571          else
572            last->reg_cache_infos.needed_registers[r64[reg]] = NULL;
573          
574          last++;
575       }
576     
577     if (dirty[reg]) 
578       {
579          mov_m32_reg32(reg_content[reg], reg);
580          mov_m32_reg32(reg_content[r64[reg]], r64[reg]);
581          dirty[reg] = 0;
582       }
583     last_access[r64[reg]] = NULL;
584     free_since[r64[reg]] = dst+1;
585     r64[reg] = -1;
586      }
587 }
588
589 void allocate_register_manually(int reg, unsigned int *addr)
590 {
591    int i;
592    
593    if (last_access[reg] != NULL && reg_content[reg] == addr)
594      {
595     precomp_instr *last = last_access[reg]+1;
596          
597     while (last <= dst)
598       {
599          last->reg_cache_infos.needed_registers[reg] = reg_content[reg];
600          last++;
601       }
602     last_access[reg] = dst;
603     if (r64[reg] != -1) 
604       {
605          last = last_access[r64[reg]]+1;
606          
607          while (last <= dst)
608            {
609           last->reg_cache_infos.needed_registers[r64[reg]] = reg_content[r64[reg]];
610           last++;
611            }
612          last_access[r64[reg]] = dst;
613       }
614     return;
615      }
616    
617    if (last_access[reg]) free_register(reg);
618    else
619      {
620     while (free_since[reg] <= dst)
621       {
622          free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
623          free_since[reg]++;
624       }
625      }
626    
627    // is it already cached ?
628    for (i=0; i<8; i++)
629      {
630     if (last_access[i] != NULL && reg_content[i] == addr)
631       {
632          precomp_instr *last = last_access[i]+1;
633          
634          while (last <= dst)
635            {
636           last->reg_cache_infos.needed_registers[i] = reg_content[i];
637           last++;
638            }
639          last_access[i] = dst;
640          if (r64[i] != -1) 
641            {
642           last = last_access[r64[i]]+1;
643           
644           while (last <= dst)
645             {
646                last->reg_cache_infos.needed_registers[r64[i]] = reg_content[r64[i]];
647                last++;
648             }
649           last_access[r64[i]] = dst;
650            }
651          
652          mov_reg32_reg32(reg, i);
653          last_access[reg] = dst;
654          r64[reg] = r64[i];
655          if (r64[reg] != -1) r64[r64[reg]] = reg;
656          dirty[reg] = dirty[i];
657          reg_content[reg] = reg_content[i];
658          free_since[i] = dst+1;
659          last_access[i] = NULL;
660          
661          return;
662       }
663      }
664    
665    last_access[reg] = dst;
666    reg_content[reg] = addr;
667    dirty[reg] = 0;
668    r64[reg] = -1;
669    
670    if (addr != NULL)
671      {
672     if (addr == r0 || addr == r0+1)
673       xor_reg32_reg32(reg, reg);
674     else
675       mov_reg32_m32(reg, addr);
676      }
677 }
678
679 void allocate_register_manually_w(int reg, unsigned int *addr, int load)
680 {
681    int i;
682    
683    if (last_access[reg] != NULL && reg_content[reg] == addr)
684      {
685     precomp_instr *last = last_access[reg]+1;
686          
687     while (last <= dst)
688       {
689          last->reg_cache_infos.needed_registers[reg] = reg_content[reg];
690          last++;
691       }
692     last_access[reg] = dst;
693     
694     if (r64[reg] != -1) 
695       {
696          last = last_access[r64[reg]]+1;
697          
698          while (last <= dst)
699            {
700           last->reg_cache_infos.needed_registers[r64[reg]] = reg_content[r64[reg]];
701           last++;
702            }
703          last_access[r64[reg]] = NULL;
704          free_since[r64[reg]] = dst+1;
705          r64[reg] = -1;
706       }
707     dirty[reg] = 1;
708     return;
709      }
710    
711    if (last_access[reg]) free_register(reg);
712    else
713      {
714     while (free_since[reg] <= dst)
715       {
716          free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL;
717          free_since[reg]++;
718       }
719      }
720    
721    // is it already cached ?
722    for (i=0; i<8; i++)
723      {
724     if (last_access[i] != NULL && reg_content[i] == addr)
725       {
726          precomp_instr *last = last_access[i]+1;
727          
728          while (last <= dst)
729            {
730           last->reg_cache_infos.needed_registers[i] = reg_content[i];
731           last++;
732            }
733          last_access[i] = dst;
734          if (r64[i] != -1)
735            {
736           last = last_access[r64[i]]+1;
737           while (last <= dst)
738             {
739                last->reg_cache_infos.needed_registers[r64[i]] = NULL;
740                last++;
741             }
742           free_since[r64[i]] = dst+1;
743           last_access[r64[i]] = NULL;
744           r64[i] = -1;
745            }
746          
747          if (load)
748            mov_reg32_reg32(reg, i);
749          last_access[reg] = dst;
750          dirty[reg] = 1;
751          r64[reg] = -1;
752          reg_content[reg] = reg_content[i];
753          free_since[i] = dst+1;
754          last_access[i] = NULL;
755          
756          return;
757       }
758      }
759    
760    last_access[reg] = dst;
761    reg_content[reg] = addr;
762    dirty[reg] = 1;
763    r64[reg] = -1;
764    
765    if (addr != NULL && load)
766      {
767     if (addr == r0 || addr == r0+1)
768       xor_reg32_reg32(reg, reg);
769     else
770       mov_reg32_m32(reg, addr);
771      }
772 }
773
774 // 0x81 0xEC 0x4 0x0 0x0 0x0  sub esp, 4
775 // 0xA1            0xXXXXXXXX mov eax, XXXXXXXX (&code start)
776 // 0x05            0xXXXXXXXX add eax, XXXXXXXX (local_addr)
777 // 0x89 0x04 0x24             mov [esp], eax
778 // 0x8B (reg<<3)|5 0xXXXXXXXX mov eax, [XXXXXXXX]
779 // 0x8B (reg<<3)|5 0xXXXXXXXX mov ebx, [XXXXXXXX]
780 // 0x8B (reg<<3)|5 0xXXXXXXXX mov ecx, [XXXXXXXX]
781 // 0x8B (reg<<3)|5 0xXXXXXXXX mov edx, [XXXXXXXX]
782 // 0x8B (reg<<3)|5 0xXXXXXXXX mov ebp, [XXXXXXXX]
783 // 0x8B (reg<<3)|5 0xXXXXXXXX mov esi, [XXXXXXXX]
784 // 0x8B (reg<<3)|5 0xXXXXXXXX mov edi, [XXXXXXXX]
785 // 0xC3 ret
786 // total : 62 bytes
787 static void build_wrapper(precomp_instr *instr, unsigned char* code, precomp_block* block)
788 {
789    int i;
790    int j=0;
791
792 #if defined(PROFILE_R4300)
793    long x86addr = (long) code;
794    int mipsop = -4;
795    fwrite(&mipsop, 1, 4, pfProfile); // write 4-byte MIPS opcode
796    fwrite(&x86addr, 1, sizeof(char *), pfProfile); // write pointer to dynamically generated x86 code for this MIPS instruction
797 #endif
798    
799    code[j++] = 0x81;
800    code[j++] = 0xEC;
801    code[j++] = 0x04;
802    code[j++] = 0x00;
803    code[j++] = 0x00;
804    code[j++] = 0x00;
805    
806    code[j++] = 0xA1;
807    *((unsigned int*)&code[j]) = (unsigned int)(&block->code);
808    j+=4;
809    
810    code[j++] = 0x05;
811    *((unsigned int*)&code[j]) = (unsigned int)instr->local_addr;
812    j+=4;
813    
814    code[j++] = 0x89;
815    code[j++] = 0x04;
816    code[j++] = 0x24;
817    
818    for (i=0; i<8; i++)
819      {
820     if (instr->reg_cache_infos.needed_registers[i] != NULL)
821       {
822          code[j++] = 0x8B;
823          code[j++] = (i << 3) | 5;
824          *((unsigned int*)&code[j]) =
825                  (unsigned int)instr->reg_cache_infos.needed_registers[i];
826          j+=4;
827       }
828      }
829    
830    code[j++] = 0xC3;
831 }
832
833 void build_wrappers(precomp_instr *instr, int start, int end, precomp_block* block)
834 {
835    int i, reg;;
836    for (i=start; i<end; i++)
837      {
838     instr[i].reg_cache_infos.need_map = 0;
839     for (reg=0; reg<8; reg++)
840       {
841          if (instr[i].reg_cache_infos.needed_registers[reg] != NULL)
842            {
843           instr[i].reg_cache_infos.need_map = 1;
844           build_wrapper(&instr[i], instr[i].reg_cache_infos.jump_wrapper, block);
845           break;
846            }
847       }
848      }
849 }
850
851 void simplify_access(void)
852 {
853    int i;
854    dst->local_addr = code_length;
855    for(i=0; i<8; i++) dst->reg_cache_infos.needed_registers[i] = NULL;
856 }
857