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