2 /* Instruction handling support for the MIPS architecture simulator.
4 This file is part of the MIPS sim
6 THIS SOFTWARE IS NOT COPYRIGHTED
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.
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.
22 #define DEBUG (1) /* Just for testing */
25 /* All output sent to stdout is for the simulator engine. All program
26 related warnings and errors should be sent to stderr. */
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
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.
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).
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). */
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. */
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. */
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
100 /*---------------------------------------------------------------------------*/
102 /* Program defaults */
104 #define DEF_PROC64 (1 == 1)
105 #define DEF_FP (1 == 1)
106 #define DEF_FPSINGLE (1 == 0)
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 */
121 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31)
123 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
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). */
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. */
142 /* FEATURE_WARN_ZERO */
143 /* Notify the user if an attempt is made to use GPR 0 as a destination. */
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). */
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
159 /*---------------------------------------------------------------------------*/
166 #include "ansidecl.h"
167 #include "opcode/mips.h"
169 /* FIXME: ansidecl.h defines AND. */
173 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
176 static unsigned long my_strtoul ();
180 #define TRUE (1 == 1)
181 #define FALSE (1 == 0)
185 /*---------------------------------------------------------------------------*/
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: */
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): */
196 typedef struct operand_encoding
{
197 char id
; /* character identifier */
198 int fpos
; /* first bit position */
199 int flen
; /* field length in bits */
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 */
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 */
249 /* Main instruction encoding types: */
256 COP1S
, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
264 /* mips16 encoding types. */
265 I
, RI
, RR
, RRI
, RRR
, RRI_A
, ISHIFT
, I8
, I8_MOVR32
, I8_MOV32R
, I64
, RI64
268 /* Main instruction families: */
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 */
309 /* start-sanitize-r5900 */
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" */
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 */
373 /* Shorthand to get the size field from the flags value: */
374 #define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
376 /* The rest are single bit flags: */
377 #define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
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. */
410 /* Overloadings of above bits */
411 #define PIPE1 LIKELY /* Using pipeline 1 (DIV,MUL) */
412 #define OP3 EQ /* 3 operand version of operation (MUL) */
414 #define SATURATE OVERFLOW /* for PADD, saturate for overflow */
416 #define SUBTRACT LEFT /* for PMULT, PMULT becomes PMSUB */
417 #define ADDITION RIGHT /* for PMULT, PMULT becomes PMADD */
419 #define FROM LEFT /* move from special register */
420 #define TO RIGHT /* move to special register */
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 = ^ */
428 #define GET_OP_FROM_INSN(insn) (((insn)->flags)&(LEFT|LIKELY))
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 */
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. */
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. */
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.
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;
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.
466 Independent bits are listed in MASK_ISA_INDEP, the rest are dependent.
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 */
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 */ \
477 /* end-sanitize-r5900 */ \
480 #define MASK_ISA_DEP ~(MASK_ISA_INDEP | MASK_ISA)
483 /* Very short names for use in the table below to keep it neet. */
484 #define G1 (3 | ARCH_VR4100)
487 /* start-sanitize-r5900 */ \
489 /* end-sanitize-r5900 */ \
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 */ \
497 /* end-sanitize-r5900 */ \
502 /* start-sanitize-r5900 */
503 #define T5 ARCH_R5900
504 /* end-sanitize-r5900 */
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. */
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
)},
667 /* start-sanitize-r5900 */
668 {"PABSH", T5
,"01110000000TTTTTddddd00101101000",MMI1
, PABS
, (HALFWORD
)},
669 {"PABSW", T5
,"01110000000TTTTTddddd00001101000",MMI1
, PABS
, (WORD
)},
671 {"PADDB", T5
,"011100SSSSSTTTTTddddd01000001000",MMI0
, PADD
, (BYTE
)},
672 {"PADDH", T5
,"011100SSSSSTTTTTddddd00100001000",MMI0
, PADD
, (HALFWORD
)},
673 {"PADDW", T5
,"011100SSSSSTTTTTddddd00000001000",MMI0
, PADD
, (WORD
)},
675 {"PADDSB", T5
,"011100SSSSSTTTTTddddd11000001000",MMI0
, PADD
, (BYTE
| SATURATE
)},
676 {"PADDSH", T5
,"011100SSSSSTTTTTddddd10100001000",MMI0
, PADD
, (HALFWORD
| SATURATE
)},
677 {"PADDSW", T5
,"011100SSSSSTTTTTddddd10000001000",MMI0
, PADD
, (WORD
| SATURATE
)},
679 {"PADDUB", T5
,"011100SSSSSTTTTTddddd11000101000",MMI1
, PADD
, (BYTE
| UNSIGNED
)},
680 {"PADDUH", T5
,"011100SSSSSTTTTTddddd10100101000",MMI1
, PADD
, (HALFWORD
| UNSIGNED
)},
681 {"PADDUW", T5
,"011100SSSSSTTTTTddddd10000101000",MMI1
, PADD
, (WORD
| UNSIGNED
)},
683 {"PADSBH", T5
,"011100SSSSSTTTTTddddd00100101000",MMI1
, PADSBH
, (NONE
)},
685 {"PAND", T5
,"011100SSSSSTTTTTddddd10010001001",MMI2
, POP
, (POP_AND
)},
687 {"PCEQB", T5
,"011100SSSSSTTTTTddddd01010101000",MMI1
, PCMP
, (EQ
| BYTE
)},
688 {"PCEQH", T5
,"011100SSSSSTTTTTddddd00110101000",MMI1
, PCMP
, (EQ
| HALFWORD
)},
689 {"PCEQW", T5
,"011100SSSSSTTTTTddddd00010101000",MMI1
, PCMP
, (EQ
| WORD
)},
691 {"PCGTB", T5
,"011100SSSSSTTTTTddddd01010001000",MMI0
, PCMP
, (GT
| BYTE
)},
692 {"PCGTH", T5
,"011100SSSSSTTTTTddddd00110001000",MMI0
, PCMP
, (GT
| HALFWORD
)},
693 {"PCGTW", T5
,"011100SSSSSTTTTTddddd00010001000",MMI0
, PCMP
, (GT
| WORD
)},
695 {"PCPYH", T5
,"01110000000TTTTTddddd11011101001",MMI3
, PCPYH
, (NONE
)},
696 {"PCPYLD", T5
,"011100SSSSSTTTTTddddd01110001001",MMI2
, PCPYLD
, (NONE
)},
697 {"PCPYUD", T5
,"011100SSSSSTTTTTddddd01110101001",MMI3
, PCPYUD
, (NONE
)},
699 {"PDIVBW", T5
,"011100SSSSSTTTTT0000011101001001",MMI2
, PDIVBW
, (NONE
)},
700 {"PDIVUW", T5
,"011100SSSSSTTTTT0000001101101001",MMI3
, PDIVW
, (UNSIGNED
)},
701 {"PDIVW", T5
,"011100SSSSSTTTTT0000001101001001",MMI2
, PDIVW
, (NONE
)},
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
)},
708 {"PEXT5", T5
,"01110000000TTTTTddddd11110001000",MMI0
, PEXT5
, (NONE
)},
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
)},
717 {"PHMADDH",T5
,"011100SSSSSTTTTTddddd10001001001",MMI2
, PHMADDH
, (NONE
)},
718 {"PHMSUBH",T5
,"011100SSSSSTTTTTddddd10101001001",MMI2
, PHMADDH
, (SUBTRACT
)},
720 {"PINTH", T5
,"011100SSSSSTTTTTddddd01010001001",MMI2
, PINTH
, (NONE
)},
721 {"PINTOH", T5
,"011100SSSSSTTTTTddddd01010101001",MMI3
, PINTOH
, (NONE
)},
723 {"PLZCW", T5
,"011100SSSSS00000ddddd00000000100",MMINORM
,PLZCW
, (NONE
)},
725 {"PMADDH", T5
,"011100SSSSSTTTTTddddd10000001001",MMI2
, PMULTH
, (ADDITION
)},
726 {"PMADDUW",T5
,"011100SSSSSTTTTTddddd00000101001",MMI3
, PMULTW
, (ADDITION
| UNSIGNED
)},
727 {"PMADDW", T5
,"011100SSSSSTTTTTddddd00000001001",MMI2
, PMULTW
, (ADDITION
)},
729 {"PMAXH", T5
,"011100SSSSSTTTTTddddd00111001000",MMI0
, PMAXMIN
, (GT
| HALFWORD
)},
730 {"PMAXW", T5
,"011100SSSSSTTTTTddddd00011001000",MMI0
, PMAXMIN
, (GT
| WORD
)},
732 {"PMFHI", T5
,"0111000000000000ddddd01000001001",MMI2
, PMXX
, (HI
|FROM
)},
733 {"PMFLO", T5
,"0111000000000000ddddd01001001001",MMI2
, PMXX
, (LO
|FROM
)},
735 {"PMFHL", T5
,"0111000000000000dddddaaaaa110000",MMINORM
,PMFHL
, (NONE
)},
737 {"PMINH", T5
,"011100SSSSSTTTTTddddd00111101000",MMI1
, PMAXMIN
, (LT
| HALFWORD
)},
738 {"PMINW", T5
,"011100SSSSSTTTTTddddd00011101000",MMI1
, PMAXMIN
, (LT
| WORD
)},
740 {"PMSUBH", T5
,"011100SSSSSTTTTTddddd10100001001",MMI2
, PMULTH
, (SUBTRACT
)},
741 {"PMSUBW", T5
,"011100SSSSSTTTTTddddd00100001001",MMI2
, PMULTW
, (SUBTRACT
)},
743 {"PMTHI", T5
,"011100SSSSS000000000001000101001",MMI3
, PMXX
, (HI
|TO
)},
744 {"PMTLO", T5
,"011100SSSSS000000000001001101001",MMI3
, PMXX
, (LO
|TO
)},
746 {"PMTHL.LW",T5
,"011100SSSSS000000000000000110001",MMINORM
,PMTHL
, (NONE
)},
748 {"PMULTH", T5
,"011100SSSSSTTTTTddddd11100001001",MMI2
, PMULTH
, (NONE
)},
749 {"PMULTUW",T5
,"011100SSSSSTTTTTddddd01100101001",MMI3
, PMULTW
, (UNSIGNED
)},
750 {"PMULTW", T5
,"011100SSSSSTTTTTddddd01100001001",MMI2
, PMULTW
, (NONE
)},
752 {"PNOR", T5
,"011100SSSSSTTTTTddddd10011101001",MMI3
, POP
, (POP_NOR
)},
753 {"POR", T5
,"011100SSSSSTTTTTddddd10010101001",MMI3
, POP
, (POP_OR
)},
755 {"PPAC5", T5
,"01110000000TTTTTddddd11111001000",MMI0
, PPAC5
, (NONE
)},
757 {"PPACB", T5
,"011100SSSSSTTTTTddddd11011001000",MMI0
, PPACB
, (NONE
)},
758 {"PPACH", T5
,"011100SSSSSTTTTTddddd10111001000",MMI0
, PPACH
, (NONE
)},
759 {"PPACW", T5
,"011100SSSSSTTTTTddddd10011001000",MMI0
, PPACW
, (NONE
)},
761 {"PREVH", T5
,"01110000000TTTTTddddd11011001001",MMI2
, PREVH
, (NONE
)},
762 {"PROT3W", T5
,"01110000000TTTTTddddd11111001001",MMI2
, PROT3W
, (NONE
)},
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
)},
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
)},
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
)},
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
)},
786 {"PXOR", T5
,"011100SSSSSTTTTTddddd10011001001",MMI2
, POP
, (POP_XOR
)},
787 /* end-sanitize-r5900 */
789 {"PREF", G2
,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, PREFETCH
, (NONE
)},
790 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X
, FPPREFX
, (FP
)},
792 /* start-sanitize-r5900 */
793 {"QFSRV", T5
,"011100SSSSSTTTTTddddd11011101000",MMI1
, QFSRV
, (NONE
)},
794 /* end-sanitize-r5900 */
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
)},
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
},
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
},
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
}
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
*));
949 /*---------------------------------------------------------------------------*/
952 name_for_data_len( insn
)
953 struct instruction
* insn
;
955 if (GETDATASIZEINSN(insn
) == BYTE
)
958 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
961 else if (GETDATASIZEINSN(insn
) == WORD
)
964 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
967 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
975 letter_for_data_len( insn
)
976 struct instruction
* insn
;
978 if (GETDATASIZEINSN(insn
) == BYTE
)
981 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
984 else if (GETDATASIZEINSN(insn
) == WORD
)
987 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
990 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
998 type_for_data_len( insn
)
999 struct instruction
* insn
;
1001 if (GETDATASIZEINSN(insn
) == BYTE
)
1004 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1007 else if (GETDATASIZEINSN(insn
) == WORD
)
1010 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1013 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1021 max_for_data_len( insn
)
1022 struct instruction
* insn
;
1024 if (GETDATASIZEINSN(insn
) == BYTE
)
1027 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1030 else if (GETDATASIZEINSN(insn
) == WORD
)
1031 return "(int)0x7FFFFFFF";
1033 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1036 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1044 min_for_data_len( insn
)
1045 struct instruction
* insn
;
1047 if (GETDATASIZEINSN(insn
) == BYTE
)
1050 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1053 else if (GETDATASIZEINSN(insn
) == WORD
)
1054 return "(int)0x80000000";
1056 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1059 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1067 umax_for_data_len( insn
)
1068 struct instruction
* insn
;
1070 if (GETDATASIZEINSN(insn
) == BYTE
)
1073 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1076 else if (GETDATASIZEINSN(insn
) == WORD
)
1077 return "0xFFFFFFFF";
1079 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1082 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1090 bits_for_data_len( insn
)
1091 struct instruction
* insn
;
1093 if (GETDATASIZEINSN(insn
) == BYTE
)
1096 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1099 else if (GETDATASIZEINSN(insn
) == WORD
)
1102 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1105 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1112 /*---------------------------------------------------------------------------*/
1116 convert_bitmap(bitmap
,onemask
,zeromask
,dontmask
)
1118 unsigned int *onemask
, *zeromask
, *dontmask
;
1120 int loop
; /* current bitmap position */
1121 int lastsp
= -1; /* last bitmap field starting position */
1122 int lastoe
= -1; /* last bitmap field encoding */
1124 *onemask
= 0x00000000;
1125 *zeromask
= 0x00000000;
1126 *dontmask
= 0x00000000;
1128 if (strlen(bitmap
) != 32) {
1129 fprintf(stderr
,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap
);
1133 for (loop
= 0; (loop
< 32); loop
++) {
1135 for (oefield
= 0; (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))); oefield
++)
1136 if (bitmap
[31 - loop
] == opfields
[oefield
].id
)
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
);
1145 switch (bitmap
[31 - loop
]) {
1146 case '0' : /* fixed value */
1147 *zeromask
|= (1 << loop
);
1152 case '1' : /* fixed value */
1153 *onemask
|= (1 << loop
);
1158 case '?' : /* fixed value */
1159 *dontmask
|= (1 << loop
);
1164 default : /* check character encoding */
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
);
1177 *dontmask
|= (1 << loop
);
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
);
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. */
1192 /* Get the value of a 16 bit bitstring for a given shift count and
1196 bitmap_val (bitmap
, shift
, bits
)
1205 s
= bitmap
+ 16 - shift
- bits
;
1206 for (; bits
> 0; --bits
)
1221 /*---------------------------------------------------------------------------*/
1224 build_operands(doisa
,features
,insn
)
1226 unsigned int features
;
1229 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
1230 int finish_jump_flag
= 0;
1232 int check_condition_code
= 0;
1233 int sfield_used
= 0;
1234 int gfield_used
= 0;
1235 int any_operand
= 0;
1237 int current_field_id
= -1;
1240 for (bitpos
=0; bitpos
<32; bitpos
++) {
1241 if (insn
->bitmap
[31-bitpos
] != current_field_id
)
1245 current_field_id
= insn
->bitmap
[31-bitpos
];
1247 for (opindex
= 0; (opindex
< (sizeof(opfields
) / sizeof(operand_encoding
))); opindex
++)
1248 if ((opfields
[opindex
].fpos
!= -1) && (opfields
[opindex
].id
== insn
->bitmap
[31-bitpos
])) {
1252 printf(" %s %s = ",opfields
[opindex
].type
,opfields
[opindex
].name
);
1254 if (opfields
[opindex
].flags
& OP_SIGNX
)
1255 printf("SIGNEXTEND((%s)",opfields
[opindex
].type
);
1257 if (opfields
[opindex
].flags
& OP_GPR
)
1260 if (opfields
[opindex
].flags
& OP_SHIFT2
)
1263 printf("((instruction >> %d) & 0x%08X)",opfields
[opindex
].fpos
,((1 << opfields
[opindex
].flen
) - 1));
1265 if (opfields
[opindex
].flags
& OP_SHIFT2
)
1268 if (opfields
[opindex
].flags
& OP_GPR
)
1271 if (opfields
[opindex
].flags
& OP_BITS5
)
1274 if (opfields
[opindex
].flags
& OP_SIGNX
)
1275 printf(",%d)",(opfields
[opindex
].flen
+ ((opfields
[opindex
].flags
& OP_SHIFT2
) ? 2 : 0)));
1279 if (opfields
[opindex
].flags
& OP_GPR1
)
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));
1288 if (opfields
[opindex
].id
== 'j')
1289 finish_jump_flag
= 1;
1291 if (opfields
[opindex
].id
== 'e')
1294 if (opfields
[opindex
].id
== 'w')
1297 if (opfields
[opindex
].id
== 'w')
1300 if (opfields
[opindex
].id
== 'p')
1301 check_condition_code
= 1;
1303 if (opfields
[opindex
].id
== 's')
1306 if (opfields
[opindex
].id
== 'g')
1312 if ( !any_operand
&& !(insn
->flags
& NOARG
)) {
1313 fprintf(stderr
,"Bitmap error: Instruction with no operand fields \"%s\"\n",insn
->name
) ;
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");
1321 /* Now perform required operand checks: */
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. */
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
1338 if (check_mult
!= 0 && check_mult
!= 1) {
1339 printf(" if (instruction & 0x%1X)\n", check_mult
);
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
1345 printf(" sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
1350 /* The extended condition codes only appeared in ISA IV */
1351 if (check_condition_code
&& (doisa
< 4)) {
1352 printf(" if (condition_code != 0)\n");
1354 printf(" SignalException(ReservedInstruction,instruction);\n");
1359 if ((insn
->flags
& WORD32
) && (GETDATASIZEINSN(insn
) != WORD
)) {
1360 fprintf(stderr
,"Error in opcode table: WORD32 set for non-WORD opcode\n");
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") ;
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") ;
1389 /* The mips16 operand table. */
1393 /* The character which appears in the bitmap string. */
1395 /* The type of the variable in the simulator. */
1396 const char *vartype
;
1397 /* The name of the variable in the simulator. */
1399 /* The number of bits. */
1401 /* The number of bits when extended (zero if can not be extended). */
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. */
1410 /* Flags which appears in the mips16 operand table. */
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)
1429 #define MIPS16_ZERO (0x100)
1431 #define MIPS16_TREG (0x200)
1433 #define MIPS16_RA (0x400)
1435 #define MIPS16_JUMP_ADDR (0x800)
1436 /* Branch offset. */
1437 #define MIPS16_BRANCH (0x1000)
1439 /* The mips16 operand table. */
1441 static const struct mips16_op mips16_op_table
[] =
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
},
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
},
1488 { '\0', NULL
, NULL
, 0, 0, 0, 0 }
1491 /* Build mips16 operands. */
1494 build_mips16_operands (bitmap
)
1499 const struct mips16_op
*op
= NULL
;
1500 const struct mips16_op
*ops
[3];
1504 for (s
= bitmap
; *s
!= '\0'; s
++)
1511 /* Make sure we saw the right number of bits for that
1513 if (op
->nbits
!= 0 && (s
- bitmap
) - op
->nbits
!= start
)
1518 if (*s
== '0' || *s
== '1' || *s
== '?')
1523 for (op
= mips16_op_table
; op
->type
!= *s
; ++op
)
1524 if (op
->type
== '\0')
1527 printf (" %s %s = ", op
->vartype
, op
->name
);
1529 printf ("(instruction >> %d) & 0x%x",
1530 16 - (s
- bitmap
) - op
->nbits
,
1531 (1 << op
->nbits
) - 1);
1534 if ((op
->flags
& MIPS16_SP
) != 0)
1536 else if ((op
->flags
& MIPS16_PC
) != 0)
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);
1545 else if ((op
->flags
& MIPS16_ZERO
) != 0)
1547 else if ((op
->flags
& MIPS16_TREG
) != 0)
1549 else if ((op
->flags
& MIPS16_RA
) != 0)
1556 if ((op
->flags
& MIPS16_DESTREG
) != 0)
1557 printf (" int destreg;\n");
1567 /* Make sure we saw the right number of bits for that
1569 if (op
->nbits
!= 0 && 16 - op
->nbits
!= start
)
1573 for (i
= 0; i
< opindex
; i
++)
1576 if ((op
->flags
& MIPS16_REG16
) != 0)
1578 printf (" if (%s < 2)\n", op
->name
);
1579 printf (" %s += 16;\n", op
->name
);
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
);
1589 if (op
->extbits
!= 0)
1591 printf (" if (have_extendval)\n");
1593 if (op
->extbits
== 16)
1594 printf (" %s |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0);\n",
1596 else if (op
->extbits
== 15)
1597 printf (" %s |= ((extendval & 0xf) << 11) | (extendval & 0x7f0);\n",
1599 else if (op
->extbits
== 6)
1600 printf (" %s = ((extendval >> 6) & 0x1f) | (extendval & 0x20);\n",
1603 printf (" %s = (extendval >> 6) & 0x1f;\n",
1605 if ((op
->flags
& MIPS16_EXTU
) == 0)
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
);
1612 printf (" have_extendval = 0;\n");
1616 if ((op
->flags
& MIPS16_UNSP
) == 0)
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
);
1624 printf (" %s <<= %d;\n", op
->name
, op
->shift
);
1625 if (op
->type
== '<' || op
->type
== '>'
1626 || op
->type
== '[' || op
->type
== ']')
1628 printf (" if (%s == 0)\n", op
->name
);
1629 printf (" %s = 8;\n", op
->name
);
1634 if ((op
->flags
& MIPS16_BRANCH
) != 0)
1635 printf (" %s *= 2;\n", op
->name
);
1637 if ((op
->flags
& MIPS16_JUMP_ADDR
) != 0)
1640 printf (" uword64 paddr;\n");
1641 printf (" int uncached;\n");
1642 printf (" if (AddressTranslation (PC &~ (uword64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL))\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");
1660 printf (" %s |= PC & ~ (uword64) 0x0fffffff;\n", op
->name
);
1664 /* FIXME: Is this the way to detect an unused extend opcode? */
1665 printf (" if (have_extendval)\n");
1666 printf (" SignalException (ReservedInstruction, instruction);\n");
1669 /*---------------------------------------------------------------------------*/
1677 build_endian_shift(proc64
,datalen
,endbit
,direction
,shift
)
1681 e_endshift direction
;
1685 printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit
,endbit
);
1686 printf(" memval %s= %d;\n",direction
== s_left
? "<<" : ">>",shift
);
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.
1701 process_instructions(doarch
,features
)
1702 unsigned int doarch
;
1703 unsigned int features
;
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
);
1715 fprintf(stderr
,"process_instructions: invalid structure length\n");
1719 if (proc64
&& (gprlen
!= 64)) {
1720 fprintf(stderr
,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
1724 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
1727 for (loop
= 0; (loop
< limit
); loop
++)
1728 if ((MIPS_DECODE
[loop
].isa
& MASK_ISA
) > maxisa
)
1729 maxisa
= (MIPS_DECODE
[loop
].isa
& MASK_ISA
);
1734 printf("#if defined(SIM_MANIFESTS)\n");
1735 printf("#define MIPSISA (%d)\n",doisa
);
1737 printf("#define PROCESSOR_64BIT (1 == 1)\n");
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);
1743 printf("#define LOADDRMASK (0x%08X)\n",(proc64
? 0x7 : 0x3));
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"));
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");
1767 printf("#else /* simulator engine */\n");
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
);
1772 printf("/* %sFP instructions included */\n",(fpsingle
? "Single precision " : ""));
1773 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
1776 printf("#if !defined(PROCESSOR_64BIT)\n");
1777 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
1781 printf("/* Actual instruction decoding block */\n");
1782 printf("if ((vaddr & 1) == 0){\n");
1785 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP
,OP_MASK_OP
);
1786 limit
= (OP_MASK_OP
+ 1);
1788 printf("#ifdef DEBUG\n");
1789 printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n");
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);
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);
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
)));
1803 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
1804 limit
+= (OP_MASK_SPEC
+ 1);
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
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);
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);
1818 printf("else if (num == 0x1C) {\n");
1819 printf(" int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI
,OP_MASK_MMI
);
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);
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);
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);
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);
1838 printf(" num = (%d + mmi_func);\n",limit
);
1839 limit
+= (OP_MASK_MMI
+ 1);
1843 printf("/* Total possible switch entries: %d */\n",limit
) ;
1846 printf("#ifdef DEBUG\n");
1847 printf("printf(\"DBG: num = %%d\\n\",num);\n");
1850 printf("switch (num)\n") ;
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
;
1868 unsigned int number
;
1870 convert_bitmap(MIPS_DECODE
[loop
].bitmap
,&onemask
,&zeromask
,&dontmask
);
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
);
1879 printf("/* DEBUG: onemask 0x%08X */\n",onemask
) ;
1880 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask
) ;
1881 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask
) ;
1884 switch (MIPS_DECODE
[loop
].mark
) {
1886 mask
= (OP_MASK_OP
<< OP_SH_OP
) ;
1887 number
= ((onemask
>> OP_SH_OP
) & OP_MASK_OP
) ;
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
)) ;
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
)) ;
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
)) ;
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
)) ;
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
)) ;
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
)) ;
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
)) ;
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
)) ;
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
)) ;
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
)) ;
1960 fprintf(stderr
,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE
[loop
].mark
,loop
,MIPS_DECODE
[loop
].name
) ;
1964 printf("case %d : /* \"%s\" %s */\n",number
,MIPS_DECODE
[loop
].name
,MIPS_DECODE
[loop
].bitmap
) ;
1967 printf("/* DEBUG: mask 0x%08X */\n",mask
) ;
1968 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE
[loop
].name
);
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
) ;
1975 printf(" SignalException(ReservedInstruction,instruction);\n") ;
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.
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.
1993 build_operands(doisa
, features
, &MIPS_DECODE
[loop
]);
1997 build_instruction (doisa
, features
, 0, &MIPS_DECODE
[loop
]);
2001 printf(" break ;\n") ;
2005 printf("default : /* Unrecognised instruction */\n") ;
2006 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2007 printf(" break ;\n") ;
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
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");
2037 for (loop
= 0; loop
< sizeof MIPS16_DECODE
/ sizeof MIPS16_DECODE
[0]; loop
++)
2042 if (! proc64
&& GETDATASIZEINSN (&MIPS16_DECODE
[loop
]) == DOUBLEWORD
)
2045 bitmap
= MIPS16_DECODE
[loop
].bitmap
;
2046 switch (MIPS16_DECODE
[loop
].mark
)
2051 num
= bitmap_val (bitmap
, 11, 5);
2054 num
= 32 + bitmap_val (bitmap
, 0, 2);
2057 num
= 36 + bitmap_val (bitmap
, 4, 1);
2062 num
= 38 + bitmap_val (bitmap
, 8, 3);
2065 num
= 46 + bitmap_val (bitmap
, 0, 2);
2071 minor
= bitmap_val (bitmap
, 0, 5);
2075 num
= 90 + bitmap_val (bitmap
, 5, 3);
2080 num
= 82 + bitmap_val (bitmap
, 8, 3);
2086 printf ("case %d: /* \"%s\" %s */\n", num
, MIPS16_DECODE
[loop
].name
,
2091 build_mips16_operands (bitmap
);
2095 /* build_instruction doesn't know about extend. */
2097 build_instruction (doisa
, features
, 1, &MIPS16_DECODE
[loop
]);
2100 printf (" extendval = ext;\n");
2101 printf (" have_extendval = 1;\n");
2106 printf (" break ;\n") ;
2109 printf ("default : /* Unrecognised instruction */\n") ;
2110 printf (" SignalException(ReservedInstruction,instruction);\n") ;
2111 printf (" break ;\n") ;
2114 printf("#endif /* simulator engine */\n");
2119 /* Output the code to execute an instruction, assuming the operands
2120 have already been extracted. */
2123 build_instruction (doisa
, features
, mips16
, insn
)
2125 unsigned int features
;
2127 const struct instruction
*insn
;
2129 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
2130 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
2131 char *regtype
= ((gprlen
== 64) ? "uword64" : "unsigned int");
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. */
2142 char *signed_basetype
= "unknown";
2143 char *unsigned_basetype
= "unknown";
2145 switch (GETDATASIZEINSN(insn
)) {
2147 signed_basetype
= "signed int";
2148 unsigned_basetype
= "unsigned int";
2151 signed_basetype
= "word64";
2152 unsigned_basetype
= "uword64";
2155 fprintf(stderr
,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZEINSN(insn
));
2159 if ((insn
->type
) == ADD
) {
2160 printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype
, unsigned_basetype
);
2161 printf(" %s tempS = (%s)temp;\n", signed_basetype
, signed_basetype
);
2162 if (insn
->flags
& OVERFLOW
) {
2163 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
2164 printf(" SignalException(IntegerOverflow);\n");
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
);
2172 printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype
, unsigned_basetype
);
2173 printf(" %s tempS = (%s)temp;\n", signed_basetype
, signed_basetype
);
2174 if (insn
->flags
& OVERFLOW
) { /* different signs => overflow if result_sign != arg_sign */
2175 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
2176 printf(" SignalException(IntegerOverflow);\n");
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
);
2193 char* pipe
= (insn
->flags
& PIPE1
) ? "1" : "";
2195 if (features
& FEATURE_WARN_LOHI
) {
2196 printf(" CHECKHILO(\"Multiplication\");\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)
2205 printf(" int sign = 0;\n");
2206 printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n");
2207 printf(" if (op2 < 0) { op2 = - op2; ++sign; }\n");
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
);
2226 if (insn
->flags
& UNSIGNED
)
2227 printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
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
);
2233 if (insn
->flags
& OP3
)
2235 printf(" if ( destreg != 0 )\n");
2236 printf(" GPR[destreg] = LO%s;\n",pipe
);
2243 int boolU
= (insn
->flags
& UNSIGNED
);
2244 int pipe1
= (insn
->flags
& PIPE1
);
2246 if (features
& FEATURE_WARN_LOHI
) {
2247 printf(" CHECKHILO(\"Division\");\n");
2250 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2251 printf(" LO%s = ((%sword64)op1 / (%sword64)op2);\n",
2253 (boolU
? "u" : ""),(boolU
? "u" : ""));
2254 printf(" HI%s = ((%sword64)op1 %c (%sword64)op2);\n",
2256 (boolU
? "u" : ""),'%',(boolU
? "u" : ""));
2258 printf(" LO%s = SIGNEXTEND(((%sint)op1 / (%sint)op2),32);\n",
2260 (boolU
? "unsigned " : ""),(boolU
? "unsigned " : ""));
2261 printf(" HI%s = SIGNEXTEND(((%sint)op1 %c (%sint)op2),32);\n",
2263 (boolU
? "unsigned " : ""),'%',(boolU
? "unsigned " : ""));
2271 int datalen
= GETDATASIZEINSN(insn
);
2272 int bits
= ((datalen
== WORD
) ? 32 : 64);
2273 char *ltype
= ((datalen
== WORD
) ? "unsigned int" : "uword64");
2275 /* Check that the specified SHIFT is valid: */
2276 if ((datalen
== BYTE
) || (datalen
== HALFWORD
)) {
2277 fprintf(stderr
,"Shift \"%s\" specified with BYTE or HALFWORD\n",insn
->name
);
2280 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
2281 fprintf(stderr
,"Shift \"%s\" specified with both LEFT and RIGHT\n",insn
->name
);
2284 if (!(insn
->flags
& LEFT
) && !(insn
->flags
& RIGHT
)) {
2285 fprintf(stderr
,"Shift \"%s\" specified with neither LEFT or RIGHT\n",insn
->name
);
2288 if ((insn
->flags
& LOGICAL
) && (insn
->flags
& ARITHMETIC
)) {
2289 fprintf(stderr
,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",insn
->name
);
2292 if (!(insn
->flags
& LOGICAL
) && !(insn
->flags
& ARITHMETIC
)) {
2293 fprintf(stderr
,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",insn
->name
);
2296 if ((insn
->flags
& LEFT
) && (insn
->flags
& ARITHMETIC
)) {
2297 fprintf(stderr
,"Arithmetic LEFT shift \"%s\" specified\n",insn
->name
);
2301 /* Work around an MSC code generation bug by precomputing a value
2302 * with the sign bit set. */
2303 if (insn
->flags
& ARITHMETIC
)
2304 printf(" %s highbit = (%s)1 << %d;\n", ltype
, ltype
, bits
- 1);
2306 /* If register specified shift, then extract the relevant shift amount: */
2307 if (insn
->flags
& REG
)
2308 printf(" op1 &= 0x%02X;\n",(bits
- 1));
2310 /* If HI32 specified, then shift range is 32..63 */
2311 if (insn
->flags
& HI32
)
2312 printf(" op1 |= (1 << 5);\n");
2314 /* We do not need to perform pre-masking with 0xFFFFFFFF when
2315 dealing with 32bit shift lefts, since the sign-extension
2316 code will replace any remaining hi-bits: */
2317 if (insn
->flags
& LEFT
)
2318 printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
2320 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits
== 32) ? " & 0xFFFFFFFF" : ""));
2322 /* For ARITHMETIC shifts, we must duplicate the sign-bit. We
2323 don't do this if op1 is zero, since it is not needed and
2324 since that would cause an undefined shift of the number of
2325 bits in the type. */
2326 if (insn
->flags
& ARITHMETIC
)
2327 printf(" GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype
,bits
);
2329 /* Ensure WORD values are sign-extended into 64bit registers */
2330 if ((bits
== 32) && (gprlen
== 64))
2331 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits
);
2336 if (insn
->flags
& (HI
| LO
)) {
2337 char *regname
= ((insn
->flags
& LO
) ? "LO" : "HI");
2338 int pipe1
= (insn
->flags
& PIPE1
);
2339 if (insn
->flags
& LEFT
)
2340 printf(" GPR[destreg] = %s%s;\n",regname
,(pipe1
? "1" : ""));
2342 if (features
& FEATURE_WARN_LOHI
) {
2343 printf(" if (%s%sACCESS != 0)\n",regname
,(pipe1
? "1" : ""));
2344 printf(" sim_warning(\"MT (move-to) over-writing %s register value\");\n",regname
);
2346 printf(" %s%s = op1;\n",regname
,(pipe1
? "1" : ""));
2348 if (features
& FEATURE_WARN_LOHI
)
2349 printf(" %s%sACCESS = 3; /* 3rd instruction will be safe */\n",regname
,(pipe1
? "1" : ""));
2351 if (insn
->flags
& SHIFT16
)
2352 printf(" GPR[destreg] = (op2 << 16);\n");
2354 /* perform conditional move */
2355 if (!(insn
->flags
& EQ
)) {
2356 fprintf(stderr
,"Standard conditional %s does not have the equality flag\n",insn
->name
);
2359 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
2360 printf(" GPR[destreg] = op1;\n");
2365 printf(" SyncOperation(op1);\n");
2369 printf(" SignalException(SystemCall,instruction);\n");
2373 printf(" SignalException(BreakPoint,instruction);\n");
2378 int boolNOT
= (insn
->flags
& NOT
);
2379 int boolEQ
= (insn
->flags
& EQ
);
2380 int boolGT
= (insn
->flags
& GT
);
2381 int boolLT
= (insn
->flags
& LT
);
2382 int boolU
= (insn
->flags
& UNSIGNED
);
2384 if (boolGT
&& boolLT
) {
2385 fprintf(stderr
,"GT and LT specified for \"%s\"\n",insn
->name
);
2389 if (boolNOT
&& (boolGT
|| boolLT
)) {
2390 fprintf(stderr
,"NOT specified with GT or LT specified for \"%s\"\n",insn
->name
);
2394 printf(" if ((%sword64)op1 ",(boolU
? "u" : ""));
2395 printf("%c%s",(boolNOT
? '!' : (boolLT
? '<' : (boolGT
? '>' : '='))),(boolEQ
? "=" : ""));
2396 printf(" (%sword64)op2)\n",(boolU
? "u" : ""));
2397 printf(" SignalException(Trap,instruction);\n");
2403 int boolU
= (insn
->flags
& UNSIGNED
);
2405 if (!(insn
->flags
& LT
)) {
2406 fprintf(stderr
,"Set instruction without LT specified \"%s\"\n",insn
->name
);
2410 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU
? "u" : ""),(boolU
? "u" : ""));
2411 printf(" GPR[destreg] = 1;\n");
2413 printf(" GPR[destreg] = 0;\n");
2418 printf(" GPR[destreg] = (op1 & op2);\n");
2422 /* The default mips16 nop instruction does an or to register
2423 zero; catch that case, so that we don't get useless warnings
2424 from the simulator. */
2426 printf (" if (destreg != 0)\n");
2427 printf(" GPR[destreg] = %s(op1 | op2);\n",((insn
->flags
& NOT
) ? "~" : ""));
2431 printf(" GPR[destreg] = (op1 ^ op2);\n");
2435 printf(" decode_coproc(instruction);\n");
2439 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
2440 /* The virtual address is translated to a physical address using the TLB */
2441 /* The hint specifies a cache operation for that address */
2442 printf(" uword64 vaddr = (op1 + offset);\n");
2443 printf(" uword64 paddr;\n");
2444 printf(" int uncached;\n");
2445 /* NOTE: We are assuming that the AddressTranslation is a load: */
2446 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2447 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
2450 case MADD16
: /* VR4100 specific multiply-add instructions */
2451 /* Some of this code is shared with the standard multiply
2452 routines, so an effort should be made to merge where
2454 if (features
& FEATURE_WARN_LOHI
) {
2455 printf(" CHECKHILO(\"Multiply-Add\");\n");
2457 if (features
& FEATURE_WARN_RESULT
) {
2458 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
2459 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
2460 printf(" sim_warning(\"MADD16 operation with non-16bit operands\");\n");
2463 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
2464 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2465 printf(" LO = LO + temp;\n");
2467 printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
2468 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype
);
2469 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype
);
2474 case RSVD
: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
2476 printf(" if (CoProcPresent(3))\n");
2477 printf(" SignalException(CoProcessorUnusable);\n");
2480 printf(" SignalException(ReservedInstruction,instruction);\n");
2484 if (insn
->flags
& LINK
) {
2485 if (!(insn
->flags
& REG
))
2486 printf(" int destreg = 31;\n");
2487 printf(" GPR[destreg] = (PC + %d); /* NOTE: The PC is already %d ahead within the simulator */\n",
2488 mips16
? 2 : 4, mips16
? 2 : 4);
2491 if (insn
->flags
& NOT
)
2492 printf(" op1 ^= 1;\n");
2494 printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n");
2495 printf(" so we just truncate it to 32 bits here. */\n");
2496 printf(" op1 = WORD64LO(op1);\n");
2497 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
2498 printf(" DSPC = op1;\n");
2499 if (insn
->flags
& LINK
)
2500 printf(" JALDELAYSLOT();\n");
2502 printf(" DELAYSLOT();\n");
2505 case BRANCH
: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
2506 if (insn
->flags
& FP
) {
2508 printf(" if (condition_code != 0)\n");
2509 printf(" SignalException(ReservedInstruction,instruction);\n");
2510 printf(" else {\n");
2512 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
2513 printf(" int condition = (%s == boolean);\n",((doisa
< 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
2515 if ((insn
->flags
& NOT
) && !(insn
->flags
& EQ
)) {
2516 fprintf(stderr
,"NOT specified when not EQ in \"%s\"\n",insn
->name
);
2519 if ((insn
->flags
& NOT
) && (insn
->flags
& (GT
| LT
))) {
2520 fprintf(stderr
,"NOT specified with GT or LT in \"%s\"\n",insn
->name
);
2524 if (insn
->flags
& GT
)
2525 printf(" int condition = (op1 >%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
2527 if (insn
->flags
& LT
)
2528 printf(" int condition = (op1 <%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
2530 if (insn
->flags
& EQ
)
2531 printf(" int condition = (op1 %c= op2);\n",((insn
->flags
& NOT
) ? '!' : '='));
2534 if (insn
->flags
& LINK
) {
2535 if (features
& FEATURE_WARN_R31
) {
2536 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS
,OP_MASK_RS
);
2537 printf(" sim_warning(\"Branch with link using r31 as source operand\");\n");
2539 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
2543 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
2544 printf(" if (condition) {\n");
2545 printf(" DSPC = (PC + offset);\n");
2546 printf(" DELAYSLOT();\n");
2549 /* No delayed slots for mips16 branches. */
2550 printf(" if (condition)\n");
2551 printf(" PC = PC + offset;\n");
2553 if ((insn
->flags
& FP
) && (doisa
!= 1)) {
2554 printf(" else if (likely) {\n");
2555 printf(" NULLIFY();\n");
2557 } else if (insn
->flags
& LIKELY
) {
2559 printf(" NULLIFY();\n");
2561 if ((insn
->flags
& FP
) && (doisa
< 4))
2565 case PREFETCH
: /* The beginning is shared with normal load operations */
2569 int isload
= ((insn
->type
== LOAD
) || (insn
->type
== PREFETCH
));
2571 char *accesslength
= "<UNKNOWN>";
2573 switch (GETDATASIZEINSN(insn
)) {
2576 accesslength
= "AccessLength_BYTE";
2581 accesslength
= "AccessLength_HALFWORD";
2586 accesslength
= "AccessLength_WORD";
2591 accesslength
= "AccessLength_DOUBLEWORD";
2596 accesslength
= "AccessLength_QUADWORD";
2600 if (insn
->flags
& REG
)
2601 printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
2603 printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
2604 printf(" uword64 paddr;\n");
2605 printf(" int uncached;\n");
2607 /* The following check should only occur on normal (non-shifted) memory loads */
2608 if ((datalen
!= 1) && !(insn
->flags
& (LEFT
| RIGHT
))) {
2609 printf(" if ((vaddr & %d) != 0)\n",(datalen
- 1));
2610 printf(" SignalException(%s);\n",(isload
? "AddressLoad" : "AddressStore"));
2615 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload
? "isLOAD" : "isSTORE"));
2617 if (insn
->type
== PREFETCH
)
2618 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
2621 printf(" uword64 memval;\n");
2622 printf(" uword64 memval1;\n");
2624 if ((insn
->flags
& COPROC
) && ((datalen
!= 4) && (datalen
!= 8))) {
2625 fprintf(stderr
,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
2629 if (insn
->flags
& (LEFT
| RIGHT
)) {
2630 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
2631 fprintf(stderr
,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",insn
->name
);
2638 fprintf(stderr
,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn
->name
);
2641 /* fall through to... */
2644 printf(" uword64 mask = %d;\n",((datalen
== 8) ? 0x7 : 0x3));
2645 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
2646 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
2647 printf(" int byte;\n");
2648 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
2649 printf(" byte = ((vaddr & mask) ^ bigend);\n");
2650 printf(" if (%s!ByteSwapMem)\n",((insn
->flags
& LEFT
) ? "!" : ""));
2651 printf(" paddr &= ~mask;\n");
2654 if (insn
->flags
& LEFT
)
2656 printf(" LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
2660 printf(" LoadMemory(&memval,&memval1,uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen
- 1));
2664 if (insn
->flags
& LEFT
) {
2666 /* For WORD transfers work out if the value will
2667 be in the top or bottom of the DOUBLEWORD
2670 build_endian_shift(proc64
,datalen
,2,s_right
,32);
2672 if (proc64
&& (datalen
== 4)) {
2673 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2674 printf(" memval >>= 32;\n");
2678 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen
- 1),(datalen
- 1));
2679 if (proc64
&& (datalen
== 4))
2680 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2681 } else { /* store */
2682 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen
- 1));
2684 build_endian_shift(proc64
,datalen
,2,s_left
,32);
2686 /* TODO: This is duplicated in the LOAD code
2687 above - and the RIGHT LOAD and STORE code
2688 below. It should be merged if possible. */
2689 if (proc64
&& (datalen
== 4)) {
2690 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2691 printf(" memval <<= 32;\n");
2695 printf(" StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);\n");
2697 } else { /* RIGHT */
2700 build_endian_shift(proc64
,datalen
,2,s_right
,32);
2702 if (proc64
&& (datalen
== 4)) {
2703 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2704 printf(" memval >>= 32;\n");
2709 printf(" uword64 srcmask;\n");
2710 /* All of this extra code is just a bodge
2711 required because some hosts don't allow
2712 ((v) << 64). The SPARC just leaves the (v)
2713 value un-touched. */
2714 printf(" if (byte == 0)\n");
2715 printf(" srcmask = 0;\n");
2717 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen
);
2718 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n");
2720 if (proc64
&& (datalen
== 4))
2721 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2722 } else { /* store */
2723 printf(" memval = ((uword64) op2 << (byte * 8));\n");
2724 build_endian_shift(proc64
,datalen
,2,s_left
,32);
2725 printf(" StoreMemory(uncached,(%s - byte),memval,memval1,paddr,vaddr,isREAL);\n",accesslength
);
2732 fprintf(stderr
,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
2735 } else { /* normal memory transfer */
2736 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
2737 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
2739 /* TODO: The R4000 documentation states that a LWU
2740 instruction executed when in a 32bit processor mode
2741 should cause a ReservedInstruction exception. This
2742 will mean adding a run-time check into the code
2747 #if 1 /* see the comments attached to LOADDRMASK above */
2748 printf(" uword64 mask = 0x7;\n");
2750 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2752 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
2753 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
2754 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
2755 printf(" unsigned int byte;\n");
2757 /* TODO: This should really also check for 32bit world performing 32bit access */
2758 if (datalen
< 8) /* not for DOUBLEWORD or QUADWORD*/
2759 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2761 printf(" LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength
);
2763 /* The following will only make sense if the
2764 "LoadMemory" above returns a DOUBLEWORD entity */
2765 if (datalen
< 8) { /* not for DOUBLEWORD or QUADWORD*/
2777 valmask
= 0xFFFFFFFF;
2781 fprintf(stderr
,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen
,insn
->name
);
2784 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2785 /* NOTE: The R4000 user manual has the COP_LW
2786 occuring in the same cycle as the rest of the
2787 instruction, yet the MIPS IV shows the operation
2788 happening on the next cycle. To keep the simulator
2789 simple, this code follows the R4000
2790 manual. Experimentation with a silicon
2791 implementation will be needed to ascertain the
2792 correct operation. */
2793 if (insn
->flags
& COPROC
)
2794 printf(" COP_LW(%s,destreg,(unsigned int)",
2795 ((insn
->flags
& REG
)
2797 : "((instruction >> 26) & 0x3)"));
2799 printf(" GPR[destreg] = (");
2801 if (insn
->flags
& SIGNEXTEND
)
2802 printf("SIGNEXTEND(");
2803 printf("((memval >> (8 * byte)) & 0x%08X)",valmask
);
2804 if (insn
->flags
& SIGNEXTEND
)
2805 printf(",%d)",(datalen
* 8));
2808 if (insn
->flags
& COPROC
)
2809 printf(" COP_LD(%s,destreg,memval);;\n",
2810 ((insn
->flags
& REG
)
2812 : "((instruction >> 26) & 0x3)"));
2815 printf(" GPR[destreg] = memval;\n");
2817 printf(" GPR1[destreg] = memval1;\n");
2820 } else { /* store operation */
2821 if ((datalen
== 1) || (datalen
== 2)) {
2823 #if 1 /* see the comments attached to LOADDRMASK above */
2824 printf(" uword64 mask = 0x7;\n");
2826 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2828 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
2829 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
2830 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
2831 printf(" unsigned int byte;\n");
2833 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2834 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2835 printf(" memval = ((uword64) op2 << (8 * byte));\n");
2837 if (datalen
== 4) { /* SC and SW */
2838 #if 1 /* see the comments attached to LOADDRMASK above */
2839 printf(" uword64 mask = 0x7;\n");
2841 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2843 printf(" unsigned int byte;\n");
2844 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
2845 printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
2846 if (insn
->flags
& COPROC
)
2847 printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n",
2848 ((insn
->flags
& REG
)
2850 : "((instruction >> 26) & 0x3)"),
2851 ((insn
->flags
& FP
) ? "fs" : "destreg"));
2853 printf(" memval = ((uword64) op2 << (8 * byte));\n");
2854 } else if (datalen
<= 8) { /* SD and SCD */
2855 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
2856 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
2859 if (insn
->flags
& COPROC
)
2860 printf(" memval = (uword64)COP_SD(%s,%s);\n",
2861 ((insn
->flags
& REG
)
2863 : "((instruction >> 26) & 0x3)"),
2864 ((insn
->flags
& FP
) ? "fs" : "destreg"));
2866 printf(" memval = op2;\n");
2867 } else { /* wider than 8 */
2868 if (insn
->flags
& COPROC
) {
2869 fprintf(stderr
,"COPROC not available for 128 bit operations \"%s\"\n",insn
->name
);
2872 printf(" memval = rt_reg;\n");
2873 printf(" memval1 = rt_reg1;\n");
2876 if (insn
->flags
& ATOMIC
)
2877 printf(" if (LLBIT)\n");
2880 printf(" StoreMemory(uncached,%s,memval,memval1,paddr,vaddr,isREAL);\n",accesslength
);
2884 if (insn
->flags
& ATOMIC
) {
2885 if ((datalen
!= 4) && (datalen
!= 8)) {
2886 fprintf(stderr
,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",insn
->name
);
2890 printf(" LLBIT = 1;\n");
2892 /* The documentation states that:
2894 SC *WILL* fail if coherent store into the same
2895 block occurs, or if an exception occurs between
2896 the LL and SC instructions.
2898 SC *MAY* fail if a load, store or prefetch is
2899 executed on the processor (VR4300 doesn't seem
2900 to), or if the instructions between the LL and
2901 SC are not in a 2048byte contiguous VM range.
2903 SC *MUST* have been preceded by an LL
2904 (i.e. LLBIT will be set), and it must use the
2905 same Vaddr, Paddr and cache-coherence algorithm
2906 as the LL (which means we should store this
2907 information from the load-conditional).
2909 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT
,OP_MASK_RT
);
2920 /* This code could be merged with the PREFIX generation above: */
2921 printf(" uword64 vaddr = ((uword64)op1 + (uword64)op2);\n");
2922 printf(" uword64 paddr;\n");
2923 printf(" int uncached;\n");
2924 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2925 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
2929 if (insn
->flags
& CONTROL
) {
2930 /* The following "magic" of interpreting the FP
2931 control-register number would not be needed if we were not
2932 trying to match our internal register numbers with those
2934 printf(" if (to) {\n");
2936 printf(" if (fs == 0) {\n");
2937 printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
2938 printf(" } else if (fs == 31) {\n");
2939 printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
2940 printf(" } /* else NOP */\n");
2941 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
2943 printf(" if (fs == 0) {\n");
2944 printf(" FCR0 = WORD64LO(GPR[ft]);\n");
2945 printf(" } else if (fs == 31) {\n");
2946 printf(" FCR31 = WORD64LO(GPR[ft]);\n");
2947 printf(" } /* else NOP */\n");
2948 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
2950 printf(" } else { /* control from */\n");
2952 printf(" if (fs == 0) {\n");
2953 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
2954 printf(" } else if (fs == 31) {\n");
2955 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
2956 printf(" } /* else NOP */\n");
2958 printf(" if (fs == 0) {\n");
2959 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
2960 printf(" } else if (fs == 31) {\n");
2961 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
2962 printf(" } /* else NOP */\n");
2966 printf(" if (to) {\n");
2967 if (GETDATASIZEINSN(insn
) == WORD
) {
2969 printf(" if (SizeFGR() == 64) {\n");
2970 printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
2971 printf(" } else { \n");
2972 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
2975 printf(" if (SizeFGR() == 64)\n");
2976 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
2978 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
2979 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
2981 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2983 printf(" if (SizeFGR() == 64) {\n");
2984 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
2985 printf(" } else\n");
2986 printf(" if ((fs & 0x1) == 0)\n");
2988 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
2989 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
2991 if (features
& FEATURE_WARN_RESULT
) {
2993 printf(" UndefinedResult();\n");
2996 printf(" if (SizeFGR() == 64) {\n");
2997 printf(" FGR[fs] = GPR[ft];\n");
2998 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
2999 printf(" } else\n");
3000 printf(" if ((fs & 0x1) == 0)\n");
3002 printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
3003 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3004 printf(" fpr_state[fs + 1] = fmt_uninterpreted;\n");
3005 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3007 if (features
& FEATURE_WARN_RESULT
) {
3009 printf(" UndefinedResult();\n");
3013 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
3016 printf(" } else {\n");
3017 if (GETDATASIZEINSN(insn
) == WORD
) {
3018 if (doisa
< 4) /* write-back occurs in next cycle */
3019 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
3020 else /* in this cycle */
3021 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
3022 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
3024 printf(" if (SizeFGR() == 64) {\n");
3025 printf(" PENDING_FILL(ft,FGR[fs]);\n");
3026 printf(" } else\n");
3027 printf(" if ((fs & 0x1) == 0) {\n");
3028 printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
3029 printf(" } else {\n");
3030 printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3031 if (features
& FEATURE_WARN_RESULT
)
3032 printf(" UndefinedResult();\n");
3035 printf(" if (SizeFGR() == 64)\n");
3036 printf(" GPR[ft] = FGR[fs];\n");
3038 printf(" if ((fs & 0x1) == 0)\n");
3039 printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
3040 printf(" else {\n");
3041 printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3042 if (features
& FEATURE_WARN_RESULT
)
3043 printf(" UndefinedResult();\n");
3047 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
3055 if (insn
->flags
& CONDITIONAL
) {
3056 if (insn
->flags
& INTEGER
) { /* moving GPR - testing FGR */
3057 printf(" if (GETFCC(condition_code) == boolean)\n");
3058 printf(" GPR[destreg] = op1;\n");
3060 if (insn
->flags
& EQ
) /* moving FGR - testing GPR */
3061 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
3063 printf(" if (GETFCC(condition_code) == boolean)\n");
3064 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3066 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
3068 } else { /* simple MOVE */
3069 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3074 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3075 printf(" SignalException(ReservedInstruction,instruction);\n");
3077 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
3081 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3082 printf(" SignalException(ReservedInstruction,instruction);\n");
3084 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
3088 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3089 printf(" SignalException(ReservedInstruction,instruction);\n");
3091 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3095 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3096 printf(" SignalException(ReservedInstruction,instruction);\n");
3098 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3102 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3103 printf(" SignalException(ReservedInstruction,instruction);\n");
3105 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
3109 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3110 printf(" SignalException(ReservedInstruction,instruction);\n");
3112 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((insn
->flags
& RECIP
) ? "Recip" : ""));
3123 switch (insn
->type
) {
3125 op
= "FP_RM_TOPINF";
3128 op
= "FP_RM_TOMINF";
3131 op
= "FP_RM_TOZERO";
3134 op
= "FP_RM_NEAREST";
3137 fprintf(stderr
,"Error: Handled missing for FP reason code %d\n",insn
->type
);
3141 switch (GETDATASIZEINSN(insn
)) {
3149 fprintf(stderr
,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op
);
3152 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3153 printf(" SignalException(ReservedInstruction,instruction);\n");
3155 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type
,op
,type
);
3162 switch (GETDATASIZEINSN(insn
)) {
3164 type
= "fmt_single";
3167 type
= "fmt_double";
3176 fprintf(stderr
,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn
));
3180 /* Not all combinations of conversion are valid at the
3181 moment: When converting to a fixed-point format, only
3182 floating-point sources are allowed. */
3183 printf(" if ((format == %s) | %s)\n",type
,((insn
->flags
& FIXED
) ? "((format == fmt_long) || (format == fmt_word))": "0"));
3184 printf(" SignalException(ReservedInstruction,instruction);\n");
3186 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type
,type
);
3191 if (insn
->flags
& MULTIPLY
) {
3193 switch (GETDATASIZEINSN(insn
)) {
3195 type
= "fmt_single";
3198 type
= "fmt_double";
3201 fprintf(stderr
,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn
));
3204 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
);
3206 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3207 printf(" SignalException(ReservedInstruction,instruction);\n");
3209 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3214 if (insn
->flags
& MULTIPLY
) {
3216 switch (GETDATASIZEINSN(insn
)) {
3218 type
= "fmt_single";
3221 type
= "fmt_double";
3224 fprintf(stderr
,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn
));
3227 if (insn
->flags
& NOT
)
3228 printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
3229 type
, type
, type
, type
, type
, type
, type
);
3231 printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
3232 type
, type
, type
, type
, type
, type
);
3234 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3235 printf(" SignalException(ReservedInstruction,instruction);\n");
3237 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3242 /* For the MIPS I,II or III there *MUST* be at least one
3243 instruction between the compare that sets a condition code
3244 and the branch that tests it. NOTE: However the hardware
3245 does not detect this condition. */
3246 /* Explicitly limit the operation to S and D formats: */
3247 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3248 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3249 printf(" else {\n");
3251 printf(" if (condition_code != 0)\n");
3252 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3256 printf(" int ignore = 0;\n");
3257 printf(" int less = 0;\n");
3258 printf(" int equal = 0;\n");
3259 printf(" int unordered = 1;\n");
3260 printf(" uword64 ofs = ValueFPR(fs,format);\n");
3261 printf(" uword64 oft = ValueFPR(ft,format);\n");
3262 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
3263 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
3264 printf(" FCSR |= FP_CAUSE(IO);\n");
3265 printf(" SignalException(FPE);\n");
3266 printf(" ignore = 1;\n");
3268 printf(" } else {\n");
3269 printf(" less = Less(ofs,oft,format);\n");
3270 printf(" equal = Equal(ofs,oft,format);\n");
3271 printf(" unordered = 0;\n");
3273 printf(" if (!ignore) {\n");
3274 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
3275 printf(" SETFCC(condition_code,condition);\n");
3281 /* start-sanitize-r5900 */
3284 char* pipeline
= (insn
->flags
& PIPE1
) ? "1" : "";
3285 int notsigned
= (insn
->flags
& UNSIGNED
);
3286 char* prodtype
= notsigned
? "uword64" : "word64";
3288 printf("%s prod = (%s)WORD64(WORD64LO(HI%s),WORD64LO(LO%s)) + ((%s)%s(op1%s) * (%s)%s(op2%s));\n",
3289 prodtype
, prodtype
, pipeline
, pipeline
,
3290 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32"),
3291 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32")
3293 printf("GPR[destreg] = LO%s = SIGNEXTEND(prod,32);\n", pipeline
);
3294 printf("HI%s = SIGNEXTEND( WORD64HI(prod), 32);\n", pipeline
);
3300 if (insn
->flags
& TO
)
3301 printf("SA = op1;\n");
3303 printf("GPR[destreg] = SA;\n");
3308 printf("SA = ((op1 & 0xF) ^ (op2 & 0xF)) * 8;\n");
3312 printf("SA = ((op1 & 0x7) ^ (op2 & 0x7)) * 16;\n");
3316 printf("int bytes = (SA / 8) %% 16;\n"); /* mod 16 to avoid garbage */
3317 printf("if (SA %% 8)\n");
3318 printf(" SignalException(ReservedInstruction,instruction);\n");
3321 printf(" int i;\n");
3322 printf(" for(i=0;i<(16-bytes);i++)\n");
3323 printf(" GPR_SB(destreg,i) = RT_SB(bytes+i);\n");
3324 printf(" for(;i<16;i++)\n");
3325 printf(" GPR_SB(destreg,i) = RS_SB(i-(16-bytes));\n");
3331 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3332 char* name
= name_for_data_len( insn
);
3333 char* letter
= letter_for_data_len( insn
);
3340 if ( insn
->flags
& UNSIGNED
)
3342 tmptype
= type_for_data_len( insn
);
3343 signedness
= "unsigned";
3344 maximum
= umax_for_data_len( insn
);
3347 else if ( insn
->flags
& SATURATE
)
3349 tmptype
= type_for_data_len( insn
);
3356 tmptype
= type_for_data_len( insn
);
3358 maximum
= max_for_data_len( insn
);
3359 minimum
= min_for_data_len( insn
);
3363 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3365 printf(" %s %s r = RS_S%s(i) %s RT_S%s(i);\n", signedness
, tmptype
, letter
, op
, letter
);
3368 printf(" if (r > %s) GPR_S%s(destreg,i) = %s;\n", maximum
, letter
, maximum
);
3370 printf(" else if (r < %s) GPR_S%s(destreg,i) = %s;\n", minimum
, letter
, minimum
);
3373 printf("GPR_S%s(destreg,i) = r;\n", letter
);
3381 if ( insn
->flags
& SUBTRACT
)
3383 else if ( insn
->flags
& ADDITION
)
3388 printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op
);
3389 printf(" LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op
);
3390 printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op
);
3391 printf(" HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op
);
3392 printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op
);
3393 printf(" LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op
);
3394 printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op
);
3395 printf(" HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op
);
3402 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3403 char* prodtype
= (insn
->flags
& UNSIGNED
) ? "uword64" : "word64";
3404 char* constructor
= (insn
->flags
& UNSIGNED
) ? "UWORD64" : "WORD64";
3406 printf("%s prod0;\n", prodtype
);
3407 printf("%s prod1;\n", prodtype
);
3409 if ( insn
->flags
& SUBTRACT
)
3412 printf("prod0 = %s( HI_SW(0), LO_SW(0) );\n", constructor
);
3413 printf("prod1 = %s( HI_SW(2), LO_SW(2) );\n", constructor
);
3415 else if ( insn
->flags
& ADDITION
)
3418 printf("prod0 = %s( HI_SW(0), LO_SW(0) );\n", constructor
);
3419 printf("prod1 = %s( HI_SW(2), LO_SW(2) );\n", constructor
);
3424 printf("prod0 %s= (%s)RS_SW(0) * (%s)RT_SW(0);\n", op
, prodtype
, prodtype
);
3425 printf("prod1 %s= (%s)RS_SW(2) * (%s)RT_SW(2);\n", op
, prodtype
, prodtype
);
3427 printf("GPR_%sD(destreg,0) = prod0;\n", sign
);
3428 printf("GPR_%sD(destreg,1) = prod1;\n", sign
);
3430 printf("LO = SIGNEXTEND( prod0, 32 );\n");
3431 printf("HI = SIGNEXTEND( WORD64HI(prod0), 32 );\n");
3432 printf("LO1 = SIGNEXTEND( prod1, 32 );\n");
3433 printf("HI1 = SIGNEXTEND( WORD64HI(prod1), 32 );\n");
3439 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3441 printf("LO = RS_%sW(0) / RT_%sW(0);\n", sign
, sign
);
3442 printf("HI = RS_%sW(0) %% RT_%sW(0);\n", sign
, sign
);
3443 printf("LO1 = RS_%sW(2) / RT_%sW(2);\n", sign
, sign
);
3444 printf("HI1 = RS_%sW(2) %% RT_%sW(2);\n", sign
, sign
);
3449 printf("int devisor = RT_SH(0);\n");
3450 printf("LO_SW(0) = RS_SW(0) / devisor;\n");
3451 printf("HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n");
3452 printf("LO_SW(1) = RS_SW(1) / devisor;\n");
3453 printf("HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n");
3454 printf("LO_SW(2) = RS_SW(2) / devisor;\n");
3455 printf("HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n");
3456 printf("LO_SW(3) = RS_SW(3) / devisor;\n");
3457 printf("HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n");
3462 printf("for(i=0;i<HALFWORDS_IN_MMI_REGS/2;i++)\n");
3463 printf(" GPR_SH(destreg,i) = RS_SH(i) - RT_SH(i);\n");
3464 printf("for(;i<HALFWORDS_IN_MMI_REGS;i++)\n");
3465 printf(" GPR_SH(destreg,i) = RS_SH(i) + RT_SH(i);\n");
3470 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3471 printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op
);
3472 printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op
);
3473 printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op
);
3474 printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op
);
3480 char* name
= name_for_data_len( insn
);
3481 char* letter
= letter_for_data_len( insn
);
3482 char* bits
= bits_for_data_len( insn
);
3483 char* shift
= (insn
->flags
& RIGHT
) ? ">>" : "<<";
3484 char* sign
= (insn
->flags
& ARITHMETIC
) ? "S" : "U";
3486 printf("int shift_by = op1 & (%s-1);\n", bits
);
3488 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3489 printf(" GPR_%s%s(destreg,i) = ", sign
, letter
);
3490 if ( insn
->flags
& ARITHMETIC
)
3491 printf("SIGNEXTEND( ");
3492 printf("(RT_%s%s(i) %s shift_by)", sign
, letter
, shift
);
3493 if ( insn
->flags
& ARITHMETIC
)
3494 printf(", (%s-shift_by) )", bits
);
3500 printf("GPR_UD(destreg,0) = RT_UW(0) << (RS_UB(0) & 0x1F);\n");
3501 printf("GPR_UD(destreg,1) = RT_UW(2) << (RS_UB(8) & 0x1F);\n");
3505 printf("GPR_UD(destreg,0) = RT_UW(0) >> (RS_UB(0) & 0x1F);\n");
3506 printf("GPR_UD(destreg,1) = RT_UW(2) >> (RS_UB(8) & 0x1F);\n");
3510 printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n");
3511 printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n");
3519 if ( GET_OP_FROM_INSN(insn
) == POP_AND
)
3524 else if ( GET_OP_FROM_INSN(insn
) == POP_OR
)
3529 else if ( GET_OP_FROM_INSN(insn
) == POP_NOR
)
3534 else if ( GET_OP_FROM_INSN(insn
) == POP_XOR
)
3541 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3542 printf(" GPR_UW(destreg,i) = %s(RS_UW(i) %s RT_UW(i));\n", op2
, op1
);
3548 char* name
= name_for_data_len( insn
);
3549 char* letter
= letter_for_data_len( insn
);
3550 char* maximum
= umax_for_data_len( insn
);
3551 char* op
= (insn
->flags
& GT
) ? ">" : "==";
3554 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3556 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n",
3557 letter
, op
, letter
, letter
, maximum
);
3558 printf(" else GPR_S%s(destreg,i) = 0;\n", letter
);
3565 char* name
= name_for_data_len( insn
);
3566 char* letter
= letter_for_data_len( insn
);
3567 char* op
= (insn
->flags
& GT
) ? ">" : "<";
3570 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3572 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n",
3573 letter
, op
, letter
, letter
, letter
);
3574 printf(" else GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
3581 char* name
= name_for_data_len( insn
);
3582 char* letter
= letter_for_data_len( insn
);
3585 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3587 printf(" if (RT_S%s(i) < 0)\n", letter
);
3588 printf(" GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter
, letter
);
3590 printf(" GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
3596 printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n");
3597 printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n");
3601 printf("GPR_UD(destreg,0) = RT_UD(0);\n");
3602 printf("GPR_UD(destreg,1) = RS_UD(0);\n");
3606 printf("GPR_UD(destreg,0) = RS_UD(1);\n");
3607 printf("GPR_UD(destreg,1) = RT_UD(1);\n");
3611 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3612 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3613 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3614 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3615 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3616 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3617 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3618 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3622 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3623 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3624 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3625 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3629 printf("GPR_UH(destreg,0) = RT_UH(2);\n");
3630 printf("GPR_UH(destreg,1) = RT_UH(1);\n");
3631 printf("GPR_UH(destreg,2) = RT_UH(0);\n");
3632 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3633 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3634 printf("GPR_UH(destreg,5) = RT_UH(5);\n");
3635 printf("GPR_UH(destreg,6) = RT_UH(4);\n");
3636 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3640 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3641 printf("GPR_UW(destreg,1) = RT_UW(1);\n");
3642 printf("GPR_UW(destreg,2) = RT_UW(0);\n");
3643 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3647 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3648 printf("GPR_UB(destreg,1) = RS_UB(0);\n");
3649 printf("GPR_UB(destreg,2) = RT_UB(1);\n");
3650 printf("GPR_UB(destreg,3) = RS_UB(1);\n");
3651 printf("GPR_UB(destreg,4) = RT_UB(2);\n");
3652 printf("GPR_UB(destreg,5) = RS_UB(2);\n");
3653 printf("GPR_UB(destreg,6) = RT_UB(3);\n");
3654 printf("GPR_UB(destreg,7) = RS_UB(3);\n");
3655 printf("GPR_UB(destreg,8) = RT_UB(4);\n");
3656 printf("GPR_UB(destreg,9) = RS_UB(4);\n");
3657 printf("GPR_UB(destreg,10) = RT_UB(5);\n");
3658 printf("GPR_UB(destreg,11) = RS_UB(5);\n");
3659 printf("GPR_UB(destreg,12) = RT_UB(6);\n");
3660 printf("GPR_UB(destreg,13) = RS_UB(6);\n");
3661 printf("GPR_UB(destreg,14) = RT_UB(7);\n");
3662 printf("GPR_UB(destreg,15) = RS_UB(7);\n");
3666 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3667 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3668 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3669 printf("GPR_UH(destreg,3) = RS_UH(1);\n");
3670 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3671 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3672 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3673 printf("GPR_UH(destreg,7) = RS_UH(3);\n");
3677 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3678 printf("GPR_UW(destreg,1) = RS_UW(0);\n");
3679 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3680 printf("GPR_UW(destreg,3) = RS_UW(1);\n");
3684 printf("GPR_UB(destreg,0) = RT_UB(8);\n");
3685 printf("GPR_UB(destreg,1) = RS_UB(8);\n");
3686 printf("GPR_UB(destreg,2) = RT_UB(9);\n");
3687 printf("GPR_UB(destreg,3) = RS_UB(9);\n");
3688 printf("GPR_UB(destreg,4) = RT_UB(10);\n");
3689 printf("GPR_UB(destreg,5) = RS_UB(10);\n");
3690 printf("GPR_UB(destreg,6) = RT_UB(11);\n");
3691 printf("GPR_UB(destreg,7) = RS_UB(11);\n");
3692 printf("GPR_UB(destreg,8) = RT_UB(12);\n");
3693 printf("GPR_UB(destreg,9) = RS_UB(12);\n");
3694 printf("GPR_UB(destreg,10) = RT_UB(13);\n");
3695 printf("GPR_UB(destreg,11) = RS_UB(13);\n");
3696 printf("GPR_UB(destreg,12) = RT_UB(14);\n");
3697 printf("GPR_UB(destreg,13) = RS_UB(14);\n");
3698 printf("GPR_UB(destreg,14) = RT_UB(15);\n");
3699 printf("GPR_UB(destreg,15) = RS_UB(15);\n");
3703 printf("GPR_UH(destreg,0) = RT_UH(4);\n");
3704 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3705 printf("GPR_UH(destreg,2) = RT_UH(5);\n");
3706 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3707 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3708 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3709 printf("GPR_UH(destreg,6) = RT_UH(7);\n");
3710 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3714 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3715 printf("GPR_UW(destreg,1) = RS_UW(2);\n");
3716 printf("GPR_UW(destreg,2) = RT_UW(3);\n");
3717 printf("GPR_UW(destreg,3) = RS_UW(3);\n");
3721 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3722 printf("GPR_UB(destreg,1) = RT_UB(2);\n");
3723 printf("GPR_UB(destreg,2) = RT_UB(4);\n");
3724 printf("GPR_UB(destreg,3) = RT_UB(6);\n");
3725 printf("GPR_UB(destreg,4) = RT_UB(8);\n");
3726 printf("GPR_UB(destreg,5) = RT_UB(10);\n");
3727 printf("GPR_UB(destreg,6) = RT_UB(12);\n");
3728 printf("GPR_UB(destreg,7) = RT_UB(14);\n");
3729 printf("GPR_UB(destreg,8) = RS_UB(0);\n");
3730 printf("GPR_UB(destreg,9) = RS_UB(2);\n");
3731 printf("GPR_UB(destreg,10) = RS_UB(4);\n");
3732 printf("GPR_UB(destreg,11) = RS_UB(6);\n");
3733 printf("GPR_UB(destreg,12) = RS_UB(8);\n");
3734 printf("GPR_UB(destreg,13) = RS_UB(10);\n");
3735 printf("GPR_UB(destreg,14) = RS_UB(12);\n");
3736 printf("GPR_UB(destreg,15) = RS_UB(14);\n");
3740 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3741 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3742 printf("GPR_UH(destreg,2) = RT_UH(4);\n");
3743 printf("GPR_UH(destreg,3) = RT_UH(6);\n");
3744 printf("GPR_UH(destreg,4) = RS_UH(0);\n");
3745 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3746 printf("GPR_UH(destreg,6) = RS_UH(4);\n");
3747 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3751 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3752 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3753 printf("GPR_UW(destreg,2) = RS_UW(0);\n");
3754 printf("GPR_UW(destreg,3) = RS_UW(2);\n");
3758 printf("GPR_UH(destreg,0) = RT_UH(3);\n");
3759 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3760 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3761 printf("GPR_UH(destreg,3) = RT_UH(0);\n");
3762 printf("GPR_UH(destreg,4) = RT_UH(7);\n");
3763 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3764 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3765 printf("GPR_UH(destreg,7) = RT_UH(4);\n");
3769 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3770 printf("GPR_UW(destreg,1) = RT_UW(3);\n");
3771 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3772 printf("GPR_UW(destreg,3) = RT_UW(2);\n");
3776 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3777 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3778 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3779 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3780 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3781 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3782 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3783 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3787 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3788 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3789 printf("GPR_UH(destreg,2) = RT_UH(2);\n");
3790 printf("GPR_UH(destreg,3) = RS_UH(2);\n");
3791 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3792 printf("GPR_UH(destreg,5) = RS_UH(4);\n");
3793 printf("GPR_UH(destreg,6) = RT_UH(6);\n");
3794 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3797 case PMXX
: /* Parallel move HI or LO / TO or FROM */
3799 if ( (insn
->flags
& (HI
|FROM
)) == (HI
|FROM
) )
3801 printf("GPR_SD(destreg,0) = HI;\n");
3802 printf("GPR_SD(destreg,1) = HI1;\n");
3804 else if ( (insn
->flags
& (LO
|FROM
)) == (LO
|FROM
) )
3806 printf("GPR_SD(destreg,0) = LO;\n");
3807 printf("GPR_SD(destreg,1) = LO1;\n");
3809 else if ( (insn
->flags
& (HI
|TO
)) == (HI
|TO
) )
3811 printf("HI = RS_SD(0);\n");
3812 printf("HI1 = RS_SD(1);\n");
3814 else if ( (insn
->flags
& (LO
|TO
)) == (LO
|TO
) )
3816 printf("LO = RS_SD(0);\n");
3817 printf("LO1 = RS_SD(1);\n");
3823 printf("LO_UW(0) = RS_UW(0);\n");
3824 printf("HI_UW(0) = RS_UW(1);\n");
3825 printf("LO_UW(2) = RS_UW(2);\n");
3826 printf("HI_UW(2) = RS_UW(3);\n");
3830 printf("if (op1 == 0)\n");
3832 printf(" GPR_UW(destreg,0) = LO_UW(0);\n");
3833 printf(" GPR_UW(destreg,1) = HI_UW(0);\n");
3834 printf(" GPR_UW(destreg,2) = LO_UW(2);\n");
3835 printf(" GPR_UW(destreg,3) = HI_UW(2);\n");
3837 printf("else if (op1 == 1)\n");
3839 printf(" GPR_UW(destreg,0) = LO_UW(1);\n");
3840 printf(" GPR_UW(destreg,1) = HI_UW(1);\n");
3841 printf(" GPR_UW(destreg,2) = LO_UW(3);\n");
3842 printf(" GPR_UW(destreg,3) = HI_UW(3);\n");
3844 printf("else if (op1 == 2)\n");
3846 printf(" unsigned long long t = ((uword64)HI_UW(0) << 32) | (uword64)LO_UW(0);\n");
3847 printf(" if ( t > 0x7FFFFFFF )\n");
3848 printf(" GPR_SD(destreg,0) = 0x7FFFFFFF;\n");
3849 printf(" else if ( t > (uword64)0xFFFFFFFF80000000LL )\n");
3850 printf(" GPR_SD(destreg,0) = (uword64)0xFFFFFFFF80000000LL;\n");
3852 printf(" GPR_SD(destreg,0) = SIGNEXTEND(t,32);\n");
3854 printf("else if (op1 == 3)\n");
3856 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3857 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3858 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
3859 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
3860 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
3861 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
3862 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
3863 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
3865 printf("else if (op1 == 4)\n");
3867 printf(" if (LO_UW(0) > 0x00007FFF)\n");
3868 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
3869 printf(" else if (LO_UW(0) >= 0xFFFF8000)\n");
3870 printf(" GPR_UH(destreg,0) = 0x8000;\n");
3872 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3874 printf(" if (LO_UW(1) > 0x00007FFF)\n");
3875 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
3876 printf(" else if (LO_UW(1) >= 0xFFFF8000)\n");
3877 printf(" GPR_UH(destreg,1) = 0x8000;\n");
3879 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3881 printf(" if (HI_UW(0) > 0x00007FFF)\n");
3882 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
3883 printf(" else if (HI_UW(0) >= 0xFFFF8000)\n");
3884 printf(" GPR_UH(destreg,0) = 0x8000;\n");
3886 printf(" GPR_UH(destreg,0) = HI_UH(0);\n");
3888 printf(" if (HI_UW(1) > 0x00007FFF)\n");
3889 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
3890 printf(" else if (HI_UW(1) >= 0xFFFF8000)\n");
3891 printf(" GPR_UH(destreg,1) = 0x8000;\n");
3893 printf(" GPR_UH(destreg,1) = HI_UH(2);\n");
3895 printf(" if (LO_UW(2) > 0x00007FFF)\n");
3896 printf(" GPR_UH(destreg,4) = 0x7FFF;\n");
3897 printf(" else if (LO_UW(2) >= 0xFFFF8000)\n");
3898 printf(" GPR_UH(destreg,4) = 0x8000;\n");
3900 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
3902 printf(" if (LO_UW(3) > 0x00007FFF)\n");
3903 printf(" GPR_UH(destreg,5) = 0x7FFF;\n");
3904 printf(" else if (LO_UW(3) >= 0xFFFF8000)\n");
3905 printf(" GPR_UH(destreg,5) = 0x8000;\n");
3907 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
3909 printf(" if (HI_UW(2) > 0x00007FFF)\n");
3910 printf(" GPR_UH(destreg,6) = 0x7FFF;\n");
3911 printf(" else if (HI_UW(2) >= 0xFFFF8000)\n");
3912 printf(" GPR_UH(destreg,6) = 0x8000;\n");
3914 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
3916 printf(" if (HI_UW(3) > 0x00007FFF)\n");
3917 printf(" GPR_UH(destreg,7) = 0x7FFF;\n");
3918 printf(" else if (HI_UW(3) >= 0xFFFF8000)\n");
3919 printf(" GPR_UH(destreg,7) = 0x8000;\n");
3921 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
3927 printf("unsigned long value;\n");
3928 printf("int test;\n");
3929 printf("int count;\n");
3932 printf("value = RS_UW(0);\n");
3933 printf("count = 0;\n");
3934 printf("test = !!(value & (1 << 31));\n");
3935 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
3936 printf(" count++;\n");
3937 printf("GPR_UW(destreg,0) = count;\n");
3939 printf("value = RS_UW(1);\n");
3940 printf("count = 0;\n");
3941 printf("test = !!(value & (1 << 31));\n");
3942 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
3943 printf(" count++;\n");
3944 printf("GPR_UW(destreg,1) = count;\n");
3949 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3951 printf(" int x = RT_UW(i);\n");
3952 printf(" GPR_UW(destreg,i) = ((x & (1 << 15)) << (24 - 15)) \n");
3953 printf(" | ((x & (31 << 10)) << (19 - 10)) \n");
3954 printf(" | ((x & (31 << 5)) << (11 - 5)) \n");
3955 printf(" | ((x & (31 << 0)) << (3 - 0)); \n");
3961 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3963 printf(" int x = RT_UW(i);\n");
3964 printf(" GPR_UW(destreg,i) = ((x & (1 << 24)) >> (24 - 15)) \n");
3965 printf(" | ((x & (31 << 19)) >> (19 - 10)) \n");
3966 printf(" | ((x & (31 << 11)) >> (11 - 5)) \n");
3967 printf(" | ((x & (31 << 3)) >> (3 - 0)); \n");
3970 /* end-sanitize-r5900 */
3973 fprintf(stderr
,"Warning: Unimplemented opcode: %s\n",insn
->name
) ;
3975 printf("SignalException(ReservedInstruction,instruction);\n");
3979 fprintf(stderr
,"Unrecognised opcode type %d\n",insn
->type
) ;
3984 /*---------------------------------------------------------------------------*/
3986 /* The command-line feature controls are presented in a similar style
3987 to those offered by GCC, in the aim of providing a consistent
3988 interface to the user. */
3990 T_NONE
, /* no argument - mask and value fields control "feature" definition */
3991 T_NUM
, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
3992 T_STRING
/* string argument - optionally prcededed by '=' */
4001 } machine_options
[] = {
4002 {"ips", T_NUM
, MASK_ISA
,0,"\tSelect MIPS ISA version"},
4003 {"cpu", T_STRING
,0,0,"\t\tSelect particular MIPS architecture"},
4004 {"gp64", T_NONE
, FEATURE_GP64
,FEATURE_GP64
,"\t\t\tSelect 64bit GP registers"},
4005 {"gp32", T_NONE
, FEATURE_GP64
,0,"\t\t\tSelect 32bit GP registers"},
4006 {"no-fp", T_NONE
, FEATURE_HASFPU
,0,"\t\tDisable FP simulation"},
4007 {"single-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),(FEATURE_FPSINGLE
| FEATURE_HASFPU
),"\t\tSelect single precision only FPU"},
4008 {"double-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),FEATURE_HASFPU
,"\t\tSelect double precision FPU"},
4012 /* The following architecture identies are those accepted by the "-mcpu" option: */
4013 struct architectures
{
4014 const char *name
; /* ASCII string identifier for command-line, no white-space allowed */
4015 unsigned int idflag
; /* or-ed into "isa" value */
4018 static const struct architectures available_architectures
[] = {
4019 {"4100",ARCH_VR4100
}, /* NEC MIPS VR4100 */
4020 /* start-sanitize-r5900 */
4021 {"5900",ARCH_R5900
},
4022 /* end-sanitize-r5900 */
4023 {0, 0} /* terminator */
4026 /*---------------------------------------------------------------------------*/
4034 fprintf(stderr
,"%s: Construct a MIPS simulator engine.\n",name
);
4037 The output of this program is a block of 'C' code designed to be\n\
4038 included into the main simulation control loop of a device specific\n\
4041 fprintf(stderr
,"\nOptions:\n");
4042 fprintf(stderr
," -h --help\t\tProvide this help text\n");
4043 fprintf(stderr
," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
4044 fprintf(stderr
," -w --warnings\t\tEnable all the simulator engine warnings\n");
4046 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++) {
4047 fprintf(stderr
," -m%s",machine_options
[loop
].name
);
4048 switch (machine_options
[loop
].type
) {
4050 fprintf(stderr
,"N (range 0..%d)",machine_options
[loop
].mask
);
4055 fprintf(stderr
,"=name");
4059 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",name
,machine_options
[loop
].type
);
4062 fprintf(stderr
,"%s\n",machine_options
[loop
].desc
);
4065 fprintf(stderr
,"\nAvailable \"-mcpu\" architectures: ");
4066 for (loop
= 0; (available_architectures
[loop
].name
!= 0); loop
++)
4067 fprintf(stderr
,"%s ",available_architectures
[loop
].name
);
4068 fprintf(stderr
,"\n\n");
4071 The \"trace\" and \"warnings\" options do not define the output stream.\n\
4072 They only inform the code that includes the constructed engine to provide\n\
4073 the required features.\n\n\
4074 The \"-mips0\" option forces the construction of a simulator supporting\n\
4075 the highest available MIPS ISA supported.\n");
4080 /*---------------------------------------------------------------------------*/
4088 char *progname
= argv
[0];
4089 unsigned int doarch
= DEF_ISA
;
4090 unsigned int features
= 0; /* default state */
4093 features
|= FEATURE_HASFPU
;
4095 features
|= FEATURE_PROC32
;
4097 features
|= FEATURE_FPSINGLE
;
4099 if (features
& FEATURE_PROC32
)
4100 features
&= ~FEATURE_GP64
;
4102 features
|= FEATURE_GP64
;
4105 int option_index
= 0;
4106 static struct option cmdline
[] = {
4109 {"warnings",0,0,'w'},
4113 c
= getopt_long(argc
,argv
,"hm:tw",cmdline
,&option_index
);
4115 break ; /* out of the while loop */
4118 case 'h' : /* help */
4122 case 'f' : /* fast */
4123 features
|= FEATURE_FAST
;
4126 case 'w' : /* warnings */
4127 features
|= FEATURE_WARNINGS
;
4128 /* TODO: Future extension: Allow better control over the warnings generated:
4129 disable warnings -wnone ~FEATURE_WARNINGS
4130 all possible warnings -wall FEATURE_WARNINGS
4131 pipeline stall occuring -wstall FEATURE_WARN_STALL
4132 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
4133 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
4134 bad r31 use -wr31 FEATURE_WARN_R31
4135 undefined results -wresult FEATURE_WARN_RESULT
4139 case 'm' : /* machine options */
4143 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++)
4144 if (strncmp(machine_options
[loop
].name
,optarg
,strlen(machine_options
[loop
].name
)) == 0) {
4145 char *loptarg
= (optarg
+ strlen(machine_options
[loop
].name
));
4146 switch (machine_options
[loop
].type
) {
4149 fprintf(stderr
,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname
,loptarg
,machine_options
[loop
].name
);
4152 features
&= ~(machine_options
[loop
].mask
);
4153 features
|= machine_options
[loop
].value
;
4157 if (*loptarg
&& *loptarg
== '=')
4160 if (strcmp(machine_options
[loop
].name
,"ips") == 0) {
4164 fprintf(stderr
,"%s: ISA number expected after -mips\n",progname
);
4168 num
= my_strtoul(loptarg
,&loptarg
,10);
4170 if ((num
== ULONG_MAX
) && (errno
= ERANGE
)) {
4171 fprintf(stderr
,"%s: Invalid number given to -mips option\n",progname
);
4176 fprintf(stderr
,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname
,loptarg
);
4180 if (num
> MASK_ISA
) {
4181 fprintf(stderr
,"%s: ISA number %d outside acceptable range (0..%d)\n",progname
,num
,MASK_ISA
);
4185 doarch
= ((doarch
& ~MASK_ISA
) | num
);
4186 if ((num
== 0) || (num
> 2)) {
4187 if ((features
& FEATURE_PROC32
) || !(features
& FEATURE_GP64
))
4188 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp64\n",progname
,num
);
4189 features
|= FEATURE_GP64
;
4190 features
&= ~FEATURE_PROC32
;
4192 if (!(features
& FEATURE_PROC32
) || (features
& FEATURE_GP64
))
4193 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp32\n",progname
,num
);
4194 features
&= ~FEATURE_GP64
;
4195 features
|= FEATURE_PROC32
;
4198 fprintf(stderr
,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname
,optarg
);
4204 if (*loptarg
&& *loptarg
== '=')
4207 if (strcmp(machine_options
[loop
].name
,"cpu") == 0) {
4211 fprintf(stderr
,"%s: Architecture identifier expected after -mcpu\n",progname
);
4215 for (archloop
= 0; (available_architectures
[archloop
].name
!= 0); archloop
++) {
4216 if ((*loptarg
== 'v') || (*loptarg
== 'V'))
4219 if ((*loptarg
== 'r') || (*loptarg
== 'R'))
4222 if (strcmp(available_architectures
[archloop
].name
,loptarg
) == 0) {
4223 doarch
|= available_architectures
[archloop
].idflag
;
4228 if (available_architectures
[archloop
].name
== 0) {
4229 fprintf(stderr
,"%s: Unrecognised MIPS architecture \"%s\"\n",progname
,loptarg
);
4233 fprintf(stderr
,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname
,optarg
);
4239 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",progname
,machine_options
[loop
].type
);
4245 if (machine_options
[loop
].name
== 0) {
4246 fprintf(stderr
,"%s: Unrecognised option: -m%s\n",progname
,optarg
);
4253 /* An error message should already have been displayed */
4257 fprintf(stderr
,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname
,c
);
4262 if (optind
< argc
) {
4263 fprintf(stderr
,"%s: Spurios non-option arguments ",progname
);
4264 while (optind
< argc
)
4265 fprintf(stderr
,"\"%s\" ",argv
[optind
++]);
4266 fprintf(stderr
,"\n");
4270 if ((features
& FEATURE_FAST
) && (features
& FEATURE_WARNINGS
))
4271 fprintf(stderr
,"Warning: Fast model generation selected, along with trace or warnings.\n");
4273 process_instructions(doarch
,features
) ;
4277 /*---------------------------------------------------------------------------*/
4279 /* We can't assume that the compiler for the build system has strtoul,
4280 so we provide our own copy. */
4283 * Copyright (c) 1990 Regents of the University of California.
4284 * All rights reserved.
4286 * Redistribution and use in source and binary forms, with or without
4287 * modification, are permitted provided that the following conditions
4289 * 1. Redistributions of source code must retain the above copyright
4290 * notice, this list of conditions and the following disclaimer.
4291 * 2. Redistributions in binary form must reproduce the above copyright
4292 * notice, this list of conditions and the following disclaimer in the
4293 * documentation and/or other materials provided with the distribution.
4294 * 3. All advertising materials mentioning features or use of this software
4295 * must display the following acknowledgement:
4296 * This product includes software developed by the University of
4297 * California, Berkeley and its contributors.
4298 * 4. Neither the name of the University nor the names of its contributors
4299 * may be used to endorse or promote products derived from this software
4300 * without specific prior written permission.
4302 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4303 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4304 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4305 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4306 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4307 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4308 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4309 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4310 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4311 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4316 * Convert a string to an unsigned long integer.
4318 * Ignores `locale' stuff. Assumes that the upper and lower case
4319 * alphabets and digits are each contiguous.
4321 static unsigned long
4322 my_strtoul(nptr
, endptr
, base
)
4327 register const char *s
= nptr
;
4328 register unsigned long acc
;
4330 register unsigned long cutoff
;
4331 register int neg
= 0, any
, cutlim
;
4334 * See strtol for comments as to the logic used.
4338 } while (isspace(c
));
4342 } else if (c
== '+')
4344 if ((base
== 0 || base
== 16) &&
4345 c
== '0' && (*s
== 'x' || *s
== 'X')) {
4351 base
= c
== '0' ? 8 : 10;
4352 cutoff
= (unsigned long)ULONG_MAX
/ (unsigned long)base
;
4353 cutlim
= (unsigned long)ULONG_MAX
% (unsigned long)base
;
4354 for (acc
= 0, any
= 0;; c
= *s
++) {
4357 else if (isalpha(c
))
4358 c
-= isupper(c
) ? 'A' - 10 : 'a' - 10;
4363 if (any
< 0 || acc
> cutoff
|| (acc
== cutoff
&& c
> cutlim
))
4377 *endptr
= (char *) (any
? s
- 1 : nptr
);
4381 /*---------------------------------------------------------------------------*/
4383 /*> EOF gencode.c <*/