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 */
120 /* We used to enable FEATURE_WARN_ZERO, but it is perfectly legitimate to
121 have the zero register as a destination -- the zero register just doesn't
123 /* start-sanitize-r5900 */
124 /* The 5900 madd instructions for example use this feature. */
125 /* end-sanitize-r5900 */
127 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31)
129 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
132 /* FEATURE_WARN_STALL */
133 /* If MIPS I we want to raise a warning if an attempt is made to
134 access Rn in an instruction immediately following an Rn update
135 "WARNING : Invalid value read". The simulator engine is designed
136 that the previous value is read in such cases, to allow programs
137 that make use of this feature to execute. */
138 /* If MIPS II or later, attempting to read a register before the
139 update has completed will generate a "WARNING : Processor stall"
140 message (since the processor will lock the pipeline until the value
141 becomes available). */
143 /* FEATURE_WARN_LOHI */
144 /* Warn if an attempt is made to read the HI/LO registers before the
145 update has completed, or if an attempt is made to update the
146 registers whilst an update is occurring. */
148 /* FEATURE_WARN_ZERO */
149 /* Notify the user if an attempt is made to use GPR 0 as a destination. */
151 /* FEATURE_WARN_R31 */
152 /* Notify the user if register r31 (the default procedure call return
153 address) is used unwisely. e.g. If r31 is used as the source in a
154 branch-and-link instruction, it would mean that an exception in the
155 delay slot instruction would not allow the branch to be re-started
156 (since r31 will have been overwritten by the link operation during
157 the first execution of the branch). */
159 /* FEATURE_WARN_RESULT */
160 /* Certain instructions do not raise exceptions when invalid operands
161 are given, they will just result in undefined values being
162 generated. This option controls whether the simulator flags such
165 /*---------------------------------------------------------------------------*/
172 #include "ansidecl.h"
173 #include "opcode/mips.h"
175 /* FIXME: ansidecl.h defines AND. */
179 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
182 static unsigned long my_strtoul ();
186 #define TRUE (1 == 1)
187 #define FALSE (1 == 0)
191 /*---------------------------------------------------------------------------*/
193 /* Holding the instruction table this way makes it easier to check the
194 instruction values defined, and to add instructions to the
195 system. However, it makes the process of constructing the simulator
196 a bit more complicated: */
198 /* The "bitmap" is encoded as follows (NOTE: Only lower-case
199 alphabetic characters should be used, since the letter ordinal is
200 used as a bit position): */
202 typedef struct operand_encoding
{
203 char id
; /* character identifier */
204 int fpos
; /* first bit position */
205 int flen
; /* field length in bits */
211 /* Values for the "flags" field: */
212 #define OP_NONE (0 << 0) /* To keep the source tidy */
213 #define OP_GPR (1 << 0) /* Get operand from integer register bank */
214 #define OP_SIGNX (1 << 1) /* Sign-extend the operand */
215 #define OP_SHIFT2 (1 << 2) /* Shift field left by 2 */
216 #define OP_BITS5 (1 << 3) /* Only take the lo 5-bits of the operand */
217 #define OP_GPR1 (1 << 4) /* fetch from the GPR1 registers */
219 struct operand_encoding opfields
[] = {
220 {'0',-1,-1,"", "", (OP_NONE
)}, /* special case for explicit zero */
221 {'1',-1,-1,"", "", (OP_NONE
)}, /* special case for explicit one */
222 {'?',-1,-1,"", "", (OP_NONE
)}, /* undefined (do not care at this level) */
223 /* The rest are the explicit operand fields: */
224 {'a', 6, 5,"int", "op1", (OP_NONE
)}, /* shift amount (or hint) */
225 {'b',21, 5,"int", "fr", (OP_NONE
)}, /* fr register */
226 {'c',16, 1,"int", "boolean", (OP_NONE
)}, /* TRUE or FALSE boolean */
227 {'d',11, 5,"int", "destreg", (OP_NONE
)}, /* integer destination/rd register */
228 {'e', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-3bits must be zero) */
229 {'f',17, 1,"int", "likely", (OP_NONE
)}, /* set if branch LIKELY */
230 {'g',16, 5,"t_reg", "op2", (OP_GPR
)}, /* integer source rt register */
231 {'h', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-1bit must be zero) */
232 {'i', 0,16,"t_reg", "op2", (OP_SIGNX
)}, /* signed immediate (op2) */
233 {'j', 0,26,"ut_reg","op1", (OP_SHIFT2
)},/* shifted left 2 bits and combined with hi-order bits of address in the delay slot */
234 {'k',16, 5,"int", "ft", (OP_NONE
)},
235 {'l', 0,16,"t_reg", "offset", (OP_SIGNX
| OP_SHIFT2
)}, /* signed offset shifted left 2 to make 18bit signed offset */
236 {'m',21, 3,"int", "format", (OP_NONE
)}, /* FP format field */
237 {'n',16, 5,"int", "hint", (OP_NONE
)}, /* hint */
238 {'o',21, 5,"t_reg", "op1", (OP_GPR
| OP_BITS5
)}, /* integer source/rs register (but never treated as 32bit word) */
239 {'p', 8, 3,"int", "condition_code",(OP_NONE
)}, /* FP condition code field */
240 {'q',18, 3,"int", "condition_code",(OP_NONE
)}, /* FP condition code field */
241 {'r', 6, 5,"int", "destreg", (OP_NONE
)}, /* FP fd register */
242 {'s',21, 5,"t_reg", "op1", (OP_GPR
)}, /* integer source/rs register */
243 {'t',16, 5,"int", "destreg", (OP_NONE
)}, /* integer target rt (destination) register */
244 {'u', 0, 4,"int", "cmpflags", (OP_NONE
)}, /* FP comparison control flags */
245 {'v',11, 5,"int", "fs", (OP_NONE
)}, /* FP fs register (or PREFX hint) */
246 {'w', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-2bits must be zero) */
247 {'x',23, 1,"int", "to", (OP_NONE
)}, /* TRUE if move To; FALSE if move From */
248 {'y', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset */
249 {'z', 0,16,"ut_reg","op2", (OP_NONE
)}, /* unsigned immediate (zero extended) */
250 {'S',21, 5,"t_reg", "rs_reg", (OP_GPR
|OP_GPR1
)}, /* rs field, GPR[rs] and GPR1[rs] as source */
251 {'T',16, 5,"t_reg", "rt_reg", (OP_GPR
|OP_GPR1
)}, /* rt field, GPR[rt] and GPR1[rt] as source */
255 /* Main instruction encoding types: */
262 COP1S
, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
270 /* mips16 encoding types. */
271 I
, RI
, RR
, RRI
, RRR
, RRI_A
, ISHIFT
, I8
, I8_MOVR32
, I8_MOV32R
, I64
, RI64
274 /* Main instruction families: */
276 ADD
, /* res = operand1 + operand2 */
277 SUB
, /* res = operand1 - operand2 */
278 MUL
, /* res = operand1 * operand2 */
279 DIV
, /* res = operand1 / operand2 */
280 AND
, /* res = operand1 & operand2 */
281 OR
, /* res = operand1 | operand2 */
282 XOR
, /* res = operand1 ^ operand2 */
283 MOVE
, /* res = operand1 */
284 BRANCH
, /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
285 JUMP
, /* execute delay slot instruction before jump */
286 LOAD
, /* load from memory */
287 STORE
, /* store to memory */
288 PREFETCH
, /* prefetch data into cache */
289 SET
, /* set register on result of condition code */
290 SHIFT
, /* perform a logical or arithmetic shift */
291 TRAP
, /* system exception generation */
292 BREAK
, /* system breakpoint exception generation */
293 SYSCALL
, /* system exception generation */
294 SYNC
, /* system cache control */
295 DECODE
, /* co-processor instruction */
296 CACHE
, /* co-processor 0 CACHE instruction */
297 MADD16
, /* VR4100 specific multiply-add extensions */
316 /* start-sanitize-r5900 */
362 /* end-sanitize-r5900 */
363 NYI
, /* Not Yet Implemented, placeholder, errors if used */
364 RSVD
/* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
368 #define NONE (0 << 0) /* Zero value (used to keep source tidy) */
369 #define SIM_SH_SIZE (0)
370 #define SIM_MASK_SIZE (0x7)
371 #define BYTE (0) /* 8bit */
372 #define HALFWORD (1) /* 16bit */
373 #define WORD (2) /* 32bit */
374 #define DOUBLEWORD (3) /* 64bit */
375 #define SINGLE (4) /* single precision FP */
376 #define DOUBLE (5) /* double precision FP */
377 #define QUADWORD (6) /* 128bit */
379 /* Shorthand to get the size field from the flags value: */
380 #define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
382 /* The rest are single bit flags: */
383 #define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
388 #define LIKELY (1 << 8)
389 #define SIGNEXTEND (1 << 9)
390 #define OVERFLOW (1 << 10)
391 #define LINK (1 << 11)
392 #define ATOMIC (1 << 12)
393 #define SHIFT16 (1 << 13)
394 #define REG (1 << 14)
395 #define LEFT (1 << 15) /* Deliberate explicit encodings to allow check for neither, or both */
396 #define RIGHT (1 << 16) /* Mutually exclusive with "LEFT" */
397 #define LOGICAL (1 << 17)
398 #define ARITHMETIC (1 << 18)
399 #define UNSIGNED (1 << 19)
400 #define HI32 (1 << 20)
401 #define HI (1 << 21) /* accesses or updates the HI register */
402 #define LO (1 << 22) /* accesses or updates the LO register */
403 #define WORD32 (1 << 23)
404 #define FP (1 << 24) /* Floating Point operation */
405 #define FIXED (1 << 25) /* fixed point arithmetic */
406 #define COPROC (1 << 26)
407 #define INTEGER (1 << 27)
408 #define CONDITIONAL (1 << 28)
409 #define RECIP (1 << 29)
410 #define CONTROL (1 << 30)
411 #define NOARG (1 << 31) /* Instruction has no (defined) operands */
412 /* NOTE: We can overload the use of certain of these flags, since not
413 all options are applicable to all instruction types. This will free
414 up more space for new flags. */
416 /* Overloadings of above bits */
417 #define PIPE1 LIKELY /* Using pipeline 1 (DIV,MUL) */
418 #define OP3 EQ /* 3 operand version of operation (MUL) */
420 #define SATURATE OVERFLOW /* for PADD, saturate for overflow */
422 #define SUBTRACT LEFT /* for PMULT, PMULT becomes PMSUB */
423 #define ADDITION RIGHT /* for PMULT, PMULT becomes PMADD */
425 #define FROM LEFT /* move from special register */
426 #define TO RIGHT /* move to special register */
428 /* For bitwise parallel operations */
429 #define POP_AND 0 /* for POP, op = & */
430 #define POP_OR LEFT /* for POP, op = | */
431 #define POP_NOR LIKELY /* for POP, op = ~(x | y) */
432 #define POP_XOR LEFT|LIKELY /* for POP, op = ^ */
434 #define GET_OP_FROM_INSN(insn) (((insn)->flags)&(LEFT|LIKELY))
438 typedef struct instruction
{
439 char *name
; /* ASCII mnemonic name */
440 unsigned int isa
; /* MIPS ISA number where instruction introduced */
441 char *bitmap
; /* 32character string describing instruction operands */
442 inst_type mark
; /* type of MIPS instruction encoding */
443 opcode_type type
; /* main instruction family */
444 unsigned int flags
; /* flags describing instruction features */
446 /* The number of pipeline cycles taken by an instruction varies
447 between MIPS processors. This means that the information must be
448 encoded elsewhere, in a CPU specific structure. */
450 /* NOTE: Undefined instructions cause "Reserved Instruction"
451 exceptions. i.e. if there is no bit-mapping defined then the
452 instruction is deemed to be undefined. */
454 /* NOTE: The "isa" field is also used to encode flags for particular
455 chip architecture extensions. e.g. the NEC VR4100 specific
456 instructions. Normally chip extensions are added via the COP0
457 space. However, the VR4100 (and possibly other devices) also use
458 the normal instruction space. */
459 #define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */
460 /* The other bits are allocated downwards, to avoid renumbering if we
461 have to extend the bits allocated to the pure ISA number.
463 These architecture bits come in two flavors:
464 ISA dependent - marking insns that should be included in the opcode
465 set if that architecture is requested on the gencode command line
466 AND the ISA of the insn is <= requested ISA;
468 ISA independent - marking insn that should be included in the opcode
469 set if that architecture is requested
470 OR the ISA of the insn is <= requested ISA.
472 Independent bits are listed in MASK_ISA_INDEP, the rest are dependent.
474 #define ARCH_VR4100 ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
475 /* start-sanitize-r5900 */
476 #define ARCH_R5900 ((unsigned)1 << 30) /* Toshiba r5900 extension instructions */
477 /* end-sanitize-r5900 */
478 #define ARCH_R3900 ((unsigned)1 << 29) /* Toshiba r3900 (tx39) */
479 /* start-sanitize-tx19 */
480 /* The r1900 (tx19) is a tx39 with a mips16 decoder. For the purposes
481 of implementing the simulator we treat them as the same. */
482 /* end-sanitize-tx19 */
484 /* A list (or'ed) of extension insn sets that can be requested independant of the ISA# */
485 #define MASK_ISA_INDEP (0 \
487 /* start-sanitize-r5900 */ \
489 /* end-sanitize-r5900 */ \
492 #define MASK_ISA_DEP ~(MASK_ISA_INDEP | MASK_ISA)
494 /* Very short names for use in the table below to keep it neet. */
495 #define G1 (3 | ARCH_VR4100)
498 /* start-sanitize-r5900 */ \
500 /* end-sanitize-r5900 */ \
504 /* start-sanitize-r5900 */ \
505 /* insn that are not really 5900 insn but were left in */ \
506 /* until we can rewrite the code-gen and libs */ \
508 /* end-sanitize-r5900 */ \
511 #define G4 (2 | ARCH_R3900)
515 /* start-sanitize-r5900 */ \
517 /* end-sanitize-r5900 */ \
520 #define G6 (3 | ARCH_R3900)
522 #define T3 ARCH_R3900
523 /* start-sanitize-r5900 */
524 #define T5 ARCH_R5900
525 /* end-sanitize-r5900 */
528 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
529 COP0 space. This means that an external decoder should be added
530 when constructing a full VR4100 simulator. However some arithmetic
531 instructions are encoded in the normal instruction space. */
533 struct instruction MIPS_DECODE
[] = {
534 /* The instructions are alphabetical, and not in instruction bit-order: */
535 {"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1
, FPABS
, (FP
)},
536 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL
,ADD
, (WORD
| WORD32
| OVERFLOW
)}, /* rd = rs + rt */
537 {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1
, FPADD
, (FP
)},
538 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
| OVERFLOW
)},
539 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL
,ADD
, (WORD
| WORD32
)}, /* rd = rs + rt */
540 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
)},
541 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL
,AND
, (NONE
)}, /* rd = rs AND rt */
542 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, AND
, (NONE
)},
543 {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S
, BRANCH
, (FP
)},
544 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
)},
545 {"BEQL", G4
,"010100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
| LIKELY
)},
546 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
)},
547 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
548 {"BGEZALL",G4
,"000001sssss10011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
549 {"BGEZL", G4
,"000001sssss00011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LIKELY
)},
550 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
)},
551 {"BGTZL", G4
,"010111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
| LIKELY
)},
552 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
)},
553 {"BLEZL", G4
,"010110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
| LIKELY
)},
554 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM
, BRANCH
, (LT
)},
555 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
)},
556 {"BLTZALL",G4
,"000001sssss10010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
| LIKELY
)},
557 {"BLTZL", G4
,"000001sssss00010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LIKELY
)},
558 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
)},
559 {"BNEL", G4
,"010101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
| LIKELY
)},
560 {"BREAK", 1,"000000????????????????????001101",SPECIAL
,BREAK
, (NOARG
)},
561 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1
, FPCEIL
, (FP
| FIXED
| DOUBLEWORD
)},
562 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1
, FPCEIL
, (FP
| FIXED
| WORD
)},
563 {"COP0", 1,"010000??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
564 {"COP2", 1,"010010??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
565 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1
, FPCONVERT
,(FP
| DOUBLE
)},
566 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1
, FPCONVERT
,(FP
| FIXED
| DOUBLEWORD
)},
567 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1
, FPCONVERT
,(FP
| SINGLE
)},
568 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1
, FPCONVERT
,(FP
| FIXED
| WORD
)},
569 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1
, FPCOMPARE
,(FP
)},
570 {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
| CONTROL
)},
571 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL
,ADD
, (DOUBLEWORD
| OVERFLOW
)},
572 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| OVERFLOW
)},
573 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL
,ADD
, (DOUBLEWORD
| UNSIGNED
)},
574 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| UNSIGNED
)},
575 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL
,DIV
, (DOUBLEWORD
| HI
| LO
)},
576 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL
,DIV
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
577 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
)},
578 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1
, FPDIV
, (FP
| WORD
| HI
| LO
)},
579 /* start-sanitize-r5900 */
580 {"DIV1", T5
,"011100sssssggggg0000000000011010",MMINORM
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
| PIPE1
)},
581 /* end-sanitize-r5900 */
582 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
)},
583 /* start-sanitize-r5900 */
584 {"DIVU1", T5
,"011100sssssggggg0000000000011011",MMINORM
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
| PIPE1
)},
585 /* end-sanitize-r5900 */
586 {"DMADD16",G1
,"000000sssssggggg0000000000101001",SPECIAL
,MADD16
, (DOUBLEWORD
| HI
| LO
)},
587 {"DMULT", 3,"000000sssssggggg0000000000011100",SPECIAL
,MUL
, (DOUBLEWORD
| HI
| LO
)},
588 {"DMULTU", 3,"000000sssssggggg0000000000011101",SPECIAL
,MUL
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
589 {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| DOUBLEWORD
)},
590 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
)},
591 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| REG
)},
592 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| HI32
)}, /* rd = rt << (sa + 32) */
593 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
)},
594 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| REG
)},
595 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| HI32
)}, /* rd = rt >> (sa + 32) */
596 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
)},
597 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| REG
)},
598 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| HI32
)},
599 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL
,SUB
, (DOUBLEWORD
)},
600 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL
,SUB
, (DOUBLEWORD
| UNSIGNED
)},
601 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1
, FPFLOOR
, (FP
| FIXED
| DOUBLEWORD
)},
602 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1
, FPFLOOR
, (FP
| FIXED
| WORD
)},
603 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (NONE
)}, /* NOTE: boundary case due to delay slot address being used */
604 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
)}, /* NOTE: boundary case due to delay slot address being used */
605 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL
,JUMP
, (LINK
| REG
)},
606 {"JALX", 1,"011101jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
| NOT
)},
607 {"JR", 1,"000000sssss000000000000000001000",SPECIAL
,JUMP
, (NONE
)}, /* need to check PC as part of instruction fetch */
608 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
| SIGNEXTEND
)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
609 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
)}, /* NOTE: See "LB" comment */
610 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
)},
611 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
612 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
613 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| LEFT
)}, /* NOTE: See "LB" comment */
614 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| RIGHT
)}, /* NOTE: See "LB" comment */
615 {"LDXC1", G3
,"010011sssssggggg00000rrrrr000001",COP1X
, LOAD
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
616 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
| SIGNEXTEND
)},
617 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
)},
618 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| ATOMIC
| SIGNEXTEND
)},
619 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| ATOMIC
)},
620 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL
, MOVE
, (SHIFT16
)}, /* Cheat and specify sign-extension of immediate field */
621 /* start-sanitize-r5900 */
622 {"LQ", T5
,"011110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (QUADWORD
)},
623 /* end-sanitize-r5900 */
624 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| SIGNEXTEND
)},
625 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
626 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
627 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| LEFT
)},
628 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| RIGHT
)},
629 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
)},
630 {"LWXC1", G3
,"010011sssssggggg00000rrrrr000000",COP1X
, LOAD
, (FP
| WORD
| COPROC
| REG
)},
631 {"MADD", G5
,"011100sssssgggggddddd00000000000",MMINORM
,MADD
, (NONE
)},
632 {"MADDU", G5
,"011100sssssgggggddddd00000000001",MMINORM
,MADD
, (UNSIGNED
)},
633 /* start-sanitize-r5900 */
634 {"MADD1", T5
,"011100sssssgggggddddd00000100000",MMINORM
,MADD
, (PIPE1
)},
635 {"MADDU1", T5
,"011100sssssgggggddddd00000100001",MMINORM
,MADD
, (UNSIGNED
| PIPE1
)},
636 /* end-sanitize-r5900 */
637 {"MADD16", G1
,"000000sssssggggg0000000000101000",SPECIAL
,MADD16
, (WORD
| HI
| LO
)},
638 {"MADD.D", G3
,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X
, FPADD
, (FP
| MULTIPLY
| DOUBLE
)},
639 {"MADD.S", G3
,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X
, FPADD
, (FP
| MULTIPLY
| SINGLE
)},
640 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL
,MOVE
, (HI
| LEFT
)}, /* with following, from and to denoted by usage of LEFT or RIGHT */
641 /* start-sanitize-r5900 */
642 {"MFHI1", T5
,"0111000000000000ddddd00000010000",MMINORM
,MOVE
, (HI
| LEFT
| PIPE1
)},
643 /* end-sanitize-r5900 */
644 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL
,MOVE
, (LO
| LEFT
)},
645 /* start-sanitize-r5900 */
646 {"MFLO1", T5
,"0111000000000000ddddd00000010010",MMINORM
,MOVE
, (LO
| LEFT
| PIPE1
)},
647 {"MFSA", T5
,"0000000000000000ddddd00000101000",SPECIAL
,MxSA
, (FROM
)},
648 /* end-sanitize-r5900 */
649 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL
,MOVE
, (HI
| RIGHT
)},
650 /* start-sanitize-r5900 */
651 {"MTHI1", T5
,"011100sssss000000000000000010001",MMINORM
,MOVE
, (HI
| RIGHT
| PIPE1
)},
652 /* end-sanitize-r5900 */
653 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL
,MOVE
, (LO
| RIGHT
)},
654 /* start-sanitize-r5900 */
655 {"MTLO1", T5
,"011100sssss000000000000000010011",MMINORM
,MOVE
, (LO
| RIGHT
| PIPE1
)},
656 {"MTSA", T5
,"000000sssss000000000000000101001",SPECIAL
,MxSA
, (TO
)},
657 {"MTSAB", T5
,"000001sssss11000iiiiiiiiiiiiiiii",REGIMM
, MTSAB
, (NONE
)},
658 {"MTSAH", T5
,"000001sssss11001iiiiiiiiiiiiiiii",REGIMM
, MTSAH
, (NONE
)},
659 /* end-sanitize-r5900 */
660 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1
, FPMOVE
, (FP
)},
661 {"MOVN", G2
,"000000sssssgggggddddd00000001011",SPECIAL
,MOVE
, (NOT
| EQ
)},
662 {"MOVN", G2
,"01000110mmmgggggvvvvvrrrrr010011",COP1
, FPMOVE
, (FP
| NOT
| EQ
)},
663 {"MOV%c", G3
,"000000sssssqqq0cddddd00000000001",SPECIAL
,FPMOVE
, (FP
| CONDITIONAL
| INTEGER
)},
664 {"MOV%c", G3
,"01000110mmmqqq0cvvvvvrrrrr010001",COP1
, FPMOVE
, (FP
| CONDITIONAL
)},
665 {"MOVZ", G2
,"000000sssssgggggddddd00000001010",SPECIAL
,MOVE
, (EQ
)},
666 {"MOVZ", G2
,"01000110mmmgggggvvvvvrrrrr010010",COP1
, FPMOVE
, (FP
| EQ
)},
667 {"MSUB.D", G3
,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X
, FPSUB
, (FP
| MULTIPLY
| DOUBLE
)},
668 {"MSUB.S", G3
,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X
, FPSUB
, (FP
| MULTIPLY
| SINGLE
)},
669 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1
, FPMUL
, (FP
| HI
| LO
)},
670 {"MULT", 1,"000000sssssgggggddddd00000011000",SPECIAL
,MUL
, (OP3
| WORD
| WORD32
| HI
| LO
)},
671 /* start-sanitize-r5900 */
672 {"MULT1", T5
,"011100sssssgggggddddd00000011000",MMINORM
,MUL
, (OP3
| WORD
| WORD32
| HI
| LO
| PIPE1
)},
673 /* end-sanitize-r5900 */
674 {"MULTU", 1,"000000sssssgggggddddd00000011001",SPECIAL
,MUL
, (OP3
| WORD
| WORD32
| UNSIGNED
| HI
| LO
)},
675 /* start-sanitize-r5900 */
676 {"MULTU1", T5
,"011100sssssgggggddddd00000011001",MMINORM
,MUL
, (OP3
| WORD
| WORD32
| UNSIGNED
| HI
| LO
| PIPE1
)},
677 /* end-sanitize-r5900 */
678 {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
)},
679 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1
, FPNEG
, (FP
)},
680 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
681 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
682 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
683 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
684 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL
,OR
, (NOT
)},
685 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL
,OR
, (NONE
)},
686 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, OR
, (NONE
)},
688 /* start-sanitize-r5900 */
689 {"PABSH", T5
,"01110000000TTTTTddddd00101101000",MMI1
, PABS
, (HALFWORD
)},
690 {"PABSW", T5
,"01110000000TTTTTddddd00001101000",MMI1
, PABS
, (WORD
)},
692 {"PADDB", T5
,"011100SSSSSTTTTTddddd01000001000",MMI0
, PADD
, (BYTE
)},
693 {"PADDH", T5
,"011100SSSSSTTTTTddddd00100001000",MMI0
, PADD
, (HALFWORD
)},
694 {"PADDW", T5
,"011100SSSSSTTTTTddddd00000001000",MMI0
, PADD
, (WORD
)},
696 {"PADDSB", T5
,"011100SSSSSTTTTTddddd11000001000",MMI0
, PADD
, (BYTE
| SATURATE
)},
697 {"PADDSH", T5
,"011100SSSSSTTTTTddddd10100001000",MMI0
, PADD
, (HALFWORD
| SATURATE
)},
698 {"PADDSW", T5
,"011100SSSSSTTTTTddddd10000001000",MMI0
, PADD
, (WORD
| SATURATE
)},
700 {"PADDUB", T5
,"011100SSSSSTTTTTddddd11000101000",MMI1
, PADD
, (BYTE
| UNSIGNED
)},
701 {"PADDUH", T5
,"011100SSSSSTTTTTddddd10100101000",MMI1
, PADD
, (HALFWORD
| UNSIGNED
)},
702 {"PADDUW", T5
,"011100SSSSSTTTTTddddd10000101000",MMI1
, PADD
, (WORD
| UNSIGNED
)},
704 {"PADSBH", T5
,"011100SSSSSTTTTTddddd00100101000",MMI1
, PADSBH
, (NONE
)},
706 {"PAND", T5
,"011100SSSSSTTTTTddddd10010001001",MMI2
, POP
, (POP_AND
)},
708 {"PCEQB", T5
,"011100SSSSSTTTTTddddd01010101000",MMI1
, PCMP
, (EQ
| BYTE
)},
709 {"PCEQH", T5
,"011100SSSSSTTTTTddddd00110101000",MMI1
, PCMP
, (EQ
| HALFWORD
)},
710 {"PCEQW", T5
,"011100SSSSSTTTTTddddd00010101000",MMI1
, PCMP
, (EQ
| WORD
)},
712 {"PCGTB", T5
,"011100SSSSSTTTTTddddd01010001000",MMI0
, PCMP
, (GT
| BYTE
)},
713 {"PCGTH", T5
,"011100SSSSSTTTTTddddd00110001000",MMI0
, PCMP
, (GT
| HALFWORD
)},
714 {"PCGTW", T5
,"011100SSSSSTTTTTddddd00010001000",MMI0
, PCMP
, (GT
| WORD
)},
716 {"PCPYH", T5
,"01110000000TTTTTddddd11011101001",MMI3
, PCPYH
, (NONE
)},
717 {"PCPYLD", T5
,"011100SSSSSTTTTTddddd01110001001",MMI2
, PCPYLD
, (NONE
)},
718 {"PCPYUD", T5
,"011100SSSSSTTTTTddddd01110101001",MMI3
, PCPYUD
, (NONE
)},
720 {"PDIVBW", T5
,"011100SSSSSTTTTT0000011101001001",MMI2
, PDIVBW
, (NONE
)},
721 {"PDIVUW", T5
,"011100SSSSSTTTTT0000001101101001",MMI3
, PDIVW
, (UNSIGNED
)},
722 {"PDIVW", T5
,"011100SSSSSTTTTT0000001101001001",MMI2
, PDIVW
, (NONE
)},
724 {"PEXCH", T5
,"01110000000TTTTTddddd11010101001",MMI3
, PEXCH
, (NONE
)},
725 {"PEXCW", T5
,"01110000000TTTTTddddd11110101001",MMI3
, PEXCW
, (NONE
)},
726 {"PEXOH", T5
,"01110000000TTTTTddddd11010001001",MMI2
, PEXOH
, (NONE
)},
727 {"PEXOW", T5
,"01110000000TTTTTddddd11110001001",MMI2
, PEXOW
, (NONE
)},
729 {"PEXT5", T5
,"01110000000TTTTTddddd11110001000",MMI0
, PEXT5
, (NONE
)},
731 {"PEXTLB", T5
,"011100SSSSSTTTTTddddd11010001000",MMI0
, PEXTLB
, (NONE
)},
732 {"PEXTLH", T5
,"011100SSSSSTTTTTddddd10110001000",MMI0
, PEXTLH
, (NONE
)},
733 {"PEXTLW", T5
,"011100SSSSSTTTTTddddd10010001000",MMI0
, PEXTLW
, (NONE
)},
734 {"PEXTUB", T5
,"011100SSSSSTTTTTddddd11010101000",MMI1
, PEXTUB
, (NONE
)},
735 {"PEXTUH", T5
,"011100SSSSSTTTTTddddd10110101000",MMI1
, PEXTUH
, (NONE
)},
736 {"PEXTUW", T5
,"011100SSSSSTTTTTddddd10010101000",MMI1
, PEXTUW
, (NONE
)},
738 {"PHMADDH",T5
,"011100SSSSSTTTTTddddd10001001001",MMI2
, PHMADDH
, (NONE
)},
739 {"PHMSUBH",T5
,"011100SSSSSTTTTTddddd10101001001",MMI2
, PHMADDH
, (SUBTRACT
)},
741 {"PINTH", T5
,"011100SSSSSTTTTTddddd01010001001",MMI2
, PINTH
, (NONE
)},
742 {"PINTOH", T5
,"011100SSSSSTTTTTddddd01010101001",MMI3
, PINTOH
, (NONE
)},
744 {"PLZCW", T5
,"011100SSSSS00000ddddd00000000100",MMINORM
,PLZCW
, (NONE
)},
746 {"PMADDH", T5
,"011100SSSSSTTTTTddddd10000001001",MMI2
, PMULTH
, (ADDITION
)},
747 {"PMADDUW",T5
,"011100SSSSSTTTTTddddd00000101001",MMI3
, PMULTW
, (ADDITION
| UNSIGNED
)},
748 {"PMADDW", T5
,"011100SSSSSTTTTTddddd00000001001",MMI2
, PMULTW
, (ADDITION
)},
750 {"PMAXH", T5
,"011100SSSSSTTTTTddddd00111001000",MMI0
, PMAXMIN
, (GT
| HALFWORD
)},
751 {"PMAXW", T5
,"011100SSSSSTTTTTddddd00011001000",MMI0
, PMAXMIN
, (GT
| WORD
)},
753 {"PMFHI", T5
,"0111000000000000ddddd01000001001",MMI2
, PMXX
, (HI
|FROM
)},
754 {"PMFLO", T5
,"0111000000000000ddddd01001001001",MMI2
, PMXX
, (LO
|FROM
)},
756 {"PMFHL", T5
,"0111000000000000dddddaaaaa110000",MMINORM
,PMFHL
, (NONE
)},
758 {"PMINH", T5
,"011100SSSSSTTTTTddddd00111101000",MMI1
, PMAXMIN
, (LT
| HALFWORD
)},
759 {"PMINW", T5
,"011100SSSSSTTTTTddddd00011101000",MMI1
, PMAXMIN
, (LT
| WORD
)},
761 {"PMSUBH", T5
,"011100SSSSSTTTTTddddd10100001001",MMI2
, PMULTH
, (SUBTRACT
)},
762 {"PMSUBW", T5
,"011100SSSSSTTTTTddddd00100001001",MMI2
, PMULTW
, (SUBTRACT
)},
764 {"PMTHI", T5
,"011100SSSSS000000000001000101001",MMI3
, PMXX
, (HI
|TO
)},
765 {"PMTLO", T5
,"011100SSSSS000000000001001101001",MMI3
, PMXX
, (LO
|TO
)},
767 {"PMTHL.LW",T5
,"011100SSSSS000000000000000110001",MMINORM
,PMTHL
, (NONE
)},
769 {"PMULTH", T5
,"011100SSSSSTTTTTddddd11100001001",MMI2
, PMULTH
, (NONE
)},
770 {"PMULTUW",T5
,"011100SSSSSTTTTTddddd01100101001",MMI3
, PMULTW
, (UNSIGNED
)},
771 {"PMULTW", T5
,"011100SSSSSTTTTTddddd01100001001",MMI2
, PMULTW
, (NONE
)},
773 {"PNOR", T5
,"011100SSSSSTTTTTddddd10011101001",MMI3
, POP
, (POP_NOR
)},
774 {"POR", T5
,"011100SSSSSTTTTTddddd10010101001",MMI3
, POP
, (POP_OR
)},
776 {"PPAC5", T5
,"01110000000TTTTTddddd11111001000",MMI0
, PPAC5
, (NONE
)},
778 {"PPACB", T5
,"011100SSSSSTTTTTddddd11011001000",MMI0
, PPACB
, (NONE
)},
779 {"PPACH", T5
,"011100SSSSSTTTTTddddd10111001000",MMI0
, PPACH
, (NONE
)},
780 {"PPACW", T5
,"011100SSSSSTTTTTddddd10011001000",MMI0
, PPACW
, (NONE
)},
782 {"PREVH", T5
,"01110000000TTTTTddddd11011001001",MMI2
, PREVH
, (NONE
)},
783 {"PROT3W", T5
,"01110000000TTTTTddddd11111001001",MMI2
, PROT3W
, (NONE
)},
785 {"PSLLH", T5
,"01110000000TTTTTdddddaaaaa110100",MMINORM
,PSHIFT
, (LEFT
| LOGICAL
| HALFWORD
)},
786 {"PSLLVW", T5
,"011100SSSSSTTTTTddddd00010001001",MMI2
, PSLLVW
, (NONE
)},
787 {"PSLLW", T5
,"01110000000TTTTTdddddaaaaa111100",MMINORM
,PSHIFT
, (LEFT
| LOGICAL
| WORD
)},
789 {"PSRAH", T5
,"01110000000TTTTTdddddaaaaa110111",MMINORM
,PSHIFT
, (RIGHT
| ARITHMETIC
| HALFWORD
)},
790 {"PSRAVW", T5
,"011100SSSSSTTTTTddddd00011101001",MMI3
, PSRAVW
, (NONE
)},
791 {"PSRAW", T5
,"01110000000TTTTTdddddaaaaa111111",MMINORM
,PSHIFT
, (RIGHT
| ARITHMETIC
| WORD
)},
793 {"PSRLH", T5
,"01110000000TTTTTdddddaaaaa110110",MMINORM
,PSHIFT
, (RIGHT
| LOGICAL
| HALFWORD
)},
794 {"PSRLVW", T5
,"011100SSSSSTTTTTddddd00011001001",MMI2
, PSRLVW
, (NONE
)},
795 {"PSRLW", T5
,"01110000000TTTTTdddddaaaaa111110",MMINORM
,PSHIFT
, (RIGHT
| LOGICAL
| WORD
)},
797 {"PSUBB", T5
,"011100SSSSSTTTTTddddd01001001000",MMI0
, PADD
, (SUBTRACT
| BYTE
)},
798 {"PSUBH", T5
,"011100SSSSSTTTTTddddd00101001000",MMI0
, PADD
, (SUBTRACT
| HALFWORD
)},
799 {"PSUBSB", T5
,"011100SSSSSTTTTTddddd11001001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| BYTE
)},
800 {"PSUBSH", T5
,"011100SSSSSTTTTTddddd10101001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| HALFWORD
)},
801 {"PSUBSW", T5
,"011100SSSSSTTTTTddddd10001001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| WORD
)},
802 {"PSUBUB", T5
,"011100SSSSSTTTTTddddd11001101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| BYTE
)},
803 {"PSUBUH", T5
,"011100SSSSSTTTTTddddd10101101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| HALFWORD
)},
804 {"PSUBUW", T5
,"011100SSSSSTTTTTddddd10001101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| WORD
)},
805 {"PSUBW", T5
,"011100SSSSSTTTTTddddd00001001000",MMI0
, PADD
, (SUBTRACT
| WORD
)},
807 {"PXOR", T5
,"011100SSSSSTTTTTddddd10011001001",MMI2
, POP
, (POP_XOR
)},
808 /* end-sanitize-r5900 */
810 {"PREF", G2
,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, PREFETCH
, (NONE
)},
811 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X
, FPPREFX
, (FP
)},
813 /* start-sanitize-r5900 */
814 {"QFSRV", T5
,"011100SSSSSTTTTTddddd11011101000",MMI1
, QFSRV
, (NONE
)},
815 /* end-sanitize-r5900 */
817 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1
, FPRECIP
, (FP
)},
818 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1
, FPROUND
, (FP
| FIXED
| DOUBLEWORD
)},
819 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1
, FPROUND
, (FP
| FIXED
| WORD
)},
820 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1
, FPSQRT
, (FP
| RECIP
)},
821 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (BYTE
)},
822 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| ATOMIC
)},
823 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| ATOMIC
)},
824 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
)},
825 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
826 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
827 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| LEFT
)},
828 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| RIGHT
)},
829 {"SDXC1", G3
,"010011sssssgggggvvvvv00000001001",COP1X
, STORE
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
830 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL
, STORE
, (HALFWORD
)},
831 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << sa */
832 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
833 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL
,SET
, (LT
)},
834 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
)},
835 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL
,SET
, (LT
| UNSIGNED
)},
836 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
| UNSIGNED
)},
837 /* start-sanitize-r5900 */
838 {"SQ", T5
,"011111sssssTTTTTeeeeeeeeeeeeeeee",NORMAL
, STORE
, (QUADWORD
)},
839 /* end-sanitize-r5900 */
840 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1
, FPSQRT
, (FP
)},
841 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
842 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
843 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
844 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
845 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL
,SUB
, (WORD
| WORD32
| OVERFLOW
)},
846 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1
, FPSUB
, (FP
)},
847 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL
,SUB
, (WORD
| WORD32
)},
848 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
)},
849 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
850 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
851 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| LEFT
)},
852 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| RIGHT
)},
853 {"SWXC1", G3
,"010011sssssgggggvvvvv00000001000",COP1X
, STORE
, (FP
| WORD
| COPROC
| REG
)},
854 {"SYNC", G4
,"000000000000000000000aaaaa001111",SPECIAL
,SYNC
, (NONE
)}, /* z = 5bit stype field */
855 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL
,SYSCALL
, (NOARG
)},
856 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL
,TRAP
, (EQ
)},
857 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (EQ
)},
858 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL
,TRAP
, (GT
| EQ
)},
859 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
)},
860 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
| UNSIGNED
)},
861 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL
,TRAP
, (GT
| EQ
| UNSIGNED
)},
862 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL
,TRAP
, (LT
)},
863 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
)},
864 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
| UNSIGNED
)},
865 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL
,TRAP
, (LT
| UNSIGNED
)},
866 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL
,TRAP
, (NOT
| EQ
)},
867 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (NOT
| EQ
)},
868 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1
, FPTRUNC
, (FP
| FIXED
| DOUBLEWORD
)},
869 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1
, FPTRUNC
, (FP
| FIXED
| WORD
)},
870 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL
,XOR
, (NONE
)},
871 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, XOR
, (NONE
)},
872 {"CACHE", G6
,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, CACHE
, (NONE
)},
873 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, RSVD
, (NONE
)},
876 static const struct instruction MIPS16_DECODE
[] = {
877 {"ADDIU", 1, "01000xxxddd04444", RRI_A
, ADD
, WORD
| WORD32
},
878 {"ADDIU8", 1, "01001wwwkkkkkkkk", RI
, ADD
, WORD
| WORD32
},
879 {"ADJSP", 1, "01100011KKKKKKKKS", I8
, ADD
, WORD
| WORD32
},
880 {"ADDIUPC", 1, "00001dddAAAAAAAAP", RI
, ADD
, WORD
| WORD32
},
881 {"ADDIUSP", 1, "00000dddAAAAAAAAs", RI
, ADD
, WORD
| WORD32
},
882 {"ADDU", 1, "11100xxxyyyddd01", RRR
, ADD
, WORD
| WORD32
},
883 {"AND", 1, "11101wwwyyy01100", RR
, AND
, NONE
},
884 {"B", 1, "00010qqqqqqqqqqqzZ", I
, BRANCH
, EQ
},
885 {"BEQZ", 1, "00100xxxppppppppz", RI
, BRANCH
, EQ
},
886 {"BNEZ", 1, "00101xxxppppppppz", RI
, BRANCH
, NOT
| EQ
},
887 {"BREAK", 1, "01100??????00101", RR
, BREAK
, NOARG
},
888 {"BTEQZ", 1, "01100000pppppppptz", I8
, BRANCH
, EQ
},
889 {"BTNEZ", 1, "01100001pppppppptz", I8
, BRANCH
, NOT
| EQ
},
890 {"CMP", 1, "11101xxxyyy01010T", RR
, XOR
, NONE
},
891 {"CMPI", 1, "01110xxxUUUUUUUUT", RI
, XOR
, NONE
},
892 {"DADDIU", 3, "01000xxxddd14444", RRI_A
, ADD
, DOUBLEWORD
},
893 {"DADDIU5", 3, "11111101wwwjjjjj", RI64
, ADD
, DOUBLEWORD
},
894 {"DADJSP", 3, "11111011KKKKKKKKS", I64
, ADD
, DOUBLEWORD
},
895 {"DADIUPC", 3, "11111110dddEEEEEP", RI64
, ADD
, DOUBLEWORD
},
896 {"DADIUSP", 3, "11111111dddEEEEEs", RI64
, ADD
, DOUBLEWORD
},
897 {"DADDU", 3, "11100xxxyyyddd00", RRR
, ADD
, DOUBLEWORD
},
898 {"DDIV", 3, "11101xxxyyy11110", RR
, DIV
, DOUBLEWORD
| HI
| LO
},
899 {"DDIVU", 3, "11101xxxyyy11111", RR
, DIV
, DOUBLEWORD
| UNSIGNED
| HI
| LO
},
900 {"DIV", 1, "11101xxxyyy11010", RR
, DIV
, WORD
| WORD32
| SIGNEXTEND
| HI
| LO
},
901 {"DIVU", 1, "11101xxxyyy11011", RR
, DIV
, WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
},
902 {"DMULT", 3, "11101xxxyyy11100", RR
, MUL
, DOUBLEWORD
| HI
| LO
},
903 {"DMULTU", 3, "11101xxxyyy11101", RR
, MUL
, DOUBLEWORD
| UNSIGNED
| HI
| LO
},
904 {"DSLL", 3, "00110dddyyy[[[01", ISHIFT
, SHIFT
, DOUBLEWORD
| LEFT
| LOGICAL
},
905 {"DSLLV", 3, "11101xxxvvv10100", RR
, SHIFT
, DOUBLEWORD
| LEFT
| LOGICAL
| REG
},
906 {"DSRA", 3, "11101]]]vvv10011", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| ARITHMETIC
},
907 {"DSRAV", 3, "11101xxxvvv10111", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| ARITHMETIC
| REG
},
908 {"DSRL", 3, "11101]]]vvv01000", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| LOGICAL
},
909 {"DSRLV", 3, "11101xxxvvv10110", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| LOGICAL
| REG
},
910 {"DSUBU", 3, "11100xxxyyyddd10", RRR
, SUB
, DOUBLEWORD
| UNSIGNED
},
912 /* FIXME: Should we handle these ourselves, or should we require an
913 emulation routine? */
914 {"EXIT", 1, "1110111100001000", RR
, BREAK
, EXIT
},
915 {"ENTRY", 1, "11101??????01000", RR
, BREAK
, ENTRY
},
917 {"EXTEND", 1, "11110eeeeeeeeeee", I
, RSVD
, NOARG
},
918 {"JALR", 1, "11101xxx01000000R", RR
, JUMP
, LINK
| REG
},
919 {"JAL", 1, "00011aaaaaaaaaaa", I
, JUMP
, LINK
},
920 {"JR", 1, "11101xxx00000000", RR
, JUMP
, NONE
},
921 {"JRRA", 1, "1110100000100000r", RR
, JUMP
, NONE
},
922 {"LB", 1, "10000xxxddd55555", RRI
, LOAD
, BYTE
| SIGNEXTEND
},
923 {"LBU", 1, "10100xxxddd55555", RRI
, LOAD
, BYTE
},
924 {"LD", 3, "00111xxxdddDDDDD", RRI
, LOAD
, DOUBLEWORD
},
925 {"LDPC", 3, "11111100dddDDDDDP", RI64
, LOAD
, DOUBLEWORD
},
926 {"LDSP", 3, "11111000dddDDDDDs", RI64
, LOAD
, DOUBLEWORD
},
927 {"LH", 1, "10001xxxdddHHHHH", RRI
, LOAD
, HALFWORD
| SIGNEXTEND
},
928 {"LHU", 1, "10101xxxdddHHHHH", RRI
, LOAD
, HALFWORD
},
929 {"LI", 1, "01101dddUUUUUUUUZ", RI
, OR
, NONE
},
930 {"LW", 1, "10011xxxdddWWWWW", RRI
, LOAD
, WORD
| SIGNEXTEND
},
931 {"LWPC", 1, "10110dddVVVVVVVVP", RI
, LOAD
, WORD
| SIGNEXTEND
},
932 {"LWSP", 1, "10010dddVVVVVVVVs", RI
, LOAD
, WORD
| SIGNEXTEND
},
933 {"LWU", 1, "10111xxxdddWWWWW", RRI
, LOAD
, WORD
},
934 {"MFHI", 1, "11101ddd00010000", RR
, MOVE
, HI
| LEFT
},
935 {"MFLO", 1, "11101ddd00010010", RR
, MOVE
, LO
| LEFT
},
936 {"MOVR32", 1, "01100111dddXXXXXz", I8_MOVR32
, OR
, NONE
},
937 {"MOV32R", 1, "01100101YYYYYxxxz", I8_MOV32R
, OR
, NONE
},
938 {"MULT", 1, "11101xxxyyy11000", RR
, MUL
, WORD
| WORD32
| HI
| LO
},
939 {"MULTU", 1, "11101xxxyyy11001", RR
, MUL
, WORD
| WORD32
| UNSIGNED
| HI
| LO
},
940 {"NEG", 1, "11101dddyyy01011Z", RR
, SUB
, WORD
},
941 {"NOT", 1, "11101dddyyy01111Z", RR
, OR
, NOT
},
942 {"OR", 1, "11101wwwyyy01101", RR
, OR
, NONE
},
943 {"SB", 1, "11000xxxyyy55555", RRI
, STORE
, BYTE
},
944 {"SD", 3, "01111xxxyyyDDDDD", RRI
, STORE
, DOUBLEWORD
},
945 {"SDSP", 3, "11111001yyyDDDDDs", RI64
, STORE
, DOUBLEWORD
},
946 {"SDRASP", 3, "11111010CCCCCCCCsQ", I64
, STORE
, DOUBLEWORD
},
947 {"SH", 1, "11001xxxyyyHHHHH", RRI
, STORE
, HALFWORD
},
948 {"SLL", 1, "00110dddyyy<<<00", ISHIFT
, SHIFT
, WORD
| LEFT
| LOGICAL
},
949 {"SLLV", 1, "11101xxxvvv00100", RR
, SHIFT
, WORD
| LEFT
| LOGICAL
| REG
},
950 {"SLT", 1, "11101xxxyyy00010T", RR
, SET
, LT
},
951 {"SLTI", 1, "01010xxx88888888T", RI
, SET
, LT
},
952 {"SLTU", 1, "11101xxxyyy00011T", RR
, SET
, LT
| UNSIGNED
},
953 {"SLTIU", 1, "01011xxx88888888T", RI
, SET
, LT
| UNSIGNED
},
954 {"SRA", 1, "00110dddyyy<<<11", ISHIFT
, SHIFT
, WORD
| WORD32
| RIGHT
| ARITHMETIC
},
955 {"SRAV", 1, "11101xxxvvv00111", RR
, SHIFT
, WORD
| WORD32
| RIGHT
| ARITHMETIC
| REG
},
956 {"SRL", 1, "00110dddyyy<<<10", ISHIFT
, SHIFT
, WORD
| WORD32
| RIGHT
| LOGICAL
},
957 {"SRLV", 1, "11101xxxvvv00110", RR
, SHIFT
, WORD
| WORD32
| RIGHT
| LOGICAL
| REG
},
958 {"SUBU", 1, "11100xxxyyyddd11", RRR
, SUB
, WORD
| WORD32
},
959 {"SW", 1, "11011xxxyyyWWWWW", RRI
, STORE
, WORD
},
960 {"SWSP", 1, "11010yyyVVVVVVVVs", RI
, STORE
, WORD
},
961 {"SWRASP", 1, "01100010VVVVVVVVQs", I8
, STORE
, WORD
},
962 {"XOR", 1, "11101wwwyyy01110", RR
, XOR
, NONE
}
965 static int bitmap_val
PARAMS ((const char *, int, int));
966 static void build_mips16_operands
PARAMS ((const char *));
967 static void build_instruction
968 PARAMS ((int, unsigned int, int, const struct instruction
*));
970 /*---------------------------------------------------------------------------*/
973 name_for_data_len( insn
)
974 struct instruction
* insn
;
976 if (GETDATASIZEINSN(insn
) == BYTE
)
979 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
982 else if (GETDATASIZEINSN(insn
) == WORD
)
985 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
988 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
996 letter_for_data_len( insn
)
997 struct instruction
* insn
;
999 if (GETDATASIZEINSN(insn
) == BYTE
)
1002 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1005 else if (GETDATASIZEINSN(insn
) == WORD
)
1008 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1011 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1019 type_for_data_len( insn
, is_signed
)
1020 struct instruction
* insn
;
1023 if (GETDATASIZEINSN(insn
) == BYTE
)
1024 return is_signed
? "int" : "unsigned int";
1026 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1027 return is_signed
? "int" : "unsigned int";
1029 else if (GETDATASIZEINSN(insn
) == WORD
)
1030 return is_signed
? "signed64" : "unsigned64";
1032 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1035 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1043 max_for_data_len( insn
)
1044 struct instruction
* insn
;
1046 if (GETDATASIZEINSN(insn
) == BYTE
)
1049 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1052 else if (GETDATASIZEINSN(insn
) == WORD
)
1053 return "(int)0x7FFFFFFF";
1055 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1058 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1066 min_for_data_len( insn
)
1067 struct instruction
* insn
;
1069 if (GETDATASIZEINSN(insn
) == BYTE
)
1072 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1075 else if (GETDATASIZEINSN(insn
) == WORD
)
1076 return "(int)0x80000000";
1078 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1081 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1089 umax_for_data_len( insn
)
1090 struct instruction
* insn
;
1092 if (GETDATASIZEINSN(insn
) == BYTE
)
1095 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1098 else if (GETDATASIZEINSN(insn
) == WORD
)
1099 return "0xFFFFFFFF";
1101 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1104 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1112 bits_for_data_len( insn
)
1113 struct instruction
* insn
;
1115 if (GETDATASIZEINSN(insn
) == BYTE
)
1118 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1121 else if (GETDATASIZEINSN(insn
) == WORD
)
1124 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1127 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1134 /*---------------------------------------------------------------------------*/
1138 convert_bitmap(bitmap
,onemask
,zeromask
,dontmask
)
1140 unsigned int *onemask
, *zeromask
, *dontmask
;
1142 int loop
; /* current bitmap position */
1143 int lastsp
= -1; /* last bitmap field starting position */
1144 int lastoe
= -1; /* last bitmap field encoding */
1146 *onemask
= 0x00000000;
1147 *zeromask
= 0x00000000;
1148 *dontmask
= 0x00000000;
1150 if (strlen(bitmap
) != 32) {
1151 fprintf(stderr
,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap
);
1155 for (loop
= 0; (loop
< 32); loop
++) {
1157 for (oefield
= 0; (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))); oefield
++)
1158 if (bitmap
[31 - loop
] == opfields
[oefield
].id
)
1160 if (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))) {
1161 if ((lastoe
!= -1) && (lastoe
!= oefield
))
1162 if ((loop
- lastsp
) != (opfields
[lastoe
].flen
)) {
1163 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
);
1167 switch (bitmap
[31 - loop
]) {
1168 case '0' : /* fixed value */
1169 *zeromask
|= (1 << loop
);
1174 case '1' : /* fixed value */
1175 *onemask
|= (1 << loop
);
1180 case '?' : /* fixed value */
1181 *dontmask
|= (1 << loop
);
1186 default : /* check character encoding */
1188 if (opfields
[oefield
].fpos
!= -1) {
1189 /* If flag not set, then check starting position: */
1190 if (lastoe
!= oefield
) {
1191 if (loop
!= opfields
[oefield
].fpos
) {
1192 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
);
1199 *dontmask
|= (1 << loop
);
1204 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
);
1209 /* NOTE: Since we check for the position and size of fields when
1210 parsing the "bitmap" above, we do *NOT* need to check that invalid
1211 field combinations have been used. */
1214 /* Get the value of a 16 bit bitstring for a given shift count and
1218 bitmap_val (bitmap
, shift
, bits
)
1227 s
= bitmap
+ 16 - shift
- bits
;
1228 for (; bits
> 0; --bits
)
1243 /*---------------------------------------------------------------------------*/
1246 build_operands(doisa
,features
,insn
)
1248 unsigned int features
;
1251 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
1252 int finish_jump_flag
= 0;
1254 int check_condition_code
= 0;
1255 int sfield_used
= 0;
1256 int gfield_used
= 0;
1257 int any_operand
= 0;
1259 int current_field_id
= -1;
1262 for (bitpos
=0; bitpos
<32; bitpos
++) {
1263 if (insn
->bitmap
[31-bitpos
] != current_field_id
)
1267 current_field_id
= insn
->bitmap
[31-bitpos
];
1269 for (opindex
= 0; (opindex
< (sizeof(opfields
) / sizeof(operand_encoding
))); opindex
++)
1270 if ((opfields
[opindex
].fpos
!= -1) && (opfields
[opindex
].id
== insn
->bitmap
[31-bitpos
])) {
1274 printf(" %s %s UNUSED = ",opfields
[opindex
].type
,opfields
[opindex
].name
);
1276 if (opfields
[opindex
].flags
& OP_SIGNX
)
1277 printf("SIGNEXTEND((%s)",opfields
[opindex
].type
);
1279 if (opfields
[opindex
].flags
& OP_GPR
)
1282 if (opfields
[opindex
].flags
& OP_SHIFT2
)
1285 printf("((instruction >> %d) & 0x%08X)",opfields
[opindex
].fpos
,((1 << opfields
[opindex
].flen
) - 1));
1287 if (opfields
[opindex
].flags
& OP_SHIFT2
)
1290 if (opfields
[opindex
].flags
& OP_GPR
)
1293 if (opfields
[opindex
].flags
& OP_BITS5
)
1296 if (opfields
[opindex
].flags
& OP_SIGNX
)
1297 printf(",%d)",(opfields
[opindex
].flen
+ ((opfields
[opindex
].flags
& OP_SHIFT2
) ? 2 : 0)));
1301 if (opfields
[opindex
].flags
& OP_GPR1
)
1303 printf(" %s %s1 = GPR1[",opfields
[opindex
].type
,opfields
[opindex
].name
);
1304 printf("((instruction >> %d) & 0x%08X)",
1305 opfields
[opindex
].fpos
,
1306 ((1 << opfields
[opindex
].flen
) - 1));
1310 if (opfields
[opindex
].id
== 'j')
1311 finish_jump_flag
= 1;
1313 if (opfields
[opindex
].id
== 'e')
1316 if (opfields
[opindex
].id
== 'w')
1319 if (opfields
[opindex
].id
== 'w')
1322 if (opfields
[opindex
].id
== 'p')
1323 check_condition_code
= 1;
1325 if (opfields
[opindex
].id
== 's')
1328 if (opfields
[opindex
].id
== 'g')
1334 if ( !any_operand
&& !(insn
->flags
& NOARG
)) {
1335 fprintf(stderr
,"Bitmap error: Instruction with no operand fields \"%s\"\n",insn
->name
) ;
1339 /* Finish constructing the jump address if required: */
1340 if (finish_jump_flag
)
1341 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
1343 /* Now perform required operand checks: */
1345 /* The following code has been removed, since it seems perfectly
1346 reasonable to have a non-aligned offset that is added to another
1347 non-aligned base to create an aligned address. Some more
1348 information on exactly what the MIPS IV specification requires is
1349 needed before deciding on the best strategy. Experimentation with a
1350 VR4300 suggests that we do not need to raise the warning. */
1352 /* For MIPS IV (and onwards), certain instruction operand values
1353 will give undefined results. For the simulator we could
1354 generate explicit exceptions (i.e. ReservedInstruction) to
1355 make it easier to spot invalid use. However, for the moment we
1356 just raise a warning. NOTE: This is a different check to the
1357 later decoding, which checks for the final address being
1360 if (check_mult
!= 0 && check_mult
!= 1) {
1361 printf(" if (instruction & 0x%1X)\n", check_mult
);
1363 /* NOTE: If we change this to a SignalException(), we must
1364 ensure that the following opcode processing is not
1365 executed. i.e. the code falls straight out to the simulator
1367 printf(" sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
1372 /* The extended condition codes only appeared in ISA IV */
1373 if (check_condition_code
&& (doisa
< 4)) {
1374 printf(" if (condition_code != 0)\n");
1376 printf(" SignalException(ReservedInstruction,instruction);\n");
1381 if ((insn
->flags
& WORD32
) && (GETDATASIZEINSN(insn
) != WORD
)) {
1382 fprintf(stderr
,"Error in opcode table: WORD32 set for non-WORD opcode\n");
1387 /* The R4000 book differs slightly from the MIPS IV ISA
1388 manual. An example is the sign-extension of a 64-bit processor
1389 SUBU operation, and what is meant by an Undefined Result. This
1390 is now provided purely as a warning. After examining a HW
1391 implementation, this is now purely a warning... and the actual
1392 operation is performed, with possibly undefined results. */
1393 if (((insn
->flags
& WORD32
) && proc64
) && (features
& FEATURE_WARN_RESULT
)) {
1394 /* The compiler should optimise out an OR with zero */
1395 printf(" if (%s | %s)\n",(sfield_used
? "NOTWORDVALUE(op1)" : "0"),(gfield_used
? "NOTWORDVALUE(op2)" : "0"));
1396 printf(" UndefinedResult();\n") ;
1399 /* Check that the source is a 32bit value */
1400 if ((insn
->flags
& WORD32
) && proc64
) {
1401 /* The compiler should optimise out an OR with zero */
1402 printf(" if (%s | %s)\n",(sfield_used
? "NOTWORDVALUE(op1)" : "0"),(gfield_used
? "NOTWORDVALUE(op2)" : "0"));
1403 printf(" UndefinedResult();\n") ;
1411 /* The mips16 operand table. */
1415 /* The character which appears in the bitmap string. */
1417 /* The type of the variable in the simulator. */
1418 const char *vartype
;
1419 /* The name of the variable in the simulator. */
1421 /* The number of bits. */
1423 /* The number of bits when extended (zero if can not be extended). */
1425 /* The amount by which the short form is shifted when it is used;
1426 for example, the sw instruction has a shift count of 2. */
1432 /* Flags which appears in the mips16 operand table. */
1434 /* Whether this is a mips16 register index. */
1435 #define MIPS16_REG16 (0x1)
1436 /* Whether this is a register value. */
1437 #define MIPS16_REGVAL (0x2)
1438 /* Whether this is a swapped mips32 register index (MOV32R) */
1439 #define MIPS16_REG32_SWAPPED (0x4)
1440 /* Whether this index is also the destination register. */
1441 #define MIPS16_DESTREG (0x8)
1442 /* Whether the short form is unsigned. */
1443 #define MIPS16_UNSP (0x10)
1444 /* Whether the extended form is unsigned. */
1445 #define MIPS16_EXTU (0x20)
1446 /* Implicit stack pointer. */
1447 #define MIPS16_SP (0x40)
1448 /* Implicit program counter. */
1449 #define MIPS16_PC (0x80)
1451 #define MIPS16_ZERO (0x100)
1453 #define MIPS16_TREG (0x200)
1455 #define MIPS16_RA (0x400)
1457 #define MIPS16_JUMP_ADDR (0x800)
1458 /* Branch offset. */
1459 #define MIPS16_BRANCH (0x1000)
1461 /* The mips16 operand table. */
1463 static const struct mips16_op mips16_op_table
[] =
1465 { 'd', "int", "destreg", 3, 0, 0, MIPS16_REG16
},
1466 { 'x', "t_reg", "op1", 3, 0, 0, MIPS16_REG16
| MIPS16_REGVAL
},
1467 { 'w', "t_reg", "op1", 3, 0, 0, MIPS16_REG16
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1468 { 'y', "t_reg", "op2", 3, 0, 0, MIPS16_REG16
| MIPS16_REGVAL
},
1469 { 'v', "t_reg", "op2", 3, 0, 0, MIPS16_REG16
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1470 { 'X', "t_reg", "op1", 5, 0, 0, MIPS16_REGVAL
},
1471 { 'Y', "int", "destreg", 5, 0, 0, MIPS16_REG32_SWAPPED
},
1472 { 'a', "ut_reg", "op1", 11, 0, 0, MIPS16_JUMP_ADDR
},
1473 { 'e', "int", "ext", 11, 0, 0, 0 },
1474 { '<', "int", "op1", 3, 5, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1475 { '>', "int", "op1", 3, 5, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1476 { '[', "int", "op1", 3, 6, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1477 { ']', "int", "op1", 3, 6, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1478 { '4', "int", "op2", 4, 15, 0, 0 },
1479 { '5', "int", "offset", 5, 16, 0, MIPS16_UNSP
},
1480 { 'H', "int", "offset", 5, 16, 1, MIPS16_UNSP
},
1481 { 'W', "int", "offset", 5, 16, 2, MIPS16_UNSP
},
1482 { 'D', "int", "offset", 5, 16, 3, MIPS16_UNSP
},
1483 { 'j', "int", "op2", 5, 16, 0, 0 },
1484 { '8', "int", "op2", 8, 16, 0, MIPS16_UNSP
},
1485 { 'V', "int", "offset", 8, 16, 2, MIPS16_UNSP
},
1486 { 'C', "int", "offset", 8, 16, 3, MIPS16_UNSP
},
1487 { 'U', "int", "op2", 8, 16, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1488 { 'k', "int", "op2", 8, 16, 0, 0 },
1489 { 'K', "int", "op2", 8, 16, 3, 0 },
1490 { 'p', "int", "offset", 8, 16, 0, MIPS16_BRANCH
},
1491 { 'q', "int", "offset", 11, 16, 0, MIPS16_BRANCH
},
1492 { 'A', "int", "op2", 8, 16, 2, MIPS16_UNSP
},
1493 { 'B', "int", "op2", 5, 16, 3, MIPS16_UNSP
},
1494 { 'E', "int", "op2", 5, 16, 2, MIPS16_UNSP
},
1496 /* The remaining operands are special operands which encode implied
1497 arguments. These only appear at the end of a bitmap string, and
1498 do not represent actual bits. */
1499 { 's', "t_reg", "op1", 0, 0, 0, MIPS16_SP
| MIPS16_REGVAL
},
1500 { 'S', "t_reg", "op1", 0, 0, 0, MIPS16_SP
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1501 { 'P', "t_reg", "op1", 0, 0, 0, MIPS16_PC
},
1502 { 'z', "t_reg", "op2", 0, 0, 0, MIPS16_ZERO
},
1503 { 'Z', "t_reg", "op1", 0, 0, 0, MIPS16_ZERO
},
1504 { 't', "t_reg", "op1", 0, 0, 0, MIPS16_TREG
| MIPS16_REGVAL
},
1505 { 'T', "int", "destreg", 0, 0, 0, MIPS16_TREG
},
1506 { 'r', "t_reg", "op1", 0, 0, 0, MIPS16_RA
| MIPS16_REGVAL
},
1507 { 'R', "int", "destreg", 0, 0, 0, MIPS16_RA
},
1508 { 'Q', "t_reg", "op2", 0, 0, 0, MIPS16_RA
| MIPS16_REGVAL
},
1510 { '\0', NULL
, NULL
, 0, 0, 0, 0 }
1513 /* Build mips16 operands. */
1516 build_mips16_operands (bitmap
)
1521 const struct mips16_op
*op
= NULL
;
1522 const struct mips16_op
*ops
[3];
1526 for (s
= bitmap
; *s
!= '\0'; s
++)
1533 /* Make sure we saw the right number of bits for that
1535 if (op
->nbits
!= 0 && (s
- bitmap
) - op
->nbits
!= start
)
1540 if (*s
== '0' || *s
== '1' || *s
== '?')
1545 for (op
= mips16_op_table
; op
->type
!= *s
; ++op
)
1546 if (op
->type
== '\0')
1549 printf (" %s %s = ", op
->vartype
, op
->name
);
1551 printf ("(instruction >> %d) & 0x%x",
1552 16 - (s
- bitmap
) - op
->nbits
,
1553 (1 << op
->nbits
) - 1);
1556 if ((op
->flags
& MIPS16_SP
) != 0)
1558 else if ((op
->flags
& MIPS16_PC
) != 0)
1562 printf ("((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : (have_extendval ? IPC - 2 : IPC)) & ~ (uword64) 1)");
1563 for (j
= 0; j
< opindex
; j
++)
1564 if (ops
[j
]->shift
!= 0)
1565 printf (" & ~ (uword64) 0x%x", (1 << ops
[j
]->shift
) - 1);
1567 else if ((op
->flags
& MIPS16_ZERO
) != 0)
1569 else if ((op
->flags
& MIPS16_TREG
) != 0)
1571 else if ((op
->flags
& MIPS16_RA
) != 0)
1578 if ((op
->flags
& MIPS16_DESTREG
) != 0)
1579 printf (" int destreg;\n");
1589 /* Make sure we saw the right number of bits for that
1591 if (op
->nbits
!= 0 && 16 - op
->nbits
!= start
)
1595 for (i
= 0; i
< opindex
; i
++)
1598 if ((op
->flags
& MIPS16_REG16
) != 0)
1600 printf (" if (%s < 2)\n", op
->name
);
1601 printf (" %s += 16;\n", op
->name
);
1603 if ((op
->flags
& MIPS16_REG32_SWAPPED
) != 0)
1604 printf (" %s = (%s >> 2) | ((%s & 3) << 3);\n",
1605 op
->name
, op
->name
, op
->name
);
1606 if ((op
->flags
& MIPS16_DESTREG
) != 0)
1607 printf (" destreg = %s;\n", op
->name
);
1608 if ((op
->flags
& MIPS16_REGVAL
) != 0)
1609 printf (" %s = GPR[%s];\n", op
->name
, op
->name
);
1611 if (op
->extbits
!= 0)
1613 printf (" if (have_extendval)\n");
1615 if (op
->extbits
== 16)
1616 printf (" %s |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0);\n",
1618 else if (op
->extbits
== 15)
1619 printf (" %s |= ((extendval & 0xf) << 11) | (extendval & 0x7f0);\n",
1621 else if (op
->extbits
== 6)
1622 printf (" %s = ((extendval >> 6) & 0x1f) | (extendval & 0x20);\n",
1625 printf (" %s = (extendval >> 6) & 0x1f;\n",
1627 if ((op
->flags
& MIPS16_EXTU
) == 0)
1629 printf (" if (%s >= 0x%x)\n",
1630 op
->name
, 1 << (op
->extbits
- 1));
1631 printf (" %s -= 0x%x;\n",
1632 op
->name
, 1 << op
->extbits
);
1634 printf (" have_extendval = 0;\n");
1638 if ((op
->flags
& MIPS16_UNSP
) == 0)
1640 printf (" if (%s >= 0x%x)\n",
1641 op
->name
, 1 << (op
->nbits
- 1));
1642 printf (" %s -= 0x%x;\n",
1643 op
->name
, 1 << op
->nbits
);
1646 printf (" %s <<= %d;\n", op
->name
, op
->shift
);
1647 if (op
->type
== '<' || op
->type
== '>'
1648 || op
->type
== '[' || op
->type
== ']')
1650 printf (" if (%s == 0)\n", op
->name
);
1651 printf (" %s = 8;\n", op
->name
);
1656 if ((op
->flags
& MIPS16_BRANCH
) != 0)
1657 printf (" %s *= 2;\n", op
->name
);
1659 if ((op
->flags
& MIPS16_JUMP_ADDR
) != 0)
1662 printf (" uword64 paddr;\n");
1663 printf (" int uncached;\n");
1664 printf (" if (AddressTranslation (PC &~ (uword64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL))\n");
1666 printf (" uword64 memval;\n");
1667 printf (" unsigned int reverse = (ReverseEndian ? 3 : 0);\n");
1668 printf (" unsigned int bigend = (BigEndianCPU ? 3 : 0);\n");
1669 printf (" unsigned int byte;\n");
1670 printf (" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\n");
1671 printf (" LoadMemory (&memval,0,uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
1672 printf (" byte = (((PC &~ (uword64) 1) & 0x7) ^ (bigend << 1));\n");
1673 printf (" memval = (memval >> (8 * byte)) & 0xffff;\n");
1674 printf (" %s = (((%s & 0x1f) << 23)\n", op
->name
, op
->name
);
1675 printf (" | ((%s & 0x3e0) << 13)\n", op
->name
);
1676 printf (" | (memval << 2));\n");
1677 printf (" if ((instruction & 0x400) == 0)\n");
1678 printf (" %s |= 1;\n", op
->name
);
1679 printf (" PC += 2;\n");
1682 printf (" %s |= PC & ~ (uword64) 0x0fffffff;\n", op
->name
);
1686 /* FIXME: Is this the way to detect an unused extend opcode? */
1687 printf (" if (have_extendval)\n");
1688 printf (" SignalException (ReservedInstruction, instruction);\n");
1691 /*---------------------------------------------------------------------------*/
1699 build_endian_shift(proc64
,datalen
,endbit
,direction
,shift
)
1703 e_endshift direction
;
1707 printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit
,endbit
);
1708 printf(" memval %s= %d;\n",direction
== s_left
? "<<" : ">>",shift
);
1715 /*---------------------------------------------------------------------------*/
1716 /* doisa = number of MIPS ISA simulator table is being constructed for.
1717 * proc64 = TRUE if constructing 64bit processor world.
1718 * dofp = boolean, TRUE if FP instructions are to be included.
1719 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
1723 process_instructions(doarch
,features
)
1724 unsigned int doarch
;
1725 unsigned int features
;
1727 int doisa
= (doarch
& MASK_ISA
);
1728 int limit
= (sizeof(MIPS_DECODE
) / sizeof(instruction
));
1729 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
1730 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
1731 int dofp
= (features
& FEATURE_HASFPU
);
1732 int fpsingle
= (features
& FEATURE_FPSINGLE
);
1737 fprintf(stderr
,"process_instructions: invalid structure length\n");
1741 if (proc64
&& (gprlen
!= 64)) {
1742 fprintf(stderr
,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
1746 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
1749 for (loop
= 0; (loop
< limit
); loop
++)
1750 if ((MIPS_DECODE
[loop
].isa
& MASK_ISA
) > maxisa
)
1751 maxisa
= (MIPS_DECODE
[loop
].isa
& MASK_ISA
);
1756 printf("#if defined(SIM_MANIFESTS)\n");
1757 printf("#define MIPSISA (%d)\n",doisa
);
1759 printf("#define PROCESSOR_64BIT (1 == 1)\n");
1761 printf("#define PROCESSOR_64BIT (1 == 0)\n");
1762 #if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */
1763 printf("#define LOADDRMASK (0x%08X)\n",0x7);
1765 printf("#define LOADDRMASK (0x%08X)\n",(proc64
? 0x7 : 0x3));
1767 /* The FP registers are the same width as the CPU registers: */
1768 printf("#define GPRLEN (%d)\n",gprlen
);
1769 printf("typedef %s t_reg;\n",((gprlen
== 64) ? "word64" : "int"));
1770 printf("typedef %s ut_reg;\n",((gprlen
== 64) ? "uword64" : "unsigned int"));
1771 printf("typedef %s t_fpreg;\n",((gprlen
== 64) ? "word64" : "int"));
1773 printf("#define HASFPU (1 == 1)\n");
1774 if (features
& FEATURE_FAST
)
1775 printf("#define FASTSIM (1 == 1)\n");
1776 if (features
& FEATURE_WARN_STALL
)
1777 printf("#define WARN_STALL (1 == 1)\n");
1778 if (features
& FEATURE_WARN_LOHI
)
1779 printf("#define WARN_LOHI (1 == 1)\n");
1780 if (features
& FEATURE_WARN_ZERO
)
1781 printf("#define WARN_ZERO (1 == 1)\n");
1782 if (features
& FEATURE_WARN_MEM
)
1783 printf("#define WARN_MEM (1 == 1)\n");
1784 if (features
& FEATURE_WARN_R31
)
1785 printf("#define WARN_R31 (1 == 1)\n");
1786 if (features
& FEATURE_WARN_RESULT
)
1787 printf("#define WARN_RESULT (1 == 1)\n");
1789 printf("#else /* simulator engine */\n");
1791 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
1792 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64
? 64 : 32),doisa
,limit
);
1794 printf("/* %sFP instructions included */\n",(fpsingle
? "Single precision " : ""));
1795 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
1798 printf("#if !defined(PROCESSOR_64BIT)\n");
1799 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
1803 printf("/* Actual instruction decoding block */\n");
1804 printf("if ((vaddr & 1) == 0){\n");
1807 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP
,OP_MASK_OP
);
1808 limit
= (OP_MASK_OP
+ 1);
1810 printf("#ifdef DEBUG\n");
1811 printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n");
1814 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
1815 limit
+= (OP_MASK_SPEC
+ 1);
1817 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_RT
,OP_MASK_RT
);
1818 limit
+= (OP_MASK_RT
+ 1);
1820 printf("else if (num == 0x11) {\n");
1821 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM
,OP_SH_COP1NORM
,(OP_MASK_COP1NORM
<< OP_SH_COP1NORM
));
1822 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP
,OP_SH_COP1CMP
,(OP_MASK_COP1CMP
<< OP_SH_COP1CMP
));
1823 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,(OP_MASK_SPEC
& (OP_MASK_COP1CMP
<< OP_SH_COP1CMP
)));
1825 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
1826 limit
+= (OP_MASK_SPEC
+ 1);
1829 /* To keep this code quick, we just clear out the "to" bit
1830 here. The proper (though slower) code would be to have another
1831 conditional, checking whether this instruction is a branch or
1832 not, before limiting the range to the bottom two bits of the
1834 printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit
,OP_SH_COP1SPEC
,OP_MASK_COP1SPEC
,OP_MASK_COP1SCLR
);
1835 limit
+= (OP_MASK_COP1SPEC
+ 1);
1837 printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
1838 limit
+= (OP_MASK_SPEC
+ 1);
1840 printf("else if (num == 0x1C) {\n");
1841 printf(" int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI
,OP_MASK_MMI
);
1843 printf(" if (mmi_func == 0x08) \n");
1844 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
1845 limit
+= (OP_MASK_MMISUB
+ 1);
1847 printf(" else if (mmi_func == 0x28) \n");
1848 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
1849 limit
+= (OP_MASK_MMISUB
+ 1);
1851 printf(" else if (mmi_func == 0x09) \n");
1852 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
1853 limit
+= (OP_MASK_MMISUB
+ 1);
1855 printf(" else if (mmi_func == 0x29) \n");
1856 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
1857 limit
+= (OP_MASK_MMISUB
+ 1);
1860 printf(" num = (%d + mmi_func);\n",limit
);
1861 limit
+= (OP_MASK_MMI
+ 1);
1865 printf("/* Total possible switch entries: %d */\n",limit
) ;
1868 printf("#ifdef DEBUG\n");
1869 printf("printf(\"DBG: num = %%d\\n\",num);\n");
1872 printf("switch (num)\n") ;
1875 for (loop
= 0; (loop
< limit
); loop
++) {
1876 /* First check if the insn is in a requested isa# independent set,
1877 then check that the ISA number we are constructing for is
1878 valid, then if the instruction matches any of the
1879 architecture specific flags. NOTE: We allow a selected ISA of
1880 zero to be used to match all standard instructions. */
1881 unsigned int isa
= MIPS_DECODE
[loop
].isa
;
1882 if (((isa
& doarch
& MASK_ISA_INDEP
)
1883 || (((isa
& MASK_ISA
) <= doisa
)
1884 && (((isa
& MASK_ISA_DEP
) == 0) || ((isa
& MASK_ISA_DEP
) & doarch
) != 0)))
1885 && (!(MIPS_DECODE
[loop
].flags
& FP
) || ((MIPS_DECODE
[loop
].flags
& FP
) && dofp
))) {
1886 unsigned int onemask
;
1887 unsigned int zeromask
;
1888 unsigned int dontmask
;
1890 unsigned int number
;
1892 convert_bitmap(MIPS_DECODE
[loop
].bitmap
,&onemask
,&zeromask
,&dontmask
);
1894 if (!(MIPS_DECODE
[loop
].flags
& COPROC
)
1895 && ((GETDATASIZEINSN(&MIPS_DECODE
[loop
]) == DOUBLEWORD
) && !proc64
)) {
1896 fprintf(stderr
,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE
[loop
].name
);
1901 printf("/* DEBUG: onemask 0x%08X */\n",onemask
) ;
1902 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask
) ;
1903 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask
) ;
1906 switch (MIPS_DECODE
[loop
].mark
) {
1908 mask
= (OP_MASK_OP
<< OP_SH_OP
) ;
1909 number
= ((onemask
>> OP_SH_OP
) & OP_MASK_OP
) ;
1913 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
1914 number
= ((OP_MASK_OP
+ 1) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
1918 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_RT
<< OP_SH_RT
)) ;
1919 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_RT
) & OP_MASK_RT
)) ;
1923 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
1924 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
1928 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_COP1SPEC
<< OP_SH_COP1SPEC
)) ;
1929 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_COP1SPEC
) & OP_MASK_COP1SPEC
)) ;
1933 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
1934 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
)) ;
1938 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
1939 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
1940 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
1941 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
1942 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
1946 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
1947 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
1948 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
1949 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
1950 + (OP_MASK_MMISUB
+ 1)
1951 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
1955 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
1956 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
1957 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
1958 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
1959 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
1960 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
1964 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
1965 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
1966 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
1967 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
1968 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
1969 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
1973 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)) ;
1974 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
1975 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
1976 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
1977 + (OP_MASK_MMISUB
+ 1)
1978 + ((onemask
>> OP_SH_MMI
) & OP_MASK_MMI
)) ;
1982 fprintf(stderr
,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE
[loop
].mark
,loop
,MIPS_DECODE
[loop
].name
) ;
1986 printf("case %d : /* \"%s\" %s */\n",number
,MIPS_DECODE
[loop
].name
,MIPS_DECODE
[loop
].bitmap
) ;
1989 printf("/* DEBUG: mask 0x%08X */\n",mask
) ;
1990 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE
[loop
].name
);
1993 /* Check if there are any other explicit bits in the instruction: */
1994 if ((~mask
& (onemask
| zeromask
)) != 0x00000000) {
1995 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask
| zeromask
),onemask
) ;
1997 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2004 /* Get hold of the operands */
2005 /* NOTE: If we wanted to make the simulator code smaller, we
2006 * could pull these into a common sequence before we perform
2007 * the instruction decoding. However, this would affect the
2008 * performance since unnecessary field extraction would be
2009 * occurring for certain instructions.
2011 * Also we do not perform checking for multiple definitions of a
2012 * particular operand here, since they are caught by the
2013 * compilation of the produced code.
2015 build_operands(doisa
, features
, &MIPS_DECODE
[loop
]);
2019 build_instruction (doisa
, features
, 0, &MIPS_DECODE
[loop
]);
2023 printf(" break ;\n") ;
2027 printf("default : /* Unrecognised instruction */\n") ;
2028 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2029 printf(" break ;\n") ;
2032 /* Handle mips16 instructions. The switch table looks like this:
2033 0 - 31: I, RI, and RRI instructions by major.
2034 32 - 35: ISHIFT instructions by function + 32
2035 36 - 37: RRI_A instructions by function + 36
2036 38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38
2037 46 - 49: RRR instructions by function + 46
2038 50 - 81: RR instructions by minor + 50 (except for minor == 0)
2039 82 - 89: I64 and RI64 instructions by funct + 82
2040 90 - 97: jalr (RR minor 0) by y + 90
2042 printf ("else {\n");
2043 printf ("static int extendval;\n");
2044 printf ("static int have_extendval;\n");
2045 printf ("int num = ((instruction >> %d) & 0x%08X);\n",
2046 MIPS16OP_SH_OP
, MIPS16OP_MASK_OP
);
2047 printf ("switch (num)\n{\n");
2048 printf ("case 0x6: num = 32 + (instruction & 3); break;\n");
2049 printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n");
2050 printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n");
2051 printf ("case 0x1c: num = 46 + (instruction & 3); break;\n");
2052 printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n");
2053 printf (" if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n");
2054 printf (" break;\n");
2055 printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n");
2056 printf ("default: break;\n}\n");
2057 printf ("switch (num)\n{\n");
2059 for (loop
= 0; loop
< sizeof MIPS16_DECODE
/ sizeof MIPS16_DECODE
[0]; loop
++)
2064 if (! proc64
&& GETDATASIZEINSN (&MIPS16_DECODE
[loop
]) == DOUBLEWORD
)
2067 bitmap
= MIPS16_DECODE
[loop
].bitmap
;
2068 switch (MIPS16_DECODE
[loop
].mark
)
2073 num
= bitmap_val (bitmap
, 11, 5);
2076 num
= 32 + bitmap_val (bitmap
, 0, 2);
2079 num
= 36 + bitmap_val (bitmap
, 4, 1);
2084 num
= 38 + bitmap_val (bitmap
, 8, 3);
2087 num
= 46 + bitmap_val (bitmap
, 0, 2);
2093 minor
= bitmap_val (bitmap
, 0, 5);
2097 num
= 90 + bitmap_val (bitmap
, 5, 3);
2102 num
= 82 + bitmap_val (bitmap
, 8, 3);
2108 printf ("case %d: /* \"%s\" %s */\n", num
, MIPS16_DECODE
[loop
].name
,
2113 build_mips16_operands (bitmap
);
2117 /* build_instruction doesn't know about extend. */
2119 build_instruction (doisa
, features
, 1, &MIPS16_DECODE
[loop
]);
2122 printf (" extendval = ext;\n");
2123 printf (" have_extendval = 1;\n");
2128 printf (" break ;\n") ;
2131 printf ("default : /* Unrecognised instruction */\n") ;
2132 printf (" SignalException(ReservedInstruction,instruction);\n") ;
2133 printf (" break ;\n") ;
2136 printf("#endif /* simulator engine */\n");
2141 /* Output the code to execute an instruction, assuming the operands
2142 have already been extracted. */
2145 build_instruction (doisa
, features
, mips16
, insn
)
2147 unsigned int features
;
2149 const struct instruction
*insn
;
2151 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
2152 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
2153 char *regtype
= ((gprlen
== 64) ? "uword64" : "unsigned int");
2155 switch (insn
->type
) {
2156 /* TODO: To make these easier to edit and maintain, they should
2157 actually be provided as source macros (or inline functions)
2158 OUTSIDE this main switch statement. The PPC simulator has a
2159 neater scheme for describing the instruction sequences. */
2164 char *signed_basetype
= "unknown";
2165 char *unsigned_basetype
= "unknown";
2167 switch (GETDATASIZEINSN(insn
)) {
2169 signed_basetype
= "signed int";
2170 unsigned_basetype
= "unsigned int";
2173 signed_basetype
= "word64";
2174 unsigned_basetype
= "uword64";
2177 fprintf(stderr
,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZEINSN(insn
));
2181 if ((insn
->type
) == ADD
) {
2182 printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype
, unsigned_basetype
);
2183 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype
, signed_basetype
);
2184 if (insn
->flags
& OVERFLOW
) {
2185 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
2186 printf(" SignalException(IntegerOverflow);\n");
2189 if (!proc64
|| (insn
->flags
& UNSIGNED
) || (GETDATASIZEINSN(insn
) == DOUBLEWORD
))
2190 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
2191 else /* only sign-extend when placing 32bit result in 64bit processor */
2192 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
2194 printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype
, unsigned_basetype
);
2195 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype
, signed_basetype
);
2196 if (insn
->flags
& OVERFLOW
) { /* different signs => overflow if result_sign != arg_sign */
2197 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
2198 printf(" SignalException(IntegerOverflow);\n");
2201 /* UNSIGNED 32bit operations on a 64bit processor should
2202 *STILL* be sign-extended. We have cheated in the
2203 data-structure, by not marking it with UNSIGNED, and not
2204 setting OVERFLOW. */
2205 if (!proc64
|| (insn
->flags
& UNSIGNED
) || (GETDATASIZEINSN(insn
) == DOUBLEWORD
))
2206 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
2207 else /* only sign-extend when placing 32bit result in 64bit processor */
2208 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
2215 char* pipe
= (insn
->flags
& PIPE1
) ? "1" : "";
2217 if (features
& FEATURE_WARN_LOHI
) {
2218 printf(" CHECKHILO(\"Multiplication\");\n");
2221 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2222 printf(" uword64 mid;\n");
2223 printf(" uword64 midhi;\n");
2224 printf(" uword64 temp;\n");
2225 if ((insn
->flags
& UNSIGNED
) == 0)
2227 printf(" int sign = 0;\n");
2228 printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n");
2229 printf(" if (op2 < 0) { op2 = - op2; ++sign; }\n");
2231 printf(" LO%s = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n",pipe
);
2232 printf(" HI%s = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n",pipe
);
2233 printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
2234 printf(" midhi = SET64HI(WORD64LO(mid));\n");
2235 printf(" temp = (LO%s + midhi);\n",pipe
);
2236 printf(" if ((temp == midhi) ? (LO%s != 0) : (temp < midhi))\n",pipe
);
2237 printf(" HI%s += 1;\n",pipe
);
2238 printf(" HI%s += WORD64HI(mid);\n",pipe
);
2239 printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
2240 printf(" midhi = SET64HI(WORD64LO(mid));\n");
2241 printf(" LO%s = (temp + midhi);\n",pipe
);
2242 printf(" if ((LO%s == midhi) ? (temp != 0) : (LO%s < midhi))\n",pipe
,pipe
);
2243 printf(" HI%s += 1;\n",pipe
);
2244 printf(" HI%s += WORD64HI(mid);\n",pipe
);
2245 if ((insn
->flags
& UNSIGNED
) == 0)
2246 printf(" if (sign & 1) { LO%s = - LO%s; HI%s = (LO%s == 0 ? 0 : -1) - HI%s; }\n",pipe
,pipe
,pipe
,pipe
,pipe
);
2248 if (insn
->flags
& UNSIGNED
)
2249 printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
2251 printf(" uword64 temp = ((word64) op1 * (word64) op2);\n");
2252 printf(" LO%s = SIGNEXTEND((%s)WORD64LO(temp),32);\n",pipe
,regtype
);
2253 printf(" HI%s = SIGNEXTEND((%s)WORD64HI(temp),32);\n",pipe
,regtype
);
2255 if (insn
->flags
& OP3
)
2257 printf(" if ( destreg != 0 )\n");
2258 printf(" GPR[destreg] = LO%s;\n",pipe
);
2265 int boolU
= (insn
->flags
& UNSIGNED
);
2266 char* pipe
= (insn
->flags
& PIPE1
) ? "1" : "";
2268 if (features
& FEATURE_WARN_LOHI
) {
2269 printf(" CHECKHILO(\"Division\");\n");
2273 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2274 printf(" %sword64 d1 = op1;\n", (boolU
? "u" : ""));
2275 printf(" %sword64 d2 = op2;\n", (boolU
? "u" : ""));
2276 printf(" if (d2 == 0)\n");
2278 printf(" LO%s = SIGNED64 (0x8000000000000000);\n", pipe
);
2279 printf(" HI%s = 0;\n", pipe
);
2281 printf(" else if (d2 == -1 && d1 == SIGNED64 (0x8000000000000000))\n");
2283 printf(" LO%s = SIGNED64 (0x8000000000000000);\n", pipe
);
2284 printf(" HI%s = 0;\n", pipe
);
2288 printf(" LO%s = (d1 / d2);\n", pipe
);
2289 printf(" HI%s = (d1 %% d2);\n", pipe
);
2292 printf(" %sint d1 = op1;\n", (boolU
? "unsigned " : ""));
2293 printf(" %sint d2 = op2;\n", (boolU
? "unsigned " : ""));
2294 printf(" if (d2 == 0)\n");
2296 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe
);
2297 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe
);
2299 printf(" else if (d2 == -1 && d1 == 0x80000000)\n");
2301 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe
);
2302 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe
);
2306 printf(" LO%s = SIGNEXTEND((d1 / d2),32);\n", pipe
);
2307 printf(" HI%s = SIGNEXTEND((d1 %% d2),32);\n", pipe
);
2316 int datalen
= GETDATASIZEINSN(insn
);
2317 int bits
= ((datalen
== WORD
) ? 32 : 64);
2318 char *ltype
= ((datalen
== WORD
) ? "unsigned int" : "uword64");
2320 /* Check that the specified SHIFT is valid: */
2321 if ((datalen
== BYTE
) || (datalen
== HALFWORD
)) {
2322 fprintf(stderr
,"Shift \"%s\" specified with BYTE or HALFWORD\n",insn
->name
);
2325 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
2326 fprintf(stderr
,"Shift \"%s\" specified with both LEFT and RIGHT\n",insn
->name
);
2329 if (!(insn
->flags
& LEFT
) && !(insn
->flags
& RIGHT
)) {
2330 fprintf(stderr
,"Shift \"%s\" specified with neither LEFT or RIGHT\n",insn
->name
);
2333 if ((insn
->flags
& LOGICAL
) && (insn
->flags
& ARITHMETIC
)) {
2334 fprintf(stderr
,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",insn
->name
);
2337 if (!(insn
->flags
& LOGICAL
) && !(insn
->flags
& ARITHMETIC
)) {
2338 fprintf(stderr
,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",insn
->name
);
2341 if ((insn
->flags
& LEFT
) && (insn
->flags
& ARITHMETIC
)) {
2342 fprintf(stderr
,"Arithmetic LEFT shift \"%s\" specified\n",insn
->name
);
2346 /* Work around an MSC code generation bug by precomputing a value
2347 * with the sign bit set. */
2348 if (insn
->flags
& ARITHMETIC
)
2349 printf(" %s highbit = (%s)1 << %d;\n", ltype
, ltype
, bits
- 1);
2351 /* If register specified shift, then extract the relevant shift amount: */
2352 if (insn
->flags
& REG
)
2353 printf(" op1 &= 0x%02X;\n",(bits
- 1));
2355 /* If HI32 specified, then shift range is 32..63 */
2356 if (insn
->flags
& HI32
)
2357 printf(" op1 |= (1 << 5);\n");
2359 /* We do not need to perform pre-masking with 0xFFFFFFFF when
2360 dealing with 32bit shift lefts, since the sign-extension
2361 code will replace any remaining hi-bits: */
2362 if (insn
->flags
& LEFT
)
2363 printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
2365 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits
== 32) ? " & 0xFFFFFFFF" : ""));
2367 /* For ARITHMETIC shifts, we must duplicate the sign-bit. We
2368 don't do this if op1 is zero, since it is not needed and
2369 since that would cause an undefined shift of the number of
2370 bits in the type. */
2371 if (insn
->flags
& ARITHMETIC
)
2372 printf(" GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype
,bits
);
2374 /* Ensure WORD values are sign-extended into 64bit registers */
2375 if ((bits
== 32) && (gprlen
== 64))
2376 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits
);
2381 if (insn
->flags
& (HI
| LO
)) {
2382 char *regname
= ((insn
->flags
& LO
) ? "LO" : "HI");
2383 int pipe1
= (insn
->flags
& PIPE1
);
2384 if (insn
->flags
& LEFT
)
2385 printf(" GPR[destreg] = %s%s;\n",regname
,(pipe1
? "1" : ""));
2387 if (features
& FEATURE_WARN_LOHI
) {
2388 printf(" if (%s%sACCESS != 0)\n",regname
,(pipe1
? "1" : ""));
2389 printf(" sim_warning(\"MT (move-to) over-writing %s register value\");\n",regname
);
2391 printf(" %s%s = op1;\n",regname
,(pipe1
? "1" : ""));
2393 if (features
& FEATURE_WARN_LOHI
)
2394 printf(" %s%sACCESS = 3; /* 3rd instruction will be safe */\n",regname
,(pipe1
? "1" : ""));
2396 if (insn
->flags
& SHIFT16
)
2397 printf(" GPR[destreg] = (op2 << 16);\n");
2399 /* perform conditional move */
2400 if (!(insn
->flags
& EQ
)) {
2401 fprintf(stderr
,"Standard conditional %s does not have the equality flag\n",insn
->name
);
2404 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
2405 printf(" GPR[destreg] = op1;\n");
2410 printf(" SyncOperation(op1);\n");
2414 printf(" SignalException(SystemCall,instruction);\n");
2418 printf(" SignalException(BreakPoint,instruction);\n");
2423 int boolNOT
= (insn
->flags
& NOT
);
2424 int boolEQ
= (insn
->flags
& EQ
);
2425 int boolGT
= (insn
->flags
& GT
);
2426 int boolLT
= (insn
->flags
& LT
);
2427 int boolU
= (insn
->flags
& UNSIGNED
);
2429 if (boolGT
&& boolLT
) {
2430 fprintf(stderr
,"GT and LT specified for \"%s\"\n",insn
->name
);
2434 if (boolNOT
&& (boolGT
|| boolLT
)) {
2435 fprintf(stderr
,"NOT specified with GT or LT specified for \"%s\"\n",insn
->name
);
2439 printf(" if ((%sword64)op1 ",(boolU
? "u" : ""));
2440 printf("%c%s",(boolNOT
? '!' : (boolLT
? '<' : (boolGT
? '>' : '='))),(boolEQ
? "=" : ""));
2441 printf(" (%sword64)op2)\n",(boolU
? "u" : ""));
2442 printf(" SignalException(Trap,instruction);\n");
2448 int boolU
= (insn
->flags
& UNSIGNED
);
2450 if (!(insn
->flags
& LT
)) {
2451 fprintf(stderr
,"Set instruction without LT specified \"%s\"\n",insn
->name
);
2455 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU
? "u" : ""),(boolU
? "u" : ""));
2456 printf(" GPR[destreg] = 1;\n");
2458 printf(" GPR[destreg] = 0;\n");
2463 printf(" GPR[destreg] = (op1 & op2);\n");
2467 /* The default mips16 nop instruction does an or to register
2468 zero; catch that case, so that we don't get useless warnings
2469 from the simulator. */
2471 printf (" if (destreg != 0)\n");
2472 printf(" GPR[destreg] = %s(op1 | op2);\n",((insn
->flags
& NOT
) ? "~" : ""));
2476 printf(" GPR[destreg] = (op1 ^ op2);\n");
2480 printf(" decode_coproc(instruction);\n");
2484 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
2485 /* The virtual address is translated to a physical address using the TLB */
2486 /* The hint specifies a cache operation for that address */
2487 printf(" uword64 vaddr = (op1 + offset);\n");
2488 printf(" uword64 paddr;\n");
2489 printf(" int uncached;\n");
2490 /* NOTE: We are assuming that the AddressTranslation is a load: */
2491 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2492 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
2495 case MADD16
: /* VR4100 specific multiply-add instructions */
2496 /* Some of this code is shared with the standard multiply
2497 routines, so an effort should be made to merge where
2499 if (features
& FEATURE_WARN_LOHI
) {
2500 printf(" CHECKHILO(\"Multiply-Add\");\n");
2502 if (features
& FEATURE_WARN_RESULT
) {
2503 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
2504 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
2505 printf(" sim_warning(\"MADD16 operation with non-16bit operands\");\n");
2508 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
2509 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2510 printf(" LO = LO + temp;\n");
2512 printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
2513 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype
);
2514 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype
);
2519 case RSVD
: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
2521 printf(" if (CoProcPresent(3))\n");
2522 printf(" SignalException(CoProcessorUnusable);\n");
2525 printf(" SignalException(ReservedInstruction,instruction);\n");
2529 if (insn
->flags
& LINK
) {
2530 if (!(insn
->flags
& REG
))
2531 printf(" int destreg = 31;\n");
2532 printf(" GPR[destreg] = (PC + %d); /* NOTE: The PC is already %d ahead within the simulator */\n",
2533 mips16
? 2 : 4, mips16
? 2 : 4);
2536 if (insn
->flags
& NOT
)
2537 printf(" op1 ^= 1;\n");
2539 printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n");
2540 printf(" so we just truncate it to 32 bits here. */\n");
2541 printf(" op1 = WORD64LO(op1);\n");
2542 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
2543 printf(" DSPC = op1;\n");
2544 if ((insn
->flags
& LINK
)
2545 && ! (insn
->flags
& REG
))
2546 printf(" JALDELAYSLOT();\n");
2548 printf(" DELAYSLOT();\n");
2551 case BRANCH
: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
2552 if (insn
->flags
& FP
) {
2554 printf(" if (condition_code != 0)\n");
2555 printf(" SignalException(ReservedInstruction,instruction);\n");
2556 printf(" else {\n");
2558 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
2559 printf(" int condition = (%s == boolean);\n",((doisa
< 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
2561 if ((insn
->flags
& NOT
) && !(insn
->flags
& EQ
)) {
2562 fprintf(stderr
,"NOT specified when not EQ in \"%s\"\n",insn
->name
);
2565 if ((insn
->flags
& NOT
) && (insn
->flags
& (GT
| LT
))) {
2566 fprintf(stderr
,"NOT specified with GT or LT in \"%s\"\n",insn
->name
);
2570 if (insn
->flags
& GT
)
2571 printf(" int condition = (op1 >%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
2573 if (insn
->flags
& LT
)
2574 printf(" int condition = (op1 <%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
2576 if (insn
->flags
& EQ
)
2577 printf(" int condition = (op1 %c= op2);\n",((insn
->flags
& NOT
) ? '!' : '='));
2580 if (insn
->flags
& LINK
) {
2581 if (features
& FEATURE_WARN_R31
) {
2582 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS
,OP_MASK_RS
);
2583 printf(" sim_warning(\"Branch with link using r31 as source operand\");\n");
2585 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
2589 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
2590 printf(" if (condition) {\n");
2591 printf(" DSPC = (PC + offset);\n");
2592 printf(" DELAYSLOT();\n");
2595 /* No delayed slots for mips16 branches. */
2596 printf(" if (condition)\n");
2597 printf(" PC = PC + offset;\n");
2599 if ((insn
->flags
& FP
) && (doisa
!= 1)) {
2600 printf(" else if (likely) {\n");
2601 printf(" NULLIFY();\n");
2603 } else if (insn
->flags
& LIKELY
) {
2605 printf(" NULLIFY();\n");
2607 if ((insn
->flags
& FP
) && (doisa
< 4))
2611 case PREFETCH
: /* The beginning is shared with normal load operations */
2615 int isload
= ((insn
->type
== LOAD
) || (insn
->type
== PREFETCH
));
2617 char *accesslength
= "<UNKNOWN>";
2619 switch (GETDATASIZEINSN(insn
)) {
2622 accesslength
= "AccessLength_BYTE";
2627 accesslength
= "AccessLength_HALFWORD";
2632 accesslength
= "AccessLength_WORD";
2637 accesslength
= "AccessLength_DOUBLEWORD";
2642 accesslength
= "AccessLength_QUADWORD";
2646 if (insn
->flags
& REG
)
2647 printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
2649 printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
2650 printf(" uword64 paddr;\n");
2651 printf(" int uncached;\n");
2653 /* The following check should only occur on normal (non-shifted) memory loads */
2654 if ((datalen
!= 1) && !(insn
->flags
& (LEFT
| RIGHT
))) {
2655 printf(" if ((vaddr & %d) != 0)\n",(datalen
- 1));
2656 printf(" SignalException(%s);\n",(isload
? "AddressLoad" : "AddressStore"));
2661 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload
? "isLOAD" : "isSTORE"));
2663 if (insn
->type
== PREFETCH
)
2664 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
2667 printf(" uword64 memval = 0;\n");
2668 printf(" uword64 memval1 = 0;\n");
2670 if ((insn
->flags
& COPROC
) && ((datalen
!= 4) && (datalen
!= 8))) {
2671 fprintf(stderr
,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
2675 if (insn
->flags
& (LEFT
| RIGHT
)) {
2676 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
2677 fprintf(stderr
,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",insn
->name
);
2684 fprintf(stderr
,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn
->name
);
2687 /* fall through to... */
2690 printf(" uword64 mask = %d;\n",((datalen
== 8) ? 0x7 : 0x3));
2691 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
2692 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
2693 printf(" int byte;\n");
2694 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
2695 printf(" byte = ((vaddr & mask) ^ bigend);\n");
2696 printf(" if (%s!ByteSwapMem)\n",((insn
->flags
& LEFT
) ? "!" : ""));
2697 printf(" paddr &= ~mask;\n");
2700 if (insn
->flags
& LEFT
)
2702 printf(" LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
2706 printf(" LoadMemory(&memval,&memval1,uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen
- 1));
2710 if (insn
->flags
& LEFT
) {
2712 /* For WORD transfers work out if the value will
2713 be in the top or bottom of the DOUBLEWORD
2716 build_endian_shift(proc64
,datalen
,2,s_right
,32);
2718 if (proc64
&& (datalen
== 4)) {
2719 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2720 printf(" memval >>= 32;\n");
2724 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen
- 1),(datalen
- 1));
2725 if (proc64
&& (datalen
== 4))
2726 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2727 } else { /* store */
2728 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen
- 1));
2730 build_endian_shift(proc64
,datalen
,2,s_left
,32);
2732 /* TODO: This is duplicated in the LOAD code
2733 above - and the RIGHT LOAD and STORE code
2734 below. It should be merged if possible. */
2735 if (proc64
&& (datalen
== 4)) {
2736 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2737 printf(" memval <<= 32;\n");
2741 printf(" StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);\n");
2743 } else { /* RIGHT */
2746 build_endian_shift(proc64
,datalen
,2,s_right
,32);
2748 if (proc64
&& (datalen
== 4)) {
2749 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2750 printf(" memval >>= 32;\n");
2755 printf(" uword64 srcmask;\n");
2756 /* All of this extra code is just a bodge
2757 required because some hosts don't allow
2758 ((v) << 64). The SPARC just leaves the (v)
2759 value un-touched. */
2760 printf(" if (byte == 0)\n");
2761 printf(" srcmask = 0;\n");
2763 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen
);
2764 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n");
2766 if (proc64
&& (datalen
== 4))
2767 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2768 } else { /* store */
2769 printf(" memval = ((uword64) op2 << (byte * 8));\n");
2770 build_endian_shift(proc64
,datalen
,2,s_left
,32);
2771 printf(" StoreMemory(uncached,(%s - byte),memval,memval1,paddr,vaddr,isREAL);\n",accesslength
);
2778 fprintf(stderr
,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
2781 } else { /* normal memory transfer */
2782 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
2783 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
2785 /* TODO: The R4000 documentation states that a LWU
2786 instruction executed when in a 32bit processor mode
2787 should cause a ReservedInstruction exception. This
2788 will mean adding a run-time check into the code
2793 #if 1 /* see the comments attached to LOADDRMASK above */
2794 printf(" uword64 mask = 0x7;\n");
2796 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2798 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
2799 printf(" unsigned int reverse UNUSED = (ReverseEndian ? (mask >> shift) : 0);\n");
2800 printf(" unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0);\n");
2801 printf(" unsigned int byte UNUSED;\n");
2803 /* TODO: This should really also check for 32bit world performing 32bit access */
2804 if (datalen
< 8) /* not for DOUBLEWORD or QUADWORD*/
2805 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2807 printf(" LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength
);
2809 /* The following will only make sense if the
2810 "LoadMemory" above returns a DOUBLEWORD entity */
2811 if (datalen
< 8) { /* not for DOUBLEWORD or QUADWORD*/
2823 valmask
= 0xFFFFFFFF;
2827 fprintf(stderr
,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen
,insn
->name
);
2830 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2831 /* NOTE: The R4000 user manual has the COP_LW
2832 occuring in the same cycle as the rest of the
2833 instruction, yet the MIPS IV shows the operation
2834 happening on the next cycle. To keep the simulator
2835 simple, this code follows the R4000
2836 manual. Experimentation with a silicon
2837 implementation will be needed to ascertain the
2838 correct operation. */
2839 if (insn
->flags
& COPROC
)
2840 printf(" COP_LW(%s,destreg,(unsigned int)",
2841 ((insn
->flags
& REG
)
2843 : "((instruction >> 26) & 0x3)"));
2845 printf(" GPR[destreg] = (");
2847 if (insn
->flags
& SIGNEXTEND
)
2848 printf("SIGNEXTEND(");
2849 printf("((memval >> (8 * byte)) & 0x%08X)",valmask
);
2850 if (insn
->flags
& SIGNEXTEND
)
2851 printf(",%d)",(datalen
* 8));
2854 if (insn
->flags
& COPROC
)
2855 printf(" COP_LD(%s,destreg,memval);;\n",
2856 ((insn
->flags
& REG
)
2858 : "((instruction >> 26) & 0x3)"));
2861 printf(" GPR[destreg] = memval;\n");
2863 printf(" GPR1[destreg] = memval1;\n");
2866 } else { /* store operation */
2867 if ((datalen
== 1) || (datalen
== 2)) {
2869 #if 1 /* see the comments attached to LOADDRMASK above */
2870 printf(" uword64 mask = 0x7;\n");
2872 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2874 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
2875 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
2876 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
2877 printf(" unsigned int byte;\n");
2879 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2880 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2881 printf(" memval = ((uword64) op2 << (8 * byte));\n");
2883 if (datalen
== 4) { /* SC and SW */
2884 #if 1 /* see the comments attached to LOADDRMASK above */
2885 printf(" uword64 mask = 0x7;\n");
2887 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2889 printf(" unsigned int byte;\n");
2890 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
2891 printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
2892 if (insn
->flags
& COPROC
)
2893 printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n",
2894 ((insn
->flags
& REG
)
2896 : "((instruction >> 26) & 0x3)"),
2897 ((insn
->flags
& FP
) ? "fs" : "destreg"));
2899 printf(" memval = ((uword64) op2 << (8 * byte));\n");
2900 } else if (datalen
<= 8) { /* SD and SCD */
2901 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
2902 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
2905 if (insn
->flags
& COPROC
)
2906 printf(" memval = (uword64)COP_SD(%s,%s);\n",
2907 ((insn
->flags
& REG
)
2909 : "((instruction >> 26) & 0x3)"),
2910 ((insn
->flags
& FP
) ? "fs" : "destreg"));
2912 printf(" memval = op2;\n");
2913 } else { /* wider than 8 */
2914 if (insn
->flags
& COPROC
) {
2915 fprintf(stderr
,"COPROC not available for 128 bit operations \"%s\"\n",insn
->name
);
2918 printf(" memval = rt_reg;\n");
2919 printf(" memval1 = rt_reg1;\n");
2922 if (insn
->flags
& ATOMIC
)
2923 printf(" if (LLBIT)\n");
2926 printf(" StoreMemory(uncached,%s,memval,memval1,paddr,vaddr,isREAL);\n",accesslength
);
2930 if (insn
->flags
& ATOMIC
) {
2931 if ((datalen
!= 4) && (datalen
!= 8)) {
2932 fprintf(stderr
,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",insn
->name
);
2936 printf(" LLBIT = 1;\n");
2938 /* The documentation states that:
2940 SC *WILL* fail if coherent store into the same
2941 block occurs, or if an exception occurs between
2942 the LL and SC instructions.
2944 SC *MAY* fail if a load, store or prefetch is
2945 executed on the processor (VR4300 doesn't seem
2946 to), or if the instructions between the LL and
2947 SC are not in a 2048byte contiguous VM range.
2949 SC *MUST* have been preceded by an LL
2950 (i.e. LLBIT will be set), and it must use the
2951 same Vaddr, Paddr and cache-coherence algorithm
2952 as the LL (which means we should store this
2953 information from the load-conditional).
2955 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT
,OP_MASK_RT
);
2966 /* This code could be merged with the PREFIX generation above: */
2967 printf(" uword64 vaddr = ((uword64)op1 + (uword64)op2);\n");
2968 printf(" uword64 paddr;\n");
2969 printf(" int uncached;\n");
2970 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2971 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
2975 if (insn
->flags
& CONTROL
) {
2976 /* The following "magic" of interpreting the FP
2977 control-register number would not be needed if we were not
2978 trying to match our internal register numbers with those
2980 printf(" if (to) {\n");
2982 printf(" if (fs == 0) {\n");
2983 printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
2984 printf(" } else if (fs == 31) {\n");
2985 printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
2986 printf(" } /* else NOP */\n");
2987 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
2989 printf(" if (fs == 0) {\n");
2990 printf(" FCR0 = WORD64LO(GPR[ft]);\n");
2991 printf(" } else if (fs == 31) {\n");
2992 printf(" FCR31 = WORD64LO(GPR[ft]);\n");
2993 printf(" } /* else NOP */\n");
2994 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
2996 printf(" } else { /* control from */\n");
2998 printf(" if (fs == 0) {\n");
2999 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
3000 printf(" } else if (fs == 31) {\n");
3001 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
3002 printf(" } /* else NOP */\n");
3004 printf(" if (fs == 0) {\n");
3005 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
3006 printf(" } else if (fs == 31) {\n");
3007 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
3008 printf(" } /* else NOP */\n");
3012 printf(" if (to) {\n");
3013 if (GETDATASIZEINSN(insn
) == WORD
) {
3015 printf(" if (SizeFGR() == 64) {\n");
3016 printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
3017 printf(" } else { \n");
3018 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3021 printf(" if (SizeFGR() == 64)\n");
3022 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
3024 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3025 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3027 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
3029 printf(" if (SizeFGR() == 64) {\n");
3030 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
3031 printf(" } else\n");
3032 printf(" if ((fs & 0x1) == 0)\n");
3034 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
3035 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3037 if (features
& FEATURE_WARN_RESULT
) {
3039 printf(" UndefinedResult();\n");
3042 printf(" if (SizeFGR() == 64) {\n");
3043 printf(" FGR[fs] = GPR[ft];\n");
3044 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3045 printf(" } else\n");
3046 printf(" if ((fs & 0x1) == 0)\n");
3048 printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
3049 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3050 printf(" fpr_state[fs + 1] = fmt_uninterpreted;\n");
3051 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3053 if (features
& FEATURE_WARN_RESULT
) {
3055 printf(" UndefinedResult();\n");
3059 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
3062 printf(" } else {\n");
3063 if (GETDATASIZEINSN(insn
) == WORD
) {
3064 if (doisa
< 4) /* write-back occurs in next cycle */
3065 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
3066 else /* in this cycle */
3067 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
3068 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
3070 printf(" if (SizeFGR() == 64) {\n");
3071 printf(" PENDING_FILL(ft,FGR[fs]);\n");
3072 printf(" } else\n");
3073 printf(" if ((fs & 0x1) == 0) {\n");
3074 printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
3075 printf(" } else {\n");
3076 printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3077 if (features
& FEATURE_WARN_RESULT
)
3078 printf(" UndefinedResult();\n");
3081 printf(" if (SizeFGR() == 64)\n");
3082 printf(" GPR[ft] = FGR[fs];\n");
3084 printf(" if ((fs & 0x1) == 0)\n");
3085 printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
3086 printf(" else {\n");
3087 printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3088 if (features
& FEATURE_WARN_RESULT
)
3089 printf(" UndefinedResult();\n");
3093 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
3101 if (insn
->flags
& CONDITIONAL
) {
3102 if (insn
->flags
& INTEGER
) { /* moving GPR - testing FGR */
3103 printf(" if (GETFCC(condition_code) == boolean)\n");
3104 printf(" GPR[destreg] = op1;\n");
3106 if (insn
->flags
& EQ
) /* moving FGR - testing GPR */
3107 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
3109 printf(" if (GETFCC(condition_code) == boolean)\n");
3110 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3112 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
3114 } else { /* simple MOVE */
3115 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3120 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3121 printf(" SignalException(ReservedInstruction,instruction);\n");
3123 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
3127 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3128 printf(" SignalException(ReservedInstruction,instruction);\n");
3130 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
3134 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3135 printf(" SignalException(ReservedInstruction,instruction);\n");
3137 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3141 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3142 printf(" SignalException(ReservedInstruction,instruction);\n");
3144 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3148 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3149 printf(" SignalException(ReservedInstruction,instruction);\n");
3151 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
3155 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3156 printf(" SignalException(ReservedInstruction,instruction);\n");
3158 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((insn
->flags
& RECIP
) ? "Recip" : ""));
3169 switch (insn
->type
) {
3171 op
= "FP_RM_TOPINF";
3174 op
= "FP_RM_TOMINF";
3177 op
= "FP_RM_TOZERO";
3180 op
= "FP_RM_NEAREST";
3183 fprintf(stderr
,"Error: Handled missing for FP reason code %d\n",insn
->type
);
3187 switch (GETDATASIZEINSN(insn
)) {
3195 fprintf(stderr
,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op
);
3198 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3199 printf(" SignalException(ReservedInstruction,instruction);\n");
3201 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type
,op
,type
);
3208 switch (GETDATASIZEINSN(insn
)) {
3210 type
= "fmt_single";
3213 type
= "fmt_double";
3222 fprintf(stderr
,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn
));
3226 /* Not all combinations of conversion are valid at the
3227 moment: When converting to a fixed-point format, only
3228 floating-point sources are allowed. */
3229 printf(" if ((format == %s) | %s)\n",type
,((insn
->flags
& FIXED
) ? "((format == fmt_long) || (format == fmt_word))": "0"));
3230 printf(" SignalException(ReservedInstruction,instruction);\n");
3232 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type
,type
);
3237 if (insn
->flags
& MULTIPLY
) {
3239 switch (GETDATASIZEINSN(insn
)) {
3241 type
= "fmt_single";
3244 type
= "fmt_double";
3247 fprintf(stderr
,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn
));
3250 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
);
3252 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3253 printf(" SignalException(ReservedInstruction,instruction);\n");
3255 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3260 if (insn
->flags
& MULTIPLY
) {
3262 switch (GETDATASIZEINSN(insn
)) {
3264 type
= "fmt_single";
3267 type
= "fmt_double";
3270 fprintf(stderr
,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn
));
3273 if (insn
->flags
& NOT
)
3274 printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
3275 type
, type
, type
, type
, type
, type
, type
);
3277 printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
3278 type
, type
, type
, type
, type
, type
);
3280 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3281 printf(" SignalException(ReservedInstruction,instruction);\n");
3283 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3288 /* For the MIPS I,II or III there *MUST* be at least one
3289 instruction between the compare that sets a condition code
3290 and the branch that tests it. NOTE: However the hardware
3291 does not detect this condition. */
3292 /* Explicitly limit the operation to S and D formats: */
3293 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3294 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3295 printf(" else {\n");
3297 printf(" if (condition_code != 0)\n");
3298 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3302 printf(" int ignore = 0;\n");
3303 printf(" int less = 0;\n");
3304 printf(" int equal = 0;\n");
3305 printf(" int unordered = 1;\n");
3306 printf(" uword64 ofs = ValueFPR(fs,format);\n");
3307 printf(" uword64 oft = ValueFPR(ft,format);\n");
3308 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
3309 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
3310 printf(" FCSR |= FP_CAUSE(IO);\n");
3311 printf(" SignalException(FPE);\n");
3312 printf(" ignore = 1;\n");
3314 printf(" } else {\n");
3315 printf(" less = Less(ofs,oft,format);\n");
3316 printf(" equal = Equal(ofs,oft,format);\n");
3317 printf(" unordered = 0;\n");
3319 printf(" if (!ignore) {\n");
3320 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
3321 printf(" SETFCC(condition_code,condition);\n");
3329 char* pipeline
= (insn
->flags
& PIPE1
) ? "1" : "";
3330 int notsigned
= (insn
->flags
& UNSIGNED
);
3331 char* prodtype
= notsigned
? "uword64" : "word64";
3333 printf("%s prod = (%s)WORD64(WORD64LO(HI%s),WORD64LO(LO%s)) + ((%s)%s(op1%s) * (%s)%s(op2%s));\n",
3334 prodtype
, prodtype
, pipeline
, pipeline
,
3335 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32"),
3336 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32")
3338 printf("LO%s = SIGNEXTEND(prod,32);\n", pipeline
);
3339 printf("HI%s = SIGNEXTEND( WORD64HI(prod), 32);\n", pipeline
);
3340 printf("if( destreg != 0 ) GPR[destreg] = LO%s;\n", pipeline
);
3344 /* start-sanitize-r5900 */
3347 if (insn
->flags
& TO
)
3348 printf("SA = op1;\n");
3350 printf("GPR[destreg] = SA;\n");
3355 printf("SA = ((op1 & 0xF) ^ (op2 & 0xF)) * 8;\n");
3359 printf("SA = ((op1 & 0x7) ^ (op2 & 0x7)) * 16;\n");
3363 printf("int bytes = (SA / 8) %% 16;\n"); /* mod 16 to avoid garbage */
3364 printf("if (SA %% 8)\n");
3365 printf(" SignalException(ReservedInstruction,instruction);\n");
3368 printf(" int i;\n");
3369 printf(" for(i=0;i<(16-bytes);i++)\n");
3370 printf(" GPR_SB(destreg,i) = RT_SB(bytes+i);\n");
3371 printf(" for(;i<16;i++)\n");
3372 printf(" GPR_SB(destreg,i) = RS_SB(i-(16-bytes));\n");
3378 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3379 char* name
= name_for_data_len( insn
);
3380 char* letter
= letter_for_data_len( insn
);
3388 if ( insn
->flags
& UNSIGNED
)
3390 tmptype
= type_for_data_len( insn
, 0/*unsigned*/ );
3392 maximum
= umax_for_data_len( insn
);
3393 maxsat
= (insn
->flags
& SUBTRACT
) ? "0" : maximum
;
3396 else if ( insn
->flags
& SATURATE
)
3398 tmptype
= type_for_data_len( insn
, 1/*signed*/ );
3400 maximum
= max_for_data_len( insn
);
3402 minimum
= min_for_data_len( insn
);
3406 tmptype
= type_for_data_len( insn
, 1/*signed*/ );
3413 printf(" int i;\n");
3414 printf(" for (i=0; i < %sS_IN_MMI_REGS; i++)\n", name
);
3416 printf(" %s s = RS_%s%s(i);\n", tmptype
, signletter
, letter
);
3417 printf(" %s t = RT_%s%s(i);\n", tmptype
, signletter
, letter
);
3418 printf(" %s r = s %s t;\n", tmptype
, op
);
3421 printf(" if (r > %s)\n", maximum
);
3422 printf(" GPR_%s%s(destreg,i) = %s;\n", signletter
, letter
, maxsat
);
3425 printf(" else if (r < %s)\n", minimum
);
3426 printf(" GPR_%s%s(destreg,i) = %s;\n", signletter
, letter
, minimum
);
3431 printf(" GPR_%s%s(destreg,i) = r;\n", signletter
, letter
);
3439 if ( insn
->flags
& SUBTRACT
)
3441 else if ( insn
->flags
& ADDITION
)
3446 printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op
);
3447 printf(" LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op
);
3448 printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op
);
3449 printf(" HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op
);
3450 printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op
);
3451 printf(" LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op
);
3452 printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op
);
3453 printf(" HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op
);
3460 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3461 char* prodtype
= (insn
->flags
& UNSIGNED
) ? "unsigned64" : "signed64";
3462 char* constructor
= (insn
->flags
& UNSIGNED
) ? "UWORD64" : "WORD64";
3464 if ( insn
->flags
& SUBTRACT
)
3467 printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype
, constructor
);
3468 printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype
, constructor
);
3470 else if ( insn
->flags
& ADDITION
)
3473 printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype
, constructor
);
3474 printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype
, constructor
);
3479 printf(" %s sum0 = 0;\n", prodtype
);
3480 printf(" %s sum1 = 0;\n", prodtype
);
3483 printf(" %s prod0 = (%s)RS_%sW(0) * (%s)RT_%sW(0);\n", prodtype
, prodtype
, sign
, prodtype
, sign
);
3484 printf(" %s prod1 = (%s)RS_%sW(2) * (%s)RT_%sW(2);\n", prodtype
, prodtype
, sign
, prodtype
, sign
);
3486 printf(" sum0 %s= prod0;\n", op
);
3487 printf(" sum1 %s= prod1;\n", op
);
3489 printf(" GPR_%sD(destreg,0) = sum0;\n", sign
);
3490 printf(" GPR_%sD(destreg,1) = sum1;\n", sign
);
3492 printf(" LO = SIGNEXTEND( sum0, 32 );\n");
3493 printf(" HI = SIGNEXTEND( WORD64HI(sum0), 32 );\n");
3494 printf(" LO1 = SIGNEXTEND( sum1, 32 );\n");
3495 printf(" HI1 = SIGNEXTEND( WORD64HI(sum1), 32 );\n");
3501 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3503 for (i
= 0; i
< 2; i
++)
3505 char hi
= (i
== 0 ? ' ' : '1');
3507 if (! (insn
->flags
& UNSIGNED
))
3509 printf("if (RT_SW(%d) == -1)\n", d
);
3511 printf(" LO%c = -RS_%sW(%d);\n", hi
, sign
, d
);
3512 printf(" HI%c = 0;\n", hi
);
3513 printf(" }\nelse ");
3515 printf("if (RT_UW(%d) != 0)\n", d
);
3517 printf(" LO%c = (signed32)(RS_%sW(%d) / RT_%sW(%d));\n", hi
, sign
, d
, sign
, d
);
3518 printf(" HI%c = (signed32)(RS_%sW(%d) %% RT_%sW(%d));\n", hi
, sign
, d
, sign
, d
);
3525 printf("signed32 devisor = RT_SH(0);\n");
3526 printf("if (devisor == -1)\n");
3528 printf(" LO_SW(0) = -RS_SW(0);\n");
3529 printf(" HI_SW(0) = 0;\n");
3530 printf(" LO_SW(1) = -RS_SW(1);\n");
3531 printf(" HI_SW(1) = 0;\n");
3532 printf(" LO_SW(2) = -RS_SW(2);\n");
3533 printf(" HI_SW(2) = 0;\n");
3534 printf(" LO_SW(3) = -RS_SW(3);\n");
3535 printf(" HI_SW(3) = 0;\n");
3537 printf("else if (devisor != 0)\n");
3539 printf(" LO_SW(0) = RS_SW(0) / devisor;\n");
3540 printf(" HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n");
3541 printf(" LO_SW(1) = RS_SW(1) / devisor;\n");
3542 printf(" HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n");
3543 printf(" LO_SW(2) = RS_SW(2) / devisor;\n");
3544 printf(" HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n");
3545 printf(" LO_SW(3) = RS_SW(3) / devisor;\n");
3546 printf(" HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n");
3552 printf("for(i=0;i<HALFWORDS_IN_MMI_REGS/2;i++)\n");
3553 printf(" GPR_SH(destreg,i) = RS_SH(i) - RT_SH(i);\n");
3554 printf("for(;i<HALFWORDS_IN_MMI_REGS;i++)\n");
3555 printf(" GPR_SH(destreg,i) = RS_SH(i) + RT_SH(i);\n");
3560 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3561 printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op
);
3562 printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op
);
3563 printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op
);
3564 printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op
);
3570 char* name
= name_for_data_len( insn
);
3571 char* letter
= letter_for_data_len( insn
);
3572 char* bits
= bits_for_data_len( insn
);
3573 char* shift
= (insn
->flags
& RIGHT
) ? ">>" : "<<";
3574 char* sign
= (insn
->flags
& ARITHMETIC
) ? "S" : "U";
3576 printf("int shift_by = op1 & (%s-1);\n", bits
);
3578 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3579 printf(" GPR_%s%s(destreg,i) = ", sign
, letter
);
3580 if ( insn
->flags
& ARITHMETIC
)
3581 printf("SIGNEXTEND( ");
3582 printf("(RT_%s%s(i) %s shift_by)", sign
, letter
, shift
);
3583 if ( insn
->flags
& ARITHMETIC
)
3584 printf(", (%s-shift_by) )", bits
);
3590 printf("int s0 = (RS_UB(0) & 0x1F);\n");
3591 printf("int s1 = (RS_UB(8) & 0x1F);\n");
3592 printf("signed32 temp0 = RT_UW(0) << s0;\n");
3593 printf("signed32 temp1 = RT_UW(2) << s1;\n");
3594 printf("GPR_SD(destreg,0) = (signed64)temp0;\n");
3595 printf("GPR_SD(destreg,1) = (signed64)temp1;\n");
3599 printf("GPR_UD(destreg,0) = SIGNEXTEND ( RT_UW(0) >> (RS_UB(0) & 0x1F), 31);\n");
3600 printf("GPR_UD(destreg,1) = SIGNEXTEND ( RT_UW(2) >> (RS_UB(8) & 0x1F), 31);\n");
3604 printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n");
3605 printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n");
3613 if ( GET_OP_FROM_INSN(insn
) == POP_AND
)
3618 else if ( GET_OP_FROM_INSN(insn
) == POP_OR
)
3623 else if ( GET_OP_FROM_INSN(insn
) == POP_NOR
)
3628 else if ( GET_OP_FROM_INSN(insn
) == POP_XOR
)
3635 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3636 printf(" GPR_UW(destreg,i) = %s(RS_UW(i) %s RT_UW(i));\n", op2
, op1
);
3642 char* name
= name_for_data_len( insn
);
3643 char* letter
= letter_for_data_len( insn
);
3644 char* maximum
= umax_for_data_len( insn
);
3645 char* op
= (insn
->flags
& GT
) ? ">" : "==";
3648 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3650 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n",
3651 letter
, op
, letter
, letter
, maximum
);
3652 printf(" else GPR_S%s(destreg,i) = 0;\n", letter
);
3659 char* name
= name_for_data_len( insn
);
3660 char* letter
= letter_for_data_len( insn
);
3661 char* op
= (insn
->flags
& GT
) ? ">" : "<";
3664 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3666 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n",
3667 letter
, op
, letter
, letter
, letter
);
3668 printf(" else GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
3675 char* name
= name_for_data_len( insn
);
3676 char* letter
= letter_for_data_len( insn
);
3677 char* min
= min_for_data_len( insn
);
3678 char* max
= max_for_data_len( insn
);
3681 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3683 printf(" if (RT_S%s(i) >= 0)\n", letter
);
3684 printf(" GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
3685 printf(" else if (RT_S%s(i) == %s)\n", letter
, min
);
3686 printf(" GPR_S%s(destreg,i) = %s;\n", letter
, max
);
3688 printf(" GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter
, letter
);
3694 printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n");
3695 printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n");
3699 printf("GPR_UD(destreg,0) = RT_UD(0);\n");
3700 printf("GPR_UD(destreg,1) = RS_UD(0);\n");
3704 printf("GPR_UD(destreg,0) = RS_UD(1);\n");
3705 printf("GPR_UD(destreg,1) = RT_UD(1);\n");
3709 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3710 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3711 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3712 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3713 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3714 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3715 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3716 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3720 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3721 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3722 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3723 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3727 printf("GPR_UH(destreg,0) = RT_UH(2);\n");
3728 printf("GPR_UH(destreg,1) = RT_UH(1);\n");
3729 printf("GPR_UH(destreg,2) = RT_UH(0);\n");
3730 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3731 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3732 printf("GPR_UH(destreg,5) = RT_UH(5);\n");
3733 printf("GPR_UH(destreg,6) = RT_UH(4);\n");
3734 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3738 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3739 printf("GPR_UW(destreg,1) = RT_UW(1);\n");
3740 printf("GPR_UW(destreg,2) = RT_UW(0);\n");
3741 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3745 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3746 printf("GPR_UB(destreg,1) = RS_UB(0);\n");
3747 printf("GPR_UB(destreg,2) = RT_UB(1);\n");
3748 printf("GPR_UB(destreg,3) = RS_UB(1);\n");
3749 printf("GPR_UB(destreg,4) = RT_UB(2);\n");
3750 printf("GPR_UB(destreg,5) = RS_UB(2);\n");
3751 printf("GPR_UB(destreg,6) = RT_UB(3);\n");
3752 printf("GPR_UB(destreg,7) = RS_UB(3);\n");
3753 printf("GPR_UB(destreg,8) = RT_UB(4);\n");
3754 printf("GPR_UB(destreg,9) = RS_UB(4);\n");
3755 printf("GPR_UB(destreg,10) = RT_UB(5);\n");
3756 printf("GPR_UB(destreg,11) = RS_UB(5);\n");
3757 printf("GPR_UB(destreg,12) = RT_UB(6);\n");
3758 printf("GPR_UB(destreg,13) = RS_UB(6);\n");
3759 printf("GPR_UB(destreg,14) = RT_UB(7);\n");
3760 printf("GPR_UB(destreg,15) = RS_UB(7);\n");
3764 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3765 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3766 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3767 printf("GPR_UH(destreg,3) = RS_UH(1);\n");
3768 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3769 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3770 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3771 printf("GPR_UH(destreg,7) = RS_UH(3);\n");
3775 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3776 printf("GPR_UW(destreg,1) = RS_UW(0);\n");
3777 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3778 printf("GPR_UW(destreg,3) = RS_UW(1);\n");
3782 printf("GPR_UB(destreg,0) = RT_UB(8);\n");
3783 printf("GPR_UB(destreg,1) = RS_UB(8);\n");
3784 printf("GPR_UB(destreg,2) = RT_UB(9);\n");
3785 printf("GPR_UB(destreg,3) = RS_UB(9);\n");
3786 printf("GPR_UB(destreg,4) = RT_UB(10);\n");
3787 printf("GPR_UB(destreg,5) = RS_UB(10);\n");
3788 printf("GPR_UB(destreg,6) = RT_UB(11);\n");
3789 printf("GPR_UB(destreg,7) = RS_UB(11);\n");
3790 printf("GPR_UB(destreg,8) = RT_UB(12);\n");
3791 printf("GPR_UB(destreg,9) = RS_UB(12);\n");
3792 printf("GPR_UB(destreg,10) = RT_UB(13);\n");
3793 printf("GPR_UB(destreg,11) = RS_UB(13);\n");
3794 printf("GPR_UB(destreg,12) = RT_UB(14);\n");
3795 printf("GPR_UB(destreg,13) = RS_UB(14);\n");
3796 printf("GPR_UB(destreg,14) = RT_UB(15);\n");
3797 printf("GPR_UB(destreg,15) = RS_UB(15);\n");
3801 printf("GPR_UH(destreg,0) = RT_UH(4);\n");
3802 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3803 printf("GPR_UH(destreg,2) = RT_UH(5);\n");
3804 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3805 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3806 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3807 printf("GPR_UH(destreg,6) = RT_UH(7);\n");
3808 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3812 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3813 printf("GPR_UW(destreg,1) = RS_UW(2);\n");
3814 printf("GPR_UW(destreg,2) = RT_UW(3);\n");
3815 printf("GPR_UW(destreg,3) = RS_UW(3);\n");
3819 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3820 printf("GPR_UB(destreg,1) = RT_UB(2);\n");
3821 printf("GPR_UB(destreg,2) = RT_UB(4);\n");
3822 printf("GPR_UB(destreg,3) = RT_UB(6);\n");
3823 printf("GPR_UB(destreg,4) = RT_UB(8);\n");
3824 printf("GPR_UB(destreg,5) = RT_UB(10);\n");
3825 printf("GPR_UB(destreg,6) = RT_UB(12);\n");
3826 printf("GPR_UB(destreg,7) = RT_UB(14);\n");
3827 printf("GPR_UB(destreg,8) = RS_UB(0);\n");
3828 printf("GPR_UB(destreg,9) = RS_UB(2);\n");
3829 printf("GPR_UB(destreg,10) = RS_UB(4);\n");
3830 printf("GPR_UB(destreg,11) = RS_UB(6);\n");
3831 printf("GPR_UB(destreg,12) = RS_UB(8);\n");
3832 printf("GPR_UB(destreg,13) = RS_UB(10);\n");
3833 printf("GPR_UB(destreg,14) = RS_UB(12);\n");
3834 printf("GPR_UB(destreg,15) = RS_UB(14);\n");
3838 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3839 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3840 printf("GPR_UH(destreg,2) = RT_UH(4);\n");
3841 printf("GPR_UH(destreg,3) = RT_UH(6);\n");
3842 printf("GPR_UH(destreg,4) = RS_UH(0);\n");
3843 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3844 printf("GPR_UH(destreg,6) = RS_UH(4);\n");
3845 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3849 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3850 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3851 printf("GPR_UW(destreg,2) = RS_UW(0);\n");
3852 printf("GPR_UW(destreg,3) = RS_UW(2);\n");
3856 printf("GPR_UH(destreg,0) = RT_UH(3);\n");
3857 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3858 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3859 printf("GPR_UH(destreg,3) = RT_UH(0);\n");
3860 printf("GPR_UH(destreg,4) = RT_UH(7);\n");
3861 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3862 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3863 printf("GPR_UH(destreg,7) = RT_UH(4);\n");
3867 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3868 printf("GPR_UW(destreg,1) = RT_UW(3);\n");
3869 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3870 printf("GPR_UW(destreg,3) = RT_UW(2);\n");
3874 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3875 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3876 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3877 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3878 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3879 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3880 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3881 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3885 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3886 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3887 printf("GPR_UH(destreg,2) = RT_UH(2);\n");
3888 printf("GPR_UH(destreg,3) = RS_UH(2);\n");
3889 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3890 printf("GPR_UH(destreg,5) = RS_UH(4);\n");
3891 printf("GPR_UH(destreg,6) = RT_UH(6);\n");
3892 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3895 case PMXX
: /* Parallel move HI or LO / TO or FROM */
3897 if ( (insn
->flags
& (HI
|FROM
)) == (HI
|FROM
) )
3899 printf("GPR_SD(destreg,0) = HI;\n");
3900 printf("GPR_SD(destreg,1) = HI1;\n");
3902 else if ( (insn
->flags
& (LO
|FROM
)) == (LO
|FROM
) )
3904 printf("GPR_SD(destreg,0) = LO;\n");
3905 printf("GPR_SD(destreg,1) = LO1;\n");
3907 else if ( (insn
->flags
& (HI
|TO
)) == (HI
|TO
) )
3909 printf("HI = RS_SD(0);\n");
3910 printf("HI1 = RS_SD(1);\n");
3912 else if ( (insn
->flags
& (LO
|TO
)) == (LO
|TO
) )
3914 printf("LO = RS_SD(0);\n");
3915 printf("LO1 = RS_SD(1);\n");
3921 printf("LO_UW(0) = RS_UW(0);\n");
3922 printf("HI_UW(0) = RS_UW(1);\n");
3923 printf("LO_UW(2) = RS_UW(2);\n");
3924 printf("HI_UW(2) = RS_UW(3);\n");
3928 printf("if (op1 == 0)\n");
3930 printf(" GPR_UW(destreg,0) = LO_UW(0);\n");
3931 printf(" GPR_UW(destreg,1) = HI_UW(0);\n");
3932 printf(" GPR_UW(destreg,2) = LO_UW(2);\n");
3933 printf(" GPR_UW(destreg,3) = HI_UW(2);\n");
3935 printf("else if (op1 == 1)\n");
3937 printf(" GPR_UW(destreg,0) = LO_UW(1);\n");
3938 printf(" GPR_UW(destreg,1) = HI_UW(1);\n");
3939 printf(" GPR_UW(destreg,2) = LO_UW(3);\n");
3940 printf(" GPR_UW(destreg,3) = HI_UW(3);\n");
3942 printf("else if (op1 == 2)\n");
3944 printf(" /* NOTE: This code implements a saturate according to the\n");
3945 printf(" figure on page B-115 and not according to the\n");
3946 printf(" definition on page B-113 */\n");
3947 printf(" signed64 t = ((unsigned64)HI_UW(0) << 32) | (unsigned64)LO_UW(0);\n");
3948 printf(" signed64 u = ((unsigned64)HI_UW(2) << 32) | (unsigned64)LO_UW(2);\n");
3949 printf(" if ( t > SIGNED64 (0x000000007FFFFFFF) )\n");
3950 printf(" GPR_SD(destreg,0) = SIGNED64 (0x000000007FFFFFFF);\n");
3951 printf(" else if ( t < - SIGNED64 (0x0000000080000000) )\n");
3952 printf(" GPR_SD(destreg,0) = - SIGNED64 (0x0000000080000000);\n");
3954 printf(" GPR_SD(destreg,0) = t;\n");
3955 printf(" if ( u > SIGNED64 (0x000000007FFFFFFF) )\n");
3956 printf(" GPR_SD(destreg,1) = SIGNED64 (0x000000007FFFFFFF);\n");
3957 printf(" else if ( u < - SIGNED64 (0x0000000080000000) )\n");
3958 printf(" GPR_SD(destreg,1) = - SIGNED64 (0x0000000080000000);\n");
3960 printf(" GPR_SD(destreg,1) = u;\n");
3962 printf("else if (op1 == 3)\n");
3964 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3965 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3966 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
3967 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
3968 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
3969 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
3970 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
3971 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
3973 printf("else if (op1 == 4)\n");
3975 printf(" if (LO_SW(0) > 0x7FFF)\n");
3976 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
3977 printf(" else if (LO_SW(0) < -0x8000)\n");
3978 printf(" GPR_UH(destreg,0) = 0x8000;\n");
3980 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3982 printf(" if (LO_SW(1) > 0x7FFF)\n");
3983 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
3984 printf(" else if (LO_SW(1) < -0x8000)\n");
3985 printf(" GPR_UH(destreg,1) = 0x8000;\n");
3987 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3989 printf(" if (HI_SW(0) > 0x7FFF)\n");
3990 printf(" GPR_UH(destreg,2) = 0x7FFF;\n");
3991 printf(" else if (HI_SW(0) < -0x8000)\n");
3992 printf(" GPR_UH(destreg,2) = 0x8000;\n");
3994 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
3996 printf(" if (HI_SW(1) > 0x7FFF)\n");
3997 printf(" GPR_UH(destreg,3) = 0x7FFF;\n");
3998 printf(" else if (HI_SW(1) < -0x8000)\n");
3999 printf(" GPR_UH(destreg,3) = 0x8000;\n");
4001 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
4003 printf(" if (LO_SW(2) > 0x7FFF)\n");
4004 printf(" GPR_UH(destreg,4) = 0x7FFF;\n");
4005 printf(" else if (LO_SW(2) < -0x8000)\n");
4006 printf(" GPR_UH(destreg,4) = 0x8000;\n");
4008 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
4010 printf(" if (LO_SW(3) > 0x7FFF)\n");
4011 printf(" GPR_UH(destreg,5) = 0x7FFF;\n");
4012 printf(" else if (LO_SW(3) < -0x8000)\n");
4013 printf(" GPR_UH(destreg,5) = 0x8000;\n");
4015 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
4017 printf(" if (HI_SW(2) > 0x7FFF)\n");
4018 printf(" GPR_UH(destreg,6) = 0x7FFF;\n");
4019 printf(" else if (HI_SW(2) < -0x8000)\n");
4020 printf(" GPR_UH(destreg,6) = 0x8000;\n");
4022 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
4024 printf(" if (HI_SW(3) > 0x7FFF)\n");
4025 printf(" GPR_UH(destreg,7) = 0x7FFF;\n");
4026 printf(" else if (HI_SW(3) < -0x8000)\n");
4027 printf(" GPR_UH(destreg,7) = 0x8000;\n");
4029 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
4035 printf("unsigned long value;\n");
4036 printf("int test;\n");
4037 printf("int count;\n");
4040 printf("value = RS_UW(0);\n");
4041 printf("count = 0;\n");
4042 printf("test = !!(value & (1 << 31));\n");
4043 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
4044 printf(" count++;\n");
4045 printf("GPR_UW(destreg,0) = count;\n");
4047 printf("value = RS_UW(1);\n");
4048 printf("count = 0;\n");
4049 printf("test = !!(value & (1 << 31));\n");
4050 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
4051 printf(" count++;\n");
4052 printf("GPR_UW(destreg,1) = count;\n");
4057 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
4059 printf(" unsigned32 x = RT_UW(i);\n");
4060 printf(" GPR_UW(destreg,i) = ((x & (1 << 15)) << (31 - 15)) \n");
4061 printf(" | ((x & (31 << 10)) << (19 - 10)) \n");
4062 printf(" | ((x & (31 << 5)) << (11 - 5)) \n");
4063 printf(" | ((x & (31 << 0)) << (3 - 0)); \n");
4069 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
4071 printf(" unsigned32 x = RT_UW(i);\n");
4072 printf(" GPR_UW(destreg,i) = ((x & (1 << 31)) >> (31 - 15)) \n");
4073 printf(" | ((x & (31 << 19)) >> (19 - 10)) \n");
4074 printf(" | ((x & (31 << 11)) >> (11 - 5)) \n");
4075 printf(" | ((x & (31 << 3)) >> (3 - 0)); \n");
4078 /* end-sanitize-r5900 */
4081 fprintf(stderr
,"Warning: Unimplemented opcode: %s\n",insn
->name
) ;
4083 printf("SignalException(ReservedInstruction,instruction);\n");
4087 fprintf(stderr
,"Unrecognised opcode type %d\n",insn
->type
) ;
4092 /*---------------------------------------------------------------------------*/
4094 /* The command-line feature controls are presented in a similar style
4095 to those offered by GCC, in the aim of providing a consistent
4096 interface to the user. */
4098 T_NONE
, /* no argument - mask and value fields control "feature" definition */
4099 T_NUM
, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
4100 T_STRING
/* string argument - optionally prcededed by '=' */
4109 } machine_options
[] = {
4110 {"ips", T_NUM
, MASK_ISA
,0,"\tSelect MIPS ISA version"},
4111 {"cpu", T_STRING
,0,0,"\t\tSelect particular MIPS architecture"},
4112 {"gp64", T_NONE
, FEATURE_GP64
,FEATURE_GP64
,"\t\t\tSelect 64bit GP registers"},
4113 {"gp32", T_NONE
, FEATURE_GP64
,0,"\t\t\tSelect 32bit GP registers"},
4114 {"no-fp", T_NONE
, FEATURE_HASFPU
,0,"\t\tDisable FP simulation"},
4115 {"single-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),(FEATURE_FPSINGLE
| FEATURE_HASFPU
),"\t\tSelect single precision only FPU"},
4116 {"double-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),FEATURE_HASFPU
,"\t\tSelect double precision FPU"},
4120 /* The following architecture identies are those accepted by the "-mcpu" option: */
4121 struct architectures
{
4122 const char *name
; /* ASCII string identifier for command-line, no white-space allowed */
4123 unsigned int idflag
; /* or-ed into "isa" value */
4126 static const struct architectures available_architectures
[] = {
4127 {"4100",ARCH_VR4100
}, /* NEC MIPS VR4100 */
4128 {"3900",ARCH_R3900
}, /* Toshiba R3900 (TX39) */
4129 /* start-sanitize-tx19 */
4130 {"1900",ARCH_R3900
}, /* Toshiba R1900 (TX19) */
4131 /* end-sanitize-tx19 */
4132 /* start-sanitize-r5900 */
4133 {"5900",ARCH_R5900
},
4134 /* end-sanitize-r5900 */
4135 {0, 0} /* terminator */
4138 /*---------------------------------------------------------------------------*/
4146 fprintf(stderr
,"%s: Construct a MIPS simulator engine.\n",name
);
4149 The output of this program is a block of 'C' code designed to be\n\
4150 included into the main simulation control loop of a device specific\n\
4153 fprintf(stderr
,"\nOptions:\n");
4154 fprintf(stderr
," -h --help\t\tProvide this help text\n");
4155 fprintf(stderr
," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
4156 fprintf(stderr
," -w --warnings\t\tEnable all the simulator engine warnings\n");
4158 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++) {
4159 fprintf(stderr
," -m%s",machine_options
[loop
].name
);
4160 switch (machine_options
[loop
].type
) {
4162 fprintf(stderr
,"N (range 0..%d)",machine_options
[loop
].mask
);
4167 fprintf(stderr
,"=name");
4171 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",name
,machine_options
[loop
].type
);
4174 fprintf(stderr
,"%s\n",machine_options
[loop
].desc
);
4177 fprintf(stderr
,"\nAvailable \"-mcpu\" architectures: ");
4178 for (loop
= 0; (available_architectures
[loop
].name
!= 0); loop
++)
4179 fprintf(stderr
,"%s ",available_architectures
[loop
].name
);
4180 fprintf(stderr
,"\n\n");
4183 The \"trace\" and \"warnings\" options do not define the output stream.\n\
4184 They only inform the code that includes the constructed engine to provide\n\
4185 the required features.\n\n\
4186 The \"-mips0\" option forces the construction of a simulator supporting\n\
4187 the highest available MIPS ISA supported.\n");
4192 /*---------------------------------------------------------------------------*/
4200 char *progname
= argv
[0];
4201 unsigned int doarch
= DEF_ISA
;
4202 unsigned int features
= 0; /* default state */
4205 features
|= FEATURE_HASFPU
;
4207 features
|= FEATURE_PROC32
;
4209 features
|= FEATURE_FPSINGLE
;
4211 if (features
& FEATURE_PROC32
)
4212 features
&= ~FEATURE_GP64
;
4214 features
|= FEATURE_GP64
;
4217 int option_index
= 0;
4218 static struct option cmdline
[] = {
4221 {"warnings",0,0,'w'},
4225 c
= getopt_long(argc
,argv
,"hm:tw",cmdline
,&option_index
);
4227 break ; /* out of the while loop */
4230 case 'h' : /* help */
4234 case 'f' : /* fast */
4235 features
|= FEATURE_FAST
;
4238 case 'w' : /* warnings */
4239 features
|= FEATURE_WARNINGS
;
4240 /* TODO: Future extension: Allow better control over the warnings generated:
4241 disable warnings -wnone ~FEATURE_WARNINGS
4242 all possible warnings -wall FEATURE_WARNINGS
4243 pipeline stall occuring -wstall FEATURE_WARN_STALL
4244 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
4245 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
4246 bad r31 use -wr31 FEATURE_WARN_R31
4247 undefined results -wresult FEATURE_WARN_RESULT
4251 case 'm' : /* machine options */
4255 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++)
4256 if (strncmp(machine_options
[loop
].name
,optarg
,strlen(machine_options
[loop
].name
)) == 0) {
4257 char *loptarg
= (optarg
+ strlen(machine_options
[loop
].name
));
4258 switch (machine_options
[loop
].type
) {
4261 fprintf(stderr
,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname
,loptarg
,machine_options
[loop
].name
);
4264 features
&= ~(machine_options
[loop
].mask
);
4265 features
|= machine_options
[loop
].value
;
4269 if (*loptarg
&& *loptarg
== '=')
4272 if (strcmp(machine_options
[loop
].name
,"ips") == 0) {
4276 fprintf(stderr
,"%s: ISA number expected after -mips\n",progname
);
4280 num
= my_strtoul(loptarg
,&loptarg
,10);
4282 if ((num
== ULONG_MAX
) && (errno
= ERANGE
)) {
4283 fprintf(stderr
,"%s: Invalid number given to -mips option\n",progname
);
4288 fprintf(stderr
,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname
,loptarg
);
4292 if (num
> MASK_ISA
) {
4293 fprintf(stderr
,"%s: ISA number %d outside acceptable range (0..%d)\n",progname
,num
,MASK_ISA
);
4297 doarch
= ((doarch
& ~MASK_ISA
) | num
);
4298 if ((num
== 0) || (num
> 2)) {
4299 if ((features
& FEATURE_PROC32
) || !(features
& FEATURE_GP64
))
4300 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp64\n",progname
,num
);
4301 features
|= FEATURE_GP64
;
4302 features
&= ~FEATURE_PROC32
;
4304 if (!(features
& FEATURE_PROC32
) || (features
& FEATURE_GP64
))
4305 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp32\n",progname
,num
);
4306 features
&= ~FEATURE_GP64
;
4307 features
|= FEATURE_PROC32
;
4310 fprintf(stderr
,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname
,optarg
);
4316 if (*loptarg
&& *loptarg
== '=')
4319 if (strcmp(machine_options
[loop
].name
,"cpu") == 0) {
4323 fprintf(stderr
,"%s: Architecture identifier expected after -mcpu\n",progname
);
4327 for (archloop
= 0; (available_architectures
[archloop
].name
!= 0); archloop
++) {
4328 if ((*loptarg
== 'v') || (*loptarg
== 'V'))
4331 if ((*loptarg
== 'r') || (*loptarg
== 'R'))
4334 if (strcmp(available_architectures
[archloop
].name
,loptarg
) == 0) {
4335 doarch
|= available_architectures
[archloop
].idflag
;
4340 if (available_architectures
[archloop
].name
== 0) {
4341 fprintf(stderr
,"%s: Unrecognised MIPS architecture \"%s\"\n",progname
,loptarg
);
4345 fprintf(stderr
,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname
,optarg
);
4351 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",progname
,machine_options
[loop
].type
);
4357 if (machine_options
[loop
].name
== 0) {
4358 fprintf(stderr
,"%s: Unrecognised option: -m%s\n",progname
,optarg
);
4365 /* An error message should already have been displayed */
4369 fprintf(stderr
,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname
,c
);
4374 if (optind
< argc
) {
4375 fprintf(stderr
,"%s: Spurios non-option arguments ",progname
);
4376 while (optind
< argc
)
4377 fprintf(stderr
,"\"%s\" ",argv
[optind
++]);
4378 fprintf(stderr
,"\n");
4382 if ((features
& FEATURE_FAST
) && (features
& FEATURE_WARNINGS
))
4383 fprintf(stderr
,"Warning: Fast model generation selected, along with trace or warnings.\n");
4385 process_instructions(doarch
,features
) ;
4389 /*---------------------------------------------------------------------------*/
4391 /* We can't assume that the compiler for the build system has strtoul,
4392 so we provide our own copy. */
4395 * Copyright (c) 1990 Regents of the University of California.
4396 * All rights reserved.
4398 * Redistribution and use in source and binary forms, with or without
4399 * modification, are permitted provided that the following conditions
4401 * 1. Redistributions of source code must retain the above copyright
4402 * notice, this list of conditions and the following disclaimer.
4403 * 2. Redistributions in binary form must reproduce the above copyright
4404 * notice, this list of conditions and the following disclaimer in the
4405 * documentation and/or other materials provided with the distribution.
4406 * 3. All advertising materials mentioning features or use of this software
4407 * must display the following acknowledgement:
4408 * This product includes software developed by the University of
4409 * California, Berkeley and its contributors.
4410 * 4. Neither the name of the University nor the names of its contributors
4411 * may be used to endorse or promote products derived from this software
4412 * without specific prior written permission.
4414 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4415 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4416 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4417 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4418 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4419 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4420 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4421 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4422 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4423 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4428 * Convert a string to an unsigned long integer.
4430 * Ignores `locale' stuff. Assumes that the upper and lower case
4431 * alphabets and digits are each contiguous.
4433 static unsigned long
4434 my_strtoul(nptr
, endptr
, base
)
4439 register const char *s
= nptr
;
4440 register unsigned long acc
;
4442 register unsigned long cutoff
;
4443 register int neg
= 0, any
, cutlim
;
4446 * See strtol for comments as to the logic used.
4450 } while (isspace(c
));
4454 } else if (c
== '+')
4456 if ((base
== 0 || base
== 16) &&
4457 c
== '0' && (*s
== 'x' || *s
== 'X')) {
4463 base
= c
== '0' ? 8 : 10;
4464 cutoff
= (unsigned long)ULONG_MAX
/ (unsigned long)base
;
4465 cutlim
= (unsigned long)ULONG_MAX
% (unsigned long)base
;
4466 for (acc
= 0, any
= 0;; c
= *s
++) {
4469 else if (isalpha(c
))
4470 c
-= isupper(c
) ? 'A' - 10 : 'a' - 10;
4475 if (any
< 0 || acc
> cutoff
|| (acc
== cutoff
&& c
> cutlim
))
4489 *endptr
= (char *) (any
? s
- 1 : nptr
);
4493 /*---------------------------------------------------------------------------*/
4495 /*> EOF gencode.c <*/