Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / x86 / assemble.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   Mupen64plus - assemble.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 <stdlib.h>
23 #include <stdio.h>
24
25 #include "assemble.h"
26
27 #include "api/m64p_types.h"
28 #include "api/callbacks.h"
29 #include "osal/preproc.h"
30 #include "r4300/recomph.h"
31 #include "r4300/recomp.h"
32 #include "r4300/r4300.h"
33
34 typedef struct _jump_table
35 {
36    unsigned int mi_addr;
37    unsigned int pc_addr;
38 } jump_table;
39
40 static jump_table *jumps_table = NULL;
41 static int jumps_number, max_jumps_number;
42
43 void init_assembler(void *block_jumps_table, int block_jumps_number, void *block_riprel_table, int block_riprel_number)
44 {
45    if (block_jumps_table)
46    {
47      jumps_table = (jump_table *) block_jumps_table;
48      jumps_number = block_jumps_number;
49      max_jumps_number = jumps_number;
50    }
51    else
52    {
53      jumps_table = (jump_table *) malloc(1000*sizeof(jump_table));
54      jumps_number = 0;
55      max_jumps_number = 1000;
56    }
57 }
58
59 void free_assembler(void **block_jumps_table, int *block_jumps_number, void **block_riprel_table, int *block_riprel_number)
60 {
61    *block_jumps_table = jumps_table;
62    *block_jumps_number = jumps_number;
63    *block_riprel_table = NULL;  /* RIP-relative addressing is only for x86-64 */
64    *block_riprel_number = 0;
65 }
66
67 void add_jump(unsigned int pc_addr, unsigned int mi_addr)
68 {
69    if (jumps_number == max_jumps_number)
70    {
71      max_jumps_number += 1000;
72      jumps_table = (jump_table *) realloc(jumps_table, max_jumps_number*sizeof(jump_table));
73    }
74    jumps_table[jumps_number].pc_addr = pc_addr;
75    jumps_table[jumps_number].mi_addr = mi_addr;
76    jumps_number++;
77 }
78
79 void passe2(precomp_instr *dest, int start, int end, precomp_block *block)
80 {
81    unsigned int real_code_length, addr_dest;
82    int i;
83    build_wrappers(dest, start, end, block);
84    real_code_length = code_length;
85    
86    for (i=0; i < jumps_number; i++)
87    {
88      code_length = jumps_table[i].pc_addr;
89      if (dest[(jumps_table[i].mi_addr - dest[0].addr)/4].reg_cache_infos.need_map)
90      {
91        addr_dest = (unsigned int)dest[(jumps_table[i].mi_addr - dest[0].addr)/4].reg_cache_infos.jump_wrapper;
92        put32(addr_dest-((unsigned int)block->code+code_length)-4);
93      }
94      else
95      {
96        addr_dest = dest[(jumps_table[i].mi_addr - dest[0].addr)/4].local_addr;
97        put32(addr_dest-code_length-4);
98      }
99    }
100    code_length = real_code_length;
101 }
102
103 static unsigned int g_jump_start8 = 0;
104 static unsigned int g_jump_start32 = 0;
105
106 void jump_start_rel8(void)
107 {
108   g_jump_start8 = code_length;
109 }
110
111 void jump_start_rel32(void)
112 {
113   g_jump_start32 = code_length;
114 }
115
116 void jump_end_rel8(void)
117 {
118   unsigned int jump_end = code_length;
119   int jump_vec = jump_end - g_jump_start8;
120
121   if (jump_vec > 127 || jump_vec < -128)
122   {
123     DebugMessage(M64MSG_ERROR, "8-bit relative jump too long! From %x to %x", g_jump_start8, jump_end);
124     OSAL_BREAKPOINT_INTERRUPT;
125   }
126
127   code_length = g_jump_start8 - 1;
128   put8(jump_vec);
129   code_length = jump_end;
130 }
131
132 void jump_end_rel32(void)
133 {
134   unsigned int jump_end = code_length;
135   int jump_vec = jump_end - g_jump_start32;
136
137   code_length = g_jump_start32 - 4;
138   put32(jump_vec);
139   code_length = jump_end;
140 }