]>
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. |
15c16493 | 23 | ::internal::illegal |
f03b093c AC |
24 | sim_io_eprintf (SD, "0x%lx: illegal instruction\n", (unsigned long) cia.ip); |
25 | sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIGILL); | |
26 | ||
381f42ef AC |
27 | // The following is called when ever an FP op is attempted with FPU disabled. |
28 | ::internal::fp_unavailable | |
f03b093c AC |
29 | sim_io_eprintf (SD, "0x%lx: floating-point unavailable\n", (unsigned long) cia.ip); |
30 | sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIGFPE); | |
84902350 AC |
31 | |
32 | // Handle a branch instruction | |
33 | instruction_address::function::do_branch:int annul, address_word target, int rLink_p, unsigned32 *rLink | |
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 | |
37a684b8 AC |
52 | void::function::do_add:unsigned32 *rDest, signed32 source1, signed32 source2 |
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 | |
37a684b8 AC |
72 | void::function::do_addu:unsigned32 *rDest, unsigned32 source1, unsigned32 source2 |
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 | ||
37a684b8 AC |
88 | void::function::do_and:signed32 *rDest, signed32 source1, signed32 source2 |
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] |
381f42ef | 143 | instruction_address::function::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; | |
381f42ef | 153 | TRACE_COND_BR(MY_INDEX, jump_p, bitnum, target); |
480e740c | 154 | return nia; |
128b5154 AC |
155 | const char *::function::str_A:int A |
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] | |
381f42ef | 172 | instruction_address::function::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; | |
381f42ef | 182 | TRACE_COND_BR(MY_INDEX, jump_p, bitnum, target); |
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] | |
381f42ef | 196 | instruction_address::function::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 | } |
381f42ef | 224 | TRACE_COND_BR(MY_INDEX, condition, source, target); |
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 | |
381f42ef AC |
241 | sim_cia::function::do_brcr:instruction_address nia, int cr |
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] | |
381f42ef | 269 | instruction_address::function::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 | |
381f42ef | 286 | void::function::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 | |
480e740c AC |
335 | unsigned32::function::cmp_vals:signed32 s1, unsigned32 u1, signed32 s2, unsigned32 u2 |
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; |
37a684b8 | 348 | void::function::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); | |
355 | TRACE_ALU3 (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 | |
128b5154 AC |
369 | const char *::function::str_F:int F |
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 AC |
436 | sim_fpu::function::get_fp_reg:int reg, unsigned32 val, int precision |
437 | switch (precision) | |
438 | { | |
439 | case 0: /* single */ | |
aa3a0447 | 440 | return sim_fpu_32to (val); |
3971886a AC |
441 | case 1: /* double */ |
442 | if (reg < 0) | |
f03b093c | 443 | sim_engine_abort (SD, CPU, cia, "DP immediate invalid"); |
3971886a | 444 | if (reg & 1) |
f03b093c | 445 | sim_engine_abort (SD, CPU, cia, "DP FP register must be even"); |
3971886a | 446 | if (reg <= 1) |
f03b093c | 447 | sim_engine_abort (SD, CPU, cia, "DP FP register must be >= 2"); |
37a684b8 AC |
448 | return sim_fpu_64to (INSERTED64 (GPR (reg + 1), 63, 32) |
449 | | INSERTED64 (GPR (reg), 31, 0)); | |
3971886a | 450 | case 2: /* 32 bit signed integer */ |
aa3a0447 | 451 | return sim_fpu_i32to (val); |
3971886a | 452 | case 3: /* 32 bit unsigned integer */ |
aa3a0447 | 453 | return sim_fpu_u32to (val); |
3971886a | 454 | default: |
f03b093c | 455 | sim_engine_abort (SD, CPU, cia, "Unsupported FP precision"); |
3971886a | 456 | } |
aa3a0447 | 457 | return sim_fpu_i32to (0); |
3971886a AC |
458 | void::function::set_fp_reg:int Dest, sim_fpu val, int PD |
459 | switch (PD) | |
460 | { | |
461 | case 0: /* single */ | |
462 | { | |
463 | GPR (Dest) = sim_fpu_to32 (val); | |
464 | break; | |
465 | } | |
466 | case 1: /* double */ | |
467 | { | |
aa3a0447 | 468 | unsigned64 v = sim_fpu_to64 (val); |
3971886a | 469 | if (Dest & 1) |
f03b093c | 470 | sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be even"); |
3971886a | 471 | if (Dest <= 1) |
f03b093c | 472 | sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be >= 2"); |
aa3a0447 AC |
473 | GPR (Dest + 0) = VL4_8 (v); |
474 | GPR (Dest + 1) = VH4_8 (v); | |
3971886a AC |
475 | break; |
476 | } | |
477 | case 2: /* signed */ | |
07b4c0a6 AC |
478 | { |
479 | GPR (Dest) = sim_fpu_to32i (val); | |
480 | break; | |
481 | } | |
3971886a | 482 | case 3: /* unsigned */ |
07b4c0a6 AC |
483 | { |
484 | GPR (Dest) = sim_fpu_to32u (val); | |
485 | break; | |
486 | } | |
3971886a | 487 | default: |
f03b093c | 488 | sim_engine_abort (SD, CPU, cia, "Unsupported FP precision"); |
3971886a AC |
489 | } |
490 | ||
15c16493 | 491 | // fadd.{s|d}{s|d}{s|d} |
3971886a AC |
492 | void::function::do_fadd:int Dest, int PD, sim_fpu s1, sim_fpu s2 |
493 | sim_fpu ans = sim_fpu_add (s1, s2); | |
128b5154 | 494 | TRACE_FPU3 (ans, s1, s2); |
3971886a | 495 | set_fp_reg (_SD, Dest, ans, PD); |
128b5154 AC |
496 | const char *::function::str_PX:int PX |
497 | switch (PX) | |
498 | { | |
499 | case 0: return "s"; | |
500 | case 1: return "d"; | |
501 | case 2: return "i"; | |
502 | case 3: return "u"; | |
503 | default: return "?"; | |
504 | } | |
381f42ef | 505 | 31.Dest,26.Source2,21.0b111110000,12.0,11.r,10.PD,8.P2,6.P1,4.Source1::f::fadd r |
128b5154 | 506 | "fadd.%s<PX#P1>%s<PX#P2>%s<PX#PD> r<Source1>, r<Source2>, r<Dest>" |
3971886a | 507 | do_fadd (_SD, Dest, PD, |
37a684b8 AC |
508 | get_fp_reg (_SD, Source1, vSource1, P1), |
509 | get_fp_reg (_SD, Source2, vSource2, P2)); | |
128b5154 AC |
510 | 31.Dest,26.Source2,21.0b111110000,12.1,11.r,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fadd l |
511 | "fadd.%s<PX#P1>%s<PX#P2>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Source2>, r<Dest>" | |
3971886a AC |
512 | do_fadd (_SD, Dest, PD, |
513 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), | |
37a684b8 | 514 | get_fp_reg (_SD, Source2, vSource2, P2)); |
15c16493 AC |
515 | |
516 | ||
517 | // fcmp.{s|d}{s|d}{s|d} | |
37a684b8 | 518 | void::function::do_fcmp:unsigned32 *rDest, sim_fpu s1, sim_fpu s2 |
aa3a0447 | 519 | unsigned32 result = 0; |
3971886a | 520 | if (sim_fpu_is_nan (s1) || sim_fpu_is_nan (s2)) |
aa3a0447 | 521 | result |= BIT32 (30); |
3971886a AC |
522 | else |
523 | { | |
aa3a0447 AC |
524 | result |= BIT32 (31); |
525 | if (sim_fpu_is_eq (s1, s2)) result |= BIT32(20); | |
526 | if (sim_fpu_is_ne (s1, s2)) result |= BIT32(21); | |
527 | if (sim_fpu_is_gt (s1, s2)) result |= BIT32(22); | |
528 | if (sim_fpu_is_le (s1, s2)) result |= BIT32(23); | |
529 | if (sim_fpu_is_lt (s1, s2)) result |= BIT32(24); | |
530 | if (sim_fpu_is_ge (s1, s2)) result |= BIT32(25); | |
531 | if (sim_fpu_is_lt (s1, sim_fpu_i32to (0)) | |
532 | || sim_fpu_is_gt (s1, s2)) result |= BIT32(26); | |
533 | if (sim_fpu_is_lt (sim_fpu_i32to (0), s1) | |
534 | && sim_fpu_is_lt (s1, s2)) result |= BIT32(27); | |
535 | if (sim_fpu_is_le (sim_fpu_i32to (0), s1) | |
536 | && sim_fpu_is_le (s1, s2)) result |= BIT32(28); | |
537 | if (sim_fpu_is_le (s1, sim_fpu_i32to (0)) | |
538 | || sim_fpu_is_ge (s1, s2)) result |= BIT32(29); | |
3971886a | 539 | } |
37a684b8 | 540 | *rDest = result; |
128b5154 | 541 | TRACE_FPU2I (result, s1, s2); |
381f42ef | 542 | 31.Dest,26.Source2,21.0b111110101,12.0,11./,10.0,8.P2,6.P1,4.Source1::f::fcmp r |
128b5154 | 543 | "fcmp.%s<PX#P1>%s<PX#P2> r<Source1>, r<Source2>, r<Dest>" |
37a684b8 AC |
544 | do_fcmp (_SD, rDest, |
545 | get_fp_reg (_SD, Source1, vSource1, P1), | |
546 | get_fp_reg (_SD, Source2, vSource2, P2)); | |
128b5154 AC |
547 | 31.Dest,26.Source2,21.0b111110101,12.1,11./,10.0,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fcmp l |
548 | "fcmp.%s<PX#P1>%s<PX#P2> 0x%08lx<SinglePrecisionFloatingPoint>, r<Source2>, r<Dest>" | |
37a684b8 | 549 | do_fcmp (_SD, rDest, |
3971886a | 550 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), |
37a684b8 | 551 | get_fp_reg (_SD, Source2, vSource2, P2)); |
3971886a | 552 | |
15c16493 AC |
553 | |
554 | ||
555 | // fdiv.{s|d}{s|d}{s|d} | |
3971886a AC |
556 | void::function::do_fdiv:int Dest, int PD, sim_fpu s1, sim_fpu s2 |
557 | sim_fpu ans = sim_fpu_div (s1, s2); | |
128b5154 | 558 | TRACE_FPU3 (ans, s1, s2); |
3971886a | 559 | set_fp_reg (_SD, Dest, ans, PD); |
381f42ef | 560 | 31.Dest,26.Source2,21.0b111110011,12.0,11./,10.PD,8.P2,6.P1,4.Source1::f::fdiv r |
128b5154 | 561 | "fdiv.%s<PX#P1>%s<PX#P2>%s<PX#PD> r<Source1>, r<Source2>, r<Dest>" |
3971886a | 562 | do_fdiv (_SD, Dest, PD, |
37a684b8 AC |
563 | get_fp_reg (_SD, Source1, vSource1, P1), |
564 | get_fp_reg (_SD, Source2, vSource2, P2)); | |
128b5154 AC |
565 | 31.Dest,26.Source2,21.0b111110011,12.1,11./,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fdiv l |
566 | "fdiv.%s<PX#P1>%s<PX#P2>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Source2>, r<Dest>" | |
3971886a AC |
567 | do_fdiv (_SD, Dest, PD, |
568 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), | |
37a684b8 | 569 | get_fp_reg (_SD, Source2, vSource2, P2)); |
15c16493 AC |
570 | |
571 | ||
572 | // fmpy.{s|d|i|u}{s|d|i|u}{s|d|i|u} | |
3971886a | 573 | void::function::do_fmpy:int Dest, int PD, sim_fpu s1, sim_fpu s2 |
07b4c0a6 AC |
574 | switch (PD) |
575 | { | |
576 | case 2: /* signed */ | |
577 | { | |
578 | GPR (Dest) = sim_fpu_to64i (s1) * sim_fpu_to64i (s2); | |
128b5154 | 579 | TRACE_FPU2I (GPR (Dest), s1, s2); |
07b4c0a6 AC |
580 | break; |
581 | } | |
582 | case 3: /* unsigned */ | |
583 | { | |
584 | GPR (Dest) = sim_fpu_to64u (s1) * sim_fpu_to64u (s2); | |
128b5154 | 585 | TRACE_FPU2I (GPR (Dest), s1, s2); |
07b4c0a6 AC |
586 | break; |
587 | } | |
588 | default: | |
589 | { | |
590 | sim_fpu ans = sim_fpu_mul (s1, s2); | |
591 | set_fp_reg (_SD, Dest, ans, PD); | |
128b5154 | 592 | TRACE_FPU3 (ans, s1, s2); |
07b4c0a6 AC |
593 | } |
594 | } | |
381f42ef | 595 | 31.Dest,26.Source2,21.0b111110010,12.0,11./,10.PD,8.P2,6.P1,4.Source1::f::fmpy r |
128b5154 | 596 | "fmpy.%s<PX#P1>%s<PX#P2>%s<PX#PD> r<Source1>, r<Source2>, r<Dest>" |
3971886a | 597 | do_fmpy (_SD, Dest, PD, |
37a684b8 AC |
598 | get_fp_reg (_SD, Source1, vSource1, P1), |
599 | get_fp_reg (_SD, Source2, vSource2, P2)); | |
128b5154 AC |
600 | 31.Dest,26.Source2,21.0b111110010,12.1,11./,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fmpy l |
601 | "fmpy.%s<PX#P1>%s<PX#P2>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Source2>, r<Dest>" | |
3971886a AC |
602 | do_fmpy (_SD, Dest, PD, |
603 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), | |
37a684b8 | 604 | get_fp_reg (_SD, Source2, vSource2, P2)); |
15c16493 AC |
605 | |
606 | ||
128b5154 | 607 | // frndm.{s|d|i|u}{s|d|i|u} |
3971886a AC |
608 | void::function::do_frnd:int Dest, int PD, sim_fpu s1 |
609 | set_fp_reg (_SD, Dest, s1, PD); | |
128b5154 AC |
610 | TRACE_FPU1 (s1); |
611 | 31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b11,6.P1,4.Source::f::frndm r | |
612 | "frndm.%s<PX#P1>%s<PX#PD> r<Source>, r<Dest>" | |
3971886a | 613 | do_frnd (_SD, Dest, PD, |
37a684b8 | 614 | get_fp_reg (_SD, Source, vSource, P1)); |
128b5154 AC |
615 | 31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b11,6.P1,4./+SinglePrecisionFloatingPoint::f::frndm l |
616 | "frndm.%s<PX#P1>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Dest>" | |
3971886a AC |
617 | do_frnd (_SD, Dest, PD, |
618 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); | |
15c16493 AC |
619 | |
620 | ||
128b5154 AC |
621 | // frndn.{s|d|i|u}{s|d|i|u} |
622 | 31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b00,6.P1,4.Source::f::frndn r | |
623 | "frndn.%s<PX#P1>%s<PX#PD> r<Source>, r<Dest>" | |
3971886a | 624 | do_frnd (_SD, Dest, PD, |
37a684b8 | 625 | get_fp_reg (_SD, Source, vSource, P1)); |
128b5154 AC |
626 | 31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b00,6.P1,4./+SinglePrecisionFloatingPoint::f::frndn l |
627 | "frndn.%s<PX#P1>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Dest>" | |
3971886a AC |
628 | do_frnd (_SD, Dest, PD, |
629 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); | |
15c16493 AC |
630 | |
631 | ||
128b5154 AC |
632 | // frndp.{s|d|i|u}{s|d|i|u} |
633 | 31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b10,6.P1,4.Source::f::frndp r | |
634 | "frndp.%s<PX#P1>%s<PX#PD> r<Source>, r<Dest>" | |
3971886a | 635 | do_frnd (_SD, Dest, PD, |
37a684b8 | 636 | get_fp_reg (_SD, Source, vSource, P1)); |
128b5154 AC |
637 | 31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b10,6.P1,4./+SinglePrecisionFloatingPoint::f::frndp l |
638 | "frndp.%s<PX#P1>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Dest>" | |
3971886a AC |
639 | do_frnd (_SD, Dest, PD, |
640 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); | |
15c16493 AC |
641 | |
642 | ||
128b5154 AC |
643 | // frndz.{s|d|i|u}{s|d|i|u} |
644 | 31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b01,6.P1,4.Source::f::frndz r | |
645 | "frndz.%s<PX#P1>%s<PX#PD> r<Source>, r<Dest>" | |
3971886a | 646 | do_frnd (_SD, Dest, PD, |
37a684b8 | 647 | get_fp_reg (_SD, Source, vSource, P1)); |
128b5154 AC |
648 | 31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b01,6.P1,4./+SinglePrecisionFloatingPoint::f::frndz l |
649 | "frndz.%s<PX#P1>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Dest>" | |
3971886a AC |
650 | do_frnd (_SD, Dest, PD, |
651 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); | |
15c16493 AC |
652 | |
653 | ||
654 | // fsqrt.{s|d}{s|d}{s|d} | |
128b5154 | 655 | #void::function::do_fsqrt:unsigned32 *rDest, unsigned32 Source, unsigned32 Source2 |
15c16493 | 656 | # sim_io_error ("fsqrt"); |
128b5154 AC |
657 | 31.Dest,26./,21.0b111110111,12.0,11./,10.PD,8.//,6.P1,4.Source::f::fsqrt r |
658 | "fsqrt.%s<PX#P1>%s<PX#PD> r<Source>, r<Dest>" | |
659 | # do_fsqrt (_SD, rDest, vSource); | |
660 | 31.Dest,26./,21.0b111110111,12.1,11./,10.PD,8.//,6.P1,4./+SinglePrecisionFloatingPoint::f::fsqrt l | |
661 | "fsqrt.%s<PX#P1>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Dest>" | |
662 | # do_fsqrt (_SD, rDest, SinglePrecisionFloatingPoint); | |
15c16493 AC |
663 | |
664 | ||
665 | // fsub.{s|d}{s|d}{s|d} | |
3971886a AC |
666 | void::function::do_fsub:int Dest, int PD, sim_fpu s1, sim_fpu s2 |
667 | sim_fpu ans = sim_fpu_sub (s1, s2); | |
128b5154 | 668 | TRACE_FPU3 (ans, s1, s2); |
3971886a | 669 | set_fp_reg (_SD, Dest, ans, PD); |
381f42ef | 670 | 31.Dest,26.Source2,21.0b111110001,12.0,11.r,10.PD,8.P2,6.P1,4.Source1::f::fsub r |
128b5154 | 671 | "fsub.%s<PX#P1>%s<PX#P2>%s<PX#PD> r<Source1>, r<Source2>, r<Dest>" |
3971886a | 672 | do_fsub (_SD, Dest, PD, |
37a684b8 AC |
673 | get_fp_reg (_SD, Source1, vSource1, P1), |
674 | get_fp_reg (_SD, Source2, vSource2, P2)); | |
128b5154 AC |
675 | 31.Dest,26.Source2,21.0b111110001,12.1,11.r,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fsub l |
676 | "fsub.%s<PX#P1>%s<PX#P2>%s<PX#PD> 0x%08lx<SinglePrecisionFloatingPoint>, r<Source2>, r<Dest>" | |
3971886a AC |
677 | do_fsub (_SD, Dest, PD, |
678 | get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), | |
37a684b8 | 679 | get_fp_reg (_SD, Source2, vSource2, P2)); |
15c16493 AC |
680 | |
681 | ||
682 | // illop | |
abe293a0 | 683 | 31./,21.0b0000000,14./::::illop |
128b5154 | 684 | "illop" |
abe293a0 | 685 | 31./,21.0b111111111,12./::::illop l |
128b5154 | 686 | "illop" |
15c16493 AC |
687 | |
688 | ||
abe293a0 | 689 | // ins - see sl.im |
15c16493 AC |
690 | |
691 | ||
692 | // jsr[.a] | |
381f42ef | 693 | instruction_address::function::do_jsr:instruction_address nia, signed32 *rLink, int annul, unsigned32 offset, unsigned32 base |
84902350 AC |
694 | address_word target = offset + base; |
695 | TRACE_UCOND_BR (MY_INDEX, target); | |
696 | nia = do_branch (_SD, annul, target, 1, rLink); | |
d5e2c74e | 697 | if (nia.dp & 0x3) |
f03b093c AC |
698 | sim_engine_abort (SD, CPU, cia, |
699 | "0x%lx: destination address 0x%lx misaligned", | |
700 | (unsigned long) cia.ip, | |
701 | (unsigned long) nia.dp); | |
480e740c AC |
702 | return nia; |
703 | 31.Link,26.Base,21.0b100010,15.A,14.SignedOffset::::jsr i | |
128b5154 | 704 | "jsr%s<A> <SignedOffset>, r<Link>" |
37a684b8 | 705 | nia = do_jsr (_SD, nia, rLink, A, vSignedOffset, vBase); |
128b5154 AC |
706 | 31.Link,26.Base,21.0b11100010,13.A,12.0,11./,4.IndOff::::jsr r |
707 | "jsr%s<A> r<IndOff>, r<Link>" | |
708 | nia = do_jsr (_SD, nia, rLink, A, rIndOff, vBase); | |
709 | 31.Link,26.Base,21.0b11100010,13.A,12.1,11./+LongSignedImmediate::::jsr l | |
710 | "jsr%s<A> <LongSignedImmediate>, r<Link>" | |
37a684b8 | 711 | nia = do_jsr (_SD, nia, rLink, A, LongSignedImmediate, vBase); |
15c16493 AC |
712 | |
713 | ||
714 | // ld[{.b.h.d}] | |
37a684b8 | 715 | void::function::do_ld:int Dest, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset |
abe293a0 AC |
716 | unsigned32 addr; |
717 | switch (sz) | |
718 | { | |
719 | case 0: | |
37a684b8 | 720 | addr = base + (S ? (offset << 0) : offset); |
d5e2c74e AC |
721 | if (m) |
722 | *rBase = addr; | |
723 | GPR(Dest) = MEM (signed, addr, 1); | |
abe293a0 AC |
724 | break; |
725 | case 1: | |
37a684b8 | 726 | addr = base + (S ? (offset << 1) : offset); |
d5e2c74e AC |
727 | if (m) |
728 | *rBase = addr; | |
729 | GPR(Dest) = MEM (signed, addr, 2); | |
abe293a0 AC |
730 | break; |
731 | case 2: | |
37a684b8 | 732 | addr = base + (S ? (offset << 2) : offset); |
d5e2c74e AC |
733 | if (m) |
734 | *rBase = addr; | |
735 | GPR(Dest) = MEM (signed, addr, 4); | |
abe293a0 AC |
736 | break; |
737 | case 3: | |
c445af5a AC |
738 | { |
739 | signed64 val; | |
740 | if (Dest & 0x1) | |
f03b093c AC |
741 | sim_engine_abort (SD, CPU, cia, "0x%lx: ld.d to odd register %d", |
742 | cia.ip, Dest); | |
37a684b8 | 743 | addr = base + (S ? (offset << 3) : offset); |
c445af5a AC |
744 | if (m) |
745 | *rBase = addr; | |
746 | val = MEM (signed, addr, 8); | |
747 | GPR(Dest + 1) = VH4_8 (val); | |
748 | GPR(Dest + 0) = VL4_8 (val); | |
749 | } | |
abe293a0 AC |
750 | break; |
751 | default: | |
752 | addr = -1; | |
f03b093c | 753 | sim_engine_abort (SD, CPU, cia, "ld - invalid sz %d", sz); |
abe293a0 | 754 | } |
128b5154 AC |
755 | TRACE_LD (GPR(Dest), m, S, base, offset); |
756 | const char *::function::str_sz:int sz | |
757 | switch (sz) | |
758 | { | |
759 | case 0: return ".b"; | |
760 | case 1: return ".h"; | |
761 | case 2: return ""; | |
762 | case 3: return ".d"; | |
763 | default: return "?"; | |
764 | } | |
765 | const char *::function::str_m:int m | |
766 | if (m) | |
767 | return ":m"; | |
768 | else | |
769 | return ""; | |
770 | const char *::function::str_S:int S | |
771 | if (S) | |
772 | return ":s"; | |
773 | else | |
774 | return ""; | |
abe293a0 | 775 | 31.Dest,26.Base,21.0b0100,17.m,16.sz,14.SignedOffset::::ld i |
128b5154 | 776 | "ld%s<sz> <SignedOffset> (r<Base>%s<m>), r<Dest>" |
37a684b8 | 777 | do_ld (_SD, Dest, vBase, rBase, m, sz, 0, vSignedOffset); |
abe293a0 | 778 | 31.Dest,26.Base,21.0b110100,15.m,14.sz,12.0,11.S,10.0,9./,4.IndOff::::ld r |
128b5154 | 779 | "ld%s<sz> r<IndOff>%s<S> (r<Base>%s<m>), r<Dest>" |
37a684b8 | 780 | do_ld (_SD, Dest, vBase, rBase, m, sz, S, rIndOff); |
128b5154 AC |
781 | 31.Dest,26.Base,21.0b110100,15.m,14.sz,12.1,11.S,10.0,9./+LongSignedImmediateOffset::::ld l |
782 | "ld%s<sz> 0x%08lx<LongSignedImmediateOffset>%s<S> (r<Base>%s<m>), r<Dest>" | |
37a684b8 | 783 | do_ld (_SD, Dest, vBase, rBase, m, sz, S, LongSignedImmediateOffset); |
15c16493 AC |
784 | |
785 | ||
786 | // ld.u[{.b.h.d}] | |
37a684b8 | 787 | void::function::do_ld_u:unsigned32 *rDest, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset |
abe293a0 AC |
788 | unsigned32 addr; |
789 | switch (sz) | |
790 | { | |
791 | case 0: | |
37a684b8 | 792 | addr = base + (S ? (offset << 0) : offset); |
abe293a0 AC |
793 | *rDest = MEM (unsigned, addr, 1); |
794 | break; | |
795 | case 1: | |
37a684b8 | 796 | addr = base + (S ? (offset << 1) : offset); |
abe293a0 AC |
797 | *rDest = MEM (unsigned, addr, 2); |
798 | break; | |
799 | default: | |
800 | addr = -1; | |
f03b093c | 801 | sim_engine_abort (SD, CPU, cia, "ld.u - invalid sz %d", sz); |
abe293a0 AC |
802 | } |
803 | if (m) | |
804 | *rBase = addr; | |
128b5154 | 805 | TRACE_LD (m, S, *rDest, base, offset); |
abe293a0 | 806 | 31.Dest,26.Base,21.0b0101,17.m,16.sz,14.SignedOffset::::ld.u i |
128b5154 | 807 | "ld.u%s<sz> <SignedOffset> (r<Base>%s<m>), r<Dest>" |
37a684b8 | 808 | do_ld_u (_SD, rDest, vBase, rBase, m, sz, 0, vSignedOffset); |
abe293a0 | 809 | 31.Dest,26.Base,21.0b110101,15.m,14.sz,12.0,11.S,10.0,9./,4.IndOff::::ld.u r |
128b5154 | 810 | "ld.u%s<sz> r<IndOff>%s<S> (r<Base>%s<m>), r<Dest>" |
37a684b8 | 811 | do_ld_u (_SD, rDest, vBase, rBase, m, sz, S, rIndOff); |
128b5154 AC |
812 | 31.Dest,26.Base,21.0b110101,15.m,14.sz,12.1,11.S,10.0,9./+LongSignedImmediateOffset::::ld.u l |
813 | "ld.u%s<sz> 0x%08lx<LongSignedImmediateOffset>%s<S> (r<Base>%s<m>), r<Dest>" | |
37a684b8 | 814 | do_ld_u (_SD, rDest, vBase, rBase, m, sz, S, LongSignedImmediateOffset); |
15c16493 AC |
815 | |
816 | ||
817 | // lmo | |
450be234 | 818 | 31.Dest,26.Source,21.0b111111000,12.0,11./::::lmo |
128b5154 | 819 | "lmo r<Source>, r<Dest>" |
381f42ef AC |
820 | int b; |
821 | for (b = 0; b < 32; b++) | |
37a684b8 | 822 | if (vSource & BIT32 (31 - b)) |
381f42ef | 823 | break; |
37a684b8 | 824 | TRACE_ALU2 (MY_INDEX, b, vSource); |
381f42ef AC |
825 | *rDest = b; |
826 | ||
15c16493 | 827 | |
abe293a0 | 828 | // nop - see rdcr 0, r0 |
15c16493 AC |
829 | |
830 | ||
381f42ef | 831 | void::function::do_or:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2 |
7b167b09 | 832 | unsigned32 result = Source1 | Source2; |
381f42ef | 833 | TRACE_ALU3 (MY_INDEX, result, Source1, Source2); |
7b167b09 | 834 | *rDest = result; |
15c16493 AC |
835 | |
836 | ||
837 | // or, or.tt | |
480e740c | 838 | 31.Dest,26.Source2,21.0b0010111,14.UnsignedImmediate::::or.tt i |
128b5154 | 839 | "or.tt <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 840 | do_or (_SD, rDest, vSource1, vSource2); |
480e740c | 841 | 31.Dest,26.Source2,21.0b110010111,12.0,11./,4.Source1::::or.tt r |
128b5154 | 842 | "or.tt r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 843 | do_or (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
844 | 31.Dest,26.Source2,21.0b110010111,12.1,11./+LongUnsignedImmediate::::or.tt l |
845 | "or.tt 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 846 | do_or (_SD, rDest, LongUnsignedImmediate, vSource2); |
15c16493 AC |
847 | |
848 | ||
849 | // or.ff | |
480e740c | 850 | 31.Dest,26.Source2,21.0b0011110,14.UnsignedImmediate::::or.ff i |
128b5154 | 851 | "or.ff <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 852 | do_or (_SD, rDest, ~vSource1, ~vSource2); |
480e740c | 853 | 31.Dest,26.Source2,21.0b110011110,12.0,11./,4.Source1::::or.ff r |
128b5154 | 854 | "or.ff r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 855 | do_or (_SD, rDest, ~vSource1, ~vSource2); |
128b5154 AC |
856 | 31.Dest,26.Source2,21.0b110011110,12.1,11./+LongUnsignedImmediate::::or.ff l |
857 | "or.ff 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 858 | do_or (_SD, rDest, ~LongUnsignedImmediate, ~vSource2); |
15c16493 AC |
859 | |
860 | ||
861 | // or.ft | |
480e740c | 862 | 31.Dest,26.Source2,21.0b0011101,14.UnsignedImmediate::::or.ft i |
128b5154 | 863 | "or.ft <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 864 | do_or (_SD, rDest, ~vSource1, vSource2); |
480e740c | 865 | 31.Dest,26.Source2,21.0b110011101,12.0,11./,4.Source1::::or.ft r |
128b5154 | 866 | "or.ft r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 867 | do_or (_SD, rDest, ~vSource1, vSource2); |
128b5154 AC |
868 | 31.Dest,26.Source2,21.0b110011101,12.1,11./+LongUnsignedImmediate::::or.ft l |
869 | "or.ft 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 870 | do_or (_SD, rDest, ~LongUnsignedImmediate, vSource2); |
15c16493 AC |
871 | |
872 | ||
873 | // or.tf | |
480e740c | 874 | 31.Dest,26.Source2,21.0b0011011,14.UnsignedImmediate::::or.tf i |
128b5154 | 875 | "or.tf <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 876 | do_or (_SD, rDest, vSource1, ~vSource2); |
480e740c | 877 | 31.Dest,26.Source2,21.0b110011011,12.0,11./,4.Source1::::or.tf r |
128b5154 | 878 | "or.tf r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 879 | do_or (_SD, rDest, vSource1, ~vSource2); |
128b5154 AC |
880 | 31.Dest,26.Source2,21.0b110011011,12.1,11./+LongUnsignedImmediate::::or.tf l |
881 | "or.tf 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 882 | do_or (_SD, rDest, LongUnsignedImmediate, ~vSource2); |
15c16493 AC |
883 | |
884 | ||
885 | // rdcr | |
381f42ef AC |
886 | void::function::do_rdcr:unsigned32 Dest, int cr |
887 | TRACE_SINK2 (MY_INDEX, Dest, cr); | |
888 | GPR (Dest) = CR (cr); | |
abe293a0 | 889 | 31.Dest,26.0,21.0b0000100,14.UCRN::::rdcr i |
128b5154 | 890 | "rdcr CR[<UCRN>], r<Dest>" |
381f42ef | 891 | do_rdcr (_SD, Dest, UCRN); |
abe293a0 | 892 | 31.Dest,26.0,21.0b110000100,12.0,11./,4.INDCR::::rdcr r |
128b5154 | 893 | "rdcr CR[r<INDCR>], r<Dest>" |
381f42ef | 894 | do_rdcr (_SD, Dest, UCRN); |
128b5154 AC |
895 | 31.Dest,26.0,21.0b110000100,12.1,11./+UnsignedControlRegisterNumber::::rdcr l |
896 | "rdcr CR[<UnsignedControlRegisterNumber>], r<Dest>" | |
381f42ef | 897 | do_rdcr (_SD, Dest, UnsignedControlRegisterNumber); |
15c16493 AC |
898 | |
899 | ||
900 | // rmo | |
abe293a0 | 901 | 31.Dest,26.Source,21.0b111111001,12.0,11./::::rmo |
128b5154 | 902 | "rmo r<Source>, r<Dest>" |
381f42ef AC |
903 | int b; |
904 | for (b = 0; b < 32; b++) | |
37a684b8 | 905 | if (vSource & BIT32 (b)) |
381f42ef AC |
906 | break; |
907 | if (b < 32) | |
908 | b = 31 - b; | |
37a684b8 | 909 | TRACE_ALU2 (MY_INDEX, b, vSource); |
381f42ef | 910 | *rDest = b; |
15c16493 AC |
911 | |
912 | ||
abe293a0 | 913 | // rotl - see sl.dz |
15c16493 AC |
914 | |
915 | ||
381f42ef | 916 | // rotr - see sl.dz |
15c16493 AC |
917 | |
918 | ||
abe293a0 | 919 | // shl - see sl.iz |
15c16493 AC |
920 | |
921 | ||
922 | // sl.{d|e|i}{m|s|z} | |
37a684b8 | 923 | void::function::do_shift:int Dest, unsigned32 source, int Merge, int i, int n, int EndMask, int Rotate |
c1c77d40 | 924 | /* see 10-30 for a reasonable description */ |
37a684b8 | 925 | unsigned32 input = source; |
c1c77d40 AC |
926 | unsigned32 rotated; |
927 | unsigned32 endmask; | |
928 | unsigned32 shiftmask; | |
929 | unsigned32 cm; | |
930 | int nRotate; | |
931 | /* rotate the source */ | |
932 | if (n) | |
933 | { | |
37a684b8 | 934 | rotated = ROTR32 (source, Rotate); |
c1c77d40 AC |
935 | nRotate = (- Rotate) & 31; |
936 | } | |
937 | else | |
938 | { | |
37a684b8 | 939 | rotated = ROTL32 (source, Rotate); |
c1c77d40 AC |
940 | nRotate = Rotate; |
941 | } | |
942 | /* form the end mask */ | |
943 | if (EndMask == 0) | |
450be234 | 944 | endmask = ~ (unsigned32)0; |
c1c77d40 AC |
945 | else |
946 | endmask = (1 << EndMask) - 1; | |
947 | if (i) | |
948 | endmask = ~endmask; | |
949 | /* form the shiftmask */ | |
950 | switch (Merge) | |
951 | { | |
952 | case 0: case 1: case 2: | |
450be234 | 953 | shiftmask = ~ (unsigned32)0; /* disabled */ |
c1c77d40 | 954 | break; |
07b4c0a6 AC |
955 | case 3: case 5: /* enabled - 0 -> 32 */ |
956 | if (nRotate == 0) | |
957 | shiftmask = ~ (unsigned32)0; | |
958 | else | |
959 | shiftmask = ((1 << nRotate) - 1); /* enabled - 0 -> 0 */ | |
960 | break; | |
961 | case 4: | |
962 | shiftmask = ((1 << nRotate) - 1); /* enabled - 0 -> 0 */ | |
c1c77d40 AC |
963 | break; |
964 | case 6: case 7: | |
450be234 | 965 | shiftmask = ~((1 << nRotate) - 1); /* inverted */ |
c1c77d40 AC |
966 | break; |
967 | default: | |
f03b093c AC |
968 | sim_engine_abort (SD, CPU, cia, |
969 | "0x%lx: Invalid merge (%d) for shift", | |
970 | cia.ip, source); | |
c1c77d40 AC |
971 | shiftmask = 0; |
972 | } | |
973 | /* and the composite mask */ | |
974 | cm = shiftmask & endmask; | |
975 | /* and merge */ | |
976 | switch (Merge) | |
977 | { | |
450be234 | 978 | case 0: case 3: case 6: /* zero */ |
c1c77d40 AC |
979 | GPR (Dest) = rotated & cm; |
980 | break; | |
450be234 | 981 | case 1: case 4: case 7: /* merge */ |
c1c77d40 AC |
982 | GPR (Dest) = (rotated & cm) | (GPR (Dest) & ~cm); |
983 | break; | |
450be234 | 984 | case 2: case 5: /* sign */ |
c1c77d40 AC |
985 | { |
986 | int b; | |
987 | GPR (Dest) = rotated & cm; | |
988 | for (b = 1; b <= 31; b++) | |
989 | if (!MASKED32 (cm, b, b)) | |
990 | GPR (Dest) |= INSERTED32 (EXTRACTED32 (GPR (Dest), b - 1, b - 1), | |
991 | b, b); | |
992 | } | |
993 | break; | |
994 | default: | |
f03b093c AC |
995 | sim_engine_abort (SD, CPU, cia, |
996 | "0x%lx: Invalid merge (%d)", | |
997 | cia.ip, source); | |
c1c77d40 AC |
998 | |
999 | } | |
450be234 | 1000 | TRACE_SHIFT (MY_INDEX, GPR (Dest), input, i, n, Merge, EndMask, Rotate); |
128b5154 AC |
1001 | const char *::function::str_Merge:int Merge |
1002 | switch (Merge) | |
1003 | { | |
1004 | case 0: return "dz"; | |
1005 | case 1: return "dm"; | |
1006 | case 2: return "ds"; | |
1007 | case 3: return "ez"; | |
1008 | case 4: return "em"; | |
1009 | case 5: return "es"; | |
1010 | case 6: return "iz"; | |
1011 | case 7: return "im"; | |
1012 | default: return "?"; | |
1013 | } | |
c1c77d40 | 1014 | 31.Dest,26.Source,21.0b0001,17.Merge,14./,11.i,10.n,9.EndMask,4.Rotate::::sl i |
128b5154 | 1015 | "sl.%s<Merge> <Rotate>, <EndMask>, r<Source>, r<Dest>" |
37a684b8 | 1016 | do_shift (_SD, Dest, vSource, Merge, i, n, EndMask, Rotate); |
c1c77d40 | 1017 | 31.Dest,26.Source,21.0b110001,15.Merge,12.0,11.i,10.n,9.EndMask,4.RotReg::::sl r |
128b5154 | 1018 | "sl.%s<Merge> r<RotReg>, <EndMask>, r<Source>, r<Dest>" |
37a684b8 | 1019 | do_shift (_SD, Dest, vSource, Merge, i, n, EndMask, GPR (RotReg) & 31); |
15c16493 AC |
1020 | |
1021 | ||
381f42ef | 1022 | // sli.{d|e|i}{m|s|z} - see shift |
15c16493 AC |
1023 | |
1024 | ||
381f42ef | 1025 | // sr.{d|e|i}{m|s|z} - see shift |
15c16493 AC |
1026 | |
1027 | ||
381f42ef | 1028 | // sra - see sr.es - see shift |
15c16493 AC |
1029 | |
1030 | ||
381f42ef | 1031 | // sri.{d|e|i}{m|s|z} - see shift |
15c16493 AC |
1032 | |
1033 | ||
1034 | // srl - see sr.ez | |
1035 | ||
1036 | ||
1037 | // st[{.b|.h|.d}] | |
37a684b8 | 1038 | void::function::do_st:int Source, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset |
abe293a0 AC |
1039 | unsigned32 addr; |
1040 | switch (sz) | |
1041 | { | |
1042 | case 0: | |
37a684b8 | 1043 | addr = base + (S ? (offset << 0) : offset); |
d5e2c74e | 1044 | STORE (addr, 1, GPR(Source)); |
abe293a0 AC |
1045 | break; |
1046 | case 1: | |
37a684b8 | 1047 | addr = base + (S ? (offset << 1) : offset); |
d5e2c74e | 1048 | STORE (addr, 2, GPR(Source)); |
abe293a0 AC |
1049 | break; |
1050 | case 2: | |
37a684b8 | 1051 | addr = base + (S ? (offset << 2) : offset); |
d5e2c74e | 1052 | STORE (addr, 4, GPR(Source)); |
abe293a0 AC |
1053 | break; |
1054 | case 3: | |
c445af5a AC |
1055 | { |
1056 | signed64 val; | |
1057 | if (Source & 0x1) | |
f03b093c AC |
1058 | sim_engine_abort (SD, CPU, cia, |
1059 | "0x%lx: st.d with odd source register %d", | |
1060 | cia.ip, Source); | |
37a684b8 | 1061 | addr = base + (S ? (offset << 3) : offset); |
d6fea803 | 1062 | val = U8_4 (GPR(Source + 1), GPR(Source)); |
c445af5a AC |
1063 | STORE (addr, 8, val); |
1064 | } | |
abe293a0 AC |
1065 | break; |
1066 | default: | |
1067 | addr = -1; | |
f03b093c | 1068 | sim_engine_abort (SD, CPU, cia, "st - invalid sz %d", sz); |
abe293a0 AC |
1069 | } |
1070 | if (m) | |
1071 | *rBase = addr; | |
128b5154 | 1072 | TRACE_ST (Source, m, S, base, offset); |
abe293a0 | 1073 | 31.Source,26.Base,21.0b0110,17.m,16.sz,14.SignedOffset::::st i |
128b5154 | 1074 | "st%s<sz> <SignedOffset> (r<Base>%s<m>), r<Source>" |
37a684b8 | 1075 | do_st (_SD, Source, vBase, rBase, m, sz, 0, vSignedOffset); |
abe293a0 | 1076 | 31.Source,26.Base,21.0b110110,15.m,14.sz,12.0,11.S,10.0,9./,4.IndOff::::st r |
128b5154 | 1077 | "st%s<sz> r<IndOff>%s<S> (r<Base>%s<m>), r<Source>" |
37a684b8 | 1078 | do_st (_SD, Source, vBase, rBase, m, sz, S, rIndOff); |
128b5154 AC |
1079 | 31.Source,26.Base,21.0b110110,15.m,14.sz,12.1,11.S,10.0,9./+LongSignedImmediateOffset::::st l |
1080 | "st%s<sz> 0x%08lx<LongSignedImmediateOffset>%s<S> (r<Base>%s<m>), r<Source>" | |
37a684b8 | 1081 | do_st (_SD, Source, vBase, rBase, m, sz, S, LongSignedImmediateOffset); |
15c16493 AC |
1082 | |
1083 | ||
1084 | // sub | |
381f42ef | 1085 | void::function::do_sub:signed32 *rDest, signed32 Source1, signed32 Source2 |
abe293a0 AC |
1086 | ALU_BEGIN (Source1); |
1087 | ALU_SUB (Source2); | |
7b167b09 | 1088 | ALU_END (*rDest); |
381f42ef | 1089 | TRACE_ALU3 (MY_INDEX, *rDest, Source1, Source2); |
abe293a0 | 1090 | 31.Dest,26.Source2,21.0b101101,15.0,14.SignedImmediate::::sub i |
128b5154 | 1091 | "sub <SignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 1092 | do_sub (_SD, rDest, vSource1, vSource2); |
abe293a0 | 1093 | 31.Dest,26.Source2,21.0b11101101,13.0,12.0,11./,4.Source1::::sub r |
128b5154 | 1094 | "sub r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 1095 | do_sub (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
1096 | 31.Dest,26.Source2,21.0b11101101,13.0,12.1,11./+LongSignedImmediate::::sub l |
1097 | "sub 0x%08lx<LongSignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 1098 | do_sub (_SD, rDest, LongSignedImmediate, vSource2); |
15c16493 AC |
1099 | |
1100 | ||
1101 | // subu | |
450be234 | 1102 | void::function::do_subu:unsigned32 *rDest, unsigned32 Source1, signed32 Source2 |
7b167b09 | 1103 | unsigned32 result = Source1 - Source2; |
381f42ef | 1104 | TRACE_ALU3 (MY_INDEX, result, Source1, Source2); |
7b167b09 | 1105 | *rDest = result; |
d5e2c74e | 1106 | // NOTE - the book has 15.1 which conflicts with subu. |
4e95b94e | 1107 | 31.Dest,26.Source2,21.0b101101,15.1,14.SignedImmediate::::subu i |
128b5154 | 1108 | "subu <SignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 1109 | do_subu (_SD, rDest, vSource1, vSource2); |
abe293a0 | 1110 | 31.Dest,26.Source2,21.0b11101101,13.1,12.0,11./,4.Source1::::subu r |
128b5154 | 1111 | "subu r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 1112 | do_subu (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
1113 | 31.Dest,26.Source2,21.0b11101101,13.1,12.1,11./+LongSignedImmediate::::subu l |
1114 | "subu 0x%08lx<LongSignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 1115 | do_subu (_SD, rDest, LongSignedImmediate, vSource2); |
15c16493 AC |
1116 | |
1117 | ||
1118 | // swcr | |
37a684b8 | 1119 | void::function::do_swcr:int Dest, signed32 source, signed32 cr |
381f42ef AC |
1120 | tic80_control_regs reg = tic80_index2cr (cr); |
1121 | /* cache the old CR value */ | |
1122 | unsigned32 old_cr = CR (cr); | |
1123 | /* Handle the write if allowed */ | |
1124 | if (cr >= 0x4000 || !(CPU)->is_user_mode) | |
1125 | switch (reg) | |
1126 | { | |
1127 | case INTPEN_CR: | |
37a684b8 | 1128 | CR (cr) &= ~source; |
381f42ef AC |
1129 | break; |
1130 | default: | |
37a684b8 | 1131 | CR (cr) = source; |
381f42ef AC |
1132 | break; |
1133 | } | |
1134 | /* Finish off the read */ | |
1135 | GPR (Dest) = old_cr; | |
37a684b8 | 1136 | TRACE_SINK3 (MY_INDEX, source, cr, Dest); |
381f42ef | 1137 | 31.Dest,26.Source,21.0b000010,15.1,14.UCRN::::swcr i |
128b5154 | 1138 | "swcr CR[<UCRN>], r<Dest>" |
37a684b8 | 1139 | do_swcr (_SD, Dest, vSource, UCRN); |
abe293a0 | 1140 | 31.Dest,26.Source,21.0b11000010,13.1,12.0,11./,4.INDCR::::swcr r |
128b5154 | 1141 | "swcr CR[r<INDCR>], r<Dest>" |
37a684b8 | 1142 | do_swcr (_SD, Dest, vSource, UCRN); |
128b5154 AC |
1143 | 31.Dest,26.Source,21.0b11000010,13.1,12.1,11./+LongUnsignedControlRegisterNumber::::swcr l |
1144 | "swcr CR[<LongUnsignedControlRegisterNumber>], r<Dest>" | |
1145 | do_swcr (_SD, Dest, vSource, LongUnsignedControlRegisterNumber); | |
15c16493 AC |
1146 | |
1147 | ||
1148 | // trap | |
381f42ef | 1149 | void::function::do_trap:unsigned32 trap_number |
1b6f4dde | 1150 | int i; |
381f42ef | 1151 | TRACE_SINK1 (MY_INDEX, trap_number); |
d5e2c74e | 1152 | switch (trap_number) |
15c16493 | 1153 | { |
d5e2c74e AC |
1154 | case 72: |
1155 | switch (GPR(15)) | |
15c16493 AC |
1156 | { |
1157 | case 1: /* EXIT */ | |
1158 | { | |
f03b093c | 1159 | sim_engine_halt (SD, CPU, NULL, cia, sim_exited, GPR(2)); |
15c16493 AC |
1160 | break; |
1161 | } | |
1162 | case 4: /* WRITE */ | |
1163 | { | |
1164 | int i; | |
3971886a AC |
1165 | if (GPR(2) == 1) |
1166 | for (i = 0; i < GPR(6); i++) | |
1167 | { | |
1168 | char c; | |
1169 | c = MEM (unsigned, GPR(4) + i, 1); | |
1170 | sim_io_write_stdout (SD, &c, 1); | |
1171 | } | |
1172 | else if (GPR(2) == 2) | |
1173 | for (i = 0; i < GPR(6); i++) | |
1174 | { | |
1175 | char c; | |
1176 | c = MEM (unsigned, GPR(4) + i, 1); | |
1177 | sim_io_write_stderr (SD, &c, 1); | |
1178 | } | |
1179 | else | |
f03b093c AC |
1180 | sim_engine_abort (SD, CPU, cia, |
1181 | "0x%lx: write to invalid fid %d", | |
1182 | (unsigned long) cia.ip, GPR(2)); | |
d5e2c74e | 1183 | GPR(2) = GPR(6); |
15c16493 AC |
1184 | break; |
1185 | } | |
8c5b6ead MM |
1186 | case 20: /* GETPID */ |
1187 | { | |
1188 | GPR(2) = getpid (); | |
1189 | break; | |
1190 | } | |
1191 | case 37: /* KILL */ | |
1192 | if (GPR (2) != getpid ()) | |
1193 | { | |
1194 | int ret = kill (GPR(2), GPR(4)); | |
1195 | if (ret < 0) | |
1196 | ret = -errno; | |
1197 | GPR (2) = ret; | |
1198 | break; | |
1199 | } | |
1200 | else | |
1201 | { | |
1202 | sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, GPR(4)); | |
1203 | break; | |
1204 | } | |
15c16493 | 1205 | default: |
1b6f4dde MM |
1206 | /* For system calls which are defined, just return EINVAL instead of trapping */ |
1207 | if (GPR(15) <= 204) | |
1208 | { | |
1209 | GPR(2) = -22; /* -EINVAL */ | |
1210 | break; | |
1211 | } | |
f03b093c AC |
1212 | sim_engine_abort (SD, CPU, cia, |
1213 | "0x%lx: unknown syscall %d", | |
1214 | (unsigned long) cia.ip, GPR(15)); | |
15c16493 | 1215 | } |
d5e2c74e | 1216 | break; |
c1c77d40 | 1217 | case 73: |
f03b093c | 1218 | sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIGTRAP); |
1b6f4dde MM |
1219 | |
1220 | /* Add a few traps for now to print the register state */ | |
1221 | case 74: | |
1222 | case 75: | |
1223 | case 76: | |
1224 | case 77: | |
1225 | case 78: | |
1226 | case 79: | |
1227 | if (!TRACE_ALU_P (CPU)) | |
1228 | trace_one_insn (SD, CPU, cia.ip, 1, itable[MY_INDEX].file, | |
1229 | itable[MY_INDEX].line_nr, "trap", | |
2310e3c2 | 1230 | "Trap %ld", (long) trap_number); |
1b6f4dde MM |
1231 | |
1232 | for (i = 0; i < 32; i++) | |
1233 | sim_io_eprintf (SD, "%s0x%.8lx%s", ((i % 8) == 0) ? "\t" : " ", (long)GPR(i), | |
1234 | (((i+1) % 8) == 0) ? "\n" : ""); | |
1235 | sim_io_write_stderr (SD, "\n", 1); | |
1236 | break; | |
1237 | ||
d5e2c74e | 1238 | default: |
f03b093c AC |
1239 | sim_engine_abort (SD, CPU, cia, |
1240 | "0x%lx: unsupported trap %d", | |
1241 | (unsigned long) cia.ip, trap_number); | |
15c16493 AC |
1242 | } |
1243 | 31./,27.0,26./,21.0b0000001,14.UTN::::trap i | |
128b5154 | 1244 | "trap <UTN>" |
381f42ef | 1245 | do_trap (_SD, UTN); |
15c16493 | 1246 | 31./,27.0,26./,21.0b110000001,12.0,11./,4.INDTR::::trap r |
128b5154 | 1247 | "trap r<INDTR>" |
381f42ef | 1248 | do_trap (_SD, UTN); |
128b5154 AC |
1249 | 31./,27.0,26./,21.0b110000001,12.1,11./+UTN::::trap l |
1250 | "trap 0x%08lx<UTN>" | |
381f42ef | 1251 | do_trap (_SD, UTN); |
15c16493 AC |
1252 | |
1253 | ||
1254 | // vadd.{s|d}{s|d} | |
381f42ef AC |
1255 | 31.*,26.Dest,21.0b11110,16./,15.0b000,12.0,11./,10.*,9.*,7.PD,6.*,5.P1,4.Source::f::vadd r |
1256 | 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 |
1257 | |
1258 | ||
abe293a0 | 1259 | // vld{0|1}.{s|d} - see above - same instruction |
381f42ef | 1260 | #31.Dest,26.*,21.0b11110,16.*,10.1,9.S,8.*,6.p,7.******::f::vld |
15c16493 AC |
1261 | |
1262 | ||
1263 | // vmac.ss{s|d} | |
381f42ef AC |
1264 | #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 |
1265 | 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 | |
1266 | #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 | |
1267 | 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 |
1268 | |
1269 | ||
1270 | // vmpy.{s|d}{s|d} | |
381f42ef AC |
1271 | 31.*,26.Dest,21.0b11110,16./,15.0b010,12.0,11./,10.*,8.*,7.PD,6.*,5.P1,4.Source::f::vmpy r |
1272 | 31.*,26.Dest,21.0b11110,16./,15.0b010,12.1,11./,10.*,8.*,7.PD,6.*,5.P1,4./::f::vmpy l | |
15c16493 AC |
1273 | |
1274 | ||
1275 | // vmsc.ss{s|d} | |
381f42ef AC |
1276 | #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 |
1277 | 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 | |
1278 | #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 | |
1279 | 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 |
1280 | |
1281 | ||
1282 | // vmsub.{s|d}{s|d} | |
381f42ef AC |
1283 | 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 |
1284 | 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 |
1285 | |
1286 | ||
1287 | // vrnd.{s|d}{s|d} | |
381f42ef AC |
1288 | 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 |
1289 | 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 |
1290 | |
1291 | ||
1292 | // vrnd.{i|u}{s|d} | |
381f42ef AC |
1293 | 31.*,26.Dest,21.0b11110,16./,15.0b101,12.0,11./,10.*,8./,7.PD,6.*,5.P1,4.Source::f::vrnd i r |
1294 | 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 |
1295 | |
1296 | ||
abe293a0 | 1297 | // vst.{s|d} - see above - same instruction |
381f42ef | 1298 | #31.Source,26.*,21.0b11110,16.*,10.0,9.S,8.*,6.1,5.*::f::vst |
15c16493 AC |
1299 | |
1300 | ||
1301 | // vsub.{i|u}{s|d} | |
381f42ef AC |
1302 | 31.*,26.Dest,21.0b11110,16./,15.0b001,12.0,11./,10.*,8./,7.PD,6.*,5.P1,4.Source::f::vsub r |
1303 | 31.*,26.Dest,21.0b11110,16./,15.0b001,12.1,11./,10.*,8./,7.PD,6.*,5.P1,4./::f::vsub l | |
15c16493 AC |
1304 | |
1305 | ||
abe293a0 | 1306 | // wrcr - see swcr, creg, source, r0 |
15c16493 AC |
1307 | |
1308 | ||
1309 | // xnor | |
37a684b8 AC |
1310 | void::function::do_xnor:signed32 *rDest, signed32 source1, signed32 source2 |
1311 | unsigned32 result = ~ (source1 ^ source2); | |
1312 | TRACE_ALU3 (MY_INDEX, result, source1, source2); | |
7b167b09 | 1313 | *rDest = result; |
abe293a0 | 1314 | 31.Dest,26.Source2,21.0b0011001,14.UnsignedImmediate::::xnor i |
128b5154 | 1315 | "xnor <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 1316 | do_xnor (_SD, rDest, vSource1, vSource2); |
abe293a0 | 1317 | 31.Dest,26.Source2,21.0b110011001,12.0,11./,4.Source1::::xnor r |
128b5154 | 1318 | "xnor r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 1319 | do_xnor (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
1320 | 31.Dest,26.Source2,21.0b110011001,12.1,11./+LongUnsignedImmediate::::xnor l |
1321 | "xnor 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 1322 | do_xnor (_SD, rDest, LongUnsignedImmediate, vSource2); |
15c16493 AC |
1323 | |
1324 | ||
1325 | // xor | |
37a684b8 AC |
1326 | void::function::do_xor:signed32 *rDest, signed32 source1, signed32 source2 |
1327 | unsigned32 result = source1 ^ source2; | |
1328 | TRACE_ALU3 (MY_INDEX, result, source1, source2); | |
7b167b09 | 1329 | *rDest = result; |
480e740c | 1330 | 31.Dest,26.Source2,21.0b0010110,14.UnsignedImmediate::::xor i |
128b5154 | 1331 | "xor <UnsignedImmediate>, r<Source2>, r<Dest>" |
37a684b8 | 1332 | do_xor (_SD, rDest, vSource1, vSource2); |
89d1a478 | 1333 | 31.Dest,26.Source2,21.0b110010110,12.0,11./,4.Source1::::xor r |
128b5154 | 1334 | "xor r<Source1>, r<Source2>, r<Dest>" |
37a684b8 | 1335 | do_xor (_SD, rDest, vSource1, vSource2); |
128b5154 AC |
1336 | 31.Dest,26.Source2,21.0b110010110,12.1,11./+LongUnsignedImmediate::::xor l |
1337 | "xor 0x%08lx<LongUnsignedImmediate>, r<Source2>, r<Dest>" | |
37a684b8 | 1338 | do_xor (_SD, rDest, LongUnsignedImmediate, vSource2); |