* gencode.c (build_instruction): Handle "ppac5" according to
[deliverable/binutils-gdb.git] / sim / mips / gencode.c
1 /*> gencode.c <*/
2 /* Instruction handling support for the MIPS architecture simulator.
3
4 This file is part of the MIPS sim
5
6 THIS SOFTWARE IS NOT COPYRIGHTED
7
8 Cygnus offers the following for use in the public domain. Cygnus
9 makes no warranty with regard to the software or it's performance
10 and the user accepts the software "AS IS" with all faults.
11
12 CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
13 THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15
16 $Revision$
17 $Author$
18 $Date$
19 */
20
21 #if 0
22 #define DEBUG (1) /* Just for testing */
23 #endif
24
25 /* All output sent to stdout is for the simulator engine. All program
26 related warnings and errors should be sent to stderr. */
27
28 /* The simulator decode table is constructed this way to allow the
29 minimal code required for a particular instruction type to be
30 coded. This avoids a large simulator source file, with lots of
31 build-time conditionals controlling what code is included. However
32 this two-stage process does mean that care must be taken to ensure
33 that the correct decoding source is generated for a particular MIPS
34 simulator. */
35
36 /* Notes:
37
38 We could provide pipeline modelling by splitting the simulation of
39 instructions into seperate bytecodes for each pipeline
40 stage. e.g. for the VR4300 each instruction would generate 5
41 bytecodes, one for each pipeline stage. The simulator control would
42 then insert these into the relevant pipeline slots, and execute a
43 complete slots worth of bytecodes. However, the shape of the
44 pipeline, and what parts of each instruction are executed in each
45 pipeline stage, are different between MIPS implementations. If we
46 were to construct a simulator for a particular MIPS architecture
47 this would be a good solution.
48
49 To avoid having to provide multiple different pipeline models, a
50 simple approach for dealing with the delay slots, and register
51 dependencies has been used. The "MIPS IV Instruction Set" document
52 (Revision 3.1 - January 1995) details the standard MIPS instruction
53 set, and it defines operations in instruction (not pipe-line)
54 cycles. This means we only need to worry about a few cases where
55 the result is not available until after the next instruction, or
56 where registers in the previous two instruction cycles may be
57 corrupted. The case for corruption only occurs with HI or LO
58 register access, so we can just keep a count within the engine for
59 upto two cycles before marking the register as safe. We then only
60 need to check the safety flag when performing an update that
61 involves the HI or LO register. The only other case is the
62 BC1F/BC1T instructions in the FP unit. For ISAs I, II and III there
63 must be an instruction between the FP CMP and the BC1[FT]. We can
64 perform the same instruction cycle count scheme, so we can raise a
65 warning if an attempt is made to access the condition code early
66 (NOTE: The hardware does not interlock on this operation, so the
67 simulator should just raise a warning).
68
69 For the situations where a result is not available until later, we
70 implent a slot to hold pending values. After the PC is incremented,
71 and before the instruction is decoded we can execute the required
72 register update (or remainder of instruction processing). */
73
74 /* The FP instruction decoding is also provided by this code. The
75 instructions are marked as "FP" ones so that we can construct a
76 simulator without an FPU if required. Similarly we mark
77 instructions as Single or Double precision, since some MIPS
78 processors only have single precision FP hardware. */
79
80 /* NOTE: Ideally all state should be passed as parameters. This allows
81 a single simulator engine to be used for multiple concurrent
82 simulations. More importantly, if a suitably powerful control is in
83 place it will allow speculative simulation, since the context can
84 be saved easily, and then restored after performing some
85 simulation. The down-side is that for certain host architectures it
86 can slow the simulator down (e.g. if globals can be accessed faster
87 than local structures). However, this is not actually the case at
88 the moment. The constructed engine uses direct names (that can be
89 macro definitions). This keeps the engine source smalled (using
90 short-hands), and it also allows the user to control whether they
91 want to use global, or indirected memory locations. i.e. whether
92 they want a single- or multi-threaded simulator engine. */
93
94 /* The constructed simulator engine contains manifests for each of the
95 features supported. The code that includes the engine can then
96 discover the available features during its build. This information
97 can be used to control run-time features provided by the final
98 simulator. */
99
100 /*---------------------------------------------------------------------------*/
101
102 /* Program defaults */
103 #define DEF_ISA (3)
104 #define DEF_PROC64 (1 == 1)
105 #define DEF_FP (1 == 1)
106 #define DEF_FPSINGLE (1 == 0)
107
108 #define FEATURE_PROC32 (1 << 0) /* 0 = 64bit; 1 = 32bit */
109 #define FEATURE_HASFPU (1 << 1) /* 0 = no FPU; 1 = include FPU */
110 #define FEATURE_FPSINGLE (1 << 1) /* 0 = double; 1 = single (only used if FEATURE_HASFPU defined) */
111 #define FEATURE_GP64 (1 << 2) /* 0 = GPRLEN 32; 1 = GPRLEN 64 */
112 #define FEATURE_FAST (1 << 17) /* 0 = normal; 1 = disable features that slow performance */
113 #define FEATURE_WARN_STALL (1 << 24) /* 0 = nothing; 1 = generate warnings when pipeline would stall */
114 #define FEATURE_WARN_LOHI (1 << 25) /* 0 = nothing; 1 = generate warnings when LO/HI corrupted */
115 #define FEATURE_WARN_ZERO (1 << 26) /* 0 = nothing; 1 = generate warnings if attempt to write register zero */
116 #define FEATURE_WARN_MEM (1 << 27) /* 0 = nothing; 1 = generate warnings when memory problems are noticed */
117 #define FEATURE_WARN_R31 (1 << 28) /* 0 = nothing; 1 = generate warnings if r31 used dangerously */
118 #define FEATURE_WARN_RESULT (1 << 29) /* 0 = nothing; 1 = generate warnings when undefined results may occur */
119
120 /* We used to enable FEATURE_WARN_ZERO, but it is perfectly legitimate to
121 have the zero register as a destination -- the zero register just doesn't
122 actually change. */
123 /* start-sanitize-r5900 */
124 /* The 5900 madd instructions for example use this feature. */
125 /* end-sanitize-r5900 */
126 #if 1
127 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31)
128 #else
129 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
130 #endif
131
132 /* FEATURE_WARN_STALL */
133 /* If MIPS I we want to raise a warning if an attempt is made to
134 access Rn in an instruction immediately following an Rn update
135 "WARNING : Invalid value read". The simulator engine is designed
136 that the previous value is read in such cases, to allow programs
137 that make use of this feature to execute. */
138 /* If MIPS II or later, attempting to read a register before the
139 update has completed will generate a "WARNING : Processor stall"
140 message (since the processor will lock the pipeline until the value
141 becomes available). */
142
143 /* FEATURE_WARN_LOHI */
144 /* Warn if an attempt is made to read the HI/LO registers before the
145 update has completed, or if an attempt is made to update the
146 registers whilst an update is occurring. */
147
148 /* FEATURE_WARN_ZERO */
149 /* Notify the user if an attempt is made to use GPR 0 as a destination. */
150
151 /* FEATURE_WARN_R31 */
152 /* Notify the user if register r31 (the default procedure call return
153 address) is used unwisely. e.g. If r31 is used as the source in a
154 branch-and-link instruction, it would mean that an exception in the
155 delay slot instruction would not allow the branch to be re-started
156 (since r31 will have been overwritten by the link operation during
157 the first execution of the branch). */
158
159 /* FEATURE_WARN_RESULT */
160 /* Certain instructions do not raise exceptions when invalid operands
161 are given, they will just result in undefined values being
162 generated. This option controls whether the simulator flags such
163 events. */
164
165 /*---------------------------------------------------------------------------*/
166
167 #include <stdio.h>
168 #include <getopt.h>
169 #include <limits.h>
170 #include <errno.h>
171 #include <ctype.h>
172 #include "ansidecl.h"
173 #include "opcode/mips.h"
174
175 /* FIXME: ansidecl.h defines AND. */
176 #undef AND
177
178 #ifndef ULONG_MAX
179 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
180 #endif
181
182 static unsigned long my_strtoul ();
183
184 #if 0
185 #ifndef TRUE
186 #define TRUE (1 == 1)
187 #define FALSE (1 == 0)
188 #endif
189 #endif
190
191 /*---------------------------------------------------------------------------*/
192
193 /* Holding the instruction table this way makes it easier to check the
194 instruction values defined, and to add instructions to the
195 system. However, it makes the process of constructing the simulator
196 a bit more complicated: */
197
198 /* The "bitmap" is encoded as follows (NOTE: Only lower-case
199 alphabetic characters should be used, since the letter ordinal is
200 used as a bit position): */
201
202 typedef struct operand_encoding {
203 char id; /* character identifier */
204 int fpos; /* first bit position */
205 int flen; /* field length in bits */
206 char * const type;
207 char * const name;
208 unsigned int flags;
209 } operand_encoding;
210
211 /* Values for the "flags" field: */
212 #define OP_NONE (0 << 0) /* To keep the source tidy */
213 #define OP_GPR (1 << 0) /* Get operand from integer register bank */
214 #define OP_SIGNX (1 << 1) /* Sign-extend the operand */
215 #define OP_SHIFT2 (1 << 2) /* Shift field left by 2 */
216 #define OP_BITS5 (1 << 3) /* Only take the lo 5-bits of the operand */
217 #define OP_GPR1 (1 << 4) /* fetch from the GPR1 registers */
218
219 struct operand_encoding opfields[] = {
220 {'0',-1,-1,"", "", (OP_NONE)}, /* special case for explicit zero */
221 {'1',-1,-1,"", "", (OP_NONE)}, /* special case for explicit one */
222 {'?',-1,-1,"", "", (OP_NONE)}, /* undefined (do not care at this level) */
223 /* The rest are the explicit operand fields: */
224 {'a', 6, 5,"int", "op1", (OP_NONE)}, /* shift amount (or hint) */
225 {'b',21, 5,"int", "fr", (OP_NONE)}, /* fr register */
226 {'c',16, 1,"int", "boolean", (OP_NONE)}, /* TRUE or FALSE boolean */
227 {'d',11, 5,"int", "destreg", (OP_NONE)}, /* integer destination/rd register */
228 {'e', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-3bits must be zero) */
229 {'f',17, 1,"int", "likely", (OP_NONE)}, /* set if branch LIKELY */
230 {'g',16, 5,"t_reg", "op2", (OP_GPR)}, /* integer source rt register */
231 {'h', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-1bit must be zero) */
232 {'i', 0,16,"t_reg", "op2", (OP_SIGNX)}, /* signed immediate (op2) */
233 {'j', 0,26,"ut_reg","op1", (OP_SHIFT2)},/* shifted left 2 bits and combined with hi-order bits of address in the delay slot */
234 {'k',16, 5,"int", "ft", (OP_NONE)},
235 {'l', 0,16,"t_reg", "offset", (OP_SIGNX | OP_SHIFT2)}, /* signed offset shifted left 2 to make 18bit signed offset */
236 {'m',21, 3,"int", "format", (OP_NONE)}, /* FP format field */
237 {'n',16, 5,"int", "hint", (OP_NONE)}, /* hint */
238 {'o',21, 5,"t_reg", "op1", (OP_GPR | OP_BITS5)}, /* integer source/rs register (but never treated as 32bit word) */
239 {'p', 8, 3,"int", "condition_code",(OP_NONE)}, /* FP condition code field */
240 {'q',18, 3,"int", "condition_code",(OP_NONE)}, /* FP condition code field */
241 {'r', 6, 5,"int", "destreg", (OP_NONE)}, /* FP fd register */
242 {'s',21, 5,"t_reg", "op1", (OP_GPR)}, /* integer source/rs register */
243 {'t',16, 5,"int", "destreg", (OP_NONE)}, /* integer target rt (destination) register */
244 {'u', 0, 4,"int", "cmpflags", (OP_NONE)}, /* FP comparison control flags */
245 {'v',11, 5,"int", "fs", (OP_NONE)}, /* FP fs register (or PREFX hint) */
246 {'w', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-2bits must be zero) */
247 {'x',23, 1,"int", "to", (OP_NONE)}, /* TRUE if move To; FALSE if move From */
248 {'y', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset */
249 {'z', 0,16,"ut_reg","op2", (OP_NONE)}, /* unsigned immediate (zero extended) */
250 {'S',21, 5,"t_reg", "rs_reg", (OP_GPR|OP_GPR1)}, /* rs field, GPR[rs] and GPR1[rs] as source */
251 {'T',16, 5,"t_reg", "rt_reg", (OP_GPR|OP_GPR1)}, /* rt field, GPR[rt] and GPR1[rt] as source */
252 };
253
254
255 /* Main instruction encoding types: */
256 typedef enum {
257 NORMAL,
258 SPECIAL,
259 REGIMM,
260 COP1,
261 COP1X,
262 COP1S, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
263
264 MMINORM,
265 MMI0,
266 MMI1,
267 MMI2,
268 MMI3,
269
270 /* mips16 encoding types. */
271 I, RI, RR, RRI, RRR, RRI_A, ISHIFT, I8, I8_MOVR32, I8_MOV32R, I64, RI64
272 } inst_type;
273
274 /* Main instruction families: */
275 typedef enum {
276 ADD, /* res = operand1 + operand2 */
277 SUB, /* res = operand1 - operand2 */
278 MUL, /* res = operand1 * operand2 */
279 DIV, /* res = operand1 / operand2 */
280 AND, /* res = operand1 & operand2 */
281 OR, /* res = operand1 | operand2 */
282 XOR, /* res = operand1 ^ operand2 */
283 MOVE, /* res = operand1 */
284 BRANCH, /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
285 JUMP, /* execute delay slot instruction before jump */
286 LOAD, /* load from memory */
287 STORE, /* store to memory */
288 PREFETCH, /* prefetch data into cache */
289 SET, /* set register on result of condition code */
290 SHIFT, /* perform a logical or arithmetic shift */
291 TRAP, /* system exception generation */
292 BREAK, /* system breakpoint exception generation */
293 SYSCALL, /* system exception generation */
294 SYNC, /* system cache control */
295 DECODE, /* co-processor instruction */
296 CACHE, /* co-processor 0 CACHE instruction */
297 MADD16, /* VR4100 specific multiply-add extensions */
298 FPMOVE,
299 FPMOVEC,
300 FPFLOOR,
301 FPCEIL,
302 FPTRUNC,
303 FPROUND,
304 FPNEG,
305 FPABS,
306 FPDIV,
307 FPMUL,
308 FPSUB,
309 FPADD,
310 FPPREFX,
311 FPRECIP,
312 FPSQRT,
313 FPCONVERT,
314 FPCOMPARE,
315 /* start-sanitize-r5900 */
316 MADD,
317 PABS,
318 PADD,
319 PADSBH,
320 POP,
321 PCMP,
322 PCPYH,
323 PCPYLD,
324 PCPYUD,
325 PEXCH,
326 PEXCW,
327 PEXOH,
328 PEXOW,
329 PEXTLB,
330 PEXTLH,
331 PEXTLW,
332 PEXTUB,
333 PEXTUH,
334 PEXTUW,
335 PPACB,
336 PPACH,
337 PPACW,
338 PREVH,
339 PROT3W,
340 PINTH,
341 PINTOH,
342 PMXX,
343 PMFHL,
344 PMTHL,
345 PMAXMIN,
346 QFSRV,
347 MxSA,
348 MTSAB,
349 MTSAH,
350 PSHIFT,
351 PSLLVW,
352 PSRLVW,
353 PSRAVW,
354 PLZCW,
355 PHMADDH,
356 PMULTH,
357 PMULTW,
358 PDIVBW,
359 PDIVW,
360 PEXT5,
361 PPAC5,
362 /* end-sanitize-r5900 */
363 NYI, /* Not Yet Implemented, placeholder, errors if used */
364 RSVD /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
365 } opcode_type;
366
367 /* Flags field: */
368 #define NONE (0 << 0) /* Zero value (used to keep source tidy) */
369 #define SIM_SH_SIZE (0)
370 #define SIM_MASK_SIZE (0x7)
371 #define BYTE (0) /* 8bit */
372 #define HALFWORD (1) /* 16bit */
373 #define WORD (2) /* 32bit */
374 #define DOUBLEWORD (3) /* 64bit */
375 #define SINGLE (4) /* single precision FP */
376 #define DOUBLE (5) /* double precision FP */
377 #define QUADWORD (6) /* 128bit */
378
379 /* Shorthand to get the size field from the flags value: */
380 #define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
381
382 /* The rest are single bit flags: */
383 #define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
384 #define EQ (1 << 4)
385 #define GT (1 << 5)
386 #define LT (1 << 6)
387 #define NOT (1 << 7)
388 #define LIKELY (1 << 8)
389 #define SIGNEXTEND (1 << 9)
390 #define OVERFLOW (1 << 10)
391 #define LINK (1 << 11)
392 #define ATOMIC (1 << 12)
393 #define SHIFT16 (1 << 13)
394 #define REG (1 << 14)
395 #define LEFT (1 << 15) /* Deliberate explicit encodings to allow check for neither, or both */
396 #define RIGHT (1 << 16) /* Mutually exclusive with "LEFT" */
397 #define LOGICAL (1 << 17)
398 #define ARITHMETIC (1 << 18)
399 #define UNSIGNED (1 << 19)
400 #define HI32 (1 << 20)
401 #define HI (1 << 21) /* accesses or updates the HI register */
402 #define LO (1 << 22) /* accesses or updates the LO register */
403 #define WORD32 (1 << 23)
404 #define FP (1 << 24) /* Floating Point operation */
405 #define FIXED (1 << 25) /* fixed point arithmetic */
406 #define COPROC (1 << 26)
407 #define INTEGER (1 << 27)
408 #define CONDITIONAL (1 << 28)
409 #define RECIP (1 << 29)
410 #define CONTROL (1 << 30)
411 #define NOARG (1 << 31) /* Instruction has no (defined) operands */
412 /* NOTE: We can overload the use of certain of these flags, since not
413 all options are applicable to all instruction types. This will free
414 up more space for new flags. */
415
416 /* Overloadings of above bits */
417 #define PIPE1 LIKELY /* Using pipeline 1 (DIV,MUL) */
418 #define OP3 EQ /* 3 operand version of operation (MUL) */
419
420 #define SATURATE OVERFLOW /* for PADD, saturate for overflow */
421
422 #define SUBTRACT LEFT /* for PMULT, PMULT becomes PMSUB */
423 #define ADDITION RIGHT /* for PMULT, PMULT becomes PMADD */
424
425 #define FROM LEFT /* move from special register */
426 #define TO RIGHT /* move to special register */
427
428 /* For bitwise parallel operations */
429 #define POP_AND 0 /* for POP, op = & */
430 #define POP_OR LEFT /* for POP, op = | */
431 #define POP_NOR LIKELY /* for POP, op = ~(x | y) */
432 #define POP_XOR LEFT|LIKELY /* for POP, op = ^ */
433
434 #define GET_OP_FROM_INSN(insn) (((insn)->flags)&(LEFT|LIKELY))
435
436
437
438 typedef struct instruction {
439 char *name; /* ASCII mnemonic name */
440 unsigned int isa; /* MIPS ISA number where instruction introduced */
441 char *bitmap; /* 32character string describing instruction operands */
442 inst_type mark; /* type of MIPS instruction encoding */
443 opcode_type type; /* main instruction family */
444 unsigned int flags; /* flags describing instruction features */
445 } instruction;
446 /* The number of pipeline cycles taken by an instruction varies
447 between MIPS processors. This means that the information must be
448 encoded elsewhere, in a CPU specific structure. */
449
450 /* NOTE: Undefined instructions cause "Reserved Instruction"
451 exceptions. i.e. if there is no bit-mapping defined then the
452 instruction is deemed to be undefined. */
453
454 /* NOTE: The "isa" field is also used to encode flags for particular
455 chip architecture extensions. e.g. the NEC VR4100 specific
456 instructions. Normally chip extensions are added via the COP0
457 space. However, the VR4100 (and possibly other devices) also use
458 the normal instruction space. */
459 #define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */
460 /* The other bits are allocated downwards, to avoid renumbering if we
461 have to extend the bits allocated to the pure ISA number.
462
463 These architecture bits come in two flavors:
464 ISA dependent - marking insns that should be included in the opcode
465 set if that architecture is requested on the gencode command line
466 AND the ISA of the insn is <= requested ISA;
467
468 ISA independent - marking insn that should be included in the opcode
469 set if that architecture is requested
470 OR the ISA of the insn is <= requested ISA.
471
472 Independent bits are listed in MASK_ISA_INDEP, the rest are dependent.
473 */
474 #define ARCH_VR4100 ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
475 /* start-sanitize-r5900 */
476 #define ARCH_R5900 ((unsigned)1 << 30) /* Toshiba r5900 extension instructions */
477 /* end-sanitize-r5900 */
478
479 /* A list (or'ed) of extension insn sets that can be requested independant of the ISA# */
480 #define MASK_ISA_INDEP (0 \
481 /* start-sanitize-r5900 */ \
482 | ARCH_R5900 \
483 /* end-sanitize-r5900 */ \
484 | 0)
485
486 #define MASK_ISA_DEP ~(MASK_ISA_INDEP | MASK_ISA)
487
488
489 /* Very short names for use in the table below to keep it neet. */
490 #define G1 (3 | ARCH_VR4100)
491
492 #define G2 (4 \
493 /* start-sanitize-r5900 */ \
494 | ARCH_R5900 \
495 /* end-sanitize-r5900 */ \
496 | 0)
497
498 #define G3 (4 \
499 /* start-sanitize-r5900 */ \
500 /* insn that are not really 5900 insn but were left in */ \
501 /* until we can rewrite the code-gen and libs */ \
502 | ARCH_R5900 \
503 /* end-sanitize-r5900 */ \
504 | 0)
505
506
507
508 /* start-sanitize-r5900 */
509 #define T5 ARCH_R5900
510 /* end-sanitize-r5900 */
511
512
513 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
514 COP0 space. This means that an external decoder should be added
515 when constructing a full VR4100 simulator. However some arithmetic
516 instructions are encoded in the normal instruction space. */
517
518 struct instruction MIPS_DECODE[] = {
519 /* The instructions are alphabetical, and not in instruction bit-order: */
520 {"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1, FPABS, (FP)},
521 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL,ADD, (WORD | WORD32 | OVERFLOW)}, /* rd = rs + rt */
522 {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1, FPADD, (FP)},
523 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (WORD | WORD32 | OVERFLOW)},
524 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL,ADD, (WORD | WORD32)}, /* rd = rs + rt */
525 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (WORD | WORD32)},
526 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL,AND, (NONE)}, /* rd = rs AND rt */
527 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL, AND, (NONE)},
528 {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S, BRANCH, (FP)},
529 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL, BRANCH, (EQ)},
530 {"BEQL", 2,"010100sssssgggggllllllllllllllll",NORMAL, BRANCH, (EQ | LIKELY)},
531 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM, BRANCH, (GT | EQ)},
532 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LINK)},
533 {"BGEZALL", 2,"000001sssss10011llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LINK)},
534 {"BGEZL", 2,"000001sssss00011llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LIKELY)},
535 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL, BRANCH, (GT)},
536 {"BGTZL", 2,"010111sssss00000llllllllllllllll",NORMAL, BRANCH, (GT | LIKELY)},
537 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL, BRANCH, (LT | EQ)},
538 {"BLEZL", 2,"010110sssss00000llllllllllllllll",NORMAL, BRANCH, (LT | EQ | LIKELY)},
539 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM, BRANCH, (LT)},
540 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM, BRANCH, (LT | LINK)},
541 {"BLTZALL", 2,"000001sssss10010llllllllllllllll",REGIMM, BRANCH, (LT | LINK | LIKELY)},
542 {"BLTZL", 2,"000001sssss00010llllllllllllllll",REGIMM, BRANCH, (LT | LIKELY)},
543 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL, BRANCH, (NOT | EQ)},
544 {"BNEL", 2,"010101sssssgggggllllllllllllllll",NORMAL, BRANCH, (NOT | EQ | LIKELY)},
545 {"BREAK", 1,"000000????????????????????001101",SPECIAL,BREAK, (NOARG)},
546 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1, FPCEIL, (FP | FIXED | DOUBLEWORD)},
547 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1, FPCEIL, (FP | FIXED | WORD)},
548 {"COP0", 1,"010000??????????????????????????",NORMAL, DECODE, (NOARG)},
549 {"COP2", 1,"010010??????????????????????????",NORMAL, DECODE, (NOARG)},
550 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1, FPCONVERT,(FP | DOUBLE)},
551 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1, FPCONVERT,(FP | FIXED | DOUBLEWORD)},
552 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1, FPCONVERT,(FP | SINGLE)},
553 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1, FPCONVERT,(FP | FIXED | WORD)},
554 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1, FPCOMPARE,(FP)},
555 {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD | CONTROL)},
556 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL,ADD, (DOUBLEWORD | OVERFLOW)},
557 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (DOUBLEWORD | OVERFLOW)},
558 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL,ADD, (DOUBLEWORD | UNSIGNED)},
559 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (DOUBLEWORD | UNSIGNED)},
560 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL,DIV, (DOUBLEWORD | HI | LO)},
561 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL,DIV, (DOUBLEWORD | UNSIGNED | HI | LO)},
562 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL,DIV, (WORD | WORD32 | SIGNEXTEND | HI | LO)},
563 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1, FPDIV, (FP | WORD | HI | LO)},
564 /* start-sanitize-r5900 */
565 {"DIV1", T5,"011100sssssggggg0000000000011010",MMINORM,DIV, (WORD | WORD32 | SIGNEXTEND | HI | LO | PIPE1)},
566 /* end-sanitize-r5900 */
567 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL,DIV, (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO)},
568 /* start-sanitize-r5900 */
569 {"DIVU1", T5,"011100sssssggggg0000000000011011",MMINORM,DIV, (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO | PIPE1)},
570 /* end-sanitize-r5900 */
571 {"DMADD16",G1,"000000sssssggggg0000000000101001",SPECIAL,MADD16, (DOUBLEWORD | HI | LO)},
572 {"DMULT", 3,"000000sssssggggg0000000000011100",SPECIAL,MUL, (DOUBLEWORD | HI | LO)},
573 {"DMULTU", 3,"000000sssssggggg0000000000011101",SPECIAL,MUL, (DOUBLEWORD | UNSIGNED | HI | LO)},
574 {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | DOUBLEWORD)},
575 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL)},
576 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL | REG)},
577 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL | HI32)}, /* rd = rt << (sa + 32) */
578 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC)},
579 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC | REG)},
580 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC | HI32)}, /* rd = rt >> (sa + 32) */
581 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL)},
582 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL | REG)},
583 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL | HI32)},
584 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL,SUB, (DOUBLEWORD)},
585 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL,SUB, (DOUBLEWORD | UNSIGNED)},
586 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1, FPFLOOR, (FP | FIXED | DOUBLEWORD)},
587 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1, FPFLOOR, (FP | FIXED | WORD)},
588 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (NONE)}, /* NOTE: boundary case due to delay slot address being used */
589 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (LINK)}, /* NOTE: boundary case due to delay slot address being used */
590 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL,JUMP, (LINK | REG)},
591 {"JALX", 1,"011101jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (LINK | NOT)},
592 {"JR", 1,"000000sssss000000000000000001000",SPECIAL,JUMP, (NONE)}, /* need to check PC as part of instruction fetch */
593 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE | SIGNEXTEND)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
594 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE)}, /* NOTE: See "LB" comment */
595 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD)},
596 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | COPROC)},
597 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | COPROC)},
598 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (DOUBLEWORD | LEFT)}, /* NOTE: See "LB" comment */
599 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (DOUBLEWORD | RIGHT)}, /* NOTE: See "LB" comment */
600 {"LDXC1", G3,"010011sssssggggg00000rrrrr000001",COP1X, LOAD, (FP | DOUBLEWORD | COPROC | REG)},
601 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD, (HALFWORD | SIGNEXTEND)},
602 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD, (HALFWORD)},
603 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | ATOMIC | SIGNEXTEND)},
604 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | ATOMIC)},
605 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL, MOVE, (SHIFT16)}, /* Cheat and specify sign-extension of immediate field */
606 /* start-sanitize-r5900 */
607 {"LQ", T5,"011110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (QUADWORD)},
608 /* end-sanitize-r5900 */
609 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | SIGNEXTEND)},
610 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | COPROC)},
611 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | COPROC)},
612 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (WORD | LEFT)},
613 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (WORD | RIGHT)},
614 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD)},
615 {"LWXC1", G3,"010011sssssggggg00000rrrrr000000",COP1X, LOAD, (FP | WORD | COPROC | REG)},
616 /* start-sanitize-r5900 */
617 {"MADD", T5,"011100sssssgggggddddd00000000000",MMINORM,MADD, (NONE)},
618 {"MADD1", T5,"011100sssssgggggddddd00000100000",MMINORM,MADD, (PIPE1)},
619 {"MADDU", T5,"011100sssssgggggddddd00000000001",MMINORM,MADD, (UNSIGNED)},
620 {"MADDU1", T5,"011100sssssgggggddddd00000100001",MMINORM,MADD, (UNSIGNED | PIPE1)},
621 /* end-sanitize-r5900 */
622 {"MADD16", G1,"000000sssssggggg0000000000101000",SPECIAL,MADD16, (WORD | HI | LO)},
623 {"MADD.D", G3,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X, FPADD, (FP | MULTIPLY | DOUBLE)},
624 {"MADD.S", G3,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X, FPADD, (FP | MULTIPLY | SINGLE)},
625 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL,MOVE, (HI | LEFT)}, /* with following, from and to denoted by usage of LEFT or RIGHT */
626 /* start-sanitize-r5900 */
627 {"MFHI1", T5,"0111000000000000ddddd00000010000",MMINORM,MOVE, (HI | LEFT | PIPE1)},
628 /* end-sanitize-r5900 */
629 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL,MOVE, (LO | LEFT)},
630 /* start-sanitize-r5900 */
631 {"MFLO1", T5,"0111000000000000ddddd00000010010",MMINORM,MOVE, (LO | LEFT | PIPE1)},
632 {"MFSA", T5,"0000000000000000ddddd00000101000",SPECIAL,MxSA, (FROM)},
633 /* end-sanitize-r5900 */
634 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL,MOVE, (HI | RIGHT)},
635 /* start-sanitize-r5900 */
636 {"MTHI1", T5,"011100sssss000000000000000010001",MMINORM,MOVE, (HI | RIGHT | PIPE1)},
637 /* end-sanitize-r5900 */
638 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL,MOVE, (LO | RIGHT)},
639 /* start-sanitize-r5900 */
640 {"MTLO1", T5,"011100sssss000000000000000010011",MMINORM,MOVE, (LO | RIGHT | PIPE1)},
641 {"MTSA", T5,"000000sssss000000000000000101001",SPECIAL,MxSA, (TO)},
642 {"MTSAB", T5,"000001sssss11000iiiiiiiiiiiiiiii",REGIMM, MTSAB, (NONE)},
643 {"MTSAH", T5,"000001sssss11001iiiiiiiiiiiiiiii",REGIMM, MTSAH, (NONE)},
644 /* end-sanitize-r5900 */
645 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1, FPMOVE, (FP)},
646 {"MOVN", G2,"000000sssssgggggddddd00000001011",SPECIAL,MOVE, (NOT | EQ)},
647 {"MOVN", G2,"01000110mmmgggggvvvvvrrrrr010011",COP1, FPMOVE, (FP | NOT | EQ)},
648 {"MOV%c", G3,"000000sssssqqq0cddddd00000000001",SPECIAL,FPMOVE, (FP | CONDITIONAL | INTEGER)},
649 {"MOV%c", G3,"01000110mmmqqq0cvvvvvrrrrr010001",COP1, FPMOVE, (FP | CONDITIONAL)},
650 {"MOVZ", G2,"000000sssssgggggddddd00000001010",SPECIAL,MOVE, (EQ)},
651 {"MOVZ", G2,"01000110mmmgggggvvvvvrrrrr010010",COP1, FPMOVE, (FP | EQ)},
652 {"MSUB.D", G3,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X, FPSUB, (FP | MULTIPLY | DOUBLE)},
653 {"MSUB.S", G3,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X, FPSUB, (FP | MULTIPLY | SINGLE)},
654 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1, FPMUL, (FP | HI | LO)},
655 {"MULT", 1,"000000sssssgggggddddd00000011000",SPECIAL,MUL, (OP3 | WORD | WORD32 | HI | LO)},
656 /* start-sanitize-r5900 */
657 {"MULT1", T5,"011100sssssgggggddddd00000011000",MMINORM,MUL, (OP3 | WORD | WORD32 | HI | LO | PIPE1)},
658 /* end-sanitize-r5900 */
659 {"MULTU", 1,"000000sssssgggggddddd00000011001",SPECIAL,MUL, (OP3 | WORD | WORD32 | UNSIGNED | HI | LO)},
660 /* start-sanitize-r5900 */
661 {"MULTU1", T5,"011100sssssgggggddddd00000011001",MMINORM,MUL, (OP3 | WORD | WORD32 | UNSIGNED | HI | LO | PIPE1)},
662 /* end-sanitize-r5900 */
663 {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD)},
664 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1, FPNEG, (FP)},
665 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X, FPADD, (FP | NOT | MULTIPLY | DOUBLE)},
666 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X, FPADD, (FP | NOT | MULTIPLY | SINGLE)},
667 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X, FPSUB, (FP | NOT | MULTIPLY | DOUBLE)},
668 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X, FPSUB, (FP | NOT | MULTIPLY | SINGLE)},
669 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL,OR, (NOT)},
670 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL,OR, (NONE)},
671 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL, OR, (NONE)},
672
673 /* start-sanitize-r5900 */
674 {"PABSH", T5,"01110000000TTTTTddddd00101101000",MMI1, PABS, (HALFWORD)},
675 {"PABSW", T5,"01110000000TTTTTddddd00001101000",MMI1, PABS, (WORD)},
676
677 {"PADDB", T5,"011100SSSSSTTTTTddddd01000001000",MMI0, PADD, (BYTE)},
678 {"PADDH", T5,"011100SSSSSTTTTTddddd00100001000",MMI0, PADD, (HALFWORD)},
679 {"PADDW", T5,"011100SSSSSTTTTTddddd00000001000",MMI0, PADD, (WORD)},
680
681 {"PADDSB", T5,"011100SSSSSTTTTTddddd11000001000",MMI0, PADD, (BYTE | SATURATE)},
682 {"PADDSH", T5,"011100SSSSSTTTTTddddd10100001000",MMI0, PADD, (HALFWORD | SATURATE)},
683 {"PADDSW", T5,"011100SSSSSTTTTTddddd10000001000",MMI0, PADD, (WORD | SATURATE)},
684
685 {"PADDUB", T5,"011100SSSSSTTTTTddddd11000101000",MMI1, PADD, (BYTE | UNSIGNED)},
686 {"PADDUH", T5,"011100SSSSSTTTTTddddd10100101000",MMI1, PADD, (HALFWORD | UNSIGNED)},
687 {"PADDUW", T5,"011100SSSSSTTTTTddddd10000101000",MMI1, PADD, (WORD | UNSIGNED)},
688
689 {"PADSBH", T5,"011100SSSSSTTTTTddddd00100101000",MMI1, PADSBH, (NONE)},
690
691 {"PAND", T5,"011100SSSSSTTTTTddddd10010001001",MMI2, POP, (POP_AND)},
692
693 {"PCEQB", T5,"011100SSSSSTTTTTddddd01010101000",MMI1, PCMP, (EQ | BYTE)},
694 {"PCEQH", T5,"011100SSSSSTTTTTddddd00110101000",MMI1, PCMP, (EQ | HALFWORD)},
695 {"PCEQW", T5,"011100SSSSSTTTTTddddd00010101000",MMI1, PCMP, (EQ | WORD)},
696
697 {"PCGTB", T5,"011100SSSSSTTTTTddddd01010001000",MMI0, PCMP, (GT | BYTE)},
698 {"PCGTH", T5,"011100SSSSSTTTTTddddd00110001000",MMI0, PCMP, (GT | HALFWORD)},
699 {"PCGTW", T5,"011100SSSSSTTTTTddddd00010001000",MMI0, PCMP, (GT | WORD)},
700
701 {"PCPYH", T5,"01110000000TTTTTddddd11011101001",MMI3, PCPYH, (NONE)},
702 {"PCPYLD", T5,"011100SSSSSTTTTTddddd01110001001",MMI2, PCPYLD, (NONE)},
703 {"PCPYUD", T5,"011100SSSSSTTTTTddddd01110101001",MMI3, PCPYUD, (NONE)},
704
705 {"PDIVBW", T5,"011100SSSSSTTTTT0000011101001001",MMI2, PDIVBW, (NONE)},
706 {"PDIVUW", T5,"011100SSSSSTTTTT0000001101101001",MMI3, PDIVW, (UNSIGNED)},
707 {"PDIVW", T5,"011100SSSSSTTTTT0000001101001001",MMI2, PDIVW, (NONE)},
708
709 {"PEXCH", T5,"01110000000TTTTTddddd11010101001",MMI3, PEXCH, (NONE)},
710 {"PEXCW", T5,"01110000000TTTTTddddd11110101001",MMI3, PEXCW, (NONE)},
711 {"PEXOH", T5,"01110000000TTTTTddddd11010001001",MMI2, PEXOH, (NONE)},
712 {"PEXOW", T5,"01110000000TTTTTddddd11110001001",MMI2, PEXOW, (NONE)},
713
714 {"PEXT5", T5,"01110000000TTTTTddddd11110001000",MMI0, PEXT5, (NONE)},
715
716 {"PEXTLB", T5,"011100SSSSSTTTTTddddd11010001000",MMI0, PEXTLB, (NONE)},
717 {"PEXTLH", T5,"011100SSSSSTTTTTddddd10110001000",MMI0, PEXTLH, (NONE)},
718 {"PEXTLW", T5,"011100SSSSSTTTTTddddd10010001000",MMI0, PEXTLW, (NONE)},
719 {"PEXTUB", T5,"011100SSSSSTTTTTddddd11010101000",MMI1, PEXTUB, (NONE)},
720 {"PEXTUH", T5,"011100SSSSSTTTTTddddd10110101000",MMI1, PEXTUH, (NONE)},
721 {"PEXTUW", T5,"011100SSSSSTTTTTddddd10010101000",MMI1, PEXTUW, (NONE)},
722
723 {"PHMADDH",T5,"011100SSSSSTTTTTddddd10001001001",MMI2, PHMADDH, (NONE)},
724 {"PHMSUBH",T5,"011100SSSSSTTTTTddddd10101001001",MMI2, PHMADDH, (SUBTRACT)},
725
726 {"PINTH", T5,"011100SSSSSTTTTTddddd01010001001",MMI2, PINTH, (NONE)},
727 {"PINTOH", T5,"011100SSSSSTTTTTddddd01010101001",MMI3, PINTOH, (NONE)},
728
729 {"PLZCW", T5,"011100SSSSS00000ddddd00000000100",MMINORM,PLZCW, (NONE)},
730
731 {"PMADDH", T5,"011100SSSSSTTTTTddddd10000001001",MMI2, PMULTH, (ADDITION)},
732 {"PMADDUW",T5,"011100SSSSSTTTTTddddd00000101001",MMI3, PMULTW, (ADDITION | UNSIGNED)},
733 {"PMADDW", T5,"011100SSSSSTTTTTddddd00000001001",MMI2, PMULTW, (ADDITION)},
734
735 {"PMAXH", T5,"011100SSSSSTTTTTddddd00111001000",MMI0, PMAXMIN, (GT | HALFWORD)},
736 {"PMAXW", T5,"011100SSSSSTTTTTddddd00011001000",MMI0, PMAXMIN, (GT | WORD)},
737
738 {"PMFHI", T5,"0111000000000000ddddd01000001001",MMI2, PMXX, (HI|FROM)},
739 {"PMFLO", T5,"0111000000000000ddddd01001001001",MMI2, PMXX, (LO|FROM)},
740
741 {"PMFHL", T5,"0111000000000000dddddaaaaa110000",MMINORM,PMFHL, (NONE)},
742
743 {"PMINH", T5,"011100SSSSSTTTTTddddd00111101000",MMI1, PMAXMIN, (LT | HALFWORD)},
744 {"PMINW", T5,"011100SSSSSTTTTTddddd00011101000",MMI1, PMAXMIN, (LT | WORD)},
745
746 {"PMSUBH", T5,"011100SSSSSTTTTTddddd10100001001",MMI2, PMULTH, (SUBTRACT)},
747 {"PMSUBW", T5,"011100SSSSSTTTTTddddd00100001001",MMI2, PMULTW, (SUBTRACT)},
748
749 {"PMTHI", T5,"011100SSSSS000000000001000101001",MMI3, PMXX, (HI|TO)},
750 {"PMTLO", T5,"011100SSSSS000000000001001101001",MMI3, PMXX, (LO|TO)},
751
752 {"PMTHL.LW",T5,"011100SSSSS000000000000000110001",MMINORM,PMTHL, (NONE)},
753
754 {"PMULTH", T5,"011100SSSSSTTTTTddddd11100001001",MMI2, PMULTH, (NONE)},
755 {"PMULTUW",T5,"011100SSSSSTTTTTddddd01100101001",MMI3, PMULTW, (UNSIGNED)},
756 {"PMULTW", T5,"011100SSSSSTTTTTddddd01100001001",MMI2, PMULTW, (NONE)},
757
758 {"PNOR", T5,"011100SSSSSTTTTTddddd10011101001",MMI3, POP, (POP_NOR)},
759 {"POR", T5,"011100SSSSSTTTTTddddd10010101001",MMI3, POP, (POP_OR)},
760
761 {"PPAC5", T5,"01110000000TTTTTddddd11111001000",MMI0, PPAC5, (NONE)},
762
763 {"PPACB", T5,"011100SSSSSTTTTTddddd11011001000",MMI0, PPACB, (NONE)},
764 {"PPACH", T5,"011100SSSSSTTTTTddddd10111001000",MMI0, PPACH, (NONE)},
765 {"PPACW", T5,"011100SSSSSTTTTTddddd10011001000",MMI0, PPACW, (NONE)},
766
767 {"PREVH", T5,"01110000000TTTTTddddd11011001001",MMI2, PREVH, (NONE)},
768 {"PROT3W", T5,"01110000000TTTTTddddd11111001001",MMI2, PROT3W, (NONE)},
769
770 {"PSLLH", T5,"01110000000TTTTTdddddaaaaa110100",MMINORM,PSHIFT, (LEFT | LOGICAL | HALFWORD)},
771 {"PSLLVW", T5,"011100SSSSSTTTTTddddd00010001001",MMI2, PSLLVW, (NONE)},
772 {"PSLLW", T5,"01110000000TTTTTdddddaaaaa111100",MMINORM,PSHIFT, (LEFT | LOGICAL | WORD)},
773
774 {"PSRAH", T5,"01110000000TTTTTdddddaaaaa110111",MMINORM,PSHIFT, (RIGHT | ARITHMETIC | HALFWORD)},
775 {"PSRAVW", T5,"011100SSSSSTTTTTddddd00011101001",MMI3, PSRAVW, (NONE)},
776 {"PSRAW", T5,"01110000000TTTTTdddddaaaaa111111",MMINORM,PSHIFT, (RIGHT | ARITHMETIC | WORD)},
777
778 {"PSRLH", T5,"01110000000TTTTTdddddaaaaa110110",MMINORM,PSHIFT, (RIGHT | LOGICAL | HALFWORD)},
779 {"PSRLVW", T5,"011100SSSSSTTTTTddddd00011001001",MMI2, PSRLVW, (NONE)},
780 {"PSRLW", T5,"01110000000TTTTTdddddaaaaa111110",MMINORM,PSHIFT, (RIGHT | LOGICAL | WORD)},
781
782 {"PSUBB", T5,"011100SSSSSTTTTTddddd01001001000",MMI0, PADD, (SUBTRACT | BYTE)},
783 {"PSUBH", T5,"011100SSSSSTTTTTddddd00101001000",MMI0, PADD, (SUBTRACT | HALFWORD)},
784 {"PSUBSB", T5,"011100SSSSSTTTTTddddd11001001000",MMI0, PADD, (SUBTRACT | SATURATE | BYTE )},
785 {"PSUBSH", T5,"011100SSSSSTTTTTddddd10101001000",MMI0, PADD, (SUBTRACT | SATURATE | HALFWORD)},
786 {"PSUBSW", T5,"011100SSSSSTTTTTddddd10001001000",MMI0, PADD, (SUBTRACT | SATURATE | WORD)},
787 {"PSUBUB", T5,"011100SSSSSTTTTTddddd11001101000",MMI1, PADD, (SUBTRACT | UNSIGNED | BYTE)},
788 {"PSUBUH", T5,"011100SSSSSTTTTTddddd10101101000",MMI1, PADD, (SUBTRACT | UNSIGNED | HALFWORD)},
789 {"PSUBUW", T5,"011100SSSSSTTTTTddddd10001101000",MMI1, PADD, (SUBTRACT | UNSIGNED | WORD)},
790 {"PSUBW", T5,"011100SSSSSTTTTTddddd00001001000",MMI0, PADD, (SUBTRACT | WORD)},
791
792 {"PXOR", T5,"011100SSSSSTTTTTddddd10011001001",MMI2, POP, (POP_XOR)},
793 /* end-sanitize-r5900 */
794
795 {"PREF", G2,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, PREFETCH, (NONE)},
796 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X, FPPREFX, (FP)},
797
798 /* start-sanitize-r5900 */
799 {"QFSRV", T5,"011100SSSSSTTTTTddddd11011101000",MMI1, QFSRV, (NONE)},
800 /* end-sanitize-r5900 */
801
802 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1, FPRECIP, (FP)},
803 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1, FPROUND, (FP | FIXED | DOUBLEWORD)},
804 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1, FPROUND, (FP | FIXED | WORD)},
805 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1, FPSQRT, (FP | RECIP)},
806 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (BYTE)},
807 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | ATOMIC)},
808 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | ATOMIC)},
809 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD)},
810 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | COPROC)},
811 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | COPROC)},
812 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (DOUBLEWORD | LEFT)},
813 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (DOUBLEWORD | RIGHT)},
814 {"SDXC1", G3,"010011sssssgggggvvvvv00000001001",COP1X, STORE, (FP | DOUBLEWORD | COPROC | REG)},
815 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL, STORE, (HALFWORD)},
816 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL,SHIFT, (WORD | LEFT | LOGICAL)}, /* rd = rt << sa */
817 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL,SHIFT, (WORD | LEFT | LOGICAL)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
818 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL,SET, (LT)},
819 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET, (LT)},
820 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL,SET, (LT | UNSIGNED)},
821 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET, (LT | UNSIGNED)},
822 /* start-sanitize-r5900 */
823 {"SQ", T5,"011111sssssTTTTTeeeeeeeeeeeeeeee",NORMAL, STORE, (QUADWORD)},
824 /* end-sanitize-r5900 */
825 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1, FPSQRT, (FP)},
826 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | ARITHMETIC)},
827 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | ARITHMETIC)},
828 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | LOGICAL)},
829 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | LOGICAL)},
830 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL,SUB, (WORD | WORD32 | OVERFLOW)},
831 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1, FPSUB, (FP)},
832 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL,SUB, (WORD | WORD32)},
833 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD)},
834 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | COPROC)},
835 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | COPROC)},
836 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (WORD | LEFT)},
837 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (WORD | RIGHT)},
838 {"SWXC1", G3,"010011sssssgggggvvvvv00000001000",COP1X, STORE, (FP | WORD | COPROC | REG)},
839 {"SYNC", 2,"000000000000000000000aaaaa001111",SPECIAL,SYNC, (NONE)}, /* z = 5bit stype field */
840 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL,SYSCALL, (NOARG)},
841 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL,TRAP, (EQ)},
842 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM, TRAP, (EQ)},
843 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL,TRAP, (GT | EQ)},
844 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM, TRAP, (GT | EQ)},
845 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM, TRAP, (GT | EQ | UNSIGNED)},
846 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL,TRAP, (GT | EQ | UNSIGNED)},
847 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL,TRAP, (LT)},
848 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM, TRAP, (LT)},
849 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM, TRAP, (LT | UNSIGNED)},
850 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL,TRAP, (LT | UNSIGNED)},
851 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL,TRAP, (NOT | EQ)},
852 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM, TRAP, (NOT | EQ)},
853 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1, FPTRUNC, (FP | FIXED | DOUBLEWORD)},
854 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1, FPTRUNC, (FP | FIXED | WORD)},
855 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL,XOR, (NONE)},
856 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL, XOR, (NONE)},
857 {"CACHE", 3,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, CACHE, (NONE)},
858 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL, RSVD, (NONE)},
859 };
860
861 static const struct instruction MIPS16_DECODE[] = {
862 {"ADDIU", 1, "01000xxxddd04444", RRI_A, ADD, WORD | WORD32 },
863 {"ADDIU8", 1, "01001wwwkkkkkkkk", RI, ADD, WORD | WORD32 },
864 {"ADJSP", 1, "01100011KKKKKKKKS", I8, ADD, WORD | WORD32 },
865 {"ADDIUPC", 1, "00001dddAAAAAAAAP", RI, ADD, WORD | WORD32 },
866 {"ADDIUSP", 1, "00000dddAAAAAAAAs", RI, ADD, WORD | WORD32 },
867 {"ADDU", 1, "11100xxxyyyddd01", RRR, ADD, WORD | WORD32 },
868 {"AND", 1, "11101wwwyyy01100", RR, AND, NONE },
869 {"B", 1, "00010qqqqqqqqqqqzZ", I, BRANCH, EQ },
870 {"BEQZ", 1, "00100xxxppppppppz", RI, BRANCH, EQ },
871 {"BNEZ", 1, "00101xxxppppppppz", RI, BRANCH, NOT | EQ },
872 {"BREAK", 1, "01100??????00101", RR, BREAK, NOARG },
873 {"BTEQZ", 1, "01100000pppppppptz", I8, BRANCH, EQ },
874 {"BTNEZ", 1, "01100001pppppppptz", I8, BRANCH, NOT | EQ },
875 {"CMP", 1, "11101xxxyyy01010T", RR, XOR, NONE },
876 {"CMPI", 1, "01110xxxUUUUUUUUT", RI, XOR, NONE },
877 {"DADDIU", 3, "01000xxxddd14444", RRI_A, ADD, DOUBLEWORD },
878 {"DADDIU5", 3, "11111101wwwjjjjj", RI64, ADD, DOUBLEWORD },
879 {"DADJSP", 3, "11111011KKKKKKKKS", I64, ADD, DOUBLEWORD },
880 {"DADIUPC", 3, "11111110dddEEEEEP", RI64, ADD, DOUBLEWORD },
881 {"DADIUSP", 3, "11111111dddEEEEEs", RI64, ADD, DOUBLEWORD },
882 {"DADDU", 3, "11100xxxyyyddd00", RRR, ADD, DOUBLEWORD },
883 {"DDIV", 3, "11101xxxyyy11110", RR, DIV, DOUBLEWORD | HI | LO },
884 {"DDIVU", 3, "11101xxxyyy11111", RR, DIV, DOUBLEWORD | UNSIGNED | HI | LO },
885 {"DIV", 1, "11101xxxyyy11010", RR, DIV, WORD | WORD32 | SIGNEXTEND | HI | LO },
886 {"DIVU", 1, "11101xxxyyy11011", RR, DIV, WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO },
887 {"DMULT", 3, "11101xxxyyy11100", RR, MUL, DOUBLEWORD | HI | LO },
888 {"DMULTU", 3, "11101xxxyyy11101", RR, MUL, DOUBLEWORD | UNSIGNED | HI | LO },
889 {"DSLL", 3, "00110dddyyy[[[01", ISHIFT, SHIFT, DOUBLEWORD | LEFT | LOGICAL },
890 {"DSLLV", 3, "11101xxxvvv10100", RR, SHIFT, DOUBLEWORD | LEFT | LOGICAL | REG },
891 {"DSRA", 3, "11101]]]vvv10011", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC },
892 {"DSRAV", 3, "11101xxxvvv10111", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC | REG},
893 {"DSRL", 3, "11101]]]vvv01000", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL },
894 {"DSRLV", 3, "11101xxxvvv10110", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL | REG},
895 {"DSUBU", 3, "11100xxxyyyddd10", RRR, SUB, DOUBLEWORD | UNSIGNED},
896 #if 0
897 /* FIXME: Should we handle these ourselves, or should we require an
898 emulation routine? */
899 {"EXIT", 1, "1110111100001000", RR, BREAK, EXIT },
900 {"ENTRY", 1, "11101??????01000", RR, BREAK, ENTRY },
901 #endif
902 {"EXTEND", 1, "11110eeeeeeeeeee", I, RSVD, NOARG },
903 {"JALR", 1, "11101xxx01000000R", RR, JUMP, LINK | REG },
904 {"JAL", 1, "00011aaaaaaaaaaa", I, JUMP, LINK },
905 {"JR", 1, "11101xxx00000000", RR, JUMP, NONE },
906 {"JRRA", 1, "1110100000100000r", RR, JUMP, NONE },
907 {"LB", 1, "10000xxxddd55555", RRI, LOAD, BYTE | SIGNEXTEND },
908 {"LBU", 1, "10100xxxddd55555", RRI, LOAD, BYTE },
909 {"LD", 3, "00111xxxdddDDDDD", RRI, LOAD, DOUBLEWORD },
910 {"LDPC", 3, "11111100dddDDDDDP", RI64, LOAD, DOUBLEWORD },
911 {"LDSP", 3, "11111000dddDDDDDs", RI64, LOAD, DOUBLEWORD },
912 {"LH", 1, "10001xxxdddHHHHH", RRI, LOAD, HALFWORD | SIGNEXTEND },
913 {"LHU", 1, "10101xxxdddHHHHH", RRI, LOAD, HALFWORD },
914 {"LI", 1, "01101dddUUUUUUUUZ", RI, OR, NONE },
915 {"LW", 1, "10011xxxdddWWWWW", RRI, LOAD, WORD | SIGNEXTEND },
916 {"LWPC", 1, "10110dddVVVVVVVVP", RI, LOAD, WORD | SIGNEXTEND },
917 {"LWSP", 1, "10010dddVVVVVVVVs", RI, LOAD, WORD | SIGNEXTEND },
918 {"LWU", 1, "10111xxxdddWWWWW", RRI, LOAD, WORD },
919 {"MFHI", 1, "11101ddd00010000", RR, MOVE, HI | LEFT },
920 {"MFLO", 1, "11101ddd00010010", RR, MOVE, LO | LEFT },
921 {"MOVR32", 1, "01100111dddXXXXXz", I8_MOVR32, OR, NONE },
922 {"MOV32R", 1, "01100101YYYYYxxxz", I8_MOV32R, OR, NONE },
923 {"MULT", 1, "11101xxxyyy11000", RR, MUL, WORD | WORD32 | HI | LO},
924 {"MULTU", 1, "11101xxxyyy11001", RR, MUL, WORD | WORD32 | UNSIGNED | HI | LO },
925 {"NEG", 1, "11101dddyyy01011Z", RR, SUB, WORD },
926 {"NOT", 1, "11101dddyyy01111Z", RR, OR, NOT },
927 {"OR", 1, "11101wwwyyy01101", RR, OR, NONE },
928 {"SB", 1, "11000xxxyyy55555", RRI, STORE, BYTE },
929 {"SD", 3, "01111xxxyyyDDDDD", RRI, STORE, DOUBLEWORD },
930 {"SDSP", 3, "11111001yyyDDDDDs", RI64, STORE, DOUBLEWORD },
931 {"SDRASP", 3, "11111010CCCCCCCCsQ", I64, STORE, DOUBLEWORD },
932 {"SH", 1, "11001xxxyyyHHHHH", RRI, STORE, HALFWORD },
933 {"SLL", 1, "00110dddyyy<<<00", ISHIFT, SHIFT, WORD | LEFT | LOGICAL },
934 {"SLLV", 1, "11101xxxvvv00100", RR, SHIFT, WORD | LEFT | LOGICAL | REG},
935 {"SLT", 1, "11101xxxyyy00010T", RR, SET, LT },
936 {"SLTI", 1, "01010xxx88888888T", RI, SET, LT },
937 {"SLTU", 1, "11101xxxyyy00011T", RR, SET, LT | UNSIGNED },
938 {"SLTIU", 1, "01011xxx88888888T", RI, SET, LT | UNSIGNED },
939 {"SRA", 1, "00110dddyyy<<<11", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC },
940 {"SRAV", 1, "11101xxxvvv00111", RR, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC | REG },
941 {"SRL", 1, "00110dddyyy<<<10", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | LOGICAL },
942 {"SRLV", 1, "11101xxxvvv00110", RR, SHIFT, WORD | WORD32 | RIGHT | LOGICAL | REG },
943 {"SUBU", 1, "11100xxxyyyddd11", RRR, SUB, WORD | WORD32 },
944 {"SW", 1, "11011xxxyyyWWWWW", RRI, STORE, WORD },
945 {"SWSP", 1, "11010yyyVVVVVVVVs", RI, STORE, WORD },
946 {"SWRASP", 1, "01100010VVVVVVVVQs", I8, STORE, WORD },
947 {"XOR", 1, "11101wwwyyy01110", RR, XOR, NONE }
948 };
949
950 static int bitmap_val PARAMS ((const char *, int, int));
951 static void build_mips16_operands PARAMS ((const char *));
952 static void build_instruction
953 PARAMS ((int, unsigned int, int, const struct instruction *));
954
955 /*---------------------------------------------------------------------------*/
956
957 static char*
958 name_for_data_len( insn )
959 struct instruction* insn;
960 {
961 if (GETDATASIZEINSN(insn) == BYTE)
962 return "BYTE";
963
964 else if (GETDATASIZEINSN(insn) == HALFWORD)
965 return "HALFWORD";
966
967 else if (GETDATASIZEINSN(insn) == WORD)
968 return "WORD";
969
970 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
971 return "DOUBLEWORD";
972
973 else if (GETDATASIZEINSN(insn) == QUADWORD)
974 return "QUADWORD";
975
976 else
977 return 0;
978 }
979
980 static char*
981 letter_for_data_len( insn )
982 struct instruction* insn;
983 {
984 if (GETDATASIZEINSN(insn) == BYTE)
985 return "B";
986
987 else if (GETDATASIZEINSN(insn) == HALFWORD)
988 return "H";
989
990 else if (GETDATASIZEINSN(insn) == WORD)
991 return "W";
992
993 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
994 return "D";
995
996 else if (GETDATASIZEINSN(insn) == QUADWORD)
997 return "Q";
998
999 else
1000 return 0;
1001 }
1002
1003 static char*
1004 type_for_data_len( insn )
1005 struct instruction* insn;
1006 {
1007 if (GETDATASIZEINSN(insn) == BYTE)
1008 return "int";
1009
1010 else if (GETDATASIZEINSN(insn) == HALFWORD)
1011 return "int";
1012
1013 else if (GETDATASIZEINSN(insn) == WORD)
1014 return "long";
1015
1016 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
1017 return "long long";
1018
1019 else if (GETDATASIZEINSN(insn) == QUADWORD)
1020 return 0;
1021
1022 else
1023 return 0;
1024 }
1025
1026 static char*
1027 max_for_data_len( insn )
1028 struct instruction* insn;
1029 {
1030 if (GETDATASIZEINSN(insn) == BYTE)
1031 return "127";
1032
1033 else if (GETDATASIZEINSN(insn) == HALFWORD)
1034 return "32767";
1035
1036 else if (GETDATASIZEINSN(insn) == WORD)
1037 return "(int)0x7FFFFFFF";
1038
1039 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
1040 return 0;
1041
1042 else if (GETDATASIZEINSN(insn) == QUADWORD)
1043 return 0;
1044
1045 else
1046 return 0;
1047 }
1048
1049 static char*
1050 min_for_data_len( insn )
1051 struct instruction* insn;
1052 {
1053 if (GETDATASIZEINSN(insn) == BYTE)
1054 return "-128";
1055
1056 else if (GETDATASIZEINSN(insn) == HALFWORD)
1057 return "-32768";
1058
1059 else if (GETDATASIZEINSN(insn) == WORD)
1060 return "(int)0x80000000";
1061
1062 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
1063 return 0;
1064
1065 else if (GETDATASIZEINSN(insn) == QUADWORD)
1066 return 0;
1067
1068 else
1069 return 0;
1070 }
1071
1072 static char*
1073 umax_for_data_len( insn )
1074 struct instruction* insn;
1075 {
1076 if (GETDATASIZEINSN(insn) == BYTE)
1077 return "0xFF";
1078
1079 else if (GETDATASIZEINSN(insn) == HALFWORD)
1080 return "0xFFFF";
1081
1082 else if (GETDATASIZEINSN(insn) == WORD)
1083 return "0xFFFFFFFF";
1084
1085 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
1086 return 0;
1087
1088 else if (GETDATASIZEINSN(insn) == QUADWORD)
1089 return 0;
1090
1091 else
1092 return 0;
1093 }
1094
1095 static char*
1096 bits_for_data_len( insn )
1097 struct instruction* insn;
1098 {
1099 if (GETDATASIZEINSN(insn) == BYTE)
1100 return "8";
1101
1102 else if (GETDATASIZEINSN(insn) == HALFWORD)
1103 return "16";
1104
1105 else if (GETDATASIZEINSN(insn) == WORD)
1106 return "32";
1107
1108 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
1109 return "64";
1110
1111 else if (GETDATASIZEINSN(insn) == QUADWORD)
1112 return "128";
1113
1114 else
1115 return 0;
1116 }
1117
1118 /*---------------------------------------------------------------------------*/
1119
1120
1121 void
1122 convert_bitmap(bitmap,onemask,zeromask,dontmask)
1123 char *bitmap;
1124 unsigned int *onemask, *zeromask, *dontmask;
1125 {
1126 int loop; /* current bitmap position */
1127 int lastsp = -1; /* last bitmap field starting position */
1128 int lastoe = -1; /* last bitmap field encoding */
1129
1130 *onemask = 0x00000000;
1131 *zeromask = 0x00000000;
1132 *dontmask = 0x00000000;
1133
1134 if (strlen(bitmap) != 32) {
1135 fprintf(stderr,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap);
1136 exit(3);
1137 }
1138
1139 for (loop = 0; (loop < 32); loop++) {
1140 int oefield ;
1141 for (oefield = 0; (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))); oefield++)
1142 if (bitmap[31 - loop] == opfields[oefield].id)
1143 break;
1144 if (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))) {
1145 if ((lastoe != -1) && (lastoe != oefield))
1146 if ((loop - lastsp) != (opfields[lastoe].flen)) {
1147 fprintf(stderr,"Invalid field length %d for bitmap field '%c' (0x%02X) (should be %d) : bitmap = \"%s\"\n",(loop - lastsp),(((bitmap[31 - loop] < 0x20) || (bitmap[31 - loop] >= 0x7F)) ? '.' : bitmap[31 - loop]),bitmap[31 - loop],opfields[lastoe].flen,bitmap);
1148 exit(4);
1149 }
1150
1151 switch (bitmap[31 - loop]) {
1152 case '0' : /* fixed value */
1153 *zeromask |= (1 << loop);
1154 lastsp = loop;
1155 lastoe = -1;
1156 break;
1157
1158 case '1' : /* fixed value */
1159 *onemask |= (1 << loop);
1160 lastsp = loop;
1161 lastoe = -1;
1162 break;
1163
1164 case '?' : /* fixed value */
1165 *dontmask |= (1 << loop);
1166 lastsp = loop;
1167 lastoe = -1;
1168 break;
1169
1170 default : /* check character encoding */
1171 {
1172 if (opfields[oefield].fpos != -1) {
1173 /* If flag not set, then check starting position: */
1174 if (lastoe != oefield) {
1175 if (loop != opfields[oefield].fpos) {
1176 fprintf(stderr,"Bitmap field '%c' (0x%02X) at wrong offset %d in bitmap \"%s\"\n",(((bitmap[31 - loop] < 0x20) || (bitmap[31 - loop] >= 0x7F)) ? '.' : bitmap[31 - loop]),bitmap[31 - loop],loop,bitmap);
1177 exit(4);
1178 }
1179 lastsp = loop;
1180 lastoe = oefield;
1181 }
1182 }
1183 *dontmask |= (1 << loop);
1184 }
1185 break;
1186 }
1187 } else {
1188 fprintf(stderr,"Unrecognised bitmap character '%c' (0x%02X) at offset %d in bitmap \"%s\"\n",(((bitmap[31 - loop] < 0x20) || (bitmap[31 - loop] >= 0x7F)) ? '.' : bitmap[31 - loop]),bitmap[31 - loop],loop,bitmap);
1189 exit(4);
1190 }
1191 }
1192
1193 /* NOTE: Since we check for the position and size of fields when
1194 parsing the "bitmap" above, we do *NOT* need to check that invalid
1195 field combinations have been used. */
1196 }
1197
1198 /* Get the value of a 16 bit bitstring for a given shift count and
1199 number of bits. */
1200
1201 static int
1202 bitmap_val (bitmap, shift, bits)
1203 const char *bitmap;
1204 int shift;
1205 int bits;
1206 {
1207 const char *s;
1208 int ret;
1209
1210 ret = 0;
1211 s = bitmap + 16 - shift - bits;
1212 for (; bits > 0; --bits)
1213 {
1214 ret <<= 1;
1215 if (*s == '0')
1216 ;
1217 else if (*s == '1')
1218 ret |= 1;
1219 else
1220 abort ();
1221 ++s;
1222 }
1223
1224 return ret;
1225 }
1226
1227 /*---------------------------------------------------------------------------*/
1228
1229 static void
1230 build_operands(doisa,features,insn)
1231 int doisa;
1232 unsigned int features;
1233 instruction* insn;
1234 {
1235 int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
1236 int finish_jump_flag = 0;
1237 int check_mult = 0;
1238 int check_condition_code = 0;
1239 int sfield_used = 0;
1240 int gfield_used = 0;
1241 int any_operand = 0;
1242
1243 int current_field_id = -1;
1244 int bitpos;
1245
1246 for (bitpos=0; bitpos<32; bitpos++) {
1247 if (insn->bitmap[31-bitpos] != current_field_id)
1248 {
1249 int opindex;
1250
1251 current_field_id = insn->bitmap[31-bitpos];
1252
1253 for (opindex = 0; (opindex < (sizeof(opfields) / sizeof(operand_encoding))); opindex++)
1254 if ((opfields[opindex].fpos != -1) && (opfields[opindex].id == insn->bitmap[31-bitpos])) {
1255
1256 any_operand = 1;
1257
1258 printf(" %s %s UNUSED = ",opfields[opindex].type,opfields[opindex].name);
1259
1260 if (opfields[opindex].flags & OP_SIGNX)
1261 printf("SIGNEXTEND((%s)",opfields[opindex].type);
1262
1263 if (opfields[opindex].flags & OP_GPR)
1264 printf("GPR[");
1265
1266 if (opfields[opindex].flags & OP_SHIFT2)
1267 printf("(");
1268
1269 printf("((instruction >> %d) & 0x%08X)",opfields[opindex].fpos,((1 << opfields[opindex].flen) - 1));
1270
1271 if (opfields[opindex].flags & OP_SHIFT2)
1272 printf(" << 2)");
1273
1274 if (opfields[opindex].flags & OP_GPR)
1275 printf("]");
1276
1277 if (opfields[opindex].flags & OP_BITS5)
1278 printf("&0x1F");
1279
1280 if (opfields[opindex].flags & OP_SIGNX)
1281 printf(",%d)",(opfields[opindex].flen + ((opfields[opindex].flags & OP_SHIFT2) ? 2 : 0)));
1282
1283 printf(";\n");
1284
1285 if (opfields[opindex].flags & OP_GPR1)
1286 {
1287 printf(" %s %s1 = GPR1[",opfields[opindex].type,opfields[opindex].name);
1288 printf("((instruction >> %d) & 0x%08X)",
1289 opfields[opindex].fpos,
1290 ((1 << opfields[opindex].flen) - 1));
1291 printf("];\n");
1292 }
1293
1294 if (opfields[opindex].id == 'j')
1295 finish_jump_flag = 1;
1296
1297 if (opfields[opindex].id == 'e')
1298 check_mult = 8;
1299
1300 if (opfields[opindex].id == 'w')
1301 check_mult = 4;
1302
1303 if (opfields[opindex].id == 'w')
1304 check_mult = 2;
1305
1306 if (opfields[opindex].id == 'p')
1307 check_condition_code = 1;
1308
1309 if (opfields[opindex].id == 's')
1310 sfield_used = 1;
1311
1312 if (opfields[opindex].id == 'g')
1313 gfield_used = 1;
1314 }
1315 }
1316 }
1317
1318 if ( !any_operand && !(insn->flags & NOARG)) {
1319 fprintf(stderr,"Bitmap error: Instruction with no operand fields \"%s\"\n",insn->name) ;
1320 exit(5) ;
1321 }
1322
1323 /* Finish constructing the jump address if required: */
1324 if (finish_jump_flag)
1325 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
1326
1327 /* Now perform required operand checks: */
1328
1329 /* The following code has been removed, since it seems perfectly
1330 reasonable to have a non-aligned offset that is added to another
1331 non-aligned base to create an aligned address. Some more
1332 information on exactly what the MIPS IV specification requires is
1333 needed before deciding on the best strategy. Experimentation with a
1334 VR4300 suggests that we do not need to raise the warning. */
1335 #if 0
1336 /* For MIPS IV (and onwards), certain instruction operand values
1337 will give undefined results. For the simulator we could
1338 generate explicit exceptions (i.e. ReservedInstruction) to
1339 make it easier to spot invalid use. However, for the moment we
1340 just raise a warning. NOTE: This is a different check to the
1341 later decoding, which checks for the final address being
1342 valid. */
1343
1344 if (check_mult != 0 && check_mult != 1) {
1345 printf(" if (instruction & 0x%1X)\n", check_mult);
1346 printf(" {\n");
1347 /* NOTE: If we change this to a SignalException(), we must
1348 ensure that the following opcode processing is not
1349 executed. i.e. the code falls straight out to the simulator
1350 control loop. */
1351 printf(" sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
1352 printf(" }\n");
1353 }
1354 #endif
1355
1356 /* The extended condition codes only appeared in ISA IV */
1357 if (check_condition_code && (doisa < 4)) {
1358 printf(" if (condition_code != 0)\n");
1359 printf(" {\n");
1360 printf(" SignalException(ReservedInstruction,instruction);\n");
1361 printf(" }\n");
1362 printf(" else\n");
1363 }
1364
1365 if ((insn->flags & WORD32) && (GETDATASIZEINSN(insn) != WORD)) {
1366 fprintf(stderr,"Error in opcode table: WORD32 set for non-WORD opcode\n");
1367 exit(1);
1368 }
1369
1370 #if 1
1371 /* The R4000 book differs slightly from the MIPS IV ISA
1372 manual. An example is the sign-extension of a 64-bit processor
1373 SUBU operation, and what is meant by an Undefined Result. This
1374 is now provided purely as a warning. After examining a HW
1375 implementation, this is now purely a warning... and the actual
1376 operation is performed, with possibly undefined results. */
1377 if (((insn->flags & WORD32) && proc64) && (features & FEATURE_WARN_RESULT)) {
1378 /* The compiler should optimise out an OR with zero */
1379 printf(" if (%s | %s)\n",(sfield_used ? "NOTWORDVALUE(op1)" : "0"),(gfield_used ? "NOTWORDVALUE(op2)" : "0"));
1380 printf(" UndefinedResult();\n") ;
1381 }
1382 #else
1383 /* Check that the source is a 32bit value */
1384 if ((insn->flags & WORD32) && proc64) {
1385 /* The compiler should optimise out an OR with zero */
1386 printf(" if (%s | %s)\n",(sfield_used ? "NOTWORDVALUE(op1)" : "0"),(gfield_used ? "NOTWORDVALUE(op2)" : "0"));
1387 printf(" UndefinedResult();\n") ;
1388 printf(" else\n") ;
1389 }
1390 #endif
1391
1392 return;
1393 }
1394
1395 /* The mips16 operand table. */
1396
1397 struct mips16_op
1398 {
1399 /* The character which appears in the bitmap string. */
1400 int type;
1401 /* The type of the variable in the simulator. */
1402 const char *vartype;
1403 /* The name of the variable in the simulator. */
1404 const char *name;
1405 /* The number of bits. */
1406 int nbits;
1407 /* The number of bits when extended (zero if can not be extended). */
1408 int extbits;
1409 /* The amount by which the short form is shifted when it is used;
1410 for example, the sw instruction has a shift count of 2. */
1411 int shift;
1412 /* Flags. */
1413 int flags;
1414 };
1415
1416 /* Flags which appears in the mips16 operand table. */
1417
1418 /* Whether this is a mips16 register index. */
1419 #define MIPS16_REG16 (0x1)
1420 /* Whether this is a register value. */
1421 #define MIPS16_REGVAL (0x2)
1422 /* Whether this is a swapped mips32 register index (MOV32R) */
1423 #define MIPS16_REG32_SWAPPED (0x4)
1424 /* Whether this index is also the destination register. */
1425 #define MIPS16_DESTREG (0x8)
1426 /* Whether the short form is unsigned. */
1427 #define MIPS16_UNSP (0x10)
1428 /* Whether the extended form is unsigned. */
1429 #define MIPS16_EXTU (0x20)
1430 /* Implicit stack pointer. */
1431 #define MIPS16_SP (0x40)
1432 /* Implicit program counter. */
1433 #define MIPS16_PC (0x80)
1434 /* Implicit $0. */
1435 #define MIPS16_ZERO (0x100)
1436 /* Implicit $24. */
1437 #define MIPS16_TREG (0x200)
1438 /* Implicit $31. */
1439 #define MIPS16_RA (0x400)
1440 /* Jump address. */
1441 #define MIPS16_JUMP_ADDR (0x800)
1442 /* Branch offset. */
1443 #define MIPS16_BRANCH (0x1000)
1444
1445 /* The mips16 operand table. */
1446
1447 static const struct mips16_op mips16_op_table[] =
1448 {
1449 { 'd', "int", "destreg", 3, 0, 0, MIPS16_REG16 },
1450 { 'x', "t_reg", "op1", 3, 0, 0, MIPS16_REG16 | MIPS16_REGVAL },
1451 { 'w', "t_reg", "op1", 3, 0, 0, MIPS16_REG16|MIPS16_REGVAL|MIPS16_DESTREG},
1452 { 'y', "t_reg", "op2", 3, 0, 0, MIPS16_REG16 | MIPS16_REGVAL },
1453 { 'v', "t_reg", "op2", 3, 0, 0, MIPS16_REG16|MIPS16_REGVAL|MIPS16_DESTREG },
1454 { 'X', "t_reg", "op1", 5, 0, 0, MIPS16_REGVAL },
1455 { 'Y', "int", "destreg", 5, 0, 0, MIPS16_REG32_SWAPPED },
1456 { 'a', "ut_reg", "op1", 11, 0, 0, MIPS16_JUMP_ADDR },
1457 { 'e', "int", "ext", 11, 0, 0, 0 },
1458 { '<', "int", "op1", 3, 5, 0, MIPS16_UNSP | MIPS16_EXTU },
1459 { '>', "int", "op1", 3, 5, 0, MIPS16_UNSP | MIPS16_EXTU },
1460 { '[', "int", "op1", 3, 6, 0, MIPS16_UNSP | MIPS16_EXTU },
1461 { ']', "int", "op1", 3, 6, 0, MIPS16_UNSP | MIPS16_EXTU },
1462 { '4', "int", "op2", 4, 15, 0, 0 },
1463 { '5', "int", "offset", 5, 16, 0, MIPS16_UNSP },
1464 { 'H', "int", "offset", 5, 16, 1, MIPS16_UNSP },
1465 { 'W', "int", "offset", 5, 16, 2, MIPS16_UNSP },
1466 { 'D', "int", "offset", 5, 16, 3, MIPS16_UNSP },
1467 { 'j', "int", "op2", 5, 16, 0, 0 },
1468 { '8', "int", "op2", 8, 16, 0, MIPS16_UNSP },
1469 { 'V', "int", "offset", 8, 16, 2, MIPS16_UNSP },
1470 { 'C', "int", "offset", 8, 16, 3, MIPS16_UNSP },
1471 { 'U', "int", "op2", 8, 16, 0, MIPS16_UNSP | MIPS16_EXTU },
1472 { 'k', "int", "op2", 8, 16, 0, 0 },
1473 { 'K', "int", "op2", 8, 16, 3, 0 },
1474 { 'p', "int", "offset", 8, 16, 0, MIPS16_BRANCH },
1475 { 'q', "int", "offset", 11, 16, 0, MIPS16_BRANCH },
1476 { 'A', "int", "op2", 8, 16, 2, MIPS16_UNSP },
1477 { 'B', "int", "op2", 5, 16, 3, MIPS16_UNSP },
1478 { 'E', "int", "op2", 5, 16, 2, MIPS16_UNSP },
1479
1480 /* The remaining operands are special operands which encode implied
1481 arguments. These only appear at the end of a bitmap string, and
1482 do not represent actual bits. */
1483 { 's', "t_reg", "op1", 0, 0, 0, MIPS16_SP | MIPS16_REGVAL },
1484 { 'S', "t_reg", "op1", 0, 0, 0, MIPS16_SP|MIPS16_REGVAL|MIPS16_DESTREG },
1485 { 'P', "t_reg", "op1", 0, 0, 0, MIPS16_PC },
1486 { 'z', "t_reg", "op2", 0, 0, 0, MIPS16_ZERO },
1487 { 'Z', "t_reg", "op1", 0, 0, 0, MIPS16_ZERO },
1488 { 't', "t_reg", "op1", 0, 0, 0, MIPS16_TREG | MIPS16_REGVAL },
1489 { 'T', "int", "destreg", 0, 0, 0, MIPS16_TREG },
1490 { 'r', "t_reg", "op1", 0, 0, 0, MIPS16_RA | MIPS16_REGVAL },
1491 { 'R', "int", "destreg", 0, 0, 0, MIPS16_RA },
1492 { 'Q', "t_reg", "op2", 0, 0, 0, MIPS16_RA | MIPS16_REGVAL },
1493
1494 { '\0', NULL, NULL, 0, 0, 0, 0 }
1495 };
1496
1497 /* Build mips16 operands. */
1498
1499 static void
1500 build_mips16_operands (bitmap)
1501 const char *bitmap;
1502 {
1503 const char *s;
1504 int start = -1;
1505 const struct mips16_op *op = NULL;
1506 const struct mips16_op *ops[3];
1507 int opindex = 0;
1508 int i;
1509
1510 for (s = bitmap; *s != '\0'; s++)
1511 {
1512 if (op != NULL)
1513 {
1514 if (op->type == *s)
1515 continue;
1516
1517 /* Make sure we saw the right number of bits for that
1518 operand. */
1519 if (op->nbits != 0 && (s - bitmap) - op->nbits != start)
1520 abort ();
1521 op = NULL;
1522 }
1523
1524 if (*s == '0' || *s == '1' || *s == '?')
1525 continue;
1526
1527 start = s - bitmap;
1528
1529 for (op = mips16_op_table; op->type != *s; ++op)
1530 if (op->type == '\0')
1531 abort ();
1532
1533 printf (" %s %s = ", op->vartype, op->name);
1534 if (op->nbits != 0)
1535 printf ("(instruction >> %d) & 0x%x",
1536 16 - (s - bitmap) - op->nbits,
1537 (1 << op->nbits) - 1);
1538 else
1539 {
1540 if ((op->flags & MIPS16_SP) != 0)
1541 printf ("29");
1542 else if ((op->flags & MIPS16_PC) != 0)
1543 {
1544 int j;
1545
1546 printf ("((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : (have_extendval ? IPC - 2 : IPC)) & ~ (uword64) 1)");
1547 for (j = 0; j < opindex; j++)
1548 if (ops[j]->shift != 0)
1549 printf (" & ~ (uword64) 0x%x", (1 << ops[j]->shift) - 1);
1550 }
1551 else if ((op->flags & MIPS16_ZERO) != 0)
1552 printf ("0");
1553 else if ((op->flags & MIPS16_TREG) != 0)
1554 printf ("24");
1555 else if ((op->flags & MIPS16_RA) != 0)
1556 printf ("31");
1557 else
1558 abort ();
1559 }
1560 printf (";\n");
1561
1562 if ((op->flags & MIPS16_DESTREG) != 0)
1563 printf (" int destreg;\n");
1564
1565 if (opindex > 2)
1566 abort ();
1567 ops[opindex] = op;
1568 ++opindex;
1569 }
1570
1571 if (op != NULL)
1572 {
1573 /* Make sure we saw the right number of bits for that
1574 operand. */
1575 if (op->nbits != 0 && 16 - op->nbits != start)
1576 abort ();
1577 }
1578
1579 for (i = 0; i < opindex; i++)
1580 {
1581 op = ops[i];
1582 if ((op->flags & MIPS16_REG16) != 0)
1583 {
1584 printf (" if (%s < 2)\n", op->name);
1585 printf (" %s += 16;\n", op->name);
1586 }
1587 if ((op->flags & MIPS16_REG32_SWAPPED) != 0)
1588 printf (" %s = (%s >> 2) | ((%s & 3) << 3);\n",
1589 op->name, op->name, op->name);
1590 if ((op->flags & MIPS16_DESTREG) != 0)
1591 printf (" destreg = %s;\n", op->name);
1592 if ((op->flags & MIPS16_REGVAL) != 0)
1593 printf (" %s = GPR[%s];\n", op->name, op->name);
1594
1595 if (op->extbits != 0)
1596 {
1597 printf (" if (have_extendval)\n");
1598 printf (" {\n");
1599 if (op->extbits == 16)
1600 printf (" %s |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0);\n",
1601 op->name);
1602 else if (op->extbits == 15)
1603 printf (" %s |= ((extendval & 0xf) << 11) | (extendval & 0x7f0);\n",
1604 op->name);
1605 else if (op->extbits == 6)
1606 printf (" %s = ((extendval >> 6) & 0x1f) | (extendval & 0x20);\n",
1607 op->name);
1608 else
1609 printf (" %s = (extendval >> 6) & 0x1f;\n",
1610 op->name);
1611 if ((op->flags & MIPS16_EXTU) == 0)
1612 {
1613 printf (" if (%s >= 0x%x)\n",
1614 op->name, 1 << (op->extbits - 1));
1615 printf (" %s -= 0x%x;\n",
1616 op->name, 1 << op->extbits);
1617 }
1618 printf (" have_extendval = 0;\n");
1619 printf (" }\n");
1620 printf (" else\n");
1621 printf (" {\n");
1622 if ((op->flags & MIPS16_UNSP) == 0)
1623 {
1624 printf (" if (%s >= 0x%x)\n",
1625 op->name, 1 << (op->nbits - 1));
1626 printf (" %s -= 0x%x;\n",
1627 op->name, 1 << op->nbits);
1628 }
1629 if (op->shift != 0)
1630 printf (" %s <<= %d;\n", op->name, op->shift);
1631 if (op->type == '<' || op->type == '>'
1632 || op->type == '[' || op->type == ']')
1633 {
1634 printf (" if (%s == 0)\n", op->name);
1635 printf (" %s = 8;\n", op->name);
1636 }
1637 printf (" }\n");
1638 }
1639
1640 if ((op->flags & MIPS16_BRANCH) != 0)
1641 printf (" %s *= 2;\n", op->name);
1642
1643 if ((op->flags & MIPS16_JUMP_ADDR) != 0)
1644 {
1645 printf (" {\n");
1646 printf (" uword64 paddr;\n");
1647 printf (" int uncached;\n");
1648 printf (" if (AddressTranslation (PC &~ (uword64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL))\n");
1649 printf (" {\n");
1650 printf (" uword64 memval;\n");
1651 printf (" unsigned int reverse = (ReverseEndian ? 3 : 0);\n");
1652 printf (" unsigned int bigend = (BigEndianCPU ? 3 : 0);\n");
1653 printf (" unsigned int byte;\n");
1654 printf (" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\n");
1655 printf (" LoadMemory (&memval,0,uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
1656 printf (" byte = (((PC &~ (uword64) 1) & 0x7) ^ (bigend << 1));\n");
1657 printf (" memval = (memval >> (8 * byte)) & 0xffff;\n");
1658 printf (" %s = (((%s & 0x1f) << 23)\n", op->name, op->name);
1659 printf (" | ((%s & 0x3e0) << 13)\n", op->name);
1660 printf (" | (memval << 2));\n");
1661 printf (" if ((instruction & 0x400) == 0)\n");
1662 printf (" %s |= 1;\n", op->name);
1663 printf (" PC += 2;\n");
1664 printf (" }\n");
1665 printf (" }\n");
1666 printf (" %s |= PC & ~ (uword64) 0x0fffffff;\n", op->name);
1667 }
1668 }
1669
1670 /* FIXME: Is this the way to detect an unused extend opcode? */
1671 printf (" if (have_extendval)\n");
1672 printf (" SignalException (ReservedInstruction, instruction);\n");
1673 }
1674
1675 /*---------------------------------------------------------------------------*/
1676
1677 typedef enum {
1678 s_left,
1679 s_right
1680 } e_endshift;
1681
1682 static void
1683 build_endian_shift(proc64,datalen,endbit,direction,shift)
1684 int proc64;
1685 int datalen;
1686 int endbit;
1687 e_endshift direction;
1688 int shift;
1689 {
1690 if (datalen == 4) {
1691 printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit,endbit);
1692 printf(" memval %s= %d;\n",direction == s_left ? "<<" : ">>",shift);
1693 printf(" }\n");
1694 }
1695
1696 return;
1697 }
1698
1699 /*---------------------------------------------------------------------------*/
1700 /* doisa = number of MIPS ISA simulator table is being constructed for.
1701 * proc64 = TRUE if constructing 64bit processor world.
1702 * dofp = boolean, TRUE if FP instructions are to be included.
1703 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
1704 */
1705
1706 void
1707 process_instructions(doarch,features)
1708 unsigned int doarch;
1709 unsigned int features;
1710 {
1711 int doisa = (doarch & MASK_ISA);
1712 int limit = (sizeof(MIPS_DECODE) / sizeof(instruction));
1713 int gprlen=((features & FEATURE_GP64) ? 64 : 32);
1714 int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
1715 int dofp = (features & FEATURE_HASFPU);
1716 int fpsingle = (features & FEATURE_FPSINGLE);
1717 int maxisa;
1718 int loop;
1719
1720 if (limit < 1) {
1721 fprintf(stderr,"process_instructions: invalid structure length\n");
1722 exit(1);
1723 }
1724
1725 if (proc64 && (gprlen != 64)) {
1726 fprintf(stderr,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
1727 exit(3);
1728 }
1729
1730 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
1731
1732 maxisa = 0;
1733 for (loop = 0; (loop < limit); loop++)
1734 if ((MIPS_DECODE[loop].isa & MASK_ISA) > maxisa)
1735 maxisa = (MIPS_DECODE[loop].isa & MASK_ISA);
1736
1737 if (doisa == 0)
1738 doisa = maxisa;
1739
1740 printf("#if defined(SIM_MANIFESTS)\n");
1741 printf("#define MIPSISA (%d)\n",doisa);
1742 if (proc64)
1743 printf("#define PROCESSOR_64BIT (1 == 1)\n");
1744 else
1745 printf("#define PROCESSOR_64BIT (1 == 0)\n");
1746 #if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */
1747 printf("#define LOADDRMASK (0x%08X)\n",0x7);
1748 #else
1749 printf("#define LOADDRMASK (0x%08X)\n",(proc64 ? 0x7 : 0x3));
1750 #endif
1751 /* The FP registers are the same width as the CPU registers: */
1752 printf("#define GPRLEN (%d)\n",gprlen);
1753 printf("typedef %s t_reg;\n",((gprlen == 64) ? "word64" : "int"));
1754 printf("typedef %s ut_reg;\n",((gprlen == 64) ? "uword64" : "unsigned int"));
1755 printf("typedef %s t_fpreg;\n",((gprlen == 64) ? "word64" : "int"));
1756 if (dofp)
1757 printf("#define HASFPU (1 == 1)\n");
1758 if (features & FEATURE_FAST)
1759 printf("#define FASTSIM (1 == 1)\n");
1760 if (features & FEATURE_WARN_STALL)
1761 printf("#define WARN_STALL (1 == 1)\n");
1762 if (features & FEATURE_WARN_LOHI)
1763 printf("#define WARN_LOHI (1 == 1)\n");
1764 if (features & FEATURE_WARN_ZERO)
1765 printf("#define WARN_ZERO (1 == 1)\n");
1766 if (features & FEATURE_WARN_MEM)
1767 printf("#define WARN_MEM (1 == 1)\n");
1768 if (features & FEATURE_WARN_R31)
1769 printf("#define WARN_R31 (1 == 1)\n");
1770 if (features & FEATURE_WARN_RESULT)
1771 printf("#define WARN_RESULT (1 == 1)\n");
1772
1773 printf("#else /* simulator engine */\n");
1774
1775 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
1776 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64 ? 64 : 32),doisa,limit);
1777 if (dofp)
1778 printf("/* %sFP instructions included */\n",(fpsingle ? "Single precision " : ""));
1779 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
1780
1781 if (proc64) {
1782 printf("#if !defined(PROCESSOR_64BIT)\n");
1783 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
1784 printf("#endif\n");
1785 }
1786
1787 printf("/* Actual instruction decoding block */\n");
1788 printf("if ((vaddr & 1) == 0){\n");
1789 {
1790 int limit;
1791 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP,OP_MASK_OP);
1792 limit = (OP_MASK_OP + 1);
1793
1794 printf("#ifdef DEBUG\n");
1795 printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n");
1796 printf("#endif\n");
1797
1798 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
1799 limit += (OP_MASK_SPEC + 1);
1800
1801 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_RT,OP_MASK_RT);
1802 limit += (OP_MASK_RT + 1);
1803
1804 printf("else if (num == 0x11) {\n");
1805 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM,OP_SH_COP1NORM,(OP_MASK_COP1NORM << OP_SH_COP1NORM));
1806 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP,OP_SH_COP1CMP,(OP_MASK_COP1CMP << OP_SH_COP1CMP));
1807 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,(OP_MASK_SPEC & (OP_MASK_COP1CMP << OP_SH_COP1CMP)));
1808 printf(" else\n");
1809 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
1810 limit += (OP_MASK_SPEC + 1);
1811
1812 printf(" else\n");
1813 /* To keep this code quick, we just clear out the "to" bit
1814 here. The proper (though slower) code would be to have another
1815 conditional, checking whether this instruction is a branch or
1816 not, before limiting the range to the bottom two bits of the
1817 move operation. */
1818 printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit,OP_SH_COP1SPEC,OP_MASK_COP1SPEC,OP_MASK_COP1SCLR);
1819 limit += (OP_MASK_COP1SPEC + 1);
1820
1821 printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
1822 limit += (OP_MASK_SPEC + 1);
1823
1824 printf("else if (num == 0x1C) {\n");
1825 printf(" int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI,OP_MASK_MMI);
1826
1827 printf(" if (mmi_func == 0x08) \n");
1828 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
1829 limit += (OP_MASK_MMISUB + 1);
1830
1831 printf(" else if (mmi_func == 0x28) \n");
1832 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
1833 limit += (OP_MASK_MMISUB + 1);
1834
1835 printf(" else if (mmi_func == 0x09) \n");
1836 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
1837 limit += (OP_MASK_MMISUB + 1);
1838
1839 printf(" else if (mmi_func == 0x29) \n");
1840 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
1841 limit += (OP_MASK_MMISUB + 1);
1842
1843 printf(" else \n");
1844 printf(" num = (%d + mmi_func);\n",limit);
1845 limit += (OP_MASK_MMI + 1);
1846
1847 printf("}\n");
1848
1849 printf("/* Total possible switch entries: %d */\n",limit) ;
1850 }
1851
1852 printf("#ifdef DEBUG\n");
1853 printf("printf(\"DBG: num = %%d\\n\",num);\n");
1854 printf("#endif\n");
1855
1856 printf("switch (num)\n") ;
1857 printf("{\n");
1858
1859 for (loop = 0; (loop < limit); loop++) {
1860 /* First check if the insn is in a requested isa# independent set,
1861 then check that the ISA number we are constructing for is
1862 valid, then if the instruction matches any of the
1863 architecture specific flags. NOTE: We allow a selected ISA of
1864 zero to be used to match all standard instructions. */
1865 unsigned int isa = MIPS_DECODE[loop].isa;
1866 if (((isa & doarch & MASK_ISA_INDEP)
1867 || (((isa & MASK_ISA) <= doisa)
1868 && (((isa & MASK_ISA_DEP) == 0) || ((isa & MASK_ISA_DEP) & doarch) != 0)))
1869 && (!(MIPS_DECODE[loop].flags & FP) || ((MIPS_DECODE[loop].flags & FP) && dofp))) {
1870 unsigned int onemask;
1871 unsigned int zeromask;
1872 unsigned int dontmask;
1873 unsigned int mask;
1874 unsigned int number;
1875
1876 convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask);
1877
1878 if (!(MIPS_DECODE[loop].flags & COPROC)
1879 && ((GETDATASIZEINSN(&MIPS_DECODE[loop]) == DOUBLEWORD) && !proc64)) {
1880 fprintf(stderr,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE[loop].name);
1881 exit(4);
1882 }
1883
1884 #if defined(DEBUG)
1885 printf("/* DEBUG: onemask 0x%08X */\n",onemask) ;
1886 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask) ;
1887 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask) ;
1888 #endif
1889
1890 switch (MIPS_DECODE[loop].mark) {
1891 case NORMAL :
1892 mask = (OP_MASK_OP << OP_SH_OP) ;
1893 number = ((onemask >> OP_SH_OP) & OP_MASK_OP) ;
1894 break ;
1895
1896 case SPECIAL :
1897 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
1898 number = ((OP_MASK_OP + 1) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ;
1899 break ;
1900
1901 case REGIMM :
1902 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_RT << OP_SH_RT)) ;
1903 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_RT) & OP_MASK_RT)) ;
1904 break ;
1905
1906 case COP1 :
1907 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
1908 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ;
1909 break ;
1910
1911 case COP1S :
1912 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_COP1SPEC << OP_SH_COP1SPEC)) ;
1913 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_COP1SPEC) & OP_MASK_COP1SPEC)) ;
1914 break;
1915
1916 case COP1X :
1917 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
1918 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ;
1919 break ;
1920
1921 case MMI0 :
1922 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
1923 | (OP_MASK_MMISUB << OP_SH_MMISUB));
1924 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)
1925 + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
1926 + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
1927 break ;
1928
1929 case MMI1 :
1930 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
1931 | (OP_MASK_MMISUB << OP_SH_MMISUB));
1932 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)
1933 + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
1934 + (OP_MASK_MMISUB + 1)
1935 + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
1936 break ;
1937
1938 case MMI2 :
1939 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
1940 | (OP_MASK_MMISUB << OP_SH_MMISUB));
1941 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)
1942 + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
1943 + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
1944 + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
1945 break ;
1946
1947 case MMI3 :
1948 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
1949 | (OP_MASK_MMISUB << OP_SH_MMISUB));
1950 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)
1951 + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
1952 + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
1953 + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
1954 break ;
1955
1956 case MMINORM :
1957 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)) ;
1958 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)
1959 + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
1960 + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
1961 + (OP_MASK_MMISUB + 1)
1962 + ((onemask >> OP_SH_MMI) & OP_MASK_MMI)) ;
1963 break ;
1964
1965 default :
1966 fprintf(stderr,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE[loop].mark,loop,MIPS_DECODE[loop].name) ;
1967 exit(5) ;
1968 }
1969
1970 printf("case %d : /* \"%s\" %s */\n",number,MIPS_DECODE[loop].name,MIPS_DECODE[loop].bitmap) ;
1971
1972 #if defined(DEBUG)
1973 printf("/* DEBUG: mask 0x%08X */\n",mask) ;
1974 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE[loop].name);
1975 #endif
1976
1977 /* Check if there are any other explicit bits in the instruction: */
1978 if ((~mask & (onemask | zeromask)) != 0x00000000) {
1979 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask | zeromask),onemask) ;
1980 printf(" {\n") ;
1981 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1982 printf(" }\n") ;
1983 printf(" else\n") ;
1984 }
1985
1986 printf(" {\n") ;
1987
1988 /* Get hold of the operands */
1989 /* NOTE: If we wanted to make the simulator code smaller, we
1990 * could pull these into a common sequence before we perform
1991 * the instruction decoding. However, this would affect the
1992 * performance since unnecessary field extraction would be
1993 * occurring for certain instructions.
1994 *
1995 * Also we do not perform checking for multiple definitions of a
1996 * particular operand here, since they are caught by the
1997 * compilation of the produced code.
1998 */
1999 build_operands(doisa, features, &MIPS_DECODE[loop]);
2000
2001 printf(" {\n") ;
2002
2003 build_instruction (doisa, features, 0, &MIPS_DECODE[loop]);
2004
2005 printf(" }\n") ;
2006 printf(" }\n") ;
2007 printf(" break ;\n") ;
2008 }
2009 }
2010
2011 printf("default : /* Unrecognised instruction */\n") ;
2012 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2013 printf(" break ;\n") ;
2014 printf("}\n}\n") ;
2015
2016 /* Handle mips16 instructions. The switch table looks like this:
2017 0 - 31: I, RI, and RRI instructions by major.
2018 32 - 35: ISHIFT instructions by function + 32
2019 36 - 37: RRI_A instructions by function + 36
2020 38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38
2021 46 - 49: RRR instructions by function + 46
2022 50 - 81: RR instructions by minor + 50 (except for minor == 0)
2023 82 - 89: I64 and RI64 instructions by funct + 82
2024 90 - 97: jalr (RR minor 0) by y + 90
2025 */
2026 printf ("else {\n");
2027 printf ("static int extendval;\n");
2028 printf ("static int have_extendval;\n");
2029 printf ("int num = ((instruction >> %d) & 0x%08X);\n",
2030 MIPS16OP_SH_OP, MIPS16OP_MASK_OP);
2031 printf ("switch (num)\n{\n");
2032 printf ("case 0x6: num = 32 + (instruction & 3); break;\n");
2033 printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n");
2034 printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n");
2035 printf ("case 0x1c: num = 46 + (instruction & 3); break;\n");
2036 printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n");
2037 printf (" if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n");
2038 printf (" break;\n");
2039 printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n");
2040 printf ("default: break;\n}\n");
2041 printf ("switch (num)\n{\n");
2042
2043 for (loop = 0; loop < sizeof MIPS16_DECODE / sizeof MIPS16_DECODE[0]; loop++)
2044 {
2045 const char *bitmap;
2046 int num;
2047
2048 if (! proc64 && GETDATASIZEINSN (&MIPS16_DECODE[loop]) == DOUBLEWORD)
2049 continue;
2050
2051 bitmap = MIPS16_DECODE[loop].bitmap;
2052 switch (MIPS16_DECODE[loop].mark)
2053 {
2054 case I:
2055 case RI:
2056 case RRI:
2057 num = bitmap_val (bitmap, 11, 5);
2058 break;
2059 case ISHIFT:
2060 num = 32 + bitmap_val (bitmap, 0, 2);
2061 break;
2062 case RRI_A:
2063 num = 36 + bitmap_val (bitmap, 4, 1);
2064 break;
2065 case I8:
2066 case I8_MOV32R:
2067 case I8_MOVR32:
2068 num = 38 + bitmap_val (bitmap, 8, 3);
2069 break;
2070 case RRR:
2071 num = 46 + bitmap_val (bitmap, 0, 2);
2072 break;
2073 case RR:
2074 {
2075 int minor;
2076
2077 minor = bitmap_val (bitmap, 0, 5);
2078 if (minor != 0)
2079 num = 50 + minor;
2080 else
2081 num = 90 + bitmap_val (bitmap, 5, 3);
2082 }
2083 break;
2084 case I64:
2085 case RI64:
2086 num = 82 + bitmap_val (bitmap, 8, 3);
2087 break;
2088 default:
2089 abort ();
2090 }
2091
2092 printf ("case %d: /* \"%s\" %s */\n", num, MIPS16_DECODE[loop].name,
2093 bitmap);
2094
2095 printf (" {\n");
2096
2097 build_mips16_operands (bitmap);
2098
2099 printf (" {\n") ;
2100
2101 /* build_instruction doesn't know about extend. */
2102 if (num != 30)
2103 build_instruction (doisa, features, 1, &MIPS16_DECODE[loop]);
2104 else
2105 {
2106 printf (" extendval = ext;\n");
2107 printf (" have_extendval = 1;\n");
2108 }
2109
2110 printf (" }\n");
2111 printf (" }\n") ;
2112 printf (" break ;\n") ;
2113 }
2114
2115 printf ("default : /* Unrecognised instruction */\n") ;
2116 printf (" SignalException(ReservedInstruction,instruction);\n") ;
2117 printf (" break ;\n") ;
2118 printf ("}\n}\n") ;
2119
2120 printf("#endif /* simulator engine */\n");
2121
2122 return ;
2123 }
2124
2125 /* Output the code to execute an instruction, assuming the operands
2126 have already been extracted. */
2127
2128 static void
2129 build_instruction (doisa, features, mips16, insn)
2130 int doisa;
2131 unsigned int features;
2132 int mips16;
2133 const struct instruction *insn;
2134 {
2135 int gprlen=((features & FEATURE_GP64) ? 64 : 32);
2136 int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
2137 char *regtype = ((gprlen == 64) ? "uword64" : "unsigned int");
2138
2139 switch (insn->type) {
2140 /* TODO: To make these easier to edit and maintain, they should
2141 actually be provided as source macros (or inline functions)
2142 OUTSIDE this main switch statement. The PPC simulator has a
2143 neater scheme for describing the instruction sequences. */
2144
2145 case ADD:
2146 case SUB:
2147 {
2148 char *signed_basetype = "unknown";
2149 char *unsigned_basetype = "unknown";
2150
2151 switch (GETDATASIZEINSN(insn)) {
2152 case WORD :
2153 signed_basetype = "signed int";
2154 unsigned_basetype = "unsigned int";
2155 break;
2156 case DOUBLEWORD :
2157 signed_basetype = "word64";
2158 unsigned_basetype = "uword64";
2159 break;
2160 default :
2161 fprintf(stderr,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZEINSN(insn));
2162 exit(1);
2163 }
2164
2165 if ((insn->type) == ADD) {
2166 printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype, unsigned_basetype);
2167 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype);
2168 if (insn->flags & OVERFLOW) {
2169 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
2170 printf(" SignalException(IntegerOverflow);\n");
2171 printf(" else\n");
2172 }
2173 if (!proc64 || (insn->flags & UNSIGNED) || (GETDATASIZEINSN(insn) == DOUBLEWORD))
2174 printf(" GPR[destreg] = (%s)temp;\n",regtype);
2175 else /* only sign-extend when placing 32bit result in 64bit processor */
2176 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
2177 } else { /* SUB */
2178 printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype, unsigned_basetype);
2179 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype);
2180 if (insn->flags & OVERFLOW) { /* different signs => overflow if result_sign != arg_sign */
2181 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
2182 printf(" SignalException(IntegerOverflow);\n");
2183 printf(" else\n");
2184 }
2185 /* UNSIGNED 32bit operations on a 64bit processor should
2186 *STILL* be sign-extended. We have cheated in the
2187 data-structure, by not marking it with UNSIGNED, and not
2188 setting OVERFLOW. */
2189 if (!proc64 || (insn->flags & UNSIGNED) || (GETDATASIZEINSN(insn) == DOUBLEWORD))
2190 printf(" GPR[destreg] = (%s)temp;\n",regtype);
2191 else /* only sign-extend when placing 32bit result in 64bit processor */
2192 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
2193 }
2194 }
2195 break ;
2196
2197 case MUL:
2198 {
2199 char* pipe = (insn->flags & PIPE1) ? "1" : "";
2200
2201 if (features & FEATURE_WARN_LOHI) {
2202 printf(" CHECKHILO(\"Multiplication\");\n");
2203 }
2204 printf(" {\n");
2205 if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
2206 printf(" uword64 mid;\n");
2207 printf(" uword64 midhi;\n");
2208 printf(" uword64 temp;\n");
2209 if ((insn->flags & UNSIGNED) == 0)
2210 {
2211 printf(" int sign = 0;\n");
2212 printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n");
2213 printf(" if (op2 < 0) { op2 = - op2; ++sign; }\n");
2214 }
2215 printf(" LO%s = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n",pipe);
2216 printf(" HI%s = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n",pipe);
2217 printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
2218 printf(" midhi = SET64HI(WORD64LO(mid));\n");
2219 printf(" temp = (LO%s + midhi);\n",pipe);
2220 printf(" if ((temp == midhi) ? (LO%s != 0) : (temp < midhi))\n",pipe);
2221 printf(" HI%s += 1;\n",pipe);
2222 printf(" HI%s += WORD64HI(mid);\n",pipe);
2223 printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
2224 printf(" midhi = SET64HI(WORD64LO(mid));\n");
2225 printf(" LO%s = (temp + midhi);\n",pipe);
2226 printf(" if ((LO%s == midhi) ? (temp != 0) : (LO%s < midhi))\n",pipe,pipe);
2227 printf(" HI%s += 1;\n",pipe);
2228 printf(" HI%s += WORD64HI(mid);\n",pipe);
2229 if ((insn->flags & UNSIGNED) == 0)
2230 printf(" if (sign & 1) { LO%s = - LO%s; HI%s = (LO%s == 0 ? 0 : -1) - HI%s; }\n",pipe,pipe,pipe,pipe,pipe);
2231 } else {
2232 if (insn->flags & UNSIGNED)
2233 printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
2234 else
2235 printf(" uword64 temp = ((word64) op1 * (word64) op2);\n");
2236 printf(" LO%s = SIGNEXTEND((%s)WORD64LO(temp),32);\n",pipe,regtype);
2237 printf(" HI%s = SIGNEXTEND((%s)WORD64HI(temp),32);\n",pipe,regtype);
2238 }
2239 if (insn->flags & OP3)
2240 {
2241 printf(" if ( destreg != 0 )\n");
2242 printf(" GPR[destreg] = LO%s;\n",pipe);
2243 }
2244 printf(" }\n");
2245 break ;
2246 }
2247 case DIV:
2248 {
2249 int boolU = (insn->flags & UNSIGNED);
2250 char* pipe = (insn->flags & PIPE1) ? "1" : "";
2251
2252 if (features & FEATURE_WARN_LOHI) {
2253 printf(" CHECKHILO(\"Division\");\n");
2254 }
2255 printf(" {\n");
2256
2257 if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
2258 printf(" %sword64 d1 = op1;\n", (boolU ? "u" : ""));
2259 printf(" %sword64 d2 = op2;\n", (boolU ? "u" : ""));
2260 printf(" if (d2 == 0)\n");
2261 printf(" {\n");
2262 printf(" LO%s = 0x8000000000000000LL;\n", pipe);
2263 printf(" HI%s = 0;\n", pipe);
2264 printf(" }\n");
2265 printf(" else if (d2 == -1 && d1 == 0x8000000000000000LL)\n");
2266 printf(" {\n");
2267 printf(" LO%s = 0x8000000000000000LL;\n", pipe);
2268 printf(" HI%s = 0;\n", pipe);
2269 printf(" }\n");
2270 printf(" else\n");
2271 printf(" {\n");
2272 printf(" LO%s = (d1 / d2);\n", pipe);
2273 printf(" HI%s = (d1 %% d2);\n", pipe);
2274 printf(" }\n");
2275 } else {
2276 printf(" %sint d1 = op1;\n", (boolU ? "unsigned " : ""));
2277 printf(" %sint d2 = op2;\n", (boolU ? "unsigned " : ""));
2278 printf(" if (d2 == 0)\n");
2279 printf(" {\n");
2280 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe);
2281 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe);
2282 printf(" }\n");
2283 printf(" else if (d2 == -1 && d1 == 0x80000000)\n");
2284 printf(" {\n");
2285 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe);
2286 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe);
2287 printf(" }\n");
2288 printf(" else\n");
2289 printf(" {\n");
2290 printf(" LO%s = SIGNEXTEND((d1 / d2),32);\n", pipe);
2291 printf(" HI%s = SIGNEXTEND((d1 %% d2),32);\n", pipe);
2292 printf(" }\n");
2293 }
2294 printf(" }\n");
2295 }
2296 break ;
2297
2298 case SHIFT:
2299 {
2300 int datalen = GETDATASIZEINSN(insn);
2301 int bits = ((datalen == WORD) ? 32 : 64);
2302 char *ltype = ((datalen == WORD) ? "unsigned int" : "uword64");
2303
2304 /* Check that the specified SHIFT is valid: */
2305 if ((datalen == BYTE) || (datalen == HALFWORD)) {
2306 fprintf(stderr,"Shift \"%s\" specified with BYTE or HALFWORD\n",insn->name);
2307 exit(9);
2308 }
2309 if ((insn->flags & LEFT) && (insn->flags & RIGHT)) {
2310 fprintf(stderr,"Shift \"%s\" specified with both LEFT and RIGHT\n",insn->name);
2311 exit(9);
2312 }
2313 if (!(insn->flags & LEFT) && !(insn->flags & RIGHT)) {
2314 fprintf(stderr,"Shift \"%s\" specified with neither LEFT or RIGHT\n",insn->name);
2315 exit(9);
2316 }
2317 if ((insn->flags & LOGICAL) && (insn->flags & ARITHMETIC)) {
2318 fprintf(stderr,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",insn->name);
2319 exit(9);
2320 }
2321 if (!(insn->flags & LOGICAL) && !(insn->flags & ARITHMETIC)) {
2322 fprintf(stderr,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",insn->name);
2323 exit(9);
2324 }
2325 if ((insn->flags & LEFT) && (insn->flags & ARITHMETIC)) {
2326 fprintf(stderr,"Arithmetic LEFT shift \"%s\" specified\n",insn->name);
2327 exit(9);
2328 }
2329
2330 /* Work around an MSC code generation bug by precomputing a value
2331 * with the sign bit set. */
2332 if (insn->flags & ARITHMETIC)
2333 printf(" %s highbit = (%s)1 << %d;\n", ltype, ltype, bits - 1);
2334
2335 /* If register specified shift, then extract the relevant shift amount: */
2336 if (insn->flags & REG)
2337 printf(" op1 &= 0x%02X;\n",(bits - 1));
2338
2339 /* If HI32 specified, then shift range is 32..63 */
2340 if (insn->flags & HI32)
2341 printf(" op1 |= (1 << 5);\n");
2342
2343 /* We do not need to perform pre-masking with 0xFFFFFFFF when
2344 dealing with 32bit shift lefts, since the sign-extension
2345 code will replace any remaining hi-bits: */
2346 if (insn->flags & LEFT)
2347 printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
2348 else
2349 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits == 32) ? " & 0xFFFFFFFF" : ""));
2350
2351 /* For ARITHMETIC shifts, we must duplicate the sign-bit. We
2352 don't do this if op1 is zero, since it is not needed and
2353 since that would cause an undefined shift of the number of
2354 bits in the type. */
2355 if (insn->flags & ARITHMETIC)
2356 printf(" GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype,bits);
2357
2358 /* Ensure WORD values are sign-extended into 64bit registers */
2359 if ((bits == 32) && (gprlen == 64))
2360 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits);
2361 }
2362 break ;
2363
2364 case MOVE:
2365 if (insn->flags & (HI | LO)) {
2366 char *regname = ((insn->flags & LO) ? "LO" : "HI");
2367 int pipe1 = (insn->flags & PIPE1);
2368 if (insn->flags & LEFT)
2369 printf(" GPR[destreg] = %s%s;\n",regname,(pipe1 ? "1" : ""));
2370 else {
2371 if (features & FEATURE_WARN_LOHI) {
2372 printf(" if (%s%sACCESS != 0)\n",regname,(pipe1 ? "1" : ""));
2373 printf(" sim_warning(\"MT (move-to) over-writing %s register value\");\n",regname);
2374 }
2375 printf(" %s%s = op1;\n",regname,(pipe1 ? "1" : ""));
2376 }
2377 if (features & FEATURE_WARN_LOHI)
2378 printf(" %s%sACCESS = 3; /* 3rd instruction will be safe */\n",regname,(pipe1 ? "1" : ""));
2379 } else
2380 if (insn->flags & SHIFT16)
2381 printf(" GPR[destreg] = (op2 << 16);\n");
2382 else {
2383 /* perform conditional move */
2384 if (!(insn->flags & EQ)) {
2385 fprintf(stderr,"Standard conditional %s does not have the equality flag\n",insn->name);
2386 exit(8);
2387 }
2388 printf(" if (op2 %c= 0)\n",((insn->flags & NOT) ? '!' : '='));
2389 printf(" GPR[destreg] = op1;\n");
2390 }
2391 break ;
2392
2393 case SYNC:
2394 printf(" SyncOperation(op1);\n");
2395 break ;
2396
2397 case SYSCALL:
2398 printf(" SignalException(SystemCall,instruction);\n");
2399 break ;
2400
2401 case BREAK:
2402 printf(" SignalException(BreakPoint,instruction);\n");
2403 break ;
2404
2405 case TRAP:
2406 {
2407 int boolNOT = (insn->flags & NOT);
2408 int boolEQ = (insn->flags & EQ);
2409 int boolGT = (insn->flags & GT);
2410 int boolLT = (insn->flags & LT);
2411 int boolU = (insn->flags & UNSIGNED);
2412
2413 if (boolGT && boolLT) {
2414 fprintf(stderr,"GT and LT specified for \"%s\"\n",insn->name);
2415 exit(8);
2416 }
2417
2418 if (boolNOT && (boolGT || boolLT)) {
2419 fprintf(stderr,"NOT specified with GT or LT specified for \"%s\"\n",insn->name);
2420 exit(8);
2421 }
2422
2423 printf(" if ((%sword64)op1 ",(boolU ? "u" : ""));
2424 printf("%c%s",(boolNOT ? '!' : (boolLT ? '<' : (boolGT ? '>' : '='))),(boolEQ ? "=" : ""));
2425 printf(" (%sword64)op2)\n",(boolU ? "u" : ""));
2426 printf(" SignalException(Trap,instruction);\n");
2427 }
2428 break ;
2429
2430 case SET:
2431 {
2432 int boolU = (insn->flags & UNSIGNED);
2433
2434 if (!(insn->flags & LT)) {
2435 fprintf(stderr,"Set instruction without LT specified \"%s\"\n",insn->name);
2436 exit(8);
2437 }
2438
2439 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU ? "u" : ""),(boolU ? "u" : ""));
2440 printf(" GPR[destreg] = 1;\n");
2441 printf(" else\n");
2442 printf(" GPR[destreg] = 0;\n");
2443 }
2444 break ;
2445
2446 case AND:
2447 printf(" GPR[destreg] = (op1 & op2);\n");
2448 break ;
2449
2450 case OR:
2451 /* The default mips16 nop instruction does an or to register
2452 zero; catch that case, so that we don't get useless warnings
2453 from the simulator. */
2454 if (mips16)
2455 printf (" if (destreg != 0)\n");
2456 printf(" GPR[destreg] = %s(op1 | op2);\n",((insn->flags & NOT) ? "~" : ""));
2457 break ;
2458
2459 case XOR:
2460 printf(" GPR[destreg] = (op1 ^ op2);\n");
2461 break ;
2462
2463 case DECODE:
2464 printf(" decode_coproc(instruction);\n");
2465 break ;
2466
2467 case CACHE:
2468 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
2469 /* The virtual address is translated to a physical address using the TLB */
2470 /* The hint specifies a cache operation for that address */
2471 printf(" uword64 vaddr = (op1 + offset);\n");
2472 printf(" uword64 paddr;\n");
2473 printf(" int uncached;\n");
2474 /* NOTE: We are assuming that the AddressTranslation is a load: */
2475 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2476 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
2477 break;
2478
2479 case MADD16: /* VR4100 specific multiply-add instructions */
2480 /* Some of this code is shared with the standard multiply
2481 routines, so an effort should be made to merge where
2482 possible. */
2483 if (features & FEATURE_WARN_LOHI) {
2484 printf(" CHECKHILO(\"Multiply-Add\");\n");
2485 }
2486 if (features & FEATURE_WARN_RESULT) {
2487 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
2488 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
2489 printf(" sim_warning(\"MADD16 operation with non-16bit operands\");\n");
2490 }
2491 printf(" {\n");
2492 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
2493 if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
2494 printf(" LO = LO + temp;\n");
2495 } else { /* WORD */
2496 printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
2497 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype);
2498 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype);
2499 }
2500 printf(" }\n");
2501 break;
2502
2503 case RSVD: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
2504 if (doisa < 4) {
2505 printf(" if (CoProcPresent(3))\n");
2506 printf(" SignalException(CoProcessorUnusable);\n");
2507 printf(" else\n");
2508 }
2509 printf(" SignalException(ReservedInstruction,instruction);\n");
2510 break ;
2511
2512 case JUMP:
2513 if (insn->flags & LINK) {
2514 if (!(insn->flags & REG))
2515 printf(" int destreg = 31;\n");
2516 printf(" GPR[destreg] = (PC + %d); /* NOTE: The PC is already %d ahead within the simulator */\n",
2517 mips16 ? 2 : 4, mips16 ? 2 : 4);
2518 }
2519
2520 if (insn->flags & NOT)
2521 printf(" op1 ^= 1;\n");
2522
2523 printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n");
2524 printf(" so we just truncate it to 32 bits here. */\n");
2525 printf(" op1 = WORD64LO(op1);\n");
2526 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
2527 printf(" DSPC = op1;\n");
2528 if (insn->flags & LINK)
2529 printf(" JALDELAYSLOT();\n");
2530 else
2531 printf(" DELAYSLOT();\n");
2532 break ;
2533
2534 case BRANCH: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
2535 if (insn->flags & FP) {
2536 if (doisa < 4) {
2537 printf(" if (condition_code != 0)\n");
2538 printf(" SignalException(ReservedInstruction,instruction);\n");
2539 printf(" else {\n");
2540 }
2541 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
2542 printf(" int condition = (%s == boolean);\n",((doisa < 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
2543 } else {
2544 if ((insn->flags & NOT) && !(insn->flags & EQ)) {
2545 fprintf(stderr,"NOT specified when not EQ in \"%s\"\n",insn->name);
2546 exit(7);
2547 }
2548 if ((insn->flags & NOT) && (insn->flags & (GT | LT))) {
2549 fprintf(stderr,"NOT specified with GT or LT in \"%s\"\n",insn->name);
2550 exit(7);
2551 }
2552 /* GT LT */
2553 if (insn->flags & GT)
2554 printf(" int condition = (op1 >%s 0);\n",((insn->flags & EQ) ? "=" : ""));
2555 else
2556 if (insn->flags & LT)
2557 printf(" int condition = (op1 <%s 0);\n",((insn->flags & EQ) ? "=" : ""));
2558 else
2559 if (insn->flags & EQ)
2560 printf(" int condition = (op1 %c= op2);\n",((insn->flags & NOT) ? '!' : '='));
2561 }
2562
2563 if (insn->flags & LINK) {
2564 if (features & FEATURE_WARN_R31) {
2565 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS,OP_MASK_RS);
2566 printf(" sim_warning(\"Branch with link using r31 as source operand\");\n");
2567 }
2568 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
2569 }
2570
2571 if (! mips16) {
2572 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
2573 printf(" if (condition) {\n");
2574 printf(" DSPC = (PC + offset);\n");
2575 printf(" DELAYSLOT();\n");
2576 printf(" }\n");
2577 } else {
2578 /* No delayed slots for mips16 branches. */
2579 printf(" if (condition)\n");
2580 printf(" PC = PC + offset;\n");
2581 }
2582 if ((insn->flags & FP) && (doisa != 1)) {
2583 printf(" else if (likely) {\n");
2584 printf(" NULLIFY();\n");
2585 printf(" }\n");
2586 } else if (insn->flags & LIKELY) {
2587 printf(" else\n");
2588 printf(" NULLIFY();\n");
2589 }
2590 if ((insn->flags & FP) && (doisa < 4))
2591 printf(" }\n");
2592 break ;
2593
2594 case PREFETCH: /* The beginning is shared with normal load operations */
2595 case LOAD:
2596 case STORE:
2597 {
2598 int isload = ((insn->type == LOAD) || (insn->type == PREFETCH));
2599 int datalen;
2600 char *accesslength = "<UNKNOWN>";
2601
2602 switch (GETDATASIZEINSN(insn)) {
2603 case BYTE :
2604 datalen = 1;
2605 accesslength = "AccessLength_BYTE";
2606 break ;
2607
2608 case HALFWORD :
2609 datalen = 2;
2610 accesslength = "AccessLength_HALFWORD";
2611 break ;
2612
2613 case WORD :
2614 datalen = 4;
2615 accesslength = "AccessLength_WORD";
2616 break ;
2617
2618 case DOUBLEWORD :
2619 datalen = 8;
2620 accesslength = "AccessLength_DOUBLEWORD";
2621 break ;
2622
2623 case QUADWORD :
2624 datalen = 16;
2625 accesslength = "AccessLength_QUADWORD";
2626 break ;
2627 }
2628
2629 if (insn->flags & REG)
2630 printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
2631 else
2632 printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
2633 printf(" uword64 paddr;\n");
2634 printf(" int uncached;\n");
2635
2636 /* The following check should only occur on normal (non-shifted) memory loads */
2637 if ((datalen != 1) && !(insn->flags & (LEFT | RIGHT))) {
2638 printf(" if ((vaddr & %d) != 0)\n",(datalen - 1));
2639 printf(" SignalException(%s);\n",(isload ? "AddressLoad" : "AddressStore"));
2640 printf(" else\n") ;
2641 }
2642
2643 printf(" {\n");
2644 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload ? "isLOAD" : "isSTORE"));
2645
2646 if (insn->type == PREFETCH)
2647 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
2648 else {
2649 printf(" {\n");
2650 printf(" uword64 memval = 0;\n");
2651 printf(" uword64 memval1 = 0;\n");
2652
2653 if ((insn->flags & COPROC) && ((datalen != 4) && (datalen != 8))) {
2654 fprintf(stderr,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn->name);
2655 exit(6);
2656 }
2657
2658 if (insn->flags & (LEFT | RIGHT)) {
2659 if ((insn->flags & LEFT) && (insn->flags & RIGHT)) {
2660 fprintf(stderr,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",insn->name);
2661 exit(4);
2662 }
2663
2664 switch (datalen) {
2665 case 8:
2666 if (!proc64) {
2667 fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn->name);
2668 exit(4);
2669 }
2670 /* fall through to... */
2671 case 4:
2672 {
2673 printf(" uword64 mask = %d;\n",((datalen == 8) ? 0x7 : 0x3));
2674 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
2675 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
2676 printf(" int byte;\n");
2677 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
2678 printf(" byte = ((vaddr & mask) ^ bigend);\n");
2679 printf(" if (%s!ByteSwapMem)\n",((insn->flags & LEFT) ? "!" : ""));
2680 printf(" paddr &= ~mask;\n");
2681
2682 if (isload) {
2683 if (insn->flags & LEFT)
2684 {
2685 printf(" LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
2686 }
2687 else
2688 {
2689 printf(" LoadMemory(&memval,&memval1,uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
2690 }
2691 }
2692
2693 if (insn->flags & LEFT) {
2694 if (isload) {
2695 /* For WORD transfers work out if the value will
2696 be in the top or bottom of the DOUBLEWORD
2697 returned: */
2698 #if 1
2699 build_endian_shift(proc64,datalen,2,s_right,32);
2700 #else
2701 if (proc64 && (datalen == 4)) {
2702 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2703 printf(" memval >>= 32;\n");
2704 printf(" }\n");
2705 }
2706 #endif
2707 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen - 1),(datalen - 1));
2708 if (proc64 && (datalen == 4))
2709 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2710 } else { /* store */
2711 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen - 1));
2712 #if 1
2713 build_endian_shift(proc64,datalen,2,s_left,32);
2714 #else
2715 /* TODO: This is duplicated in the LOAD code
2716 above - and the RIGHT LOAD and STORE code
2717 below. It should be merged if possible. */
2718 if (proc64 && (datalen == 4)) {
2719 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2720 printf(" memval <<= 32;\n");
2721 printf(" }\n");
2722 }
2723 #endif
2724 printf(" StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);\n");
2725 }
2726 } else { /* RIGHT */
2727 if (isload) {
2728 #if 1
2729 build_endian_shift(proc64,datalen,2,s_right,32);
2730 #else
2731 if (proc64 && (datalen == 4)) {
2732 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2733 printf(" memval >>= 32;\n");
2734 printf(" }\n");
2735 }
2736 #endif
2737 printf(" {\n");
2738 printf(" uword64 srcmask;\n");
2739 /* All of this extra code is just a bodge
2740 required because some hosts don't allow
2741 ((v) << 64). The SPARC just leaves the (v)
2742 value un-touched. */
2743 printf(" if (byte == 0)\n");
2744 printf(" srcmask = 0;\n");
2745 printf(" else\n");
2746 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen);
2747 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n");
2748 printf(" }\n");
2749 if (proc64 && (datalen == 4))
2750 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2751 } else { /* store */
2752 printf(" memval = ((uword64) op2 << (byte * 8));\n");
2753 build_endian_shift(proc64,datalen,2,s_left,32);
2754 printf(" StoreMemory(uncached,(%s - byte),memval,memval1,paddr,vaddr,isREAL);\n",accesslength);
2755 }
2756 }
2757 }
2758 break;
2759
2760 default:
2761 fprintf(stderr,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",insn->name);
2762 exit(6);
2763 }
2764 } else { /* normal memory transfer */
2765 if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) {
2766 fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name);
2767 exit(4);
2768 /* TODO: The R4000 documentation states that a LWU
2769 instruction executed when in a 32bit processor mode
2770 should cause a ReservedInstruction exception. This
2771 will mean adding a run-time check into the code
2772 sequence. */
2773 }
2774
2775 if (isload) {
2776 #if 1 /* see the comments attached to LOADDRMASK above */
2777 printf(" uword64 mask = 0x7;\n");
2778 #else
2779 printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
2780 #endif
2781 printf(" unsigned int shift = %d;\n",(datalen >> 1));
2782 printf(" unsigned int reverse UNUSED = (ReverseEndian ? (mask >> shift) : 0);\n");
2783 printf(" unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0);\n");
2784 printf(" unsigned int byte UNUSED;\n");
2785
2786 /* TODO: This should really also check for 32bit world performing 32bit access */
2787 if (datalen < 8) /* not for DOUBLEWORD or QUADWORD*/
2788 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2789
2790 printf(" LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength);
2791
2792 /* The following will only make sense if the
2793 "LoadMemory" above returns a DOUBLEWORD entity */
2794 if (datalen < 8) { /* not for DOUBLEWORD or QUADWORD*/
2795 int valmask;
2796 switch (datalen) {
2797 case 1:
2798 valmask = 0xFF;
2799 break;
2800
2801 case 2:
2802 valmask = 0xFFFF;
2803 break;
2804
2805 case 4:
2806 valmask = 0xFFFFFFFF;
2807 break;
2808
2809 default:
2810 fprintf(stderr,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen,insn->name);
2811 exit(4);
2812 }
2813 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2814 /* NOTE: The R4000 user manual has the COP_LW
2815 occuring in the same cycle as the rest of the
2816 instruction, yet the MIPS IV shows the operation
2817 happening on the next cycle. To keep the simulator
2818 simple, this code follows the R4000
2819 manual. Experimentation with a silicon
2820 implementation will be needed to ascertain the
2821 correct operation. */
2822 if (insn->flags & COPROC)
2823 printf(" COP_LW(%s,destreg,(unsigned int)",
2824 ((insn->flags & REG)
2825 ? "1"
2826 : "((instruction >> 26) & 0x3)"));
2827 else
2828 printf(" GPR[destreg] = (");
2829
2830 if (insn->flags & SIGNEXTEND)
2831 printf("SIGNEXTEND(");
2832 printf("((memval >> (8 * byte)) & 0x%08X)",valmask);
2833 if (insn->flags & SIGNEXTEND)
2834 printf(",%d)",(datalen * 8));
2835 printf(");\n");
2836 } else {
2837 if (insn->flags & COPROC)
2838 printf(" COP_LD(%s,destreg,memval);;\n",
2839 ((insn->flags & REG)
2840 ? "1"
2841 : "((instruction >> 26) & 0x3)"));
2842 else
2843 {
2844 printf(" GPR[destreg] = memval;\n");
2845 if (datalen > 8)
2846 printf(" GPR1[destreg] = memval1;\n");
2847 }
2848 }
2849 } else { /* store operation */
2850 if ((datalen == 1) || (datalen == 2)) {
2851 /* SH and SB */
2852 #if 1 /* see the comments attached to LOADDRMASK above */
2853 printf(" uword64 mask = 0x7;\n");
2854 #else
2855 printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
2856 #endif
2857 printf(" unsigned int shift = %d;\n",(datalen >> 1));
2858 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
2859 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
2860 printf(" unsigned int byte;\n");
2861
2862 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2863 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2864 printf(" memval = ((uword64) op2 << (8 * byte));\n");
2865 } else
2866 if (datalen == 4) { /* SC and SW */
2867 #if 1 /* see the comments attached to LOADDRMASK above */
2868 printf(" uword64 mask = 0x7;\n");
2869 #else
2870 printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
2871 #endif
2872 printf(" unsigned int byte;\n");
2873 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
2874 printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
2875 if (insn->flags & COPROC)
2876 printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n",
2877 ((insn->flags & REG)
2878 ? "1"
2879 : "((instruction >> 26) & 0x3)"),
2880 ((insn->flags & FP) ? "fs" : "destreg"));
2881 else
2882 printf(" memval = ((uword64) op2 << (8 * byte));\n");
2883 } else if (datalen <= 8) { /* SD and SCD */
2884 if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) {
2885 fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name);
2886 exit(4);
2887 }
2888 if (insn->flags & COPROC)
2889 printf(" memval = (uword64)COP_SD(%s,%s);\n",
2890 ((insn->flags & REG)
2891 ? "1"
2892 : "((instruction >> 26) & 0x3)"),
2893 ((insn->flags & FP) ? "fs" : "destreg"));
2894 else
2895 printf(" memval = op2;\n");
2896 } else { /* wider than 8 */
2897 if (insn->flags & COPROC) {
2898 fprintf(stderr,"COPROC not available for 128 bit operations \"%s\"\n",insn->name);
2899 exit(4);
2900 }
2901 printf(" memval = rt_reg;\n");
2902 printf(" memval1 = rt_reg1;\n");
2903 }
2904
2905 if (insn->flags & ATOMIC)
2906 printf(" if (LLBIT)\n");
2907
2908 printf(" {\n");
2909 printf(" StoreMemory(uncached,%s,memval,memval1,paddr,vaddr,isREAL);\n",accesslength);
2910 printf(" }\n");
2911 }
2912
2913 if (insn->flags & ATOMIC) {
2914 if ((datalen != 4) && (datalen != 8)) {
2915 fprintf(stderr,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",insn->name);
2916 exit(4);
2917 } else
2918 if (isload)
2919 printf(" LLBIT = 1;\n");
2920 else {
2921 /* The documentation states that:
2922
2923 SC *WILL* fail if coherent store into the same
2924 block occurs, or if an exception occurs between
2925 the LL and SC instructions.
2926
2927 SC *MAY* fail if a load, store or prefetch is
2928 executed on the processor (VR4300 doesn't seem
2929 to), or if the instructions between the LL and
2930 SC are not in a 2048byte contiguous VM range.
2931
2932 SC *MUST* have been preceded by an LL
2933 (i.e. LLBIT will be set), and it must use the
2934 same Vaddr, Paddr and cache-coherence algorithm
2935 as the LL (which means we should store this
2936 information from the load-conditional).
2937 */
2938 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT,OP_MASK_RT);
2939 }
2940 }
2941 }
2942 printf(" }\n");
2943 }
2944 printf(" }\n");
2945 }
2946 break ;
2947
2948 case FPPREFX:
2949 /* This code could be merged with the PREFIX generation above: */
2950 printf(" uword64 vaddr = ((uword64)op1 + (uword64)op2);\n");
2951 printf(" uword64 paddr;\n");
2952 printf(" int uncached;\n");
2953 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2954 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
2955 break ;
2956
2957 case FPMOVEC:
2958 if (insn->flags & CONTROL) {
2959 /* The following "magic" of interpreting the FP
2960 control-register number would not be needed if we were not
2961 trying to match our internal register numbers with those
2962 used by GDB. */
2963 printf(" if (to) {\n");
2964 if (doisa < 4) {
2965 printf(" if (fs == 0) {\n");
2966 printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
2967 printf(" } else if (fs == 31) {\n");
2968 printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
2969 printf(" } /* else NOP */\n");
2970 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
2971 } else {
2972 printf(" if (fs == 0) {\n");
2973 printf(" FCR0 = WORD64LO(GPR[ft]);\n");
2974 printf(" } else if (fs == 31) {\n");
2975 printf(" FCR31 = WORD64LO(GPR[ft]);\n");
2976 printf(" } /* else NOP */\n");
2977 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
2978 }
2979 printf(" } else { /* control from */\n");
2980 if (doisa < 4) {
2981 printf(" if (fs == 0) {\n");
2982 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
2983 printf(" } else if (fs == 31) {\n");
2984 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
2985 printf(" } /* else NOP */\n");
2986 } else {
2987 printf(" if (fs == 0) {\n");
2988 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
2989 printf(" } else if (fs == 31) {\n");
2990 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
2991 printf(" } /* else NOP */\n");
2992 }
2993 printf(" }\n");
2994 } else {
2995 printf(" if (to) {\n");
2996 if (GETDATASIZEINSN(insn) == WORD) {
2997 if (doisa < 4) {
2998 printf(" if (SizeFGR() == 64) {\n");
2999 printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
3000 printf(" } else { \n");
3001 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3002 printf(" }\n");
3003 } else {
3004 printf(" if (SizeFGR() == 64)\n");
3005 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
3006 printf(" else\n");
3007 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3008 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3009 }
3010 } else if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
3011 if (doisa < 4) {
3012 printf(" if (SizeFGR() == 64) {\n");
3013 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
3014 printf(" } else\n");
3015 printf(" if ((fs & 0x1) == 0)\n");
3016 printf(" {\n");
3017 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
3018 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3019 printf(" }\n");
3020 if (features & FEATURE_WARN_RESULT) {
3021 printf(" else\n");
3022 printf(" UndefinedResult();\n");
3023 }
3024 } else {
3025 printf(" if (SizeFGR() == 64) {\n");
3026 printf(" FGR[fs] = GPR[ft];\n");
3027 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3028 printf(" } else\n");
3029 printf(" if ((fs & 0x1) == 0)\n");
3030 printf(" {\n");
3031 printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
3032 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3033 printf(" fpr_state[fs + 1] = fmt_uninterpreted;\n");
3034 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3035 printf(" }\n");
3036 if (features & FEATURE_WARN_RESULT) {
3037 printf(" else\n");
3038 printf(" UndefinedResult();\n");
3039 }
3040 }
3041 } else {
3042 fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
3043 exit(1);
3044 }
3045 printf(" } else {\n");
3046 if (GETDATASIZEINSN(insn) == WORD) {
3047 if (doisa < 4) /* write-back occurs in next cycle */
3048 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
3049 else /* in this cycle */
3050 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
3051 } else if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
3052 if (doisa < 4) {
3053 printf(" if (SizeFGR() == 64) {\n");
3054 printf(" PENDING_FILL(ft,FGR[fs]);\n");
3055 printf(" } else\n");
3056 printf(" if ((fs & 0x1) == 0) {\n");
3057 printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
3058 printf(" } else {\n");
3059 printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3060 if (features & FEATURE_WARN_RESULT)
3061 printf(" UndefinedResult();\n");
3062 printf(" }\n");
3063 } else {
3064 printf(" if (SizeFGR() == 64)\n");
3065 printf(" GPR[ft] = FGR[fs];\n");
3066 printf(" else\n");
3067 printf(" if ((fs & 0x1) == 0)\n");
3068 printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
3069 printf(" else {\n");
3070 printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3071 if (features & FEATURE_WARN_RESULT)
3072 printf(" UndefinedResult();\n");
3073 printf(" }\n");
3074 }
3075 } else {
3076 fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
3077 exit(1);
3078 }
3079 printf(" }\n");
3080 }
3081 break ;
3082
3083 case FPMOVE:
3084 if (insn->flags & CONDITIONAL) {
3085 if (insn->flags & INTEGER) { /* moving GPR - testing FGR */
3086 printf(" if (GETFCC(condition_code) == boolean)\n");
3087 printf(" GPR[destreg] = op1;\n");
3088 } else {
3089 if (insn->flags & EQ) /* moving FGR - testing GPR */
3090 printf(" if (op2 %c= 0)\n",((insn->flags & NOT) ? '!' : '='));
3091 else
3092 printf(" if (GETFCC(condition_code) == boolean)\n");
3093 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3094 printf(" else\n");
3095 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
3096 }
3097 } else { /* simple MOVE */
3098 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3099 }
3100 break ;
3101
3102 case FPNEG:
3103 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3104 printf(" SignalException(ReservedInstruction,instruction);\n");
3105 printf(" else\n");
3106 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
3107 break ;
3108
3109 case FPABS:
3110 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3111 printf(" SignalException(ReservedInstruction,instruction);\n");
3112 printf(" else\n");
3113 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
3114 break ;
3115
3116 case FPDIV:
3117 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3118 printf(" SignalException(ReservedInstruction,instruction);\n");
3119 printf(" else\n");
3120 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3121 break ;
3122
3123 case FPMUL:
3124 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3125 printf(" SignalException(ReservedInstruction,instruction);\n");
3126 printf(" else\n");
3127 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3128 break ;
3129
3130 case FPRECIP:
3131 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3132 printf(" SignalException(ReservedInstruction,instruction);\n");
3133 printf(" else\n");
3134 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
3135 break ;
3136
3137 case FPSQRT:
3138 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3139 printf(" SignalException(ReservedInstruction,instruction);\n");
3140 printf(" else\n");
3141 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((insn->flags & RECIP) ? "Recip" : ""));
3142 break ;
3143
3144 case FPCEIL:
3145 case FPFLOOR:
3146 case FPTRUNC:
3147 case FPROUND:
3148 {
3149 char *op = "";
3150 char *type = "";
3151
3152 switch (insn->type) {
3153 case FPCEIL:
3154 op = "FP_RM_TOPINF";
3155 break;
3156 case FPFLOOR:
3157 op = "FP_RM_TOMINF";
3158 break;
3159 case FPTRUNC:
3160 op = "FP_RM_TOZERO";
3161 break;
3162 case FPROUND:
3163 op = "FP_RM_NEAREST";
3164 break;
3165 default:
3166 fprintf(stderr,"Error: Handled missing for FP reason code %d\n",insn->type);
3167 exit(1);
3168 }
3169
3170 switch (GETDATASIZEINSN(insn)) {
3171 case WORD :
3172 type = "fmt_word";
3173 break;
3174 case DOUBLEWORD :
3175 type = "fmt_long";
3176 break;
3177 default:
3178 fprintf(stderr,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op);
3179 exit(1);
3180 }
3181 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3182 printf(" SignalException(ReservedInstruction,instruction);\n");
3183 printf(" else\n");
3184 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type,op,type);
3185 }
3186 break ;
3187
3188 case FPCONVERT:
3189 {
3190 char *type = "";
3191 switch (GETDATASIZEINSN(insn)) {
3192 case SINGLE:
3193 type = "fmt_single";
3194 break;
3195 case DOUBLE:
3196 type = "fmt_double";
3197 break;
3198 case WORD:
3199 type = "fmt_word";
3200 break;
3201 case DOUBLEWORD:
3202 type = "fmt_long";
3203 break;
3204 default :
3205 fprintf(stderr,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn));
3206 exit(1);
3207 }
3208
3209 /* Not all combinations of conversion are valid at the
3210 moment: When converting to a fixed-point format, only
3211 floating-point sources are allowed. */
3212 printf(" if ((format == %s) | %s)\n",type,((insn->flags & FIXED) ? "((format == fmt_long) || (format == fmt_word))": "0"));
3213 printf(" SignalException(ReservedInstruction,instruction);\n");
3214 printf(" else\n");
3215 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type,type);
3216 }
3217 break ;
3218
3219 case FPSUB:
3220 if (insn->flags & MULTIPLY) {
3221 char *type = "";
3222 switch (GETDATASIZEINSN(insn)) {
3223 case SINGLE:
3224 type = "fmt_single";
3225 break;
3226 case DOUBLE:
3227 type = "fmt_double";
3228 break;
3229 default:
3230 fprintf(stderr,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn));
3231 exit(1);
3232 }
3233 printf(" StoreFPR(destreg,%s,%s(Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",type,((insn->flags & NOT) ? "Negate" : ""),type,type,type,type,type,type);
3234 } else {
3235 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3236 printf(" SignalException(ReservedInstruction,instruction);\n");
3237 printf(" else\n");
3238 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3239 }
3240 break ;
3241
3242 case FPADD:
3243 if (insn->flags & MULTIPLY) {
3244 char *type = "";
3245 switch (GETDATASIZEINSN(insn)) {
3246 case SINGLE:
3247 type = "fmt_single";
3248 break;
3249 case DOUBLE:
3250 type = "fmt_double";
3251 break;
3252 default:
3253 fprintf(stderr,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn));
3254 exit(1);
3255 }
3256 if (insn->flags & NOT)
3257 printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
3258 type, type, type, type, type, type, type);
3259 else
3260 printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
3261 type, type, type, type, type, type);
3262 } else {
3263 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3264 printf(" SignalException(ReservedInstruction,instruction);\n");
3265 printf(" else\n");
3266 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3267 }
3268 break ;
3269
3270 case FPCOMPARE:
3271 /* For the MIPS I,II or III there *MUST* be at least one
3272 instruction between the compare that sets a condition code
3273 and the branch that tests it. NOTE: However the hardware
3274 does not detect this condition. */
3275 /* Explicitly limit the operation to S and D formats: */
3276 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3277 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3278 printf(" else {\n");
3279 if (doisa < 4) {
3280 printf(" if (condition_code != 0)\n");
3281 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3282 printf(" else\n");
3283 }
3284 printf(" {\n");
3285 printf(" int ignore = 0;\n");
3286 printf(" int less = 0;\n");
3287 printf(" int equal = 0;\n");
3288 printf(" int unordered = 1;\n");
3289 printf(" uword64 ofs = ValueFPR(fs,format);\n");
3290 printf(" uword64 oft = ValueFPR(ft,format);\n");
3291 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
3292 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
3293 printf(" FCSR |= FP_CAUSE(IO);\n");
3294 printf(" SignalException(FPE);\n");
3295 printf(" ignore = 1;\n");
3296 printf(" }\n");
3297 printf(" } else {\n");
3298 printf(" less = Less(ofs,oft,format);\n");
3299 printf(" equal = Equal(ofs,oft,format);\n");
3300 printf(" unordered = 0;\n");
3301 printf(" }\n");
3302 printf(" if (!ignore) {\n");
3303 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
3304 printf(" SETFCC(condition_code,condition);\n");
3305 printf(" }\n");
3306 printf(" }\n");
3307 printf(" }\n");
3308 break ;
3309
3310 /* start-sanitize-r5900 */
3311 case MADD:
3312 {
3313 char* pipeline = (insn->flags & PIPE1) ? "1" : "";
3314 int notsigned = (insn->flags & UNSIGNED);
3315 char* prodtype = notsigned ? "uword64" : "word64";
3316
3317 printf("%s prod = (%s)WORD64(WORD64LO(HI%s),WORD64LO(LO%s)) + ((%s)%s(op1%s) * (%s)%s(op2%s));\n",
3318 prodtype, prodtype, pipeline, pipeline,
3319 prodtype, (notsigned ? "WORD64LO" : "SIGNEXTEND"), (notsigned ? "" : ",32"),
3320 prodtype, (notsigned ? "WORD64LO" : "SIGNEXTEND"), (notsigned ? "" : ",32")
3321 );
3322 printf("GPR[destreg] = LO%s = SIGNEXTEND(prod,32);\n", pipeline );
3323 printf("HI%s = SIGNEXTEND( WORD64HI(prod), 32);\n", pipeline );
3324 break;
3325 }
3326
3327 case MxSA:
3328 {
3329 if (insn->flags & TO)
3330 printf("SA = op1;\n");
3331 else
3332 printf("GPR[destreg] = SA;\n");
3333 break;
3334 }
3335
3336 case MTSAB:
3337 printf("SA = ((op1 & 0xF) ^ (op2 & 0xF)) * 8;\n");
3338 break;
3339
3340 case MTSAH:
3341 printf("SA = ((op1 & 0x7) ^ (op2 & 0x7)) * 16;\n");
3342 break;
3343
3344 case QFSRV:
3345 printf("int bytes = (SA / 8) %% 16;\n"); /* mod 16 to avoid garbage */
3346 printf("if (SA %% 8)\n");
3347 printf(" SignalException(ReservedInstruction,instruction);\n");
3348 printf("else\n");
3349 printf(" {\n");
3350 printf(" int i;\n");
3351 printf(" for(i=0;i<(16-bytes);i++)\n");
3352 printf(" GPR_SB(destreg,i) = RT_SB(bytes+i);\n");
3353 printf(" for(;i<16;i++)\n");
3354 printf(" GPR_SB(destreg,i) = RS_SB(i-(16-bytes));\n");
3355 printf(" }\n");
3356 break;
3357
3358 case PADD:
3359 {
3360 char* op = (insn->flags & SUBTRACT) ? "-" : "+";
3361 char* name = name_for_data_len( insn );
3362 char* letter = letter_for_data_len( insn );
3363
3364 char* tmptype;
3365 char* maximum;
3366 char* minimum;
3367 char* signedness;
3368 char* signletter;
3369
3370 if ( insn->flags & UNSIGNED )
3371 {
3372 tmptype = type_for_data_len( insn );
3373 signedness = "unsigned";
3374 signletter = "U";
3375 maximum = umax_for_data_len( insn );
3376 minimum = 0;
3377 }
3378 else if ( insn->flags & SATURATE )
3379 {
3380 tmptype = type_for_data_len( insn );
3381 signedness = "";
3382 signletter = "S";
3383 maximum = max_for_data_len( insn );
3384 minimum = min_for_data_len( insn );
3385 }
3386 else
3387 {
3388 tmptype = type_for_data_len( insn );
3389 signedness = "";
3390 signletter = "S";
3391 maximum = 0;
3392 minimum = 0;
3393 }
3394
3395 printf("int i;\n");
3396 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3397 printf(" {\n");
3398 printf(" %s %s r = RS_%s%s(i) %s RT_%s%s(i);\n", signedness, tmptype, signletter, letter, op, signletter, letter );
3399 if ( maximum )
3400 {
3401 printf(" if (r > %s) GPR_%s%s(destreg,i) = %s;\n", maximum, signletter, letter, maximum );
3402 if ( minimum )
3403 printf(" else if (r < %s) GPR_%s%s(destreg,i) = %s;\n", minimum, signletter, letter, minimum );
3404 printf(" else ");
3405 }
3406 printf("GPR_%s%s(destreg,i) = r;\n", signletter, letter );
3407 printf(" }\n");
3408 break;
3409 }
3410
3411 case PMULTH:
3412 {
3413 char* op;
3414 if ( insn->flags & SUBTRACT )
3415 op = "-";
3416 else if ( insn->flags & ADDITION )
3417 op = "+";
3418 else
3419 op = "";
3420
3421 printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op);
3422 printf(" LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op);
3423 printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op);
3424 printf(" HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op);
3425 printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op);
3426 printf(" LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op);
3427 printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op);
3428 printf(" HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op);
3429 break;
3430 }
3431
3432 case PMULTW:
3433 {
3434 char* op;
3435 char* sign = (insn->flags & UNSIGNED) ? "U" : "S";
3436 char* prodtype = (insn->flags & UNSIGNED) ? "uword64" : "word64";
3437 char* constructor = (insn->flags & UNSIGNED) ? "UWORD64" : "WORD64";
3438
3439 printf("%s prod0;\n", prodtype );
3440 printf("%s prod1;\n", prodtype );
3441
3442 if ( insn->flags & SUBTRACT )
3443 {
3444 op = "-";
3445 printf("prod0 = %s( HI_SW(0), LO_SW(0) );\n", constructor );
3446 printf("prod1 = %s( HI_SW(2), LO_SW(2) );\n", constructor );
3447 }
3448 else if ( insn->flags & ADDITION )
3449 {
3450 op = "+";
3451 printf("prod0 = %s( HI_SW(0), LO_SW(0) );\n", constructor );
3452 printf("prod1 = %s( HI_SW(2), LO_SW(2) );\n", constructor );
3453 }
3454 else
3455 op = "";
3456
3457 printf("prod0 %s= (%s)RS_SW(0) * (%s)RT_SW(0);\n", op, prodtype, prodtype );
3458 printf("prod1 %s= (%s)RS_SW(2) * (%s)RT_SW(2);\n", op, prodtype, prodtype );
3459
3460 printf("GPR_%sD(destreg,0) = prod0;\n", sign );
3461 printf("GPR_%sD(destreg,1) = prod1;\n", sign );
3462
3463 printf("LO = SIGNEXTEND( prod0, 32 );\n");
3464 printf("HI = SIGNEXTEND( WORD64HI(prod0), 32 );\n");
3465 printf("LO1 = SIGNEXTEND( prod1, 32 );\n");
3466 printf("HI1 = SIGNEXTEND( WORD64HI(prod1), 32 );\n");
3467 break;
3468 }
3469
3470 case PDIVW:
3471 {
3472 char* sign = (insn->flags & UNSIGNED) ? "U" : "S";
3473
3474 printf("LO = RS_%sW(0) / RT_%sW(0);\n", sign, sign );
3475 printf("HI = RS_%sW(0) %% RT_%sW(0);\n", sign, sign );
3476 printf("LO1 = RS_%sW(2) / RT_%sW(2);\n", sign, sign );
3477 printf("HI1 = RS_%sW(2) %% RT_%sW(2);\n", sign, sign );
3478 break;
3479 }
3480
3481 case PDIVBW:
3482 printf("int devisor = RT_SH(0);\n");
3483 printf("LO_SW(0) = RS_SW(0) / devisor;\n");
3484 printf("HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n");
3485 printf("LO_SW(1) = RS_SW(1) / devisor;\n");
3486 printf("HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n");
3487 printf("LO_SW(2) = RS_SW(2) / devisor;\n");
3488 printf("HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n");
3489 printf("LO_SW(3) = RS_SW(3) / devisor;\n");
3490 printf("HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n");
3491 break;
3492
3493 case PADSBH:
3494 printf("int i;\n");
3495 printf("for(i=0;i<HALFWORDS_IN_MMI_REGS/2;i++)\n");
3496 printf(" GPR_SH(destreg,i) = RS_SH(i) - RT_SH(i);\n");
3497 printf("for(;i<HALFWORDS_IN_MMI_REGS;i++)\n");
3498 printf(" GPR_SH(destreg,i) = RS_SH(i) + RT_SH(i);\n");
3499 break;
3500
3501 case PHMADDH:
3502 {
3503 char* op = (insn->flags & SUBTRACT) ? "-" : "+";
3504 printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op );
3505 printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op );
3506 printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op );
3507 printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op );
3508 }
3509 break;
3510
3511 case PSHIFT:
3512 {
3513 char* name = name_for_data_len( insn );
3514 char* letter = letter_for_data_len( insn );
3515 char* bits = bits_for_data_len( insn );
3516 char* shift = (insn->flags & RIGHT) ? ">>" : "<<";
3517 char* sign = (insn->flags & ARITHMETIC) ? "S" : "U";
3518
3519 printf("int shift_by = op1 & (%s-1);\n", bits );
3520 printf("int i;\n");
3521 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3522 printf(" GPR_%s%s(destreg,i) = ", sign, letter );
3523 if ( insn->flags & ARITHMETIC )
3524 printf("SIGNEXTEND( ");
3525 printf("(RT_%s%s(i) %s shift_by)", sign, letter, shift );
3526 if ( insn->flags & ARITHMETIC )
3527 printf(", (%s-shift_by) )", bits );
3528 printf(";\n");
3529 break;
3530 }
3531
3532 case PSLLVW:
3533 printf("GPR_UD(destreg,0) = RT_UW(0) << (RS_UB(0) & 0x1F);\n");
3534 printf("GPR_UD(destreg,1) = RT_UW(2) << (RS_UB(8) & 0x1F);\n");
3535 break;
3536
3537 case PSRLVW:
3538 printf("GPR_UD(destreg,0) = RT_UW(0) >> (RS_UB(0) & 0x1F);\n");
3539 printf("GPR_UD(destreg,1) = RT_UW(2) >> (RS_UB(8) & 0x1F);\n");
3540 break;
3541
3542 case PSRAVW:
3543 printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n");
3544 printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n");
3545 break;
3546
3547 case POP:
3548 {
3549 char* op1;
3550 char* op2;
3551
3552 if ( GET_OP_FROM_INSN(insn) == POP_AND )
3553 {
3554 op1 = "&";
3555 op2 = "";
3556 }
3557 else if ( GET_OP_FROM_INSN(insn) == POP_OR )
3558 {
3559 op1 = "|";
3560 op2 = "";
3561 }
3562 else if ( GET_OP_FROM_INSN(insn) == POP_NOR )
3563 {
3564 op1 = "|";
3565 op2 = "~";
3566 }
3567 else if ( GET_OP_FROM_INSN(insn) == POP_XOR )
3568 {
3569 op1 = "^";
3570 op2 = "";
3571 }
3572
3573 printf("int i;\n");
3574 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3575 printf(" GPR_UW(destreg,i) = %s(RS_UW(i) %s RT_UW(i));\n", op2, op1 );
3576 break;
3577 }
3578
3579 case PCMP:
3580 {
3581 char* name = name_for_data_len( insn );
3582 char* letter = letter_for_data_len( insn );
3583 char* maximum = umax_for_data_len( insn );
3584 char* op = (insn->flags & GT) ? ">" : "==";
3585
3586 printf("int i;\n");
3587 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3588 printf(" {\n");
3589 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n",
3590 letter, op, letter, letter, maximum );
3591 printf(" else GPR_S%s(destreg,i) = 0;\n", letter );
3592 printf(" }\n");
3593 break;
3594 }
3595
3596 case PMAXMIN:
3597 {
3598 char* name = name_for_data_len( insn );
3599 char* letter = letter_for_data_len( insn );
3600 char* op = (insn->flags & GT) ? ">" : "<";
3601
3602 printf("int i;\n");
3603 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3604 printf(" {\n");
3605 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n",
3606 letter, op, letter, letter, letter );
3607 printf(" else GPR_S%s(destreg,i) = RT_S%s(i);\n", letter, letter );
3608 printf(" }\n");
3609 break;
3610 }
3611
3612 case PABS:
3613 {
3614 char* name = name_for_data_len( insn );
3615 char* letter = letter_for_data_len( insn );
3616
3617 printf("int i;\n");
3618 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3619 printf(" {\n");
3620 printf(" if (RT_S%s(i) < 0)\n", letter );
3621 printf(" GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter, letter );
3622 printf(" else\n");
3623 printf(" GPR_S%s(destreg,i) = RT_S%s(i);\n", letter, letter );
3624 printf(" }\n");
3625 break;
3626 }
3627
3628 case PCPYH:
3629 printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n");
3630 printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n");
3631 break;
3632
3633 case PCPYLD:
3634 printf("GPR_UD(destreg,0) = RT_UD(0);\n");
3635 printf("GPR_UD(destreg,1) = RS_UD(0);\n");
3636 break;
3637
3638 case PCPYUD:
3639 printf("GPR_UD(destreg,0) = RS_UD(1);\n");
3640 printf("GPR_UD(destreg,1) = RT_UD(1);\n");
3641 break;
3642
3643 case PEXCH:
3644 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3645 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3646 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3647 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3648 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3649 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3650 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3651 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3652 break;
3653
3654 case PEXCW:
3655 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3656 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3657 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3658 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3659 break;
3660
3661 case PEXOH:
3662 printf("GPR_UH(destreg,0) = RT_UH(2);\n");
3663 printf("GPR_UH(destreg,1) = RT_UH(1);\n");
3664 printf("GPR_UH(destreg,2) = RT_UH(0);\n");
3665 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3666 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3667 printf("GPR_UH(destreg,5) = RT_UH(5);\n");
3668 printf("GPR_UH(destreg,6) = RT_UH(4);\n");
3669 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3670 break;
3671
3672 case PEXOW:
3673 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3674 printf("GPR_UW(destreg,1) = RT_UW(1);\n");
3675 printf("GPR_UW(destreg,2) = RT_UW(0);\n");
3676 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3677 break;
3678
3679 case PEXTLB:
3680 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3681 printf("GPR_UB(destreg,1) = RS_UB(0);\n");
3682 printf("GPR_UB(destreg,2) = RT_UB(1);\n");
3683 printf("GPR_UB(destreg,3) = RS_UB(1);\n");
3684 printf("GPR_UB(destreg,4) = RT_UB(2);\n");
3685 printf("GPR_UB(destreg,5) = RS_UB(2);\n");
3686 printf("GPR_UB(destreg,6) = RT_UB(3);\n");
3687 printf("GPR_UB(destreg,7) = RS_UB(3);\n");
3688 printf("GPR_UB(destreg,8) = RT_UB(4);\n");
3689 printf("GPR_UB(destreg,9) = RS_UB(4);\n");
3690 printf("GPR_UB(destreg,10) = RT_UB(5);\n");
3691 printf("GPR_UB(destreg,11) = RS_UB(5);\n");
3692 printf("GPR_UB(destreg,12) = RT_UB(6);\n");
3693 printf("GPR_UB(destreg,13) = RS_UB(6);\n");
3694 printf("GPR_UB(destreg,14) = RT_UB(7);\n");
3695 printf("GPR_UB(destreg,15) = RS_UB(7);\n");
3696 break;
3697
3698 case PEXTLH:
3699 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3700 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3701 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3702 printf("GPR_UH(destreg,3) = RS_UH(1);\n");
3703 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3704 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3705 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3706 printf("GPR_UH(destreg,7) = RS_UH(3);\n");
3707 break;
3708
3709 case PEXTLW:
3710 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3711 printf("GPR_UW(destreg,1) = RS_UW(0);\n");
3712 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3713 printf("GPR_UW(destreg,3) = RS_UW(1);\n");
3714 break;
3715
3716 case PEXTUB:
3717 printf("GPR_UB(destreg,0) = RT_UB(8);\n");
3718 printf("GPR_UB(destreg,1) = RS_UB(8);\n");
3719 printf("GPR_UB(destreg,2) = RT_UB(9);\n");
3720 printf("GPR_UB(destreg,3) = RS_UB(9);\n");
3721 printf("GPR_UB(destreg,4) = RT_UB(10);\n");
3722 printf("GPR_UB(destreg,5) = RS_UB(10);\n");
3723 printf("GPR_UB(destreg,6) = RT_UB(11);\n");
3724 printf("GPR_UB(destreg,7) = RS_UB(11);\n");
3725 printf("GPR_UB(destreg,8) = RT_UB(12);\n");
3726 printf("GPR_UB(destreg,9) = RS_UB(12);\n");
3727 printf("GPR_UB(destreg,10) = RT_UB(13);\n");
3728 printf("GPR_UB(destreg,11) = RS_UB(13);\n");
3729 printf("GPR_UB(destreg,12) = RT_UB(14);\n");
3730 printf("GPR_UB(destreg,13) = RS_UB(14);\n");
3731 printf("GPR_UB(destreg,14) = RT_UB(15);\n");
3732 printf("GPR_UB(destreg,15) = RS_UB(15);\n");
3733 break;
3734
3735 case PEXTUH:
3736 printf("GPR_UH(destreg,0) = RT_UH(4);\n");
3737 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3738 printf("GPR_UH(destreg,2) = RT_UH(5);\n");
3739 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3740 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3741 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3742 printf("GPR_UH(destreg,6) = RT_UH(7);\n");
3743 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3744 break;
3745
3746 case PEXTUW:
3747 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3748 printf("GPR_UW(destreg,1) = RS_UW(2);\n");
3749 printf("GPR_UW(destreg,2) = RT_UW(3);\n");
3750 printf("GPR_UW(destreg,3) = RS_UW(3);\n");
3751 break;
3752
3753 case PPACB:
3754 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3755 printf("GPR_UB(destreg,1) = RT_UB(2);\n");
3756 printf("GPR_UB(destreg,2) = RT_UB(4);\n");
3757 printf("GPR_UB(destreg,3) = RT_UB(6);\n");
3758 printf("GPR_UB(destreg,4) = RT_UB(8);\n");
3759 printf("GPR_UB(destreg,5) = RT_UB(10);\n");
3760 printf("GPR_UB(destreg,6) = RT_UB(12);\n");
3761 printf("GPR_UB(destreg,7) = RT_UB(14);\n");
3762 printf("GPR_UB(destreg,8) = RS_UB(0);\n");
3763 printf("GPR_UB(destreg,9) = RS_UB(2);\n");
3764 printf("GPR_UB(destreg,10) = RS_UB(4);\n");
3765 printf("GPR_UB(destreg,11) = RS_UB(6);\n");
3766 printf("GPR_UB(destreg,12) = RS_UB(8);\n");
3767 printf("GPR_UB(destreg,13) = RS_UB(10);\n");
3768 printf("GPR_UB(destreg,14) = RS_UB(12);\n");
3769 printf("GPR_UB(destreg,15) = RS_UB(14);\n");
3770 break;
3771
3772 case PPACH:
3773 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3774 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3775 printf("GPR_UH(destreg,2) = RT_UH(4);\n");
3776 printf("GPR_UH(destreg,3) = RT_UH(6);\n");
3777 printf("GPR_UH(destreg,4) = RS_UH(0);\n");
3778 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3779 printf("GPR_UH(destreg,6) = RS_UH(4);\n");
3780 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3781 break;
3782
3783 case PPACW:
3784 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3785 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3786 printf("GPR_UW(destreg,2) = RS_UW(0);\n");
3787 printf("GPR_UW(destreg,3) = RS_UW(2);\n");
3788 break;
3789
3790 case PREVH:
3791 printf("GPR_UH(destreg,0) = RT_UH(3);\n");
3792 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3793 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3794 printf("GPR_UH(destreg,3) = RT_UH(0);\n");
3795 printf("GPR_UH(destreg,4) = RT_UH(7);\n");
3796 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3797 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3798 printf("GPR_UH(destreg,7) = RT_UH(4);\n");
3799 break;
3800
3801 case PROT3W:
3802 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3803 printf("GPR_UW(destreg,1) = RT_UW(3);\n");
3804 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3805 printf("GPR_UW(destreg,3) = RT_UW(2);\n");
3806 break;
3807
3808 case PINTH:
3809 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3810 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3811 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3812 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3813 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3814 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3815 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3816 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3817 break;
3818
3819 case PINTOH:
3820 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3821 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3822 printf("GPR_UH(destreg,2) = RT_UH(2);\n");
3823 printf("GPR_UH(destreg,3) = RS_UH(2);\n");
3824 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3825 printf("GPR_UH(destreg,5) = RS_UH(4);\n");
3826 printf("GPR_UH(destreg,6) = RT_UH(6);\n");
3827 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3828 break;
3829
3830 case PMXX: /* Parallel move HI or LO / TO or FROM */
3831 {
3832 if ( (insn->flags & (HI|FROM)) == (HI|FROM) )
3833 {
3834 printf("GPR_SD(destreg,0) = HI;\n");
3835 printf("GPR_SD(destreg,1) = HI1;\n");
3836 }
3837 else if ( (insn->flags & (LO|FROM)) == (LO|FROM) )
3838 {
3839 printf("GPR_SD(destreg,0) = LO;\n");
3840 printf("GPR_SD(destreg,1) = LO1;\n");
3841 }
3842 else if ( (insn->flags & (HI|TO)) == (HI|TO) )
3843 {
3844 printf("HI = RS_SD(0);\n");
3845 printf("HI1 = RS_SD(1);\n");
3846 }
3847 else if ( (insn->flags & (LO|TO)) == (LO|TO) )
3848 {
3849 printf("LO = RS_SD(0);\n");
3850 printf("LO1 = RS_SD(1);\n");
3851 }
3852 break;
3853 }
3854
3855 case PMTHL:
3856 printf("LO_UW(0) = RS_UW(0);\n");
3857 printf("HI_UW(0) = RS_UW(1);\n");
3858 printf("LO_UW(2) = RS_UW(2);\n");
3859 printf("HI_UW(2) = RS_UW(3);\n");
3860 break;
3861
3862 case PMFHL:
3863 printf("if (op1 == 0)\n");
3864 printf(" {\n");
3865 printf(" GPR_UW(destreg,0) = LO_UW(0);\n");
3866 printf(" GPR_UW(destreg,1) = HI_UW(0);\n");
3867 printf(" GPR_UW(destreg,2) = LO_UW(2);\n");
3868 printf(" GPR_UW(destreg,3) = HI_UW(2);\n");
3869 printf(" }\n");
3870 printf("else if (op1 == 1)\n");
3871 printf(" {\n");
3872 printf(" GPR_UW(destreg,0) = LO_UW(1);\n");
3873 printf(" GPR_UW(destreg,1) = HI_UW(1);\n");
3874 printf(" GPR_UW(destreg,2) = LO_UW(3);\n");
3875 printf(" GPR_UW(destreg,3) = HI_UW(3);\n");
3876 printf(" }\n");
3877 printf("else if (op1 == 2)\n");
3878 printf(" {\n");
3879 printf(" unsigned long long t = ((uword64)HI_UW(0) << 32) | (uword64)LO_UW(0);\n");
3880 printf(" if ( t > 0x7FFFFFFF )\n");
3881 printf(" GPR_SD(destreg,0) = 0x7FFFFFFF;\n");
3882 printf(" else if ( t > (uword64)0xFFFFFFFF80000000LL )\n");
3883 printf(" GPR_SD(destreg,0) = (uword64)0xFFFFFFFF80000000LL;\n");
3884 printf(" else\n");
3885 printf(" GPR_SD(destreg,0) = SIGNEXTEND(t,32);\n");
3886 printf(" }\n");
3887 printf("else if (op1 == 3)\n");
3888 printf(" {\n");
3889 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3890 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3891 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
3892 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
3893 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
3894 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
3895 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
3896 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
3897 printf(" }\n");
3898 printf("else if (op1 == 4)\n");
3899 printf(" {\n");
3900 printf(" if (LO_UW(0) > 0x00007FFF)\n");
3901 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
3902 printf(" else if (LO_UW(0) >= 0xFFFF8000)\n");
3903 printf(" GPR_UH(destreg,0) = 0x8000;\n");
3904 printf(" else\n");
3905 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3906
3907 printf(" if (LO_UW(1) > 0x00007FFF)\n");
3908 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
3909 printf(" else if (LO_UW(1) >= 0xFFFF8000)\n");
3910 printf(" GPR_UH(destreg,1) = 0x8000;\n");
3911 printf(" else\n");
3912 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3913
3914 printf(" if (HI_UW(0) > 0x00007FFF)\n");
3915 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
3916 printf(" else if (HI_UW(0) >= 0xFFFF8000)\n");
3917 printf(" GPR_UH(destreg,0) = 0x8000;\n");
3918 printf(" else\n");
3919 printf(" GPR_UH(destreg,0) = HI_UH(0);\n");
3920
3921 printf(" if (HI_UW(1) > 0x00007FFF)\n");
3922 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
3923 printf(" else if (HI_UW(1) >= 0xFFFF8000)\n");
3924 printf(" GPR_UH(destreg,1) = 0x8000;\n");
3925 printf(" else\n");
3926 printf(" GPR_UH(destreg,1) = HI_UH(2);\n");
3927
3928 printf(" if (LO_UW(2) > 0x00007FFF)\n");
3929 printf(" GPR_UH(destreg,4) = 0x7FFF;\n");
3930 printf(" else if (LO_UW(2) >= 0xFFFF8000)\n");
3931 printf(" GPR_UH(destreg,4) = 0x8000;\n");
3932 printf(" else\n");
3933 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
3934
3935 printf(" if (LO_UW(3) > 0x00007FFF)\n");
3936 printf(" GPR_UH(destreg,5) = 0x7FFF;\n");
3937 printf(" else if (LO_UW(3) >= 0xFFFF8000)\n");
3938 printf(" GPR_UH(destreg,5) = 0x8000;\n");
3939 printf(" else\n");
3940 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
3941
3942 printf(" if (HI_UW(2) > 0x00007FFF)\n");
3943 printf(" GPR_UH(destreg,6) = 0x7FFF;\n");
3944 printf(" else if (HI_UW(2) >= 0xFFFF8000)\n");
3945 printf(" GPR_UH(destreg,6) = 0x8000;\n");
3946 printf(" else\n");
3947 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
3948
3949 printf(" if (HI_UW(3) > 0x00007FFF)\n");
3950 printf(" GPR_UH(destreg,7) = 0x7FFF;\n");
3951 printf(" else if (HI_UW(3) >= 0xFFFF8000)\n");
3952 printf(" GPR_UH(destreg,7) = 0x8000;\n");
3953 printf(" else\n");
3954 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
3955
3956 printf(" }\n");
3957 break;
3958
3959 case PLZCW:
3960 printf("unsigned long value;\n");
3961 printf("int test;\n");
3962 printf("int count;\n");
3963 printf("int i;\n");
3964
3965 printf("value = RS_UW(0);\n");
3966 printf("count = 0;\n");
3967 printf("test = !!(value & (1 << 31));\n");
3968 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
3969 printf(" count++;\n");
3970 printf("GPR_UW(destreg,0) = count;\n");
3971
3972 printf("value = RS_UW(1);\n");
3973 printf("count = 0;\n");
3974 printf("test = !!(value & (1 << 31));\n");
3975 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
3976 printf(" count++;\n");
3977 printf("GPR_UW(destreg,1) = count;\n");
3978 break;
3979
3980 case PEXT5:
3981 printf("int i;\n");
3982 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3983 printf(" {\n");
3984 printf(" int x = RT_UW(i);\n");
3985 printf(" GPR_UW(destreg,i) = ((x & (1 << 15)) << (24 - 15)) \n");
3986 printf(" | ((x & (31 << 10)) << (19 - 10)) \n");
3987 printf(" | ((x & (31 << 5)) << (11 - 5)) \n");
3988 printf(" | ((x & (31 << 0)) << (3 - 0)); \n");
3989 printf(" }\n");
3990 break;
3991
3992 case PPAC5:
3993 printf("int i;\n");
3994 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3995 printf(" {\n");
3996 printf(" int x = RT_UW(i);\n");
3997 printf(" GPR_UW(destreg,i) = ((x & (1 << 31)) >> (31 - 15)) \n");
3998 printf(" | ((x & (31 << 19)) >> (19 - 10)) \n");
3999 printf(" | ((x & (31 << 11)) >> (11 - 5)) \n");
4000 printf(" | ((x & (31 << 3)) >> (3 - 0)); \n");
4001 printf(" }\n");
4002 break;
4003 /* end-sanitize-r5900 */
4004
4005 case NYI:
4006 fprintf(stderr,"Warning: Unimplemented opcode: %s\n",insn->name) ;
4007
4008 printf("SignalException(ReservedInstruction,instruction);\n");
4009 break;
4010
4011 default:
4012 fprintf(stderr,"Unrecognised opcode type %d\n",insn->type) ;
4013 exit(6) ;
4014 }
4015 }
4016
4017 /*---------------------------------------------------------------------------*/
4018
4019 /* The command-line feature controls are presented in a similar style
4020 to those offered by GCC, in the aim of providing a consistent
4021 interface to the user. */
4022 typedef enum {
4023 T_NONE, /* no argument - mask and value fields control "feature" definition */
4024 T_NUM, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
4025 T_STRING /* string argument - optionally prcededed by '=' */
4026 } mactypes;
4027
4028 struct {
4029 char *name;
4030 mactypes type;
4031 unsigned int mask;
4032 unsigned int value;
4033 char *desc;
4034 } machine_options[] = {
4035 {"ips", T_NUM, MASK_ISA,0,"\tSelect MIPS ISA version"},
4036 {"cpu", T_STRING,0,0,"\t\tSelect particular MIPS architecture"},
4037 {"gp64", T_NONE, FEATURE_GP64,FEATURE_GP64,"\t\t\tSelect 64bit GP registers"},
4038 {"gp32", T_NONE, FEATURE_GP64,0,"\t\t\tSelect 32bit GP registers"},
4039 {"no-fp", T_NONE, FEATURE_HASFPU,0,"\t\tDisable FP simulation"},
4040 {"single-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),(FEATURE_FPSINGLE | FEATURE_HASFPU),"\t\tSelect single precision only FPU"},
4041 {"double-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),FEATURE_HASFPU,"\t\tSelect double precision FPU"},
4042 {0, T_NONE, 0,0}
4043 };
4044
4045 /* The following architecture identies are those accepted by the "-mcpu" option: */
4046 struct architectures {
4047 const char *name; /* ASCII string identifier for command-line, no white-space allowed */
4048 unsigned int idflag; /* or-ed into "isa" value */
4049 };
4050
4051 static const struct architectures available_architectures[] = {
4052 {"4100",ARCH_VR4100}, /* NEC MIPS VR4100 */
4053 /* start-sanitize-r5900 */
4054 {"5900",ARCH_R5900},
4055 /* end-sanitize-r5900 */
4056 {0, 0} /* terminator */
4057 };
4058
4059 /*---------------------------------------------------------------------------*/
4060
4061 static void
4062 usage(name)
4063 char *name;
4064 {
4065 int loop;
4066
4067 fprintf(stderr,"%s: Construct a MIPS simulator engine.\n",name);
4068
4069 fprintf(stderr,"\
4070 The output of this program is a block of 'C' code designed to be\n\
4071 included into the main simulation control loop of a device specific\n\
4072 simulator.\n");
4073
4074 fprintf(stderr,"\nOptions:\n");
4075 fprintf(stderr," -h --help\t\tProvide this help text\n");
4076 fprintf(stderr," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
4077 fprintf(stderr," -w --warnings\t\tEnable all the simulator engine warnings\n");
4078
4079 for (loop = 0; (machine_options[loop].name != 0); loop++) {
4080 fprintf(stderr," -m%s",machine_options[loop].name);
4081 switch (machine_options[loop].type) {
4082 case T_NUM :
4083 fprintf(stderr,"N (range 0..%d)",machine_options[loop].mask);
4084 case T_NONE :
4085 break;
4086
4087 case T_STRING :
4088 fprintf(stderr,"=name");
4089 break;
4090
4091 default :
4092 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",name,machine_options[loop].type);
4093 exit(1);
4094 }
4095 fprintf(stderr,"%s\n",machine_options[loop].desc);
4096 }
4097
4098 fprintf(stderr,"\nAvailable \"-mcpu\" architectures: ");
4099 for (loop = 0; (available_architectures[loop].name != 0); loop++)
4100 fprintf(stderr,"%s ",available_architectures[loop].name);
4101 fprintf(stderr,"\n\n");
4102
4103 fprintf(stderr,"\
4104 The \"trace\" and \"warnings\" options do not define the output stream.\n\
4105 They only inform the code that includes the constructed engine to provide\n\
4106 the required features.\n\n\
4107 The \"-mips0\" option forces the construction of a simulator supporting\n\
4108 the highest available MIPS ISA supported.\n");
4109
4110 return;
4111 }
4112
4113 /*---------------------------------------------------------------------------*/
4114
4115 int
4116 main(argc,argv)
4117 int argc;
4118 char **argv;
4119 {
4120 int c;
4121 char *progname = argv[0];
4122 unsigned int doarch = DEF_ISA;
4123 unsigned int features = 0; /* default state */
4124
4125 if (DEF_FP)
4126 features |= FEATURE_HASFPU;
4127 if (!DEF_PROC64)
4128 features |= FEATURE_PROC32;
4129 if (DEF_FPSINGLE)
4130 features |= FEATURE_FPSINGLE;
4131
4132 if (features & FEATURE_PROC32)
4133 features &= ~FEATURE_GP64;
4134 else
4135 features |= FEATURE_GP64;
4136
4137 while (1) {
4138 int option_index = 0;
4139 static struct option cmdline[] = {
4140 {"fast", 0,0,'f'},
4141 {"help", 0,0,'h'},
4142 {"warnings",0,0,'w'},
4143 {0, 0,0,0}
4144 };
4145
4146 c = getopt_long(argc,argv,"hm:tw",cmdline,&option_index);
4147 if (c == -1)
4148 break ; /* out of the while loop */
4149
4150 switch (c) {
4151 case 'h' : /* help */
4152 usage(progname);
4153 exit(0);
4154
4155 case 'f' : /* fast */
4156 features |= FEATURE_FAST;
4157 break;
4158
4159 case 'w' : /* warnings */
4160 features |= FEATURE_WARNINGS;
4161 /* TODO: Future extension: Allow better control over the warnings generated:
4162 disable warnings -wnone ~FEATURE_WARNINGS
4163 all possible warnings -wall FEATURE_WARNINGS
4164 pipeline stall occuring -wstall FEATURE_WARN_STALL
4165 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
4166 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
4167 bad r31 use -wr31 FEATURE_WARN_R31
4168 undefined results -wresult FEATURE_WARN_RESULT
4169 */
4170 break;
4171
4172 case 'm' : /* machine options */
4173 {
4174 int loop;
4175
4176 for (loop = 0; (machine_options[loop].name != 0); loop++)
4177 if (strncmp(machine_options[loop].name,optarg,strlen(machine_options[loop].name)) == 0) {
4178 char *loptarg = (optarg + strlen(machine_options[loop].name));
4179 switch (machine_options[loop].type) {
4180 case T_NONE :
4181 if (*loptarg) {
4182 fprintf(stderr,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname,loptarg,machine_options[loop].name);
4183 exit(1);
4184 }
4185 features &= ~(machine_options[loop].mask);
4186 features |= machine_options[loop].value;
4187 break;
4188
4189 case T_NUM :
4190 if (*loptarg && *loptarg == '=')
4191 loptarg++;
4192
4193 if (strcmp(machine_options[loop].name,"ips") == 0) {
4194 unsigned int num;
4195
4196 if (!*loptarg) {
4197 fprintf(stderr,"%s: ISA number expected after -mips\n",progname);
4198 exit(1);
4199 }
4200
4201 num = my_strtoul(loptarg,&loptarg,10);
4202
4203 if ((num == ULONG_MAX) && (errno = ERANGE)) {
4204 fprintf(stderr,"%s: Invalid number given to -mips option\n",progname);
4205 exit(1);
4206 }
4207
4208 if (*loptarg) {
4209 fprintf(stderr,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname,loptarg);
4210 exit(1);
4211 }
4212
4213 if (num > MASK_ISA) {
4214 fprintf(stderr,"%s: ISA number %d outside acceptable range (0..%d)\n",progname,num,MASK_ISA);
4215 exit(1);
4216 }
4217
4218 doarch = ((doarch & ~MASK_ISA) | num);
4219 if ((num == 0) || (num > 2)) {
4220 if ((features & FEATURE_PROC32) || !(features & FEATURE_GP64))
4221 fprintf(stderr,"%s: Warning: -mips%d forcing -mgp64\n",progname,num);
4222 features |= FEATURE_GP64;
4223 features &= ~FEATURE_PROC32;
4224 } else {
4225 if (!(features & FEATURE_PROC32) || (features & FEATURE_GP64))
4226 fprintf(stderr,"%s: Warning: -mips%d forcing -mgp32\n",progname,num);
4227 features &= ~FEATURE_GP64;
4228 features |= FEATURE_PROC32;
4229 }
4230 } else {
4231 fprintf(stderr,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname,optarg);
4232 exit(1);
4233 }
4234 break;
4235
4236 case T_STRING :
4237 if (*loptarg && *loptarg == '=')
4238 loptarg++;
4239
4240 if (strcmp(machine_options[loop].name,"cpu") == 0) {
4241 int archloop;
4242
4243 if (!*loptarg) {
4244 fprintf(stderr,"%s: Architecture identifier expected after -mcpu\n",progname);
4245 exit(1);
4246 }
4247
4248 for (archloop = 0; (available_architectures[archloop].name != 0); archloop++) {
4249 if ((*loptarg == 'v') || (*loptarg == 'V'))
4250 loptarg++;
4251
4252 if ((*loptarg == 'r') || (*loptarg == 'R'))
4253 loptarg++;
4254
4255 if (strcmp(available_architectures[archloop].name,loptarg) == 0) {
4256 doarch |= available_architectures[archloop].idflag;
4257 break;
4258 }
4259 }
4260
4261 if (available_architectures[archloop].name == 0) {
4262 fprintf(stderr,"%s: Unrecognised MIPS architecture \"%s\"\n",progname,loptarg);
4263 exit(1);
4264 }
4265 } else {
4266 fprintf(stderr,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname,optarg);
4267 exit(1);
4268 }
4269 break;
4270
4271 default :
4272 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",progname,machine_options[loop].type);
4273 exit(1);
4274 }
4275 break;
4276 }
4277
4278 if (machine_options[loop].name == 0) {
4279 fprintf(stderr,"%s: Unrecognised option: -m%s\n",progname,optarg);
4280 exit(1);
4281 }
4282 }
4283 break;
4284
4285 case '?' :
4286 /* An error message should already have been displayed */
4287 exit(1);
4288
4289 default :
4290 fprintf(stderr,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname,c);
4291 exit(1);
4292 }
4293 }
4294
4295 if (optind < argc) {
4296 fprintf(stderr,"%s: Spurios non-option arguments ",progname);
4297 while (optind < argc)
4298 fprintf(stderr,"\"%s\" ",argv[optind++]);
4299 fprintf(stderr,"\n");
4300 exit(1);
4301 }
4302
4303 if ((features & FEATURE_FAST) && (features & FEATURE_WARNINGS))
4304 fprintf(stderr,"Warning: Fast model generation selected, along with trace or warnings.\n");
4305
4306 process_instructions(doarch,features) ;
4307 return(0) ;
4308 }
4309
4310 /*---------------------------------------------------------------------------*/
4311
4312 /* We can't assume that the compiler for the build system has strtoul,
4313 so we provide our own copy. */
4314
4315 /*
4316 * Copyright (c) 1990 Regents of the University of California.
4317 * All rights reserved.
4318 *
4319 * Redistribution and use in source and binary forms, with or without
4320 * modification, are permitted provided that the following conditions
4321 * are met:
4322 * 1. Redistributions of source code must retain the above copyright
4323 * notice, this list of conditions and the following disclaimer.
4324 * 2. Redistributions in binary form must reproduce the above copyright
4325 * notice, this list of conditions and the following disclaimer in the
4326 * documentation and/or other materials provided with the distribution.
4327 * 3. All advertising materials mentioning features or use of this software
4328 * must display the following acknowledgement:
4329 * This product includes software developed by the University of
4330 * California, Berkeley and its contributors.
4331 * 4. Neither the name of the University nor the names of its contributors
4332 * may be used to endorse or promote products derived from this software
4333 * without specific prior written permission.
4334 *
4335 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4336 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4337 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4338 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4339 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4340 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4341 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4342 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4343 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4344 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4345 * SUCH DAMAGE.
4346 */
4347
4348 /*
4349 * Convert a string to an unsigned long integer.
4350 *
4351 * Ignores `locale' stuff. Assumes that the upper and lower case
4352 * alphabets and digits are each contiguous.
4353 */
4354 static unsigned long
4355 my_strtoul(nptr, endptr, base)
4356 const char *nptr;
4357 char **endptr;
4358 register int base;
4359 {
4360 register const char *s = nptr;
4361 register unsigned long acc;
4362 register int c;
4363 register unsigned long cutoff;
4364 register int neg = 0, any, cutlim;
4365
4366 /*
4367 * See strtol for comments as to the logic used.
4368 */
4369 do {
4370 c = *s++;
4371 } while (isspace(c));
4372 if (c == '-') {
4373 neg = 1;
4374 c = *s++;
4375 } else if (c == '+')
4376 c = *s++;
4377 if ((base == 0 || base == 16) &&
4378 c == '0' && (*s == 'x' || *s == 'X')) {
4379 c = s[1];
4380 s += 2;
4381 base = 16;
4382 }
4383 if (base == 0)
4384 base = c == '0' ? 8 : 10;
4385 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
4386 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
4387 for (acc = 0, any = 0;; c = *s++) {
4388 if (isdigit(c))
4389 c -= '0';
4390 else if (isalpha(c))
4391 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
4392 else
4393 break;
4394 if (c >= base)
4395 break;
4396 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
4397 any = -1;
4398 else {
4399 any = 1;
4400 acc *= base;
4401 acc += c;
4402 }
4403 }
4404 if (any < 0) {
4405 acc = ULONG_MAX;
4406 errno = ERANGE;
4407 } else if (neg)
4408 acc = -acc;
4409 if (endptr != 0)
4410 *endptr = (char *) (any ? s - 1 : nptr);
4411 return (acc);
4412 }
4413
4414 /*---------------------------------------------------------------------------*/
4415
4416 /*> EOF gencode.c <*/
4417
4418
4419
4420
4421
4422
4423
This page took 0.153414 seconds and 5 git commands to generate.