1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz
3 /***************************************************************************
4
5 e132xsfe.cpp
6
7 Front end for Hyperstone recompiler
8
9 ***************************************************************************/
10
11 #include "emu.h"
12 #include "e132xsfe.h"
13 #include "32xsdefs.h"
14
15 #define FE_FP ((m_cpu->m_core->global_regs[1] & 0xfe000000) >> 25)
16 #define FE_FL (m_cpu->m_core->fl_lut[((m_cpu->m_core->global_regs[1] >> 21) & 0xf)])
17 #define FE_DST_CODE ((op & 0xf0) >> 4)
18 #define FE_SRC_CODE (op & 0x0f)
19 #define SR_CODE (1 << 1)
20
21 /***************************************************************************
22 INSTRUCTION PARSERS
23 ***************************************************************************/
24
e132xs_frontend(hyperstone_device * e132xs,uint32_t window_start,uint32_t window_end,uint32_t max_sequence)25 e132xs_frontend::e132xs_frontend(hyperstone_device *e132xs, uint32_t window_start, uint32_t window_end, uint32_t max_sequence)
26 : drc_frontend(*e132xs, window_start, window_end, max_sequence)
27 , m_cpu(e132xs)
28 {
29 }
30
read_word(opcode_desc & desc)31 inline uint16_t e132xs_frontend::read_word(opcode_desc &desc)
32 {
33 return m_cpu->m_pr16(desc.physpc);
34 }
35
read_imm1(opcode_desc & desc)36 inline uint16_t e132xs_frontend::read_imm1(opcode_desc &desc)
37 {
38 return m_cpu->m_pr16(desc.physpc + 2);
39 }
40
read_imm2(opcode_desc & desc)41 inline uint16_t e132xs_frontend::read_imm2(opcode_desc &desc)
42 {
43 return m_cpu->m_pr16(desc.physpc + 4);
44 }
45
read_ldstxx_imm(opcode_desc & desc)46 inline uint32_t e132xs_frontend::read_ldstxx_imm(opcode_desc &desc)
47 {
48 const uint16_t imm1 = read_imm1(desc);
49 uint32_t extra_s;
50 if (imm1 & 0x8000)
51 {
52 extra_s = read_imm2(desc);
53 extra_s |= ((imm1 & 0xfff) << 16);
54
55 if (imm1 & 0x4000)
56 extra_s |= 0xf0000000;
57 }
58 else
59 {
60 extra_s = imm1 & 0xfff;
61
62 if (imm1 & 0x4000)
63 extra_s |= 0xfffff000;
64 }
65 return extra_s;
66 }
67
read_limm(opcode_desc & desc,uint16_t op)68 inline uint32_t e132xs_frontend::read_limm(opcode_desc &desc, uint16_t op)
69 {
70 static const int32_t immediate_values[16] =
71 {
72 16, 0, 0, 0, 32, 64, 128, int32_t(0x80000000),
73 -8, -7, -6, -5, -4, -3, -2, -1
74 };
75
76 uint8_t nybble = op & 0xf;
77 switch (nybble)
78 {
79 case 0:
80 return 16;
81 case 1:
82 desc.length = 6;
83 return (read_imm1(desc) << 16) | read_imm2(desc);
84 case 2:
85 desc.length = 4;
86 return read_imm1(desc);
87 case 3:
88 desc.length = 4;
89 return 0xffff0000 | read_imm1(desc);
90 default:
91 return immediate_values[nybble];
92 }
93 }
94
decode_pcrel(opcode_desc & desc,uint16_t op)95 inline int32_t e132xs_frontend::decode_pcrel(opcode_desc &desc, uint16_t op)
96 {
97 if (op & 0x80)
98 {
99 uint16_t next = read_imm1(desc);
100
101 desc.length = 4;
102
103 int32_t offset = (op & 0x7f) << 16;
104 offset |= (next & 0xfffe);
105
106 if (next & 1)
107 offset |= 0xff800000;
108
109 return offset;
110 }
111 else
112 {
113 int32_t offset = op & 0x7e;
114 if (op & 1)
115 offset |= 0xffffff80;
116 return offset;
117 }
118 }
119
decode_call(opcode_desc & desc)120 inline int32_t e132xs_frontend::decode_call(opcode_desc &desc)
121 {
122 const uint16_t imm_1 = read_imm1(desc);
123 int32_t extra_s = 0;
124 if (imm_1 & 0x8000)
125 {
126 desc.length = 6;
127 extra_s = read_imm2(desc);
128 extra_s |= ((imm_1 & 0x3fff) << 16);
129
130 if (imm_1 & 0x4000)
131 extra_s |= 0xc0000000;
132 }
133 else
134 {
135 desc.length = 4;
136 extra_s = imm_1 & 0x3fff;
137 if (imm_1 & 0x4000)
138 extra_s |= 0xffffc000;
139 }
140 return extra_s;
141 }
142
143
144 /*-------------------------------------------------
145 describe - build a description of a single
146 instruction
147 -------------------------------------------------*/
148
describe(opcode_desc & desc,const opcode_desc * prev)149 bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
150 {
151 uint16_t op = desc.opptr.w[0] = read_word(desc);
152
153 /* most instructions are 2 bytes and a single cycle */
154 desc.length = 2;
155 desc.delayslots = 0;
156
157 const uint32_t fp = FE_FP;
158 const uint32_t gdst_code = FE_DST_CODE;
159 const uint32_t gdstf_code = gdst_code + 1;
160 const uint32_t gsrc_code = FE_SRC_CODE;
161 const uint32_t gsrcf_code = gsrc_code + 1;
162 const uint32_t ldst_code = (gdst_code + fp) & 0x1f;
163 const uint32_t ldstf_code = (gdstf_code + fp) & 0x1f;
164 const uint32_t lsrc_code = (gsrc_code + fp) & 0x1f;
165 const uint32_t lsrcf_code = (gsrcf_code + fp) & 0x1f;
166 const uint32_t ldst_group = 1 + (((FE_DST_CODE + fp) & 0x20) >> 5);
167 const uint32_t ldstf_group = 1 + (((FE_DST_CODE + fp + 1) & 0x20) >> 5);
168 const uint32_t lsrc_group = 1 + (((FE_SRC_CODE + fp) & 0x20) >> 5);
169 const uint32_t lsrcf_group = 1 + ((FE_SRC_CODE + fp + 1) >> 5);
170
171 switch (op >> 8)
172 {
173 case 0x00: // chk global,global
174 desc.regin[0] |= 1 << gdst_code;
175 desc.regin[0] |= 1 << gsrc_code;
176 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
177 break;
178 case 0x01: // chk global,local
179 desc.regin[0] |= SR_CODE;
180 desc.regin[0] |= 1 << gdst_code;
181 desc.regin[lsrc_group] |= 1 << lsrc_code;
182 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
183 break;
184 case 0x02: // chk local,global
185 desc.regin[0] |= SR_CODE;
186 desc.regin[ldst_group] |= 1 << ldst_code;
187 desc.regin[0] |= 1 << gsrc_code;
188 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
189 break;
190 case 0x03: // chk local,local
191 desc.regin[0] |= SR_CODE;
192 desc.regin[ldst_group] |= 1 << ldst_code;
193 desc.regin[lsrc_group] |= 1 << lsrc_code;
194 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
195 break;
196 case 0x04: // movd global,global
197 desc.regin[0] |= 1 << gsrc_code;
198 desc.regin[0] |= 1 << gsrcf_code;
199 desc.regout[0] |= 1 << gdst_code;
200 desc.regout[0] |= 1 << gdstf_code;
201 if (gdst_code == 0)
202 {
203 desc.regout[1] = 0xffffffff;
204 desc.regout[2] = 0xffffffff;
205 desc.targetpc = BRANCH_TARGET_DYNAMIC;
206 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION;
207 }
208 desc.regout[0] |= SR_CODE;
209 break;
210 case 0x05: // movd global,local
211 desc.regin[0] |= SR_CODE;
212 desc.regin[lsrc_group] |= 1 << lsrc_code;
213 desc.regin[lsrcf_group] |= 1 << lsrcf_code;
214 desc.regout[0] |= 1 << gdst_code;
215 desc.regout[0] |= 1 << gdstf_code;
216 if (gdst_code == 0)
217 {
218 desc.regout[1] = 0xffffffff;
219 desc.regout[2] = 0xffffffff;
220 desc.targetpc = BRANCH_TARGET_DYNAMIC;
221 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION;
222 }
223 desc.regout[0] |= SR_CODE;
224 break;
225 case 0x06: // movd local,global
226 desc.regin[0] |= SR_CODE;
227 desc.regin[0] |= 1 << gsrc_code;
228 desc.regin[0] |= 1 << gsrcf_code;
229 desc.regout[ldst_group] |= 1 << ldst_code;
230 desc.regout[ldstf_group] |= 1 << ldstf_code;
231 desc.regout[0] |= SR_CODE;
232 break;
233 case 0x07: // movd local,local
234 desc.regin[0] |= SR_CODE;
235 desc.regin[lsrc_group] |= 1 << lsrc_code;
236 desc.regin[lsrcf_group] |= 1 << lsrcf_code;
237 desc.regout[ldst_group] |= 1 << ldst_code;
238 desc.regout[ldstf_group] |= 1 << ldstf_code;
239 desc.regout[0] |= SR_CODE;
240 break;
241 case 0x08: // divu global,global
242 case 0x0c: // divs global,global
243 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
244 desc.regin[0] |= 1 << gsrc_code;
245 desc.regin[0] |= 1 << gdst_code;
246 desc.regin[0] |= 1 << gdstf_code;
247 desc.regout[0] |= 1 << gdst_code;
248 desc.regout[0] |= 1 << gdstf_code;
249 desc.regout[0] |= SR_CODE;
250 break;
251 case 0x09: // divu global,local
252 case 0x0d: // divs global,local
253 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
254 desc.regin[0] |= SR_CODE;
255 desc.regin[lsrc_group] |= 1 << lsrc_code;
256 desc.regin[0] |= 1 << gdst_code;
257 desc.regin[0] |= 1 << gdstf_code;
258 desc.regout[0] |= 1 << gdst_code;
259 desc.regout[0] |= 1 << gdstf_code;
260 desc.regout[0] |= SR_CODE;
261 break;
262 case 0x0a: // divu local,global
263 case 0x0e: // divs local,global
264 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
265 desc.regin[0] |= SR_CODE;
266 desc.regin[0] |= 1 << gsrc_code;
267 desc.regin[ldst_group] |= 1 << ldst_code;
268 desc.regin[ldstf_group] |= 1 << ldstf_code;
269 desc.regout[ldst_group] |= 1 << ldst_code;
270 desc.regout[ldstf_group] |= 1 << ldstf_code;
271 desc.regout[0] |= SR_CODE;
272 break;
273 case 0x0b: // divu local,local
274 case 0x0f: // divs local,local
275 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
276 desc.regin[0] |= SR_CODE;
277 desc.regin[lsrc_group] |= 1 << lsrc_code;
278 desc.regin[ldst_group] |= 1 << ldst_code;
279 desc.regin[ldstf_group] |= 1 << ldstf_code;
280 desc.regout[ldst_group] |= 1 << ldst_code;
281 desc.regout[ldstf_group] |= 1 << ldstf_code;
282 desc.regout[0] |= SR_CODE;
283 break;
284 case 0x10: // xm global,global
285 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
286 desc.regin[0] |= 1 << gsrc_code;
287 desc.regout[0] |= 1 << gdst_code;
288 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
289 break;
290 case 0x11: // xm global,local
291 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
292 desc.regin[0] |= SR_CODE;
293 desc.regin[lsrc_group] |= 1 << lsrc_code;
294 desc.regout[0] |= 1 << gdst_code;
295 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
296 break;
297 case 0x12: // xm local,global
298 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
299 desc.regin[0] |= SR_CODE;
300 desc.regin[0] |= 1 << gsrc_code;
301 desc.regout[ldst_group] |= 1 << ldst_code;
302 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
303 break;
304 case 0x13: // xm local,local
305 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
306 desc.regin[0] |= SR_CODE;
307 desc.regin[lsrc_group] |= 1 << lsrc_code;
308 desc.regout[ldst_group] |= 1 << ldst_code;
309 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
310 break;
311 case 0x14: // mask global,global
312 desc.regin[0] |= 1 << gsrc_code;
313 desc.regout[0] |= 1 << gdst_code;
314 desc.regout[0] |= SR_CODE;
315 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
316 break;
317 case 0x15: // mask global,local
318 desc.regin[0] |= SR_CODE;
319 desc.regin[lsrc_group] |= 1 << lsrc_code;
320 desc.regout[0] |= 1 << gdst_code;
321 desc.regout[0] |= SR_CODE;
322 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
323 break;
324 case 0x16: // mask local,global
325 desc.regin[0] |= SR_CODE;
326 desc.regin[0] |= 1 << gsrc_code;
327 desc.regout[ldst_group] |= 1 << ldst_code;
328 desc.regout[0] |= SR_CODE;
329 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
330 break;
331 case 0x17: // mask local,local
332 desc.regin[0] |= SR_CODE;
333 desc.regin[lsrc_group] |= 1 << lsrc_code;
334 desc.regout[ldst_group] |= 1 << ldst_code;
335 desc.regout[0] |= SR_CODE;
336 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
337 break;
338 case 0x18: // sum global,global
339 case 0x1c: // sums global,global
340 desc.regin[0] |= 1 << gsrc_code;
341 desc.regout[0] |= 1 << gdst_code;
342 desc.regout[0] |= SR_CODE;
343 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
344 if (op & 0x4 && gsrc_code != SR_REGISTER) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
345 break;
346 case 0x19: // sum global,local
347 case 0x1d: // sums global,local
348 desc.regin[0] |= SR_CODE;
349 desc.regin[lsrc_group] |= 1 << lsrc_code;
350 desc.regout[0] |= 1 << gdst_code;
351 desc.regout[0] |= SR_CODE;
352 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
353 if (op & 0x4) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
354 break;
355 case 0x1a: // sum local,global
356 case 0x1e: // sums local,global
357 desc.regin[0] |= SR_CODE;
358 desc.regin[0] |= 1 << gsrc_code;
359 desc.regout[ldst_group] |= 1 << ldst_code;
360 desc.regout[0] |= SR_CODE;
361 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
362 if (op & 0x4 && gsrc_code != SR_REGISTER) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
363 break;
364 case 0x1b: // sum local,local
365 case 0x1f: // sums local,local
366 desc.regin[0] |= SR_CODE;
367 desc.regin[lsrc_group] |= 1 << lsrc_code;
368 desc.regout[ldst_group] |= 1 << ldst_code;
369 desc.regout[0] |= SR_CODE;
370 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
371 if (op & 0x4) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
372 break;
373 case 0x20: // cmp global,global
374 case 0x30: // cmpb global,global
375 desc.regin[0] |= 1 << gsrc_code;
376 desc.regin[0] |= 1 << gdst_code;
377 desc.regout[0] |= SR_CODE;
378 break;
379 case 0x21: // cmp global,local
380 case 0x31: // cmpb global,local
381 desc.regin[0] |= SR_CODE;
382 desc.regin[lsrc_group] |= 1 << lsrc_code;
383 desc.regin[0] |= 1 << gdst_code;
384 desc.regout[0] |= SR_CODE;
385 break;
386 case 0x22: // cmp local,global
387 case 0x32: // cmpb local,global
388 desc.regin[0] |= SR_CODE;
389 desc.regin[0] |= 1 << gsrc_code;
390 desc.regin[ldst_group] |= 1 << ldst_code;
391 desc.regout[0] |= SR_CODE;
392 break;
393 case 0x23: // cmp local,local
394 case 0x33: // cmpb local,local
395 desc.regin[0] |= SR_CODE;
396 desc.regin[lsrc_group] |= 1 << lsrc_code;
397 desc.regin[ldst_group] |= 1 << ldst_code;
398 desc.regout[0] |= SR_CODE;
399 break;
400 case 0x24: // mov global,global
401 desc.regin[0] |= SR_CODE;
402 desc.regin[0] |= 1 << gsrc_code;
403 desc.regin[0] |= 1 << (gsrc_code + 16);
404 desc.regout[0] |= 1 << gdst_code;
405 desc.regout[0] |= SR_CODE;
406 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
407 if (gdst_code == PC_REGISTER)
408 {
409 desc.targetpc = BRANCH_TARGET_DYNAMIC;
410 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
411 }
412 else if (gdst_code == 5) // TPR_REGISTER & 0xf
413 {
414 desc.flags |= OPFLAG_END_SEQUENCE;
415 }
416 break;
417 case 0x25: // mov global,local
418 desc.regin[0] |= SR_CODE;
419 desc.regin[lsrc_group] |= 1 << lsrc_code;
420 desc.regout[0] |= 1 << gdst_code;
421 desc.regout[0] |= SR_CODE;
422 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
423 if (gdst_code == PC_REGISTER)
424 {
425 desc.targetpc = BRANCH_TARGET_DYNAMIC;
426 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
427 }
428 else if (gdst_code == 5) // TPR_REGISTER & 0xf
429 {
430 desc.flags |= OPFLAG_END_SEQUENCE;
431 }
432 break;
433 case 0x26: // mov local,global
434 desc.regin[0] |= SR_CODE;
435 desc.regin[0] |= 1 << gsrc_code;
436 desc.regin[0] |= 1 << (gsrc_code + 16);
437 desc.regout[ldst_group] |= 1 << ldst_code;
438 desc.regout[0] |= SR_CODE;
439 break;
440 case 0x27: // mov local,local
441 desc.regin[0] |= SR_CODE;
442 desc.regin[lsrc_group] |= 1 << lsrc_code;
443 desc.regout[ldst_group] |= 1 << ldst_code;
444 desc.regout[0] |= SR_CODE;
445 break;
446 case 0x28: // add global,global
447 case 0x2c: // adds global,global
448 case 0x48: // sub global,global
449 case 0x4c: // subs global,global
450 desc.regin[0] |= 1 << gsrc_code;
451 desc.regin[0] |= 1 << gdst_code;
452 desc.regout[0] |= 1 << gdst_code;
453 desc.regout[0] |= SR_CODE;
454 if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // adds, subs
455 if (gdst_code == PC_REGISTER)
456 {
457 desc.targetpc = BRANCH_TARGET_DYNAMIC;
458 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
459 }
460 break;
461 case 0x29: // add global,local
462 case 0x2d: // adds global,local
463 case 0x49: // sub global,local
464 case 0x4d: // subs global,local
465 desc.regin[0] |= SR_CODE;
466 desc.regin[lsrc_group] |= 1 << lsrc_code;
467 desc.regin[0] |= 1 << gdst_code;
468 desc.regout[0] |= 1 << gdst_code;
469 desc.regout[0] |= SR_CODE;
470 if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // adds, subs
471 if (gdst_code == PC_REGISTER)
472 {
473 desc.targetpc = BRANCH_TARGET_DYNAMIC;
474 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
475 }
476 break;
477 case 0x2a: // add local,global
478 case 0x2e: // adds local,global
479 case 0x4a: // sub local,global
480 case 0x4e: // subs local,global
481 desc.regin[0] |= SR_CODE;
482 desc.regin[0] |= 1 << gsrc_code;
483 desc.regin[ldst_group] |= 1 << ldst_code;
484 desc.regout[ldst_group] |= 1 << ldst_code;
485 desc.regout[0] |= SR_CODE;
486 if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // adds, subs
487 break;
488 case 0x2b: // add local,local
489 case 0x2f: // adds local,local
490 case 0x4b: // sub local,local
491 case 0x4f: // subs local,local
492 desc.regin[0] |= SR_CODE;
493 desc.regin[lsrc_group] |= 1 << lsrc_code;
494 desc.regin[ldst_group] |= 1 << ldst_code;
495 desc.regout[ldst_group] |= 1 << ldst_code;
496 desc.regout[0] |= SR_CODE;
497 if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // adds, subs
498 break;
499 case 0x34: // andn global,global
500 case 0x38: // or global,global
501 case 0x3c: // xor global,global
502 case 0x54: // and global,global
503 desc.regin[0] |= 1 << gsrc_code;
504 desc.regin[0] |= 1 << gdst_code;
505 desc.regout[0] |= 1 << gdst_code;
506 desc.regout[0] |= SR_CODE;
507 if (gdst_code == PC_REGISTER)
508 {
509 desc.targetpc = BRANCH_TARGET_DYNAMIC;
510 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
511 }
512 break;
513 case 0x35: // andn global,local
514 case 0x39: // or global,local
515 case 0x3d: // xor global,local
516 case 0x55: // and global,local
517 desc.regin[0] |= SR_CODE;
518 desc.regin[lsrc_group] |= 1 << lsrc_code;
519 desc.regin[0] |= 1 << gdst_code;
520 desc.regout[0] |= 1 << gdst_code;
521 desc.regout[0] |= SR_CODE;
522 if (gdst_code == PC_REGISTER)
523 {
524 desc.targetpc = BRANCH_TARGET_DYNAMIC;
525 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
526 }
527 break;
528 case 0x36: // andn local,global
529 case 0x3a: // or local,global
530 case 0x3e: // xor local,global
531 case 0x56: // and local,global
532 desc.regin[0] |= SR_CODE;
533 desc.regin[0] |= 1 << gsrc_code;
534 desc.regin[ldst_group] |= 1 << ldst_code;
535 desc.regout[ldst_group] |= 1 << ldst_code;
536 desc.regout[0] |= SR_CODE;
537 break;
538 case 0x37: // andn local,local
539 case 0x3b: // or local,local
540 case 0x3f: // xor local,local
541 case 0x57: // and local,local
542 desc.regin[0] |= SR_CODE;
543 desc.regin[lsrc_group] |= 1 << lsrc_code;
544 desc.regin[ldst_group] |= 1 << ldst_code;
545 desc.regout[ldst_group] |= 1 << ldst_code;
546 desc.regout[0] |= SR_CODE;
547 break;
548 case 0x40: // subc global,global
549 case 0x50: // addc global,global
550 desc.regin[0] |= SR_CODE;
551 desc.regin[0] |= 1 << gsrc_code;
552 desc.regin[0] |= 1 << gdst_code;
553 desc.regout[0] |= 1 << gdst_code;
554 desc.regout[0] |= SR_CODE;
555 if (gdst_code == PC_REGISTER)
556 {
557 desc.targetpc = BRANCH_TARGET_DYNAMIC;
558 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
559 }
560 break;
561 case 0x41: // subc global,local
562 case 0x51: // addc global,local
563 desc.regin[0] |= SR_CODE;
564 desc.regin[lsrc_group] |= 1 << lsrc_code;
565 desc.regin[0] |= 1 << gdst_code;
566 desc.regout[0] |= 1 << gdst_code;
567 desc.regout[0] |= SR_CODE;
568 if (gdst_code == PC_REGISTER)
569 {
570 desc.targetpc = BRANCH_TARGET_DYNAMIC;
571 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
572 }
573 break;
574 case 0x42: // subc local,global
575 case 0x52: // addc local,global
576 desc.regin[0] |= SR_CODE;
577 desc.regin[0] |= 1 << gsrc_code;
578 desc.regin[ldst_group] |= 1 << ldst_code;
579 desc.regout[ldst_group] |= 1 << ldst_code;
580 desc.regout[0] |= SR_CODE;
581 break;
582 case 0x43: // subc local,local
583 case 0x53: // addc local,local
584 desc.regin[0] |= SR_CODE;
585 desc.regin[lsrc_group] |= 1 << lsrc_code;
586 desc.regin[ldst_group] |= 1 << ldst_code;
587 desc.regout[ldst_group] |= 1 << ldst_code;
588 desc.regout[0] |= SR_CODE;
589 break;
590 case 0x44: // not global,global
591 case 0x58: // neg global,global
592 desc.regin[0] |= 1 << gsrc_code;
593 desc.regout[0] |= 1 << gdst_code;
594 desc.regout[0] |= SR_CODE;
595 if (gdst_code == PC_REGISTER)
596 {
597 desc.targetpc = BRANCH_TARGET_DYNAMIC;
598 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
599 }
600 break;
601 case 0x45: // not global,local
602 case 0x59: // neg global,local
603 desc.regin[0] |= SR_CODE;
604 desc.regin[lsrc_group] |= 1 << lsrc_code;
605 desc.regout[0] |= 1 << gdst_code;
606 desc.regout[0] |= SR_CODE;
607 if (gdst_code == PC_REGISTER)
608 {
609 desc.targetpc = BRANCH_TARGET_DYNAMIC;
610 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
611 }
612 break;
613 case 0x46: // not local,global
614 case 0x5a: // neg local,global
615 desc.regin[0] |= SR_CODE;
616 desc.regin[0] |= 1 << gsrc_code;
617 desc.regout[ldst_group] |= 1 << ldst_code;
618 desc.regout[0] |= SR_CODE;
619 break;
620 case 0x47: // not local,local
621 case 0x5b: // neg local,local
622 desc.regin[0] |= SR_CODE;
623 desc.regin[lsrc_group] |= 1 << lsrc_code;
624 desc.regout[ldst_group] |= 1 << ldst_code;
625 desc.regout[0] |= SR_CODE;
626 break;
627 case 0x5c: // negs global,global
628 desc.regin[0] |= 1 << gsrc_code;
629 desc.regout[0] |= 1 << gdst_code;
630 desc.regout[0] |= SR_CODE;
631 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
632 if (gdst_code == PC_REGISTER)
633 {
634 desc.targetpc = BRANCH_TARGET_DYNAMIC;
635 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
636 }
637 break;
638 case 0x5d: // negs global,local
639 desc.regin[0] |= SR_CODE;
640 desc.regin[lsrc_group] |= 1 << lsrc_code;
641 desc.regout[0] |= 1 << gdst_code;
642 desc.regout[0] |= SR_CODE;
643 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
644 if (gdst_code == PC_REGISTER)
645 {
646 desc.targetpc = BRANCH_TARGET_DYNAMIC;
647 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
648 }
649 break;
650 case 0x5e: // negs local,global
651 desc.regin[0] |= SR_CODE;
652 desc.regin[0] |= 1 << gsrc_code;
653 desc.regout[ldst_group] |= 1 << ldst_code;
654 desc.regout[0] |= SR_CODE;
655 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
656 break;
657 case 0x5f: // negs local,local
658 desc.regin[0] |= SR_CODE;
659 desc.regin[lsrc_group] |= 1 << lsrc_code;
660 desc.regout[ldst_group] |= 1 << ldst_code;
661 desc.regout[0] |= SR_CODE;
662 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
663 break;
664 case 0x60: // cmpi global,simm
665 case 0x70: // cmpbi global,simm
666 desc.regout[0] |= 1 << gdst_code;
667 desc.regout[0] |= SR_CODE;
668 break;
669 case 0x61: // cmpi global,limm
670 case 0x71: // cmpbi global,limm
671 desc.regout[0] |= 1 << gdst_code;
672 desc.regout[0] |= SR_CODE;
673 desc.length = hyperstone_device::imm_length(op) << 1;
674 break;
675 case 0x62: // cmpi local,simm
676 case 0x72: // cmpbi local,simm
677 desc.regin[0] |= SR_CODE;
678 desc.regout[ldst_group] |= 1 << ldst_code;
679 desc.regout[0] |= SR_CODE;
680 break;
681 case 0x63: // cmpi local,limm
682 case 0x73: // cmpbi local,limm
683 desc.regin[0] |= SR_CODE;
684 desc.regout[ldst_group] |= 1 << ldst_code;
685 desc.regout[0] |= SR_CODE;
686 desc.length = hyperstone_device::imm_length(op) << 1;
687 break;
688 case 0x64: // movi global,simm
689 desc.regin[0] |= SR_CODE;
690 desc.regout[0] |= 1 << gdst_code;
691 desc.regout[0] |= 1 << (gdst_code + 16);
692 desc.regout[0] |= SR_CODE;
693 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
694 if (gdst_code == PC_REGISTER)
695 {
696 desc.targetpc = op & 0xf;
697 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
698 }
699 else if (gdst_code == 5) // TPR_REGISTER & 0xf
700 {
701 desc.flags |= OPFLAG_END_SEQUENCE;
702 }
703 break;
704 case 0x65: // movi global,limm
705 desc.regin[0] |= SR_CODE;
706 desc.regout[0] |= 1 << gdst_code;
707 desc.regout[0] |= 1 << (gdst_code + 16);
708 desc.regout[0] |= SR_CODE;
709 desc.length = hyperstone_device::imm_length(op) << 1;
710 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
711 if (gdst_code == PC_REGISTER)
712 {
713 desc.targetpc = read_limm(desc, op);
714 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
715 }
716 else if (gdst_code == 5) // TPR_REGISTER & 0xf
717 {
718 desc.flags |= OPFLAG_END_SEQUENCE;
719 }
720 break;
721 case 0x66: // movi local,simm
722 desc.regin[0] |= SR_CODE;
723 desc.regout[ldst_group] |= 1 << ldst_code;
724 desc.regout[0] |= SR_CODE;
725 break;
726 case 0x67: // movi local,limm
727 desc.regin[0] |= SR_CODE;
728 desc.regout[ldst_group] |= 1 << ldst_code;
729 desc.regout[0] |= SR_CODE;
730 desc.length = hyperstone_device::imm_length(op) << 1;
731 break;
732 case 0x68: // addi global,simm
733 case 0x6c: // addsi global,simm
734 desc.regin[0] |= SR_CODE;
735 desc.regin[0] |= 1 << gdst_code;
736 desc.regout[0] |= 1 << gdst_code;
737 desc.regout[0] |= SR_CODE;
738 if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // addsi
739 if (gdst_code == PC_REGISTER)
740 {
741 desc.targetpc = BRANCH_TARGET_DYNAMIC;
742 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
743 }
744 break;
745 case 0x69: // addi global,limm
746 case 0x6d: // addsi global,limm
747 desc.regin[0] |= SR_CODE;
748 desc.regin[0] |= 1 << gdst_code;
749 desc.regout[0] |= 1 << gdst_code;
750 desc.regout[0] |= SR_CODE;
751 desc.length = hyperstone_device::imm_length(op) << 1;
752 if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // addsi
753 if (gdst_code == PC_REGISTER)
754 {
755 desc.targetpc = desc.pc + desc.length + read_limm(desc, op);
756 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
757 }
758 break;
759 case 0x6a: // addi local,simm
760 case 0x6e: // addsi local,simm
761 desc.regin[0] |= SR_CODE;
762 desc.regin[ldst_group] |= 1 << ldst_code;
763 desc.regout[ldst_group] |= 1 << ldst_code;
764 desc.regout[0] |= SR_CODE;
765 if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // addsi
766 break;
767 case 0x6b: // addi local,limm
768 case 0x6f: // addsi local,limm
769 desc.regin[0] |= SR_CODE;
770 desc.regin[ldst_group] |= 1 << ldst_code;
771 desc.regout[ldst_group] |= 1 << ldst_code;
772 desc.regout[0] |= SR_CODE;
773 desc.length = hyperstone_device::imm_length(op) << 1;
774 if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // addsi
775 break;
776 case 0x74: // andni global,simm
777 case 0x78: // ori global,simm
778 case 0x7c: // xori global,simm
779 desc.regin[0] |= SR_CODE;
780 desc.regin[0] |= 1 << gdst_code;
781 desc.regout[0] |= 1 << gdst_code;
782 desc.regout[0] |= SR_CODE;
783 if (gdst_code == PC_REGISTER)
784 {
785 desc.targetpc = BRANCH_TARGET_DYNAMIC;
786 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
787 }
788 break;
789 case 0x75: // andni global,limm
790 case 0x79: // ori global,limm
791 case 0x7d: // xori global,limm
792 desc.regin[0] |= SR_CODE;
793 desc.regin[0] |= 1 << gdst_code;
794 desc.regout[0] |= 1 << gdst_code;
795 desc.regout[0] |= SR_CODE;
796 desc.length = hyperstone_device::imm_length(op) << 1;
797 if (gdst_code == PC_REGISTER)
798 {
799 desc.targetpc = BRANCH_TARGET_DYNAMIC;
800 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
801 }
802 break;
803 case 0x76: // andni local,simm
804 case 0x7a: // ori local,simm
805 case 0x7e: // xori local,simm
806 desc.regin[0] |= SR_CODE;
807 desc.regin[ldst_group] |= 1 << ldst_code;
808 desc.regout[ldst_group] |= 1 << ldst_code;
809 desc.regout[0] |= SR_CODE;
810 break;
811 case 0x77: // andni local,limm
812 case 0x7b: // ori local,limm
813 case 0x7f: // xori local,limm
814 desc.regin[0] |= SR_CODE;
815 desc.regin[ldst_group] |= 1 << ldst_code;
816 desc.regout[ldst_group] |= 1 << ldst_code;
817 desc.regout[0] |= SR_CODE;
818 desc.length = hyperstone_device::imm_length(op) << 1;
819 break;
820 case 0x80: case 0x81: // shrdi
821 case 0x84: case 0x85: // sardi
822 case 0x88: case 0x89: // shldi
823 desc.regin[0] |= SR_CODE;
824 desc.regout[ldst_group] |= 1 << ldst_code;
825 desc.regout[ldstf_group] |= 1 << ldstf_code;
826 desc.regout[0] |= SR_CODE;
827 break;
828 case 0x82: // shrd
829 case 0x86: // sard
830 case 0x8a: // shld
831 desc.regin[0] |= SR_CODE;
832 desc.regin[lsrc_group] |= 1 << lsrc_code;
833 desc.regout[ldst_group] |= 1 << ldst_code;
834 desc.regout[ldstf_group] |= 1 << ldstf_code;
835 desc.regout[0] |= SR_CODE;
836 break;
837 case 0x83: // shr
838 case 0x87: // sar
839 case 0x8b: // shl
840 case 0x8f: // rol
841 desc.regin[0] |= SR_CODE;
842 desc.regin[lsrc_group] |= 1 << lsrc_code;
843 desc.regout[ldst_group] |= 1 << ldst_code;
844 desc.regout[0] |= SR_CODE;
845 break;
846 case 0x8c: case 0x8d: // reserved
847 return false;
848 case 0x8e: // testlz
849 desc.regin[0] |= SR_CODE;
850 desc.regin[lsrc_group] |= 1 << lsrc_code;
851 desc.regout[ldst_group] |= 1 << ldst_code;
852 break;
853 case 0x90: // ldxx1 global,global
854 {
855 const uint16_t imm1 = read_imm1(desc);
856 const uint32_t extra_s = read_ldstxx_imm(desc);
857
858 desc.regin[0] |= 1 << gdst_code;
859 desc.regout[0] |= 1 << gsrc_code;
860 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[0] |= 1 << gsrcf_code;
861
862 desc.length = (imm1 & 0x8000) ? 6 : 4;
863 desc.flags |= OPFLAG_READS_MEMORY;
864 if (gdst_code == PC_REGISTER)
865 {
866 desc.targetpc = BRANCH_TARGET_DYNAMIC;
867 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
868 }
869 break;
870 }
871 case 0x91: // ldxx1 global,local
872 {
873 const uint16_t imm1 = read_imm1(desc);
874 const uint32_t extra_s = read_ldstxx_imm(desc);
875
876 desc.regin[0] |= SR_CODE;
877 desc.regin[0] |= 1 << gdst_code;
878 desc.regout[lsrc_group] |= 1 << lsrc_code;
879 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[lsrcf_group] |= 1 << lsrcf_code;
880
881 desc.length = (imm1 & 0x8000) ? 6 : 4;
882 desc.flags |= OPFLAG_READS_MEMORY;
883 if (gdst_code == PC_REGISTER)
884 {
885 desc.targetpc = BRANCH_TARGET_DYNAMIC;
886 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
887 }
888 break;
889 }
890 case 0x92: // ldxx1 local,global
891 {
892 const uint16_t imm1 = read_imm1(desc);
893 const uint32_t extra_s = read_ldstxx_imm(desc);
894
895 desc.regin[0] |= SR_CODE;
896 desc.regin[ldst_group] |= 1 << ldst_code;
897 desc.regout[0] |= 1 << gsrc_code;
898 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[0] |= 1 << gsrcf_code;
899
900 desc.length = (imm1 & 0x8000) ? 6 : 4;
901 desc.flags |= OPFLAG_READS_MEMORY;
902 break;
903 }
904 case 0x93: // ldxx1 local,local
905 {
906 const uint16_t imm1 = read_imm1(desc);
907 const uint32_t extra_s = read_ldstxx_imm(desc);
908
909 desc.regin[0] |= SR_CODE;
910 desc.regin[ldst_group] |= 1 << ldst_code;
911 desc.regout[lsrc_group] |= 1 << lsrc_code;
912 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[lsrcf_group] |= 1 << lsrcf_code;
913
914 desc.length = (imm1 & 0x8000) ? 6 : 4;
915 desc.flags |= OPFLAG_READS_MEMORY;
916 break;
917 }
918 case 0x94: // ldxx2 global,global
919 {
920 const uint16_t imm1 = read_imm1(desc);
921 const uint32_t extra_s = read_ldstxx_imm(desc);
922
923 desc.regin[0] |= 1 << gdst_code;
924 desc.regout[0] |= 1 << gdst_code;
925 desc.regout[0] |= 1 << gsrc_code;
926 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[0] |= 1 << gsrcf_code;
927
928 desc.length = (imm1 & 0x8000) ? 6 : 4;
929 desc.flags |= OPFLAG_READS_MEMORY;
930 if (gdst_code == PC_REGISTER)
931 {
932 desc.targetpc = BRANCH_TARGET_DYNAMIC;
933 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
934 }
935 break;
936 }
937 case 0x95: // ldxx2 global,local
938 {
939 const uint16_t imm1 = read_imm1(desc);
940 const uint32_t extra_s = read_ldstxx_imm(desc);
941
942 desc.regin[0] |= SR_CODE;
943 desc.regin[0] |= 1 << gdst_code;
944 desc.regout[0] |= 1 << gdst_code;
945 desc.regout[lsrc_group] |= 1 << lsrc_code;
946 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[lsrcf_group] |= 1 << lsrcf_code;
947
948 desc.length = (imm1 & 0x8000) ? 6 : 4;
949 desc.flags |= OPFLAG_READS_MEMORY;
950 if (gdst_code == PC_REGISTER)
951 {
952 desc.targetpc = BRANCH_TARGET_DYNAMIC;
953 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
954 }
955 break;
956 }
957 case 0x96: // ldxx2 local,global
958 {
959 const uint16_t imm1 = read_imm1(desc);
960 const uint32_t extra_s = read_ldstxx_imm(desc);
961
962 desc.regin[0] |= SR_CODE;
963 desc.regin[ldst_group] |= 1 << ldst_code;
964 desc.regout[ldst_group] |= 1 << ldst_code;
965 desc.regout[0] |= 1 << gsrc_code;
966 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[0] |= 1 << gsrcf_code;
967
968 desc.length = (imm1 & 0x8000) ? 6 : 4;
969 desc.flags |= OPFLAG_READS_MEMORY;
970 break;
971 }
972 case 0x97: // ldxx2 local,local
973 {
974 const uint16_t imm1 = read_imm1(desc);
975 const uint32_t extra_s = read_ldstxx_imm(desc);
976
977 desc.regin[0] |= SR_CODE;
978 desc.regin[ldst_group] |= 1 << ldst_code;
979 desc.regout[ldst_group] |= 1 << ldst_code;
980 desc.regout[lsrc_group] |= 1 << lsrc_code;
981 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regout[lsrcf_group] |= 1 << lsrcf_code;
982
983 desc.length = (imm1 & 0x8000) ? 6 : 4;
984 desc.flags |= OPFLAG_READS_MEMORY;
985 break;
986 }
987 case 0x98: // stxx1 global,global
988 {
989 const uint16_t imm1 = read_imm1(desc);
990 const uint32_t extra_s = read_ldstxx_imm(desc);
991
992 desc.regin[0] |= 1 << gdst_code;
993 desc.regin[0] |= 1 << gsrc_code;
994 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[0] |= 1 << gsrcf_code;
995
996 desc.length = (imm1 & 0x8000) ? 6 : 4;
997 desc.flags |= OPFLAG_WRITES_MEMORY;
998 break;
999 }
1000 case 0x99: // stxx1 global,local
1001 {
1002 const uint16_t imm1 = read_imm1(desc);
1003 const uint32_t extra_s = read_ldstxx_imm(desc);
1004
1005 desc.regin[0] |= SR_CODE;
1006 desc.regin[0] |= 1 << gdst_code;
1007 desc.regin[lsrc_group] |= 1 << lsrc_code;
1008 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[lsrcf_group] |= 1 << lsrcf_code;
1009
1010 desc.length = (imm1 & 0x8000) ? 6 : 4;
1011 desc.flags |= OPFLAG_WRITES_MEMORY;
1012 break;
1013 }
1014 case 0x9a: // stxx1 local,global
1015 {
1016 const uint16_t imm1 = read_imm1(desc);
1017 const uint32_t extra_s = read_ldstxx_imm(desc);
1018
1019 desc.regin[0] |= SR_CODE;
1020 desc.regin[ldst_group] |= 1 << ldst_code;
1021 desc.regin[0] |= 1 << gsrc_code;
1022 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[0] |= 1 << gsrcf_code;
1023
1024 desc.length = (imm1 & 0x8000) ? 6 : 4;
1025 desc.flags |= OPFLAG_WRITES_MEMORY;
1026 break;
1027 }
1028 case 0x9b: // stxx1 local,local
1029 {
1030 const uint16_t imm1 = read_imm1(desc);
1031 const uint32_t extra_s = read_ldstxx_imm(desc);
1032
1033 desc.regin[0] |= SR_CODE;
1034 desc.regin[ldst_group] |= 1 << ldst_code;
1035 desc.regin[lsrc_group] |= 1 << lsrc_code;
1036 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[lsrcf_group] |= 1 << lsrcf_code;
1037
1038 desc.length = (imm1 & 0x8000) ? 6 : 4;
1039 desc.flags |= OPFLAG_WRITES_MEMORY;
1040 break;
1041 }
1042 case 0x9c: // stxx2 global,global
1043 {
1044 const uint16_t imm1 = read_imm1(desc);
1045 const uint32_t extra_s = read_ldstxx_imm(desc);
1046
1047 desc.regin[0] |= 1 << gdst_code;
1048 desc.regin[0] |= 1 << gsrc_code;
1049 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[0] |= 1 << gsrcf_code;
1050 desc.regout[0] |= 1 << gdst_code;
1051
1052 desc.length = (imm1 & 0x8000) ? 6 : 4;
1053 desc.flags |= OPFLAG_WRITES_MEMORY;
1054 break;
1055 }
1056 case 0x9d: // stxx2 global,local
1057 {
1058 const uint16_t imm1 = read_imm1(desc);
1059 const uint32_t extra_s = read_ldstxx_imm(desc);
1060
1061 desc.regin[0] |= SR_CODE;
1062 desc.regin[0] |= 1 << gdst_code;
1063 desc.regin[lsrc_group] |= 1 << lsrc_code;
1064 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[lsrcf_group] |= 1 << lsrcf_code;
1065 desc.regout[0] |= 1 << gdst_code;
1066
1067 desc.length = (imm1 & 0x8000) ? 6 : 4;
1068 desc.flags |= OPFLAG_WRITES_MEMORY;
1069 break;
1070 }
1071 case 0x9e: // stxx2 local,global
1072 {
1073 const uint16_t imm1 = read_imm1(desc);
1074 const uint32_t extra_s = read_ldstxx_imm(desc);
1075
1076 desc.regin[0] |= SR_CODE;
1077 desc.regin[ldst_group] |= 1 << ldst_code;
1078 desc.regin[0] |= 1 << gsrc_code;
1079 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[0] |= 1 << gsrcf_code;
1080 desc.regout[ldst_group] |= 1 << ldst_code;
1081
1082 desc.length = (imm1 & 0x8000) ? 6 : 4;
1083 desc.flags |= OPFLAG_WRITES_MEMORY;
1084 break;
1085 }
1086 case 0x9f: // stxx2 local,local
1087 {
1088 const uint16_t imm1 = read_imm1(desc);
1089 const uint32_t extra_s = read_ldstxx_imm(desc);
1090
1091 desc.regin[0] |= SR_CODE;
1092 desc.regin[ldst_group] |= 1 << ldst_code;
1093 desc.regin[lsrc_group] |= 1 << lsrc_code;
1094 if ((imm1 & 0x3000) == 0x3000 && (extra_s & 2)) desc.regin[lsrcf_group] |= 1 << lsrcf_code;
1095 desc.regout[ldst_group] |= 1 << ldst_code;
1096
1097 desc.length = (imm1 & 0x8000) ? 6 : 4;
1098 desc.flags |= OPFLAG_WRITES_MEMORY;
1099 break;
1100 }
1101 case 0xa0: // shri global (lo n)
1102 case 0xa1: // shri global (hi n)
1103 case 0xa4: // sari global (lo n)
1104 case 0xa5: // sari global (hi n)
1105 case 0xa8: // shli global (lo n)
1106 case 0xa9: // shli global (hi n)
1107 desc.regin[0] |= 1 << gdst_code;
1108 desc.regout[0] |= 1 << gdst_code;
1109 desc.regout[0] |= SR_CODE;
1110 break;
1111 case 0xa2: // shri local (lo n)
1112 case 0xa3: // shri local (hi n)
1113 case 0xa6: // sari local (lo n)
1114 case 0xa7: // sari local (hi n)
1115 case 0xaa: // shli local (lo n)
1116 case 0xab: // shli local (hi n)
1117 desc.regin[0] |= SR_CODE;
1118 desc.regin[ldst_group] |= 1 << ldst_code;
1119 desc.regout[ldst_group] |= 1 << ldst_code;
1120 desc.regout[0] |= SR_CODE;
1121 break;
1122 case 0xac: case 0xad: case 0xae: case 0xaf: // reserved
1123 return false;
1124 case 0xb0: // mulu global,global
1125 case 0xb4: // muls global,global
1126 desc.regin[0] |= 1 << gsrc_code;
1127 desc.regin[0] |= 1 << gdst_code;
1128 desc.regout[0] |= 1 << gdst_code;
1129 desc.regout[0] |= 1 << gdstf_code;
1130 desc.regout[0] |= SR_CODE;
1131 break;
1132 case 0xb1: // mulu global,local
1133 case 0xb5: // muls global,local
1134 desc.regin[lsrc_group] |= 1 << lsrc_code;
1135 desc.regin[0] |= 1 << gdst_code;
1136 desc.regout[0] |= 1 << gdst_code;
1137 desc.regout[0] |= 1 << gdstf_code;
1138 desc.regout[0] |= SR_CODE;
1139 break;
1140 case 0xb2: // mulu local,global
1141 case 0xb6: // muls local,global
1142 desc.regin[0] |= 1 << gsrc_code;
1143 desc.regin[ldst_group] |= 1 << ldst_code;
1144 desc.regout[ldst_group] |= 1 << ldst_code;
1145 desc.regout[ldstf_group] |= 1 << ldstf_code;
1146 desc.regout[0] |= SR_CODE;
1147 break;
1148 case 0xb3: // mulu local,local
1149 case 0xb7: // muls local,local
1150 desc.regin[lsrc_group] |= 1 << lsrc_code;
1151 desc.regin[ldst_group] |= 1 << ldst_code;
1152 desc.regout[ldst_group] |= 1 << ldst_code;
1153 desc.regout[ldstf_group] |= 1 << ldstf_code;
1154 desc.regout[0] |= SR_CODE;
1155 break;
1156 case 0xb8: // set global (lo n)
1157 case 0xb9: // set global (hi n)
1158 desc.regin[0] |= SR_CODE;
1159 desc.regout[0] |= 1 << gdst_code;
1160 break;
1161 case 0xba: // set local (lo n)
1162 case 0xbb: // set local (hi n)
1163 desc.regout[ldst_group] |= 1 << ldst_code;
1164 break;
1165 case 0xbc: // mul global,global
1166 desc.regin[0] |= 1 << gsrc_code;
1167 desc.regin[0] |= 1 << gdst_code;
1168 desc.regout[0] |= 1 << gdst_code;
1169 desc.regout[0] |= SR_CODE;
1170 break;
1171 case 0xbd: // muls global,local
1172 desc.regin[lsrc_group] |= 1 << lsrc_code;
1173 desc.regin[0] |= 1 << gdst_code;
1174 desc.regout[0] |= 1 << gdst_code;
1175 desc.regout[0] |= SR_CODE;
1176 break;
1177 case 0xbe: // muls local,global
1178 desc.regin[0] |= 1 << gsrc_code;
1179 desc.regin[ldst_group] |= 1 << ldst_code;
1180 desc.regout[ldst_group] |= 1 << ldst_code;
1181 desc.regout[0] |= SR_CODE;
1182 break;
1183 case 0xbf: // mulu local,local
1184 desc.regin[lsrc_group] |= 1 << lsrc_code;
1185 desc.regin[ldst_group] |= 1 << ldst_code;
1186 desc.regout[ldst_group] |= 1 << ldst_code;
1187 desc.regout[0] |= SR_CODE;
1188 break;
1189 case 0xc0: case 0xc1: case 0xc2: case 0xc3: // software
1190 case 0xc4: case 0xc5: case 0xc6: case 0xc7: // software
1191 case 0xc8: case 0xc9: case 0xca: case 0xcb: // software
1192 case 0xcc: case 0xcd: // software
1193 {
1194 desc.regin[0] |= SR_CODE;
1195 desc.regin[lsrc_group] |= 1 << lsrc_code;
1196 desc.regin[lsrcf_group] |= 1 << lsrcf_code;
1197
1198 const uint32_t reg = FE_FP + FE_FL;
1199 desc.regout[1 + (((reg + 0) & 0x20) >> 5)] |= 1 << ((reg + 0) & 0x1f);
1200 desc.regout[1 + (((reg + 1) & 0x20) >> 5)] |= 1 << ((reg + 1) & 0x1f);
1201 desc.regout[1 + (((reg + 2) & 0x20) >> 5)] |= 1 << ((reg + 2) & 0x1f);
1202 desc.regout[1 + (((reg + 3) & 0x20) >> 5)] |= 1 << ((reg + 3) & 0x1f);
1203 desc.regout[1 + (((reg + 4) & 0x20) >> 5)] |= 1 << ((reg + 4) & 0x1f);
1204
1205 desc.regout[0] |= SR_CODE;
1206
1207 desc.targetpc = BRANCH_TARGET_DYNAMIC;
1208 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
1209 break;
1210 }
1211 case 0xce: // extend - 4 bytes
1212 desc.regin[0] |= SR_CODE;
1213 desc.regin[0] |= (3 << 14); // global regs 14, 15
1214 desc.regin[lsrc_group] |= 1 << lsrc_code;
1215 desc.regin[ldst_group] |= 1 << ldst_code;
1216 desc.regout[0] |= (3 << 14); // global regs 14, 15
1217 desc.length = 4;
1218 break;
1219 case 0xcf: // do
1220 return false;
1221 case 0xd0: // ldwr global
1222 case 0xd4: // ldwp global
1223 desc.regin[0] |= SR_CODE;
1224 desc.regin[ldst_group] |= 1 << ldst_code;
1225 desc.regout[0] |= 1 << gsrc_code;
1226 if (op & 0x04) desc.regout[ldst_group] |= 1 << ldst_code;
1227 desc.flags |= OPFLAG_READS_MEMORY;
1228 break;
1229 case 0xd1: // ldwr local
1230 case 0xd5: // ldwp local
1231 desc.regin[0] |= SR_CODE;
1232 desc.regin[ldst_group] |= 1 << ldst_code;
1233 desc.regout[lsrc_group] |= 1 << lsrc_code;
1234 if (op & 0x04) desc.regout[ldst_group] |= 1 << ldst_code;
1235 desc.flags |= OPFLAG_READS_MEMORY;
1236 break;
1237 case 0xd2: // lddr global
1238 case 0xd6: // lddp global
1239 desc.regin[0] |= SR_CODE;
1240 desc.regin[ldst_group] |= 1 << ldst_code;
1241 desc.regout[0] |= 1 << gsrc_code;
1242 desc.regout[0] |= 1 << gsrcf_code;
1243 if (op & 0x04) desc.regout[ldst_group] |= 1 << ldst_code;
1244 desc.flags |= OPFLAG_READS_MEMORY;
1245 break;
1246 case 0xd3: // lddr local
1247 case 0xd7: // lddp local
1248 desc.regin[0] |= SR_CODE;
1249 desc.regin[ldst_group] |= 1 << ldst_code;
1250 desc.regout[lsrc_group] |= 1 << lsrc_code;
1251 desc.regout[lsrcf_group] |= 1 << lsrcf_code;
1252 if (op & 0x04) desc.regout[ldst_group] |= 1 << ldst_code;
1253 desc.flags |= OPFLAG_READS_MEMORY;
1254 break;
1255 case 0xd8: // stwr global
1256 case 0xdc: // stwp global
1257 desc.regin[0] |= SR_CODE;
1258 desc.regin[ldst_group] |= 1 << ldst_code;
1259 desc.regin[0] |= 1 << gsrc_code;
1260 if (op & 0x04) desc.regout[ldst_group] |= 1 << ldst_code;
1261 desc.flags |= OPFLAG_WRITES_MEMORY;
1262 break;
1263 case 0xd9: // stwr local
1264 case 0xdd: // stwp local
1265 desc.regin[0] |= SR_CODE;
1266 desc.regin[ldst_group] |= 1 << ldst_code;
1267 desc.regin[lsrc_group] |= 1 << lsrc_code;
1268 if (op & 0x04) desc.regout[ldst_group] |= 1 << ldst_code;
1269 desc.flags |= OPFLAG_WRITES_MEMORY;
1270 break;
1271 case 0xda: // stdr global
1272 case 0xde: // stdp global
1273 desc.regin[0] |= SR_CODE;
1274 desc.regin[ldst_group] |= 1 << ldst_code;
1275 desc.regin[0] |= 1 << gsrc_code;
1276 desc.regin[0] |= 1 << gsrcf_code;
1277 if (op & 0x04) desc.regout[ldst_group] |= 1 << ldst_code;
1278 desc.flags |= OPFLAG_WRITES_MEMORY;
1279 break;
1280 case 0xdb: // stdr local
1281 case 0xdf: // stdp local
1282 desc.regin[0] |= SR_CODE;
1283 desc.regin[ldst_group] |= 1 << ldst_code;
1284 desc.regin[lsrc_group] |= 1 << lsrc_code;
1285 desc.regin[lsrcf_group] |= 1 << lsrcf_code;
1286 if (op & 0x04) desc.regout[ldst_group] |= 1 << ldst_code;
1287 desc.flags |= OPFLAG_WRITES_MEMORY;
1288 break;
1289 case 0xe0: case 0xe1: case 0xe2: case 0xe3: // dbv, dbnv, dbe, dbne - could be 4 bytes (pcrel)
1290 case 0xe4: case 0xe5: case 0xe6: case 0xe7: // dbc, dbnc, dbse, dbht - could be 4 bytes (pcrel)
1291 case 0xe8: case 0xe9: case 0xea: case 0xeb: // dbn, dbnn, dblt, dbgt - could be 4 bytes (pcrel)
1292 decode_pcrel(desc, op);
1293 desc.regin[0] |= SR_CODE;
1294 desc.targetpc = BRANCH_TARGET_DYNAMIC;
1295 desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
1296 desc.delayslots = 1;
1297 desc.length = (op & 0x80) ? 4 : 2;
1298 break;
1299 case 0xec: // dbr
1300 decode_pcrel(desc, op);
1301 desc.targetpc = BRANCH_TARGET_DYNAMIC;
1302 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
1303 desc.delayslots = 1;
1304 desc.length = (op & 0x80) ? 4 : 2;
1305 break;
1306 case 0xed: // frame
1307 desc.regin[0] |= SR_CODE;
1308 desc.regin[1] = 0xffffffff;
1309 desc.regin[2] = 0xffffffff;
1310 desc.regout[0] |= SR_CODE;
1311 desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_END_SEQUENCE;
1312 break;
1313 case 0xee: // call global
1314 desc.regin[0] |= SR_CODE;
1315 desc.regin[0] |= 1 << gsrc_code;
1316 desc.regout[ldst_group] |= 1 << ldst_code;
1317 desc.regout[ldstf_group] |= 1 << ldstf_code;
1318 desc.targetpc = BRANCH_TARGET_DYNAMIC;
1319 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
1320 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
1321 break;
1322 case 0xef: // call local
1323 desc.regin[0] |= SR_CODE;
1324 desc.regin[lsrc_group] |= 1 << lsrc_code;
1325 desc.regout[ldst_group] |= 1 << ldst_code;
1326 desc.regout[ldstf_group] |= 1 << ldstf_code;
1327 desc.targetpc = BRANCH_TARGET_DYNAMIC;
1328 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
1329 desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
1330 break;
1331 case 0xf0: case 0xf1: case 0xf2: case 0xf3: // bv, bnv, be, bne
1332 case 0xf4: case 0xf5: case 0xf6: case 0xf7: // bc, bnc, bse, bht
1333 case 0xf8: case 0xf9: case 0xfa: case 0xfb: // bn, bnn, blt, bgt
1334 decode_pcrel(desc, op);
1335 desc.regin[0] |= SR_CODE;
1336 desc.targetpc = BRANCH_TARGET_DYNAMIC;
1337 desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
1338 desc.length = (op & 0x80) ? 4 : 2;
1339 break;
1340 case 0xfc: // br
1341 {
1342 int32_t offset = decode_pcrel(desc, op);
1343 desc.targetpc = (desc.pc + desc.length) + offset;
1344 desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
1345 desc.length = (op & 0x80) ? 4 : 2;
1346 break;
1347 }
1348 case 0xfd: case 0xfe: case 0xff: // trap
1349 desc.regin[0] |= SR_CODE;
1350 desc.targetpc = BRANCH_TARGET_DYNAMIC;
1351 desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION;
1352 break;
1353 }
1354 return true;
1355 }
1356