451ab91e |
1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus - gcop1.c * |
3 | * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * |
4 | * Copyright (C) 2007 Richard Goedeken (Richard42) * |
5 | * Copyright (C) 2002 Hacktarux * |
6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * |
9 | * the Free Software Foundation; either version 2 of the License, or * |
10 | * (at your option) any later version. * |
11 | * * |
12 | * This program is distributed in the hope that it will be useful, * |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
15 | * GNU General Public License for more details. * |
16 | * * |
17 | * You should have received a copy of the GNU General Public License * |
18 | * along with this program; if not, write to the * |
19 | * Free Software Foundation, Inc., * |
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
21 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
22 | |
23 | #include <stdio.h> |
24 | |
25 | #include "assemble.h" |
26 | #include "interpret.h" |
27 | |
28 | #include "r4300/recomph.h" |
29 | #include "r4300/recomp.h" |
30 | #include "r4300/r4300.h" |
31 | #include "r4300/ops.h" |
32 | #include "r4300/macros.h" |
33 | |
34 | #include "memory/memory.h" |
35 | |
36 | void genmfc1(void) |
37 | { |
38 | #if defined(COUNT_INSTR) |
39 | inc_m32rel(&instr_count[111]); |
40 | #endif |
41 | #ifdef INTERPRET_MFC1 |
42 | gencallinterp((unsigned long long)cached_interpreter_table.MFC1, 0); |
43 | #else |
44 | gencheck_cop1_unusable(); |
45 | mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.r.nrd])); |
46 | mov_reg32_preg64(EBX, RAX); |
47 | mov_m32rel_xreg32((unsigned int*)dst->f.r.rt, EBX); |
48 | sar_reg32_imm8(EBX, 31); |
49 | mov_m32rel_xreg32(((unsigned int*)dst->f.r.rt)+1, EBX); |
50 | #endif |
51 | } |
52 | |
53 | void gendmfc1(void) |
54 | { |
55 | #if defined(COUNT_INSTR) |
56 | inc_m32rel(&instr_count[112]); |
57 | #endif |
58 | #ifdef INTERPRET_DMFC1 |
59 | gencallinterp((unsigned long long)cached_interpreter_table.DMFC1, 0); |
60 | #else |
61 | gencheck_cop1_unusable(); |
62 | mov_xreg64_m64rel(RAX, (unsigned long long *) (®_cop1_double[dst->f.r.nrd])); |
63 | mov_reg32_preg64(EBX, RAX); |
64 | mov_reg32_preg64pimm32(ECX, RAX, 4); |
65 | mov_m32rel_xreg32((unsigned int*)dst->f.r.rt, EBX); |
66 | mov_m32rel_xreg32(((unsigned int*)dst->f.r.rt)+1, ECX); |
67 | #endif |
68 | } |
69 | |
70 | void gencfc1(void) |
71 | { |
72 | #if defined(COUNT_INSTR) |
73 | inc_m32rel(&instr_count[113]); |
74 | #endif |
75 | #ifdef INTERPRET_CFC1 |
76 | gencallinterp((unsigned long long)cached_interpreter_table.CFC1, 0); |
77 | #else |
78 | gencheck_cop1_unusable(); |
79 | if(dst->f.r.nrd == 31) mov_xreg32_m32rel(EAX, (unsigned int*)&FCR31); |
80 | else mov_xreg32_m32rel(EAX, (unsigned int*)&FCR0); |
81 | mov_m32rel_xreg32((unsigned int*)dst->f.r.rt, EAX); |
82 | sar_reg32_imm8(EAX, 31); |
83 | mov_m32rel_xreg32(((unsigned int*)dst->f.r.rt)+1, EAX); |
84 | #endif |
85 | } |
86 | |
87 | void genmtc1(void) |
88 | { |
89 | #if defined(COUNT_INSTR) |
90 | inc_m32rel(&instr_count[114]); |
91 | #endif |
92 | #ifdef INTERPRET_MTC1 |
93 | gencallinterp((unsigned long long)cached_interpreter_table.MTC1, 0); |
94 | #else |
95 | gencheck_cop1_unusable(); |
96 | mov_xreg32_m32rel(EAX, (unsigned int*)dst->f.r.rt); |
97 | mov_xreg64_m64rel(RBX, (unsigned long long *)(®_cop1_simple[dst->f.r.nrd])); |
98 | mov_preg64_reg32(RBX, EAX); |
99 | #endif |
100 | } |
101 | |
102 | void gendmtc1(void) |
103 | { |
104 | #if defined(COUNT_INSTR) |
105 | inc_m32rel(&instr_count[115]); |
106 | #endif |
107 | #ifdef INTERPRET_DMTC1 |
108 | gencallinterp((unsigned long long)cached_interpreter_table.DMTC1, 0); |
109 | #else |
110 | gencheck_cop1_unusable(); |
111 | mov_xreg32_m32rel(EAX, (unsigned int*)dst->f.r.rt); |
112 | mov_xreg32_m32rel(EBX, ((unsigned int*)dst->f.r.rt)+1); |
113 | mov_xreg64_m64rel(RDX, (unsigned long long *)(®_cop1_double[dst->f.r.nrd])); |
114 | mov_preg64_reg32(RDX, EAX); |
115 | mov_preg64pimm32_reg32(RDX, 4, EBX); |
116 | #endif |
117 | } |
118 | |
119 | void genctc1(void) |
120 | { |
121 | #if defined(COUNT_INSTR) |
122 | inc_m32rel(&instr_count[116]); |
123 | #endif |
124 | #ifdef INTERPRET_CTC1 |
125 | gencallinterp((unsigned long long)cached_interpreter_table.CTC1, 0); |
126 | #else |
127 | gencheck_cop1_unusable(); |
128 | |
129 | if (dst->f.r.nrd != 31) return; |
130 | mov_xreg32_m32rel(EAX, (unsigned int*)dst->f.r.rt); |
131 | mov_m32rel_xreg32((unsigned int*)&FCR31, EAX); |
132 | and_eax_imm32(3); |
133 | |
134 | cmp_eax_imm32(0); |
135 | jne_rj(13); |
136 | mov_m32rel_imm32((unsigned int*)&rounding_mode, 0x33F); // 11 |
137 | jmp_imm_short(51); // 2 |
138 | |
139 | cmp_eax_imm32(1); // 5 |
140 | jne_rj(13); // 2 |
141 | mov_m32rel_imm32((unsigned int*)&rounding_mode, 0xF3F); // 11 |
142 | jmp_imm_short(31); // 2 |
143 | |
144 | cmp_eax_imm32(2); // 5 |
145 | jne_rj(13); // 2 |
146 | mov_m32rel_imm32((unsigned int*)&rounding_mode, 0xB3F); // 11 |
147 | jmp_imm_short(11); // 2 |
148 | |
149 | mov_m32rel_imm32((unsigned int*)&rounding_mode, 0x73F); // 11 |
150 | |
151 | fldcw_m16rel((unsigned short*)&rounding_mode); |
152 | #endif |
153 | } |
154 | |