o Fix padd insn
[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 UNUSED = ",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 UNUSED = (%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 UNUSED = (%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 = 0;\n");
2645 printf(" uword64 memval1 = 0;\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 UNUSED = (ReverseEndian ? (mask >> shift) : 0);\n");
2777 printf(" unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0);\n");
2778 printf(" unsigned int byte UNUSED;\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 char* signletter;
3363
3364 if ( insn->flags & UNSIGNED )
3365 {
3366 tmptype = type_for_data_len( insn );
3367 signedness = "unsigned";
3368 signletter = "U";
3369 maximum = umax_for_data_len( insn );
3370 minimum = 0;
3371 }
3372 else if ( insn->flags & SATURATE )
3373 {
3374 tmptype = type_for_data_len( insn );
3375 signedness = "";
3376 signletter = "S";
3377 maximum = max_for_data_len( insn );
3378 minimum = min_for_data_len( insn );
3379 }
3380 else
3381 {
3382 tmptype = type_for_data_len( insn );
3383 signedness = "";
3384 signletter = "S";
3385 maximum = 0;
3386 minimum = 0;
3387 }
3388
3389 printf("int i;\n");
3390 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3391 printf(" {\n");
3392 printf(" %s %s r = RS_%s%s(i) %s RT_%s%s(i);\n", signedness, tmptype, signletter, letter, op, signletter, letter );
3393 if ( maximum )
3394 {
3395 printf(" if (r > %s) GPR_%s%s(destreg,i) = %s;\n", maximum, signletter, letter, maximum );
3396 if ( minimum )
3397 printf(" else if (r < %s) GPR_%s%s(destreg,i) = %s;\n", minimum, signletter, letter, minimum );
3398 printf(" else ");
3399 }
3400 printf("GPR_%s%s(destreg,i) = r;\n", signletter, letter );
3401 printf(" }\n");
3402 break;
3403 }
3404
3405 case PMULTH:
3406 {
3407 char* op;
3408 if ( insn->flags & SUBTRACT )
3409 op = "-";
3410 else if ( insn->flags & ADDITION )
3411 op = "+";
3412 else
3413 op = "";
3414
3415 printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op);
3416 printf(" LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op);
3417 printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op);
3418 printf(" HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op);
3419 printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op);
3420 printf(" LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op);
3421 printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op);
3422 printf(" HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op);
3423 break;
3424 }
3425
3426 case PMULTW:
3427 {
3428 char* op;
3429 char* sign = (insn->flags & UNSIGNED) ? "U" : "S";
3430 char* prodtype = (insn->flags & UNSIGNED) ? "uword64" : "word64";
3431 char* constructor = (insn->flags & UNSIGNED) ? "UWORD64" : "WORD64";
3432
3433 printf("%s prod0;\n", prodtype );
3434 printf("%s prod1;\n", prodtype );
3435
3436 if ( insn->flags & SUBTRACT )
3437 {
3438 op = "-";
3439 printf("prod0 = %s( HI_SW(0), LO_SW(0) );\n", constructor );
3440 printf("prod1 = %s( HI_SW(2), LO_SW(2) );\n", constructor );
3441 }
3442 else if ( insn->flags & ADDITION )
3443 {
3444 op = "+";
3445 printf("prod0 = %s( HI_SW(0), LO_SW(0) );\n", constructor );
3446 printf("prod1 = %s( HI_SW(2), LO_SW(2) );\n", constructor );
3447 }
3448 else
3449 op = "";
3450
3451 printf("prod0 %s= (%s)RS_SW(0) * (%s)RT_SW(0);\n", op, prodtype, prodtype );
3452 printf("prod1 %s= (%s)RS_SW(2) * (%s)RT_SW(2);\n", op, prodtype, prodtype );
3453
3454 printf("GPR_%sD(destreg,0) = prod0;\n", sign );
3455 printf("GPR_%sD(destreg,1) = prod1;\n", sign );
3456
3457 printf("LO = SIGNEXTEND( prod0, 32 );\n");
3458 printf("HI = SIGNEXTEND( WORD64HI(prod0), 32 );\n");
3459 printf("LO1 = SIGNEXTEND( prod1, 32 );\n");
3460 printf("HI1 = SIGNEXTEND( WORD64HI(prod1), 32 );\n");
3461 break;
3462 }
3463
3464 case PDIVW:
3465 {
3466 char* sign = (insn->flags & UNSIGNED) ? "U" : "S";
3467
3468 printf("LO = RS_%sW(0) / RT_%sW(0);\n", sign, sign );
3469 printf("HI = RS_%sW(0) %% RT_%sW(0);\n", sign, sign );
3470 printf("LO1 = RS_%sW(2) / RT_%sW(2);\n", sign, sign );
3471 printf("HI1 = RS_%sW(2) %% RT_%sW(2);\n", sign, sign );
3472 break;
3473 }
3474
3475 case PDIVBW:
3476 printf("int devisor = RT_SH(0);\n");
3477 printf("LO_SW(0) = RS_SW(0) / devisor;\n");
3478 printf("HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n");
3479 printf("LO_SW(1) = RS_SW(1) / devisor;\n");
3480 printf("HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n");
3481 printf("LO_SW(2) = RS_SW(2) / devisor;\n");
3482 printf("HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n");
3483 printf("LO_SW(3) = RS_SW(3) / devisor;\n");
3484 printf("HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n");
3485 break;
3486
3487 case PADSBH:
3488 printf("int i;\n");
3489 printf("for(i=0;i<HALFWORDS_IN_MMI_REGS/2;i++)\n");
3490 printf(" GPR_SH(destreg,i) = RS_SH(i) - RT_SH(i);\n");
3491 printf("for(;i<HALFWORDS_IN_MMI_REGS;i++)\n");
3492 printf(" GPR_SH(destreg,i) = RS_SH(i) + RT_SH(i);\n");
3493 break;
3494
3495 case PHMADDH:
3496 {
3497 char* op = (insn->flags & SUBTRACT) ? "-" : "+";
3498 printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op );
3499 printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op );
3500 printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op );
3501 printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op );
3502 }
3503 break;
3504
3505 case PSHIFT:
3506 {
3507 char* name = name_for_data_len( insn );
3508 char* letter = letter_for_data_len( insn );
3509 char* bits = bits_for_data_len( insn );
3510 char* shift = (insn->flags & RIGHT) ? ">>" : "<<";
3511 char* sign = (insn->flags & ARITHMETIC) ? "S" : "U";
3512
3513 printf("int shift_by = op1 & (%s-1);\n", bits );
3514 printf("int i;\n");
3515 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3516 printf(" GPR_%s%s(destreg,i) = ", sign, letter );
3517 if ( insn->flags & ARITHMETIC )
3518 printf("SIGNEXTEND( ");
3519 printf("(RT_%s%s(i) %s shift_by)", sign, letter, shift );
3520 if ( insn->flags & ARITHMETIC )
3521 printf(", (%s-shift_by) )", bits );
3522 printf(";\n");
3523 break;
3524 }
3525
3526 case PSLLVW:
3527 printf("GPR_UD(destreg,0) = RT_UW(0) << (RS_UB(0) & 0x1F);\n");
3528 printf("GPR_UD(destreg,1) = RT_UW(2) << (RS_UB(8) & 0x1F);\n");
3529 break;
3530
3531 case PSRLVW:
3532 printf("GPR_UD(destreg,0) = RT_UW(0) >> (RS_UB(0) & 0x1F);\n");
3533 printf("GPR_UD(destreg,1) = RT_UW(2) >> (RS_UB(8) & 0x1F);\n");
3534 break;
3535
3536 case PSRAVW:
3537 printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n");
3538 printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n");
3539 break;
3540
3541 case POP:
3542 {
3543 char* op1;
3544 char* op2;
3545
3546 if ( GET_OP_FROM_INSN(insn) == POP_AND )
3547 {
3548 op1 = "&";
3549 op2 = "";
3550 }
3551 else if ( GET_OP_FROM_INSN(insn) == POP_OR )
3552 {
3553 op1 = "|";
3554 op2 = "";
3555 }
3556 else if ( GET_OP_FROM_INSN(insn) == POP_NOR )
3557 {
3558 op1 = "|";
3559 op2 = "~";
3560 }
3561 else if ( GET_OP_FROM_INSN(insn) == POP_XOR )
3562 {
3563 op1 = "^";
3564 op2 = "";
3565 }
3566
3567 printf("int i;\n");
3568 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3569 printf(" GPR_UW(destreg,i) = %s(RS_UW(i) %s RT_UW(i));\n", op2, op1 );
3570 break;
3571 }
3572
3573 case PCMP:
3574 {
3575 char* name = name_for_data_len( insn );
3576 char* letter = letter_for_data_len( insn );
3577 char* maximum = umax_for_data_len( insn );
3578 char* op = (insn->flags & GT) ? ">" : "==";
3579
3580 printf("int i;\n");
3581 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3582 printf(" {\n");
3583 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n",
3584 letter, op, letter, letter, maximum );
3585 printf(" else GPR_S%s(destreg,i) = 0;\n", letter );
3586 printf(" }\n");
3587 break;
3588 }
3589
3590 case PMAXMIN:
3591 {
3592 char* name = name_for_data_len( insn );
3593 char* letter = letter_for_data_len( insn );
3594 char* op = (insn->flags & GT) ? ">" : "<";
3595
3596 printf("int i;\n");
3597 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3598 printf(" {\n");
3599 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n",
3600 letter, op, letter, letter, letter );
3601 printf(" else GPR_S%s(destreg,i) = RT_S%s(i);\n", letter, letter );
3602 printf(" }\n");
3603 break;
3604 }
3605
3606 case PABS:
3607 {
3608 char* name = name_for_data_len( insn );
3609 char* letter = letter_for_data_len( insn );
3610
3611 printf("int i;\n");
3612 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3613 printf(" {\n");
3614 printf(" if (RT_S%s(i) < 0)\n", letter );
3615 printf(" GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter, letter );
3616 printf(" else\n");
3617 printf(" GPR_S%s(destreg,i) = RT_S%s(i);\n", letter, letter );
3618 printf(" }\n");
3619 break;
3620 }
3621
3622 case PCPYH:
3623 printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n");
3624 printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n");
3625 break;
3626
3627 case PCPYLD:
3628 printf("GPR_UD(destreg,0) = RT_UD(0);\n");
3629 printf("GPR_UD(destreg,1) = RS_UD(0);\n");
3630 break;
3631
3632 case PCPYUD:
3633 printf("GPR_UD(destreg,0) = RS_UD(1);\n");
3634 printf("GPR_UD(destreg,1) = RT_UD(1);\n");
3635 break;
3636
3637 case PEXCH:
3638 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3639 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3640 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3641 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3642 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3643 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3644 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3645 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3646 break;
3647
3648 case PEXCW:
3649 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3650 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3651 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3652 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3653 break;
3654
3655 case PEXOH:
3656 printf("GPR_UH(destreg,0) = RT_UH(2);\n");
3657 printf("GPR_UH(destreg,1) = RT_UH(1);\n");
3658 printf("GPR_UH(destreg,2) = RT_UH(0);\n");
3659 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3660 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3661 printf("GPR_UH(destreg,5) = RT_UH(5);\n");
3662 printf("GPR_UH(destreg,6) = RT_UH(4);\n");
3663 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3664 break;
3665
3666 case PEXOW:
3667 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3668 printf("GPR_UW(destreg,1) = RT_UW(1);\n");
3669 printf("GPR_UW(destreg,2) = RT_UW(0);\n");
3670 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3671 break;
3672
3673 case PEXTLB:
3674 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3675 printf("GPR_UB(destreg,1) = RS_UB(0);\n");
3676 printf("GPR_UB(destreg,2) = RT_UB(1);\n");
3677 printf("GPR_UB(destreg,3) = RS_UB(1);\n");
3678 printf("GPR_UB(destreg,4) = RT_UB(2);\n");
3679 printf("GPR_UB(destreg,5) = RS_UB(2);\n");
3680 printf("GPR_UB(destreg,6) = RT_UB(3);\n");
3681 printf("GPR_UB(destreg,7) = RS_UB(3);\n");
3682 printf("GPR_UB(destreg,8) = RT_UB(4);\n");
3683 printf("GPR_UB(destreg,9) = RS_UB(4);\n");
3684 printf("GPR_UB(destreg,10) = RT_UB(5);\n");
3685 printf("GPR_UB(destreg,11) = RS_UB(5);\n");
3686 printf("GPR_UB(destreg,12) = RT_UB(6);\n");
3687 printf("GPR_UB(destreg,13) = RS_UB(6);\n");
3688 printf("GPR_UB(destreg,14) = RT_UB(7);\n");
3689 printf("GPR_UB(destreg,15) = RS_UB(7);\n");
3690 break;
3691
3692 case PEXTLH:
3693 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3694 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3695 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3696 printf("GPR_UH(destreg,3) = RS_UH(1);\n");
3697 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3698 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3699 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3700 printf("GPR_UH(destreg,7) = RS_UH(3);\n");
3701 break;
3702
3703 case PEXTLW:
3704 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3705 printf("GPR_UW(destreg,1) = RS_UW(0);\n");
3706 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3707 printf("GPR_UW(destreg,3) = RS_UW(1);\n");
3708 break;
3709
3710 case PEXTUB:
3711 printf("GPR_UB(destreg,0) = RT_UB(8);\n");
3712 printf("GPR_UB(destreg,1) = RS_UB(8);\n");
3713 printf("GPR_UB(destreg,2) = RT_UB(9);\n");
3714 printf("GPR_UB(destreg,3) = RS_UB(9);\n");
3715 printf("GPR_UB(destreg,4) = RT_UB(10);\n");
3716 printf("GPR_UB(destreg,5) = RS_UB(10);\n");
3717 printf("GPR_UB(destreg,6) = RT_UB(11);\n");
3718 printf("GPR_UB(destreg,7) = RS_UB(11);\n");
3719 printf("GPR_UB(destreg,8) = RT_UB(12);\n");
3720 printf("GPR_UB(destreg,9) = RS_UB(12);\n");
3721 printf("GPR_UB(destreg,10) = RT_UB(13);\n");
3722 printf("GPR_UB(destreg,11) = RS_UB(13);\n");
3723 printf("GPR_UB(destreg,12) = RT_UB(14);\n");
3724 printf("GPR_UB(destreg,13) = RS_UB(14);\n");
3725 printf("GPR_UB(destreg,14) = RT_UB(15);\n");
3726 printf("GPR_UB(destreg,15) = RS_UB(15);\n");
3727 break;
3728
3729 case PEXTUH:
3730 printf("GPR_UH(destreg,0) = RT_UH(4);\n");
3731 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3732 printf("GPR_UH(destreg,2) = RT_UH(5);\n");
3733 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3734 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3735 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3736 printf("GPR_UH(destreg,6) = RT_UH(7);\n");
3737 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3738 break;
3739
3740 case PEXTUW:
3741 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3742 printf("GPR_UW(destreg,1) = RS_UW(2);\n");
3743 printf("GPR_UW(destreg,2) = RT_UW(3);\n");
3744 printf("GPR_UW(destreg,3) = RS_UW(3);\n");
3745 break;
3746
3747 case PPACB:
3748 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3749 printf("GPR_UB(destreg,1) = RT_UB(2);\n");
3750 printf("GPR_UB(destreg,2) = RT_UB(4);\n");
3751 printf("GPR_UB(destreg,3) = RT_UB(6);\n");
3752 printf("GPR_UB(destreg,4) = RT_UB(8);\n");
3753 printf("GPR_UB(destreg,5) = RT_UB(10);\n");
3754 printf("GPR_UB(destreg,6) = RT_UB(12);\n");
3755 printf("GPR_UB(destreg,7) = RT_UB(14);\n");
3756 printf("GPR_UB(destreg,8) = RS_UB(0);\n");
3757 printf("GPR_UB(destreg,9) = RS_UB(2);\n");
3758 printf("GPR_UB(destreg,10) = RS_UB(4);\n");
3759 printf("GPR_UB(destreg,11) = RS_UB(6);\n");
3760 printf("GPR_UB(destreg,12) = RS_UB(8);\n");
3761 printf("GPR_UB(destreg,13) = RS_UB(10);\n");
3762 printf("GPR_UB(destreg,14) = RS_UB(12);\n");
3763 printf("GPR_UB(destreg,15) = RS_UB(14);\n");
3764 break;
3765
3766 case PPACH:
3767 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3768 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3769 printf("GPR_UH(destreg,2) = RT_UH(4);\n");
3770 printf("GPR_UH(destreg,3) = RT_UH(6);\n");
3771 printf("GPR_UH(destreg,4) = RS_UH(0);\n");
3772 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3773 printf("GPR_UH(destreg,6) = RS_UH(4);\n");
3774 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3775 break;
3776
3777 case PPACW:
3778 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3779 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3780 printf("GPR_UW(destreg,2) = RS_UW(0);\n");
3781 printf("GPR_UW(destreg,3) = RS_UW(2);\n");
3782 break;
3783
3784 case PREVH:
3785 printf("GPR_UH(destreg,0) = RT_UH(3);\n");
3786 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3787 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3788 printf("GPR_UH(destreg,3) = RT_UH(0);\n");
3789 printf("GPR_UH(destreg,4) = RT_UH(7);\n");
3790 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3791 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3792 printf("GPR_UH(destreg,7) = RT_UH(4);\n");
3793 break;
3794
3795 case PROT3W:
3796 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3797 printf("GPR_UW(destreg,1) = RT_UW(3);\n");
3798 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3799 printf("GPR_UW(destreg,3) = RT_UW(2);\n");
3800 break;
3801
3802 case PINTH:
3803 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3804 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3805 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3806 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3807 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3808 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3809 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3810 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3811 break;
3812
3813 case PINTOH:
3814 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3815 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3816 printf("GPR_UH(destreg,2) = RT_UH(2);\n");
3817 printf("GPR_UH(destreg,3) = RS_UH(2);\n");
3818 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3819 printf("GPR_UH(destreg,5) = RS_UH(4);\n");
3820 printf("GPR_UH(destreg,6) = RT_UH(6);\n");
3821 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3822 break;
3823
3824 case PMXX: /* Parallel move HI or LO / TO or FROM */
3825 {
3826 if ( (insn->flags & (HI|FROM)) == (HI|FROM) )
3827 {
3828 printf("GPR_SD(destreg,0) = HI;\n");
3829 printf("GPR_SD(destreg,1) = HI1;\n");
3830 }
3831 else if ( (insn->flags & (LO|FROM)) == (LO|FROM) )
3832 {
3833 printf("GPR_SD(destreg,0) = LO;\n");
3834 printf("GPR_SD(destreg,1) = LO1;\n");
3835 }
3836 else if ( (insn->flags & (HI|TO)) == (HI|TO) )
3837 {
3838 printf("HI = RS_SD(0);\n");
3839 printf("HI1 = RS_SD(1);\n");
3840 }
3841 else if ( (insn->flags & (LO|TO)) == (LO|TO) )
3842 {
3843 printf("LO = RS_SD(0);\n");
3844 printf("LO1 = RS_SD(1);\n");
3845 }
3846 break;
3847 }
3848
3849 case PMTHL:
3850 printf("LO_UW(0) = RS_UW(0);\n");
3851 printf("HI_UW(0) = RS_UW(1);\n");
3852 printf("LO_UW(2) = RS_UW(2);\n");
3853 printf("HI_UW(2) = RS_UW(3);\n");
3854 break;
3855
3856 case PMFHL:
3857 printf("if (op1 == 0)\n");
3858 printf(" {\n");
3859 printf(" GPR_UW(destreg,0) = LO_UW(0);\n");
3860 printf(" GPR_UW(destreg,1) = HI_UW(0);\n");
3861 printf(" GPR_UW(destreg,2) = LO_UW(2);\n");
3862 printf(" GPR_UW(destreg,3) = HI_UW(2);\n");
3863 printf(" }\n");
3864 printf("else if (op1 == 1)\n");
3865 printf(" {\n");
3866 printf(" GPR_UW(destreg,0) = LO_UW(1);\n");
3867 printf(" GPR_UW(destreg,1) = HI_UW(1);\n");
3868 printf(" GPR_UW(destreg,2) = LO_UW(3);\n");
3869 printf(" GPR_UW(destreg,3) = HI_UW(3);\n");
3870 printf(" }\n");
3871 printf("else if (op1 == 2)\n");
3872 printf(" {\n");
3873 printf(" unsigned long long t = ((uword64)HI_UW(0) << 32) | (uword64)LO_UW(0);\n");
3874 printf(" if ( t > 0x7FFFFFFF )\n");
3875 printf(" GPR_SD(destreg,0) = 0x7FFFFFFF;\n");
3876 printf(" else if ( t > (uword64)0xFFFFFFFF80000000LL )\n");
3877 printf(" GPR_SD(destreg,0) = (uword64)0xFFFFFFFF80000000LL;\n");
3878 printf(" else\n");
3879 printf(" GPR_SD(destreg,0) = SIGNEXTEND(t,32);\n");
3880 printf(" }\n");
3881 printf("else if (op1 == 3)\n");
3882 printf(" {\n");
3883 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3884 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3885 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
3886 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
3887 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
3888 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
3889 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
3890 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
3891 printf(" }\n");
3892 printf("else if (op1 == 4)\n");
3893 printf(" {\n");
3894 printf(" if (LO_UW(0) > 0x00007FFF)\n");
3895 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
3896 printf(" else if (LO_UW(0) >= 0xFFFF8000)\n");
3897 printf(" GPR_UH(destreg,0) = 0x8000;\n");
3898 printf(" else\n");
3899 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3900
3901 printf(" if (LO_UW(1) > 0x00007FFF)\n");
3902 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
3903 printf(" else if (LO_UW(1) >= 0xFFFF8000)\n");
3904 printf(" GPR_UH(destreg,1) = 0x8000;\n");
3905 printf(" else\n");
3906 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3907
3908 printf(" if (HI_UW(0) > 0x00007FFF)\n");
3909 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
3910 printf(" else if (HI_UW(0) >= 0xFFFF8000)\n");
3911 printf(" GPR_UH(destreg,0) = 0x8000;\n");
3912 printf(" else\n");
3913 printf(" GPR_UH(destreg,0) = HI_UH(0);\n");
3914
3915 printf(" if (HI_UW(1) > 0x00007FFF)\n");
3916 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
3917 printf(" else if (HI_UW(1) >= 0xFFFF8000)\n");
3918 printf(" GPR_UH(destreg,1) = 0x8000;\n");
3919 printf(" else\n");
3920 printf(" GPR_UH(destreg,1) = HI_UH(2);\n");
3921
3922 printf(" if (LO_UW(2) > 0x00007FFF)\n");
3923 printf(" GPR_UH(destreg,4) = 0x7FFF;\n");
3924 printf(" else if (LO_UW(2) >= 0xFFFF8000)\n");
3925 printf(" GPR_UH(destreg,4) = 0x8000;\n");
3926 printf(" else\n");
3927 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
3928
3929 printf(" if (LO_UW(3) > 0x00007FFF)\n");
3930 printf(" GPR_UH(destreg,5) = 0x7FFF;\n");
3931 printf(" else if (LO_UW(3) >= 0xFFFF8000)\n");
3932 printf(" GPR_UH(destreg,5) = 0x8000;\n");
3933 printf(" else\n");
3934 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
3935
3936 printf(" if (HI_UW(2) > 0x00007FFF)\n");
3937 printf(" GPR_UH(destreg,6) = 0x7FFF;\n");
3938 printf(" else if (HI_UW(2) >= 0xFFFF8000)\n");
3939 printf(" GPR_UH(destreg,6) = 0x8000;\n");
3940 printf(" else\n");
3941 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
3942
3943 printf(" if (HI_UW(3) > 0x00007FFF)\n");
3944 printf(" GPR_UH(destreg,7) = 0x7FFF;\n");
3945 printf(" else if (HI_UW(3) >= 0xFFFF8000)\n");
3946 printf(" GPR_UH(destreg,7) = 0x8000;\n");
3947 printf(" else\n");
3948 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
3949
3950 printf(" }\n");
3951 break;
3952
3953 case PLZCW:
3954 printf("unsigned long value;\n");
3955 printf("int test;\n");
3956 printf("int count;\n");
3957 printf("int i;\n");
3958
3959 printf("value = RS_UW(0);\n");
3960 printf("count = 0;\n");
3961 printf("test = !!(value & (1 << 31));\n");
3962 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
3963 printf(" count++;\n");
3964 printf("GPR_UW(destreg,0) = count;\n");
3965
3966 printf("value = RS_UW(1);\n");
3967 printf("count = 0;\n");
3968 printf("test = !!(value & (1 << 31));\n");
3969 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
3970 printf(" count++;\n");
3971 printf("GPR_UW(destreg,1) = count;\n");
3972 break;
3973
3974 case PEXT5:
3975 printf("int i;\n");
3976 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3977 printf(" {\n");
3978 printf(" int x = RT_UW(i);\n");
3979 printf(" GPR_UW(destreg,i) = ((x & (1 << 15)) << (24 - 15)) \n");
3980 printf(" | ((x & (31 << 10)) << (19 - 10)) \n");
3981 printf(" | ((x & (31 << 5)) << (11 - 5)) \n");
3982 printf(" | ((x & (31 << 0)) << (3 - 0)); \n");
3983 printf(" }\n");
3984 break;
3985
3986 case PPAC5:
3987 printf("int i;\n");
3988 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3989 printf(" {\n");
3990 printf(" int x = RT_UW(i);\n");
3991 printf(" GPR_UW(destreg,i) = ((x & (1 << 24)) >> (24 - 15)) \n");
3992 printf(" | ((x & (31 << 19)) >> (19 - 10)) \n");
3993 printf(" | ((x & (31 << 11)) >> (11 - 5)) \n");
3994 printf(" | ((x & (31 << 3)) >> (3 - 0)); \n");
3995 printf(" }\n");
3996 break;
3997 /* end-sanitize-r5900 */
3998
3999 case NYI:
4000 fprintf(stderr,"Warning: Unimplemented opcode: %s\n",insn->name) ;
4001
4002 printf("SignalException(ReservedInstruction,instruction);\n");
4003 break;
4004
4005 default:
4006 fprintf(stderr,"Unrecognised opcode type %d\n",insn->type) ;
4007 exit(6) ;
4008 }
4009 }
4010
4011 /*---------------------------------------------------------------------------*/
4012
4013 /* The command-line feature controls are presented in a similar style
4014 to those offered by GCC, in the aim of providing a consistent
4015 interface to the user. */
4016 typedef enum {
4017 T_NONE, /* no argument - mask and value fields control "feature" definition */
4018 T_NUM, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
4019 T_STRING /* string argument - optionally prcededed by '=' */
4020 } mactypes;
4021
4022 struct {
4023 char *name;
4024 mactypes type;
4025 unsigned int mask;
4026 unsigned int value;
4027 char *desc;
4028 } machine_options[] = {
4029 {"ips", T_NUM, MASK_ISA,0,"\tSelect MIPS ISA version"},
4030 {"cpu", T_STRING,0,0,"\t\tSelect particular MIPS architecture"},
4031 {"gp64", T_NONE, FEATURE_GP64,FEATURE_GP64,"\t\t\tSelect 64bit GP registers"},
4032 {"gp32", T_NONE, FEATURE_GP64,0,"\t\t\tSelect 32bit GP registers"},
4033 {"no-fp", T_NONE, FEATURE_HASFPU,0,"\t\tDisable FP simulation"},
4034 {"single-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),(FEATURE_FPSINGLE | FEATURE_HASFPU),"\t\tSelect single precision only FPU"},
4035 {"double-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),FEATURE_HASFPU,"\t\tSelect double precision FPU"},
4036 {0, T_NONE, 0,0}
4037 };
4038
4039 /* The following architecture identies are those accepted by the "-mcpu" option: */
4040 struct architectures {
4041 const char *name; /* ASCII string identifier for command-line, no white-space allowed */
4042 unsigned int idflag; /* or-ed into "isa" value */
4043 };
4044
4045 static const struct architectures available_architectures[] = {
4046 {"4100",ARCH_VR4100}, /* NEC MIPS VR4100 */
4047 /* start-sanitize-r5900 */
4048 {"5900",ARCH_R5900},
4049 /* end-sanitize-r5900 */
4050 {0, 0} /* terminator */
4051 };
4052
4053 /*---------------------------------------------------------------------------*/
4054
4055 static void
4056 usage(name)
4057 char *name;
4058 {
4059 int loop;
4060
4061 fprintf(stderr,"%s: Construct a MIPS simulator engine.\n",name);
4062
4063 fprintf(stderr,"\
4064 The output of this program is a block of 'C' code designed to be\n\
4065 included into the main simulation control loop of a device specific\n\
4066 simulator.\n");
4067
4068 fprintf(stderr,"\nOptions:\n");
4069 fprintf(stderr," -h --help\t\tProvide this help text\n");
4070 fprintf(stderr," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
4071 fprintf(stderr," -w --warnings\t\tEnable all the simulator engine warnings\n");
4072
4073 for (loop = 0; (machine_options[loop].name != 0); loop++) {
4074 fprintf(stderr," -m%s",machine_options[loop].name);
4075 switch (machine_options[loop].type) {
4076 case T_NUM :
4077 fprintf(stderr,"N (range 0..%d)",machine_options[loop].mask);
4078 case T_NONE :
4079 break;
4080
4081 case T_STRING :
4082 fprintf(stderr,"=name");
4083 break;
4084
4085 default :
4086 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",name,machine_options[loop].type);
4087 exit(1);
4088 }
4089 fprintf(stderr,"%s\n",machine_options[loop].desc);
4090 }
4091
4092 fprintf(stderr,"\nAvailable \"-mcpu\" architectures: ");
4093 for (loop = 0; (available_architectures[loop].name != 0); loop++)
4094 fprintf(stderr,"%s ",available_architectures[loop].name);
4095 fprintf(stderr,"\n\n");
4096
4097 fprintf(stderr,"\
4098 The \"trace\" and \"warnings\" options do not define the output stream.\n\
4099 They only inform the code that includes the constructed engine to provide\n\
4100 the required features.\n\n\
4101 The \"-mips0\" option forces the construction of a simulator supporting\n\
4102 the highest available MIPS ISA supported.\n");
4103
4104 return;
4105 }
4106
4107 /*---------------------------------------------------------------------------*/
4108
4109 int
4110 main(argc,argv)
4111 int argc;
4112 char **argv;
4113 {
4114 int c;
4115 char *progname = argv[0];
4116 unsigned int doarch = DEF_ISA;
4117 unsigned int features = 0; /* default state */
4118
4119 if (DEF_FP)
4120 features |= FEATURE_HASFPU;
4121 if (!DEF_PROC64)
4122 features |= FEATURE_PROC32;
4123 if (DEF_FPSINGLE)
4124 features |= FEATURE_FPSINGLE;
4125
4126 if (features & FEATURE_PROC32)
4127 features &= ~FEATURE_GP64;
4128 else
4129 features |= FEATURE_GP64;
4130
4131 while (1) {
4132 int option_index = 0;
4133 static struct option cmdline[] = {
4134 {"fast", 0,0,'f'},
4135 {"help", 0,0,'h'},
4136 {"warnings",0,0,'w'},
4137 {0, 0,0,0}
4138 };
4139
4140 c = getopt_long(argc,argv,"hm:tw",cmdline,&option_index);
4141 if (c == -1)
4142 break ; /* out of the while loop */
4143
4144 switch (c) {
4145 case 'h' : /* help */
4146 usage(progname);
4147 exit(0);
4148
4149 case 'f' : /* fast */
4150 features |= FEATURE_FAST;
4151 break;
4152
4153 case 'w' : /* warnings */
4154 features |= FEATURE_WARNINGS;
4155 /* TODO: Future extension: Allow better control over the warnings generated:
4156 disable warnings -wnone ~FEATURE_WARNINGS
4157 all possible warnings -wall FEATURE_WARNINGS
4158 pipeline stall occuring -wstall FEATURE_WARN_STALL
4159 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
4160 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
4161 bad r31 use -wr31 FEATURE_WARN_R31
4162 undefined results -wresult FEATURE_WARN_RESULT
4163 */
4164 break;
4165
4166 case 'm' : /* machine options */
4167 {
4168 int loop;
4169
4170 for (loop = 0; (machine_options[loop].name != 0); loop++)
4171 if (strncmp(machine_options[loop].name,optarg,strlen(machine_options[loop].name)) == 0) {
4172 char *loptarg = (optarg + strlen(machine_options[loop].name));
4173 switch (machine_options[loop].type) {
4174 case T_NONE :
4175 if (*loptarg) {
4176 fprintf(stderr,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname,loptarg,machine_options[loop].name);
4177 exit(1);
4178 }
4179 features &= ~(machine_options[loop].mask);
4180 features |= machine_options[loop].value;
4181 break;
4182
4183 case T_NUM :
4184 if (*loptarg && *loptarg == '=')
4185 loptarg++;
4186
4187 if (strcmp(machine_options[loop].name,"ips") == 0) {
4188 unsigned int num;
4189
4190 if (!*loptarg) {
4191 fprintf(stderr,"%s: ISA number expected after -mips\n",progname);
4192 exit(1);
4193 }
4194
4195 num = my_strtoul(loptarg,&loptarg,10);
4196
4197 if ((num == ULONG_MAX) && (errno = ERANGE)) {
4198 fprintf(stderr,"%s: Invalid number given to -mips option\n",progname);
4199 exit(1);
4200 }
4201
4202 if (*loptarg) {
4203 fprintf(stderr,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname,loptarg);
4204 exit(1);
4205 }
4206
4207 if (num > MASK_ISA) {
4208 fprintf(stderr,"%s: ISA number %d outside acceptable range (0..%d)\n",progname,num,MASK_ISA);
4209 exit(1);
4210 }
4211
4212 doarch = ((doarch & ~MASK_ISA) | num);
4213 if ((num == 0) || (num > 2)) {
4214 if ((features & FEATURE_PROC32) || !(features & FEATURE_GP64))
4215 fprintf(stderr,"%s: Warning: -mips%d forcing -mgp64\n",progname,num);
4216 features |= FEATURE_GP64;
4217 features &= ~FEATURE_PROC32;
4218 } else {
4219 if (!(features & FEATURE_PROC32) || (features & FEATURE_GP64))
4220 fprintf(stderr,"%s: Warning: -mips%d forcing -mgp32\n",progname,num);
4221 features &= ~FEATURE_GP64;
4222 features |= FEATURE_PROC32;
4223 }
4224 } else {
4225 fprintf(stderr,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname,optarg);
4226 exit(1);
4227 }
4228 break;
4229
4230 case T_STRING :
4231 if (*loptarg && *loptarg == '=')
4232 loptarg++;
4233
4234 if (strcmp(machine_options[loop].name,"cpu") == 0) {
4235 int archloop;
4236
4237 if (!*loptarg) {
4238 fprintf(stderr,"%s: Architecture identifier expected after -mcpu\n",progname);
4239 exit(1);
4240 }
4241
4242 for (archloop = 0; (available_architectures[archloop].name != 0); archloop++) {
4243 if ((*loptarg == 'v') || (*loptarg == 'V'))
4244 loptarg++;
4245
4246 if ((*loptarg == 'r') || (*loptarg == 'R'))
4247 loptarg++;
4248
4249 if (strcmp(available_architectures[archloop].name,loptarg) == 0) {
4250 doarch |= available_architectures[archloop].idflag;
4251 break;
4252 }
4253 }
4254
4255 if (available_architectures[archloop].name == 0) {
4256 fprintf(stderr,"%s: Unrecognised MIPS architecture \"%s\"\n",progname,loptarg);
4257 exit(1);
4258 }
4259 } else {
4260 fprintf(stderr,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname,optarg);
4261 exit(1);
4262 }
4263 break;
4264
4265 default :
4266 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",progname,machine_options[loop].type);
4267 exit(1);
4268 }
4269 break;
4270 }
4271
4272 if (machine_options[loop].name == 0) {
4273 fprintf(stderr,"%s: Unrecognised option: -m%s\n",progname,optarg);
4274 exit(1);
4275 }
4276 }
4277 break;
4278
4279 case '?' :
4280 /* An error message should already have been displayed */
4281 exit(1);
4282
4283 default :
4284 fprintf(stderr,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname,c);
4285 exit(1);
4286 }
4287 }
4288
4289 if (optind < argc) {
4290 fprintf(stderr,"%s: Spurios non-option arguments ",progname);
4291 while (optind < argc)
4292 fprintf(stderr,"\"%s\" ",argv[optind++]);
4293 fprintf(stderr,"\n");
4294 exit(1);
4295 }
4296
4297 if ((features & FEATURE_FAST) && (features & FEATURE_WARNINGS))
4298 fprintf(stderr,"Warning: Fast model generation selected, along with trace or warnings.\n");
4299
4300 process_instructions(doarch,features) ;
4301 return(0) ;
4302 }
4303
4304 /*---------------------------------------------------------------------------*/
4305
4306 /* We can't assume that the compiler for the build system has strtoul,
4307 so we provide our own copy. */
4308
4309 /*
4310 * Copyright (c) 1990 Regents of the University of California.
4311 * All rights reserved.
4312 *
4313 * Redistribution and use in source and binary forms, with or without
4314 * modification, are permitted provided that the following conditions
4315 * are met:
4316 * 1. Redistributions of source code must retain the above copyright
4317 * notice, this list of conditions and the following disclaimer.
4318 * 2. Redistributions in binary form must reproduce the above copyright
4319 * notice, this list of conditions and the following disclaimer in the
4320 * documentation and/or other materials provided with the distribution.
4321 * 3. All advertising materials mentioning features or use of this software
4322 * must display the following acknowledgement:
4323 * This product includes software developed by the University of
4324 * California, Berkeley and its contributors.
4325 * 4. Neither the name of the University nor the names of its contributors
4326 * may be used to endorse or promote products derived from this software
4327 * without specific prior written permission.
4328 *
4329 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4330 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4331 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4332 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4333 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4334 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4335 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4336 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4337 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4338 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4339 * SUCH DAMAGE.
4340 */
4341
4342 /*
4343 * Convert a string to an unsigned long integer.
4344 *
4345 * Ignores `locale' stuff. Assumes that the upper and lower case
4346 * alphabets and digits are each contiguous.
4347 */
4348 static unsigned long
4349 my_strtoul(nptr, endptr, base)
4350 const char *nptr;
4351 char **endptr;
4352 register int base;
4353 {
4354 register const char *s = nptr;
4355 register unsigned long acc;
4356 register int c;
4357 register unsigned long cutoff;
4358 register int neg = 0, any, cutlim;
4359
4360 /*
4361 * See strtol for comments as to the logic used.
4362 */
4363 do {
4364 c = *s++;
4365 } while (isspace(c));
4366 if (c == '-') {
4367 neg = 1;
4368 c = *s++;
4369 } else if (c == '+')
4370 c = *s++;
4371 if ((base == 0 || base == 16) &&
4372 c == '0' && (*s == 'x' || *s == 'X')) {
4373 c = s[1];
4374 s += 2;
4375 base = 16;
4376 }
4377 if (base == 0)
4378 base = c == '0' ? 8 : 10;
4379 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
4380 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
4381 for (acc = 0, any = 0;; c = *s++) {
4382 if (isdigit(c))
4383 c -= '0';
4384 else if (isalpha(c))
4385 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
4386 else
4387 break;
4388 if (c >= base)
4389 break;
4390 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
4391 any = -1;
4392 else {
4393 any = 1;
4394 acc *= base;
4395 acc += c;
4396 }
4397 }
4398 if (any < 0) {
4399 acc = ULONG_MAX;
4400 errno = ERANGE;
4401 } else if (neg)
4402 acc = -acc;
4403 if (endptr != 0)
4404 *endptr = (char *) (any ? s - 1 : nptr);
4405 return (acc);
4406 }
4407
4408 /*---------------------------------------------------------------------------*/
4409
4410 /*> EOF gencode.c <*/
4411
4412
4413
4414
4415
4416
4417
This page took 0.144696 seconds and 5 git commands to generate.