Commit | Line | Data |
---|---|---|
3971886a AC |
1 | // Texas Instruments TMS320C80 (MVP) Simulator. |
2 | // Copyright (C) 1997 Free Software Foundation, Inc. | |
3 | // Contributed by Cygnus Support. | |
4 | // | |
5 | // This file is part of GDB, the GNU debugger. | |
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, or (at your option) | |
10 | // 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 along | |
18 | // with this program; if not, write to the Free Software Foundation, Inc., | |
19 | // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | ||
381f42ef | 22 | // The following is called when ever an illegal instruction is encountered. |
89d09738 | 23 | :internal::::illegal: |
f03b093c | 24 | sim_io_eprintf (SD, "0x%lx: illegal instruction\n", (unsigned long) cia.ip); |
aaa11abe | 25 | sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIM_SIGILL); |
f03b093c | 26 | |
381f42ef | 27 | // The following is called when ever an FP op is attempted with FPU disabled. |
89d09738 | 28 | :internal::::fp_unavailable: |
f03b093c | 29 | sim_io_eprintf (SD, "0x%lx: floating-point unavailable\n", (unsigned long) cia.ip); |
aaa11abe | 30 | sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIM_SIGFPE); |
84902350 AC |
31 | |
32 | // Handle a branch instruction | |
89d09738 | 33 | :function:::instruction_address:do_branch:int annul, address_word target, int rLink_p, unsigned32 *rLink |
84902350 AC |
34 | instruction_address nia; |
35 | if (annul) | |
36 | { | |
37 | if (rLink_p) | |
38 | *rLink = cia.dp; | |
39 | nia.ip = target; | |
40 | nia.dp = target + 4; | |
41 | } | |
42 | else | |
43 | { | |
44 | if (rLink_p) | |
45 | *rLink = cia.dp + sizeof (instruction_word); | |
46 | nia.ip = cia.dp; | |
47 | nia.dp = target; | |
48 | } | |
49 | return nia; | |
15c16493 AC |
50 | |
51 | // Signed Integer Add - add source1, source2, dest | |
89d09738 | 52 | :function:::void:do_add:unsigned32 *rDest, signed32 source1, signed32 source2 |
37a684b8 AC |
53 | unsigned32 result; |
54 | ALU_BEGIN (source1); | |
55 | ALU_ADD (source2); | |
56 | ALU_END (result); | |
57 | *rDest = result; | |
58 | TRACE_ALU3 (MY_INDEX, result, source1, source2); | |
480e740c AC |
59 | /* FIXME - a signed add may cause an exception */ |
60 | 31.Dest,26.Source2,21.0b101100,15.0,14.SignedImmediate::::add i | |
128b5154 | 61 | "add <SignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 62 | do_add (_SD, rDest, vSource1, vSource2); |
15c16493 | 63 | 31.Dest,26.Source2,21.0b11101100,13.0,12.0,11./,4.Source1::::add r |
128b5154 | 64 | "add r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 65 | do_add (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
66 | 31.Dest,26.Source2,21.0b11101100,13.0,12.1,11./+LongSignedImmediate::::add l |
67 | "add 0x%08lx<LongSignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 68 | do_add (_SD, rDest, LongSignedImmediate, vSource2); |
15c16493 AC |
69 | |
70 | ||
71 | // Unsigned Integer Add - addu source1, source2, dest | |
89d09738 | 72 | :function:::void:do_addu:unsigned32 *rDest, unsigned32 source1, unsigned32 source2 |
37a684b8 AC |
73 | unsigned32 result = source1 + source2; |
74 | TRACE_ALU3 (MY_INDEX, result, source1, source2); | |
7b167b09 MM |
75 | *rDest = result; |
76 | ||
480e740c | 77 | 31.Dest,26.Source2,21.0b101100,15.1,14.SignedImmediate::::addu i |
128b5154 | 78 | "addu <SignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 79 | do_addu (_SD, rDest, vSource1, vSource2); |
15c16493 | 80 | 31.Dest,26.Source2,21.0b11101100,13.1,12.0,11./,4.Source1::::addu r |
128b5154 | 81 | "addu r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 82 | do_addu (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
83 | 31.Dest,26.Source2,21.0b11101100,13.1,12.1,11./+LongSignedImmediate::::addu l |
84 | "addu 0x%08lx<LongSignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 85 | do_addu (_SD, rDest, LongSignedImmediate, vSource2); |
15c16493 AC |
86 | |
87 | ||
89d09738 | 88 | :function:::void:do_and:signed32 *rDest, signed32 source1, signed32 source2 |
37a684b8 AC |
89 | unsigned32 result = source1 & source2; |
90 | TRACE_ALU3 (MY_INDEX, result, source1, source2); | |
7b167b09 | 91 | *rDest = result; |
15c16493 AC |
92 | |
93 | ||
94 | // and, and.tt | |
20b2f9bc | 95 | 31.Dest,26.Source2,21.0b0010001,14.UnsignedImmediate::::and.tt i |
128b5154 | 96 | "and.tt <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 97 | do_and (_SD, rDest, vSource1, vSource2); |
480e740c | 98 | 31.Dest,26.Source2,21.0b110010001,12.0,11./,4.Source1::::and.tt r |
128b5154 | 99 | "and.tt r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 100 | do_and (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
101 | 31.Dest,26.Source2,21.0b110010001,12.1,11./+LongSignedImmediate::::and.tt l |
102 | "and.tt 0x%08lx<LongSignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 103 | do_and (_SD, rDest, LongSignedImmediate, vSource2); |
15c16493 AC |
104 | |
105 | ||
106 | // and.ff | |
20b2f9bc | 107 | 31.Dest,26.Source2,21.0b0011000,14.UnsignedImmediate::::and.ff i |
128b5154 | 108 | "and.ff <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 109 | do_and (_SD, rDest, ~vSource1, ~vSource2); |
480e740c | 110 | 31.Dest,26.Source2,21.0b110011000,12.0,11./,4.Source1::::and.ff r |
128b5154 | 111 | "and.ff r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 112 | do_and (_SD, rDest, ~vSource1, ~vSource2); |
128b5154 AC |
113 | 31.Dest,26.Source2,21.0b110011000,12.1,11./+LongSignedImmediate::::and.ff l |
114 | "and.ff 0x%08lx<LongSignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 115 | do_and (_SD, rDest, ~LongSignedImmediate, ~vSource2); |
15c16493 AC |
116 | |
117 | ||
118 | // and.ft | |
20b2f9bc | 119 | 31.Dest,26.Source2,21.0b0010100,14.UnsignedImmediate::::and.ft i |
128b5154 | 120 | "and.ft <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 121 | do_and (_SD, rDest, ~vSource1, vSource2); |
480e740c | 122 | 31.Dest,26.Source2,21.0b110010100,12.0,11./,4.Source1::::and.ft r |
128b5154 | 123 | "and.ft r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 124 | do_and (_SD, rDest, ~vSource1, vSource2); |
128b5154 AC |
125 | 31.Dest,26.Source2,21.0b110010100,12.1,11./+LongSignedImmediate::::and.ft l |
126 | "and.ft 0x%08lx<LongSignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 127 | do_and (_SD, rDest, ~LongSignedImmediate, vSource2); |
15c16493 AC |
128 | |
129 | ||
130 | // and.tf | |
20b2f9bc | 131 | 31.Dest,26.Source2,21.0b0010010,14.UnsignedImmediate::::and.tf i |
128b5154 | 132 | "and.tf <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 133 | do_and (_SD, rDest, vSource1, ~vSource2); |
480e740c | 134 | 31.Dest,26.Source2,21.0b110010010,12.0,11./,4.Source1::::and.tf r |
128b5154 | 135 | "and.tf r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 136 | do_and (_SD, rDest, vSource1, ~vSource2); |
128b5154 AC |
137 | 31.Dest,26.Source2,21.0b110010010,12.1,11./+LongSignedImmediate::::and.tf l |
138 | "and.tf 0x%08lx<LongSignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 139 | do_and (_SD, rDest, LongSignedImmediate, ~vSource2); |
15c16493 AC |
140 | |
141 | ||
128b5154 | 142 | // bbo[.a] |
89d09738 | 143 | :function:::instruction_address:do_bbo:instruction_address nia, int bitnum, unsigned32 source, int annul, unsigned32 offset |
7b167b09 | 144 | int jump_p; |
84902350 | 145 | address_word target = cia.ip + 4 * offset; |
c3cad878 | 146 | if (MASKED32 (source, bitnum, bitnum)) |
480e740c | 147 | { |
84902350 | 148 | nia = do_branch (_SD, annul, target, 0, NULL); |
7b167b09 | 149 | jump_p = 1; |
480e740c | 150 | } |
7b167b09 MM |
151 | else |
152 | jump_p = 0; | |
99022131 | 153 | TRACE_COND_BR(MY_INDEX, jump_p, bitnum, target, -1, -1); |
480e740c | 154 | return nia; |
89d09738 | 155 | :%s::::A:int A |
128b5154 AC |
156 | if (A) |
157 | return ".a"; | |
158 | else | |
159 | return ""; | |
480e740c | 160 | 31.BITNUM,26.Source,21.0b100101,15.A,14.SignedOffset::::bbo i |
128b5154 AC |
161 | "bbo%s<A> <SignedOffset>, r<Source>, <bitnum>" |
162 | nia = do_bbo (_SD, nia, bitnum, vSource, A, vSignedOffset); | |
480e740c | 163 | 31.BITNUM,26.Source,21.0b11100101,13.A,12.0,11./,4.IndOff::::bbo r |
128b5154 AC |
164 | "bbo%s<A> r<IndOff>, r<Source>, <bitnum>" |
165 | nia = do_bbo (_SD, nia, bitnum, vSource, A, rIndOff); | |
166 | 31.BITNUM,26.Source,21.0b11100101,13.A,12.1,11./+LongSignedImmediate::::bbo l | |
167 | "bbo%s<A> <LongSignedImmediate>, r<Source>, <bitnum>" | |
168 | nia = do_bbo (_SD, nia, bitnum, vSource, A, LongSignedImmediate); | |
15c16493 AC |
169 | |
170 | ||
171 | // bbz[.a] | |
89d09738 | 172 | :function:::instruction_address:do_bbz:instruction_address nia, int bitnum, unsigned32 source, int annul, unsigned32 offset |
7b167b09 | 173 | int jump_p; |
84902350 | 174 | address_word target = cia.ip + 4 * offset; |
c3cad878 | 175 | if (!MASKED32 (source, bitnum, bitnum)) |
15c16493 | 176 | { |
84902350 | 177 | nia = do_branch (_SD, annul, target, 0, NULL); |
7b167b09 | 178 | jump_p = 1; |
15c16493 | 179 | } |
7b167b09 MM |
180 | else |
181 | jump_p = 0; | |
99022131 | 182 | TRACE_COND_BR(MY_INDEX, jump_p, bitnum, target, -1, -1); |
15c16493 | 183 | return nia; |
480e740c | 184 | 31.BITNUM,26.Source,21.0b100100,15.A,14.SignedOffset::::bbz i |
128b5154 AC |
185 | "bbz%s<A> <SignedOffset>, r<Source>, <bitnum>" |
186 | nia = do_bbz (_SD, nia, bitnum, vSource, A, vSignedOffset); | |
15c16493 | 187 | 31.BITNUM,26.Source,21.0b11100100,13.A,12.0,11./,4.IndOff::::bbz r |
128b5154 AC |
188 | "bbz%s<A> r<IndOff>, r<Source>, <bitnum>" |
189 | nia = do_bbz (_SD, nia, bitnum, vSource, A, rIndOff); | |
190 | 31.BITNUM,26.Source,21.0b11100100,13.A,12.1,11./+LongSignedImmediate::::bbz l | |
191 | "bbz%s<A> <LongSignedImmediate>, r<Source>, <bitnum>" | |
192 | nia = do_bbz (_SD, nia, bitnum, vSource, A, LongSignedImmediate); | |
15c16493 AC |
193 | |
194 | ||
195 | // bcnd[.a] | |
89d09738 | 196 | :function:::instruction_address:do_bcnd:instruction_address nia, int Cond, unsigned32 source, int annul, unsigned32 offset |
480e740c AC |
197 | int condition; |
198 | int size = EXTRACTED32 (Cond, 31 - 27, 30 - 27); | |
199 | int code = EXTRACTED32 (Cond, 29 - 27, 27 - 27); | |
200 | signed32 val = 0; | |
84902350 | 201 | address_word target = cia.ip + 4 * offset; |
480e740c AC |
202 | switch (size) |
203 | { | |
204 | case 0: val = SEXT32 (source, 7); break; | |
205 | case 1: val = SEXT32 (source, 15); break; | |
206 | case 2: val = source; break; | |
f03b093c | 207 | default: sim_engine_abort (SD, CPU, cia, "bcnd - reserved size"); |
480e740c AC |
208 | } |
209 | switch (code) | |
210 | { | |
211 | case 0: condition = 0; break; | |
212 | case 1: condition = val > 0; break; | |
213 | case 2: condition = val == 0; break; | |
214 | case 3: condition = val >= 0; break; | |
215 | case 4: condition = val < 0; break; | |
216 | case 5: condition = val != 0; break; | |
217 | case 6: condition = val <= 0; break; | |
218 | default: condition = 1; break; | |
219 | } | |
220 | if (condition) | |
221 | { | |
84902350 | 222 | nia = do_branch (_SD, annul, target, 0, NULL); |
480e740c | 223 | } |
99022131 | 224 | TRACE_COND_BR(MY_INDEX, condition, val, target, size, code); |
480e740c AC |
225 | return nia; |
226 | 31.Code,26.Source,21.0b100110,15.A,14.SignedOffset::::bcnd i | |
128b5154 | 227 | "bcnd%s<A> <SignedOffset>, r<Source>, <Code>" |
37a684b8 | 228 | nia = do_bcnd (_SD, nia, Code, vSource, A, vSignedOffset); |
480e740c | 229 | 31.Code,26.Source,21.0b11100110,13.A,12.0,11./,4.IndOff::::bcnd r |
128b5154 | 230 | "bcnd%s<A> r<IndOff>, r<Source>, <Code>" |
37a684b8 | 231 | nia = do_bcnd (_SD, nia, Code, vSource, A, rIndOff); |
128b5154 AC |
232 | 31.Code,26.Source,21.0b11100110,13.A,12.1,11./+LongSignedImmediate::::bcnd l |
233 | "bcnd%s<A> <LongSignedImmediate>, r<Source>, <Code>" | |
37a684b8 | 234 | nia = do_bcnd (_SD, nia, Code, vSource, A, LongSignedImmediate); |
15c16493 AC |
235 | |
236 | ||
237 | // br[.a] - see bbz[.a] | |
238 | ||
239 | ||
240 | // brcr | |
89d09738 | 241 | :function:::sim_cia:do_brcr:instruction_address nia, int cr |
381f42ef AC |
242 | if (cr >= 0x4000 || !(CPU)->is_user_mode) |
243 | { | |
244 | unsigned32 control = CR (cr); | |
245 | unsigned32 ie = control & 0x00000001; | |
246 | unsigned32 pc = control & 0xfffffffc; | |
247 | unsigned32 is_user_mode = control & 0x00000002; | |
248 | (CPU)->is_user_mode = is_user_mode; | |
249 | nia.dp = pc; | |
250 | if (ie) | |
251 | (CPU)->cr[IE_CR] |= IE_CR_IE; | |
252 | else | |
253 | (CPU)->cr[IE_CR] &= ~IE_CR_IE; | |
254 | } | |
255 | TRACE_UCOND_BR (MY_INDEX, nia.dp); | |
256 | return nia; | |
257 | 31.//,27.0,26.//,21.0b0000110,14.UCRN::::brcr i | |
128b5154 | 258 | "brcr CR[<UCRN>]" |
381f42ef AC |
259 | nia = do_brcr (_SD, nia, UCRN); |
260 | 31.//,27.0,26.//,21.0b110000110,12.0,11./,4.INDCR::::brcr r | |
128b5154 | 261 | "brcr CR[r<INDCR>]" |
381f42ef | 262 | nia = do_brcr (_SD, nia, UCRN); |
128b5154 AC |
263 | 31.//,27.0,26.//,21.0b110000110,12.1,11./+UnsignedControlRegisterNumber::::brcr l |
264 | "brcr CR[<UnsignedControlRegisterNumber>]" | |
381f42ef | 265 | nia = do_brcr (_SD, nia, UnsignedControlRegisterNumber); |
15c16493 AC |
266 | |
267 | ||
268 | // bsr[.a] | |
89d09738 | 269 | :function:::instruction_address:do_bsr:instruction_address nia, signed32 *rLink, int annul, unsigned32 offset |
84902350 AC |
270 | address_word target = cia.ip + 4 * offset; |
271 | nia = do_branch (_SD, annul, target, 1, rLink); | |
272 | TRACE_UCOND_BR (MY_INDEX, target); | |
480e740c AC |
273 | return nia; |
274 | 31.Link,26./,21.0b100000,15.A,14.SignedOffset::::bsr i | |
128b5154 | 275 | "bsr%s<A> <SignedOffset>, r<Link>" |
381f42ef | 276 | nia = do_bsr (_SD, nia, rLink, A, vSignedOffset); |
480e740c | 277 | 31.Link,26./,21.0b11100000,13.A,12.0,11./,4.IndOff::::bsr r |
128b5154 | 278 | "bsr%s<A> r<IndOff>, r<Link>" |
381f42ef | 279 | nia = do_bsr (_SD, nia, rLink, A, rIndOff); |
128b5154 AC |
280 | 31.Link,26./,21.0b11100000,13.A,12.1,11./+LongSignedImmediate::::bsr l |
281 | "bsr%s<A> <LongSignedImmediate>, r<Link>" | |
381f42ef | 282 | nia = do_bsr (_SD, nia, rLink, A, LongSignedImmediate); |
15c16493 AC |
283 | |
284 | ||
285 | // cmnd | |
89d09738 | 286 | :function:::void:do_cmnd:signed32 source |
3971886a AC |
287 | int Reset = EXTRACTED32 (source, 31, 31); |
288 | int Halt = EXTRACTED32 (source, 30, 30); | |
289 | int Unhalt = EXTRACTED32 (source, 29, 29); | |
290 | /* int ICR = EXTRACTED32 (source, 28, 28); */ | |
291 | /* int DCR = EXTRACTED32 (source, 27, 27); */ | |
292 | int Task = EXTRACTED32 (source, 14, 14); | |
293 | int Msg = EXTRACTED32 (source, 13, 13); | |
294 | int VC = EXTRACTED32 (source, 10, 10); | |
295 | int TC = EXTRACTED32 (source, 9, 9); | |
296 | int MP = EXTRACTED32 (source, 8, 8); | |
297 | int PP = EXTRACTED32 (source, 3, 0); | |
298 | /* what is implemented? */ | |
299 | if (PP != 0) | |
f03b093c AC |
300 | sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - PPs not supported", |
301 | (unsigned long) cia.ip); | |
3971886a | 302 | if (VC != 0) |
f03b093c AC |
303 | sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - VC not supported", |
304 | (unsigned long) cia.ip); | |
3971886a | 305 | if (TC != 0) |
f03b093c AC |
306 | sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - TC not supported", |
307 | (unsigned long) cia.ip); | |
3971886a AC |
308 | if (MP) |
309 | { | |
310 | if (Reset || Halt) | |
f03b093c | 311 | sim_engine_halt (SD, CPU, NULL, cia, sim_exited, 0); |
3971886a | 312 | if (Unhalt) |
f03b093c AC |
313 | sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Can not unhalt the MP", |
314 | (unsigned long) cia.ip); | |
3971886a AC |
315 | /* if (ICR || DCR); */ |
316 | if (Task) | |
f03b093c AC |
317 | sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Can not Task the MP", |
318 | (unsigned long) cia.ip); | |
3971886a | 319 | if (Msg) |
f03b093c AC |
320 | sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Msg to MP not suported", |
321 | (unsigned long) cia.ip); | |
3971886a | 322 | } |
381f42ef | 323 | TRACE_SINK1 (MY_INDEX, source); |
abe293a0 | 324 | 31./,21.0b0000010,14.UI::::cmnd i |
128b5154 | 325 | "cmnd <UI>" |
381f42ef | 326 | do_cmnd (_SD, UI); |
3971886a | 327 | 31./,21.0b110000010,12.0,11./,4.Source::::cmnd r |
128b5154 | 328 | "cmnd r<Source>" |
37a684b8 | 329 | do_cmnd (_SD, vSource); |
128b5154 AC |
330 | 31./,21.0b110000010,12.1,11./+LongUnsignedImmediate::::cmnd l |
331 | "cmnd <LongUnsignedImmediate>" | |
381f42ef | 332 | do_cmnd (_SD, LongUnsignedImmediate); |
15c16493 AC |
333 | |
334 | // cmp | |
89d09738 | 335 | :function:::unsigned32:cmp_vals:signed32 s1, unsigned32 u1, signed32 s2, unsigned32 u2 |
480e740c | 336 | unsigned32 field = 0; |
aaa7b252 MM |
337 | if (s1 == s2) field |= 0x001; |
338 | if (s1 != s2) field |= 0x002; | |
339 | if (s1 > s2) field |= 0x004; | |
340 | if (s1 <= s2) field |= 0x008; | |
341 | if (s1 < s2) field |= 0x010; | |
342 | if (s1 >= s2) field |= 0x020; | |
343 | if (u1 > u2) field |= 0x040; | |
344 | if (u1 <= u2) field |= 0x080; | |
345 | if (u1 < u2) field |= 0x100; | |
346 | if (u1 >= u2) field |= 0x200; | |
480e740c | 347 | return field; |
89d09738 | 348 | :function:::void:do_cmp:unsigned32 *rDest, unsigned32 source1, unsigned32 source2 |
480e740c | 349 | unsigned32 field = 0; |
37a684b8 AC |
350 | field |= cmp_vals (_SD, source1, source1, source2, source2) << 20; |
351 | field |= cmp_vals (_SD, (signed16)source1, (unsigned16)source1, | |
352 | (signed16)source2, (unsigned16)source2) << 10; | |
353 | field |= cmp_vals (_SD, (signed8)source1, (unsigned8)source1, | |
354 | (signed8)source2, (unsigned8)source2); | |
241b4624 | 355 | TRACE_CMP (MY_INDEX, field, source1, source2); |
480e740c AC |
356 | *rDest = field; |
357 | 31.Dest,26.Source2,21.0b1010000,14.SignedImmediate::::cmp i | |
128b5154 | 358 | "cmp <SignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 359 | do_cmp (_SD, rDest, vSource1, vSource2); |
480e740c | 360 | 31.Dest,26.Source2,21.0b111010000,12.0,11./,4.Source1::::cmp r |
128b5154 | 361 | "cmp r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 362 | do_cmp (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
363 | 31.Dest,26.Source2,21.0b111010000,12.1,11./+LongSignedImmediate::::cmp l |
364 | "cmp 0x%08lx<LongSignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 365 | do_cmp (_SD, rDest, LongSignedImmediate, vSource2); |
15c16493 AC |
366 | |
367 | ||
368 | // dcache | |
89d09738 | 369 | :%s::::F:int F |
128b5154 AC |
370 | if (F) |
371 | return "f"; | |
372 | else | |
373 | return "c"; | |
374 | 31./,27.F,26.Source2,21.0b0111,17.m,16.0b00,14.SignedOffset::::dcache i | |
375 | "dcache%s<F> <SignedOffset> (r<Source2>%s<m>)" | |
7b167b09 | 376 | TRACE_NOP (MY_INDEX); |
480e740c | 377 | /* NOP */ |
128b5154 AC |
378 | 31./,27.F,26.Source2,21.0b110111,15.m,14.0b00,12.0,11./,4.Source1::::dcache r |
379 | "dcache%s<F> r<Source1> (r<Source2>%s<m>)" | |
7b167b09 | 380 | TRACE_NOP (MY_INDEX); |
480e740c | 381 | /* NOP */ |
128b5154 AC |
382 | 31./,27.F,26.Source2,21.0b110111,15.m,14.0b00,12.1,11./+LongSignedImmediate::::dcache l |
383 | "dcache%s<F> <LongSignedImmediate> (r<Source2>%s<m>)" | |
7b167b09 | 384 | TRACE_NOP (MY_INDEX); |
480e740c | 385 | /* NOP */ |
15c16493 AC |
386 | |
387 | ||
388 | // dld[{.b|.h|.d}] | |
37a684b8 AC |
389 | void::function::do_dld:int Dest, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset |
390 | do_ld (_SD, Dest, base, rBase, m, sz, S, offset); | |
abe293a0 | 391 | 31.Dest,26.Base,21.0b110100,15.m,14.sz,12.0,11.S,10.1,9./,4.IndOff::::dld r |
128b5154 | 392 | "dld%s<sz> r<IndOff>%s<S> (r<Base>%s<m>), r<Dest>" |
37a684b8 | 393 | do_dld (_SD, Dest, vBase, rBase, m, sz, S, rIndOff); |
128b5154 AC |
394 | 31.Dest,26.Base,21.0b110100,15.m,14.sz,12.1,11.S,10.1,9./+LongSignedImmediateOffset::::dld l |
395 | "dld%s<sz> 0x%08lx<LongSignedImmediateOffset>%s<S> (r<Base>%s<m>), r<Dest>" | |
37a684b8 | 396 | do_dld (_SD, Dest, vBase, rBase, m, sz, S, LongSignedImmediateOffset); |
15c16493 AC |
397 | |
398 | ||
399 | // dld.u[{.b|.h|.d}] | |
37a684b8 AC |
400 | void::function::do_dld_u:unsigned32 *rDest, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset |
401 | do_ld_u (_SD, rDest, base, rBase, m, sz, S, offset); | |
abe293a0 | 402 | 31.Dest,26.Base,21.0b110101,15.m,14.sz,12.0,11.S,10.1,9./,4.IndOff::::dld.u r |
128b5154 | 403 | "dld.u%s<sz> r<IndOff>%s<S> (r<Base>%s<m>), r<Dest>" |
37a684b8 | 404 | do_dld_u (_SD, rDest, vBase, rBase, m, sz, S, rIndOff); |
128b5154 AC |
405 | 31.Dest,26.Base,21.0b110101,15.m,14.sz,12.1,11.S,10.1,9./+LongSignedImmediateOffset::::dld.u l |
406 | "dld.u%s<sz> 0x%08lx<LongSignedImmediateOffset>%s<S> (r<Base>%s<m>), r<Dest>" | |
37a684b8 | 407 | do_dld_u (_SD, rDest, vBase, rBase, m, sz, S, LongSignedImmediateOffset); |
15c16493 AC |
408 | |
409 | ||
410 | // dst[{.b|.h|.d}] | |
37a684b8 AC |
411 | void::function::do_dst:int Source, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset |
412 | do_st (_SD, Source, base, rBase, m, sz, S, offset); | |
d5e2c74e | 413 | 31.Source,26.Base,21.0b110110,15.m,14.sz,12.0,11.S,10.1,9./,4.IndOff::::dst r |
128b5154 | 414 | "dst%s<sz> r<IndOff>%s<S> (r<Base>%s<m>), r<Source>" |
37a684b8 | 415 | do_dst (_SD, Source, vBase, rBase, m, sz, S, rIndOff); |
128b5154 AC |
416 | 31.Source,26.Base,21.0b110110,15.m,14.sz,12.1,11.S,10.1,9./+LongSignedImmediateOffset::::dst l |
417 | "dst%s<sz> 0x%08lx<LongSignedImmediateOffset>%s<S> (r<Base>%s<m>), r<Source>" | |
37a684b8 | 418 | do_dst (_SD, Source, vBase, rBase, m, sz, S, LongSignedImmediateOffset); |
15c16493 AC |
419 | |
420 | ||
421 | // estop | |
abe293a0 | 422 | 31./,21.0b1111111,14.1,13.0,12.0,11./::::estop |
15c16493 | 423 | |
15c16493 | 424 | // etrap |
abe293a0 AC |
425 | 31./,27.1,26./,21.0b0000001,14.UTN::::etrap i |
426 | 31./,27.1,26./,21.0b110000001,12.0,11./,4.iUTN::::etrap r | |
427 | 31./,27.1,26./,21.0b110000001,12.1,11./::::etrap l | |
15c16493 AC |
428 | |
429 | ||
430 | // exts - see shift.ds | |
431 | ||
432 | ||
433 | // extu - see shift.dz | |
434 | ||
435 | ||
3971886a | 436 | sim_fpu::function::get_fp_reg:int reg, unsigned32 val, int precision |
b3c77578 | 437 | sim_fpu ans; |
3971886a AC |
438 | switch (precision) |
439 | { | |
440 | case 0: /* single */ | |
b3c77578 AC |
441 | sim_fpu_32to (&ans, val); |
442 | break; | |
3971886a AC |
443 | case 1: /* double */ |
444 | if (reg < 0) | |
f03b093c | 445 | sim_engine_abort (SD, CPU, cia, "DP immediate invalid"); |
3971886a | 446 | if (reg & 1) |
f03b093c | 447 | sim_engine_abort (SD, CPU, cia, "DP FP register must be even"); |
3971886a | 448 | if (reg <= 1) |
f03b093c | 449 | sim_engine_abort (SD, CPU, cia, "DP FP register must be >= 2"); |
77cfb0a1 | 450 | sim_fpu_232to (&ans, GPR (reg + 1), GPR (reg)); |
b3c77578 | 451 | break; |
3971886a | 452 | case 2: /* 32 bit signed integer */ |
b3c77578 AC |
453 | sim_fpu_i32to (&ans, val, 0); |
454 | break; | |
3971886a | 455 | case 3: /* 32 bit unsigned integer */ |
b3c77578 AC |
456 | sim_fpu_u32to (&ans, val, 0); |
457 | break; | |
3971886a | 458 | default: |
f03b093c | 459 | sim_engine_abort (SD, CPU, cia, "Unsupported FP precision"); |
3971886a | 460 | } |
b3c77578 | 461 | return ans; |
3971886a AC |
462 | void::function::set_fp_reg:int Dest, sim_fpu val, int PD |
463 | switch (PD) | |
464 | { | |
465 | case 0: /* single */ | |
466 | { | |
b3c77578 | 467 | sim_fpu_to32 (&GPR (Dest), &val); |
3971886a AC |
468 | break; |
469 | } | |
470 | case 1: /* double */ | |
471 | { | |
3971886a | 472 | if (Dest & 1) |
f03b093c | 473 | sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be even"); |
3971886a | 474 | if (Dest <= 1) |
f03b093c | 475 | sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be >= 2"); |
77cfb0a1 | 476 | sim_fpu_to232 (&GPR (Dest + 1), &GPR (Dest + 0), &val); |
3971886a AC |
477 | break; |
478 | } | |
479 | case 2: /* signed */ | |
07b4c0a6 | 480 | { |
b3c77578 | 481 | sim_fpu_to32i (&GPR (Dest), &val, 0); |
07b4c0a6 AC |
482 | break; |
483 | } | |
3971886a | 484 | case 3: /* unsigned */ |
07b4c0a6 | 485 | { |
b3c77578 | 486 | sim_fpu_to32u (&GPR (Dest), &val, 0); |
07b4c0a6 AC |
487 | break; |
488 | } | |
3971886a | 489 | default: |
f03b093c | 490 | sim_engine_abort (SD, CPU, cia, "Unsupported FP precision"); |
3971886a AC |
491 | } |
492 | ||
15c16493 | 493 | // fadd.{s|d}{s|d}{s|d} |
3971886a | 494 | void::function::do_fadd:int Dest, int PD, sim_fpu s1, sim_fpu s2 |
b3c77578 AC |
495 | sim_fpu ans; |
496 | sim_fpu_add (&ans, &s1, &s2); | |
128b5154 | 497 | TRACE_FPU3 (ans, s1, s2); |
3971886a | 498 | set_fp_reg (_SD, Dest, ans, PD); |
128b5154 AC |
499 | const char *::function::str_PX:int PX |
500 | switch (PX) | |
501 | { | |
502 | case 0: return "s"; | |
503 | case 1: return "d"; | |
504 | case 2: return "i"; | |
505 | case 3: return "u"; | |
506 | default: return "?"; | |
507 | } | |
381f42ef | 508 | 31.Dest,26.Source2,21.0b111110000,12.0,11.r,10.PD,8.P2,6.P1,4.Source1::f::fadd r |
128b5154 | 509 | "fadd.%s<PX#P1>%s<PX#P2>%s<PX#PD> r<Source1>, r<Source2>, r<Dest>" |
3971886a | 510 | do_fadd (_SD, Dest, PD, |
37a684b8 AC |
511 | get_fp_reg (_SD, Source1, vSource1, P1), |
512 | get_fp_reg (_SD, Source2, vSource2, P2)); | |
128b5154 AC |
513 | 31.Dest,26.Source2,21.0b111110000,12.1,11.r,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fadd l |
514 | "fadd.%s<PX#P1>%s<PX#P2>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Source2>, r<Dest>" | |
3971886a AC |
515 | do_fadd (_SD, Dest, PD, |
516 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), | |
37a684b8 | 517 | get_fp_reg (_SD, Source2, vSource2, P2)); |
15c16493 AC |
518 | |
519 | ||
520 | // fcmp.{s|d}{s|d}{s|d} | |
37a684b8 | 521 | void::function::do_fcmp:unsigned32 *rDest, sim_fpu s1, sim_fpu s2 |
aa3a0447 | 522 | unsigned32 result = 0; |
b3c77578 | 523 | if (sim_fpu_is_nan (&s1) || sim_fpu_is_nan (&s2)) |
aa3a0447 | 524 | result |= BIT32 (30); |
3971886a AC |
525 | else |
526 | { | |
aa3a0447 | 527 | result |= BIT32 (31); |
b3c77578 AC |
528 | if (sim_fpu_is_eq (&s1, &s2)) result |= BIT32(20); |
529 | if (sim_fpu_is_ne (&s1, &s2)) result |= BIT32(21); | |
530 | if (sim_fpu_is_gt (&s1, &s2)) result |= BIT32(22); | |
531 | if (sim_fpu_is_le (&s1, &s2)) result |= BIT32(23); | |
532 | if (sim_fpu_is_lt (&s1, &s2)) result |= BIT32(24); | |
533 | if (sim_fpu_is_ge (&s1, &s2)) result |= BIT32(25); | |
534 | if (sim_fpu_is_lt (&s1, &sim_fpu_zero) | |
535 | || sim_fpu_is_gt (&s1, &s2)) result |= BIT32(26); | |
536 | if (sim_fpu_is_lt (&sim_fpu_zero, &s1) | |
537 | && sim_fpu_is_lt (&s1, &s2)) result |= BIT32(27); | |
538 | if (sim_fpu_is_le (&sim_fpu_zero, &s1) | |
539 | && sim_fpu_is_le (&s1, &s2)) result |= BIT32(28); | |
540 | if (sim_fpu_is_le (&s1, &sim_fpu_zero) | |
541 | || sim_fpu_is_ge (&s1, &s2)) result |= BIT32(29); | |
3971886a | 542 | } |
37a684b8 | 543 | *rDest = result; |
241b4624 | 544 | TRACE_FPU2CMP (result, s1, s2); |
381f42ef | 545 | 31.Dest,26.Source2,21.0b111110101,12.0,11./,10.0,8.P2,6.P1,4.Source1::f::fcmp r |
128b5154 | 546 | "fcmp.%s<PX#P1>%s<PX#P2> r<Source1>, r<Source2>, r<Dest>" |
37a684b8 AC |
547 | do_fcmp (_SD, rDest, |
548 | get_fp_reg (_SD, Source1, vSource1, P1), | |
549 | get_fp_reg (_SD, Source2, vSource2, P2)); | |
128b5154 AC |
550 | 31.Dest,26.Source2,21.0b111110101,12.1,11./,10.0,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fcmp l |
551 | "fcmp.%s<PX#P1>%s<PX#P2> 0x%08lx<SinglePrecisionFloatingPoint>, r<Source2>, r<Dest>" | |
37a684b8 | 552 | do_fcmp (_SD, rDest, |
3971886a | 553 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), |
37a684b8 | 554 | get_fp_reg (_SD, Source2, vSource2, P2)); |
3971886a | 555 | |
15c16493 AC |
556 | |
557 | ||
558 | // fdiv.{s|d}{s|d}{s|d} | |
3971886a | 559 | void::function::do_fdiv:int Dest, int PD, sim_fpu s1, sim_fpu s2 |
b3c77578 AC |
560 | sim_fpu ans; |
561 | sim_fpu_div (&ans, &s1, &s2); | |
128b5154 | 562 | TRACE_FPU3 (ans, s1, s2); |
3971886a | 563 | set_fp_reg (_SD, Dest, ans, PD); |
381f42ef | 564 | 31.Dest,26.Source2,21.0b111110011,12.0,11./,10.PD,8.P2,6.P1,4.Source1::f::fdiv r |
128b5154 | 565 | "fdiv.%s<PX#P1>%s<PX#P2>%s<PX#PD> r<Source1>, r<Source2>, r<Dest>" |
3971886a | 566 | do_fdiv (_SD, Dest, PD, |
37a684b8 AC |
567 | get_fp_reg (_SD, Source1, vSource1, P1), |
568 | get_fp_reg (_SD, Source2, vSource2, P2)); | |
128b5154 AC |
569 | 31.Dest,26.Source2,21.0b111110011,12.1,11./,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fdiv l |
570 | "fdiv.%s<PX#P1>%s<PX#P2>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Source2>, r<Dest>" | |
3971886a AC |
571 | do_fdiv (_SD, Dest, PD, |
572 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), | |
37a684b8 | 573 | get_fp_reg (_SD, Source2, vSource2, P2)); |
15c16493 AC |
574 | |
575 | ||
576 | // fmpy.{s|d|i|u}{s|d|i|u}{s|d|i|u} | |
3971886a | 577 | void::function::do_fmpy:int Dest, int PD, sim_fpu s1, sim_fpu s2 |
07b4c0a6 AC |
578 | switch (PD) |
579 | { | |
580 | case 2: /* signed */ | |
581 | { | |
b3c77578 AC |
582 | signed64 i1; |
583 | signed64 i2; | |
584 | sim_fpu_to64i (&i1, &s1, 0); | |
585 | sim_fpu_to64i (&i2, &s2, 0); | |
586 | GPR (Dest) = i1 * i2; | |
128b5154 | 587 | TRACE_FPU2I (GPR (Dest), s1, s2); |
07b4c0a6 AC |
588 | break; |
589 | } | |
590 | case 3: /* unsigned */ | |
591 | { | |
b3c77578 AC |
592 | unsigned64 u1; |
593 | unsigned64 u2; | |
594 | sim_fpu_to64u (&u1, &s1, 0); | |
595 | sim_fpu_to64u (&u2, &s2, 0); | |
596 | GPR (Dest) = u1 * u2; | |
128b5154 | 597 | TRACE_FPU2I (GPR (Dest), s1, s2); |
07b4c0a6 AC |
598 | break; |
599 | } | |
600 | default: | |
601 | { | |
b3c77578 AC |
602 | sim_fpu ans; |
603 | sim_fpu_mul (&ans, &s1, &s2); | |
07b4c0a6 | 604 | set_fp_reg (_SD, Dest, ans, PD); |
128b5154 | 605 | TRACE_FPU3 (ans, s1, s2); |
07b4c0a6 AC |
606 | } |
607 | } | |
381f42ef | 608 | 31.Dest,26.Source2,21.0b111110010,12.0,11./,10.PD,8.P2,6.P1,4.Source1::f::fmpy r |
128b5154 | 609 | "fmpy.%s<PX#P1>%s<PX#P2>%s<PX#PD> r<Source1>, r<Source2>, r<Dest>" |
3971886a | 610 | do_fmpy (_SD, Dest, PD, |
37a684b8 AC |
611 | get_fp_reg (_SD, Source1, vSource1, P1), |
612 | get_fp_reg (_SD, Source2, vSource2, P2)); | |
128b5154 AC |
613 | 31.Dest,26.Source2,21.0b111110010,12.1,11./,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fmpy l |
614 | "fmpy.%s<PX#P1>%s<PX#P2>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Source2>, r<Dest>" | |
3971886a AC |
615 | do_fmpy (_SD, Dest, PD, |
616 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), | |
37a684b8 | 617 | get_fp_reg (_SD, Source2, vSource2, P2)); |
15c16493 AC |
618 | |
619 | ||
128b5154 | 620 | // frndm.{s|d|i|u}{s|d|i|u} |
3971886a AC |
621 | void::function::do_frnd:int Dest, int PD, sim_fpu s1 |
622 | set_fp_reg (_SD, Dest, s1, PD); | |
128b5154 AC |
623 | TRACE_FPU1 (s1); |
624 | 31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b11,6.P1,4.Source::f::frndm r | |
625 | "frndm.%s<PX#P1>%s<PX#PD> r<Source>, r<Dest>" | |
3971886a | 626 | do_frnd (_SD, Dest, PD, |
37a684b8 | 627 | get_fp_reg (_SD, Source, vSource, P1)); |
128b5154 AC |
628 | 31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b11,6.P1,4./+SinglePrecisionFloatingPoint::f::frndm l |
629 | "frndm.%s<PX#P1>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Dest>" | |
3971886a AC |
630 | do_frnd (_SD, Dest, PD, |
631 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); | |
15c16493 AC |
632 | |
633 | ||
128b5154 AC |
634 | // frndn.{s|d|i|u}{s|d|i|u} |
635 | 31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b00,6.P1,4.Source::f::frndn r | |
636 | "frndn.%s<PX#P1>%s<PX#PD> r<Source>, r<Dest>" | |
3971886a | 637 | do_frnd (_SD, Dest, PD, |
37a684b8 | 638 | get_fp_reg (_SD, Source, vSource, P1)); |
128b5154 AC |
639 | 31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b00,6.P1,4./+SinglePrecisionFloatingPoint::f::frndn l |
640 | "frndn.%s<PX#P1>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Dest>" | |
3971886a AC |
641 | do_frnd (_SD, Dest, PD, |
642 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); | |
15c16493 AC |
643 | |
644 | ||
128b5154 AC |
645 | // frndp.{s|d|i|u}{s|d|i|u} |
646 | 31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b10,6.P1,4.Source::f::frndp r | |
647 | "frndp.%s<PX#P1>%s<PX#PD> r<Source>, r<Dest>" | |
3971886a | 648 | do_frnd (_SD, Dest, PD, |
37a684b8 | 649 | get_fp_reg (_SD, Source, vSource, P1)); |
128b5154 AC |
650 | 31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b10,6.P1,4./+SinglePrecisionFloatingPoint::f::frndp l |
651 | "frndp.%s<PX#P1>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Dest>" | |
3971886a AC |
652 | do_frnd (_SD, Dest, PD, |
653 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); | |
15c16493 AC |
654 | |
655 | ||
128b5154 AC |
656 | // frndz.{s|d|i|u}{s|d|i|u} |
657 | 31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b01,6.P1,4.Source::f::frndz r | |
658 | "frndz.%s<PX#P1>%s<PX#PD> r<Source>, r<Dest>" | |
3971886a | 659 | do_frnd (_SD, Dest, PD, |
37a684b8 | 660 | get_fp_reg (_SD, Source, vSource, P1)); |
128b5154 AC |
661 | 31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b01,6.P1,4./+SinglePrecisionFloatingPoint::f::frndz l |
662 | "frndz.%s<PX#P1>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Dest>" | |
3971886a AC |
663 | do_frnd (_SD, Dest, PD, |
664 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); | |
15c16493 AC |
665 | |
666 | ||
667 | // fsqrt.{s|d}{s|d}{s|d} | |
128b5154 | 668 | #void::function::do_fsqrt:unsigned32 *rDest, unsigned32 Source, unsigned32 Source2 |
15c16493 | 669 | # sim_io_error ("fsqrt"); |
128b5154 AC |
670 | 31.Dest,26./,21.0b111110111,12.0,11./,10.PD,8.//,6.P1,4.Source::f::fsqrt r |
671 | "fsqrt.%s<PX#P1>%s<PX#PD> r<Source>, r<Dest>" | |
672 | # do_fsqrt (_SD, rDest, vSource); | |
673 | 31.Dest,26./,21.0b111110111,12.1,11./,10.PD,8.//,6.P1,4./+SinglePrecisionFloatingPoint::f::fsqrt l | |
674 | "fsqrt.%s<PX#P1>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Dest>" | |
675 | # do_fsqrt (_SD, rDest, SinglePrecisionFloatingPoint); | |
15c16493 AC |
676 | |
677 | ||
678 | // fsub.{s|d}{s|d}{s|d} | |
3971886a | 679 | void::function::do_fsub:int Dest, int PD, sim_fpu s1, sim_fpu s2 |
b3c77578 AC |
680 | sim_fpu ans; |
681 | sim_fpu_sub (&ans, &s1, &s2); | |
128b5154 | 682 | TRACE_FPU3 (ans, s1, s2); |
3971886a | 683 | set_fp_reg (_SD, Dest, ans, PD); |
381f42ef | 684 | 31.Dest,26.Source2,21.0b111110001,12.0,11.r,10.PD,8.P2,6.P1,4.Source1::f::fsub r |
128b5154 | 685 | "fsub.%s<PX#P1>%s<PX#P2>%s<PX#PD> r<Source1>, r<Source2>, r<Dest>" |
3971886a | 686 | do_fsub (_SD, Dest, PD, |
37a684b8 AC |
687 | get_fp_reg (_SD, Source1, vSource1, P1), |
688 | get_fp_reg (_SD, Source2, vSource2, P2)); | |
128b5154 AC |
689 | 31.Dest,26.Source2,21.0b111110001,12.1,11.r,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fsub l |
690 | "fsub.%s<PX#P1>%s<PX#P2>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Source2>, r<Dest>" | |
3971886a AC |
691 | do_fsub (_SD, Dest, PD, |
692 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), | |
37a684b8 | 693 | get_fp_reg (_SD, Source2, vSource2, P2)); |
15c16493 AC |
694 | |
695 | ||
696 | // illop | |
abe293a0 | 697 | 31./,21.0b0000000,14./::::illop |
128b5154 | 698 | "illop" |
abe293a0 | 699 | 31./,21.0b111111111,12./::::illop l |
128b5154 | 700 | "illop" |
15c16493 AC |
701 | |
702 | ||
abe293a0 | 703 | // ins - see sl.im |
15c16493 AC |
704 | |
705 | ||
706 | // jsr[.a] | |
381f42ef | 707 | instruction_address::function::do_jsr:instruction_address nia, signed32 *rLink, int annul, unsigned32 offset, unsigned32 base |
84902350 AC |
708 | address_word target = offset + base; |
709 | TRACE_UCOND_BR (MY_INDEX, target); | |
710 | nia = do_branch (_SD, annul, target, 1, rLink); | |
d5e2c74e | 711 | if (nia.dp & 0x3) |
f03b093c AC |
712 | sim_engine_abort (SD, CPU, cia, |
713 | "0x%lx: destination address 0x%lx misaligned", | |
714 | (unsigned long) cia.ip, | |
715 | (unsigned long) nia.dp); | |
480e740c AC |
716 | return nia; |
717 | 31.Link,26.Base,21.0b100010,15.A,14.SignedOffset::::jsr i | |
128b5154 | 718 | "jsr%s<A> <SignedOffset>, r<Link>" |
37a684b8 | 719 | nia = do_jsr (_SD, nia, rLink, A, vSignedOffset, vBase); |
128b5154 AC |
720 | 31.Link,26.Base,21.0b11100010,13.A,12.0,11./,4.IndOff::::jsr r |
721 | "jsr%s<A> r<IndOff>, r<Link>" | |
722 | nia = do_jsr (_SD, nia, rLink, A, rIndOff, vBase); | |
723 | 31.Link,26.Base,21.0b11100010,13.A,12.1,11./+LongSignedImmediate::::jsr l | |
724 | "jsr%s<A> <LongSignedImmediate>, r<Link>" | |
37a684b8 | 725 | nia = do_jsr (_SD, nia, rLink, A, LongSignedImmediate, vBase); |
15c16493 AC |
726 | |
727 | ||
728 | // ld[{.b.h.d}] | |
37a684b8 | 729 | void::function::do_ld:int Dest, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset |
abe293a0 AC |
730 | unsigned32 addr; |
731 | switch (sz) | |
732 | { | |
733 | case 0: | |
37a684b8 | 734 | addr = base + (S ? (offset << 0) : offset); |
d5e2c74e AC |
735 | if (m) |
736 | *rBase = addr; | |
737 | GPR(Dest) = MEM (signed, addr, 1); | |
abe293a0 AC |
738 | break; |
739 | case 1: | |
37a684b8 | 740 | addr = base + (S ? (offset << 1) : offset); |
d5e2c74e AC |
741 | if (m) |
742 | *rBase = addr; | |
743 | GPR(Dest) = MEM (signed, addr, 2); | |
abe293a0 AC |
744 | break; |
745 | case 2: | |
37a684b8 | 746 | addr = base + (S ? (offset << 2) : offset); |
d5e2c74e AC |
747 | if (m) |
748 | *rBase = addr; | |
749 | GPR(Dest) = MEM (signed, addr, 4); | |
abe293a0 AC |
750 | break; |
751 | case 3: | |
c445af5a AC |
752 | { |
753 | signed64 val; | |
754 | if (Dest & 0x1) | |
f03b093c AC |
755 | sim_engine_abort (SD, CPU, cia, "0x%lx: ld.d to odd register %d", |
756 | cia.ip, Dest); | |
37a684b8 | 757 | addr = base + (S ? (offset << 3) : offset); |
c445af5a AC |
758 | if (m) |
759 | *rBase = addr; | |
760 | val = MEM (signed, addr, 8); | |
761 | GPR(Dest + 1) = VH4_8 (val); | |
762 | GPR(Dest + 0) = VL4_8 (val); | |
763 | } | |
abe293a0 AC |
764 | break; |
765 | default: | |
766 | addr = -1; | |
f03b093c | 767 | sim_engine_abort (SD, CPU, cia, "ld - invalid sz %d", sz); |
abe293a0 | 768 | } |
128b5154 AC |
769 | TRACE_LD (GPR(Dest), m, S, base, offset); |
770 | const char *::function::str_sz:int sz | |
771 | switch (sz) | |
772 | { | |
773 | case 0: return ".b"; | |
774 | case 1: return ".h"; | |
775 | case 2: return ""; | |
776 | case 3: return ".d"; | |
777 | default: return "?"; | |
778 | } | |
779 | const char *::function::str_m:int m | |
780 | if (m) | |
781 | return ":m"; | |
782 | else | |
783 | return ""; | |
784 | const char *::function::str_S:int S | |
785 | if (S) | |
786 | return ":s"; | |
787 | else | |
788 | return ""; | |
abe293a0 | 789 | 31.Dest,26.Base,21.0b0100,17.m,16.sz,14.SignedOffset::::ld i |
128b5154 | 790 | "ld%s<sz> <SignedOffset> (r<Base>%s<m>), r<Dest>" |
37a684b8 | 791 | do_ld (_SD, Dest, vBase, rBase, m, sz, 0, vSignedOffset); |
abe293a0 | 792 | 31.Dest,26.Base,21.0b110100,15.m,14.sz,12.0,11.S,10.0,9./,4.IndOff::::ld r |
128b5154 | 793 | "ld%s<sz> r<IndOff>%s<S> (r<Base>%s<m>), r<Dest>" |
37a684b8 | 794 | do_ld (_SD, Dest, vBase, rBase, m, sz, S, rIndOff); |
128b5154 AC |
795 | 31.Dest,26.Base,21.0b110100,15.m,14.sz,12.1,11.S,10.0,9./+LongSignedImmediateOffset::::ld l |
796 | "ld%s<sz> 0x%08lx<LongSignedImmediateOffset>%s<S> (r<Base>%s<m>), r<Dest>" | |
37a684b8 | 797 | do_ld (_SD, Dest, vBase, rBase, m, sz, S, LongSignedImmediateOffset); |
15c16493 AC |
798 | |
799 | ||
800 | // ld.u[{.b.h.d}] | |
37a684b8 | 801 | void::function::do_ld_u:unsigned32 *rDest, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset |
abe293a0 AC |
802 | unsigned32 addr; |
803 | switch (sz) | |
804 | { | |
805 | case 0: | |
37a684b8 | 806 | addr = base + (S ? (offset << 0) : offset); |
abe293a0 AC |
807 | *rDest = MEM (unsigned, addr, 1); |
808 | break; | |
809 | case 1: | |
37a684b8 | 810 | addr = base + (S ? (offset << 1) : offset); |
abe293a0 AC |
811 | *rDest = MEM (unsigned, addr, 2); |
812 | break; | |
813 | default: | |
814 | addr = -1; | |
f03b093c | 815 | sim_engine_abort (SD, CPU, cia, "ld.u - invalid sz %d", sz); |
abe293a0 AC |
816 | } |
817 | if (m) | |
818 | *rBase = addr; | |
128b5154 | 819 | TRACE_LD (m, S, *rDest, base, offset); |
abe293a0 | 820 | 31.Dest,26.Base,21.0b0101,17.m,16.sz,14.SignedOffset::::ld.u i |
128b5154 | 821 | "ld.u%s<sz> <SignedOffset> (r<Base>%s<m>), r<Dest>" |
37a684b8 | 822 | do_ld_u (_SD, rDest, vBase, rBase, m, sz, 0, vSignedOffset); |
abe293a0 | 823 | 31.Dest,26.Base,21.0b110101,15.m,14.sz,12.0,11.S,10.0,9./,4.IndOff::::ld.u r |
128b5154 | 824 | "ld.u%s<sz> r<IndOff>%s<S> (r<Base>%s<m>), r<Dest>" |
37a684b8 | 825 | do_ld_u (_SD, rDest, vBase, rBase, m, sz, S, rIndOff); |
128b5154 AC |
826 | 31.Dest,26.Base,21.0b110101,15.m,14.sz,12.1,11.S,10.0,9./+LongSignedImmediateOffset::::ld.u l |
827 | "ld.u%s<sz> 0x%08lx<LongSignedImmediateOffset>%s<S> (r<Base>%s<m>), r<Dest>" | |
37a684b8 | 828 | do_ld_u (_SD, rDest, vBase, rBase, m, sz, S, LongSignedImmediateOffset); |
15c16493 AC |
829 | |
830 | ||
831 | // lmo | |
450be234 | 832 | 31.Dest,26.Source,21.0b111111000,12.0,11./::::lmo |
128b5154 | 833 | "lmo r<Source>, r<Dest>" |
381f42ef AC |
834 | int b; |
835 | for (b = 0; b < 32; b++) | |
37a684b8 | 836 | if (vSource & BIT32 (31 - b)) |
381f42ef | 837 | break; |
37a684b8 | 838 | TRACE_ALU2 (MY_INDEX, b, vSource); |
381f42ef AC |
839 | *rDest = b; |
840 | ||
15c16493 | 841 | |
abe293a0 | 842 | // nop - see rdcr 0, r0 |
15c16493 AC |
843 | |
844 | ||
381f42ef | 845 | void::function::do_or:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2 |
7b167b09 | 846 | unsigned32 result = Source1 | Source2; |
381f42ef | 847 | TRACE_ALU3 (MY_INDEX, result, Source1, Source2); |
7b167b09 | 848 | *rDest = result; |
15c16493 AC |
849 | |
850 | ||
851 | // or, or.tt | |
480e740c | 852 | 31.Dest,26.Source2,21.0b0010111,14.UnsignedImmediate::::or.tt i |
128b5154 | 853 | "or.tt <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 854 | do_or (_SD, rDest, vSource1, vSource2); |
480e740c | 855 | 31.Dest,26.Source2,21.0b110010111,12.0,11./,4.Source1::::or.tt r |
128b5154 | 856 | "or.tt r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 857 | do_or (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
858 | 31.Dest,26.Source2,21.0b110010111,12.1,11./+LongUnsignedImmediate::::or.tt l |
859 | "or.tt 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 860 | do_or (_SD, rDest, LongUnsignedImmediate, vSource2); |
15c16493 AC |
861 | |
862 | ||
863 | // or.ff | |
480e740c | 864 | 31.Dest,26.Source2,21.0b0011110,14.UnsignedImmediate::::or.ff i |
128b5154 | 865 | "or.ff <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 866 | do_or (_SD, rDest, ~vSource1, ~vSource2); |
480e740c | 867 | 31.Dest,26.Source2,21.0b110011110,12.0,11./,4.Source1::::or.ff r |
128b5154 | 868 | "or.ff r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 869 | do_or (_SD, rDest, ~vSource1, ~vSource2); |
128b5154 AC |
870 | 31.Dest,26.Source2,21.0b110011110,12.1,11./+LongUnsignedImmediate::::or.ff l |
871 | "or.ff 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 872 | do_or (_SD, rDest, ~LongUnsignedImmediate, ~vSource2); |
15c16493 AC |
873 | |
874 | ||
875 | // or.ft | |
480e740c | 876 | 31.Dest,26.Source2,21.0b0011101,14.UnsignedImmediate::::or.ft i |
128b5154 | 877 | "or.ft <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 878 | do_or (_SD, rDest, ~vSource1, vSource2); |
480e740c | 879 | 31.Dest,26.Source2,21.0b110011101,12.0,11./,4.Source1::::or.ft r |
128b5154 | 880 | "or.ft r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 881 | do_or (_SD, rDest, ~vSource1, vSource2); |
128b5154 AC |
882 | 31.Dest,26.Source2,21.0b110011101,12.1,11./+LongUnsignedImmediate::::or.ft l |
883 | "or.ft 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 884 | do_or (_SD, rDest, ~LongUnsignedImmediate, vSource2); |
15c16493 AC |
885 | |
886 | ||
887 | // or.tf | |
480e740c | 888 | 31.Dest,26.Source2,21.0b0011011,14.UnsignedImmediate::::or.tf i |
128b5154 | 889 | "or.tf <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 890 | do_or (_SD, rDest, vSource1, ~vSource2); |
480e740c | 891 | 31.Dest,26.Source2,21.0b110011011,12.0,11./,4.Source1::::or.tf r |
128b5154 | 892 | "or.tf r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 893 | do_or (_SD, rDest, vSource1, ~vSource2); |
128b5154 AC |
894 | 31.Dest,26.Source2,21.0b110011011,12.1,11./+LongUnsignedImmediate::::or.tf l |
895 | "or.tf 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 896 | do_or (_SD, rDest, LongUnsignedImmediate, ~vSource2); |
15c16493 AC |
897 | |
898 | ||
899 | // rdcr | |
381f42ef AC |
900 | void::function::do_rdcr:unsigned32 Dest, int cr |
901 | TRACE_SINK2 (MY_INDEX, Dest, cr); | |
902 | GPR (Dest) = CR (cr); | |
abe293a0 | 903 | 31.Dest,26.0,21.0b0000100,14.UCRN::::rdcr i |
128b5154 | 904 | "rdcr CR[<UCRN>], r<Dest>" |
381f42ef | 905 | do_rdcr (_SD, Dest, UCRN); |
abe293a0 | 906 | 31.Dest,26.0,21.0b110000100,12.0,11./,4.INDCR::::rdcr r |
128b5154 | 907 | "rdcr CR[r<INDCR>], r<Dest>" |
381f42ef | 908 | do_rdcr (_SD, Dest, UCRN); |
128b5154 AC |
909 | 31.Dest,26.0,21.0b110000100,12.1,11./+UnsignedControlRegisterNumber::::rdcr l |
910 | "rdcr CR[<UnsignedControlRegisterNumber>], r<Dest>" | |
381f42ef | 911 | do_rdcr (_SD, Dest, UnsignedControlRegisterNumber); |
15c16493 AC |
912 | |
913 | ||
914 | // rmo | |
abe293a0 | 915 | 31.Dest,26.Source,21.0b111111001,12.0,11./::::rmo |
128b5154 | 916 | "rmo r<Source>, r<Dest>" |
381f42ef AC |
917 | int b; |
918 | for (b = 0; b < 32; b++) | |
37a684b8 | 919 | if (vSource & BIT32 (b)) |
381f42ef AC |
920 | break; |
921 | if (b < 32) | |
922 | b = 31 - b; | |
37a684b8 | 923 | TRACE_ALU2 (MY_INDEX, b, vSource); |
381f42ef | 924 | *rDest = b; |
15c16493 AC |
925 | |
926 | ||
abe293a0 | 927 | // rotl - see sl.dz |
15c16493 AC |
928 | |
929 | ||
381f42ef | 930 | // rotr - see sl.dz |
15c16493 AC |
931 | |
932 | ||
abe293a0 | 933 | // shl - see sl.iz |
15c16493 AC |
934 | |
935 | ||
936 | // sl.{d|e|i}{m|s|z} | |
37a684b8 | 937 | void::function::do_shift:int Dest, unsigned32 source, int Merge, int i, int n, int EndMask, int Rotate |
c1c77d40 | 938 | /* see 10-30 for a reasonable description */ |
37a684b8 | 939 | unsigned32 input = source; |
c1c77d40 AC |
940 | unsigned32 rotated; |
941 | unsigned32 endmask; | |
942 | unsigned32 shiftmask; | |
943 | unsigned32 cm; | |
944 | int nRotate; | |
945 | /* rotate the source */ | |
946 | if (n) | |
947 | { | |
37a684b8 | 948 | rotated = ROTR32 (source, Rotate); |
c1c77d40 AC |
949 | nRotate = (- Rotate) & 31; |
950 | } | |
951 | else | |
952 | { | |
37a684b8 | 953 | rotated = ROTL32 (source, Rotate); |
c1c77d40 AC |
954 | nRotate = Rotate; |
955 | } | |
956 | /* form the end mask */ | |
957 | if (EndMask == 0) | |
450be234 | 958 | endmask = ~ (unsigned32)0; |
c1c77d40 AC |
959 | else |
960 | endmask = (1 << EndMask) - 1; | |
961 | if (i) | |
962 | endmask = ~endmask; | |
963 | /* form the shiftmask */ | |
964 | switch (Merge) | |
965 | { | |
966 | case 0: case 1: case 2: | |
450be234 | 967 | shiftmask = ~ (unsigned32)0; /* disabled */ |
c1c77d40 | 968 | break; |
07b4c0a6 AC |
969 | case 3: case 5: /* enabled - 0 -> 32 */ |
970 | if (nRotate == 0) | |
971 | shiftmask = ~ (unsigned32)0; | |
972 | else | |
973 | shiftmask = ((1 << nRotate) - 1); /* enabled - 0 -> 0 */ | |
974 | break; | |
975 | case 4: | |
976 | shiftmask = ((1 << nRotate) - 1); /* enabled - 0 -> 0 */ | |
c1c77d40 AC |
977 | break; |
978 | case 6: case 7: | |
450be234 | 979 | shiftmask = ~((1 << nRotate) - 1); /* inverted */ |
c1c77d40 AC |
980 | break; |
981 | default: | |
f03b093c AC |
982 | sim_engine_abort (SD, CPU, cia, |
983 | "0x%lx: Invalid merge (%d) for shift", | |
a6a51ac7 | 984 | (long) cia.ip, (int) source); |
c1c77d40 AC |
985 | shiftmask = 0; |
986 | } | |
987 | /* and the composite mask */ | |
988 | cm = shiftmask & endmask; | |
989 | /* and merge */ | |
990 | switch (Merge) | |
991 | { | |
450be234 | 992 | case 0: case 3: case 6: /* zero */ |
c1c77d40 AC |
993 | GPR (Dest) = rotated & cm; |
994 | break; | |
450be234 | 995 | case 1: case 4: case 7: /* merge */ |
c1c77d40 AC |
996 | GPR (Dest) = (rotated & cm) | (GPR (Dest) & ~cm); |
997 | break; | |
450be234 | 998 | case 2: case 5: /* sign */ |
c1c77d40 AC |
999 | { |
1000 | int b; | |
1001 | GPR (Dest) = rotated & cm; | |
1002 | for (b = 1; b <= 31; b++) | |
1003 | if (!MASKED32 (cm, b, b)) | |
1004 | GPR (Dest) |= INSERTED32 (EXTRACTED32 (GPR (Dest), b - 1, b - 1), | |
1005 | b, b); | |
1006 | } | |
1007 | break; | |
1008 | default: | |
f03b093c AC |
1009 | sim_engine_abort (SD, CPU, cia, |
1010 | "0x%lx: Invalid merge (%d)", | |
a6a51ac7 | 1011 | (long) cia.ip, (int) source); |
c1c77d40 AC |
1012 | |
1013 | } | |
450be234 | 1014 | TRACE_SHIFT (MY_INDEX, GPR (Dest), input, i, n, Merge, EndMask, Rotate); |
128b5154 AC |
1015 | const char *::function::str_Merge:int Merge |
1016 | switch (Merge) | |
1017 | { | |
1018 | case 0: return "dz"; | |
1019 | case 1: return "dm"; | |
1020 | case 2: return "ds"; | |
1021 | case 3: return "ez"; | |
1022 | case 4: return "em"; | |
1023 | case 5: return "es"; | |
1024 | case 6: return "iz"; | |
1025 | case 7: return "im"; | |
1026 | default: return "?"; | |
1027 | } | |
c1c77d40 | 1028 | 31.Dest,26.Source,21.0b0001,17.Merge,14./,11.i,10.n,9.EndMask,4.Rotate::::sl i |
128b5154 | 1029 | "sl.%s<Merge> <Rotate>, <EndMask>, r<Source>, r<Dest>" |
37a684b8 | 1030 | do_shift (_SD, Dest, vSource, Merge, i, n, EndMask, Rotate); |
c1c77d40 | 1031 | 31.Dest,26.Source,21.0b110001,15.Merge,12.0,11.i,10.n,9.EndMask,4.RotReg::::sl r |
128b5154 | 1032 | "sl.%s<Merge> r<RotReg>, <EndMask>, r<Source>, r<Dest>" |
37a684b8 | 1033 | do_shift (_SD, Dest, vSource, Merge, i, n, EndMask, GPR (RotReg) & 31); |
15c16493 AC |
1034 | |
1035 | ||
381f42ef | 1036 | // sli.{d|e|i}{m|s|z} - see shift |
15c16493 AC |
1037 | |
1038 | ||
381f42ef | 1039 | // sr.{d|e|i}{m|s|z} - see shift |
15c16493 AC |
1040 | |
1041 | ||
381f42ef | 1042 | // sra - see sr.es - see shift |
15c16493 AC |
1043 | |
1044 | ||
381f42ef | 1045 | // sri.{d|e|i}{m|s|z} - see shift |
15c16493 AC |
1046 | |
1047 | ||
1048 | // srl - see sr.ez | |
1049 | ||
1050 | ||
1051 | // st[{.b|.h|.d}] | |
37a684b8 | 1052 | void::function::do_st:int Source, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset |
abe293a0 AC |
1053 | unsigned32 addr; |
1054 | switch (sz) | |
1055 | { | |
1056 | case 0: | |
37a684b8 | 1057 | addr = base + (S ? (offset << 0) : offset); |
d5e2c74e | 1058 | STORE (addr, 1, GPR(Source)); |
abe293a0 AC |
1059 | break; |
1060 | case 1: | |
37a684b8 | 1061 | addr = base + (S ? (offset << 1) : offset); |
d5e2c74e | 1062 | STORE (addr, 2, GPR(Source)); |
abe293a0 AC |
1063 | break; |
1064 | case 2: | |
37a684b8 | 1065 | addr = base + (S ? (offset << 2) : offset); |
d5e2c74e | 1066 | STORE (addr, 4, GPR(Source)); |
abe293a0 AC |
1067 | break; |
1068 | case 3: | |
c445af5a AC |
1069 | { |
1070 | signed64 val; | |
1071 | if (Source & 0x1) | |
f03b093c AC |
1072 | sim_engine_abort (SD, CPU, cia, |
1073 | "0x%lx: st.d with odd source register %d", | |
1074 | cia.ip, Source); | |
37a684b8 | 1075 | addr = base + (S ? (offset << 3) : offset); |
d6fea803 | 1076 | val = U8_4 (GPR(Source + 1), GPR(Source)); |
c445af5a AC |
1077 | STORE (addr, 8, val); |
1078 | } | |
abe293a0 AC |
1079 | break; |
1080 | default: | |
1081 | addr = -1; | |
f03b093c | 1082 | sim_engine_abort (SD, CPU, cia, "st - invalid sz %d", sz); |
abe293a0 AC |
1083 | } |
1084 | if (m) | |
1085 | *rBase = addr; | |
128b5154 | 1086 | TRACE_ST (Source, m, S, base, offset); |
abe293a0 | 1087 | 31.Source,26.Base,21.0b0110,17.m,16.sz,14.SignedOffset::::st i |
128b5154 | 1088 | "st%s<sz> <SignedOffset> (r<Base>%s<m>), r<Source>" |
37a684b8 | 1089 | do_st (_SD, Source, vBase, rBase, m, sz, 0, vSignedOffset); |
abe293a0 | 1090 | 31.Source,26.Base,21.0b110110,15.m,14.sz,12.0,11.S,10.0,9./,4.IndOff::::st r |
128b5154 | 1091 | "st%s<sz> r<IndOff>%s<S> (r<Base>%s<m>), r<Source>" |
37a684b8 | 1092 | do_st (_SD, Source, vBase, rBase, m, sz, S, rIndOff); |
128b5154 AC |
1093 | 31.Source,26.Base,21.0b110110,15.m,14.sz,12.1,11.S,10.0,9./+LongSignedImmediateOffset::::st l |
1094 | "st%s<sz> 0x%08lx<LongSignedImmediateOffset>%s<S> (r<Base>%s<m>), r<Source>" | |
37a684b8 | 1095 | do_st (_SD, Source, vBase, rBase, m, sz, S, LongSignedImmediateOffset); |
15c16493 AC |
1096 | |
1097 | ||
1098 | // sub | |
381f42ef | 1099 | void::function::do_sub:signed32 *rDest, signed32 Source1, signed32 Source2 |
abe293a0 AC |
1100 | ALU_BEGIN (Source1); |
1101 | ALU_SUB (Source2); | |
7b167b09 | 1102 | ALU_END (*rDest); |
381f42ef | 1103 | TRACE_ALU3 (MY_INDEX, *rDest, Source1, Source2); |
abe293a0 | 1104 | 31.Dest,26.Source2,21.0b101101,15.0,14.SignedImmediate::::sub i |
128b5154 | 1105 | "sub <SignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 1106 | do_sub (_SD, rDest, vSource1, vSource2); |
abe293a0 | 1107 | 31.Dest,26.Source2,21.0b11101101,13.0,12.0,11./,4.Source1::::sub r |
128b5154 | 1108 | "sub r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 1109 | do_sub (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
1110 | 31.Dest,26.Source2,21.0b11101101,13.0,12.1,11./+LongSignedImmediate::::sub l |
1111 | "sub 0x%08lx<LongSignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 1112 | do_sub (_SD, rDest, LongSignedImmediate, vSource2); |
15c16493 AC |
1113 | |
1114 | ||
1115 | // subu | |
450be234 | 1116 | void::function::do_subu:unsigned32 *rDest, unsigned32 Source1, signed32 Source2 |
7b167b09 | 1117 | unsigned32 result = Source1 - Source2; |
381f42ef | 1118 | TRACE_ALU3 (MY_INDEX, result, Source1, Source2); |
7b167b09 | 1119 | *rDest = result; |
d5e2c74e | 1120 | // NOTE - the book has 15.1 which conflicts with subu. |
4e95b94e | 1121 | 31.Dest,26.Source2,21.0b101101,15.1,14.SignedImmediate::::subu i |
128b5154 | 1122 | "subu <SignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 1123 | do_subu (_SD, rDest, vSource1, vSource2); |
abe293a0 | 1124 | 31.Dest,26.Source2,21.0b11101101,13.1,12.0,11./,4.Source1::::subu r |
128b5154 | 1125 | "subu r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 1126 | do_subu (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
1127 | 31.Dest,26.Source2,21.0b11101101,13.1,12.1,11./+LongSignedImmediate::::subu l |
1128 | "subu 0x%08lx<LongSignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 1129 | do_subu (_SD, rDest, LongSignedImmediate, vSource2); |
15c16493 AC |
1130 | |
1131 | ||
1132 | // swcr | |
37a684b8 | 1133 | void::function::do_swcr:int Dest, signed32 source, signed32 cr |
381f42ef AC |
1134 | tic80_control_regs reg = tic80_index2cr (cr); |
1135 | /* cache the old CR value */ | |
1136 | unsigned32 old_cr = CR (cr); | |
1137 | /* Handle the write if allowed */ | |
1138 | if (cr >= 0x4000 || !(CPU)->is_user_mode) | |
1139 | switch (reg) | |
1140 | { | |
1141 | case INTPEN_CR: | |
37a684b8 | 1142 | CR (cr) &= ~source; |
381f42ef AC |
1143 | break; |
1144 | default: | |
37a684b8 | 1145 | CR (cr) = source; |
381f42ef AC |
1146 | break; |
1147 | } | |
1148 | /* Finish off the read */ | |
1149 | GPR (Dest) = old_cr; | |
37a684b8 | 1150 | TRACE_SINK3 (MY_INDEX, source, cr, Dest); |
381f42ef | 1151 | 31.Dest,26.Source,21.0b000010,15.1,14.UCRN::::swcr i |
128b5154 | 1152 | "swcr CR[<UCRN>], r<Dest>" |
37a684b8 | 1153 | do_swcr (_SD, Dest, vSource, UCRN); |
abe293a0 | 1154 | 31.Dest,26.Source,21.0b11000010,13.1,12.0,11./,4.INDCR::::swcr r |
128b5154 | 1155 | "swcr CR[r<INDCR>], r<Dest>" |
37a684b8 | 1156 | do_swcr (_SD, Dest, vSource, UCRN); |
128b5154 AC |
1157 | 31.Dest,26.Source,21.0b11000010,13.1,12.1,11./+LongUnsignedControlRegisterNumber::::swcr l |
1158 | "swcr CR[<LongUnsignedControlRegisterNumber>], r<Dest>" | |
1159 | do_swcr (_SD, Dest, vSource, LongUnsignedControlRegisterNumber); | |
15c16493 AC |
1160 | |
1161 | ||
1162 | // trap | |
381f42ef | 1163 | void::function::do_trap:unsigned32 trap_number |
1b6f4dde | 1164 | int i; |
381f42ef | 1165 | TRACE_SINK1 (MY_INDEX, trap_number); |
d5e2c74e | 1166 | switch (trap_number) |
15c16493 | 1167 | { |
d5e2c74e AC |
1168 | case 72: |
1169 | switch (GPR(15)) | |
15c16493 AC |
1170 | { |
1171 | case 1: /* EXIT */ | |
1172 | { | |
f03b093c | 1173 | sim_engine_halt (SD, CPU, NULL, cia, sim_exited, GPR(2)); |
15c16493 AC |
1174 | break; |
1175 | } | |
1176 | case 4: /* WRITE */ | |
1177 | { | |
4113ba4c | 1178 | unsigned i; |
3971886a AC |
1179 | if (GPR(2) == 1) |
1180 | for (i = 0; i < GPR(6); i++) | |
1181 | { | |
1182 | char c; | |
1183 | c = MEM (unsigned, GPR(4) + i, 1); | |
1184 | sim_io_write_stdout (SD, &c, 1); | |
1185 | } | |
1186 | else if (GPR(2) == 2) | |
1187 | for (i = 0; i < GPR(6); i++) | |
1188 | { | |
1189 | char c; | |
1190 | c = MEM (unsigned, GPR(4) + i, 1); | |
1191 | sim_io_write_stderr (SD, &c, 1); | |
1192 | } | |
1193 | else | |
f03b093c AC |
1194 | sim_engine_abort (SD, CPU, cia, |
1195 | "0x%lx: write to invalid fid %d", | |
a6a51ac7 | 1196 | (long) cia.ip, (int) GPR(2)); |
d5e2c74e | 1197 | GPR(2) = GPR(6); |
15c16493 AC |
1198 | break; |
1199 | } | |
8c5b6ead MM |
1200 | case 20: /* GETPID */ |
1201 | { | |
1202 | GPR(2) = getpid (); | |
1203 | break; | |
1204 | } | |
1205 | case 37: /* KILL */ | |
4113ba4c | 1206 | if ( GPR (2) != (unsigned) getpid ()) |
8c5b6ead MM |
1207 | { |
1208 | int ret = kill (GPR(2), GPR(4)); | |
1209 | if (ret < 0) | |
1210 | ret = -errno; | |
1211 | GPR (2) = ret; | |
1212 | break; | |
1213 | } | |
1214 | else | |
1215 | { | |
1216 | sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, GPR(4)); | |
1217 | break; | |
1218 | } | |
15c16493 | 1219 | default: |
1b6f4dde MM |
1220 | /* For system calls which are defined, just return EINVAL instead of trapping */ |
1221 | if (GPR(15) <= 204) | |
1222 | { | |
1223 | GPR(2) = -22; /* -EINVAL */ | |
1224 | break; | |
1225 | } | |
f03b093c AC |
1226 | sim_engine_abort (SD, CPU, cia, |
1227 | "0x%lx: unknown syscall %d", | |
a6a51ac7 | 1228 | (long) cia.ip, (int) GPR(15)); |
15c16493 | 1229 | } |
d5e2c74e | 1230 | break; |
c1c77d40 | 1231 | case 73: |
aaa11abe | 1232 | sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGTRAP); |
1b6f4dde MM |
1233 | |
1234 | /* Add a few traps for now to print the register state */ | |
1235 | case 74: | |
1236 | case 75: | |
1237 | case 76: | |
1238 | case 77: | |
1239 | case 78: | |
1240 | case 79: | |
1241 | if (!TRACE_ALU_P (CPU)) | |
1242 | trace_one_insn (SD, CPU, cia.ip, 1, itable[MY_INDEX].file, | |
1243 | itable[MY_INDEX].line_nr, "trap", | |
2310e3c2 | 1244 | "Trap %ld", (long) trap_number); |
1b6f4dde MM |
1245 | |
1246 | for (i = 0; i < 32; i++) | |
1247 | sim_io_eprintf (SD, "%s0x%.8lx%s", ((i % 8) == 0) ? "\t" : " ", (long)GPR(i), | |
1248 | (((i+1) % 8) == 0) ? "\n" : ""); | |
1249 | sim_io_write_stderr (SD, "\n", 1); | |
1250 | break; | |
1251 | ||
d5e2c74e | 1252 | default: |
f03b093c AC |
1253 | sim_engine_abort (SD, CPU, cia, |
1254 | "0x%lx: unsupported trap %d", | |
a6a51ac7 | 1255 | (long) cia.ip, (int) trap_number); |
15c16493 AC |
1256 | } |
1257 | 31./,27.0,26./,21.0b0000001,14.UTN::::trap i | |
128b5154 | 1258 | "trap <UTN>" |
381f42ef | 1259 | do_trap (_SD, UTN); |
15c16493 | 1260 | 31./,27.0,26./,21.0b110000001,12.0,11./,4.INDTR::::trap r |
128b5154 | 1261 | "trap r<INDTR>" |
381f42ef | 1262 | do_trap (_SD, UTN); |
128b5154 AC |
1263 | 31./,27.0,26./,21.0b110000001,12.1,11./+UTN::::trap l |
1264 | "trap 0x%08lx<UTN>" | |
381f42ef | 1265 | do_trap (_SD, UTN); |
15c16493 AC |
1266 | |
1267 | ||
1268 | // vadd.{s|d}{s|d} | |
381f42ef AC |
1269 | 31.*,26.Dest,21.0b11110,16./,15.0b000,12.0,11./,10.*,9.*,7.PD,6.*,5.P1,4.Source::f::vadd r |
1270 | 31.*,26.Dest,21.0b11110,16./,15.0b000,12.1,11./,10.*,9.*,7.PD,6.*,5.P1,4.Source::f::vadd l | |
15c16493 AC |
1271 | |
1272 | ||
abe293a0 | 1273 | // vld{0|1}.{s|d} - see above - same instruction |
381f42ef | 1274 | #31.Dest,26.*,21.0b11110,16.*,10.1,9.S,8.*,6.p,7.******::f::vld |
15c16493 AC |
1275 | |
1276 | ||
1277 | // vmac.ss{s|d} | |
381f42ef AC |
1278 | #31.*, 26.Source2,21.0b11110,16.a0,15.0b110,12.0,11.a1,10.*,9.*, 8.Z,7./,6.*,5./,4.Source1::f::vmac.ss ra |
1279 | 31.Dest,26.Source2,21.0b11110,16.a0,15.0b110,12.0,11.a1,10.0,9.PD,8.Z,7./,6.0,5./,4.Source1::f::vmac.ss rr | |
1280 | #31.*, 26.Source2,21.0b11110,16.a0,15.0b110,12.1,11.a1,10.*,9.*, 8.Z,7./,6.*,5./,4./::f::vmac.ss ia | |
1281 | 31.Dest,26.Source2,21.0b11110,16.a0,15.0b110,12.1,11.a1,10.0,9.PD,8.Z,7./,6.0,5./,4./::f::vmac.ss ir | |
15c16493 AC |
1282 | |
1283 | ||
1284 | // vmpy.{s|d}{s|d} | |
381f42ef AC |
1285 | 31.*,26.Dest,21.0b11110,16./,15.0b010,12.0,11./,10.*,8.*,7.PD,6.*,5.P1,4.Source::f::vmpy r |
1286 | 31.*,26.Dest,21.0b11110,16./,15.0b010,12.1,11./,10.*,8.*,7.PD,6.*,5.P1,4./::f::vmpy l | |
15c16493 AC |
1287 | |
1288 | ||
1289 | // vmsc.ss{s|d} | |
381f42ef AC |
1290 | #31.*, 26.Source2,21.0b11110,16.a0,15.0b111,12.0,11.a1,10.*,9.*, 8.Z,7./,6.*,5./,4.Source1::f::vmsc.ss ra |
1291 | 31.Dest,26.Source2,21.0b11110,16.a0,15.0b111,12.0,11.a1,10.0,9.PD,8.Z,7./,6.0,5./,4.Source1::f::vmsc.ss rr | |
1292 | #31.*, 26.Source2,21.0b11110,16.a0,15.0b111,12.1,11.a1,10.*,9.*, 8.Z,7./,6.*,5./,4./::f::vmsc.ss ia | |
1293 | 31.Dest,26.Source2,21.0b11110,16.a0,15.0b111,12.1,11.a1,10.0,9.PD,8.Z,7./,6.0,5./,4./::f::vmsc.ss ir | |
15c16493 AC |
1294 | |
1295 | ||
1296 | // vmsub.{s|d}{s|d} | |
381f42ef AC |
1297 | 31.*,26.Dest,21.0b11110,16.a0,15.0b011,12.0,11.a1,10.*,8.Z,7.PD,6.*,5./,4.Source::f::vmsub r |
1298 | 31.*,26.Dest,21.0b11110,16.a0,15.0b011,12.1,11.a1,10.*,8.Z,7.PD,6.*,5./,4./::f::vmsub l | |
15c16493 AC |
1299 | |
1300 | ||
1301 | // vrnd.{s|d}{s|d} | |
381f42ef AC |
1302 | 31.*,26.Dest,21.0b11110,16.a0,15.0b100,12.0,11.a1,10.*,8.PD,6.*,5.P1,4.Source::f::vrnd f r |
1303 | 31.*,26.Dest,21.0b11110,16.a0,15.0b100,12.1,11.a1,10.*,8.PD,6.*,5.P1,4./::f::vrnd f l | |
15c16493 AC |
1304 | |
1305 | ||
1306 | // vrnd.{i|u}{s|d} | |
381f42ef AC |
1307 | 31.*,26.Dest,21.0b11110,16./,15.0b101,12.0,11./,10.*,8./,7.PD,6.*,5.P1,4.Source::f::vrnd i r |
1308 | 31.*,26.Dest,21.0b11110,16./,15.0b101,12.1,11./,10.*,8./,7.PD,6.*,5.P1,4./::f::vrnd i l | |
15c16493 AC |
1309 | |
1310 | ||
abe293a0 | 1311 | // vst.{s|d} - see above - same instruction |
381f42ef | 1312 | #31.Source,26.*,21.0b11110,16.*,10.0,9.S,8.*,6.1,5.*::f::vst |
15c16493 AC |
1313 | |
1314 | ||
1315 | // vsub.{i|u}{s|d} | |
381f42ef AC |
1316 | 31.*,26.Dest,21.0b11110,16./,15.0b001,12.0,11./,10.*,8./,7.PD,6.*,5.P1,4.Source::f::vsub r |
1317 | 31.*,26.Dest,21.0b11110,16./,15.0b001,12.1,11./,10.*,8./,7.PD,6.*,5.P1,4./::f::vsub l | |
15c16493 AC |
1318 | |
1319 | ||
abe293a0 | 1320 | // wrcr - see swcr, creg, source, r0 |
15c16493 AC |
1321 | |
1322 | ||
1323 | // xnor | |
37a684b8 AC |
1324 | void::function::do_xnor:signed32 *rDest, signed32 source1, signed32 source2 |
1325 | unsigned32 result = ~ (source1 ^ source2); | |
1326 | TRACE_ALU3 (MY_INDEX, result, source1, source2); | |
7b167b09 | 1327 | *rDest = result; |
abe293a0 | 1328 | 31.Dest,26.Source2,21.0b0011001,14.UnsignedImmediate::::xnor i |
128b5154 | 1329 | "xnor <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 1330 | do_xnor (_SD, rDest, vSource1, vSource2); |
abe293a0 | 1331 | 31.Dest,26.Source2,21.0b110011001,12.0,11./,4.Source1::::xnor r |
128b5154 | 1332 | "xnor r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 1333 | do_xnor (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
1334 | 31.Dest,26.Source2,21.0b110011001,12.1,11./+LongUnsignedImmediate::::xnor l |
1335 | "xnor 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 1336 | do_xnor (_SD, rDest, LongUnsignedImmediate, vSource2); |
15c16493 AC |
1337 | |
1338 | ||
1339 | // xor | |
37a684b8 AC |
1340 | void::function::do_xor:signed32 *rDest, signed32 source1, signed32 source2 |
1341 | unsigned32 result = source1 ^ source2; | |
1342 | TRACE_ALU3 (MY_INDEX, result, source1, source2); | |
7b167b09 | 1343 | *rDest = result; |
480e740c | 1344 | 31.Dest,26.Source2,21.0b0010110,14.UnsignedImmediate::::xor i |
128b5154 | 1345 | "xor <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 1346 | do_xor (_SD, rDest, vSource1, vSource2); |
89d1a478 | 1347 | 31.Dest,26.Source2,21.0b110010110,12.0,11./,4.Source1::::xor r |
128b5154 | 1348 | "xor r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 1349 | do_xor (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
1350 | 31.Dest,26.Source2,21.0b110010110,12.1,11./+LongUnsignedImmediate::::xor l |
1351 | "xor 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 1352 | do_xor (_SD, rDest, LongUnsignedImmediate, vSource2); |