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 */
315 /* 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 */
479 /* A list (or'ed) of extension insn sets that can be requested independant of the ISA# */
480 #define MASK_ISA_INDEP (0 \
481 /* start-sanitize-r5900 */ \
483 /* end-sanitize-r5900 */ \
486 #define MASK_ISA_DEP ~(MASK_ISA_INDEP | MASK_ISA)
489 /* Very short names for use in the table below to keep it neet. */
490 #define G1 (3 | ARCH_VR4100)
493 /* start-sanitize-r5900 */ \
495 /* end-sanitize-r5900 */ \
499 /* start-sanitize-r5900 */ \
500 /* insn that are not really 5900 insn but were left in */ \
501 /* until we can rewrite the code-gen and libs */ \
503 /* end-sanitize-r5900 */ \
508 /* start-sanitize-r5900 */
509 #define T5 ARCH_R5900
510 /* end-sanitize-r5900 */
513 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
514 COP0 space. This means that an external decoder should be added
515 when constructing a full VR4100 simulator. However some arithmetic
516 instructions are encoded in the normal instruction space. */
518 struct instruction MIPS_DECODE
[] = {
519 /* The instructions are alphabetical, and not in instruction bit-order: */
520 {"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1
, FPABS
, (FP
)},
521 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL
,ADD
, (WORD
| WORD32
| OVERFLOW
)}, /* rd = rs + rt */
522 {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1
, FPADD
, (FP
)},
523 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
| OVERFLOW
)},
524 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL
,ADD
, (WORD
| WORD32
)}, /* rd = rs + rt */
525 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
)},
526 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL
,AND
, (NONE
)}, /* rd = rs AND rt */
527 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, AND
, (NONE
)},
528 {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S
, BRANCH
, (FP
)},
529 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
)},
530 {"BEQL", 2,"010100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
| LIKELY
)},
531 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
)},
532 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
533 {"BGEZALL", 2,"000001sssss10011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
534 {"BGEZL", 2,"000001sssss00011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LIKELY
)},
535 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
)},
536 {"BGTZL", 2,"010111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
| LIKELY
)},
537 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
)},
538 {"BLEZL", 2,"010110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
| LIKELY
)},
539 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM
, BRANCH
, (LT
)},
540 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
)},
541 {"BLTZALL", 2,"000001sssss10010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
| LIKELY
)},
542 {"BLTZL", 2,"000001sssss00010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LIKELY
)},
543 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
)},
544 {"BNEL", 2,"010101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
| LIKELY
)},
545 {"BREAK", 1,"000000????????????????????001101",SPECIAL
,BREAK
, (NOARG
)},
546 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1
, FPCEIL
, (FP
| FIXED
| DOUBLEWORD
)},
547 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1
, FPCEIL
, (FP
| FIXED
| WORD
)},
548 {"COP0", 1,"010000??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
549 {"COP2", 1,"010010??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
550 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1
, FPCONVERT
,(FP
| DOUBLE
)},
551 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1
, FPCONVERT
,(FP
| FIXED
| DOUBLEWORD
)},
552 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1
, FPCONVERT
,(FP
| SINGLE
)},
553 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1
, FPCONVERT
,(FP
| FIXED
| WORD
)},
554 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1
, FPCOMPARE
,(FP
)},
555 {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
| CONTROL
)},
556 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL
,ADD
, (DOUBLEWORD
| OVERFLOW
)},
557 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| OVERFLOW
)},
558 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL
,ADD
, (DOUBLEWORD
| UNSIGNED
)},
559 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| UNSIGNED
)},
560 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL
,DIV
, (DOUBLEWORD
| HI
| LO
)},
561 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL
,DIV
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
562 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
)},
563 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1
, FPDIV
, (FP
| WORD
| HI
| LO
)},
564 /* start-sanitize-r5900 */
565 {"DIV1", T5
,"011100sssssggggg0000000000011010",MMINORM
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
| PIPE1
)},
566 /* end-sanitize-r5900 */
567 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
)},
568 /* start-sanitize-r5900 */
569 {"DIVU1", T5
,"011100sssssggggg0000000000011011",MMINORM
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
| PIPE1
)},
570 /* end-sanitize-r5900 */
571 {"DMADD16",G1
,"000000sssssggggg0000000000101001",SPECIAL
,MADD16
, (DOUBLEWORD
| HI
| LO
)},
572 {"DMULT", 3,"000000sssssggggg0000000000011100",SPECIAL
,MUL
, (DOUBLEWORD
| HI
| LO
)},
573 {"DMULTU", 3,"000000sssssggggg0000000000011101",SPECIAL
,MUL
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
574 {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| DOUBLEWORD
)},
575 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
)},
576 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| REG
)},
577 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| HI32
)}, /* rd = rt << (sa + 32) */
578 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
)},
579 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| REG
)},
580 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| HI32
)}, /* rd = rt >> (sa + 32) */
581 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
)},
582 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| REG
)},
583 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| HI32
)},
584 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL
,SUB
, (DOUBLEWORD
)},
585 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL
,SUB
, (DOUBLEWORD
| UNSIGNED
)},
586 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1
, FPFLOOR
, (FP
| FIXED
| DOUBLEWORD
)},
587 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1
, FPFLOOR
, (FP
| FIXED
| WORD
)},
588 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (NONE
)}, /* NOTE: boundary case due to delay slot address being used */
589 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
)}, /* NOTE: boundary case due to delay slot address being used */
590 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL
,JUMP
, (LINK
| REG
)},
591 {"JALX", 1,"011101jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
| NOT
)},
592 {"JR", 1,"000000sssss000000000000000001000",SPECIAL
,JUMP
, (NONE
)}, /* need to check PC as part of instruction fetch */
593 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
| SIGNEXTEND
)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
594 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
)}, /* NOTE: See "LB" comment */
595 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
)},
596 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
597 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
598 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| LEFT
)}, /* NOTE: See "LB" comment */
599 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| RIGHT
)}, /* NOTE: See "LB" comment */
600 {"LDXC1", G3
,"010011sssssggggg00000rrrrr000001",COP1X
, LOAD
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
601 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
| SIGNEXTEND
)},
602 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
)},
603 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| ATOMIC
| SIGNEXTEND
)},
604 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| ATOMIC
)},
605 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL
, MOVE
, (SHIFT16
)}, /* Cheat and specify sign-extension of immediate field */
606 /* start-sanitize-r5900 */
607 {"LQ", T5
,"011110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (QUADWORD
)},
608 /* end-sanitize-r5900 */
609 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| SIGNEXTEND
)},
610 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
611 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
612 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| LEFT
)},
613 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| RIGHT
)},
614 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
)},
615 {"LWXC1", G3
,"010011sssssggggg00000rrrrr000000",COP1X
, LOAD
, (FP
| WORD
| COPROC
| REG
)},
616 /* start-sanitize-r5900 */
617 {"MADD", T5
,"011100sssssgggggddddd00000000000",MMINORM
,MADD
, (NONE
)},
618 {"MADD1", T5
,"011100sssssgggggddddd00000100000",MMINORM
,MADD
, (PIPE1
)},
619 {"MADDU", T5
,"011100sssssgggggddddd00000000001",MMINORM
,MADD
, (UNSIGNED
)},
620 {"MADDU1", T5
,"011100sssssgggggddddd00000100001",MMINORM
,MADD
, (UNSIGNED
| PIPE1
)},
621 /* end-sanitize-r5900 */
622 {"MADD16", G1
,"000000sssssggggg0000000000101000",SPECIAL
,MADD16
, (WORD
| HI
| LO
)},
623 {"MADD.D", G3
,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X
, FPADD
, (FP
| MULTIPLY
| DOUBLE
)},
624 {"MADD.S", G3
,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X
, FPADD
, (FP
| MULTIPLY
| SINGLE
)},
625 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL
,MOVE
, (HI
| LEFT
)}, /* with following, from and to denoted by usage of LEFT or RIGHT */
626 /* start-sanitize-r5900 */
627 {"MFHI1", T5
,"0111000000000000ddddd00000010000",MMINORM
,MOVE
, (HI
| LEFT
| PIPE1
)},
628 /* end-sanitize-r5900 */
629 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL
,MOVE
, (LO
| LEFT
)},
630 /* start-sanitize-r5900 */
631 {"MFLO1", T5
,"0111000000000000ddddd00000010010",MMINORM
,MOVE
, (LO
| LEFT
| PIPE1
)},
632 {"MFSA", T5
,"0000000000000000ddddd00000101000",SPECIAL
,MxSA
, (FROM
)},
633 /* end-sanitize-r5900 */
634 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL
,MOVE
, (HI
| RIGHT
)},
635 /* start-sanitize-r5900 */
636 {"MTHI1", T5
,"011100sssss000000000000000010001",MMINORM
,MOVE
, (HI
| RIGHT
| PIPE1
)},
637 /* end-sanitize-r5900 */
638 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL
,MOVE
, (LO
| RIGHT
)},
639 /* start-sanitize-r5900 */
640 {"MTLO1", T5
,"011100sssss000000000000000010011",MMINORM
,MOVE
, (LO
| RIGHT
| PIPE1
)},
641 {"MTSA", T5
,"000000sssss000000000000000101001",SPECIAL
,MxSA
, (TO
)},
642 {"MTSAB", T5
,"000001sssss11000iiiiiiiiiiiiiiii",REGIMM
, MTSAB
, (NONE
)},
643 {"MTSAH", T5
,"000001sssss11001iiiiiiiiiiiiiiii",REGIMM
, MTSAH
, (NONE
)},
644 /* end-sanitize-r5900 */
645 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1
, FPMOVE
, (FP
)},
646 {"MOVN", G2
,"000000sssssgggggddddd00000001011",SPECIAL
,MOVE
, (NOT
| EQ
)},
647 {"MOVN", G2
,"01000110mmmgggggvvvvvrrrrr010011",COP1
, FPMOVE
, (FP
| NOT
| EQ
)},
648 {"MOV%c", G3
,"000000sssssqqq0cddddd00000000001",SPECIAL
,FPMOVE
, (FP
| CONDITIONAL
| INTEGER
)},
649 {"MOV%c", G3
,"01000110mmmqqq0cvvvvvrrrrr010001",COP1
, FPMOVE
, (FP
| CONDITIONAL
)},
650 {"MOVZ", G2
,"000000sssssgggggddddd00000001010",SPECIAL
,MOVE
, (EQ
)},
651 {"MOVZ", G2
,"01000110mmmgggggvvvvvrrrrr010010",COP1
, FPMOVE
, (FP
| EQ
)},
652 {"MSUB.D", G3
,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X
, FPSUB
, (FP
| MULTIPLY
| DOUBLE
)},
653 {"MSUB.S", G3
,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X
, FPSUB
, (FP
| MULTIPLY
| SINGLE
)},
654 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1
, FPMUL
, (FP
| HI
| LO
)},
655 {"MULT", 1,"000000sssssgggggddddd00000011000",SPECIAL
,MUL
, (OP3
| WORD
| WORD32
| HI
| LO
)},
656 /* start-sanitize-r5900 */
657 {"MULT1", T5
,"011100sssssgggggddddd00000011000",MMINORM
,MUL
, (OP3
| WORD
| WORD32
| HI
| LO
| PIPE1
)},
658 /* end-sanitize-r5900 */
659 {"MULTU", 1,"000000sssssgggggddddd00000011001",SPECIAL
,MUL
, (OP3
| WORD
| WORD32
| UNSIGNED
| HI
| LO
)},
660 /* start-sanitize-r5900 */
661 {"MULTU1", T5
,"011100sssssgggggddddd00000011001",MMINORM
,MUL
, (OP3
| WORD
| WORD32
| UNSIGNED
| HI
| LO
| PIPE1
)},
662 /* end-sanitize-r5900 */
663 {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
)},
664 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1
, FPNEG
, (FP
)},
665 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
666 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
667 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
668 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
669 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL
,OR
, (NOT
)},
670 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL
,OR
, (NONE
)},
671 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, OR
, (NONE
)},
673 /* start-sanitize-r5900 */
674 {"PABSH", T5
,"01110000000TTTTTddddd00101101000",MMI1
, PABS
, (HALFWORD
)},
675 {"PABSW", T5
,"01110000000TTTTTddddd00001101000",MMI1
, PABS
, (WORD
)},
677 {"PADDB", T5
,"011100SSSSSTTTTTddddd01000001000",MMI0
, PADD
, (BYTE
)},
678 {"PADDH", T5
,"011100SSSSSTTTTTddddd00100001000",MMI0
, PADD
, (HALFWORD
)},
679 {"PADDW", T5
,"011100SSSSSTTTTTddddd00000001000",MMI0
, PADD
, (WORD
)},
681 {"PADDSB", T5
,"011100SSSSSTTTTTddddd11000001000",MMI0
, PADD
, (BYTE
| SATURATE
)},
682 {"PADDSH", T5
,"011100SSSSSTTTTTddddd10100001000",MMI0
, PADD
, (HALFWORD
| SATURATE
)},
683 {"PADDSW", T5
,"011100SSSSSTTTTTddddd10000001000",MMI0
, PADD
, (WORD
| SATURATE
)},
685 {"PADDUB", T5
,"011100SSSSSTTTTTddddd11000101000",MMI1
, PADD
, (BYTE
| UNSIGNED
)},
686 {"PADDUH", T5
,"011100SSSSSTTTTTddddd10100101000",MMI1
, PADD
, (HALFWORD
| UNSIGNED
)},
687 {"PADDUW", T5
,"011100SSSSSTTTTTddddd10000101000",MMI1
, PADD
, (WORD
| UNSIGNED
)},
689 {"PADSBH", T5
,"011100SSSSSTTTTTddddd00100101000",MMI1
, PADSBH
, (NONE
)},
691 {"PAND", T5
,"011100SSSSSTTTTTddddd10010001001",MMI2
, POP
, (POP_AND
)},
693 {"PCEQB", T5
,"011100SSSSSTTTTTddddd01010101000",MMI1
, PCMP
, (EQ
| BYTE
)},
694 {"PCEQH", T5
,"011100SSSSSTTTTTddddd00110101000",MMI1
, PCMP
, (EQ
| HALFWORD
)},
695 {"PCEQW", T5
,"011100SSSSSTTTTTddddd00010101000",MMI1
, PCMP
, (EQ
| WORD
)},
697 {"PCGTB", T5
,"011100SSSSSTTTTTddddd01010001000",MMI0
, PCMP
, (GT
| BYTE
)},
698 {"PCGTH", T5
,"011100SSSSSTTTTTddddd00110001000",MMI0
, PCMP
, (GT
| HALFWORD
)},
699 {"PCGTW", T5
,"011100SSSSSTTTTTddddd00010001000",MMI0
, PCMP
, (GT
| WORD
)},
701 {"PCPYH", T5
,"01110000000TTTTTddddd11011101001",MMI3
, PCPYH
, (NONE
)},
702 {"PCPYLD", T5
,"011100SSSSSTTTTTddddd01110001001",MMI2
, PCPYLD
, (NONE
)},
703 {"PCPYUD", T5
,"011100SSSSSTTTTTddddd01110101001",MMI3
, PCPYUD
, (NONE
)},
705 {"PDIVBW", T5
,"011100SSSSSTTTTT0000011101001001",MMI2
, PDIVBW
, (NONE
)},
706 {"PDIVUW", T5
,"011100SSSSSTTTTT0000001101101001",MMI3
, PDIVW
, (UNSIGNED
)},
707 {"PDIVW", T5
,"011100SSSSSTTTTT0000001101001001",MMI2
, PDIVW
, (NONE
)},
709 {"PEXCH", T5
,"01110000000TTTTTddddd11010101001",MMI3
, PEXCH
, (NONE
)},
710 {"PEXCW", T5
,"01110000000TTTTTddddd11110101001",MMI3
, PEXCW
, (NONE
)},
711 {"PEXOH", T5
,"01110000000TTTTTddddd11010001001",MMI2
, PEXOH
, (NONE
)},
712 {"PEXOW", T5
,"01110000000TTTTTddddd11110001001",MMI2
, PEXOW
, (NONE
)},
714 {"PEXT5", T5
,"01110000000TTTTTddddd11110001000",MMI0
, PEXT5
, (NONE
)},
716 {"PEXTLB", T5
,"011100SSSSSTTTTTddddd11010001000",MMI0
, PEXTLB
, (NONE
)},
717 {"PEXTLH", T5
,"011100SSSSSTTTTTddddd10110001000",MMI0
, PEXTLH
, (NONE
)},
718 {"PEXTLW", T5
,"011100SSSSSTTTTTddddd10010001000",MMI0
, PEXTLW
, (NONE
)},
719 {"PEXTUB", T5
,"011100SSSSSTTTTTddddd11010101000",MMI1
, PEXTUB
, (NONE
)},
720 {"PEXTUH", T5
,"011100SSSSSTTTTTddddd10110101000",MMI1
, PEXTUH
, (NONE
)},
721 {"PEXTUW", T5
,"011100SSSSSTTTTTddddd10010101000",MMI1
, PEXTUW
, (NONE
)},
723 {"PHMADDH",T5
,"011100SSSSSTTTTTddddd10001001001",MMI2
, PHMADDH
, (NONE
)},
724 {"PHMSUBH",T5
,"011100SSSSSTTTTTddddd10101001001",MMI2
, PHMADDH
, (SUBTRACT
)},
726 {"PINTH", T5
,"011100SSSSSTTTTTddddd01010001001",MMI2
, PINTH
, (NONE
)},
727 {"PINTOH", T5
,"011100SSSSSTTTTTddddd01010101001",MMI3
, PINTOH
, (NONE
)},
729 {"PLZCW", T5
,"011100SSSSS00000ddddd00000000100",MMINORM
,PLZCW
, (NONE
)},
731 {"PMADDH", T5
,"011100SSSSSTTTTTddddd10000001001",MMI2
, PMULTH
, (ADDITION
)},
732 {"PMADDUW",T5
,"011100SSSSSTTTTTddddd00000101001",MMI3
, PMULTW
, (ADDITION
| UNSIGNED
)},
733 {"PMADDW", T5
,"011100SSSSSTTTTTddddd00000001001",MMI2
, PMULTW
, (ADDITION
)},
735 {"PMAXH", T5
,"011100SSSSSTTTTTddddd00111001000",MMI0
, PMAXMIN
, (GT
| HALFWORD
)},
736 {"PMAXW", T5
,"011100SSSSSTTTTTddddd00011001000",MMI0
, PMAXMIN
, (GT
| WORD
)},
738 {"PMFHI", T5
,"0111000000000000ddddd01000001001",MMI2
, PMXX
, (HI
|FROM
)},
739 {"PMFLO", T5
,"0111000000000000ddddd01001001001",MMI2
, PMXX
, (LO
|FROM
)},
741 {"PMFHL", T5
,"0111000000000000dddddaaaaa110000",MMINORM
,PMFHL
, (NONE
)},
743 {"PMINH", T5
,"011100SSSSSTTTTTddddd00111101000",MMI1
, PMAXMIN
, (LT
| HALFWORD
)},
744 {"PMINW", T5
,"011100SSSSSTTTTTddddd00011101000",MMI1
, PMAXMIN
, (LT
| WORD
)},
746 {"PMSUBH", T5
,"011100SSSSSTTTTTddddd10100001001",MMI2
, PMULTH
, (SUBTRACT
)},
747 {"PMSUBW", T5
,"011100SSSSSTTTTTddddd00100001001",MMI2
, PMULTW
, (SUBTRACT
)},
749 {"PMTHI", T5
,"011100SSSSS000000000001000101001",MMI3
, PMXX
, (HI
|TO
)},
750 {"PMTLO", T5
,"011100SSSSS000000000001001101001",MMI3
, PMXX
, (LO
|TO
)},
752 {"PMTHL.LW",T5
,"011100SSSSS000000000000000110001",MMINORM
,PMTHL
, (NONE
)},
754 {"PMULTH", T5
,"011100SSSSSTTTTTddddd11100001001",MMI2
, PMULTH
, (NONE
)},
755 {"PMULTUW",T5
,"011100SSSSSTTTTTddddd01100101001",MMI3
, PMULTW
, (UNSIGNED
)},
756 {"PMULTW", T5
,"011100SSSSSTTTTTddddd01100001001",MMI2
, PMULTW
, (NONE
)},
758 {"PNOR", T5
,"011100SSSSSTTTTTddddd10011101001",MMI3
, POP
, (POP_NOR
)},
759 {"POR", T5
,"011100SSSSSTTTTTddddd10010101001",MMI3
, POP
, (POP_OR
)},
761 {"PPAC5", T5
,"01110000000TTTTTddddd11111001000",MMI0
, PPAC5
, (NONE
)},
763 {"PPACB", T5
,"011100SSSSSTTTTTddddd11011001000",MMI0
, PPACB
, (NONE
)},
764 {"PPACH", T5
,"011100SSSSSTTTTTddddd10111001000",MMI0
, PPACH
, (NONE
)},
765 {"PPACW", T5
,"011100SSSSSTTTTTddddd10011001000",MMI0
, PPACW
, (NONE
)},
767 {"PREVH", T5
,"01110000000TTTTTddddd11011001001",MMI2
, PREVH
, (NONE
)},
768 {"PROT3W", T5
,"01110000000TTTTTddddd11111001001",MMI2
, PROT3W
, (NONE
)},
770 {"PSLLH", T5
,"01110000000TTTTTdddddaaaaa110100",MMINORM
,PSHIFT
, (LEFT
| LOGICAL
| HALFWORD
)},
771 {"PSLLVW", T5
,"011100SSSSSTTTTTddddd00010001001",MMI2
, PSLLVW
, (NONE
)},
772 {"PSLLW", T5
,"01110000000TTTTTdddddaaaaa111100",MMINORM
,PSHIFT
, (LEFT
| LOGICAL
| WORD
)},
774 {"PSRAH", T5
,"01110000000TTTTTdddddaaaaa110111",MMINORM
,PSHIFT
, (RIGHT
| ARITHMETIC
| HALFWORD
)},
775 {"PSRAVW", T5
,"011100SSSSSTTTTTddddd00011101001",MMI3
, PSRAVW
, (NONE
)},
776 {"PSRAW", T5
,"01110000000TTTTTdddddaaaaa111111",MMINORM
,PSHIFT
, (RIGHT
| ARITHMETIC
| WORD
)},
778 {"PSRLH", T5
,"01110000000TTTTTdddddaaaaa110110",MMINORM
,PSHIFT
, (RIGHT
| LOGICAL
| HALFWORD
)},
779 {"PSRLVW", T5
,"011100SSSSSTTTTTddddd00011001001",MMI2
, PSRLVW
, (NONE
)},
780 {"PSRLW", T5
,"01110000000TTTTTdddddaaaaa111110",MMINORM
,PSHIFT
, (RIGHT
| LOGICAL
| WORD
)},
782 {"PSUBB", T5
,"011100SSSSSTTTTTddddd01001001000",MMI0
, PADD
, (SUBTRACT
| BYTE
)},
783 {"PSUBH", T5
,"011100SSSSSTTTTTddddd00101001000",MMI0
, PADD
, (SUBTRACT
| HALFWORD
)},
784 {"PSUBSB", T5
,"011100SSSSSTTTTTddddd11001001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| BYTE
)},
785 {"PSUBSH", T5
,"011100SSSSSTTTTTddddd10101001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| HALFWORD
)},
786 {"PSUBSW", T5
,"011100SSSSSTTTTTddddd10001001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| WORD
)},
787 {"PSUBUB", T5
,"011100SSSSSTTTTTddddd11001101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| BYTE
)},
788 {"PSUBUH", T5
,"011100SSSSSTTTTTddddd10101101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| HALFWORD
)},
789 {"PSUBUW", T5
,"011100SSSSSTTTTTddddd10001101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| WORD
)},
790 {"PSUBW", T5
,"011100SSSSSTTTTTddddd00001001000",MMI0
, PADD
, (SUBTRACT
| WORD
)},
792 {"PXOR", T5
,"011100SSSSSTTTTTddddd10011001001",MMI2
, POP
, (POP_XOR
)},
793 /* end-sanitize-r5900 */
795 {"PREF", G2
,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, PREFETCH
, (NONE
)},
796 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X
, FPPREFX
, (FP
)},
798 /* start-sanitize-r5900 */
799 {"QFSRV", T5
,"011100SSSSSTTTTTddddd11011101000",MMI1
, QFSRV
, (NONE
)},
800 /* end-sanitize-r5900 */
802 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1
, FPRECIP
, (FP
)},
803 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1
, FPROUND
, (FP
| FIXED
| DOUBLEWORD
)},
804 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1
, FPROUND
, (FP
| FIXED
| WORD
)},
805 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1
, FPSQRT
, (FP
| RECIP
)},
806 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (BYTE
)},
807 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| ATOMIC
)},
808 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| ATOMIC
)},
809 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
)},
810 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
811 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
812 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| LEFT
)},
813 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| RIGHT
)},
814 {"SDXC1", G3
,"010011sssssgggggvvvvv00000001001",COP1X
, STORE
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
815 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL
, STORE
, (HALFWORD
)},
816 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << sa */
817 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
818 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL
,SET
, (LT
)},
819 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
)},
820 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL
,SET
, (LT
| UNSIGNED
)},
821 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
| UNSIGNED
)},
822 /* start-sanitize-r5900 */
823 {"SQ", T5
,"011111sssssTTTTTeeeeeeeeeeeeeeee",NORMAL
, STORE
, (QUADWORD
)},
824 /* end-sanitize-r5900 */
825 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1
, FPSQRT
, (FP
)},
826 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
827 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
828 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
829 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
830 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL
,SUB
, (WORD
| WORD32
| OVERFLOW
)},
831 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1
, FPSUB
, (FP
)},
832 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL
,SUB
, (WORD
| WORD32
)},
833 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
)},
834 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
835 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
836 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| LEFT
)},
837 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| RIGHT
)},
838 {"SWXC1", G3
,"010011sssssgggggvvvvv00000001000",COP1X
, STORE
, (FP
| WORD
| COPROC
| REG
)},
839 {"SYNC", 2,"000000000000000000000aaaaa001111",SPECIAL
,SYNC
, (NONE
)}, /* z = 5bit stype field */
840 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL
,SYSCALL
, (NOARG
)},
841 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL
,TRAP
, (EQ
)},
842 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (EQ
)},
843 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL
,TRAP
, (GT
| EQ
)},
844 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
)},
845 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
| UNSIGNED
)},
846 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL
,TRAP
, (GT
| EQ
| UNSIGNED
)},
847 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL
,TRAP
, (LT
)},
848 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
)},
849 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
| UNSIGNED
)},
850 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL
,TRAP
, (LT
| UNSIGNED
)},
851 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL
,TRAP
, (NOT
| EQ
)},
852 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (NOT
| EQ
)},
853 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1
, FPTRUNC
, (FP
| FIXED
| DOUBLEWORD
)},
854 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1
, FPTRUNC
, (FP
| FIXED
| WORD
)},
855 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL
,XOR
, (NONE
)},
856 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, XOR
, (NONE
)},
857 {"CACHE", 3,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, CACHE
, (NONE
)},
858 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, RSVD
, (NONE
)},
861 static const struct instruction MIPS16_DECODE
[] = {
862 {"ADDIU", 1, "01000xxxddd04444", RRI_A
, ADD
, WORD
| WORD32
},
863 {"ADDIU8", 1, "01001wwwkkkkkkkk", RI
, ADD
, WORD
| WORD32
},
864 {"ADJSP", 1, "01100011KKKKKKKKS", I8
, ADD
, WORD
| WORD32
},
865 {"ADDIUPC", 1, "00001dddAAAAAAAAP", RI
, ADD
, WORD
| WORD32
},
866 {"ADDIUSP", 1, "00000dddAAAAAAAAs", RI
, ADD
, WORD
| WORD32
},
867 {"ADDU", 1, "11100xxxyyyddd01", RRR
, ADD
, WORD
| WORD32
},
868 {"AND", 1, "11101wwwyyy01100", RR
, AND
, NONE
},
869 {"B", 1, "00010qqqqqqqqqqqzZ", I
, BRANCH
, EQ
},
870 {"BEQZ", 1, "00100xxxppppppppz", RI
, BRANCH
, EQ
},
871 {"BNEZ", 1, "00101xxxppppppppz", RI
, BRANCH
, NOT
| EQ
},
872 {"BREAK", 1, "01100??????00101", RR
, BREAK
, NOARG
},
873 {"BTEQZ", 1, "01100000pppppppptz", I8
, BRANCH
, EQ
},
874 {"BTNEZ", 1, "01100001pppppppptz", I8
, BRANCH
, NOT
| EQ
},
875 {"CMP", 1, "11101xxxyyy01010T", RR
, XOR
, NONE
},
876 {"CMPI", 1, "01110xxxUUUUUUUUT", RI
, XOR
, NONE
},
877 {"DADDIU", 3, "01000xxxddd14444", RRI_A
, ADD
, DOUBLEWORD
},
878 {"DADDIU5", 3, "11111101wwwjjjjj", RI64
, ADD
, DOUBLEWORD
},
879 {"DADJSP", 3, "11111011KKKKKKKKS", I64
, ADD
, DOUBLEWORD
},
880 {"DADIUPC", 3, "11111110dddEEEEEP", RI64
, ADD
, DOUBLEWORD
},
881 {"DADIUSP", 3, "11111111dddEEEEEs", RI64
, ADD
, DOUBLEWORD
},
882 {"DADDU", 3, "11100xxxyyyddd00", RRR
, ADD
, DOUBLEWORD
},
883 {"DDIV", 3, "11101xxxyyy11110", RR
, DIV
, DOUBLEWORD
| HI
| LO
},
884 {"DDIVU", 3, "11101xxxyyy11111", RR
, DIV
, DOUBLEWORD
| UNSIGNED
| HI
| LO
},
885 {"DIV", 1, "11101xxxyyy11010", RR
, DIV
, WORD
| WORD32
| SIGNEXTEND
| HI
| LO
},
886 {"DIVU", 1, "11101xxxyyy11011", RR
, DIV
, WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
},
887 {"DMULT", 3, "11101xxxyyy11100", RR
, MUL
, DOUBLEWORD
| HI
| LO
},
888 {"DMULTU", 3, "11101xxxyyy11101", RR
, MUL
, DOUBLEWORD
| UNSIGNED
| HI
| LO
},
889 {"DSLL", 3, "00110dddyyy[[[01", ISHIFT
, SHIFT
, DOUBLEWORD
| LEFT
| LOGICAL
},
890 {"DSLLV", 3, "11101xxxvvv10100", RR
, SHIFT
, DOUBLEWORD
| LEFT
| LOGICAL
| REG
},
891 {"DSRA", 3, "11101]]]vvv10011", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| ARITHMETIC
},
892 {"DSRAV", 3, "11101xxxvvv10111", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| ARITHMETIC
| REG
},
893 {"DSRL", 3, "11101]]]vvv01000", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| LOGICAL
},
894 {"DSRLV", 3, "11101xxxvvv10110", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| LOGICAL
| REG
},
895 {"DSUBU", 3, "11100xxxyyyddd10", RRR
, SUB
, DOUBLEWORD
| UNSIGNED
},
897 /* FIXME: Should we handle these ourselves, or should we require an
898 emulation routine? */
899 {"EXIT", 1, "1110111100001000", RR
, BREAK
, EXIT
},
900 {"ENTRY", 1, "11101??????01000", RR
, BREAK
, ENTRY
},
902 {"EXTEND", 1, "11110eeeeeeeeeee", I
, RSVD
, NOARG
},
903 {"JALR", 1, "11101xxx01000000R", RR
, JUMP
, LINK
| REG
},
904 {"JAL", 1, "00011aaaaaaaaaaa", I
, JUMP
, LINK
},
905 {"JR", 1, "11101xxx00000000", RR
, JUMP
, NONE
},
906 {"JRRA", 1, "1110100000100000r", RR
, JUMP
, NONE
},
907 {"LB", 1, "10000xxxddd55555", RRI
, LOAD
, BYTE
| SIGNEXTEND
},
908 {"LBU", 1, "10100xxxddd55555", RRI
, LOAD
, BYTE
},
909 {"LD", 3, "00111xxxdddDDDDD", RRI
, LOAD
, DOUBLEWORD
},
910 {"LDPC", 3, "11111100dddDDDDDP", RI64
, LOAD
, DOUBLEWORD
},
911 {"LDSP", 3, "11111000dddDDDDDs", RI64
, LOAD
, DOUBLEWORD
},
912 {"LH", 1, "10001xxxdddHHHHH", RRI
, LOAD
, HALFWORD
| SIGNEXTEND
},
913 {"LHU", 1, "10101xxxdddHHHHH", RRI
, LOAD
, HALFWORD
},
914 {"LI", 1, "01101dddUUUUUUUUZ", RI
, OR
, NONE
},
915 {"LW", 1, "10011xxxdddWWWWW", RRI
, LOAD
, WORD
| SIGNEXTEND
},
916 {"LWPC", 1, "10110dddVVVVVVVVP", RI
, LOAD
, WORD
| SIGNEXTEND
},
917 {"LWSP", 1, "10010dddVVVVVVVVs", RI
, LOAD
, WORD
| SIGNEXTEND
},
918 {"LWU", 1, "10111xxxdddWWWWW", RRI
, LOAD
, WORD
},
919 {"MFHI", 1, "11101ddd00010000", RR
, MOVE
, HI
| LEFT
},
920 {"MFLO", 1, "11101ddd00010010", RR
, MOVE
, LO
| LEFT
},
921 {"MOVR32", 1, "01100111dddXXXXXz", I8_MOVR32
, OR
, NONE
},
922 {"MOV32R", 1, "01100101YYYYYxxxz", I8_MOV32R
, OR
, NONE
},
923 {"MULT", 1, "11101xxxyyy11000", RR
, MUL
, WORD
| WORD32
| HI
| LO
},
924 {"MULTU", 1, "11101xxxyyy11001", RR
, MUL
, WORD
| WORD32
| UNSIGNED
| HI
| LO
},
925 {"NEG", 1, "11101dddyyy01011Z", RR
, SUB
, WORD
},
926 {"NOT", 1, "11101dddyyy01111Z", RR
, OR
, NOT
},
927 {"OR", 1, "11101wwwyyy01101", RR
, OR
, NONE
},
928 {"SB", 1, "11000xxxyyy55555", RRI
, STORE
, BYTE
},
929 {"SD", 3, "01111xxxyyyDDDDD", RRI
, STORE
, DOUBLEWORD
},
930 {"SDSP", 3, "11111001yyyDDDDDs", RI64
, STORE
, DOUBLEWORD
},
931 {"SDRASP", 3, "11111010CCCCCCCCsQ", I64
, STORE
, DOUBLEWORD
},
932 {"SH", 1, "11001xxxyyyHHHHH", RRI
, STORE
, HALFWORD
},
933 {"SLL", 1, "00110dddyyy<<<00", ISHIFT
, SHIFT
, WORD
| LEFT
| LOGICAL
},
934 {"SLLV", 1, "11101xxxvvv00100", RR
, SHIFT
, WORD
| LEFT
| LOGICAL
| REG
},
935 {"SLT", 1, "11101xxxyyy00010T", RR
, SET
, LT
},
936 {"SLTI", 1, "01010xxx88888888T", RI
, SET
, LT
},
937 {"SLTU", 1, "11101xxxyyy00011T", RR
, SET
, LT
| UNSIGNED
},
938 {"SLTIU", 1, "01011xxx88888888T", RI
, SET
, LT
| UNSIGNED
},
939 {"SRA", 1, "00110dddyyy<<<11", ISHIFT
, SHIFT
, WORD
| WORD32
| RIGHT
| ARITHMETIC
},
940 {"SRAV", 1, "11101xxxvvv00111", RR
, SHIFT
, WORD
| WORD32
| RIGHT
| ARITHMETIC
| REG
},
941 {"SRL", 1, "00110dddyyy<<<10", ISHIFT
, SHIFT
, WORD
| WORD32
| RIGHT
| LOGICAL
},
942 {"SRLV", 1, "11101xxxvvv00110", RR
, SHIFT
, WORD
| WORD32
| RIGHT
| LOGICAL
| REG
},
943 {"SUBU", 1, "11100xxxyyyddd11", RRR
, SUB
, WORD
| WORD32
},
944 {"SW", 1, "11011xxxyyyWWWWW", RRI
, STORE
, WORD
},
945 {"SWSP", 1, "11010yyyVVVVVVVVs", RI
, STORE
, WORD
},
946 {"SWRASP", 1, "01100010VVVVVVVVQs", I8
, STORE
, WORD
},
947 {"XOR", 1, "11101wwwyyy01110", RR
, XOR
, NONE
}
950 static int bitmap_val
PARAMS ((const char *, int, int));
951 static void build_mips16_operands
PARAMS ((const char *));
952 static void build_instruction
953 PARAMS ((int, unsigned int, int, const struct instruction
*));
955 /*---------------------------------------------------------------------------*/
958 name_for_data_len( insn
)
959 struct instruction
* insn
;
961 if (GETDATASIZEINSN(insn
) == BYTE
)
964 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
967 else if (GETDATASIZEINSN(insn
) == WORD
)
970 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
973 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
981 letter_for_data_len( insn
)
982 struct instruction
* insn
;
984 if (GETDATASIZEINSN(insn
) == BYTE
)
987 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
990 else if (GETDATASIZEINSN(insn
) == WORD
)
993 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
996 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1004 type_for_data_len( insn
)
1005 struct instruction
* insn
;
1007 if (GETDATASIZEINSN(insn
) == BYTE
)
1010 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1013 else if (GETDATASIZEINSN(insn
) == WORD
)
1016 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1019 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1027 max_for_data_len( insn
)
1028 struct instruction
* insn
;
1030 if (GETDATASIZEINSN(insn
) == BYTE
)
1033 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1036 else if (GETDATASIZEINSN(insn
) == WORD
)
1037 return "(int)0x7FFFFFFF";
1039 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1042 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1050 min_for_data_len( insn
)
1051 struct instruction
* insn
;
1053 if (GETDATASIZEINSN(insn
) == BYTE
)
1056 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1059 else if (GETDATASIZEINSN(insn
) == WORD
)
1060 return "(int)0x80000000";
1062 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1065 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1073 umax_for_data_len( insn
)
1074 struct instruction
* insn
;
1076 if (GETDATASIZEINSN(insn
) == BYTE
)
1079 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1082 else if (GETDATASIZEINSN(insn
) == WORD
)
1083 return "0xFFFFFFFF";
1085 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1088 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1096 bits_for_data_len( insn
)
1097 struct instruction
* insn
;
1099 if (GETDATASIZEINSN(insn
) == BYTE
)
1102 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1105 else if (GETDATASIZEINSN(insn
) == WORD
)
1108 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1111 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1118 /*---------------------------------------------------------------------------*/
1122 convert_bitmap(bitmap
,onemask
,zeromask
,dontmask
)
1124 unsigned int *onemask
, *zeromask
, *dontmask
;
1126 int loop
; /* current bitmap position */
1127 int lastsp
= -1; /* last bitmap field starting position */
1128 int lastoe
= -1; /* last bitmap field encoding */
1130 *onemask
= 0x00000000;
1131 *zeromask
= 0x00000000;
1132 *dontmask
= 0x00000000;
1134 if (strlen(bitmap
) != 32) {
1135 fprintf(stderr
,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap
);
1139 for (loop
= 0; (loop
< 32); loop
++) {
1141 for (oefield
= 0; (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))); oefield
++)
1142 if (bitmap
[31 - loop
] == opfields
[oefield
].id
)
1144 if (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))) {
1145 if ((lastoe
!= -1) && (lastoe
!= oefield
))
1146 if ((loop
- lastsp
) != (opfields
[lastoe
].flen
)) {
1147 fprintf(stderr
,"Invalid field length %d for bitmap field '%c' (0x%02X) (should be %d) : bitmap = \"%s\"\n",(loop
- lastsp
),(((bitmap
[31 - loop
] < 0x20) || (bitmap
[31 - loop
] >= 0x7F)) ? '.' : bitmap
[31 - loop
]),bitmap
[31 - loop
],opfields
[lastoe
].flen
,bitmap
);
1151 switch (bitmap
[31 - loop
]) {
1152 case '0' : /* fixed value */
1153 *zeromask
|= (1 << loop
);
1158 case '1' : /* fixed value */
1159 *onemask
|= (1 << loop
);
1164 case '?' : /* fixed value */
1165 *dontmask
|= (1 << loop
);
1170 default : /* check character encoding */
1172 if (opfields
[oefield
].fpos
!= -1) {
1173 /* If flag not set, then check starting position: */
1174 if (lastoe
!= oefield
) {
1175 if (loop
!= opfields
[oefield
].fpos
) {
1176 fprintf(stderr
,"Bitmap field '%c' (0x%02X) at wrong offset %d in bitmap \"%s\"\n",(((bitmap
[31 - loop
] < 0x20) || (bitmap
[31 - loop
] >= 0x7F)) ? '.' : bitmap
[31 - loop
]),bitmap
[31 - loop
],loop
,bitmap
);
1183 *dontmask
|= (1 << loop
);
1188 fprintf(stderr
,"Unrecognised bitmap character '%c' (0x%02X) at offset %d in bitmap \"%s\"\n",(((bitmap
[31 - loop
] < 0x20) || (bitmap
[31 - loop
] >= 0x7F)) ? '.' : bitmap
[31 - loop
]),bitmap
[31 - loop
],loop
,bitmap
);
1193 /* NOTE: Since we check for the position and size of fields when
1194 parsing the "bitmap" above, we do *NOT* need to check that invalid
1195 field combinations have been used. */
1198 /* Get the value of a 16 bit bitstring for a given shift count and
1202 bitmap_val (bitmap
, shift
, bits
)
1211 s
= bitmap
+ 16 - shift
- bits
;
1212 for (; bits
> 0; --bits
)
1227 /*---------------------------------------------------------------------------*/
1230 build_operands(doisa
,features
,insn
)
1232 unsigned int features
;
1235 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
1236 int finish_jump_flag
= 0;
1238 int check_condition_code
= 0;
1239 int sfield_used
= 0;
1240 int gfield_used
= 0;
1241 int any_operand
= 0;
1243 int current_field_id
= -1;
1246 for (bitpos
=0; bitpos
<32; bitpos
++) {
1247 if (insn
->bitmap
[31-bitpos
] != current_field_id
)
1251 current_field_id
= insn
->bitmap
[31-bitpos
];
1253 for (opindex
= 0; (opindex
< (sizeof(opfields
) / sizeof(operand_encoding
))); opindex
++)
1254 if ((opfields
[opindex
].fpos
!= -1) && (opfields
[opindex
].id
== insn
->bitmap
[31-bitpos
])) {
1258 printf(" %s %s UNUSED = ",opfields
[opindex
].type
,opfields
[opindex
].name
);
1260 if (opfields
[opindex
].flags
& OP_SIGNX
)
1261 printf("SIGNEXTEND((%s)",opfields
[opindex
].type
);
1263 if (opfields
[opindex
].flags
& OP_GPR
)
1266 if (opfields
[opindex
].flags
& OP_SHIFT2
)
1269 printf("((instruction >> %d) & 0x%08X)",opfields
[opindex
].fpos
,((1 << opfields
[opindex
].flen
) - 1));
1271 if (opfields
[opindex
].flags
& OP_SHIFT2
)
1274 if (opfields
[opindex
].flags
& OP_GPR
)
1277 if (opfields
[opindex
].flags
& OP_BITS5
)
1280 if (opfields
[opindex
].flags
& OP_SIGNX
)
1281 printf(",%d)",(opfields
[opindex
].flen
+ ((opfields
[opindex
].flags
& OP_SHIFT2
) ? 2 : 0)));
1285 if (opfields
[opindex
].flags
& OP_GPR1
)
1287 printf(" %s %s1 = GPR1[",opfields
[opindex
].type
,opfields
[opindex
].name
);
1288 printf("((instruction >> %d) & 0x%08X)",
1289 opfields
[opindex
].fpos
,
1290 ((1 << opfields
[opindex
].flen
) - 1));
1294 if (opfields
[opindex
].id
== 'j')
1295 finish_jump_flag
= 1;
1297 if (opfields
[opindex
].id
== 'e')
1300 if (opfields
[opindex
].id
== 'w')
1303 if (opfields
[opindex
].id
== 'w')
1306 if (opfields
[opindex
].id
== 'p')
1307 check_condition_code
= 1;
1309 if (opfields
[opindex
].id
== 's')
1312 if (opfields
[opindex
].id
== 'g')
1318 if ( !any_operand
&& !(insn
->flags
& NOARG
)) {
1319 fprintf(stderr
,"Bitmap error: Instruction with no operand fields \"%s\"\n",insn
->name
) ;
1323 /* Finish constructing the jump address if required: */
1324 if (finish_jump_flag
)
1325 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
1327 /* Now perform required operand checks: */
1329 /* The following code has been removed, since it seems perfectly
1330 reasonable to have a non-aligned offset that is added to another
1331 non-aligned base to create an aligned address. Some more
1332 information on exactly what the MIPS IV specification requires is
1333 needed before deciding on the best strategy. Experimentation with a
1334 VR4300 suggests that we do not need to raise the warning. */
1336 /* For MIPS IV (and onwards), certain instruction operand values
1337 will give undefined results. For the simulator we could
1338 generate explicit exceptions (i.e. ReservedInstruction) to
1339 make it easier to spot invalid use. However, for the moment we
1340 just raise a warning. NOTE: This is a different check to the
1341 later decoding, which checks for the final address being
1344 if (check_mult
!= 0 && check_mult
!= 1) {
1345 printf(" if (instruction & 0x%1X)\n", check_mult
);
1347 /* NOTE: If we change this to a SignalException(), we must
1348 ensure that the following opcode processing is not
1349 executed. i.e. the code falls straight out to the simulator
1351 printf(" sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
1356 /* The extended condition codes only appeared in ISA IV */
1357 if (check_condition_code
&& (doisa
< 4)) {
1358 printf(" if (condition_code != 0)\n");
1360 printf(" SignalException(ReservedInstruction,instruction);\n");
1365 if ((insn
->flags
& WORD32
) && (GETDATASIZEINSN(insn
) != WORD
)) {
1366 fprintf(stderr
,"Error in opcode table: WORD32 set for non-WORD opcode\n");
1371 /* The R4000 book differs slightly from the MIPS IV ISA
1372 manual. An example is the sign-extension of a 64-bit processor
1373 SUBU operation, and what is meant by an Undefined Result. This
1374 is now provided purely as a warning. After examining a HW
1375 implementation, this is now purely a warning... and the actual
1376 operation is performed, with possibly undefined results. */
1377 if (((insn
->flags
& WORD32
) && proc64
) && (features
& FEATURE_WARN_RESULT
)) {
1378 /* The compiler should optimise out an OR with zero */
1379 printf(" if (%s | %s)\n",(sfield_used
? "NOTWORDVALUE(op1)" : "0"),(gfield_used
? "NOTWORDVALUE(op2)" : "0"));
1380 printf(" UndefinedResult();\n") ;
1383 /* Check that the source is a 32bit value */
1384 if ((insn
->flags
& WORD32
) && proc64
) {
1385 /* The compiler should optimise out an OR with zero */
1386 printf(" if (%s | %s)\n",(sfield_used
? "NOTWORDVALUE(op1)" : "0"),(gfield_used
? "NOTWORDVALUE(op2)" : "0"));
1387 printf(" UndefinedResult();\n") ;
1395 /* The mips16 operand table. */
1399 /* The character which appears in the bitmap string. */
1401 /* The type of the variable in the simulator. */
1402 const char *vartype
;
1403 /* The name of the variable in the simulator. */
1405 /* The number of bits. */
1407 /* The number of bits when extended (zero if can not be extended). */
1409 /* The amount by which the short form is shifted when it is used;
1410 for example, the sw instruction has a shift count of 2. */
1416 /* Flags which appears in the mips16 operand table. */
1418 /* Whether this is a mips16 register index. */
1419 #define MIPS16_REG16 (0x1)
1420 /* Whether this is a register value. */
1421 #define MIPS16_REGVAL (0x2)
1422 /* Whether this is a swapped mips32 register index (MOV32R) */
1423 #define MIPS16_REG32_SWAPPED (0x4)
1424 /* Whether this index is also the destination register. */
1425 #define MIPS16_DESTREG (0x8)
1426 /* Whether the short form is unsigned. */
1427 #define MIPS16_UNSP (0x10)
1428 /* Whether the extended form is unsigned. */
1429 #define MIPS16_EXTU (0x20)
1430 /* Implicit stack pointer. */
1431 #define MIPS16_SP (0x40)
1432 /* Implicit program counter. */
1433 #define MIPS16_PC (0x80)
1435 #define MIPS16_ZERO (0x100)
1437 #define MIPS16_TREG (0x200)
1439 #define MIPS16_RA (0x400)
1441 #define MIPS16_JUMP_ADDR (0x800)
1442 /* Branch offset. */
1443 #define MIPS16_BRANCH (0x1000)
1445 /* The mips16 operand table. */
1447 static const struct mips16_op mips16_op_table
[] =
1449 { 'd', "int", "destreg", 3, 0, 0, MIPS16_REG16
},
1450 { 'x', "t_reg", "op1", 3, 0, 0, MIPS16_REG16
| MIPS16_REGVAL
},
1451 { 'w', "t_reg", "op1", 3, 0, 0, MIPS16_REG16
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1452 { 'y', "t_reg", "op2", 3, 0, 0, MIPS16_REG16
| MIPS16_REGVAL
},
1453 { 'v', "t_reg", "op2", 3, 0, 0, MIPS16_REG16
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1454 { 'X', "t_reg", "op1", 5, 0, 0, MIPS16_REGVAL
},
1455 { 'Y', "int", "destreg", 5, 0, 0, MIPS16_REG32_SWAPPED
},
1456 { 'a', "ut_reg", "op1", 11, 0, 0, MIPS16_JUMP_ADDR
},
1457 { 'e', "int", "ext", 11, 0, 0, 0 },
1458 { '<', "int", "op1", 3, 5, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1459 { '>', "int", "op1", 3, 5, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1460 { '[', "int", "op1", 3, 6, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1461 { ']', "int", "op1", 3, 6, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1462 { '4', "int", "op2", 4, 15, 0, 0 },
1463 { '5', "int", "offset", 5, 16, 0, MIPS16_UNSP
},
1464 { 'H', "int", "offset", 5, 16, 1, MIPS16_UNSP
},
1465 { 'W', "int", "offset", 5, 16, 2, MIPS16_UNSP
},
1466 { 'D', "int", "offset", 5, 16, 3, MIPS16_UNSP
},
1467 { 'j', "int", "op2", 5, 16, 0, 0 },
1468 { '8', "int", "op2", 8, 16, 0, MIPS16_UNSP
},
1469 { 'V', "int", "offset", 8, 16, 2, MIPS16_UNSP
},
1470 { 'C', "int", "offset", 8, 16, 3, MIPS16_UNSP
},
1471 { 'U', "int", "op2", 8, 16, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1472 { 'k', "int", "op2", 8, 16, 0, 0 },
1473 { 'K', "int", "op2", 8, 16, 3, 0 },
1474 { 'p', "int", "offset", 8, 16, 0, MIPS16_BRANCH
},
1475 { 'q', "int", "offset", 11, 16, 0, MIPS16_BRANCH
},
1476 { 'A', "int", "op2", 8, 16, 2, MIPS16_UNSP
},
1477 { 'B', "int", "op2", 5, 16, 3, MIPS16_UNSP
},
1478 { 'E', "int", "op2", 5, 16, 2, MIPS16_UNSP
},
1480 /* The remaining operands are special operands which encode implied
1481 arguments. These only appear at the end of a bitmap string, and
1482 do not represent actual bits. */
1483 { 's', "t_reg", "op1", 0, 0, 0, MIPS16_SP
| MIPS16_REGVAL
},
1484 { 'S', "t_reg", "op1", 0, 0, 0, MIPS16_SP
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1485 { 'P', "t_reg", "op1", 0, 0, 0, MIPS16_PC
},
1486 { 'z', "t_reg", "op2", 0, 0, 0, MIPS16_ZERO
},
1487 { 'Z', "t_reg", "op1", 0, 0, 0, MIPS16_ZERO
},
1488 { 't', "t_reg", "op1", 0, 0, 0, MIPS16_TREG
| MIPS16_REGVAL
},
1489 { 'T', "int", "destreg", 0, 0, 0, MIPS16_TREG
},
1490 { 'r', "t_reg", "op1", 0, 0, 0, MIPS16_RA
| MIPS16_REGVAL
},
1491 { 'R', "int", "destreg", 0, 0, 0, MIPS16_RA
},
1492 { 'Q', "t_reg", "op2", 0, 0, 0, MIPS16_RA
| MIPS16_REGVAL
},
1494 { '\0', NULL
, NULL
, 0, 0, 0, 0 }
1497 /* Build mips16 operands. */
1500 build_mips16_operands (bitmap
)
1505 const struct mips16_op
*op
= NULL
;
1506 const struct mips16_op
*ops
[3];
1510 for (s
= bitmap
; *s
!= '\0'; s
++)
1517 /* Make sure we saw the right number of bits for that
1519 if (op
->nbits
!= 0 && (s
- bitmap
) - op
->nbits
!= start
)
1524 if (*s
== '0' || *s
== '1' || *s
== '?')
1529 for (op
= mips16_op_table
; op
->type
!= *s
; ++op
)
1530 if (op
->type
== '\0')
1533 printf (" %s %s = ", op
->vartype
, op
->name
);
1535 printf ("(instruction >> %d) & 0x%x",
1536 16 - (s
- bitmap
) - op
->nbits
,
1537 (1 << op
->nbits
) - 1);
1540 if ((op
->flags
& MIPS16_SP
) != 0)
1542 else if ((op
->flags
& MIPS16_PC
) != 0)
1546 printf ("((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : (have_extendval ? IPC - 2 : IPC)) & ~ (uword64) 1)");
1547 for (j
= 0; j
< opindex
; j
++)
1548 if (ops
[j
]->shift
!= 0)
1549 printf (" & ~ (uword64) 0x%x", (1 << ops
[j
]->shift
) - 1);
1551 else if ((op
->flags
& MIPS16_ZERO
) != 0)
1553 else if ((op
->flags
& MIPS16_TREG
) != 0)
1555 else if ((op
->flags
& MIPS16_RA
) != 0)
1562 if ((op
->flags
& MIPS16_DESTREG
) != 0)
1563 printf (" int destreg;\n");
1573 /* Make sure we saw the right number of bits for that
1575 if (op
->nbits
!= 0 && 16 - op
->nbits
!= start
)
1579 for (i
= 0; i
< opindex
; i
++)
1582 if ((op
->flags
& MIPS16_REG16
) != 0)
1584 printf (" if (%s < 2)\n", op
->name
);
1585 printf (" %s += 16;\n", op
->name
);
1587 if ((op
->flags
& MIPS16_REG32_SWAPPED
) != 0)
1588 printf (" %s = (%s >> 2) | ((%s & 3) << 3);\n",
1589 op
->name
, op
->name
, op
->name
);
1590 if ((op
->flags
& MIPS16_DESTREG
) != 0)
1591 printf (" destreg = %s;\n", op
->name
);
1592 if ((op
->flags
& MIPS16_REGVAL
) != 0)
1593 printf (" %s = GPR[%s];\n", op
->name
, op
->name
);
1595 if (op
->extbits
!= 0)
1597 printf (" if (have_extendval)\n");
1599 if (op
->extbits
== 16)
1600 printf (" %s |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0);\n",
1602 else if (op
->extbits
== 15)
1603 printf (" %s |= ((extendval & 0xf) << 11) | (extendval & 0x7f0);\n",
1605 else if (op
->extbits
== 6)
1606 printf (" %s = ((extendval >> 6) & 0x1f) | (extendval & 0x20);\n",
1609 printf (" %s = (extendval >> 6) & 0x1f;\n",
1611 if ((op
->flags
& MIPS16_EXTU
) == 0)
1613 printf (" if (%s >= 0x%x)\n",
1614 op
->name
, 1 << (op
->extbits
- 1));
1615 printf (" %s -= 0x%x;\n",
1616 op
->name
, 1 << op
->extbits
);
1618 printf (" have_extendval = 0;\n");
1622 if ((op
->flags
& MIPS16_UNSP
) == 0)
1624 printf (" if (%s >= 0x%x)\n",
1625 op
->name
, 1 << (op
->nbits
- 1));
1626 printf (" %s -= 0x%x;\n",
1627 op
->name
, 1 << op
->nbits
);
1630 printf (" %s <<= %d;\n", op
->name
, op
->shift
);
1631 if (op
->type
== '<' || op
->type
== '>'
1632 || op
->type
== '[' || op
->type
== ']')
1634 printf (" if (%s == 0)\n", op
->name
);
1635 printf (" %s = 8;\n", op
->name
);
1640 if ((op
->flags
& MIPS16_BRANCH
) != 0)
1641 printf (" %s *= 2;\n", op
->name
);
1643 if ((op
->flags
& MIPS16_JUMP_ADDR
) != 0)
1646 printf (" uword64 paddr;\n");
1647 printf (" int uncached;\n");
1648 printf (" if (AddressTranslation (PC &~ (uword64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL))\n");
1650 printf (" uword64 memval;\n");
1651 printf (" unsigned int reverse = (ReverseEndian ? 3 : 0);\n");
1652 printf (" unsigned int bigend = (BigEndianCPU ? 3 : 0);\n");
1653 printf (" unsigned int byte;\n");
1654 printf (" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\n");
1655 printf (" LoadMemory (&memval,0,uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
1656 printf (" byte = (((PC &~ (uword64) 1) & 0x7) ^ (bigend << 1));\n");
1657 printf (" memval = (memval >> (8 * byte)) & 0xffff;\n");
1658 printf (" %s = (((%s & 0x1f) << 23)\n", op
->name
, op
->name
);
1659 printf (" | ((%s & 0x3e0) << 13)\n", op
->name
);
1660 printf (" | (memval << 2));\n");
1661 printf (" if ((instruction & 0x400) == 0)\n");
1662 printf (" %s |= 1;\n", op
->name
);
1663 printf (" PC += 2;\n");
1666 printf (" %s |= PC & ~ (uword64) 0x0fffffff;\n", op
->name
);
1670 /* FIXME: Is this the way to detect an unused extend opcode? */
1671 printf (" if (have_extendval)\n");
1672 printf (" SignalException (ReservedInstruction, instruction);\n");
1675 /*---------------------------------------------------------------------------*/
1683 build_endian_shift(proc64
,datalen
,endbit
,direction
,shift
)
1687 e_endshift direction
;
1691 printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit
,endbit
);
1692 printf(" memval %s= %d;\n",direction
== s_left
? "<<" : ">>",shift
);
1699 /*---------------------------------------------------------------------------*/
1700 /* doisa = number of MIPS ISA simulator table is being constructed for.
1701 * proc64 = TRUE if constructing 64bit processor world.
1702 * dofp = boolean, TRUE if FP instructions are to be included.
1703 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
1707 process_instructions(doarch
,features
)
1708 unsigned int doarch
;
1709 unsigned int features
;
1711 int doisa
= (doarch
& MASK_ISA
);
1712 int limit
= (sizeof(MIPS_DECODE
) / sizeof(instruction
));
1713 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
1714 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
1715 int dofp
= (features
& FEATURE_HASFPU
);
1716 int fpsingle
= (features
& FEATURE_FPSINGLE
);
1721 fprintf(stderr
,"process_instructions: invalid structure length\n");
1725 if (proc64
&& (gprlen
!= 64)) {
1726 fprintf(stderr
,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
1730 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
1733 for (loop
= 0; (loop
< limit
); loop
++)
1734 if ((MIPS_DECODE
[loop
].isa
& MASK_ISA
) > maxisa
)
1735 maxisa
= (MIPS_DECODE
[loop
].isa
& MASK_ISA
);
1740 printf("#if defined(SIM_MANIFESTS)\n");
1741 printf("#define MIPSISA (%d)\n",doisa
);
1743 printf("#define PROCESSOR_64BIT (1 == 1)\n");
1745 printf("#define PROCESSOR_64BIT (1 == 0)\n");
1746 #if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */
1747 printf("#define LOADDRMASK (0x%08X)\n",0x7);
1749 printf("#define LOADDRMASK (0x%08X)\n",(proc64
? 0x7 : 0x3));
1751 /* The FP registers are the same width as the CPU registers: */
1752 printf("#define GPRLEN (%d)\n",gprlen
);
1753 printf("typedef %s t_reg;\n",((gprlen
== 64) ? "word64" : "int"));
1754 printf("typedef %s ut_reg;\n",((gprlen
== 64) ? "uword64" : "unsigned int"));
1755 printf("typedef %s t_fpreg;\n",((gprlen
== 64) ? "word64" : "int"));
1757 printf("#define HASFPU (1 == 1)\n");
1758 if (features
& FEATURE_FAST
)
1759 printf("#define FASTSIM (1 == 1)\n");
1760 if (features
& FEATURE_WARN_STALL
)
1761 printf("#define WARN_STALL (1 == 1)\n");
1762 if (features
& FEATURE_WARN_LOHI
)
1763 printf("#define WARN_LOHI (1 == 1)\n");
1764 if (features
& FEATURE_WARN_ZERO
)
1765 printf("#define WARN_ZERO (1 == 1)\n");
1766 if (features
& FEATURE_WARN_MEM
)
1767 printf("#define WARN_MEM (1 == 1)\n");
1768 if (features
& FEATURE_WARN_R31
)
1769 printf("#define WARN_R31 (1 == 1)\n");
1770 if (features
& FEATURE_WARN_RESULT
)
1771 printf("#define WARN_RESULT (1 == 1)\n");
1773 printf("#else /* simulator engine */\n");
1775 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
1776 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64
? 64 : 32),doisa
,limit
);
1778 printf("/* %sFP instructions included */\n",(fpsingle
? "Single precision " : ""));
1779 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
1782 printf("#if !defined(PROCESSOR_64BIT)\n");
1783 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
1787 printf("/* Actual instruction decoding block */\n");
1788 printf("if ((vaddr & 1) == 0){\n");
1791 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP
,OP_MASK_OP
);
1792 limit
= (OP_MASK_OP
+ 1);
1794 printf("#ifdef DEBUG\n");
1795 printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n");
1798 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
1799 limit
+= (OP_MASK_SPEC
+ 1);
1801 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_RT
,OP_MASK_RT
);
1802 limit
+= (OP_MASK_RT
+ 1);
1804 printf("else if (num == 0x11) {\n");
1805 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM
,OP_SH_COP1NORM
,(OP_MASK_COP1NORM
<< OP_SH_COP1NORM
));
1806 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP
,OP_SH_COP1CMP
,(OP_MASK_COP1CMP
<< OP_SH_COP1CMP
));
1807 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,(OP_MASK_SPEC
& (OP_MASK_COP1CMP
<< OP_SH_COP1CMP
)));
1809 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
1810 limit
+= (OP_MASK_SPEC
+ 1);
1813 /* To keep this code quick, we just clear out the "to" bit
1814 here. The proper (though slower) code would be to have another
1815 conditional, checking whether this instruction is a branch or
1816 not, before limiting the range to the bottom two bits of the
1818 printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit
,OP_SH_COP1SPEC
,OP_MASK_COP1SPEC
,OP_MASK_COP1SCLR
);
1819 limit
+= (OP_MASK_COP1SPEC
+ 1);
1821 printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
1822 limit
+= (OP_MASK_SPEC
+ 1);
1824 printf("else if (num == 0x1C) {\n");
1825 printf(" int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI
,OP_MASK_MMI
);
1827 printf(" if (mmi_func == 0x08) \n");
1828 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
1829 limit
+= (OP_MASK_MMISUB
+ 1);
1831 printf(" else if (mmi_func == 0x28) \n");
1832 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
1833 limit
+= (OP_MASK_MMISUB
+ 1);
1835 printf(" else if (mmi_func == 0x09) \n");
1836 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
1837 limit
+= (OP_MASK_MMISUB
+ 1);
1839 printf(" else if (mmi_func == 0x29) \n");
1840 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
1841 limit
+= (OP_MASK_MMISUB
+ 1);
1844 printf(" num = (%d + mmi_func);\n",limit
);
1845 limit
+= (OP_MASK_MMI
+ 1);
1849 printf("/* Total possible switch entries: %d */\n",limit
) ;
1852 printf("#ifdef DEBUG\n");
1853 printf("printf(\"DBG: num = %%d\\n\",num);\n");
1856 printf("switch (num)\n") ;
1859 for (loop
= 0; (loop
< limit
); loop
++) {
1860 /* First check if the insn is in a requested isa# independent set,
1861 then check that the ISA number we are constructing for is
1862 valid, then if the instruction matches any of the
1863 architecture specific flags. NOTE: We allow a selected ISA of
1864 zero to be used to match all standard instructions. */
1865 unsigned int isa
= MIPS_DECODE
[loop
].isa
;
1866 if (((isa
& doarch
& MASK_ISA_INDEP
)
1867 || (((isa
& MASK_ISA
) <= doisa
)
1868 && (((isa
& MASK_ISA_DEP
) == 0) || ((isa
& MASK_ISA_DEP
) & doarch
) != 0)))
1869 && (!(MIPS_DECODE
[loop
].flags
& FP
) || ((MIPS_DECODE
[loop
].flags
& FP
) && dofp
))) {
1870 unsigned int onemask
;
1871 unsigned int zeromask
;
1872 unsigned int dontmask
;
1874 unsigned int number
;
1876 convert_bitmap(MIPS_DECODE
[loop
].bitmap
,&onemask
,&zeromask
,&dontmask
);
1878 if (!(MIPS_DECODE
[loop
].flags
& COPROC
)
1879 && ((GETDATASIZEINSN(&MIPS_DECODE
[loop
]) == DOUBLEWORD
) && !proc64
)) {
1880 fprintf(stderr
,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE
[loop
].name
);
1885 printf("/* DEBUG: onemask 0x%08X */\n",onemask
) ;
1886 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask
) ;
1887 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask
) ;
1890 switch (MIPS_DECODE
[loop
].mark
) {
1892 mask
= (OP_MASK_OP
<< OP_SH_OP
) ;
1893 number
= ((onemask
>> OP_SH_OP
) & OP_MASK_OP
) ;
1897 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
1898 number
= ((OP_MASK_OP
+ 1) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
1902 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_RT
<< OP_SH_RT
)) ;
1903 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_RT
) & OP_MASK_RT
)) ;
1907 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
1908 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
1912 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_COP1SPEC
<< OP_SH_COP1SPEC
)) ;
1913 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_COP1SPEC
) & OP_MASK_COP1SPEC
)) ;
1917 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
1918 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
1922 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
1923 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
1924 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
1925 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
1926 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
1930 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
1931 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
1932 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
1933 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
1934 + (OP_MASK_MMISUB
+ 1)
1935 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
1939 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
1940 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
1941 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
1942 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
1943 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
1944 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
1948 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
1949 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
1950 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
1951 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
1952 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
1953 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
1957 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)) ;
1958 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
1959 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
1960 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
1961 + (OP_MASK_MMISUB
+ 1)
1962 + ((onemask
>> OP_SH_MMI
) & OP_MASK_MMI
)) ;
1966 fprintf(stderr
,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE
[loop
].mark
,loop
,MIPS_DECODE
[loop
].name
) ;
1970 printf("case %d : /* \"%s\" %s */\n",number
,MIPS_DECODE
[loop
].name
,MIPS_DECODE
[loop
].bitmap
) ;
1973 printf("/* DEBUG: mask 0x%08X */\n",mask
) ;
1974 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE
[loop
].name
);
1977 /* Check if there are any other explicit bits in the instruction: */
1978 if ((~mask
& (onemask
| zeromask
)) != 0x00000000) {
1979 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask
| zeromask
),onemask
) ;
1981 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1988 /* Get hold of the operands */
1989 /* NOTE: If we wanted to make the simulator code smaller, we
1990 * could pull these into a common sequence before we perform
1991 * the instruction decoding. However, this would affect the
1992 * performance since unnecessary field extraction would be
1993 * occurring for certain instructions.
1995 * Also we do not perform checking for multiple definitions of a
1996 * particular operand here, since they are caught by the
1997 * compilation of the produced code.
1999 build_operands(doisa
, features
, &MIPS_DECODE
[loop
]);
2003 build_instruction (doisa
, features
, 0, &MIPS_DECODE
[loop
]);
2007 printf(" break ;\n") ;
2011 printf("default : /* Unrecognised instruction */\n") ;
2012 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2013 printf(" break ;\n") ;
2016 /* Handle mips16 instructions. The switch table looks like this:
2017 0 - 31: I, RI, and RRI instructions by major.
2018 32 - 35: ISHIFT instructions by function + 32
2019 36 - 37: RRI_A instructions by function + 36
2020 38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38
2021 46 - 49: RRR instructions by function + 46
2022 50 - 81: RR instructions by minor + 50 (except for minor == 0)
2023 82 - 89: I64 and RI64 instructions by funct + 82
2024 90 - 97: jalr (RR minor 0) by y + 90
2026 printf ("else {\n");
2027 printf ("static int extendval;\n");
2028 printf ("static int have_extendval;\n");
2029 printf ("int num = ((instruction >> %d) & 0x%08X);\n",
2030 MIPS16OP_SH_OP
, MIPS16OP_MASK_OP
);
2031 printf ("switch (num)\n{\n");
2032 printf ("case 0x6: num = 32 + (instruction & 3); break;\n");
2033 printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n");
2034 printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n");
2035 printf ("case 0x1c: num = 46 + (instruction & 3); break;\n");
2036 printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n");
2037 printf (" if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n");
2038 printf (" break;\n");
2039 printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n");
2040 printf ("default: break;\n}\n");
2041 printf ("switch (num)\n{\n");
2043 for (loop
= 0; loop
< sizeof MIPS16_DECODE
/ sizeof MIPS16_DECODE
[0]; loop
++)
2048 if (! proc64
&& GETDATASIZEINSN (&MIPS16_DECODE
[loop
]) == DOUBLEWORD
)
2051 bitmap
= MIPS16_DECODE
[loop
].bitmap
;
2052 switch (MIPS16_DECODE
[loop
].mark
)
2057 num
= bitmap_val (bitmap
, 11, 5);
2060 num
= 32 + bitmap_val (bitmap
, 0, 2);
2063 num
= 36 + bitmap_val (bitmap
, 4, 1);
2068 num
= 38 + bitmap_val (bitmap
, 8, 3);
2071 num
= 46 + bitmap_val (bitmap
, 0, 2);
2077 minor
= bitmap_val (bitmap
, 0, 5);
2081 num
= 90 + bitmap_val (bitmap
, 5, 3);
2086 num
= 82 + bitmap_val (bitmap
, 8, 3);
2092 printf ("case %d: /* \"%s\" %s */\n", num
, MIPS16_DECODE
[loop
].name
,
2097 build_mips16_operands (bitmap
);
2101 /* build_instruction doesn't know about extend. */
2103 build_instruction (doisa
, features
, 1, &MIPS16_DECODE
[loop
]);
2106 printf (" extendval = ext;\n");
2107 printf (" have_extendval = 1;\n");
2112 printf (" break ;\n") ;
2115 printf ("default : /* Unrecognised instruction */\n") ;
2116 printf (" SignalException(ReservedInstruction,instruction);\n") ;
2117 printf (" break ;\n") ;
2120 printf("#endif /* simulator engine */\n");
2125 /* Output the code to execute an instruction, assuming the operands
2126 have already been extracted. */
2129 build_instruction (doisa
, features
, mips16
, insn
)
2131 unsigned int features
;
2133 const struct instruction
*insn
;
2135 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
2136 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
2137 char *regtype
= ((gprlen
== 64) ? "uword64" : "unsigned int");
2139 switch (insn
->type
) {
2140 /* TODO: To make these easier to edit and maintain, they should
2141 actually be provided as source macros (or inline functions)
2142 OUTSIDE this main switch statement. The PPC simulator has a
2143 neater scheme for describing the instruction sequences. */
2148 char *signed_basetype
= "unknown";
2149 char *unsigned_basetype
= "unknown";
2151 switch (GETDATASIZEINSN(insn
)) {
2153 signed_basetype
= "signed int";
2154 unsigned_basetype
= "unsigned int";
2157 signed_basetype
= "word64";
2158 unsigned_basetype
= "uword64";
2161 fprintf(stderr
,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZEINSN(insn
));
2165 if ((insn
->type
) == ADD
) {
2166 printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype
, unsigned_basetype
);
2167 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype
, signed_basetype
);
2168 if (insn
->flags
& OVERFLOW
) {
2169 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
2170 printf(" SignalException(IntegerOverflow);\n");
2173 if (!proc64
|| (insn
->flags
& UNSIGNED
) || (GETDATASIZEINSN(insn
) == DOUBLEWORD
))
2174 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
2175 else /* only sign-extend when placing 32bit result in 64bit processor */
2176 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
2178 printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype
, unsigned_basetype
);
2179 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype
, signed_basetype
);
2180 if (insn
->flags
& OVERFLOW
) { /* different signs => overflow if result_sign != arg_sign */
2181 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
2182 printf(" SignalException(IntegerOverflow);\n");
2185 /* UNSIGNED 32bit operations on a 64bit processor should
2186 *STILL* be sign-extended. We have cheated in the
2187 data-structure, by not marking it with UNSIGNED, and not
2188 setting OVERFLOW. */
2189 if (!proc64
|| (insn
->flags
& UNSIGNED
) || (GETDATASIZEINSN(insn
) == DOUBLEWORD
))
2190 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
2191 else /* only sign-extend when placing 32bit result in 64bit processor */
2192 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
2199 char* pipe
= (insn
->flags
& PIPE1
) ? "1" : "";
2201 if (features
& FEATURE_WARN_LOHI
) {
2202 printf(" CHECKHILO(\"Multiplication\");\n");
2205 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2206 printf(" uword64 mid;\n");
2207 printf(" uword64 midhi;\n");
2208 printf(" uword64 temp;\n");
2209 if ((insn
->flags
& UNSIGNED
) == 0)
2211 printf(" int sign = 0;\n");
2212 printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n");
2213 printf(" if (op2 < 0) { op2 = - op2; ++sign; }\n");
2215 printf(" LO%s = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n",pipe
);
2216 printf(" HI%s = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n",pipe
);
2217 printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
2218 printf(" midhi = SET64HI(WORD64LO(mid));\n");
2219 printf(" temp = (LO%s + midhi);\n",pipe
);
2220 printf(" if ((temp == midhi) ? (LO%s != 0) : (temp < midhi))\n",pipe
);
2221 printf(" HI%s += 1;\n",pipe
);
2222 printf(" HI%s += WORD64HI(mid);\n",pipe
);
2223 printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
2224 printf(" midhi = SET64HI(WORD64LO(mid));\n");
2225 printf(" LO%s = (temp + midhi);\n",pipe
);
2226 printf(" if ((LO%s == midhi) ? (temp != 0) : (LO%s < midhi))\n",pipe
,pipe
);
2227 printf(" HI%s += 1;\n",pipe
);
2228 printf(" HI%s += WORD64HI(mid);\n",pipe
);
2229 if ((insn
->flags
& UNSIGNED
) == 0)
2230 printf(" if (sign & 1) { LO%s = - LO%s; HI%s = (LO%s == 0 ? 0 : -1) - HI%s; }\n",pipe
,pipe
,pipe
,pipe
,pipe
);
2232 if (insn
->flags
& UNSIGNED
)
2233 printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
2235 printf(" uword64 temp = ((word64) op1 * (word64) op2);\n");
2236 printf(" LO%s = SIGNEXTEND((%s)WORD64LO(temp),32);\n",pipe
,regtype
);
2237 printf(" HI%s = SIGNEXTEND((%s)WORD64HI(temp),32);\n",pipe
,regtype
);
2239 if (insn
->flags
& OP3
)
2241 printf(" if ( destreg != 0 )\n");
2242 printf(" GPR[destreg] = LO%s;\n",pipe
);
2249 int boolU
= (insn
->flags
& UNSIGNED
);
2250 char* pipe
= (insn
->flags
& PIPE1
) ? "1" : "";
2252 if (features
& FEATURE_WARN_LOHI
) {
2253 printf(" CHECKHILO(\"Division\");\n");
2257 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2258 printf(" %sword64 d1 = op1;\n", (boolU
? "u" : ""));
2259 printf(" %sword64 d2 = op2;\n", (boolU
? "u" : ""));
2260 printf(" if (d2 == 0)\n");
2262 printf(" LO%s = 0x8000000000000000LL;\n", pipe
);
2263 printf(" HI%s = 0;\n", pipe
);
2265 printf(" else if (d2 == -1 && d1 == 0x8000000000000000LL)\n");
2267 printf(" LO%s = 0x8000000000000000LL;\n", pipe
);
2268 printf(" HI%s = 0;\n", pipe
);
2272 printf(" LO%s = (d1 / d2);\n", pipe
);
2273 printf(" HI%s = (d1 %% d2);\n", pipe
);
2276 printf(" %sint d1 = op1;\n", (boolU
? "unsigned " : ""));
2277 printf(" %sint d2 = op2;\n", (boolU
? "unsigned " : ""));
2278 printf(" if (d2 == 0)\n");
2280 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe
);
2281 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe
);
2283 printf(" else if (d2 == -1 && d1 == 0x80000000)\n");
2285 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe
);
2286 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe
);
2290 printf(" LO%s = SIGNEXTEND((d1 / d2),32);\n", pipe
);
2291 printf(" HI%s = SIGNEXTEND((d1 %% d2),32);\n", pipe
);
2300 int datalen
= GETDATASIZEINSN(insn
);
2301 int bits
= ((datalen
== WORD
) ? 32 : 64);
2302 char *ltype
= ((datalen
== WORD
) ? "unsigned int" : "uword64");
2304 /* Check that the specified SHIFT is valid: */
2305 if ((datalen
== BYTE
) || (datalen
== HALFWORD
)) {
2306 fprintf(stderr
,"Shift \"%s\" specified with BYTE or HALFWORD\n",insn
->name
);
2309 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
2310 fprintf(stderr
,"Shift \"%s\" specified with both LEFT and RIGHT\n",insn
->name
);
2313 if (!(insn
->flags
& LEFT
) && !(insn
->flags
& RIGHT
)) {
2314 fprintf(stderr
,"Shift \"%s\" specified with neither LEFT or RIGHT\n",insn
->name
);
2317 if ((insn
->flags
& LOGICAL
) && (insn
->flags
& ARITHMETIC
)) {
2318 fprintf(stderr
,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",insn
->name
);
2321 if (!(insn
->flags
& LOGICAL
) && !(insn
->flags
& ARITHMETIC
)) {
2322 fprintf(stderr
,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",insn
->name
);
2325 if ((insn
->flags
& LEFT
) && (insn
->flags
& ARITHMETIC
)) {
2326 fprintf(stderr
,"Arithmetic LEFT shift \"%s\" specified\n",insn
->name
);
2330 /* Work around an MSC code generation bug by precomputing a value
2331 * with the sign bit set. */
2332 if (insn
->flags
& ARITHMETIC
)
2333 printf(" %s highbit = (%s)1 << %d;\n", ltype
, ltype
, bits
- 1);
2335 /* If register specified shift, then extract the relevant shift amount: */
2336 if (insn
->flags
& REG
)
2337 printf(" op1 &= 0x%02X;\n",(bits
- 1));
2339 /* If HI32 specified, then shift range is 32..63 */
2340 if (insn
->flags
& HI32
)
2341 printf(" op1 |= (1 << 5);\n");
2343 /* We do not need to perform pre-masking with 0xFFFFFFFF when
2344 dealing with 32bit shift lefts, since the sign-extension
2345 code will replace any remaining hi-bits: */
2346 if (insn
->flags
& LEFT
)
2347 printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
2349 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits
== 32) ? " & 0xFFFFFFFF" : ""));
2351 /* For ARITHMETIC shifts, we must duplicate the sign-bit. We
2352 don't do this if op1 is zero, since it is not needed and
2353 since that would cause an undefined shift of the number of
2354 bits in the type. */
2355 if (insn
->flags
& ARITHMETIC
)
2356 printf(" GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype
,bits
);
2358 /* Ensure WORD values are sign-extended into 64bit registers */
2359 if ((bits
== 32) && (gprlen
== 64))
2360 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits
);
2365 if (insn
->flags
& (HI
| LO
)) {
2366 char *regname
= ((insn
->flags
& LO
) ? "LO" : "HI");
2367 int pipe1
= (insn
->flags
& PIPE1
);
2368 if (insn
->flags
& LEFT
)
2369 printf(" GPR[destreg] = %s%s;\n",regname
,(pipe1
? "1" : ""));
2371 if (features
& FEATURE_WARN_LOHI
) {
2372 printf(" if (%s%sACCESS != 0)\n",regname
,(pipe1
? "1" : ""));
2373 printf(" sim_warning(\"MT (move-to) over-writing %s register value\");\n",regname
);
2375 printf(" %s%s = op1;\n",regname
,(pipe1
? "1" : ""));
2377 if (features
& FEATURE_WARN_LOHI
)
2378 printf(" %s%sACCESS = 3; /* 3rd instruction will be safe */\n",regname
,(pipe1
? "1" : ""));
2380 if (insn
->flags
& SHIFT16
)
2381 printf(" GPR[destreg] = (op2 << 16);\n");
2383 /* perform conditional move */
2384 if (!(insn
->flags
& EQ
)) {
2385 fprintf(stderr
,"Standard conditional %s does not have the equality flag\n",insn
->name
);
2388 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
2389 printf(" GPR[destreg] = op1;\n");
2394 printf(" SyncOperation(op1);\n");
2398 printf(" SignalException(SystemCall,instruction);\n");
2402 printf(" SignalException(BreakPoint,instruction);\n");
2407 int boolNOT
= (insn
->flags
& NOT
);
2408 int boolEQ
= (insn
->flags
& EQ
);
2409 int boolGT
= (insn
->flags
& GT
);
2410 int boolLT
= (insn
->flags
& LT
);
2411 int boolU
= (insn
->flags
& UNSIGNED
);
2413 if (boolGT
&& boolLT
) {
2414 fprintf(stderr
,"GT and LT specified for \"%s\"\n",insn
->name
);
2418 if (boolNOT
&& (boolGT
|| boolLT
)) {
2419 fprintf(stderr
,"NOT specified with GT or LT specified for \"%s\"\n",insn
->name
);
2423 printf(" if ((%sword64)op1 ",(boolU
? "u" : ""));
2424 printf("%c%s",(boolNOT
? '!' : (boolLT
? '<' : (boolGT
? '>' : '='))),(boolEQ
? "=" : ""));
2425 printf(" (%sword64)op2)\n",(boolU
? "u" : ""));
2426 printf(" SignalException(Trap,instruction);\n");
2432 int boolU
= (insn
->flags
& UNSIGNED
);
2434 if (!(insn
->flags
& LT
)) {
2435 fprintf(stderr
,"Set instruction without LT specified \"%s\"\n",insn
->name
);
2439 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU
? "u" : ""),(boolU
? "u" : ""));
2440 printf(" GPR[destreg] = 1;\n");
2442 printf(" GPR[destreg] = 0;\n");
2447 printf(" GPR[destreg] = (op1 & op2);\n");
2451 /* The default mips16 nop instruction does an or to register
2452 zero; catch that case, so that we don't get useless warnings
2453 from the simulator. */
2455 printf (" if (destreg != 0)\n");
2456 printf(" GPR[destreg] = %s(op1 | op2);\n",((insn
->flags
& NOT
) ? "~" : ""));
2460 printf(" GPR[destreg] = (op1 ^ op2);\n");
2464 printf(" decode_coproc(instruction);\n");
2468 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
2469 /* The virtual address is translated to a physical address using the TLB */
2470 /* The hint specifies a cache operation for that address */
2471 printf(" uword64 vaddr = (op1 + offset);\n");
2472 printf(" uword64 paddr;\n");
2473 printf(" int uncached;\n");
2474 /* NOTE: We are assuming that the AddressTranslation is a load: */
2475 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2476 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
2479 case MADD16
: /* VR4100 specific multiply-add instructions */
2480 /* Some of this code is shared with the standard multiply
2481 routines, so an effort should be made to merge where
2483 if (features
& FEATURE_WARN_LOHI
) {
2484 printf(" CHECKHILO(\"Multiply-Add\");\n");
2486 if (features
& FEATURE_WARN_RESULT
) {
2487 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
2488 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
2489 printf(" sim_warning(\"MADD16 operation with non-16bit operands\");\n");
2492 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
2493 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2494 printf(" LO = LO + temp;\n");
2496 printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
2497 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype
);
2498 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype
);
2503 case RSVD
: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
2505 printf(" if (CoProcPresent(3))\n");
2506 printf(" SignalException(CoProcessorUnusable);\n");
2509 printf(" SignalException(ReservedInstruction,instruction);\n");
2513 if (insn
->flags
& LINK
) {
2514 if (!(insn
->flags
& REG
))
2515 printf(" int destreg = 31;\n");
2516 printf(" GPR[destreg] = (PC + %d); /* NOTE: The PC is already %d ahead within the simulator */\n",
2517 mips16
? 2 : 4, mips16
? 2 : 4);
2520 if (insn
->flags
& NOT
)
2521 printf(" op1 ^= 1;\n");
2523 printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n");
2524 printf(" so we just truncate it to 32 bits here. */\n");
2525 printf(" op1 = WORD64LO(op1);\n");
2526 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
2527 printf(" DSPC = op1;\n");
2528 if (insn
->flags
& LINK
)
2529 printf(" JALDELAYSLOT();\n");
2531 printf(" DELAYSLOT();\n");
2534 case BRANCH
: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
2535 if (insn
->flags
& FP
) {
2537 printf(" if (condition_code != 0)\n");
2538 printf(" SignalException(ReservedInstruction,instruction);\n");
2539 printf(" else {\n");
2541 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
2542 printf(" int condition = (%s == boolean);\n",((doisa
< 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
2544 if ((insn
->flags
& NOT
) && !(insn
->flags
& EQ
)) {
2545 fprintf(stderr
,"NOT specified when not EQ in \"%s\"\n",insn
->name
);
2548 if ((insn
->flags
& NOT
) && (insn
->flags
& (GT
| LT
))) {
2549 fprintf(stderr
,"NOT specified with GT or LT in \"%s\"\n",insn
->name
);
2553 if (insn
->flags
& GT
)
2554 printf(" int condition = (op1 >%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
2556 if (insn
->flags
& LT
)
2557 printf(" int condition = (op1 <%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
2559 if (insn
->flags
& EQ
)
2560 printf(" int condition = (op1 %c= op2);\n",((insn
->flags
& NOT
) ? '!' : '='));
2563 if (insn
->flags
& LINK
) {
2564 if (features
& FEATURE_WARN_R31
) {
2565 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS
,OP_MASK_RS
);
2566 printf(" sim_warning(\"Branch with link using r31 as source operand\");\n");
2568 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
2572 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
2573 printf(" if (condition) {\n");
2574 printf(" DSPC = (PC + offset);\n");
2575 printf(" DELAYSLOT();\n");
2578 /* No delayed slots for mips16 branches. */
2579 printf(" if (condition)\n");
2580 printf(" PC = PC + offset;\n");
2582 if ((insn
->flags
& FP
) && (doisa
!= 1)) {
2583 printf(" else if (likely) {\n");
2584 printf(" NULLIFY();\n");
2586 } else if (insn
->flags
& LIKELY
) {
2588 printf(" NULLIFY();\n");
2590 if ((insn
->flags
& FP
) && (doisa
< 4))
2594 case PREFETCH
: /* The beginning is shared with normal load operations */
2598 int isload
= ((insn
->type
== LOAD
) || (insn
->type
== PREFETCH
));
2600 char *accesslength
= "<UNKNOWN>";
2602 switch (GETDATASIZEINSN(insn
)) {
2605 accesslength
= "AccessLength_BYTE";
2610 accesslength
= "AccessLength_HALFWORD";
2615 accesslength
= "AccessLength_WORD";
2620 accesslength
= "AccessLength_DOUBLEWORD";
2625 accesslength
= "AccessLength_QUADWORD";
2629 if (insn
->flags
& REG
)
2630 printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
2632 printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
2633 printf(" uword64 paddr;\n");
2634 printf(" int uncached;\n");
2636 /* The following check should only occur on normal (non-shifted) memory loads */
2637 if ((datalen
!= 1) && !(insn
->flags
& (LEFT
| RIGHT
))) {
2638 printf(" if ((vaddr & %d) != 0)\n",(datalen
- 1));
2639 printf(" SignalException(%s);\n",(isload
? "AddressLoad" : "AddressStore"));
2644 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload
? "isLOAD" : "isSTORE"));
2646 if (insn
->type
== PREFETCH
)
2647 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
2650 printf(" uword64 memval = 0;\n");
2651 printf(" uword64 memval1 = 0;\n");
2653 if ((insn
->flags
& COPROC
) && ((datalen
!= 4) && (datalen
!= 8))) {
2654 fprintf(stderr
,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
2658 if (insn
->flags
& (LEFT
| RIGHT
)) {
2659 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
2660 fprintf(stderr
,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",insn
->name
);
2667 fprintf(stderr
,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn
->name
);
2670 /* fall through to... */
2673 printf(" uword64 mask = %d;\n",((datalen
== 8) ? 0x7 : 0x3));
2674 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
2675 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
2676 printf(" int byte;\n");
2677 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
2678 printf(" byte = ((vaddr & mask) ^ bigend);\n");
2679 printf(" if (%s!ByteSwapMem)\n",((insn
->flags
& LEFT
) ? "!" : ""));
2680 printf(" paddr &= ~mask;\n");
2683 if (insn
->flags
& LEFT
)
2685 printf(" LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
2689 printf(" LoadMemory(&memval,&memval1,uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen
- 1));
2693 if (insn
->flags
& LEFT
) {
2695 /* For WORD transfers work out if the value will
2696 be in the top or bottom of the DOUBLEWORD
2699 build_endian_shift(proc64
,datalen
,2,s_right
,32);
2701 if (proc64
&& (datalen
== 4)) {
2702 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2703 printf(" memval >>= 32;\n");
2707 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen
- 1),(datalen
- 1));
2708 if (proc64
&& (datalen
== 4))
2709 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2710 } else { /* store */
2711 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen
- 1));
2713 build_endian_shift(proc64
,datalen
,2,s_left
,32);
2715 /* TODO: This is duplicated in the LOAD code
2716 above - and the RIGHT LOAD and STORE code
2717 below. It should be merged if possible. */
2718 if (proc64
&& (datalen
== 4)) {
2719 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2720 printf(" memval <<= 32;\n");
2724 printf(" StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);\n");
2726 } else { /* RIGHT */
2729 build_endian_shift(proc64
,datalen
,2,s_right
,32);
2731 if (proc64
&& (datalen
== 4)) {
2732 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2733 printf(" memval >>= 32;\n");
2738 printf(" uword64 srcmask;\n");
2739 /* All of this extra code is just a bodge
2740 required because some hosts don't allow
2741 ((v) << 64). The SPARC just leaves the (v)
2742 value un-touched. */
2743 printf(" if (byte == 0)\n");
2744 printf(" srcmask = 0;\n");
2746 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen
);
2747 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n");
2749 if (proc64
&& (datalen
== 4))
2750 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2751 } else { /* store */
2752 printf(" memval = ((uword64) op2 << (byte * 8));\n");
2753 build_endian_shift(proc64
,datalen
,2,s_left
,32);
2754 printf(" StoreMemory(uncached,(%s - byte),memval,memval1,paddr,vaddr,isREAL);\n",accesslength
);
2761 fprintf(stderr
,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
2764 } else { /* normal memory transfer */
2765 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
2766 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
2768 /* TODO: The R4000 documentation states that a LWU
2769 instruction executed when in a 32bit processor mode
2770 should cause a ReservedInstruction exception. This
2771 will mean adding a run-time check into the code
2776 #if 1 /* see the comments attached to LOADDRMASK above */
2777 printf(" uword64 mask = 0x7;\n");
2779 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2781 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
2782 printf(" unsigned int reverse UNUSED = (ReverseEndian ? (mask >> shift) : 0);\n");
2783 printf(" unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0);\n");
2784 printf(" unsigned int byte UNUSED;\n");
2786 /* TODO: This should really also check for 32bit world performing 32bit access */
2787 if (datalen
< 8) /* not for DOUBLEWORD or QUADWORD*/
2788 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2790 printf(" LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength
);
2792 /* The following will only make sense if the
2793 "LoadMemory" above returns a DOUBLEWORD entity */
2794 if (datalen
< 8) { /* not for DOUBLEWORD or QUADWORD*/
2806 valmask
= 0xFFFFFFFF;
2810 fprintf(stderr
,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen
,insn
->name
);
2813 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2814 /* NOTE: The R4000 user manual has the COP_LW
2815 occuring in the same cycle as the rest of the
2816 instruction, yet the MIPS IV shows the operation
2817 happening on the next cycle. To keep the simulator
2818 simple, this code follows the R4000
2819 manual. Experimentation with a silicon
2820 implementation will be needed to ascertain the
2821 correct operation. */
2822 if (insn
->flags
& COPROC
)
2823 printf(" COP_LW(%s,destreg,(unsigned int)",
2824 ((insn
->flags
& REG
)
2826 : "((instruction >> 26) & 0x3)"));
2828 printf(" GPR[destreg] = (");
2830 if (insn
->flags
& SIGNEXTEND
)
2831 printf("SIGNEXTEND(");
2832 printf("((memval >> (8 * byte)) & 0x%08X)",valmask
);
2833 if (insn
->flags
& SIGNEXTEND
)
2834 printf(",%d)",(datalen
* 8));
2837 if (insn
->flags
& COPROC
)
2838 printf(" COP_LD(%s,destreg,memval);;\n",
2839 ((insn
->flags
& REG
)
2841 : "((instruction >> 26) & 0x3)"));
2844 printf(" GPR[destreg] = memval;\n");
2846 printf(" GPR1[destreg] = memval1;\n");
2849 } else { /* store operation */
2850 if ((datalen
== 1) || (datalen
== 2)) {
2852 #if 1 /* see the comments attached to LOADDRMASK above */
2853 printf(" uword64 mask = 0x7;\n");
2855 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2857 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
2858 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
2859 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
2860 printf(" unsigned int byte;\n");
2862 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2863 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2864 printf(" memval = ((uword64) op2 << (8 * byte));\n");
2866 if (datalen
== 4) { /* SC and SW */
2867 #if 1 /* see the comments attached to LOADDRMASK above */
2868 printf(" uword64 mask = 0x7;\n");
2870 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2872 printf(" unsigned int byte;\n");
2873 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
2874 printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
2875 if (insn
->flags
& COPROC
)
2876 printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n",
2877 ((insn
->flags
& REG
)
2879 : "((instruction >> 26) & 0x3)"),
2880 ((insn
->flags
& FP
) ? "fs" : "destreg"));
2882 printf(" memval = ((uword64) op2 << (8 * byte));\n");
2883 } else if (datalen
<= 8) { /* SD and SCD */
2884 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
2885 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
2888 if (insn
->flags
& COPROC
)
2889 printf(" memval = (uword64)COP_SD(%s,%s);\n",
2890 ((insn
->flags
& REG
)
2892 : "((instruction >> 26) & 0x3)"),
2893 ((insn
->flags
& FP
) ? "fs" : "destreg"));
2895 printf(" memval = op2;\n");
2896 } else { /* wider than 8 */
2897 if (insn
->flags
& COPROC
) {
2898 fprintf(stderr
,"COPROC not available for 128 bit operations \"%s\"\n",insn
->name
);
2901 printf(" memval = rt_reg;\n");
2902 printf(" memval1 = rt_reg1;\n");
2905 if (insn
->flags
& ATOMIC
)
2906 printf(" if (LLBIT)\n");
2909 printf(" StoreMemory(uncached,%s,memval,memval1,paddr,vaddr,isREAL);\n",accesslength
);
2913 if (insn
->flags
& ATOMIC
) {
2914 if ((datalen
!= 4) && (datalen
!= 8)) {
2915 fprintf(stderr
,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",insn
->name
);
2919 printf(" LLBIT = 1;\n");
2921 /* The documentation states that:
2923 SC *WILL* fail if coherent store into the same
2924 block occurs, or if an exception occurs between
2925 the LL and SC instructions.
2927 SC *MAY* fail if a load, store or prefetch is
2928 executed on the processor (VR4300 doesn't seem
2929 to), or if the instructions between the LL and
2930 SC are not in a 2048byte contiguous VM range.
2932 SC *MUST* have been preceded by an LL
2933 (i.e. LLBIT will be set), and it must use the
2934 same Vaddr, Paddr and cache-coherence algorithm
2935 as the LL (which means we should store this
2936 information from the load-conditional).
2938 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT
,OP_MASK_RT
);
2949 /* This code could be merged with the PREFIX generation above: */
2950 printf(" uword64 vaddr = ((uword64)op1 + (uword64)op2);\n");
2951 printf(" uword64 paddr;\n");
2952 printf(" int uncached;\n");
2953 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2954 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
2958 if (insn
->flags
& CONTROL
) {
2959 /* The following "magic" of interpreting the FP
2960 control-register number would not be needed if we were not
2961 trying to match our internal register numbers with those
2963 printf(" if (to) {\n");
2965 printf(" if (fs == 0) {\n");
2966 printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
2967 printf(" } else if (fs == 31) {\n");
2968 printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
2969 printf(" } /* else NOP */\n");
2970 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
2972 printf(" if (fs == 0) {\n");
2973 printf(" FCR0 = WORD64LO(GPR[ft]);\n");
2974 printf(" } else if (fs == 31) {\n");
2975 printf(" FCR31 = WORD64LO(GPR[ft]);\n");
2976 printf(" } /* else NOP */\n");
2977 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
2979 printf(" } else { /* control from */\n");
2981 printf(" if (fs == 0) {\n");
2982 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
2983 printf(" } else if (fs == 31) {\n");
2984 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
2985 printf(" } /* else NOP */\n");
2987 printf(" if (fs == 0) {\n");
2988 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
2989 printf(" } else if (fs == 31) {\n");
2990 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
2991 printf(" } /* else NOP */\n");
2995 printf(" if (to) {\n");
2996 if (GETDATASIZEINSN(insn
) == WORD
) {
2998 printf(" if (SizeFGR() == 64) {\n");
2999 printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
3000 printf(" } else { \n");
3001 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3004 printf(" if (SizeFGR() == 64)\n");
3005 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
3007 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3008 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3010 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
3012 printf(" if (SizeFGR() == 64) {\n");
3013 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
3014 printf(" } else\n");
3015 printf(" if ((fs & 0x1) == 0)\n");
3017 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
3018 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3020 if (features
& FEATURE_WARN_RESULT
) {
3022 printf(" UndefinedResult();\n");
3025 printf(" if (SizeFGR() == 64) {\n");
3026 printf(" FGR[fs] = GPR[ft];\n");
3027 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3028 printf(" } else\n");
3029 printf(" if ((fs & 0x1) == 0)\n");
3031 printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
3032 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3033 printf(" fpr_state[fs + 1] = fmt_uninterpreted;\n");
3034 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3036 if (features
& FEATURE_WARN_RESULT
) {
3038 printf(" UndefinedResult();\n");
3042 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
3045 printf(" } else {\n");
3046 if (GETDATASIZEINSN(insn
) == WORD
) {
3047 if (doisa
< 4) /* write-back occurs in next cycle */
3048 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
3049 else /* in this cycle */
3050 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
3051 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
3053 printf(" if (SizeFGR() == 64) {\n");
3054 printf(" PENDING_FILL(ft,FGR[fs]);\n");
3055 printf(" } else\n");
3056 printf(" if ((fs & 0x1) == 0) {\n");
3057 printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
3058 printf(" } else {\n");
3059 printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3060 if (features
& FEATURE_WARN_RESULT
)
3061 printf(" UndefinedResult();\n");
3064 printf(" if (SizeFGR() == 64)\n");
3065 printf(" GPR[ft] = FGR[fs];\n");
3067 printf(" if ((fs & 0x1) == 0)\n");
3068 printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
3069 printf(" else {\n");
3070 printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3071 if (features
& FEATURE_WARN_RESULT
)
3072 printf(" UndefinedResult();\n");
3076 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
3084 if (insn
->flags
& CONDITIONAL
) {
3085 if (insn
->flags
& INTEGER
) { /* moving GPR - testing FGR */
3086 printf(" if (GETFCC(condition_code) == boolean)\n");
3087 printf(" GPR[destreg] = op1;\n");
3089 if (insn
->flags
& EQ
) /* moving FGR - testing GPR */
3090 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
3092 printf(" if (GETFCC(condition_code) == boolean)\n");
3093 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3095 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
3097 } else { /* simple MOVE */
3098 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3103 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3104 printf(" SignalException(ReservedInstruction,instruction);\n");
3106 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
3110 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3111 printf(" SignalException(ReservedInstruction,instruction);\n");
3113 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
3117 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3118 printf(" SignalException(ReservedInstruction,instruction);\n");
3120 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3124 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3125 printf(" SignalException(ReservedInstruction,instruction);\n");
3127 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3131 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3132 printf(" SignalException(ReservedInstruction,instruction);\n");
3134 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
3138 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3139 printf(" SignalException(ReservedInstruction,instruction);\n");
3141 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((insn
->flags
& RECIP
) ? "Recip" : ""));
3152 switch (insn
->type
) {
3154 op
= "FP_RM_TOPINF";
3157 op
= "FP_RM_TOMINF";
3160 op
= "FP_RM_TOZERO";
3163 op
= "FP_RM_NEAREST";
3166 fprintf(stderr
,"Error: Handled missing for FP reason code %d\n",insn
->type
);
3170 switch (GETDATASIZEINSN(insn
)) {
3178 fprintf(stderr
,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op
);
3181 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3182 printf(" SignalException(ReservedInstruction,instruction);\n");
3184 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type
,op
,type
);
3191 switch (GETDATASIZEINSN(insn
)) {
3193 type
= "fmt_single";
3196 type
= "fmt_double";
3205 fprintf(stderr
,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn
));
3209 /* Not all combinations of conversion are valid at the
3210 moment: When converting to a fixed-point format, only
3211 floating-point sources are allowed. */
3212 printf(" if ((format == %s) | %s)\n",type
,((insn
->flags
& FIXED
) ? "((format == fmt_long) || (format == fmt_word))": "0"));
3213 printf(" SignalException(ReservedInstruction,instruction);\n");
3215 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type
,type
);
3220 if (insn
->flags
& MULTIPLY
) {
3222 switch (GETDATASIZEINSN(insn
)) {
3224 type
= "fmt_single";
3227 type
= "fmt_double";
3230 fprintf(stderr
,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn
));
3233 printf(" StoreFPR(destreg,%s,%s(Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",type
,((insn
->flags
& NOT
) ? "Negate" : ""),type
,type
,type
,type
,type
,type
);
3235 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3236 printf(" SignalException(ReservedInstruction,instruction);\n");
3238 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3243 if (insn
->flags
& MULTIPLY
) {
3245 switch (GETDATASIZEINSN(insn
)) {
3247 type
= "fmt_single";
3250 type
= "fmt_double";
3253 fprintf(stderr
,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn
));
3256 if (insn
->flags
& NOT
)
3257 printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
3258 type
, type
, type
, type
, type
, type
, type
);
3260 printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
3261 type
, type
, type
, type
, type
, type
);
3263 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3264 printf(" SignalException(ReservedInstruction,instruction);\n");
3266 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3271 /* For the MIPS I,II or III there *MUST* be at least one
3272 instruction between the compare that sets a condition code
3273 and the branch that tests it. NOTE: However the hardware
3274 does not detect this condition. */
3275 /* Explicitly limit the operation to S and D formats: */
3276 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3277 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3278 printf(" else {\n");
3280 printf(" if (condition_code != 0)\n");
3281 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3285 printf(" int ignore = 0;\n");
3286 printf(" int less = 0;\n");
3287 printf(" int equal = 0;\n");
3288 printf(" int unordered = 1;\n");
3289 printf(" uword64 ofs = ValueFPR(fs,format);\n");
3290 printf(" uword64 oft = ValueFPR(ft,format);\n");
3291 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
3292 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
3293 printf(" FCSR |= FP_CAUSE(IO);\n");
3294 printf(" SignalException(FPE);\n");
3295 printf(" ignore = 1;\n");
3297 printf(" } else {\n");
3298 printf(" less = Less(ofs,oft,format);\n");
3299 printf(" equal = Equal(ofs,oft,format);\n");
3300 printf(" unordered = 0;\n");
3302 printf(" if (!ignore) {\n");
3303 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
3304 printf(" SETFCC(condition_code,condition);\n");
3310 /* start-sanitize-r5900 */
3313 char* pipeline
= (insn
->flags
& PIPE1
) ? "1" : "";
3314 int notsigned
= (insn
->flags
& UNSIGNED
);
3315 char* prodtype
= notsigned
? "uword64" : "word64";
3317 printf("%s prod = (%s)WORD64(WORD64LO(HI%s),WORD64LO(LO%s)) + ((%s)%s(op1%s) * (%s)%s(op2%s));\n",
3318 prodtype
, prodtype
, pipeline
, pipeline
,
3319 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32"),
3320 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32")
3322 printf("GPR[destreg] = LO%s = SIGNEXTEND(prod,32);\n", pipeline
);
3323 printf("HI%s = SIGNEXTEND( WORD64HI(prod), 32);\n", pipeline
);
3329 if (insn
->flags
& TO
)
3330 printf("SA = op1;\n");
3332 printf("GPR[destreg] = SA;\n");
3337 printf("SA = ((op1 & 0xF) ^ (op2 & 0xF)) * 8;\n");
3341 printf("SA = ((op1 & 0x7) ^ (op2 & 0x7)) * 16;\n");
3345 printf("int bytes = (SA / 8) %% 16;\n"); /* mod 16 to avoid garbage */
3346 printf("if (SA %% 8)\n");
3347 printf(" SignalException(ReservedInstruction,instruction);\n");
3350 printf(" int i;\n");
3351 printf(" for(i=0;i<(16-bytes);i++)\n");
3352 printf(" GPR_SB(destreg,i) = RT_SB(bytes+i);\n");
3353 printf(" for(;i<16;i++)\n");
3354 printf(" GPR_SB(destreg,i) = RS_SB(i-(16-bytes));\n");
3360 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3361 char* name
= name_for_data_len( insn
);
3362 char* letter
= letter_for_data_len( insn
);
3370 if ( insn
->flags
& UNSIGNED
)
3372 tmptype
= type_for_data_len( insn
);
3373 signedness
= "unsigned";
3375 maximum
= umax_for_data_len( insn
);
3378 else if ( insn
->flags
& SATURATE
)
3380 tmptype
= type_for_data_len( insn
);
3383 maximum
= max_for_data_len( insn
);
3384 minimum
= min_for_data_len( insn
);
3388 tmptype
= type_for_data_len( insn
);
3396 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3398 printf(" %s %s r = RS_%s%s(i) %s RT_%s%s(i);\n", signedness
, tmptype
, signletter
, letter
, op
, signletter
, letter
);
3401 printf(" if (r > %s) GPR_%s%s(destreg,i) = %s;\n", maximum
, signletter
, letter
, maximum
);
3403 printf(" else if (r < %s) GPR_%s%s(destreg,i) = %s;\n", minimum
, signletter
, letter
, minimum
);
3406 printf("GPR_%s%s(destreg,i) = r;\n", signletter
, letter
);
3414 if ( insn
->flags
& SUBTRACT
)
3416 else if ( insn
->flags
& ADDITION
)
3421 printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op
);
3422 printf(" LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op
);
3423 printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op
);
3424 printf(" HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op
);
3425 printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op
);
3426 printf(" LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op
);
3427 printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op
);
3428 printf(" HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op
);
3435 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3436 char* prodtype
= (insn
->flags
& UNSIGNED
) ? "uword64" : "word64";
3437 char* constructor
= (insn
->flags
& UNSIGNED
) ? "UWORD64" : "WORD64";
3439 printf("%s prod0;\n", prodtype
);
3440 printf("%s prod1;\n", prodtype
);
3442 if ( insn
->flags
& SUBTRACT
)
3445 printf("prod0 = %s( HI_SW(0), LO_SW(0) );\n", constructor
);
3446 printf("prod1 = %s( HI_SW(2), LO_SW(2) );\n", constructor
);
3448 else if ( insn
->flags
& ADDITION
)
3451 printf("prod0 = %s( HI_SW(0), LO_SW(0) );\n", constructor
);
3452 printf("prod1 = %s( HI_SW(2), LO_SW(2) );\n", constructor
);
3457 printf("prod0 %s= (%s)RS_SW(0) * (%s)RT_SW(0);\n", op
, prodtype
, prodtype
);
3458 printf("prod1 %s= (%s)RS_SW(2) * (%s)RT_SW(2);\n", op
, prodtype
, prodtype
);
3460 printf("GPR_%sD(destreg,0) = prod0;\n", sign
);
3461 printf("GPR_%sD(destreg,1) = prod1;\n", sign
);
3463 printf("LO = SIGNEXTEND( prod0, 32 );\n");
3464 printf("HI = SIGNEXTEND( WORD64HI(prod0), 32 );\n");
3465 printf("LO1 = SIGNEXTEND( prod1, 32 );\n");
3466 printf("HI1 = SIGNEXTEND( WORD64HI(prod1), 32 );\n");
3472 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3474 printf("LO = RS_%sW(0) / RT_%sW(0);\n", sign
, sign
);
3475 printf("HI = RS_%sW(0) %% RT_%sW(0);\n", sign
, sign
);
3476 printf("LO1 = RS_%sW(2) / RT_%sW(2);\n", sign
, sign
);
3477 printf("HI1 = RS_%sW(2) %% RT_%sW(2);\n", sign
, sign
);
3482 printf("int devisor = RT_SH(0);\n");
3483 printf("LO_SW(0) = RS_SW(0) / devisor;\n");
3484 printf("HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n");
3485 printf("LO_SW(1) = RS_SW(1) / devisor;\n");
3486 printf("HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n");
3487 printf("LO_SW(2) = RS_SW(2) / devisor;\n");
3488 printf("HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n");
3489 printf("LO_SW(3) = RS_SW(3) / devisor;\n");
3490 printf("HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n");
3495 printf("for(i=0;i<HALFWORDS_IN_MMI_REGS/2;i++)\n");
3496 printf(" GPR_SH(destreg,i) = RS_SH(i) - RT_SH(i);\n");
3497 printf("for(;i<HALFWORDS_IN_MMI_REGS;i++)\n");
3498 printf(" GPR_SH(destreg,i) = RS_SH(i) + RT_SH(i);\n");
3503 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3504 printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op
);
3505 printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op
);
3506 printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op
);
3507 printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op
);
3513 char* name
= name_for_data_len( insn
);
3514 char* letter
= letter_for_data_len( insn
);
3515 char* bits
= bits_for_data_len( insn
);
3516 char* shift
= (insn
->flags
& RIGHT
) ? ">>" : "<<";
3517 char* sign
= (insn
->flags
& ARITHMETIC
) ? "S" : "U";
3519 printf("int shift_by = op1 & (%s-1);\n", bits
);
3521 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3522 printf(" GPR_%s%s(destreg,i) = ", sign
, letter
);
3523 if ( insn
->flags
& ARITHMETIC
)
3524 printf("SIGNEXTEND( ");
3525 printf("(RT_%s%s(i) %s shift_by)", sign
, letter
, shift
);
3526 if ( insn
->flags
& ARITHMETIC
)
3527 printf(", (%s-shift_by) )", bits
);
3533 printf("GPR_UD(destreg,0) = RT_UW(0) << (RS_UB(0) & 0x1F);\n");
3534 printf("GPR_UD(destreg,1) = RT_UW(2) << (RS_UB(8) & 0x1F);\n");
3538 printf("GPR_UD(destreg,0) = RT_UW(0) >> (RS_UB(0) & 0x1F);\n");
3539 printf("GPR_UD(destreg,1) = RT_UW(2) >> (RS_UB(8) & 0x1F);\n");
3543 printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n");
3544 printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n");
3552 if ( GET_OP_FROM_INSN(insn
) == POP_AND
)
3557 else if ( GET_OP_FROM_INSN(insn
) == POP_OR
)
3562 else if ( GET_OP_FROM_INSN(insn
) == POP_NOR
)
3567 else if ( GET_OP_FROM_INSN(insn
) == POP_XOR
)
3574 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3575 printf(" GPR_UW(destreg,i) = %s(RS_UW(i) %s RT_UW(i));\n", op2
, op1
);
3581 char* name
= name_for_data_len( insn
);
3582 char* letter
= letter_for_data_len( insn
);
3583 char* maximum
= umax_for_data_len( insn
);
3584 char* op
= (insn
->flags
& GT
) ? ">" : "==";
3587 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3589 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n",
3590 letter
, op
, letter
, letter
, maximum
);
3591 printf(" else GPR_S%s(destreg,i) = 0;\n", letter
);
3598 char* name
= name_for_data_len( insn
);
3599 char* letter
= letter_for_data_len( insn
);
3600 char* op
= (insn
->flags
& GT
) ? ">" : "<";
3603 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3605 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n",
3606 letter
, op
, letter
, letter
, letter
);
3607 printf(" else GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
3614 char* name
= name_for_data_len( insn
);
3615 char* letter
= letter_for_data_len( insn
);
3618 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3620 printf(" if (RT_S%s(i) < 0)\n", letter
);
3621 printf(" GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter
, letter
);
3623 printf(" GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
3629 printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n");
3630 printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n");
3634 printf("GPR_UD(destreg,0) = RT_UD(0);\n");
3635 printf("GPR_UD(destreg,1) = RS_UD(0);\n");
3639 printf("GPR_UD(destreg,0) = RS_UD(1);\n");
3640 printf("GPR_UD(destreg,1) = RT_UD(1);\n");
3644 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3645 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3646 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3647 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3648 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3649 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3650 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3651 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3655 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3656 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3657 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3658 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3662 printf("GPR_UH(destreg,0) = RT_UH(2);\n");
3663 printf("GPR_UH(destreg,1) = RT_UH(1);\n");
3664 printf("GPR_UH(destreg,2) = RT_UH(0);\n");
3665 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3666 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3667 printf("GPR_UH(destreg,5) = RT_UH(5);\n");
3668 printf("GPR_UH(destreg,6) = RT_UH(4);\n");
3669 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3673 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3674 printf("GPR_UW(destreg,1) = RT_UW(1);\n");
3675 printf("GPR_UW(destreg,2) = RT_UW(0);\n");
3676 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3680 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3681 printf("GPR_UB(destreg,1) = RS_UB(0);\n");
3682 printf("GPR_UB(destreg,2) = RT_UB(1);\n");
3683 printf("GPR_UB(destreg,3) = RS_UB(1);\n");
3684 printf("GPR_UB(destreg,4) = RT_UB(2);\n");
3685 printf("GPR_UB(destreg,5) = RS_UB(2);\n");
3686 printf("GPR_UB(destreg,6) = RT_UB(3);\n");
3687 printf("GPR_UB(destreg,7) = RS_UB(3);\n");
3688 printf("GPR_UB(destreg,8) = RT_UB(4);\n");
3689 printf("GPR_UB(destreg,9) = RS_UB(4);\n");
3690 printf("GPR_UB(destreg,10) = RT_UB(5);\n");
3691 printf("GPR_UB(destreg,11) = RS_UB(5);\n");
3692 printf("GPR_UB(destreg,12) = RT_UB(6);\n");
3693 printf("GPR_UB(destreg,13) = RS_UB(6);\n");
3694 printf("GPR_UB(destreg,14) = RT_UB(7);\n");
3695 printf("GPR_UB(destreg,15) = RS_UB(7);\n");
3699 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3700 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3701 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3702 printf("GPR_UH(destreg,3) = RS_UH(1);\n");
3703 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3704 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3705 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3706 printf("GPR_UH(destreg,7) = RS_UH(3);\n");
3710 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3711 printf("GPR_UW(destreg,1) = RS_UW(0);\n");
3712 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3713 printf("GPR_UW(destreg,3) = RS_UW(1);\n");
3717 printf("GPR_UB(destreg,0) = RT_UB(8);\n");
3718 printf("GPR_UB(destreg,1) = RS_UB(8);\n");
3719 printf("GPR_UB(destreg,2) = RT_UB(9);\n");
3720 printf("GPR_UB(destreg,3) = RS_UB(9);\n");
3721 printf("GPR_UB(destreg,4) = RT_UB(10);\n");
3722 printf("GPR_UB(destreg,5) = RS_UB(10);\n");
3723 printf("GPR_UB(destreg,6) = RT_UB(11);\n");
3724 printf("GPR_UB(destreg,7) = RS_UB(11);\n");
3725 printf("GPR_UB(destreg,8) = RT_UB(12);\n");
3726 printf("GPR_UB(destreg,9) = RS_UB(12);\n");
3727 printf("GPR_UB(destreg,10) = RT_UB(13);\n");
3728 printf("GPR_UB(destreg,11) = RS_UB(13);\n");
3729 printf("GPR_UB(destreg,12) = RT_UB(14);\n");
3730 printf("GPR_UB(destreg,13) = RS_UB(14);\n");
3731 printf("GPR_UB(destreg,14) = RT_UB(15);\n");
3732 printf("GPR_UB(destreg,15) = RS_UB(15);\n");
3736 printf("GPR_UH(destreg,0) = RT_UH(4);\n");
3737 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3738 printf("GPR_UH(destreg,2) = RT_UH(5);\n");
3739 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3740 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3741 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3742 printf("GPR_UH(destreg,6) = RT_UH(7);\n");
3743 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3747 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3748 printf("GPR_UW(destreg,1) = RS_UW(2);\n");
3749 printf("GPR_UW(destreg,2) = RT_UW(3);\n");
3750 printf("GPR_UW(destreg,3) = RS_UW(3);\n");
3754 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3755 printf("GPR_UB(destreg,1) = RT_UB(2);\n");
3756 printf("GPR_UB(destreg,2) = RT_UB(4);\n");
3757 printf("GPR_UB(destreg,3) = RT_UB(6);\n");
3758 printf("GPR_UB(destreg,4) = RT_UB(8);\n");
3759 printf("GPR_UB(destreg,5) = RT_UB(10);\n");
3760 printf("GPR_UB(destreg,6) = RT_UB(12);\n");
3761 printf("GPR_UB(destreg,7) = RT_UB(14);\n");
3762 printf("GPR_UB(destreg,8) = RS_UB(0);\n");
3763 printf("GPR_UB(destreg,9) = RS_UB(2);\n");
3764 printf("GPR_UB(destreg,10) = RS_UB(4);\n");
3765 printf("GPR_UB(destreg,11) = RS_UB(6);\n");
3766 printf("GPR_UB(destreg,12) = RS_UB(8);\n");
3767 printf("GPR_UB(destreg,13) = RS_UB(10);\n");
3768 printf("GPR_UB(destreg,14) = RS_UB(12);\n");
3769 printf("GPR_UB(destreg,15) = RS_UB(14);\n");
3773 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3774 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3775 printf("GPR_UH(destreg,2) = RT_UH(4);\n");
3776 printf("GPR_UH(destreg,3) = RT_UH(6);\n");
3777 printf("GPR_UH(destreg,4) = RS_UH(0);\n");
3778 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3779 printf("GPR_UH(destreg,6) = RS_UH(4);\n");
3780 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3784 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3785 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3786 printf("GPR_UW(destreg,2) = RS_UW(0);\n");
3787 printf("GPR_UW(destreg,3) = RS_UW(2);\n");
3791 printf("GPR_UH(destreg,0) = RT_UH(3);\n");
3792 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3793 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3794 printf("GPR_UH(destreg,3) = RT_UH(0);\n");
3795 printf("GPR_UH(destreg,4) = RT_UH(7);\n");
3796 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3797 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3798 printf("GPR_UH(destreg,7) = RT_UH(4);\n");
3802 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3803 printf("GPR_UW(destreg,1) = RT_UW(3);\n");
3804 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3805 printf("GPR_UW(destreg,3) = RT_UW(2);\n");
3809 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3810 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3811 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3812 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3813 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3814 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3815 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3816 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3820 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3821 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3822 printf("GPR_UH(destreg,2) = RT_UH(2);\n");
3823 printf("GPR_UH(destreg,3) = RS_UH(2);\n");
3824 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3825 printf("GPR_UH(destreg,5) = RS_UH(4);\n");
3826 printf("GPR_UH(destreg,6) = RT_UH(6);\n");
3827 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3830 case PMXX
: /* Parallel move HI or LO / TO or FROM */
3832 if ( (insn
->flags
& (HI
|FROM
)) == (HI
|FROM
) )
3834 printf("GPR_SD(destreg,0) = HI;\n");
3835 printf("GPR_SD(destreg,1) = HI1;\n");
3837 else if ( (insn
->flags
& (LO
|FROM
)) == (LO
|FROM
) )
3839 printf("GPR_SD(destreg,0) = LO;\n");
3840 printf("GPR_SD(destreg,1) = LO1;\n");
3842 else if ( (insn
->flags
& (HI
|TO
)) == (HI
|TO
) )
3844 printf("HI = RS_SD(0);\n");
3845 printf("HI1 = RS_SD(1);\n");
3847 else if ( (insn
->flags
& (LO
|TO
)) == (LO
|TO
) )
3849 printf("LO = RS_SD(0);\n");
3850 printf("LO1 = RS_SD(1);\n");
3856 printf("LO_UW(0) = RS_UW(0);\n");
3857 printf("HI_UW(0) = RS_UW(1);\n");
3858 printf("LO_UW(2) = RS_UW(2);\n");
3859 printf("HI_UW(2) = RS_UW(3);\n");
3863 printf("if (op1 == 0)\n");
3865 printf(" GPR_UW(destreg,0) = LO_UW(0);\n");
3866 printf(" GPR_UW(destreg,1) = HI_UW(0);\n");
3867 printf(" GPR_UW(destreg,2) = LO_UW(2);\n");
3868 printf(" GPR_UW(destreg,3) = HI_UW(2);\n");
3870 printf("else if (op1 == 1)\n");
3872 printf(" GPR_UW(destreg,0) = LO_UW(1);\n");
3873 printf(" GPR_UW(destreg,1) = HI_UW(1);\n");
3874 printf(" GPR_UW(destreg,2) = LO_UW(3);\n");
3875 printf(" GPR_UW(destreg,3) = HI_UW(3);\n");
3877 printf("else if (op1 == 2)\n");
3879 printf(" unsigned long long t = ((uword64)HI_UW(0) << 32) | (uword64)LO_UW(0);\n");
3880 printf(" if ( t > 0x7FFFFFFF )\n");
3881 printf(" GPR_SD(destreg,0) = 0x7FFFFFFF;\n");
3882 printf(" else if ( t > (uword64)0xFFFFFFFF80000000LL )\n");
3883 printf(" GPR_SD(destreg,0) = (uword64)0xFFFFFFFF80000000LL;\n");
3885 printf(" GPR_SD(destreg,0) = SIGNEXTEND(t,32);\n");
3887 printf("else if (op1 == 3)\n");
3889 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3890 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3891 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
3892 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
3893 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
3894 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
3895 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
3896 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
3898 printf("else if (op1 == 4)\n");
3900 printf(" if (LO_UW(0) > 0x00007FFF)\n");
3901 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
3902 printf(" else if (LO_UW(0) >= 0xFFFF8000)\n");
3903 printf(" GPR_UH(destreg,0) = 0x8000;\n");
3905 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3907 printf(" if (LO_UW(1) > 0x00007FFF)\n");
3908 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
3909 printf(" else if (LO_UW(1) >= 0xFFFF8000)\n");
3910 printf(" GPR_UH(destreg,1) = 0x8000;\n");
3912 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3914 printf(" if (HI_UW(0) > 0x00007FFF)\n");
3915 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
3916 printf(" else if (HI_UW(0) >= 0xFFFF8000)\n");
3917 printf(" GPR_UH(destreg,0) = 0x8000;\n");
3919 printf(" GPR_UH(destreg,0) = HI_UH(0);\n");
3921 printf(" if (HI_UW(1) > 0x00007FFF)\n");
3922 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
3923 printf(" else if (HI_UW(1) >= 0xFFFF8000)\n");
3924 printf(" GPR_UH(destreg,1) = 0x8000;\n");
3926 printf(" GPR_UH(destreg,1) = HI_UH(2);\n");
3928 printf(" if (LO_UW(2) > 0x00007FFF)\n");
3929 printf(" GPR_UH(destreg,4) = 0x7FFF;\n");
3930 printf(" else if (LO_UW(2) >= 0xFFFF8000)\n");
3931 printf(" GPR_UH(destreg,4) = 0x8000;\n");
3933 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
3935 printf(" if (LO_UW(3) > 0x00007FFF)\n");
3936 printf(" GPR_UH(destreg,5) = 0x7FFF;\n");
3937 printf(" else if (LO_UW(3) >= 0xFFFF8000)\n");
3938 printf(" GPR_UH(destreg,5) = 0x8000;\n");
3940 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
3942 printf(" if (HI_UW(2) > 0x00007FFF)\n");
3943 printf(" GPR_UH(destreg,6) = 0x7FFF;\n");
3944 printf(" else if (HI_UW(2) >= 0xFFFF8000)\n");
3945 printf(" GPR_UH(destreg,6) = 0x8000;\n");
3947 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
3949 printf(" if (HI_UW(3) > 0x00007FFF)\n");
3950 printf(" GPR_UH(destreg,7) = 0x7FFF;\n");
3951 printf(" else if (HI_UW(3) >= 0xFFFF8000)\n");
3952 printf(" GPR_UH(destreg,7) = 0x8000;\n");
3954 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
3960 printf("unsigned long value;\n");
3961 printf("int test;\n");
3962 printf("int count;\n");
3965 printf("value = RS_UW(0);\n");
3966 printf("count = 0;\n");
3967 printf("test = !!(value & (1 << 31));\n");
3968 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
3969 printf(" count++;\n");
3970 printf("GPR_UW(destreg,0) = count;\n");
3972 printf("value = RS_UW(1);\n");
3973 printf("count = 0;\n");
3974 printf("test = !!(value & (1 << 31));\n");
3975 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
3976 printf(" count++;\n");
3977 printf("GPR_UW(destreg,1) = count;\n");
3982 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3984 printf(" int x = RT_UW(i);\n");
3985 printf(" GPR_UW(destreg,i) = ((x & (1 << 15)) << (24 - 15)) \n");
3986 printf(" | ((x & (31 << 10)) << (19 - 10)) \n");
3987 printf(" | ((x & (31 << 5)) << (11 - 5)) \n");
3988 printf(" | ((x & (31 << 0)) << (3 - 0)); \n");
3994 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3996 printf(" int x = RT_UW(i);\n");
3997 printf(" GPR_UW(destreg,i) = ((x & (1 << 31)) >> (31 - 15)) \n");
3998 printf(" | ((x & (31 << 19)) >> (19 - 10)) \n");
3999 printf(" | ((x & (31 << 11)) >> (11 - 5)) \n");
4000 printf(" | ((x & (31 << 3)) >> (3 - 0)); \n");
4003 /* end-sanitize-r5900 */
4006 fprintf(stderr
,"Warning: Unimplemented opcode: %s\n",insn
->name
) ;
4008 printf("SignalException(ReservedInstruction,instruction);\n");
4012 fprintf(stderr
,"Unrecognised opcode type %d\n",insn
->type
) ;
4017 /*---------------------------------------------------------------------------*/
4019 /* The command-line feature controls are presented in a similar style
4020 to those offered by GCC, in the aim of providing a consistent
4021 interface to the user. */
4023 T_NONE
, /* no argument - mask and value fields control "feature" definition */
4024 T_NUM
, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
4025 T_STRING
/* string argument - optionally prcededed by '=' */
4034 } machine_options
[] = {
4035 {"ips", T_NUM
, MASK_ISA
,0,"\tSelect MIPS ISA version"},
4036 {"cpu", T_STRING
,0,0,"\t\tSelect particular MIPS architecture"},
4037 {"gp64", T_NONE
, FEATURE_GP64
,FEATURE_GP64
,"\t\t\tSelect 64bit GP registers"},
4038 {"gp32", T_NONE
, FEATURE_GP64
,0,"\t\t\tSelect 32bit GP registers"},
4039 {"no-fp", T_NONE
, FEATURE_HASFPU
,0,"\t\tDisable FP simulation"},
4040 {"single-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),(FEATURE_FPSINGLE
| FEATURE_HASFPU
),"\t\tSelect single precision only FPU"},
4041 {"double-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),FEATURE_HASFPU
,"\t\tSelect double precision FPU"},
4045 /* The following architecture identies are those accepted by the "-mcpu" option: */
4046 struct architectures
{
4047 const char *name
; /* ASCII string identifier for command-line, no white-space allowed */
4048 unsigned int idflag
; /* or-ed into "isa" value */
4051 static const struct architectures available_architectures
[] = {
4052 {"4100",ARCH_VR4100
}, /* NEC MIPS VR4100 */
4053 /* start-sanitize-r5900 */
4054 {"5900",ARCH_R5900
},
4055 /* end-sanitize-r5900 */
4056 {0, 0} /* terminator */
4059 /*---------------------------------------------------------------------------*/
4067 fprintf(stderr
,"%s: Construct a MIPS simulator engine.\n",name
);
4070 The output of this program is a block of 'C' code designed to be\n\
4071 included into the main simulation control loop of a device specific\n\
4074 fprintf(stderr
,"\nOptions:\n");
4075 fprintf(stderr
," -h --help\t\tProvide this help text\n");
4076 fprintf(stderr
," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
4077 fprintf(stderr
," -w --warnings\t\tEnable all the simulator engine warnings\n");
4079 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++) {
4080 fprintf(stderr
," -m%s",machine_options
[loop
].name
);
4081 switch (machine_options
[loop
].type
) {
4083 fprintf(stderr
,"N (range 0..%d)",machine_options
[loop
].mask
);
4088 fprintf(stderr
,"=name");
4092 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",name
,machine_options
[loop
].type
);
4095 fprintf(stderr
,"%s\n",machine_options
[loop
].desc
);
4098 fprintf(stderr
,"\nAvailable \"-mcpu\" architectures: ");
4099 for (loop
= 0; (available_architectures
[loop
].name
!= 0); loop
++)
4100 fprintf(stderr
,"%s ",available_architectures
[loop
].name
);
4101 fprintf(stderr
,"\n\n");
4104 The \"trace\" and \"warnings\" options do not define the output stream.\n\
4105 They only inform the code that includes the constructed engine to provide\n\
4106 the required features.\n\n\
4107 The \"-mips0\" option forces the construction of a simulator supporting\n\
4108 the highest available MIPS ISA supported.\n");
4113 /*---------------------------------------------------------------------------*/
4121 char *progname
= argv
[0];
4122 unsigned int doarch
= DEF_ISA
;
4123 unsigned int features
= 0; /* default state */
4126 features
|= FEATURE_HASFPU
;
4128 features
|= FEATURE_PROC32
;
4130 features
|= FEATURE_FPSINGLE
;
4132 if (features
& FEATURE_PROC32
)
4133 features
&= ~FEATURE_GP64
;
4135 features
|= FEATURE_GP64
;
4138 int option_index
= 0;
4139 static struct option cmdline
[] = {
4142 {"warnings",0,0,'w'},
4146 c
= getopt_long(argc
,argv
,"hm:tw",cmdline
,&option_index
);
4148 break ; /* out of the while loop */
4151 case 'h' : /* help */
4155 case 'f' : /* fast */
4156 features
|= FEATURE_FAST
;
4159 case 'w' : /* warnings */
4160 features
|= FEATURE_WARNINGS
;
4161 /* TODO: Future extension: Allow better control over the warnings generated:
4162 disable warnings -wnone ~FEATURE_WARNINGS
4163 all possible warnings -wall FEATURE_WARNINGS
4164 pipeline stall occuring -wstall FEATURE_WARN_STALL
4165 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
4166 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
4167 bad r31 use -wr31 FEATURE_WARN_R31
4168 undefined results -wresult FEATURE_WARN_RESULT
4172 case 'm' : /* machine options */
4176 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++)
4177 if (strncmp(machine_options
[loop
].name
,optarg
,strlen(machine_options
[loop
].name
)) == 0) {
4178 char *loptarg
= (optarg
+ strlen(machine_options
[loop
].name
));
4179 switch (machine_options
[loop
].type
) {
4182 fprintf(stderr
,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname
,loptarg
,machine_options
[loop
].name
);
4185 features
&= ~(machine_options
[loop
].mask
);
4186 features
|= machine_options
[loop
].value
;
4190 if (*loptarg
&& *loptarg
== '=')
4193 if (strcmp(machine_options
[loop
].name
,"ips") == 0) {
4197 fprintf(stderr
,"%s: ISA number expected after -mips\n",progname
);
4201 num
= my_strtoul(loptarg
,&loptarg
,10);
4203 if ((num
== ULONG_MAX
) && (errno
= ERANGE
)) {
4204 fprintf(stderr
,"%s: Invalid number given to -mips option\n",progname
);
4209 fprintf(stderr
,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname
,loptarg
);
4213 if (num
> MASK_ISA
) {
4214 fprintf(stderr
,"%s: ISA number %d outside acceptable range (0..%d)\n",progname
,num
,MASK_ISA
);
4218 doarch
= ((doarch
& ~MASK_ISA
) | num
);
4219 if ((num
== 0) || (num
> 2)) {
4220 if ((features
& FEATURE_PROC32
) || !(features
& FEATURE_GP64
))
4221 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp64\n",progname
,num
);
4222 features
|= FEATURE_GP64
;
4223 features
&= ~FEATURE_PROC32
;
4225 if (!(features
& FEATURE_PROC32
) || (features
& FEATURE_GP64
))
4226 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp32\n",progname
,num
);
4227 features
&= ~FEATURE_GP64
;
4228 features
|= FEATURE_PROC32
;
4231 fprintf(stderr
,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname
,optarg
);
4237 if (*loptarg
&& *loptarg
== '=')
4240 if (strcmp(machine_options
[loop
].name
,"cpu") == 0) {
4244 fprintf(stderr
,"%s: Architecture identifier expected after -mcpu\n",progname
);
4248 for (archloop
= 0; (available_architectures
[archloop
].name
!= 0); archloop
++) {
4249 if ((*loptarg
== 'v') || (*loptarg
== 'V'))
4252 if ((*loptarg
== 'r') || (*loptarg
== 'R'))
4255 if (strcmp(available_architectures
[archloop
].name
,loptarg
) == 0) {
4256 doarch
|= available_architectures
[archloop
].idflag
;
4261 if (available_architectures
[archloop
].name
== 0) {
4262 fprintf(stderr
,"%s: Unrecognised MIPS architecture \"%s\"\n",progname
,loptarg
);
4266 fprintf(stderr
,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname
,optarg
);
4272 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",progname
,machine_options
[loop
].type
);
4278 if (machine_options
[loop
].name
== 0) {
4279 fprintf(stderr
,"%s: Unrecognised option: -m%s\n",progname
,optarg
);
4286 /* An error message should already have been displayed */
4290 fprintf(stderr
,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname
,c
);
4295 if (optind
< argc
) {
4296 fprintf(stderr
,"%s: Spurios non-option arguments ",progname
);
4297 while (optind
< argc
)
4298 fprintf(stderr
,"\"%s\" ",argv
[optind
++]);
4299 fprintf(stderr
,"\n");
4303 if ((features
& FEATURE_FAST
) && (features
& FEATURE_WARNINGS
))
4304 fprintf(stderr
,"Warning: Fast model generation selected, along with trace or warnings.\n");
4306 process_instructions(doarch
,features
) ;
4310 /*---------------------------------------------------------------------------*/
4312 /* We can't assume that the compiler for the build system has strtoul,
4313 so we provide our own copy. */
4316 * Copyright (c) 1990 Regents of the University of California.
4317 * All rights reserved.
4319 * Redistribution and use in source and binary forms, with or without
4320 * modification, are permitted provided that the following conditions
4322 * 1. Redistributions of source code must retain the above copyright
4323 * notice, this list of conditions and the following disclaimer.
4324 * 2. Redistributions in binary form must reproduce the above copyright
4325 * notice, this list of conditions and the following disclaimer in the
4326 * documentation and/or other materials provided with the distribution.
4327 * 3. All advertising materials mentioning features or use of this software
4328 * must display the following acknowledgement:
4329 * This product includes software developed by the University of
4330 * California, Berkeley and its contributors.
4331 * 4. Neither the name of the University nor the names of its contributors
4332 * may be used to endorse or promote products derived from this software
4333 * without specific prior written permission.
4335 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4336 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4337 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4338 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4339 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4340 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4341 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4342 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4343 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4344 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4349 * Convert a string to an unsigned long integer.
4351 * Ignores `locale' stuff. Assumes that the upper and lower case
4352 * alphabets and digits are each contiguous.
4354 static unsigned long
4355 my_strtoul(nptr
, endptr
, base
)
4360 register const char *s
= nptr
;
4361 register unsigned long acc
;
4363 register unsigned long cutoff
;
4364 register int neg
= 0, any
, cutlim
;
4367 * See strtol for comments as to the logic used.
4371 } while (isspace(c
));
4375 } else if (c
== '+')
4377 if ((base
== 0 || base
== 16) &&
4378 c
== '0' && (*s
== 'x' || *s
== 'X')) {
4384 base
= c
== '0' ? 8 : 10;
4385 cutoff
= (unsigned long)ULONG_MAX
/ (unsigned long)base
;
4386 cutlim
= (unsigned long)ULONG_MAX
% (unsigned long)base
;
4387 for (acc
= 0, any
= 0;; c
= *s
++) {
4390 else if (isalpha(c
))
4391 c
-= isupper(c
) ? 'A' - 10 : 'a' - 10;
4396 if (any
< 0 || acc
> cutoff
|| (acc
== cutoff
&& c
> cutlim
))
4410 *endptr
= (char *) (any
? s
- 1 : nptr
);
4414 /*---------------------------------------------------------------------------*/
4416 /*> EOF gencode.c <*/