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 */
119 #define FEATURE_IGEN (1 << 20) /* 0 = nothing; 1 = generate igen formatted output file */
121 /* We used to enable FEATURE_WARN_ZERO, but it is perfectly legitimate to
122 have the zero register as a destination -- the zero register just doesn't
124 /* start-sanitize-r5900 */
125 /* The 5900 madd instructions for example use this feature. */
126 /* end-sanitize-r5900 */
128 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31)
130 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
133 /* FEATURE_WARN_STALL */
134 /* If MIPS I we want to raise a warning if an attempt is made to
135 access Rn in an instruction immediately following an Rn update
136 "WARNING : Invalid value read". The simulator engine is designed
137 that the previous value is read in such cases, to allow programs
138 that make use of this feature to execute. */
139 /* If MIPS II or later, attempting to read a register before the
140 update has completed will generate a "WARNING : Processor stall"
141 message (since the processor will lock the pipeline until the value
142 becomes available). */
144 /* FEATURE_WARN_LOHI */
145 /* Warn if an attempt is made to read the HI/LO registers before the
146 update has completed, or if an attempt is made to update the
147 registers whilst an update is occurring. */
149 /* FEATURE_WARN_ZERO */
150 /* Notify the user if an attempt is made to use GPR 0 as a destination. */
152 /* FEATURE_WARN_R31 */
153 /* Notify the user if register r31 (the default procedure call return
154 address) is used unwisely. e.g. If r31 is used as the source in a
155 branch-and-link instruction, it would mean that an exception in the
156 delay slot instruction would not allow the branch to be re-started
157 (since r31 will have been overwritten by the link operation during
158 the first execution of the branch). */
160 /* FEATURE_WARN_RESULT */
161 /* Certain instructions do not raise exceptions when invalid operands
162 are given, they will just result in undefined values being
163 generated. This option controls whether the simulator flags such
166 /*---------------------------------------------------------------------------*/
173 #include "ansidecl.h"
174 #include "opcode/mips.h"
176 /* FIXME: ansidecl.h defines AND. */
180 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
183 static unsigned long my_strtoul ();
187 #define TRUE (1 == 1)
188 #define FALSE (1 == 0)
192 /*---------------------------------------------------------------------------*/
194 /* Holding the instruction table this way makes it easier to check the
195 instruction values defined, and to add instructions to the
196 system. However, it makes the process of constructing the simulator
197 a bit more complicated: */
199 /* The "bitmap" is encoded as follows (NOTE: Only lower-case
200 alphabetic characters should be used, since the letter ordinal is
201 used as a bit position): */
203 typedef struct operand_encoding
{
204 char id
; /* character identifier */
205 int fpos
; /* first bit position */
206 int flen
; /* field length in bits */
212 /* Values for the "flags" field: */
213 #define OP_NONE (0 << 0) /* To keep the source tidy */
214 #define OP_GPR (1 << 0) /* Get operand from integer register bank */
215 #define OP_SIGNX (1 << 1) /* Sign-extend the operand */
216 #define OP_SHIFT2 (1 << 2) /* Shift field left by 2 */
217 #define OP_BITS5 (1 << 3) /* Only take the lo 5-bits of the operand */
218 #define OP_GPR1 (1 << 4) /* fetch from the GPR1 registers */
220 struct operand_encoding opfields
[] = {
221 {'0',-1,-1,"", "", (OP_NONE
)}, /* special case for explicit zero */
222 {'1',-1,-1,"", "", (OP_NONE
)}, /* special case for explicit one */
223 {'?',-1,-1,"", "", (OP_NONE
)}, /* undefined (do not care at this level) */
224 /* The rest are the explicit operand fields: */
225 {'a', 6, 5,"int", "op1", (OP_NONE
)}, /* shift amount (or hint) */
226 {'b',21, 5,"int", "fr", (OP_NONE
)}, /* fr register */
227 {'c',16, 1,"int", "boolean", (OP_NONE
)}, /* TRUE or FALSE boolean */
228 {'d',11, 5,"int", "destreg", (OP_NONE
)}, /* integer destination/rd register */
229 {'e', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-3bits must be zero) */
230 {'f',17, 1,"int", "likely", (OP_NONE
)}, /* set if branch LIKELY */
231 {'g',16, 5,"t_reg", "op2", (OP_GPR
)}, /* integer source rt register */
232 {'h', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-1bit must be zero) */
233 {'i', 0,16,"t_reg", "op2", (OP_SIGNX
)}, /* signed immediate (op2) */
234 {'j', 0,26,"ut_reg","op1", (OP_SHIFT2
)},/* shifted left 2 bits and combined with hi-order bits of address in the delay slot */
235 {'k',16, 5,"int", "ft", (OP_NONE
)},
236 {'l', 0,16,"t_reg", "offset", (OP_SIGNX
| OP_SHIFT2
)}, /* signed offset shifted left 2 to make 18bit signed offset */
237 {'m',21, 3,"int", "format", (OP_NONE
)}, /* FP format field */
238 {'n',16, 5,"int", "hint", (OP_NONE
)}, /* hint */
239 {'o',21, 5,"t_reg", "op1", (OP_GPR
| OP_BITS5
)}, /* integer source/rs register (but never treated as 32bit word) */
240 {'p', 8, 3,"int", "condition_code",(OP_NONE
)}, /* FP condition code field */
241 {'q',18, 3,"int", "condition_code",(OP_NONE
)}, /* FP condition code field */
242 {'r', 6, 5,"int", "destreg", (OP_NONE
)}, /* FP fd register */
243 {'s',21, 5,"t_reg", "op1", (OP_GPR
)}, /* integer source/rs register */
244 {'t',16, 5,"int", "destreg", (OP_NONE
)}, /* integer target rt (destination) register */
245 {'u', 0, 4,"int", "cmpflags", (OP_NONE
)}, /* FP comparison control flags */
246 {'v',11, 5,"int", "fs", (OP_NONE
)}, /* FP fs register (or PREFX hint) */
247 {'w', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-2bits must be zero) */
248 {'x',23, 1,"int", "to", (OP_NONE
)}, /* TRUE if move To; FALSE if move From */
249 {'y', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset */
250 {'z', 0,16,"ut_reg","op2", (OP_NONE
)}, /* unsigned immediate (zero extended) */
251 {'S',21, 5,"t_reg", "rs_reg", (OP_GPR
|OP_GPR1
)}, /* rs field, GPR[rs] and GPR1[rs] as source */
252 {'T',16, 5,"t_reg", "rt_reg", (OP_GPR
|OP_GPR1
)}, /* rt field, GPR[rt] and GPR1[rt] as source */
256 /* Main instruction encoding types: */
263 COP1S
, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
271 /* mips16 encoding types. */
272 I
, RI
, RR
, RRI
, RRR
, RRI_A
, ISHIFT
, I8
, I8_MOVR32
, I8_MOV32R
, I64
, RI64
275 /* Main instruction families: */
277 ADD
, /* res = operand1 + operand2 */
278 SUB
, /* res = operand1 - operand2 */
279 MUL
, /* res = operand1 * operand2 */
280 DIV
, /* res = operand1 / operand2 */
281 AND
, /* res = operand1 & operand2 */
282 OR
, /* res = operand1 | operand2 */
283 XOR
, /* res = operand1 ^ operand2 */
284 MOVE
, /* res = operand1 */
285 BRANCH
, /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
286 JUMP
, /* execute delay slot instruction before jump */
287 LOAD
, /* load from memory */
288 STORE
, /* store to memory */
289 PREFETCH
, /* prefetch data into cache */
290 SET
, /* set register on result of condition code */
291 SHIFT
, /* perform a logical or arithmetic shift */
292 TRAP
, /* system exception generation */
293 BREAK
, /* system breakpoint exception generation */
294 SDBBP
, /* software debug breakpoint exception generation */
295 SYSCALL
, /* system exception generation */
296 SYNC
, /* system cache control */
297 DECODE
, /* co-processor instruction */
298 CACHE
, /* co-processor 0 CACHE instruction */
299 MADD16
, /* VR4100 specific multiply-add extensions */
318 /* start-sanitize-r5900 */
364 /* end-sanitize-r5900 */
365 NYI
, /* Not Yet Implemented, placeholder, errors if used */
366 RSVD
/* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
370 #define NONE (0 << 0) /* Zero value (used to keep source tidy) */
371 #define SIM_SH_SIZE (0)
372 #define SIM_MASK_SIZE (0x7)
373 #define BYTE (0) /* 8bit */
374 #define HALFWORD (1) /* 16bit */
375 #define WORD (2) /* 32bit */
376 #define DOUBLEWORD (3) /* 64bit */
377 #define SINGLE (4) /* single precision FP */
378 #define DOUBLE (5) /* double precision FP */
379 /* start-sanitize-r5900 */
380 #define QUADWORD (6) /* 128bit */
381 /* end-sanitize-r5900 */
383 /* Shorthand to get the size field from the flags value: */
384 #define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
386 /* The rest are single bit flags: */
387 #define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
392 #define LIKELY (1 << 8)
393 #define SIGNEXTEND (1 << 9)
394 #define OVERFLOW (1 << 10)
395 #define LINK (1 << 11)
396 #define ATOMIC (1 << 12)
397 #define SHIFT16 (1 << 13)
398 #define REG (1 << 14)
399 #define LEFT (1 << 15) /* Deliberate explicit encodings to allow check for neither, or both */
400 #define RIGHT (1 << 16) /* Mutually exclusive with "LEFT" */
401 #define LOGICAL (1 << 17)
402 #define ARITHMETIC (1 << 18)
403 #define UNSIGNED (1 << 19)
404 #define HI32 (1 << 20)
405 #define HI (1 << 21) /* accesses or updates the HI register */
406 #define LO (1 << 22) /* accesses or updates the LO register */
407 #define WORD32 (1 << 23)
408 #define FP (1 << 24) /* Floating Point operation */
409 #define FIXED (1 << 25) /* fixed point arithmetic */
410 #define COPROC (1 << 26)
411 #define INTEGER (1 << 27)
412 #define CONDITIONAL (1 << 28)
413 #define RECIP (1 << 29)
414 #define CONTROL (1 << 30)
415 #define NOARG (1 << 31) /* Instruction has no (defined) operands */
416 /* NOTE: We can overload the use of certain of these flags, since not
417 all options are applicable to all instruction types. This will free
418 up more space for new flags. */
420 /* Overloadings of above bits */
421 #define PIPE1 LIKELY /* Using pipeline 1 (DIV,MUL) */
422 #define OP3 EQ /* 3 operand version of operation (MUL) */
424 #define SATURATE OVERFLOW /* for PADD, saturate for overflow */
426 #define SUBTRACT LEFT /* for PMULT, PMULT becomes PMSUB */
427 #define ADDITION RIGHT /* for PMULT, PMULT becomes PMADD */
429 #define FROM LEFT /* move from special register */
430 #define TO RIGHT /* move to special register */
432 /* For bitwise parallel operations */
433 #define POP_AND 0 /* for POP, op = & */
434 #define POP_OR LEFT /* for POP, op = | */
435 #define POP_NOR LIKELY /* for POP, op = ~(x | y) */
436 #define POP_XOR LEFT|LIKELY /* for POP, op = ^ */
438 #define GET_OP_FROM_INSN(insn) (((insn)->flags)&(LEFT|LIKELY))
442 typedef struct instruction
{
443 char *name
; /* ASCII mnemonic name */
444 unsigned int isa
; /* MIPS ISA number where instruction introduced */
445 char *bitmap
; /* 32character string describing instruction operands */
446 inst_type mark
; /* type of MIPS instruction encoding */
447 opcode_type type
; /* main instruction family */
448 unsigned int flags
; /* flags describing instruction features */
450 /* The number of pipeline cycles taken by an instruction varies
451 between MIPS processors. This means that the information must be
452 encoded elsewhere, in a CPU specific structure. */
454 /* NOTE: Undefined instructions cause "Reserved Instruction"
455 exceptions. i.e. if there is no bit-mapping defined then the
456 instruction is deemed to be undefined. */
458 /* NOTE: The "isa" field is also used to encode flags for particular
459 chip architecture extensions. e.g. the NEC VR4100 specific
460 instructions. Normally chip extensions are added via the COP0
461 space. However, the VR4100 (and possibly other devices) also use
462 the normal instruction space. */
463 #define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */
464 /* The other bits are allocated downwards, to avoid renumbering if we
465 have to extend the bits allocated to the pure ISA number.
467 These architecture bits come in two flavors:
468 ISA dependent - marking insns that should be included in the opcode
469 set if that architecture is requested on the gencode command line
470 AND the ISA of the insn is <= requested ISA;
472 ISA independent - marking insn that should be included in the opcode
473 set if that architecture is requested
474 OR the ISA of the insn is <= requested ISA.
476 Independent bits are listed in MASK_ISA_INDEP, the rest are dependent.
478 #define ARCH_VR4100 ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
479 /* start-sanitize-r5900 */
480 #define ARCH_R5900 ((unsigned)1 << 30) /* Toshiba r5900 extension instructions */
481 /* end-sanitize-r5900 */
482 #define ARCH_R3900 ((unsigned)1 << 29) /* Toshiba r3900 (tx39) */
483 /* start-sanitize-tx19 */
484 /* The r1900 (tx19) is a tx39 with a mips16 decoder. For the purposes
485 of implementing the simulator we treat them as the same. */
486 /* end-sanitize-tx19 */
488 /* A list (or'ed) of extension insn sets that can be requested independant of the ISA# */
489 #define MASK_ISA_INDEP (0 \
491 /* start-sanitize-r5900 */ \
493 /* end-sanitize-r5900 */ \
496 #define MASK_ISA_DEP ~(MASK_ISA_INDEP | MASK_ISA)
498 /* Very short names for use in the table below to keep it neet. */
499 #define G1 (3 | ARCH_VR4100)
502 /* start-sanitize-r5900 */ \
504 /* end-sanitize-r5900 */ \
508 /* start-sanitize-r5900 */ \
509 /* insn that are not really 5900 insn but were left in */ \
510 /* until we can rewrite the code-gen and libs */ \
512 /* end-sanitize-r5900 */ \
515 #define G4 (2 | ARCH_R3900)
519 /* start-sanitize-r5900 */ \
521 /* end-sanitize-r5900 */ \
524 #define G6 (3 | ARCH_R3900)
526 #define T3 ARCH_R3900
527 /* start-sanitize-r5900 */
528 #define T5 ARCH_R5900
529 /* end-sanitize-r5900 */
532 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
533 COP0 space. This means that an external decoder should be added
534 when constructing a full VR4100 simulator. However some arithmetic
535 instructions are encoded in the normal instruction space. */
537 struct instruction MIPS_DECODE
[] = {
538 /* The instructions are alphabetical, and not in instruction bit-order: */
539 {"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1
, FPABS
, (FP
)},
540 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL
,ADD
, (WORD
| WORD32
| OVERFLOW
)}, /* rd = rs + rt */
541 {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1
, FPADD
, (FP
)},
542 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
| OVERFLOW
)},
543 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL
,ADD
, (WORD
| WORD32
)}, /* rd = rs + rt */
544 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
)},
545 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL
,AND
, (NONE
)}, /* rd = rs AND rt */
546 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, AND
, (NONE
)},
547 {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S
, BRANCH
, (FP
)},
548 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
)},
549 {"BEQL", G4
,"010100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
| LIKELY
)},
550 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
)},
551 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
552 {"BGEZALL",G4
,"000001sssss10011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
553 {"BGEZL", G4
,"000001sssss00011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LIKELY
)},
554 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
)},
555 {"BGTZL", G4
,"010111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
| LIKELY
)},
556 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
)},
557 {"BLEZL", G4
,"010110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
| LIKELY
)},
558 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM
, BRANCH
, (LT
)},
559 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
)},
560 {"BLTZALL",G4
,"000001sssss10010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
| LIKELY
)},
561 {"BLTZL", G4
,"000001sssss00010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LIKELY
)},
562 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
)},
563 {"BNEL", G4
,"010101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
| LIKELY
)},
564 {"BREAK", 1,"000000????????????????????001101",SPECIAL
,BREAK
, (NOARG
)},
565 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1
, FPCEIL
, (FP
| FIXED
| DOUBLEWORD
)},
566 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1
, FPCEIL
, (FP
| FIXED
| WORD
)},
567 {"COP0", 1,"010000??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
568 {"COP2", 1,"010010??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
569 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1
, FPCONVERT
,(FP
| DOUBLE
)},
570 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1
, FPCONVERT
,(FP
| FIXED
| DOUBLEWORD
)},
571 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1
, FPCONVERT
,(FP
| SINGLE
)},
572 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1
, FPCONVERT
,(FP
| FIXED
| WORD
)},
573 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1
, FPCOMPARE
,(FP
)},
574 {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
| CONTROL
)},
575 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL
,ADD
, (DOUBLEWORD
| OVERFLOW
)},
576 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| OVERFLOW
)},
577 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL
,ADD
, (DOUBLEWORD
| UNSIGNED
)},
578 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| UNSIGNED
)},
579 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL
,DIV
, (DOUBLEWORD
| HI
| LO
)},
580 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL
,DIV
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
581 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
)},
582 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1
, FPDIV
, (FP
| WORD
| HI
| LO
)},
583 /* start-sanitize-r5900 */
584 {"DIV1", T5
,"011100sssssggggg0000000000011010",MMINORM
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
| PIPE1
)},
585 /* end-sanitize-r5900 */
586 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
)},
587 /* start-sanitize-r5900 */
588 {"DIVU1", T5
,"011100sssssggggg0000000000011011",MMINORM
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
| PIPE1
)},
589 /* end-sanitize-r5900 */
590 {"DMADD16",G1
,"000000sssssggggg0000000000101001",SPECIAL
,MADD16
, (DOUBLEWORD
| HI
| LO
)},
591 {"DMULT", 3,"000000sssssggggg0000000000011100",SPECIAL
,MUL
, (DOUBLEWORD
| HI
| LO
)},
592 {"DMULTU", 3,"000000sssssggggg0000000000011101",SPECIAL
,MUL
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
593 {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| DOUBLEWORD
)},
594 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
)},
595 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| REG
)},
596 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| HI32
)}, /* rd = rt << (sa + 32) */
597 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
)},
598 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| REG
)},
599 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| HI32
)}, /* rd = rt >> (sa + 32) */
600 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
)},
601 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| REG
)},
602 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| HI32
)},
603 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL
,SUB
, (DOUBLEWORD
)},
604 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL
,SUB
, (DOUBLEWORD
| UNSIGNED
)},
605 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1
, FPFLOOR
, (FP
| FIXED
| DOUBLEWORD
)},
606 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1
, FPFLOOR
, (FP
| FIXED
| WORD
)},
607 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (NONE
)}, /* NOTE: boundary case due to delay slot address being used */
608 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
)}, /* NOTE: boundary case due to delay slot address being used */
609 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL
,JUMP
, (LINK
| REG
)},
610 {"JALX", 1,"011101jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
| NOT
)},
611 {"JR", 1,"000000sssss000000000000000001000",SPECIAL
,JUMP
, (NONE
)}, /* need to check PC as part of instruction fetch */
612 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
| SIGNEXTEND
)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
613 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
)}, /* NOTE: See "LB" comment */
614 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
)},
615 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
616 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
617 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| LEFT
)}, /* NOTE: See "LB" comment */
618 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| RIGHT
)}, /* NOTE: See "LB" comment */
619 {"LDXC1", G3
,"010011sssssggggg00000rrrrr000001",COP1X
, LOAD
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
620 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
| SIGNEXTEND
)},
621 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
)},
622 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| ATOMIC
| SIGNEXTEND
)},
623 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| ATOMIC
)},
624 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL
, MOVE
, (SHIFT16
)}, /* Cheat and specify sign-extension of immediate field */
625 /* start-sanitize-r5900 */
626 {"LQ", T5
,"011110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (QUADWORD
)},
627 /* end-sanitize-r5900 */
628 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| SIGNEXTEND
)},
629 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
630 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
631 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| LEFT
)},
632 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| RIGHT
)},
633 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
)},
634 {"LWXC1", G3
,"010011sssssggggg00000rrrrr000000",COP1X
, LOAD
, (FP
| WORD
| COPROC
| REG
)},
635 {"MADD", G5
,"011100sssssgggggddddd00000000000",MMINORM
,MADD
, (NONE
)},
636 {"MADDU", G5
,"011100sssssgggggddddd00000000001",MMINORM
,MADD
, (UNSIGNED
)},
637 /* start-sanitize-r5900 */
638 {"MADD1", T5
,"011100sssssgggggddddd00000100000",MMINORM
,MADD
, (PIPE1
)},
639 {"MADDU1", T5
,"011100sssssgggggddddd00000100001",MMINORM
,MADD
, (UNSIGNED
| PIPE1
)},
640 /* end-sanitize-r5900 */
641 {"MADD16", G1
,"000000sssssggggg0000000000101000",SPECIAL
,MADD16
, (WORD
| HI
| LO
)},
642 {"MADD.D", G3
,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X
, FPADD
, (FP
| MULTIPLY
| DOUBLE
)},
643 {"MADD.S", G3
,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X
, FPADD
, (FP
| MULTIPLY
| SINGLE
)},
644 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL
,MOVE
, (HI
| LEFT
)}, /* with following, from and to denoted by usage of LEFT or RIGHT */
645 /* start-sanitize-r5900 */
646 {"MFHI1", T5
,"0111000000000000ddddd00000010000",MMINORM
,MOVE
, (HI
| LEFT
| PIPE1
)},
647 /* end-sanitize-r5900 */
648 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL
,MOVE
, (LO
| LEFT
)},
649 /* start-sanitize-r5900 */
650 {"MFLO1", T5
,"0111000000000000ddddd00000010010",MMINORM
,MOVE
, (LO
| LEFT
| PIPE1
)},
651 {"MFSA", T5
,"0000000000000000ddddd00000101000",SPECIAL
,MxSA
, (FROM
)},
652 /* end-sanitize-r5900 */
653 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL
,MOVE
, (HI
| RIGHT
)},
654 /* start-sanitize-r5900 */
655 {"MTHI1", T5
,"011100sssss000000000000000010001",MMINORM
,MOVE
, (HI
| RIGHT
| PIPE1
)},
656 /* end-sanitize-r5900 */
657 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL
,MOVE
, (LO
| RIGHT
)},
658 /* start-sanitize-r5900 */
659 {"MTLO1", T5
,"011100sssss000000000000000010011",MMINORM
,MOVE
, (LO
| RIGHT
| PIPE1
)},
660 {"MTSA", T5
,"000000sssss000000000000000101001",SPECIAL
,MxSA
, (TO
)},
661 {"MTSAB", T5
,"000001sssss11000iiiiiiiiiiiiiiii",REGIMM
, MTSAB
, (NONE
)},
662 {"MTSAH", T5
,"000001sssss11001iiiiiiiiiiiiiiii",REGIMM
, MTSAH
, (NONE
)},
663 /* end-sanitize-r5900 */
664 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1
, FPMOVE
, (FP
)},
665 {"MOVN", G2
,"000000sssssgggggddddd00000001011",SPECIAL
,MOVE
, (NOT
| EQ
)},
666 {"MOVN", G2
,"01000110mmmgggggvvvvvrrrrr010011",COP1
, FPMOVE
, (FP
| NOT
| EQ
)},
667 {"MOV%c", G3
,"000000sssssqqq0cddddd00000000001",SPECIAL
,FPMOVE
, (FP
| CONDITIONAL
| INTEGER
)},
668 {"MOV%c", G3
,"01000110mmmqqq0cvvvvvrrrrr010001",COP1
, FPMOVE
, (FP
| CONDITIONAL
)},
669 {"MOVZ", G2
,"000000sssssgggggddddd00000001010",SPECIAL
,MOVE
, (EQ
)},
670 {"MOVZ", G2
,"01000110mmmgggggvvvvvrrrrr010010",COP1
, FPMOVE
, (FP
| EQ
)},
671 {"MSUB.D", G3
,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X
, FPSUB
, (FP
| MULTIPLY
| DOUBLE
)},
672 {"MSUB.S", G3
,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X
, FPSUB
, (FP
| MULTIPLY
| SINGLE
)},
673 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1
, FPMUL
, (FP
| HI
| LO
)},
674 {"MULT", 1,"000000sssssgggggddddd00000011000",SPECIAL
,MUL
, (OP3
| WORD
| WORD32
| HI
| LO
)},
675 /* start-sanitize-r5900 */
676 {"MULT1", T5
,"011100sssssgggggddddd00000011000",MMINORM
,MUL
, (OP3
| WORD
| WORD32
| HI
| LO
| PIPE1
)},
677 /* end-sanitize-r5900 */
678 {"MULTU", 1,"000000sssssgggggddddd00000011001",SPECIAL
,MUL
, (OP3
| WORD
| WORD32
| UNSIGNED
| HI
| LO
)},
679 /* start-sanitize-r5900 */
680 {"MULTU1", T5
,"011100sssssgggggddddd00000011001",MMINORM
,MUL
, (OP3
| WORD
| WORD32
| UNSIGNED
| HI
| LO
| PIPE1
)},
681 /* end-sanitize-r5900 */
682 {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
)},
683 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1
, FPNEG
, (FP
)},
684 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
685 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
686 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
687 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
688 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL
,OR
, (NOT
)},
689 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL
,OR
, (NONE
)},
690 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, OR
, (NONE
)},
692 /* start-sanitize-r5900 */
693 {"PABSH", T5
,"01110000000TTTTTddddd00101101000",MMI1
, PABS
, (HALFWORD
)},
694 {"PABSW", T5
,"01110000000TTTTTddddd00001101000",MMI1
, PABS
, (WORD
)},
696 {"PADDB", T5
,"011100SSSSSTTTTTddddd01000001000",MMI0
, PADD
, (BYTE
)},
697 {"PADDH", T5
,"011100SSSSSTTTTTddddd00100001000",MMI0
, PADD
, (HALFWORD
)},
698 {"PADDW", T5
,"011100SSSSSTTTTTddddd00000001000",MMI0
, PADD
, (WORD
)},
700 {"PADDSB", T5
,"011100SSSSSTTTTTddddd11000001000",MMI0
, PADD
, (BYTE
| SATURATE
)},
701 {"PADDSH", T5
,"011100SSSSSTTTTTddddd10100001000",MMI0
, PADD
, (HALFWORD
| SATURATE
)},
702 {"PADDSW", T5
,"011100SSSSSTTTTTddddd10000001000",MMI0
, PADD
, (WORD
| SATURATE
)},
704 {"PADDUB", T5
,"011100SSSSSTTTTTddddd11000101000",MMI1
, PADD
, (BYTE
| UNSIGNED
)},
705 {"PADDUH", T5
,"011100SSSSSTTTTTddddd10100101000",MMI1
, PADD
, (HALFWORD
| UNSIGNED
)},
706 {"PADDUW", T5
,"011100SSSSSTTTTTddddd10000101000",MMI1
, PADD
, (WORD
| UNSIGNED
)},
708 {"PADSBH", T5
,"011100SSSSSTTTTTddddd00100101000",MMI1
, PADSBH
, (NONE
)},
710 {"PAND", T5
,"011100SSSSSTTTTTddddd10010001001",MMI2
, POP
, (POP_AND
)},
712 {"PCEQB", T5
,"011100SSSSSTTTTTddddd01010101000",MMI1
, PCMP
, (EQ
| BYTE
)},
713 {"PCEQH", T5
,"011100SSSSSTTTTTddddd00110101000",MMI1
, PCMP
, (EQ
| HALFWORD
)},
714 {"PCEQW", T5
,"011100SSSSSTTTTTddddd00010101000",MMI1
, PCMP
, (EQ
| WORD
)},
716 {"PCGTB", T5
,"011100SSSSSTTTTTddddd01010001000",MMI0
, PCMP
, (GT
| BYTE
)},
717 {"PCGTH", T5
,"011100SSSSSTTTTTddddd00110001000",MMI0
, PCMP
, (GT
| HALFWORD
)},
718 {"PCGTW", T5
,"011100SSSSSTTTTTddddd00010001000",MMI0
, PCMP
, (GT
| WORD
)},
720 {"PCPYH", T5
,"01110000000TTTTTddddd11011101001",MMI3
, PCPYH
, (NONE
)},
721 {"PCPYLD", T5
,"011100SSSSSTTTTTddddd01110001001",MMI2
, PCPYLD
, (NONE
)},
722 {"PCPYUD", T5
,"011100SSSSSTTTTTddddd01110101001",MMI3
, PCPYUD
, (NONE
)},
724 {"PDIVBW", T5
,"011100SSSSSTTTTT0000011101001001",MMI2
, PDIVBW
, (NONE
)},
725 {"PDIVUW", T5
,"011100SSSSSTTTTT0000001101101001",MMI3
, PDIVW
, (UNSIGNED
)},
726 {"PDIVW", T5
,"011100SSSSSTTTTT0000001101001001",MMI2
, PDIVW
, (NONE
)},
728 {"PEXCH", T5
,"01110000000TTTTTddddd11010101001",MMI3
, PEXCH
, (NONE
)},
729 {"PEXCW", T5
,"01110000000TTTTTddddd11110101001",MMI3
, PEXCW
, (NONE
)},
730 {"PEXOH", T5
,"01110000000TTTTTddddd11010001001",MMI2
, PEXOH
, (NONE
)},
731 {"PEXOW", T5
,"01110000000TTTTTddddd11110001001",MMI2
, PEXOW
, (NONE
)},
733 {"PEXT5", T5
,"01110000000TTTTTddddd11110001000",MMI0
, PEXT5
, (NONE
)},
735 {"PEXTLB", T5
,"011100SSSSSTTTTTddddd11010001000",MMI0
, PEXTLB
, (NONE
)},
736 {"PEXTLH", T5
,"011100SSSSSTTTTTddddd10110001000",MMI0
, PEXTLH
, (NONE
)},
737 {"PEXTLW", T5
,"011100SSSSSTTTTTddddd10010001000",MMI0
, PEXTLW
, (NONE
)},
738 {"PEXTUB", T5
,"011100SSSSSTTTTTddddd11010101000",MMI1
, PEXTUB
, (NONE
)},
739 {"PEXTUH", T5
,"011100SSSSSTTTTTddddd10110101000",MMI1
, PEXTUH
, (NONE
)},
740 {"PEXTUW", T5
,"011100SSSSSTTTTTddddd10010101000",MMI1
, PEXTUW
, (NONE
)},
742 {"PHMADDH",T5
,"011100SSSSSTTTTTddddd10001001001",MMI2
, PHMADDH
, (NONE
)},
743 {"PHMSUBH",T5
,"011100SSSSSTTTTTddddd10101001001",MMI2
, PHMADDH
, (SUBTRACT
)},
745 {"PINTH", T5
,"011100SSSSSTTTTTddddd01010001001",MMI2
, PINTH
, (NONE
)},
746 {"PINTOH", T5
,"011100SSSSSTTTTTddddd01010101001",MMI3
, PINTOH
, (NONE
)},
748 {"PLZCW", T5
,"011100SSSSS00000ddddd00000000100",MMINORM
,PLZCW
, (NONE
)},
750 {"PMADDH", T5
,"011100SSSSSTTTTTddddd10000001001",MMI2
, PMULTH
, (ADDITION
)},
751 {"PMADDUW",T5
,"011100SSSSSTTTTTddddd00000101001",MMI3
, PMULTW
, (ADDITION
| UNSIGNED
)},
752 {"PMADDW", T5
,"011100SSSSSTTTTTddddd00000001001",MMI2
, PMULTW
, (ADDITION
)},
754 {"PMAXH", T5
,"011100SSSSSTTTTTddddd00111001000",MMI0
, PMAXMIN
, (GT
| HALFWORD
)},
755 {"PMAXW", T5
,"011100SSSSSTTTTTddddd00011001000",MMI0
, PMAXMIN
, (GT
| WORD
)},
757 {"PMFHI", T5
,"0111000000000000ddddd01000001001",MMI2
, PMXX
, (HI
|FROM
)},
758 {"PMFLO", T5
,"0111000000000000ddddd01001001001",MMI2
, PMXX
, (LO
|FROM
)},
760 {"PMFHL", T5
,"0111000000000000dddddaaaaa110000",MMINORM
,PMFHL
, (NONE
)},
762 {"PMINH", T5
,"011100SSSSSTTTTTddddd00111101000",MMI1
, PMAXMIN
, (LT
| HALFWORD
)},
763 {"PMINW", T5
,"011100SSSSSTTTTTddddd00011101000",MMI1
, PMAXMIN
, (LT
| WORD
)},
765 {"PMSUBH", T5
,"011100SSSSSTTTTTddddd10100001001",MMI2
, PMULTH
, (SUBTRACT
)},
766 {"PMSUBW", T5
,"011100SSSSSTTTTTddddd00100001001",MMI2
, PMULTW
, (SUBTRACT
)},
768 {"PMTHI", T5
,"011100SSSSS000000000001000101001",MMI3
, PMXX
, (HI
|TO
)},
769 {"PMTLO", T5
,"011100SSSSS000000000001001101001",MMI3
, PMXX
, (LO
|TO
)},
771 {"PMTHL.LW",T5
,"011100SSSSS000000000000000110001",MMINORM
,PMTHL
, (NONE
)},
773 {"PMULTH", T5
,"011100SSSSSTTTTTddddd11100001001",MMI2
, PMULTH
, (NONE
)},
774 {"PMULTUW",T5
,"011100SSSSSTTTTTddddd01100101001",MMI3
, PMULTW
, (UNSIGNED
)},
775 {"PMULTW", T5
,"011100SSSSSTTTTTddddd01100001001",MMI2
, PMULTW
, (NONE
)},
777 {"PNOR", T5
,"011100SSSSSTTTTTddddd10011101001",MMI3
, POP
, (POP_NOR
)},
778 {"POR", T5
,"011100SSSSSTTTTTddddd10010101001",MMI3
, POP
, (POP_OR
)},
780 {"PPAC5", T5
,"01110000000TTTTTddddd11111001000",MMI0
, PPAC5
, (NONE
)},
782 {"PPACB", T5
,"011100SSSSSTTTTTddddd11011001000",MMI0
, PPACB
, (NONE
)},
783 {"PPACH", T5
,"011100SSSSSTTTTTddddd10111001000",MMI0
, PPACH
, (NONE
)},
784 {"PPACW", T5
,"011100SSSSSTTTTTddddd10011001000",MMI0
, PPACW
, (NONE
)},
786 {"PREVH", T5
,"01110000000TTTTTddddd11011001001",MMI2
, PREVH
, (NONE
)},
787 {"PROT3W", T5
,"01110000000TTTTTddddd11111001001",MMI2
, PROT3W
, (NONE
)},
789 {"PSLLH", T5
,"01110000000TTTTTdddddaaaaa110100",MMINORM
,PSHIFT
, (LEFT
| LOGICAL
| HALFWORD
)},
790 {"PSLLVW", T5
,"011100SSSSSTTTTTddddd00010001001",MMI2
, PSLLVW
, (NONE
)},
791 {"PSLLW", T5
,"01110000000TTTTTdddddaaaaa111100",MMINORM
,PSHIFT
, (LEFT
| LOGICAL
| WORD
)},
793 {"PSRAH", T5
,"01110000000TTTTTdddddaaaaa110111",MMINORM
,PSHIFT
, (RIGHT
| ARITHMETIC
| HALFWORD
)},
794 {"PSRAVW", T5
,"011100SSSSSTTTTTddddd00011101001",MMI3
, PSRAVW
, (NONE
)},
795 {"PSRAW", T5
,"01110000000TTTTTdddddaaaaa111111",MMINORM
,PSHIFT
, (RIGHT
| ARITHMETIC
| WORD
)},
797 {"PSRLH", T5
,"01110000000TTTTTdddddaaaaa110110",MMINORM
,PSHIFT
, (RIGHT
| LOGICAL
| HALFWORD
)},
798 {"PSRLVW", T5
,"011100SSSSSTTTTTddddd00011001001",MMI2
, PSRLVW
, (NONE
)},
799 {"PSRLW", T5
,"01110000000TTTTTdddddaaaaa111110",MMINORM
,PSHIFT
, (RIGHT
| LOGICAL
| WORD
)},
801 {"PSUBB", T5
,"011100SSSSSTTTTTddddd01001001000",MMI0
, PADD
, (SUBTRACT
| BYTE
)},
802 {"PSUBH", T5
,"011100SSSSSTTTTTddddd00101001000",MMI0
, PADD
, (SUBTRACT
| HALFWORD
)},
803 {"PSUBSB", T5
,"011100SSSSSTTTTTddddd11001001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| BYTE
)},
804 {"PSUBSH", T5
,"011100SSSSSTTTTTddddd10101001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| HALFWORD
)},
805 {"PSUBSW", T5
,"011100SSSSSTTTTTddddd10001001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| WORD
)},
806 {"PSUBUB", T5
,"011100SSSSSTTTTTddddd11001101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| BYTE
)},
807 {"PSUBUH", T5
,"011100SSSSSTTTTTddddd10101101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| HALFWORD
)},
808 {"PSUBUW", T5
,"011100SSSSSTTTTTddddd10001101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| WORD
)},
809 {"PSUBW", T5
,"011100SSSSSTTTTTddddd00001001000",MMI0
, PADD
, (SUBTRACT
| WORD
)},
811 {"PXOR", T5
,"011100SSSSSTTTTTddddd10011001001",MMI2
, POP
, (POP_XOR
)},
812 /* end-sanitize-r5900 */
814 {"PREF", G2
,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, PREFETCH
, (NONE
)},
815 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X
, FPPREFX
, (FP
)},
817 /* start-sanitize-r5900 */
818 {"QFSRV", T5
,"011100SSSSSTTTTTddddd11011101000",MMI1
, QFSRV
, (NONE
)},
819 /* end-sanitize-r5900 */
821 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1
, FPRECIP
, (FP
)},
822 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1
, FPROUND
, (FP
| FIXED
| DOUBLEWORD
)},
823 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1
, FPROUND
, (FP
| FIXED
| WORD
)},
824 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1
, FPSQRT
, (FP
| RECIP
)},
825 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (BYTE
)},
826 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| ATOMIC
)},
827 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| ATOMIC
)},
828 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
)},
829 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
830 {"SDBBP", T3
,"000000????????????????????001110",SPECIAL
,SDBBP
, (NOARG
)},
831 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
832 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| LEFT
)},
833 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| RIGHT
)},
834 {"SDXC1", G3
,"010011sssssgggggvvvvv00000001001",COP1X
, STORE
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
835 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL
, STORE
, (HALFWORD
)},
836 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << sa */
837 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
838 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL
,SET
, (LT
)},
839 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
)},
840 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL
,SET
, (LT
| UNSIGNED
)},
841 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
| UNSIGNED
)},
842 /* start-sanitize-r5900 */
843 {"SQ", T5
,"011111sssssTTTTTeeeeeeeeeeeeeeee",NORMAL
, STORE
, (QUADWORD
)},
844 /* end-sanitize-r5900 */
845 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1
, FPSQRT
, (FP
)},
846 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
847 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
848 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
849 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
850 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL
,SUB
, (WORD
| WORD32
| OVERFLOW
)},
851 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1
, FPSUB
, (FP
)},
852 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL
,SUB
, (WORD
| WORD32
)},
853 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
)},
854 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
855 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
856 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| LEFT
)},
857 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| RIGHT
)},
858 {"SWXC1", G3
,"010011sssssgggggvvvvv00000001000",COP1X
, STORE
, (FP
| WORD
| COPROC
| REG
)},
859 {"SYNC", G4
,"000000000000000000000aaaaa001111",SPECIAL
,SYNC
, (NONE
)}, /* z = 5bit stype field */
860 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL
,SYSCALL
, (NOARG
)},
861 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL
,TRAP
, (EQ
)},
862 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (EQ
)},
863 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL
,TRAP
, (GT
| EQ
)},
864 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
)},
865 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
| UNSIGNED
)},
866 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL
,TRAP
, (GT
| EQ
| UNSIGNED
)},
867 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL
,TRAP
, (LT
)},
868 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
)},
869 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
| UNSIGNED
)},
870 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL
,TRAP
, (LT
| UNSIGNED
)},
871 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL
,TRAP
, (NOT
| EQ
)},
872 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (NOT
| EQ
)},
873 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1
, FPTRUNC
, (FP
| FIXED
| DOUBLEWORD
)},
874 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1
, FPTRUNC
, (FP
| FIXED
| WORD
)},
875 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL
,XOR
, (NONE
)},
876 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, XOR
, (NONE
)},
877 {"CACHE", G6
,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, CACHE
, (NONE
)},
878 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, RSVD
, (NONE
)},
881 static const struct instruction MIPS16_DECODE
[] = {
882 {"ADDIU", 1, "01000xxxddd04444", RRI_A
, ADD
, WORD
| WORD32
},
883 {"ADDIU8", 1, "01001wwwkkkkkkkk", RI
, ADD
, WORD
| WORD32
},
884 {"ADJSP", 1, "01100011KKKKKKKKS", I8
, ADD
, WORD
| WORD32
},
885 {"ADDIUPC", 1, "00001dddAAAAAAAAP", RI
, ADD
, WORD
| WORD32
},
886 {"ADDIUSP", 1, "00000dddAAAAAAAAs", RI
, ADD
, WORD
| WORD32
},
887 {"ADDU", 1, "11100xxxyyyddd01", RRR
, ADD
, WORD
| WORD32
},
888 {"AND", 1, "11101wwwyyy01100", RR
, AND
, NONE
},
889 {"B", 1, "00010qqqqqqqqqqqzZ", I
, BRANCH
, EQ
},
890 {"BEQZ", 1, "00100xxxppppppppz", RI
, BRANCH
, EQ
},
891 {"BNEZ", 1, "00101xxxppppppppz", RI
, BRANCH
, NOT
| EQ
},
892 {"BREAK", 1, "01100??????00101", RR
, BREAK
, NOARG
},
893 {"BTEQZ", 1, "01100000pppppppptz", I8
, BRANCH
, EQ
},
894 {"BTNEZ", 1, "01100001pppppppptz", I8
, BRANCH
, NOT
| EQ
},
895 {"CMP", 1, "11101xxxyyy01010T", RR
, XOR
, NONE
},
896 {"CMPI", 1, "01110xxxUUUUUUUUT", RI
, XOR
, NONE
},
897 {"DADDIU", 3, "01000xxxddd14444", RRI_A
, ADD
, DOUBLEWORD
},
898 {"DADDIU5", 3, "11111101wwwjjjjj", RI64
, ADD
, DOUBLEWORD
},
899 {"DADJSP", 3, "11111011KKKKKKKKS", I64
, ADD
, DOUBLEWORD
},
900 {"DADIUPC", 3, "11111110dddEEEEEP", RI64
, ADD
, DOUBLEWORD
},
901 {"DADIUSP", 3, "11111111dddEEEEEs", RI64
, ADD
, DOUBLEWORD
},
902 {"DADDU", 3, "11100xxxyyyddd00", RRR
, ADD
, DOUBLEWORD
},
903 {"DDIV", 3, "11101xxxyyy11110", RR
, DIV
, DOUBLEWORD
| HI
| LO
},
904 {"DDIVU", 3, "11101xxxyyy11111", RR
, DIV
, DOUBLEWORD
| UNSIGNED
| HI
| LO
},
905 {"DIV", 1, "11101xxxyyy11010", RR
, DIV
, WORD
| WORD32
| SIGNEXTEND
| HI
| LO
},
906 {"DIVU", 1, "11101xxxyyy11011", RR
, DIV
, WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
},
907 {"DMULT", 3, "11101xxxyyy11100", RR
, MUL
, DOUBLEWORD
| HI
| LO
},
908 {"DMULTU", 3, "11101xxxyyy11101", RR
, MUL
, DOUBLEWORD
| UNSIGNED
| HI
| LO
},
909 {"DSLL", 3, "00110dddyyy[[[01", ISHIFT
, SHIFT
, DOUBLEWORD
| LEFT
| LOGICAL
},
910 {"DSLLV", 3, "11101xxxvvv10100", RR
, SHIFT
, DOUBLEWORD
| LEFT
| LOGICAL
| REG
},
911 {"DSRA", 3, "11101]]]vvv10011", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| ARITHMETIC
},
912 {"DSRAV", 3, "11101xxxvvv10111", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| ARITHMETIC
| REG
},
913 {"DSRL", 3, "11101]]]vvv01000", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| LOGICAL
},
914 {"DSRLV", 3, "11101xxxvvv10110", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| LOGICAL
| REG
},
915 {"DSUBU", 3, "11100xxxyyyddd10", RRR
, SUB
, DOUBLEWORD
| UNSIGNED
},
917 /* FIXME: Should we handle these ourselves, or should we require an
918 emulation routine? */
919 {"EXIT", 1, "1110111100001000", RR
, BREAK
, EXIT
},
920 {"ENTRY", 1, "11101??????01000", RR
, BREAK
, ENTRY
},
922 {"EXTEND", 1, "11110eeeeeeeeeee", I
, RSVD
, NOARG
},
923 {"JALR", 1, "11101xxx01000000R", RR
, JUMP
, LINK
| REG
},
924 {"JAL", 1, "00011aaaaaaaaaaa", I
, JUMP
, LINK
},
925 {"JR", 1, "11101xxx00000000", RR
, JUMP
, NONE
},
926 {"JRRA", 1, "1110100000100000r", RR
, JUMP
, NONE
},
927 {"LB", 1, "10000xxxddd55555", RRI
, LOAD
, BYTE
| SIGNEXTEND
},
928 {"LBU", 1, "10100xxxddd55555", RRI
, LOAD
, BYTE
},
929 {"LD", 3, "00111xxxdddDDDDD", RRI
, LOAD
, DOUBLEWORD
},
930 {"LDPC", 3, "11111100dddDDDDDP", RI64
, LOAD
, DOUBLEWORD
},
931 {"LDSP", 3, "11111000dddDDDDDs", RI64
, LOAD
, DOUBLEWORD
},
932 {"LH", 1, "10001xxxdddHHHHH", RRI
, LOAD
, HALFWORD
| SIGNEXTEND
},
933 {"LHU", 1, "10101xxxdddHHHHH", RRI
, LOAD
, HALFWORD
},
934 {"LI", 1, "01101dddUUUUUUUUZ", RI
, OR
, NONE
},
935 {"LW", 1, "10011xxxdddWWWWW", RRI
, LOAD
, WORD
| SIGNEXTEND
},
936 {"LWPC", 1, "10110dddVVVVVVVVP", RI
, LOAD
, WORD
| SIGNEXTEND
},
937 {"LWSP", 1, "10010dddVVVVVVVVs", RI
, LOAD
, WORD
| SIGNEXTEND
},
938 {"LWU", 1, "10111xxxdddWWWWW", RRI
, LOAD
, WORD
},
939 {"MFHI", 1, "11101ddd00010000", RR
, MOVE
, HI
| LEFT
},
940 {"MFLO", 1, "11101ddd00010010", RR
, MOVE
, LO
| LEFT
},
941 {"MOVR32", 1, "01100111dddXXXXXz", I8_MOVR32
, OR
, NONE
},
942 {"MOV32R", 1, "01100101YYYYYxxxz", I8_MOV32R
, OR
, NONE
},
943 {"MULT", 1, "11101xxxyyy11000", RR
, MUL
, WORD
| WORD32
| HI
| LO
},
944 {"MULTU", 1, "11101xxxyyy11001", RR
, MUL
, WORD
| WORD32
| UNSIGNED
| HI
| LO
},
945 {"NEG", 1, "11101dddyyy01011Z", RR
, SUB
, WORD
},
946 {"NOT", 1, "11101dddyyy01111Z", RR
, OR
, NOT
},
947 {"OR", 1, "11101wwwyyy01101", RR
, OR
, NONE
},
948 {"SB", 1, "11000xxxyyy55555", RRI
, STORE
, BYTE
},
949 {"SDBBP", T3
, "11100??????00001", RR
, SDBBP
, NOARG
},
950 {"SD", 3, "01111xxxyyyDDDDD", RRI
, STORE
, DOUBLEWORD
},
951 {"SDSP", 3, "11111001yyyDDDDDs", RI64
, STORE
, DOUBLEWORD
},
952 {"SDRASP", 3, "11111010CCCCCCCCsQ", I64
, STORE
, DOUBLEWORD
},
953 {"SH", 1, "11001xxxyyyHHHHH", RRI
, STORE
, HALFWORD
},
954 {"SLL", 1, "00110dddyyy<<<00", ISHIFT
, SHIFT
, WORD
| LEFT
| LOGICAL
},
955 {"SLLV", 1, "11101xxxvvv00100", RR
, SHIFT
, WORD
| LEFT
| LOGICAL
| REG
},
956 {"SLT", 1, "11101xxxyyy00010T", RR
, SET
, LT
},
957 {"SLTI", 1, "01010xxx88888888T", RI
, SET
, LT
},
958 {"SLTU", 1, "11101xxxyyy00011T", RR
, SET
, LT
| UNSIGNED
},
959 {"SLTIU", 1, "01011xxx88888888T", RI
, SET
, LT
| UNSIGNED
},
960 {"SRA", 1, "00110dddyyy<<<11", ISHIFT
, SHIFT
, WORD
| WORD32
| RIGHT
| ARITHMETIC
},
961 {"SRAV", 1, "11101xxxvvv00111", RR
, SHIFT
, WORD
| WORD32
| RIGHT
| ARITHMETIC
| REG
},
962 {"SRL", 1, "00110dddyyy<<<10", ISHIFT
, SHIFT
, WORD
| WORD32
| RIGHT
| LOGICAL
},
963 {"SRLV", 1, "11101xxxvvv00110", RR
, SHIFT
, WORD
| WORD32
| RIGHT
| LOGICAL
| REG
},
964 {"SUBU", 1, "11100xxxyyyddd11", RRR
, SUB
, WORD
| WORD32
},
965 {"SW", 1, "11011xxxyyyWWWWW", RRI
, STORE
, WORD
},
966 {"SWSP", 1, "11010yyyVVVVVVVVs", RI
, STORE
, WORD
},
967 {"SWRASP", 1, "01100010VVVVVVVVQs", I8
, STORE
, WORD
},
968 {"XOR", 1, "11101wwwyyy01110", RR
, XOR
, NONE
}
971 /*---------------------------------------------------------------------------*/
973 static void print_igen_insn_format
PARAMS ((const char *bitmap
,
980 print_igen_insn_format (bitmap
, mark
, data_size
, options
, name
)
989 for (chp
= bitmap
; *chp
!= '\0'; chp
++)
991 if ((isdigit (lch
) && !isdigit (*chp
))
992 || (!isdigit (lch
) && isdigit (*chp
))
993 || (!isdigit (lch
) && !isdigit (*chp
) && lch
!= *chp
))
1004 printf ("s"); /* good guess */
1007 printf ("%c", *chp
);
1029 case COP1S
: /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
1049 /* mips16 encoding types. */
1075 printf ("I8_MOVR32");
1078 printf ("I8_MOV32R");
1093 /* start-sanitize-r5900 */
1097 /* end-sanitize-r5900 */
1104 printf (":%s:%s\n", options
, name
);
1107 static void print_igen_insn_models
PARAMS ((unsigned int isa
));
1110 print_igen_insn_models (isa
)
1113 /* common mips ISAs */
1114 switch ((isa
& MASK_ISA
))
1117 printf ("*mipsI:\n");
1119 printf ("*mipsII:\n");
1121 printf ("*mipsIII:\n");
1122 /* start-sanitize-cygnus-never */
1123 printf ("// %s-%s-%s\n", "start", "sanitize", "r5900");
1124 /* end-sanitize-cygnus-never */
1125 /* start-sanitize-r5900 */
1126 printf ("*r5900:\n");
1127 /* end-sanitize-r5900 */
1128 /* start-sanitize-cygnus-never */
1129 printf ("// %s-%s-%s\n", "end", "sanitize", "r5900");
1130 /* end-sanitize-cygnus-never */
1131 printf ("*r3900:\n");
1132 /* start-sanitize-cygnus-never */
1133 printf ("// %s-%s-%s\n", "start", "sanitize", "tx19");
1134 /* end-sanitize-cygnus-never */
1135 /* start-sanitize-tx19 */
1136 printf ("*tx19:\n");
1137 /* end-sanitize-tx19 */
1138 /* start-sanitize-cygnus-never */
1139 printf ("// %s-%s-%s\n", "end", "sanitize", "tx19");
1140 /* end-sanitize-cygnus-never */
1143 /* processor specific ISAs */
1144 if ((isa
& ARCH_VR4100
))
1145 printf ("*vr4100:\n");
1146 /* start-sanitize-r5900 */
1147 if ((isa
& ARCH_R5900
))
1148 printf ("*r5900:\n");
1149 /* end-sanitize-r5900 */
1150 if ((isa
& ARCH_R3900
))
1151 printf ("*r3900:\n");
1155 /*---------------------------------------------------------------------------*/
1157 static int bitmap_val
PARAMS ((const char *, int, int));
1158 static void build_mips16_operands
PARAMS ((const char *));
1159 static void build_instruction
1160 PARAMS ((int, unsigned int, int, const struct instruction
*));
1162 /*---------------------------------------------------------------------------*/
1165 name_for_data_len( insn
)
1166 struct instruction
* insn
;
1168 if (GETDATASIZEINSN(insn
) == BYTE
)
1171 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1174 else if (GETDATASIZEINSN(insn
) == WORD
)
1177 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1178 return "DOUBLEWORD";
1180 /* start-sanitize-r5900 */
1181 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1184 /* end-sanitize-r5900 */
1190 letter_for_data_len( insn
)
1191 struct instruction
* insn
;
1193 if (GETDATASIZEINSN(insn
) == BYTE
)
1196 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1199 else if (GETDATASIZEINSN(insn
) == WORD
)
1202 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1205 /* start-sanitize-r5900 */
1206 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1209 /* end-sanitize-r5900 */
1215 type_for_data_len( insn
, is_signed
)
1216 struct instruction
* insn
;
1219 if (GETDATASIZEINSN(insn
) == BYTE
)
1220 return is_signed
? "int" : "unsigned int";
1222 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1223 return is_signed
? "int" : "unsigned int";
1225 else if (GETDATASIZEINSN(insn
) == WORD
)
1226 return is_signed
? "signed64" : "unsigned64";
1228 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1231 /* start-sanitize-r5900 */
1232 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1235 /* end-sanitize-r5900 */
1241 max_for_data_len( insn
)
1242 struct instruction
* insn
;
1244 if (GETDATASIZEINSN(insn
) == BYTE
)
1247 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1250 else if (GETDATASIZEINSN(insn
) == WORD
)
1251 return "(int)0x7FFFFFFF";
1253 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1256 /* start-sanitize-r5900 */
1257 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1260 /* end-sanitize-r5900 */
1266 min_for_data_len( insn
)
1267 struct instruction
* insn
;
1269 if (GETDATASIZEINSN(insn
) == BYTE
)
1272 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1275 else if (GETDATASIZEINSN(insn
) == WORD
)
1276 return "(int)0x80000000";
1278 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1281 /* start-sanitize-r5900 */
1282 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1285 /* end-sanitize-r5900 */
1291 umax_for_data_len( insn
)
1292 struct instruction
* insn
;
1294 if (GETDATASIZEINSN(insn
) == BYTE
)
1297 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1300 else if (GETDATASIZEINSN(insn
) == WORD
)
1301 return "0xFFFFFFFF";
1303 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1306 /* start-sanitize-r5900 */
1307 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1310 /* end-sanitize-r5900 */
1316 bits_for_data_len( insn
)
1317 struct instruction
* insn
;
1319 if (GETDATASIZEINSN(insn
) == BYTE
)
1322 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1325 else if (GETDATASIZEINSN(insn
) == WORD
)
1328 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1331 /* start-sanitize-r5900 */
1332 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1335 /* end-sanitize-r5900 */
1340 /*---------------------------------------------------------------------------*/
1344 convert_bitmap(bitmap
,onemask
,zeromask
,dontmask
)
1346 unsigned int *onemask
, *zeromask
, *dontmask
;
1348 int loop
; /* current bitmap position */
1349 int lastsp
= -1; /* last bitmap field starting position */
1350 int lastoe
= -1; /* last bitmap field encoding */
1352 *onemask
= 0x00000000;
1353 *zeromask
= 0x00000000;
1354 *dontmask
= 0x00000000;
1356 if (strlen(bitmap
) != 32) {
1357 fprintf(stderr
,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap
);
1361 for (loop
= 0; (loop
< 32); loop
++) {
1363 for (oefield
= 0; (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))); oefield
++)
1364 if (bitmap
[31 - loop
] == opfields
[oefield
].id
)
1366 if (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))) {
1367 if ((lastoe
!= -1) && (lastoe
!= oefield
))
1368 if ((loop
- lastsp
) != (opfields
[lastoe
].flen
)) {
1369 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
);
1373 switch (bitmap
[31 - loop
]) {
1374 case '0' : /* fixed value */
1375 *zeromask
|= (1 << loop
);
1380 case '1' : /* fixed value */
1381 *onemask
|= (1 << loop
);
1386 case '?' : /* fixed value */
1387 *dontmask
|= (1 << loop
);
1392 default : /* check character encoding */
1394 if (opfields
[oefield
].fpos
!= -1) {
1395 /* If flag not set, then check starting position: */
1396 if (lastoe
!= oefield
) {
1397 if (loop
!= opfields
[oefield
].fpos
) {
1398 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
);
1405 *dontmask
|= (1 << loop
);
1410 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
);
1415 /* NOTE: Since we check for the position and size of fields when
1416 parsing the "bitmap" above, we do *NOT* need to check that invalid
1417 field combinations have been used. */
1420 /* Get the value of a 16 bit bitstring for a given shift count and
1424 bitmap_val (bitmap
, shift
, bits
)
1433 s
= bitmap
+ 16 - shift
- bits
;
1434 for (; bits
> 0; --bits
)
1449 /*---------------------------------------------------------------------------*/
1452 build_operands(doisa
,features
,insn
)
1454 unsigned int features
;
1457 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
1458 int finish_jump_flag
= 0;
1460 int check_condition_code
= 0;
1461 int sfield_used
= 0;
1462 int gfield_used
= 0;
1463 int any_operand
= 0;
1465 int current_field_id
= -1;
1468 for (bitpos
=0; bitpos
<32; bitpos
++) {
1469 if (insn
->bitmap
[31-bitpos
] != current_field_id
)
1473 current_field_id
= insn
->bitmap
[31-bitpos
];
1475 for (opindex
= 0; (opindex
< (sizeof(opfields
) / sizeof(operand_encoding
))); opindex
++)
1476 if ((opfields
[opindex
].fpos
!= -1) && (opfields
[opindex
].id
== insn
->bitmap
[31-bitpos
])) {
1480 printf(" %s %s UNUSED = ",opfields
[opindex
].type
,opfields
[opindex
].name
);
1482 if (opfields
[opindex
].flags
& OP_SIGNX
)
1483 printf("SIGNEXTEND((%s)",opfields
[opindex
].type
);
1485 if (opfields
[opindex
].flags
& OP_GPR
)
1488 if (opfields
[opindex
].flags
& OP_SHIFT2
)
1491 printf("((instruction >> %d) & 0x%08X)",opfields
[opindex
].fpos
,((1 << opfields
[opindex
].flen
) - 1));
1493 if (opfields
[opindex
].flags
& OP_SHIFT2
)
1496 if (opfields
[opindex
].flags
& OP_GPR
)
1499 if (opfields
[opindex
].flags
& OP_BITS5
)
1502 if (opfields
[opindex
].flags
& OP_SIGNX
)
1503 printf(",%d)",(opfields
[opindex
].flen
+ ((opfields
[opindex
].flags
& OP_SHIFT2
) ? 2 : 0)));
1507 if (opfields
[opindex
].flags
& OP_GPR1
)
1509 printf(" %s %s1 = GPR1[",opfields
[opindex
].type
,opfields
[opindex
].name
);
1510 printf("((instruction >> %d) & 0x%08X)",
1511 opfields
[opindex
].fpos
,
1512 ((1 << opfields
[opindex
].flen
) - 1));
1516 if (opfields
[opindex
].id
== 'j')
1517 finish_jump_flag
= 1;
1519 if (opfields
[opindex
].id
== 'e')
1522 if (opfields
[opindex
].id
== 'w')
1525 if (opfields
[opindex
].id
== 'w')
1528 if (opfields
[opindex
].id
== 'p')
1529 check_condition_code
= 1;
1531 if (opfields
[opindex
].id
== 's')
1534 if (opfields
[opindex
].id
== 'g')
1540 if ( !any_operand
&& !(insn
->flags
& NOARG
)) {
1541 fprintf(stderr
,"Bitmap error: Instruction with no operand fields \"%s\"\n",insn
->name
) ;
1545 /* Finish constructing the jump address if required: */
1546 if (finish_jump_flag
)
1547 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
1549 /* Now perform required operand checks: */
1551 /* The following code has been removed, since it seems perfectly
1552 reasonable to have a non-aligned offset that is added to another
1553 non-aligned base to create an aligned address. Some more
1554 information on exactly what the MIPS IV specification requires is
1555 needed before deciding on the best strategy. Experimentation with a
1556 VR4300 suggests that we do not need to raise the warning. */
1558 /* For MIPS IV (and onwards), certain instruction operand values
1559 will give undefined results. For the simulator we could
1560 generate explicit exceptions (i.e. ReservedInstruction) to
1561 make it easier to spot invalid use. However, for the moment we
1562 just raise a warning. NOTE: This is a different check to the
1563 later decoding, which checks for the final address being
1566 if (check_mult
!= 0 && check_mult
!= 1) {
1567 printf(" if (instruction & 0x%1X)\n", check_mult
);
1569 /* NOTE: If we change this to a SignalException(), we must
1570 ensure that the following opcode processing is not
1571 executed. i.e. the code falls straight out to the simulator
1573 printf(" sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
1578 /* The extended condition codes only appeared in ISA IV */
1579 if (check_condition_code
&& (doisa
< 4)) {
1580 printf(" if (condition_code != 0)\n");
1582 printf(" SignalException(ReservedInstruction,instruction);\n");
1587 if ((insn
->flags
& WORD32
) && (GETDATASIZEINSN(insn
) != WORD
)) {
1588 fprintf(stderr
,"Error in opcode table: WORD32 set for non-WORD opcode\n");
1593 /* The R4000 book differs slightly from the MIPS IV ISA
1594 manual. An example is the sign-extension of a 64-bit processor
1595 SUBU operation, and what is meant by an Undefined Result. This
1596 is now provided purely as a warning. After examining a HW
1597 implementation, this is now purely a warning... and the actual
1598 operation is performed, with possibly undefined results. */
1599 if (((insn
->flags
& WORD32
) && proc64
) && (features
& FEATURE_WARN_RESULT
)) {
1600 /* The compiler should optimise out an OR with zero */
1601 printf(" if (%s | %s)\n",(sfield_used
? "NOTWORDVALUE(op1)" : "0"),(gfield_used
? "NOTWORDVALUE(op2)" : "0"));
1602 printf(" UndefinedResult();\n") ;
1605 /* Check that the source is a 32bit value */
1606 if ((insn
->flags
& WORD32
) && proc64
) {
1607 /* The compiler should optimise out an OR with zero */
1608 printf(" if (%s | %s)\n",(sfield_used
? "NOTWORDVALUE(op1)" : "0"),(gfield_used
? "NOTWORDVALUE(op2)" : "0"));
1609 printf(" UndefinedResult();\n") ;
1617 /* The mips16 operand table. */
1621 /* The character which appears in the bitmap string. */
1623 /* The type of the variable in the simulator. */
1624 const char *vartype
;
1625 /* The name of the variable in the simulator. */
1627 /* The number of bits. */
1629 /* The number of bits when extended (zero if can not be extended). */
1631 /* The amount by which the short form is shifted when it is used;
1632 for example, the sw instruction has a shift count of 2. */
1638 /* Flags which appears in the mips16 operand table. */
1640 /* Whether this is a mips16 register index. */
1641 #define MIPS16_REG16 (0x1)
1642 /* Whether this is a register value. */
1643 #define MIPS16_REGVAL (0x2)
1644 /* Whether this is a swapped mips32 register index (MOV32R) */
1645 #define MIPS16_REG32_SWAPPED (0x4)
1646 /* Whether this index is also the destination register. */
1647 #define MIPS16_DESTREG (0x8)
1648 /* Whether the short form is unsigned. */
1649 #define MIPS16_UNSP (0x10)
1650 /* Whether the extended form is unsigned. */
1651 #define MIPS16_EXTU (0x20)
1652 /* Implicit stack pointer. */
1653 #define MIPS16_SP (0x40)
1654 /* Implicit program counter. */
1655 #define MIPS16_PC (0x80)
1657 #define MIPS16_ZERO (0x100)
1659 #define MIPS16_TREG (0x200)
1661 #define MIPS16_RA (0x400)
1663 #define MIPS16_JUMP_ADDR (0x800)
1664 /* Branch offset. */
1665 #define MIPS16_BRANCH (0x1000)
1667 /* The mips16 operand table. */
1669 static const struct mips16_op mips16_op_table
[] =
1671 { 'd', "int", "destreg", 3, 0, 0, MIPS16_REG16
},
1672 { 'x', "t_reg", "op1", 3, 0, 0, MIPS16_REG16
| MIPS16_REGVAL
},
1673 { 'w', "t_reg", "op1", 3, 0, 0, MIPS16_REG16
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1674 { 'y', "t_reg", "op2", 3, 0, 0, MIPS16_REG16
| MIPS16_REGVAL
},
1675 { 'v', "t_reg", "op2", 3, 0, 0, MIPS16_REG16
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1676 { 'X', "t_reg", "op1", 5, 0, 0, MIPS16_REGVAL
},
1677 { 'Y', "int", "destreg", 5, 0, 0, MIPS16_REG32_SWAPPED
},
1678 { 'a', "ut_reg", "op1", 11, 0, 0, MIPS16_JUMP_ADDR
},
1679 { 'e', "int", "ext", 11, 0, 0, 0 },
1680 { '<', "int", "op1", 3, 5, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1681 { '>', "int", "op1", 3, 5, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1682 { '[', "int", "op1", 3, 6, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1683 { ']', "int", "op1", 3, 6, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1684 { '4', "int", "op2", 4, 15, 0, 0 },
1685 { '5', "int", "offset", 5, 16, 0, MIPS16_UNSP
},
1686 { 'H', "int", "offset", 5, 16, 1, MIPS16_UNSP
},
1687 { 'W', "int", "offset", 5, 16, 2, MIPS16_UNSP
},
1688 { 'D', "int", "offset", 5, 16, 3, MIPS16_UNSP
},
1689 { 'j', "int", "op2", 5, 16, 0, 0 },
1690 { '8', "int", "op2", 8, 16, 0, MIPS16_UNSP
},
1691 { 'V', "int", "offset", 8, 16, 2, MIPS16_UNSP
},
1692 { 'C', "int", "offset", 8, 16, 3, MIPS16_UNSP
},
1693 { 'U', "int", "op2", 8, 16, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1694 { 'k', "int", "op2", 8, 16, 0, 0 },
1695 { 'K', "int", "op2", 8, 16, 3, 0 },
1696 { 'p', "int", "offset", 8, 16, 0, MIPS16_BRANCH
},
1697 { 'q', "int", "offset", 11, 16, 0, MIPS16_BRANCH
},
1698 { 'A', "int", "op2", 8, 16, 2, MIPS16_UNSP
},
1699 { 'B', "int", "op2", 5, 16, 3, MIPS16_UNSP
},
1700 { 'E', "int", "op2", 5, 16, 2, MIPS16_UNSP
},
1702 /* The remaining operands are special operands which encode implied
1703 arguments. These only appear at the end of a bitmap string, and
1704 do not represent actual bits. */
1705 { 's', "t_reg", "op1", 0, 0, 0, MIPS16_SP
| MIPS16_REGVAL
},
1706 { 'S', "t_reg", "op1", 0, 0, 0, MIPS16_SP
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1707 { 'P', "t_reg", "op1", 0, 0, 0, MIPS16_PC
},
1708 { 'z', "t_reg", "op2", 0, 0, 0, MIPS16_ZERO
},
1709 { 'Z', "t_reg", "op1", 0, 0, 0, MIPS16_ZERO
},
1710 { 't', "t_reg", "op1", 0, 0, 0, MIPS16_TREG
| MIPS16_REGVAL
},
1711 { 'T', "int", "destreg", 0, 0, 0, MIPS16_TREG
},
1712 { 'r', "t_reg", "op1", 0, 0, 0, MIPS16_RA
| MIPS16_REGVAL
},
1713 { 'R', "int", "destreg", 0, 0, 0, MIPS16_RA
},
1714 { 'Q', "t_reg", "op2", 0, 0, 0, MIPS16_RA
| MIPS16_REGVAL
},
1716 { '\0', NULL
, NULL
, 0, 0, 0, 0 }
1719 /* Build mips16 operands. */
1722 build_mips16_operands (bitmap
)
1727 const struct mips16_op
*op
= NULL
;
1728 const struct mips16_op
*ops
[3];
1732 for (s
= bitmap
; *s
!= '\0'; s
++)
1739 /* Make sure we saw the right number of bits for that
1741 if (op
->nbits
!= 0 && (s
- bitmap
) - op
->nbits
!= start
)
1746 if (*s
== '0' || *s
== '1' || *s
== '?')
1751 for (op
= mips16_op_table
; op
->type
!= *s
; ++op
)
1752 if (op
->type
== '\0')
1755 printf (" %s %s = ", op
->vartype
, op
->name
);
1757 printf ("(instruction >> %d) & 0x%x",
1758 16 - (s
- bitmap
) - op
->nbits
,
1759 (1 << op
->nbits
) - 1);
1762 if ((op
->flags
& MIPS16_SP
) != 0)
1764 else if ((op
->flags
& MIPS16_PC
) != 0)
1768 printf ("((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : (have_extendval ? IPC - 2 : IPC)) & ~ (uword64) 1)");
1769 for (j
= 0; j
< opindex
; j
++)
1770 if (ops
[j
]->shift
!= 0)
1771 printf (" & ~ (uword64) 0x%x", (1 << ops
[j
]->shift
) - 1);
1773 else if ((op
->flags
& MIPS16_ZERO
) != 0)
1775 else if ((op
->flags
& MIPS16_TREG
) != 0)
1777 else if ((op
->flags
& MIPS16_RA
) != 0)
1784 if ((op
->flags
& MIPS16_DESTREG
) != 0)
1785 printf (" int destreg;\n");
1795 /* Make sure we saw the right number of bits for that
1797 if (op
->nbits
!= 0 && 16 - op
->nbits
!= start
)
1801 for (i
= 0; i
< opindex
; i
++)
1804 if ((op
->flags
& MIPS16_REG16
) != 0)
1806 printf (" if (%s < 2)\n", op
->name
);
1807 printf (" %s += 16;\n", op
->name
);
1809 if ((op
->flags
& MIPS16_REG32_SWAPPED
) != 0)
1810 printf (" %s = (%s >> 2) | ((%s & 3) << 3);\n",
1811 op
->name
, op
->name
, op
->name
);
1812 if ((op
->flags
& MIPS16_DESTREG
) != 0)
1813 printf (" destreg = %s;\n", op
->name
);
1814 if ((op
->flags
& MIPS16_REGVAL
) != 0)
1815 printf (" %s = GPR[%s];\n", op
->name
, op
->name
);
1817 if (op
->extbits
!= 0)
1819 printf (" if (have_extendval)\n");
1821 if (op
->extbits
== 16)
1822 printf (" %s |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0);\n",
1824 else if (op
->extbits
== 15)
1825 printf (" %s |= ((extendval & 0xf) << 11) | (extendval & 0x7f0);\n",
1827 else if (op
->extbits
== 6)
1828 printf (" %s = ((extendval >> 6) & 0x1f) | (extendval & 0x20);\n",
1831 printf (" %s = (extendval >> 6) & 0x1f;\n",
1833 if ((op
->flags
& MIPS16_EXTU
) == 0)
1835 printf (" if (%s >= 0x%x)\n",
1836 op
->name
, 1 << (op
->extbits
- 1));
1837 printf (" %s -= 0x%x;\n",
1838 op
->name
, 1 << op
->extbits
);
1840 printf (" have_extendval = 0;\n");
1844 if ((op
->flags
& MIPS16_UNSP
) == 0)
1846 printf (" if (%s >= 0x%x)\n",
1847 op
->name
, 1 << (op
->nbits
- 1));
1848 printf (" %s -= 0x%x;\n",
1849 op
->name
, 1 << op
->nbits
);
1852 printf (" %s <<= %d;\n", op
->name
, op
->shift
);
1853 if (op
->type
== '<' || op
->type
== '>'
1854 || op
->type
== '[' || op
->type
== ']')
1856 printf (" if (%s == 0)\n", op
->name
);
1857 printf (" %s = 8;\n", op
->name
);
1862 if ((op
->flags
& MIPS16_BRANCH
) != 0)
1863 printf (" %s *= 2;\n", op
->name
);
1865 if ((op
->flags
& MIPS16_JUMP_ADDR
) != 0)
1868 printf (" uword64 paddr;\n");
1869 printf (" int uncached;\n");
1870 printf (" if (AddressTranslation (PC &~ (uword64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL))\n");
1872 printf (" uword64 memval;\n");
1873 printf (" unsigned int reverse = (ReverseEndian ? 3 : 0);\n");
1874 printf (" unsigned int bigend = (BigEndianCPU ? 3 : 0);\n");
1875 printf (" unsigned int byte;\n");
1876 printf (" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\n");
1877 printf (" LoadMemory (&memval,0,uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
1878 printf (" byte = (((PC &~ (uword64) 1) & 0x7) ^ (bigend << 1));\n");
1879 printf (" memval = (memval >> (8 * byte)) & 0xffff;\n");
1880 printf (" %s = (((%s & 0x1f) << 23)\n", op
->name
, op
->name
);
1881 printf (" | ((%s & 0x3e0) << 13)\n", op
->name
);
1882 printf (" | (memval << 2));\n");
1883 printf (" if ((instruction & 0x400) == 0)\n");
1884 printf (" %s |= 1;\n", op
->name
);
1885 printf (" PC += 2;\n");
1888 printf (" %s |= PC & ~ (uword64) 0x0fffffff;\n", op
->name
);
1892 /* FIXME: Is this the way to detect an unused extend opcode? */
1893 printf (" if (have_extendval)\n");
1894 printf (" SignalException (ReservedInstruction, instruction);\n");
1897 /*---------------------------------------------------------------------------*/
1905 build_endian_shift(proc64
,datalen
,endbit
,direction
,shift
)
1909 e_endshift direction
;
1913 printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit
,endbit
);
1914 printf(" memval %s= %d;\n",direction
== s_left
? "<<" : ">>",shift
);
1921 /*---------------------------------------------------------------------------*/
1922 /* doisa = number of MIPS ISA simulator table is being constructed for.
1923 * proc64 = TRUE if constructing 64bit processor world.
1924 * dofp = boolean, TRUE if FP instructions are to be included.
1925 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
1929 process_instructions(doarch
,features
)
1930 unsigned int doarch
;
1931 unsigned int features
;
1933 int doisa
= (doarch
& MASK_ISA
);
1934 int limit
= (sizeof(MIPS_DECODE
) / sizeof(instruction
));
1935 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
1936 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
1937 int dofp
= (features
& FEATURE_HASFPU
);
1938 int fpsingle
= (features
& FEATURE_FPSINGLE
);
1943 fprintf(stderr
,"process_instructions: invalid structure length\n");
1947 if (proc64
&& (gprlen
!= 64)) {
1948 fprintf(stderr
,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
1952 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
1955 for (loop
= 0; (loop
< limit
); loop
++)
1956 if ((MIPS_DECODE
[loop
].isa
& MASK_ISA
) > maxisa
)
1957 maxisa
= (MIPS_DECODE
[loop
].isa
& MASK_ISA
);
1962 if (!(features
& FEATURE_IGEN
))
1964 printf("#if defined(SIM_MANIFESTS)\n");
1965 printf("#define MIPSISA (%d)\n",doisa
);
1967 printf("#define PROCESSOR_64BIT (1 == 1)\n");
1969 printf("#define PROCESSOR_64BIT (1 == 0)\n");
1970 #if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */
1971 printf("#define LOADDRMASK (0x%08X)\n",0x7);
1973 printf("#define LOADDRMASK (0x%08X)\n",(proc64
? 0x7 : 0x3));
1975 /* The FP registers are the same width as the CPU registers: */
1976 printf("#define GPRLEN (%d)\n",gprlen
);
1977 printf("typedef %s t_reg;\n",((gprlen
== 64) ? "word64" : "int"));
1978 printf("typedef %s ut_reg;\n",((gprlen
== 64) ? "uword64" : "unsigned int"));
1979 printf("typedef %s t_fpreg;\n",((gprlen
== 64) ? "word64" : "int"));
1981 printf("#define HASFPU (1 == 1)\n");
1982 if (features
& FEATURE_FAST
)
1983 printf("#define FASTSIM (1 == 1)\n");
1984 if (features
& FEATURE_WARN_STALL
)
1985 printf("#define WARN_STALL (1 == 1)\n");
1986 if (features
& FEATURE_WARN_LOHI
)
1987 printf("#define WARN_LOHI (1 == 1)\n");
1988 if (features
& FEATURE_WARN_ZERO
)
1989 printf("#define WARN_ZERO (1 == 1)\n");
1990 if (features
& FEATURE_WARN_MEM
)
1991 printf("#define WARN_MEM (1 == 1)\n");
1992 if (features
& FEATURE_WARN_R31
)
1993 printf("#define WARN_R31 (1 == 1)\n");
1994 if (features
& FEATURE_WARN_RESULT
)
1995 printf("#define WARN_RESULT (1 == 1)\n");
1997 printf("#else /* simulator engine */\n");
1999 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
2000 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64
? 64 : 32),doisa
,limit
);
2002 printf("/* %sFP instructions included */\n",(fpsingle
? "Single precision " : ""));
2003 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
2006 printf("#if !defined(PROCESSOR_64BIT)\n");
2007 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
2011 printf("/* Actual instruction decoding block */\n");
2012 printf("if ((vaddr & 1) == 0){\n");
2015 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP
,OP_MASK_OP
);
2016 limit
= (OP_MASK_OP
+ 1);
2018 printf("#ifdef DEBUG\n");
2019 printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n");
2022 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
2023 limit
+= (OP_MASK_SPEC
+ 1);
2025 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_RT
,OP_MASK_RT
);
2026 limit
+= (OP_MASK_RT
+ 1);
2028 printf("else if (num == 0x11) {\n");
2029 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM
,OP_SH_COP1NORM
,(OP_MASK_COP1NORM
<< OP_SH_COP1NORM
));
2030 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP
,OP_SH_COP1CMP
,(OP_MASK_COP1CMP
<< OP_SH_COP1CMP
));
2031 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,(OP_MASK_SPEC
& (OP_MASK_COP1CMP
<< OP_SH_COP1CMP
)));
2033 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
2034 limit
+= (OP_MASK_SPEC
+ 1);
2037 /* To keep this code quick, we just clear out the "to" bit
2038 here. The proper (though slower) code would be to have another
2039 conditional, checking whether this instruction is a branch or
2040 not, before limiting the range to the bottom two bits of the
2042 printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit
,OP_SH_COP1SPEC
,OP_MASK_COP1SPEC
,OP_MASK_COP1SCLR
);
2043 limit
+= (OP_MASK_COP1SPEC
+ 1);
2045 printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
2046 limit
+= (OP_MASK_SPEC
+ 1);
2048 printf("else if (num == 0x1C) {\n");
2049 printf(" int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI
,OP_MASK_MMI
);
2051 printf(" if (mmi_func == 0x08) \n");
2052 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
2053 limit
+= (OP_MASK_MMISUB
+ 1);
2055 printf(" else if (mmi_func == 0x28) \n");
2056 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
2057 limit
+= (OP_MASK_MMISUB
+ 1);
2059 printf(" else if (mmi_func == 0x09) \n");
2060 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
2061 limit
+= (OP_MASK_MMISUB
+ 1);
2063 printf(" else if (mmi_func == 0x29) \n");
2064 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
2065 limit
+= (OP_MASK_MMISUB
+ 1);
2068 printf(" num = (%d + mmi_func);\n",limit
);
2069 limit
+= (OP_MASK_MMI
+ 1);
2073 printf("/* Total possible switch entries: %d */\n",limit
) ;
2076 printf("#ifdef DEBUG\n");
2077 printf("printf(\"DBG: num = %%d\\n\",num);\n");
2080 printf("switch (num)\n") ;
2084 for (loop
= 0; (loop
< limit
); loop
++) {
2085 /* First check if the insn is in a requested isa# independent set,
2086 then check that the ISA number we are constructing for is
2087 valid, then if the instruction matches any of the
2088 architecture specific flags. NOTE: We allow a selected ISA of
2089 zero to be used to match all standard instructions. */
2090 unsigned int isa
= MIPS_DECODE
[loop
].isa
;
2091 if (((isa
& doarch
& MASK_ISA_INDEP
)
2092 || (((isa
& MASK_ISA
) <= doisa
)
2093 && (((isa
& MASK_ISA_DEP
) == 0) || ((isa
& MASK_ISA_DEP
) & doarch
) != 0)))
2094 && (!(MIPS_DECODE
[loop
].flags
& FP
) || ((MIPS_DECODE
[loop
].flags
& FP
) && dofp
))
2095 || (features
& FEATURE_IGEN
)) {
2096 unsigned int onemask
;
2097 unsigned int zeromask
;
2098 unsigned int dontmask
;
2100 unsigned int number
;
2102 convert_bitmap(MIPS_DECODE
[loop
].bitmap
,&onemask
,&zeromask
,&dontmask
);
2104 if (!(MIPS_DECODE
[loop
].flags
& COPROC
)
2105 && ((GETDATASIZEINSN(&MIPS_DECODE
[loop
]) == DOUBLEWORD
) && !proc64
)
2106 && !(features
& FEATURE_IGEN
)) {
2107 fprintf(stderr
,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE
[loop
].name
);
2112 printf("/* DEBUG: onemask 0x%08X */\n",onemask
) ;
2113 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask
) ;
2114 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask
) ;
2117 switch (MIPS_DECODE
[loop
].mark
) {
2119 mask
= (OP_MASK_OP
<< OP_SH_OP
) ;
2120 number
= ((onemask
>> OP_SH_OP
) & OP_MASK_OP
) ;
2124 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
2125 number
= ((OP_MASK_OP
+ 1) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
2129 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_RT
<< OP_SH_RT
)) ;
2130 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_RT
) & OP_MASK_RT
)) ;
2134 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
2135 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
2139 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_COP1SPEC
<< OP_SH_COP1SPEC
)) ;
2140 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_COP1SPEC
) & OP_MASK_COP1SPEC
)) ;
2144 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
2145 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
)) ;
2149 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
2150 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
2151 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
2152 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
2153 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
2157 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
2158 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
2159 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
2160 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
2161 + (OP_MASK_MMISUB
+ 1)
2162 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
2166 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
2167 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
2168 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
2169 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
2170 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
2171 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
2175 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
2176 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
2177 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
2178 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
2179 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
2180 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
2184 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)) ;
2185 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
2186 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
2187 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
2188 + (OP_MASK_MMISUB
+ 1)
2189 + ((onemask
>> OP_SH_MMI
) & OP_MASK_MMI
)) ;
2193 fprintf(stderr
,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE
[loop
].mark
,loop
,MIPS_DECODE
[loop
].name
) ;
2197 if (!(features
& FEATURE_IGEN
))
2199 printf("case %d : /* \"%s\" %s */\n",number
,MIPS_DECODE
[loop
].name
,MIPS_DECODE
[loop
].bitmap
) ;
2202 printf("/* DEBUG: mask 0x%08X */\n",mask
) ;
2203 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE
[loop
].name
);
2206 /* Check if there are any other explicit bits in the instruction: */
2207 if ((~mask
& (onemask
| zeromask
)) != 0x00000000) {
2208 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask
| zeromask
),onemask
) ;
2210 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2219 /* start-sanitize-cygnus-never */
2220 /* If any sanitization occures, this line should be printed */
2221 if ((MIPS_DECODE
[loop
].isa
& ARCH_R5900
))
2222 printf ("// %s-%s-%s\n", "start", "sanitize", "r5900");
2223 /* end-sanitize-cygnus-never */
2225 print_igen_insn_format (MIPS_DECODE
[loop
].bitmap
,
2226 MIPS_DECODE
[loop
].mark
, /* format-name */
2227 GETDATASIZEINSN (&MIPS_DECODE
[loop
]), /* filter-flags */
2229 MIPS_DECODE
[loop
].name
);
2230 print_igen_insn_models (MIPS_DECODE
[loop
].isa
);
2232 printf (" unsigned32 instruction = instruction_0;\n");
2235 /* Get hold of the operands */
2236 /* NOTE: If we wanted to make the simulator code smaller, we
2237 * could pull these into a common sequence before we perform
2238 * the instruction decoding. However, this would affect the
2239 * performance since unnecessary field extraction would be
2240 * occurring for certain instructions.
2242 * Also we do not perform checking for multiple definitions of a
2243 * particular operand here, since they are caught by the
2244 * compilation of the produced code.
2246 build_operands(doisa
, features
, &MIPS_DECODE
[loop
]);
2250 build_instruction (doisa
, features
, 0, &MIPS_DECODE
[loop
]);
2253 if (!(features
& FEATURE_IGEN
))
2256 printf(" break ;\n") ;
2262 /* start-sanitize-cygnus-never */
2263 /* When sanitized, this output should never be produced */
2264 if ((MIPS_DECODE
[loop
].isa
& ARCH_R5900
))
2265 printf ("// %s-%s-%s\n", "end", "sanitize", "r5900");
2266 /* end-sanitize-cygnus-never */
2273 if (!(features
& FEATURE_IGEN
))
2275 printf("default : /* Unrecognised instruction */\n") ;
2276 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2277 printf(" break ;\n") ;
2281 /* Handle mips16 instructions. The switch table looks like this:
2282 0 - 31: I, RI, and RRI instructions by major.
2283 32 - 35: ISHIFT instructions by function + 32
2284 36 - 37: RRI_A instructions by function + 36
2285 38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38
2286 46 - 49: RRR instructions by function + 46
2287 50 - 81: RR instructions by minor + 50 (except for minor == 0)
2288 82 - 89: I64 and RI64 instructions by funct + 82
2289 90 - 97: jalr (RR minor 0) by y + 90
2291 if (!(features
& FEATURE_IGEN
))
2293 printf ("else {\n");
2294 printf ("static int extendval;\n");
2295 printf ("static int have_extendval;\n");
2296 printf ("int num = ((instruction >> %d) & 0x%08X);\n",
2297 MIPS16OP_SH_OP
, MIPS16OP_MASK_OP
);
2298 printf ("switch (num)\n{\n");
2299 printf ("case 0x6: num = 32 + (instruction & 3); break;\n");
2300 printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n");
2301 printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n");
2302 printf ("case 0x1c: num = 46 + (instruction & 3); break;\n");
2303 printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n");
2304 printf (" if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n");
2305 printf (" break;\n");
2306 printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n");
2307 printf ("default: break;\n}\n");
2308 printf ("switch (num)\n{\n");
2311 for (loop
= 0; loop
< sizeof MIPS16_DECODE
/ sizeof MIPS16_DECODE
[0]; loop
++)
2316 if (! proc64
&& GETDATASIZEINSN (&MIPS16_DECODE
[loop
]) == DOUBLEWORD
)
2319 bitmap
= MIPS16_DECODE
[loop
].bitmap
;
2320 switch (MIPS16_DECODE
[loop
].mark
)
2325 num
= bitmap_val (bitmap
, 11, 5);
2328 num
= 32 + bitmap_val (bitmap
, 0, 2);
2331 num
= 36 + bitmap_val (bitmap
, 4, 1);
2336 num
= 38 + bitmap_val (bitmap
, 8, 3);
2339 num
= 46 + bitmap_val (bitmap
, 0, 2);
2345 minor
= bitmap_val (bitmap
, 0, 5);
2349 num
= 90 + bitmap_val (bitmap
, 5, 3);
2354 num
= 82 + bitmap_val (bitmap
, 8, 3);
2361 if (!(features
& FEATURE_IGEN
))
2363 printf ("case %d: /* \"%s\" %s */\n", num
, MIPS16_DECODE
[loop
].name
,
2370 print_igen_insn_format (bitmap
,
2371 MIPS16_DECODE
[loop
].mark
, /* format-name */
2372 -1, /* filter-flags -- -1 => MIPS16 */
2374 MIPS16_DECODE
[loop
].name
);
2375 printf ("*mips16:\n");
2377 printf (" unsigned32 instruction = instruction_0;\n");
2380 build_mips16_operands (bitmap
);
2384 /* build_instruction doesn't know about extend. */
2386 build_instruction (doisa
, features
, 1, &MIPS16_DECODE
[loop
]);
2389 printf (" extendval = ext;\n");
2390 printf (" have_extendval = 1;\n");
2394 if (!(features
& FEATURE_IGEN
))
2397 printf (" break ;\n") ;
2406 if (!(features
& FEATURE_IGEN
))
2408 printf ("default : /* Unrecognised instruction */\n") ;
2409 printf (" SignalException(ReservedInstruction,instruction);\n") ;
2410 printf (" break ;\n") ;
2413 printf("#endif /* simulator engine */\n");
2419 /* Output the code to execute an instruction, assuming the operands
2420 have already been extracted. */
2423 build_instruction (doisa
, features
, mips16
, insn
)
2425 unsigned int features
;
2427 const struct instruction
*insn
;
2429 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
2430 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
2431 char *regtype
= ((gprlen
== 64) ? "uword64" : "unsigned int");
2433 switch (insn
->type
) {
2434 /* TODO: To make these easier to edit and maintain, they should
2435 actually be provided as source macros (or inline functions)
2436 OUTSIDE this main switch statement. The PPC simulator has a
2437 neater scheme for describing the instruction sequences. */
2442 char *signed_basetype
= "unknown";
2443 char *unsigned_basetype
= "unknown";
2445 switch (GETDATASIZEINSN(insn
)) {
2447 signed_basetype
= "signed int";
2448 unsigned_basetype
= "unsigned int";
2451 signed_basetype
= "word64";
2452 unsigned_basetype
= "uword64";
2455 fprintf(stderr
,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZEINSN(insn
));
2459 if ((insn
->type
) == ADD
) {
2460 printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype
, unsigned_basetype
);
2461 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype
, signed_basetype
);
2462 if (insn
->flags
& OVERFLOW
) {
2463 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
2464 printf(" SignalException(IntegerOverflow);\n");
2467 if (!proc64
|| (insn
->flags
& UNSIGNED
) || (GETDATASIZEINSN(insn
) == DOUBLEWORD
))
2468 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
2469 else /* only sign-extend when placing 32bit result in 64bit processor */
2470 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
2472 printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype
, unsigned_basetype
);
2473 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype
, signed_basetype
);
2474 if (insn
->flags
& OVERFLOW
) { /* different signs => overflow if result_sign != arg_sign */
2475 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
2476 printf(" SignalException(IntegerOverflow);\n");
2479 /* UNSIGNED 32bit operations on a 64bit processor should
2480 *STILL* be sign-extended. We have cheated in the
2481 data-structure, by not marking it with UNSIGNED, and not
2482 setting OVERFLOW. */
2483 if (!proc64
|| (insn
->flags
& UNSIGNED
) || (GETDATASIZEINSN(insn
) == DOUBLEWORD
))
2484 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
2485 else /* only sign-extend when placing 32bit result in 64bit processor */
2486 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
2493 char* pipe
= (insn
->flags
& PIPE1
) ? "1" : "";
2495 if (features
& FEATURE_WARN_LOHI
) {
2496 printf(" CHECKHILO(\"Multiplication\");\n");
2499 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2500 printf(" uword64 mid;\n");
2501 printf(" uword64 midhi;\n");
2502 printf(" uword64 temp;\n");
2503 if ((insn
->flags
& UNSIGNED
) == 0)
2505 printf(" int sign = 0;\n");
2506 printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n");
2507 printf(" if (op2 < 0) { op2 = - op2; ++sign; }\n");
2509 printf(" LO%s = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n",pipe
);
2510 printf(" HI%s = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n",pipe
);
2511 printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
2512 printf(" midhi = SET64HI(WORD64LO(mid));\n");
2513 printf(" temp = (LO%s + midhi);\n",pipe
);
2514 printf(" if ((temp == midhi) ? (LO%s != 0) : (temp < midhi))\n",pipe
);
2515 printf(" HI%s += 1;\n",pipe
);
2516 printf(" HI%s += WORD64HI(mid);\n",pipe
);
2517 printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
2518 printf(" midhi = SET64HI(WORD64LO(mid));\n");
2519 printf(" LO%s = (temp + midhi);\n",pipe
);
2520 printf(" if ((LO%s == midhi) ? (temp != 0) : (LO%s < midhi))\n",pipe
,pipe
);
2521 printf(" HI%s += 1;\n",pipe
);
2522 printf(" HI%s += WORD64HI(mid);\n",pipe
);
2523 if ((insn
->flags
& UNSIGNED
) == 0)
2524 printf(" if (sign & 1) { LO%s = - LO%s; HI%s = (LO%s == 0 ? 0 : -1) - HI%s; }\n",pipe
,pipe
,pipe
,pipe
,pipe
);
2526 if (insn
->flags
& UNSIGNED
)
2527 printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
2529 printf(" uword64 temp = ((word64) op1 * (word64) op2);\n");
2530 printf(" LO%s = SIGNEXTEND((%s)WORD64LO(temp),32);\n",pipe
,regtype
);
2531 printf(" HI%s = SIGNEXTEND((%s)WORD64HI(temp),32);\n",pipe
,regtype
);
2533 if (insn
->flags
& OP3
)
2535 printf(" if ( destreg != 0 )\n");
2536 printf(" GPR[destreg] = LO%s;\n",pipe
);
2543 int boolU
= (insn
->flags
& UNSIGNED
);
2544 char* pipe
= (insn
->flags
& PIPE1
) ? "1" : "";
2546 if (features
& FEATURE_WARN_LOHI
) {
2547 printf(" CHECKHILO(\"Division\");\n");
2551 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2552 printf(" %sword64 d1 = op1;\n", (boolU
? "u" : ""));
2553 printf(" %sword64 d2 = op2;\n", (boolU
? "u" : ""));
2554 printf(" if (d2 == 0)\n");
2556 printf(" LO%s = SIGNED64 (0x8000000000000000);\n", pipe
);
2557 printf(" HI%s = 0;\n", pipe
);
2559 printf(" else if (d2 == -1 && d1 == SIGNED64 (0x8000000000000000))\n");
2561 printf(" LO%s = SIGNED64 (0x8000000000000000);\n", pipe
);
2562 printf(" HI%s = 0;\n", pipe
);
2566 printf(" LO%s = (d1 / d2);\n", pipe
);
2567 printf(" HI%s = (d1 %% d2);\n", pipe
);
2570 printf(" %sint d1 = op1;\n", (boolU
? "unsigned " : ""));
2571 printf(" %sint d2 = op2;\n", (boolU
? "unsigned " : ""));
2572 printf(" if (d2 == 0)\n");
2574 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe
);
2575 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe
);
2577 printf(" else if (d2 == -1 && d1 == 0x80000000)\n");
2579 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe
);
2580 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe
);
2584 printf(" LO%s = SIGNEXTEND((d1 / d2),32);\n", pipe
);
2585 printf(" HI%s = SIGNEXTEND((d1 %% d2),32);\n", pipe
);
2594 int datalen
= GETDATASIZEINSN(insn
);
2595 int bits
= ((datalen
== WORD
) ? 32 : 64);
2596 char *ltype
= ((datalen
== WORD
) ? "unsigned int" : "uword64");
2598 /* Check that the specified SHIFT is valid: */
2599 if ((datalen
== BYTE
) || (datalen
== HALFWORD
)) {
2600 fprintf(stderr
,"Shift \"%s\" specified with BYTE or HALFWORD\n",insn
->name
);
2603 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
2604 fprintf(stderr
,"Shift \"%s\" specified with both LEFT and RIGHT\n",insn
->name
);
2607 if (!(insn
->flags
& LEFT
) && !(insn
->flags
& RIGHT
)) {
2608 fprintf(stderr
,"Shift \"%s\" specified with neither LEFT or RIGHT\n",insn
->name
);
2611 if ((insn
->flags
& LOGICAL
) && (insn
->flags
& ARITHMETIC
)) {
2612 fprintf(stderr
,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",insn
->name
);
2615 if (!(insn
->flags
& LOGICAL
) && !(insn
->flags
& ARITHMETIC
)) {
2616 fprintf(stderr
,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",insn
->name
);
2619 if ((insn
->flags
& LEFT
) && (insn
->flags
& ARITHMETIC
)) {
2620 fprintf(stderr
,"Arithmetic LEFT shift \"%s\" specified\n",insn
->name
);
2624 /* Work around an MSC code generation bug by precomputing a value
2625 * with the sign bit set. */
2626 if (insn
->flags
& ARITHMETIC
)
2627 printf(" %s highbit = (%s)1 << %d;\n", ltype
, ltype
, bits
- 1);
2629 /* If register specified shift, then extract the relevant shift amount: */
2630 if (insn
->flags
& REG
)
2631 printf(" op1 &= 0x%02X;\n",(bits
- 1));
2633 /* If HI32 specified, then shift range is 32..63 */
2634 if (insn
->flags
& HI32
)
2635 printf(" op1 |= (1 << 5);\n");
2637 /* We do not need to perform pre-masking with 0xFFFFFFFF when
2638 dealing with 32bit shift lefts, since the sign-extension
2639 code will replace any remaining hi-bits: */
2640 if (insn
->flags
& LEFT
)
2641 printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
2643 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits
== 32) ? " & 0xFFFFFFFF" : ""));
2645 /* For ARITHMETIC shifts, we must duplicate the sign-bit. We
2646 don't do this if op1 is zero, since it is not needed and
2647 since that would cause an undefined shift of the number of
2648 bits in the type. */
2649 if (insn
->flags
& ARITHMETIC
)
2650 printf(" GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype
,bits
);
2652 /* Ensure WORD values are sign-extended into 64bit registers */
2653 if ((bits
== 32) && (gprlen
== 64))
2654 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits
);
2659 if (insn
->flags
& (HI
| LO
)) {
2660 char *regname
= ((insn
->flags
& LO
) ? "LO" : "HI");
2661 int pipe1
= (insn
->flags
& PIPE1
);
2662 if (insn
->flags
& LEFT
)
2663 printf(" GPR[destreg] = %s%s;\n",regname
,(pipe1
? "1" : ""));
2665 if (features
& FEATURE_WARN_LOHI
) {
2666 printf(" if (%s%sACCESS != 0)\n",regname
,(pipe1
? "1" : ""));
2667 printf(" sim_warning(\"MT (move-to) over-writing %s register value\");\n",regname
);
2669 printf(" %s%s = op1;\n",regname
,(pipe1
? "1" : ""));
2671 if (features
& FEATURE_WARN_LOHI
)
2672 printf(" %s%sACCESS = 3; /* 3rd instruction will be safe */\n",regname
,(pipe1
? "1" : ""));
2674 if (insn
->flags
& SHIFT16
)
2675 printf(" GPR[destreg] = (op2 << 16);\n");
2677 /* perform conditional move */
2678 if (!(insn
->flags
& EQ
)) {
2679 fprintf(stderr
,"Standard conditional %s does not have the equality flag\n",insn
->name
);
2682 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
2683 printf(" GPR[destreg] = op1;\n");
2688 printf(" SyncOperation(op1);\n");
2692 printf(" SignalException(SystemCall,instruction);\n");
2696 printf(" SignalException(BreakPoint,instruction);\n");
2700 printf(" SignalException(DebugBreakPoint,instruction);\n");
2705 int boolNOT
= (insn
->flags
& NOT
);
2706 int boolEQ
= (insn
->flags
& EQ
);
2707 int boolGT
= (insn
->flags
& GT
);
2708 int boolLT
= (insn
->flags
& LT
);
2709 int boolU
= (insn
->flags
& UNSIGNED
);
2711 if (boolGT
&& boolLT
) {
2712 fprintf(stderr
,"GT and LT specified for \"%s\"\n",insn
->name
);
2716 if (boolNOT
&& (boolGT
|| boolLT
)) {
2717 fprintf(stderr
,"NOT specified with GT or LT specified for \"%s\"\n",insn
->name
);
2721 printf(" if ((%sword64)op1 ",(boolU
? "u" : ""));
2722 printf("%c%s",(boolNOT
? '!' : (boolLT
? '<' : (boolGT
? '>' : '='))),(boolEQ
? "=" : ""));
2723 printf(" (%sword64)op2)\n",(boolU
? "u" : ""));
2724 printf(" SignalException(Trap,instruction);\n");
2730 int boolU
= (insn
->flags
& UNSIGNED
);
2732 if (!(insn
->flags
& LT
)) {
2733 fprintf(stderr
,"Set instruction without LT specified \"%s\"\n",insn
->name
);
2737 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU
? "u" : ""),(boolU
? "u" : ""));
2738 printf(" GPR[destreg] = 1;\n");
2740 printf(" GPR[destreg] = 0;\n");
2745 printf(" GPR[destreg] = (op1 & op2);\n");
2749 /* The default mips16 nop instruction does an or to register
2750 zero; catch that case, so that we don't get useless warnings
2751 from the simulator. */
2753 printf (" if (destreg != 0)\n");
2754 printf(" GPR[destreg] = %s(op1 | op2);\n",((insn
->flags
& NOT
) ? "~" : ""));
2758 printf(" GPR[destreg] = (op1 ^ op2);\n");
2762 printf(" decode_coproc(instruction);\n");
2766 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
2767 /* The virtual address is translated to a physical address using the TLB */
2768 /* The hint specifies a cache operation for that address */
2769 printf(" uword64 vaddr = (op1 + offset);\n");
2770 printf(" uword64 paddr;\n");
2771 printf(" int uncached;\n");
2772 /* NOTE: We are assuming that the AddressTranslation is a load: */
2773 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2774 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
2777 case MADD16
: /* VR4100 specific multiply-add instructions */
2778 /* Some of this code is shared with the standard multiply
2779 routines, so an effort should be made to merge where
2781 if (features
& FEATURE_WARN_LOHI
) {
2782 printf(" CHECKHILO(\"Multiply-Add\");\n");
2784 if (features
& FEATURE_WARN_RESULT
) {
2785 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
2786 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
2787 printf(" sim_warning(\"MADD16 operation with non-16bit operands\");\n");
2790 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
2791 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2792 printf(" LO = LO + temp;\n");
2794 printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
2795 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype
);
2796 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype
);
2801 case RSVD
: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
2803 printf(" if (CoProcPresent(3))\n");
2804 printf(" SignalException(CoProcessorUnusable);\n");
2807 printf(" SignalException(ReservedInstruction,instruction);\n");
2811 if (insn
->flags
& LINK
) {
2812 if (!(insn
->flags
& REG
))
2813 printf(" int destreg = 31;\n");
2814 printf(" GPR[destreg] = (PC + %d); /* NOTE: The PC is already %d ahead within the simulator */\n",
2815 mips16
? 2 : 4, mips16
? 2 : 4);
2818 if (insn
->flags
& NOT
)
2819 printf(" op1 ^= 1;\n");
2821 printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n");
2822 printf(" so we just truncate it to 32 bits here. */\n");
2823 printf(" op1 = WORD64LO(op1);\n");
2824 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
2825 printf(" DSPC = op1;\n");
2826 if ((insn
->flags
& LINK
)
2827 && ! (insn
->flags
& REG
))
2828 printf(" JALDELAYSLOT();\n");
2830 printf(" DELAYSLOT();\n");
2833 case BRANCH
: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
2834 if (insn
->flags
& FP
) {
2836 printf(" if (condition_code != 0)\n");
2837 printf(" SignalException(ReservedInstruction,instruction);\n");
2838 printf(" else {\n");
2840 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
2841 printf(" int condition = (%s == boolean);\n",((doisa
< 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
2843 if ((insn
->flags
& NOT
) && !(insn
->flags
& EQ
)) {
2844 fprintf(stderr
,"NOT specified when not EQ in \"%s\"\n",insn
->name
);
2847 if ((insn
->flags
& NOT
) && (insn
->flags
& (GT
| LT
))) {
2848 fprintf(stderr
,"NOT specified with GT or LT in \"%s\"\n",insn
->name
);
2852 if (insn
->flags
& GT
)
2853 printf(" int condition = (op1 >%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
2855 if (insn
->flags
& LT
)
2856 printf(" int condition = (op1 <%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
2858 if (insn
->flags
& EQ
)
2859 printf(" int condition = (op1 %c= op2);\n",((insn
->flags
& NOT
) ? '!' : '='));
2862 if (insn
->flags
& LINK
) {
2863 if (features
& FEATURE_WARN_R31
) {
2864 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS
,OP_MASK_RS
);
2865 printf(" sim_warning(\"Branch with link using r31 as source operand\");\n");
2867 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
2871 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
2872 printf(" if (condition) {\n");
2873 printf(" DSPC = (PC + offset);\n");
2874 printf(" DELAYSLOT();\n");
2877 /* No delayed slots for mips16 branches. */
2878 printf(" if (condition)\n");
2879 printf(" PC = PC + offset;\n");
2881 if ((insn
->flags
& FP
) && (doisa
!= 1)) {
2882 printf(" else if (likely) {\n");
2883 printf(" NULLIFY();\n");
2885 } else if (insn
->flags
& LIKELY
) {
2887 printf(" NULLIFY();\n");
2889 if ((insn
->flags
& FP
) && (doisa
< 4))
2893 case PREFETCH
: /* The beginning is shared with normal load operations */
2897 int isload
= ((insn
->type
== LOAD
) || (insn
->type
== PREFETCH
));
2899 char *accesslength
= "<UNKNOWN>";
2901 switch (GETDATASIZEINSN(insn
)) {
2904 accesslength
= "AccessLength_BYTE";
2909 accesslength
= "AccessLength_HALFWORD";
2914 accesslength
= "AccessLength_WORD";
2919 accesslength
= "AccessLength_DOUBLEWORD";
2921 /* start-sanitize-r5900 */
2925 accesslength
= "AccessLength_QUADWORD";
2927 /* end-sanitize-r5900 */
2930 if (insn
->flags
& REG
)
2931 printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
2933 printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
2934 printf(" uword64 paddr;\n");
2935 printf(" int uncached;\n");
2937 /* The following check should only occur on normal (non-shifted) memory loads */
2938 if ((datalen
!= 1) && !(insn
->flags
& (LEFT
| RIGHT
))) {
2939 printf(" if ((vaddr & %d) != 0)\n",(datalen
- 1));
2940 printf(" SignalException(%s);\n",(isload
? "AddressLoad" : "AddressStore"));
2945 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload
? "isLOAD" : "isSTORE"));
2947 if (insn
->type
== PREFETCH
)
2948 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
2951 printf(" uword64 memval = 0;\n");
2952 printf(" uword64 memval1 = 0;\n");
2954 if ((insn
->flags
& COPROC
) && ((datalen
!= 4) && (datalen
!= 8))) {
2955 fprintf(stderr
,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
2959 if (insn
->flags
& (LEFT
| RIGHT
)) {
2960 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
2961 fprintf(stderr
,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",insn
->name
);
2967 if (!(features
& FEATURE_IGEN
))
2970 fprintf(stderr
,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn
->name
);
2974 /* fall through to... */
2977 printf(" uword64 mask = %d;\n",((datalen
== 8) ? 0x7 : 0x3));
2978 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
2979 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
2980 printf(" int byte;\n");
2981 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
2982 printf(" byte = ((vaddr & mask) ^ bigend);\n");
2983 printf(" if (%s!ByteSwapMem)\n",((insn
->flags
& LEFT
) ? "!" : ""));
2984 printf(" paddr &= ~mask;\n");
2987 if (insn
->flags
& LEFT
)
2989 printf(" LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
2993 printf(" LoadMemory(&memval,&memval1,uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen
- 1));
2997 if (insn
->flags
& LEFT
) {
2999 /* For WORD transfers work out if the value will
3000 be in the top or bottom of the DOUBLEWORD
3003 build_endian_shift(proc64
,datalen
,2,s_right
,32);
3005 if (proc64
&& (datalen
== 4)) {
3006 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
3007 printf(" memval >>= 32;\n");
3011 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen
- 1),(datalen
- 1));
3012 if (proc64
&& (datalen
== 4))
3013 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
3014 } else { /* store */
3015 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen
- 1));
3017 build_endian_shift(proc64
,datalen
,2,s_left
,32);
3019 /* TODO: This is duplicated in the LOAD code
3020 above - and the RIGHT LOAD and STORE code
3021 below. It should be merged if possible. */
3022 if (proc64
&& (datalen
== 4)) {
3023 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
3024 printf(" memval <<= 32;\n");
3028 printf(" StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);\n");
3030 } else { /* RIGHT */
3033 build_endian_shift(proc64
,datalen
,2,s_right
,32);
3035 if (proc64
&& (datalen
== 4)) {
3036 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
3037 printf(" memval >>= 32;\n");
3042 printf(" uword64 srcmask;\n");
3043 /* All of this extra code is just a bodge
3044 required because some hosts don't allow
3045 ((v) << 64). The SPARC just leaves the (v)
3046 value un-touched. */
3047 printf(" if (byte == 0)\n");
3048 printf(" srcmask = 0;\n");
3050 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen
);
3051 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n");
3053 if (proc64
&& (datalen
== 4))
3054 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
3055 } else { /* store */
3056 printf(" memval = ((uword64) op2 << (byte * 8));\n");
3057 build_endian_shift(proc64
,datalen
,2,s_left
,32);
3058 printf(" StoreMemory(uncached,(%s - byte),memval,memval1,paddr,vaddr,isREAL);\n",accesslength
);
3065 fprintf(stderr
,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
3068 } else { /* normal memory transfer */
3069 if (!(features
& FEATURE_IGEN
))
3071 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
3072 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
3074 /* TODO: The R4000 documentation states that a LWU
3075 instruction executed when in a 32bit processor mode
3076 should cause a ReservedInstruction exception. This
3077 will mean adding a run-time check into the code
3083 #if 1 /* see the comments attached to LOADDRMASK above */
3084 printf(" uword64 mask = 0x7;\n");
3086 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
3088 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
3089 printf(" unsigned int reverse UNUSED = (ReverseEndian ? (mask >> shift) : 0);\n");
3090 printf(" unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0);\n");
3091 printf(" unsigned int byte UNUSED;\n");
3093 /* TODO: This should really also check for 32bit world performing 32bit access */
3095 /* not for DOUBLEWORD */
3096 /* start-sanitize-r5900 */
3097 /* not for QUADWORD */
3098 /* end-sanitize-r5900 */
3099 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
3101 printf(" LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength
);
3103 /* The following will only make sense if the
3104 "LoadMemory" above returns a DOUBLEWORD entity */
3106 /* not for DOUBLEWORD */
3107 /* start-sanitize-r5900 */
3108 /* not for QUADWORD */
3109 /* end-sanitize-r5900 */
3121 valmask
= 0xFFFFFFFF;
3125 fprintf(stderr
,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen
,insn
->name
);
3128 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
3129 /* NOTE: The R4000 user manual has the COP_LW
3130 occuring in the same cycle as the rest of the
3131 instruction, yet the MIPS IV shows the operation
3132 happening on the next cycle. To keep the simulator
3133 simple, this code follows the R4000
3134 manual. Experimentation with a silicon
3135 implementation will be needed to ascertain the
3136 correct operation. */
3137 if (insn
->flags
& COPROC
)
3138 printf(" COP_LW(%s,destreg,(unsigned int)",
3139 ((insn
->flags
& REG
)
3141 : "((instruction >> 26) & 0x3)"));
3143 printf(" GPR[destreg] = (");
3145 if (insn
->flags
& SIGNEXTEND
)
3146 printf("SIGNEXTEND(");
3147 printf("((memval >> (8 * byte)) & 0x%08X)",valmask
);
3148 if (insn
->flags
& SIGNEXTEND
)
3149 printf(",%d)",(datalen
* 8));
3152 if (insn
->flags
& COPROC
)
3153 printf(" COP_LD(%s,destreg,memval);;\n",
3154 ((insn
->flags
& REG
)
3156 : "((instruction >> 26) & 0x3)"));
3159 printf(" GPR[destreg] = memval;\n");
3161 printf(" GPR1[destreg] = memval1;\n");
3164 } else { /* store operation */
3165 if ((datalen
== 1) || (datalen
== 2)) {
3167 #if 1 /* see the comments attached to LOADDRMASK above */
3168 printf(" uword64 mask = 0x7;\n");
3170 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
3172 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
3173 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
3174 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
3175 printf(" unsigned int byte;\n");
3177 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
3178 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
3179 printf(" memval = ((uword64) op2 << (8 * byte));\n");
3181 if (datalen
== 4) { /* SC and SW */
3182 #if 1 /* see the comments attached to LOADDRMASK above */
3183 printf(" uword64 mask = 0x7;\n");
3185 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
3187 printf(" unsigned int byte;\n");
3188 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
3189 printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
3190 if (insn
->flags
& COPROC
)
3191 printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n",
3192 ((insn
->flags
& REG
)
3194 : "((instruction >> 26) & 0x3)"),
3195 ((insn
->flags
& FP
) ? "fs" : "destreg"));
3197 printf(" memval = ((uword64) op2 << (8 * byte));\n");
3198 } else if (datalen
<= 8) { /* SD and SCD */
3199 if (! (features
& FEATURE_IGEN
))
3201 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
3202 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
3206 if (insn
->flags
& COPROC
)
3207 printf(" memval = (uword64)COP_SD(%s,%s);\n",
3208 ((insn
->flags
& REG
)
3210 : "((instruction >> 26) & 0x3)"),
3211 ((insn
->flags
& FP
) ? "fs" : "destreg"));
3213 printf(" memval = op2;\n");
3214 } else { /* wider than 8 */
3215 if (insn
->flags
& COPROC
) {
3216 fprintf(stderr
,"COPROC not available for 128 bit operations \"%s\"\n",insn
->name
);
3219 printf(" memval = rt_reg;\n");
3220 printf(" memval1 = rt_reg1;\n");
3223 if (insn
->flags
& ATOMIC
)
3224 printf(" if (LLBIT)\n");
3227 printf(" StoreMemory(uncached,%s,memval,memval1,paddr,vaddr,isREAL);\n",accesslength
);
3231 if (insn
->flags
& ATOMIC
) {
3232 if ((datalen
!= 4) && (datalen
!= 8)) {
3233 fprintf(stderr
,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",insn
->name
);
3237 printf(" LLBIT = 1;\n");
3239 /* The documentation states that:
3241 SC *WILL* fail if coherent store into the same
3242 block occurs, or if an exception occurs between
3243 the LL and SC instructions.
3245 SC *MAY* fail if a load, store or prefetch is
3246 executed on the processor (VR4300 doesn't seem
3247 to), or if the instructions between the LL and
3248 SC are not in a 2048byte contiguous VM range.
3250 SC *MUST* have been preceded by an LL
3251 (i.e. LLBIT will be set), and it must use the
3252 same Vaddr, Paddr and cache-coherence algorithm
3253 as the LL (which means we should store this
3254 information from the load-conditional).
3256 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT
,OP_MASK_RT
);
3267 /* This code could be merged with the PREFIX generation above: */
3268 printf(" uword64 vaddr = ((uword64)op1 + (uword64)op2);\n");
3269 printf(" uword64 paddr;\n");
3270 printf(" int uncached;\n");
3271 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
3272 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
3276 if (insn
->flags
& CONTROL
) {
3277 /* The following "magic" of interpreting the FP
3278 control-register number would not be needed if we were not
3279 trying to match our internal register numbers with those
3281 printf(" if (to) {\n");
3283 printf(" if (fs == 0) {\n");
3284 printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
3285 printf(" } else if (fs == 31) {\n");
3286 printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
3287 printf(" } /* else NOP */\n");
3288 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
3290 printf(" if (fs == 0) {\n");
3291 printf(" FCR0 = WORD64LO(GPR[ft]);\n");
3292 printf(" } else if (fs == 31) {\n");
3293 printf(" FCR31 = WORD64LO(GPR[ft]);\n");
3294 printf(" } /* else NOP */\n");
3295 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
3297 printf(" } else { /* control from */\n");
3299 printf(" if (fs == 0) {\n");
3300 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
3301 printf(" } else if (fs == 31) {\n");
3302 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
3303 printf(" } /* else NOP */\n");
3305 printf(" if (fs == 0) {\n");
3306 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
3307 printf(" } else if (fs == 31) {\n");
3308 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
3309 printf(" } /* else NOP */\n");
3313 printf(" if (to) {\n");
3314 if (GETDATASIZEINSN(insn
) == WORD
) {
3316 printf(" if (SizeFGR() == 64) {\n");
3317 printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
3318 printf(" } else { \n");
3319 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3322 printf(" if (SizeFGR() == 64)\n");
3323 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
3325 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3326 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3328 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
3330 printf(" if (SizeFGR() == 64) {\n");
3331 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
3332 printf(" } else\n");
3333 printf(" if ((fs & 0x1) == 0)\n");
3335 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
3336 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3338 if (features
& FEATURE_WARN_RESULT
) {
3340 printf(" UndefinedResult();\n");
3343 printf(" if (SizeFGR() == 64) {\n");
3344 printf(" FGR[fs] = GPR[ft];\n");
3345 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3346 printf(" } else\n");
3347 printf(" if ((fs & 0x1) == 0)\n");
3349 printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
3350 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3351 printf(" fpr_state[fs + 1] = fmt_uninterpreted;\n");
3352 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3354 if (features
& FEATURE_WARN_RESULT
) {
3356 printf(" UndefinedResult();\n");
3360 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
3363 printf(" } else {\n");
3364 if (GETDATASIZEINSN(insn
) == WORD
) {
3365 if (doisa
< 4) /* write-back occurs in next cycle */
3366 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
3367 else /* in this cycle */
3368 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
3369 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
3371 printf(" if (SizeFGR() == 64) {\n");
3372 printf(" PENDING_FILL(ft,FGR[fs]);\n");
3373 printf(" } else\n");
3374 printf(" if ((fs & 0x1) == 0) {\n");
3375 printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
3376 printf(" } else {\n");
3377 printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3378 if (features
& FEATURE_WARN_RESULT
)
3379 printf(" UndefinedResult();\n");
3382 printf(" if (SizeFGR() == 64)\n");
3383 printf(" GPR[ft] = FGR[fs];\n");
3385 printf(" if ((fs & 0x1) == 0)\n");
3386 printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
3387 printf(" else {\n");
3388 printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3389 if (features
& FEATURE_WARN_RESULT
)
3390 printf(" UndefinedResult();\n");
3394 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
3402 if (insn
->flags
& CONDITIONAL
) {
3403 if (insn
->flags
& INTEGER
) { /* moving GPR - testing FGR */
3404 printf(" if (GETFCC(condition_code) == boolean)\n");
3405 printf(" GPR[destreg] = op1;\n");
3407 if (insn
->flags
& EQ
) /* moving FGR - testing GPR */
3408 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
3410 printf(" if (GETFCC(condition_code) == boolean)\n");
3411 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3413 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
3415 } else { /* simple MOVE */
3416 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3421 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3422 printf(" SignalException(ReservedInstruction,instruction);\n");
3424 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
3428 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3429 printf(" SignalException(ReservedInstruction,instruction);\n");
3431 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
3435 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3436 printf(" SignalException(ReservedInstruction,instruction);\n");
3438 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3442 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3443 printf(" SignalException(ReservedInstruction,instruction);\n");
3445 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3449 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3450 printf(" SignalException(ReservedInstruction,instruction);\n");
3452 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
3456 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3457 printf(" SignalException(ReservedInstruction,instruction);\n");
3459 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((insn
->flags
& RECIP
) ? "Recip" : ""));
3470 switch (insn
->type
) {
3472 op
= "FP_RM_TOPINF";
3475 op
= "FP_RM_TOMINF";
3478 op
= "FP_RM_TOZERO";
3481 op
= "FP_RM_NEAREST";
3484 fprintf(stderr
,"Error: Handled missing for FP reason code %d\n",insn
->type
);
3488 switch (GETDATASIZEINSN(insn
)) {
3496 fprintf(stderr
,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op
);
3499 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3500 printf(" SignalException(ReservedInstruction,instruction);\n");
3502 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type
,op
,type
);
3509 switch (GETDATASIZEINSN(insn
)) {
3511 type
= "fmt_single";
3514 type
= "fmt_double";
3523 fprintf(stderr
,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn
));
3527 /* Not all combinations of conversion are valid at the
3528 moment: When converting to a fixed-point format, only
3529 floating-point sources are allowed. */
3530 printf(" if ((format == %s) | %s)\n",type
,((insn
->flags
& FIXED
) ? "((format == fmt_long) || (format == fmt_word))": "0"));
3531 printf(" SignalException(ReservedInstruction,instruction);\n");
3533 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type
,type
);
3538 if (insn
->flags
& MULTIPLY
) {
3540 switch (GETDATASIZEINSN(insn
)) {
3542 type
= "fmt_single";
3545 type
= "fmt_double";
3548 fprintf(stderr
,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn
));
3551 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
);
3553 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3554 printf(" SignalException(ReservedInstruction,instruction);\n");
3556 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3561 if (insn
->flags
& MULTIPLY
) {
3563 switch (GETDATASIZEINSN(insn
)) {
3565 type
= "fmt_single";
3568 type
= "fmt_double";
3571 fprintf(stderr
,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn
));
3574 if (insn
->flags
& NOT
)
3575 printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
3576 type
, type
, type
, type
, type
, type
, type
);
3578 printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
3579 type
, type
, type
, type
, type
, type
);
3581 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3582 printf(" SignalException(ReservedInstruction,instruction);\n");
3584 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3589 /* For the MIPS I,II or III there *MUST* be at least one
3590 instruction between the compare that sets a condition code
3591 and the branch that tests it. NOTE: However the hardware
3592 does not detect this condition. */
3593 /* Explicitly limit the operation to S and D formats: */
3594 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3595 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3596 printf(" else {\n");
3598 printf(" if (condition_code != 0)\n");
3599 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3603 printf(" int ignore = 0;\n");
3604 printf(" int less = 0;\n");
3605 printf(" int equal = 0;\n");
3606 printf(" int unordered = 1;\n");
3607 printf(" uword64 ofs = ValueFPR(fs,format);\n");
3608 printf(" uword64 oft = ValueFPR(ft,format);\n");
3609 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
3610 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
3611 printf(" FCSR |= FP_CAUSE(IO);\n");
3612 printf(" SignalException(FPE);\n");
3613 printf(" ignore = 1;\n");
3615 printf(" } else {\n");
3616 printf(" less = Less(ofs,oft,format);\n");
3617 printf(" equal = Equal(ofs,oft,format);\n");
3618 printf(" unordered = 0;\n");
3620 printf(" if (!ignore) {\n");
3621 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
3622 printf(" SETFCC(condition_code,condition);\n");
3630 char* pipeline
= (insn
->flags
& PIPE1
) ? "1" : "";
3631 int notsigned
= (insn
->flags
& UNSIGNED
);
3632 char* prodtype
= notsigned
? "uword64" : "word64";
3634 printf("%s prod = (%s)WORD64(WORD64LO(HI%s),WORD64LO(LO%s)) + ((%s)%s(op1%s) * (%s)%s(op2%s));\n",
3635 prodtype
, prodtype
, pipeline
, pipeline
,
3636 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32"),
3637 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32")
3639 printf("LO%s = SIGNEXTEND(prod,32);\n", pipeline
);
3640 printf("HI%s = SIGNEXTEND( WORD64HI(prod), 32);\n", pipeline
);
3641 printf("if( destreg != 0 ) GPR[destreg] = LO%s;\n", pipeline
);
3645 /* start-sanitize-r5900 */
3648 if (insn
->flags
& TO
)
3649 printf("SA = op1;\n");
3651 printf("GPR[destreg] = SA;\n");
3656 printf("SA = ((op1 & 0xF) ^ (op2 & 0xF)) * 8;\n");
3660 printf("SA = ((op1 & 0x7) ^ (op2 & 0x7)) * 16;\n");
3664 printf("int bytes = (SA / 8) %% 16;\n"); /* mod 16 to avoid garbage */
3665 printf("if (SA %% 8)\n");
3666 printf(" SignalException(ReservedInstruction,instruction);\n");
3669 printf(" int i;\n");
3670 printf(" for(i=0;i<(16-bytes);i++)\n");
3671 printf(" GPR_SB(destreg,i) = RT_SB(bytes+i);\n");
3672 printf(" for(;i<16;i++)\n");
3673 printf(" GPR_SB(destreg,i) = RS_SB(i-(16-bytes));\n");
3679 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3680 char* name
= name_for_data_len( insn
);
3681 char* letter
= letter_for_data_len( insn
);
3689 if ( insn
->flags
& UNSIGNED
)
3691 tmptype
= type_for_data_len( insn
, 0/*unsigned*/ );
3693 maximum
= umax_for_data_len( insn
);
3694 maxsat
= (insn
->flags
& SUBTRACT
) ? "0" : maximum
;
3697 else if ( insn
->flags
& SATURATE
)
3699 tmptype
= type_for_data_len( insn
, 1/*signed*/ );
3701 maximum
= max_for_data_len( insn
);
3703 minimum
= min_for_data_len( insn
);
3707 tmptype
= type_for_data_len( insn
, 1/*signed*/ );
3714 printf(" int i;\n");
3715 printf(" for (i=0; i < %sS_IN_MMI_REGS; i++)\n", name
);
3717 printf(" %s s = RS_%s%s(i);\n", tmptype
, signletter
, letter
);
3718 printf(" %s t = RT_%s%s(i);\n", tmptype
, signletter
, letter
);
3719 printf(" %s r = s %s t;\n", tmptype
, op
);
3722 printf(" if (r > %s)\n", maximum
);
3723 printf(" GPR_%s%s(destreg,i) = %s;\n", signletter
, letter
, maxsat
);
3726 printf(" else if (r < %s)\n", minimum
);
3727 printf(" GPR_%s%s(destreg,i) = %s;\n", signletter
, letter
, minimum
);
3732 printf(" GPR_%s%s(destreg,i) = r;\n", signletter
, letter
);
3740 if ( insn
->flags
& SUBTRACT
)
3742 else if ( insn
->flags
& ADDITION
)
3747 printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op
);
3748 printf(" LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op
);
3749 printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op
);
3750 printf(" HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op
);
3751 printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op
);
3752 printf(" LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op
);
3753 printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op
);
3754 printf(" HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op
);
3761 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3762 char* prodtype
= (insn
->flags
& UNSIGNED
) ? "unsigned64" : "signed64";
3763 char* constructor
= (insn
->flags
& UNSIGNED
) ? "UWORD64" : "WORD64";
3765 if ( insn
->flags
& SUBTRACT
)
3768 printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype
, constructor
);
3769 printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype
, constructor
);
3771 else if ( insn
->flags
& ADDITION
)
3774 printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype
, constructor
);
3775 printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype
, constructor
);
3780 printf(" %s sum0 = 0;\n", prodtype
);
3781 printf(" %s sum1 = 0;\n", prodtype
);
3784 printf(" %s prod0 = (%s)RS_%sW(0) * (%s)RT_%sW(0);\n", prodtype
, prodtype
, sign
, prodtype
, sign
);
3785 printf(" %s prod1 = (%s)RS_%sW(2) * (%s)RT_%sW(2);\n", prodtype
, prodtype
, sign
, prodtype
, sign
);
3787 printf(" sum0 %s= prod0;\n", op
);
3788 printf(" sum1 %s= prod1;\n", op
);
3790 printf(" GPR_%sD(destreg,0) = sum0;\n", sign
);
3791 printf(" GPR_%sD(destreg,1) = sum1;\n", sign
);
3793 printf(" LO = SIGNEXTEND( sum0, 32 );\n");
3794 printf(" HI = SIGNEXTEND( WORD64HI(sum0), 32 );\n");
3795 printf(" LO1 = SIGNEXTEND( sum1, 32 );\n");
3796 printf(" HI1 = SIGNEXTEND( WORD64HI(sum1), 32 );\n");
3802 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3804 for (i
= 0; i
< 2; i
++)
3806 char hi
= (i
== 0 ? ' ' : '1');
3808 if (! (insn
->flags
& UNSIGNED
))
3810 printf("if (RT_SW(%d) == -1)\n", d
);
3812 printf(" LO%c = -RS_%sW(%d);\n", hi
, sign
, d
);
3813 printf(" HI%c = 0;\n", hi
);
3814 printf(" }\nelse ");
3816 printf("if (RT_UW(%d) != 0)\n", d
);
3818 printf(" LO%c = (signed32)(RS_%sW(%d) / RT_%sW(%d));\n", hi
, sign
, d
, sign
, d
);
3819 printf(" HI%c = (signed32)(RS_%sW(%d) %% RT_%sW(%d));\n", hi
, sign
, d
, sign
, d
);
3826 printf("signed32 devisor = RT_SH(0);\n");
3827 printf("if (devisor == -1)\n");
3829 printf(" LO_SW(0) = -RS_SW(0);\n");
3830 printf(" HI_SW(0) = 0;\n");
3831 printf(" LO_SW(1) = -RS_SW(1);\n");
3832 printf(" HI_SW(1) = 0;\n");
3833 printf(" LO_SW(2) = -RS_SW(2);\n");
3834 printf(" HI_SW(2) = 0;\n");
3835 printf(" LO_SW(3) = -RS_SW(3);\n");
3836 printf(" HI_SW(3) = 0;\n");
3838 printf("else if (devisor != 0)\n");
3840 printf(" LO_SW(0) = RS_SW(0) / devisor;\n");
3841 printf(" HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n");
3842 printf(" LO_SW(1) = RS_SW(1) / devisor;\n");
3843 printf(" HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n");
3844 printf(" LO_SW(2) = RS_SW(2) / devisor;\n");
3845 printf(" HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n");
3846 printf(" LO_SW(3) = RS_SW(3) / devisor;\n");
3847 printf(" HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n");
3853 printf("for(i=0;i<HALFWORDS_IN_MMI_REGS/2;i++)\n");
3854 printf(" GPR_SH(destreg,i) = RS_SH(i) - RT_SH(i);\n");
3855 printf("for(;i<HALFWORDS_IN_MMI_REGS;i++)\n");
3856 printf(" GPR_SH(destreg,i) = RS_SH(i) + RT_SH(i);\n");
3861 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3862 printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op
);
3863 printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op
);
3864 printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op
);
3865 printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op
);
3871 char* name
= name_for_data_len( insn
);
3872 char* letter
= letter_for_data_len( insn
);
3873 char* bits
= bits_for_data_len( insn
);
3874 char* shift
= (insn
->flags
& RIGHT
) ? ">>" : "<<";
3875 char* sign
= (insn
->flags
& ARITHMETIC
) ? "S" : "U";
3877 printf("int shift_by = op1 & (%s-1);\n", bits
);
3879 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3880 printf(" GPR_%s%s(destreg,i) = ", sign
, letter
);
3881 if ( insn
->flags
& ARITHMETIC
)
3882 printf("SIGNEXTEND( ");
3883 printf("(RT_%s%s(i) %s shift_by)", sign
, letter
, shift
);
3884 if ( insn
->flags
& ARITHMETIC
)
3885 printf(", (%s-shift_by) )", bits
);
3891 printf("int s0 = (RS_UB(0) & 0x1F);\n");
3892 printf("int s1 = (RS_UB(8) & 0x1F);\n");
3893 printf("signed32 temp0 = RT_UW(0) << s0;\n");
3894 printf("signed32 temp1 = RT_UW(2) << s1;\n");
3895 printf("GPR_SD(destreg,0) = (signed64)temp0;\n");
3896 printf("GPR_SD(destreg,1) = (signed64)temp1;\n");
3900 printf("GPR_UD(destreg,0) = SIGNEXTEND ( RT_UW(0) >> (RS_UB(0) & 0x1F), 31);\n");
3901 printf("GPR_UD(destreg,1) = SIGNEXTEND ( RT_UW(2) >> (RS_UB(8) & 0x1F), 31);\n");
3905 printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n");
3906 printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n");
3914 if ( GET_OP_FROM_INSN(insn
) == POP_AND
)
3919 else if ( GET_OP_FROM_INSN(insn
) == POP_OR
)
3924 else if ( GET_OP_FROM_INSN(insn
) == POP_NOR
)
3929 else if ( GET_OP_FROM_INSN(insn
) == POP_XOR
)
3936 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3937 printf(" GPR_UW(destreg,i) = %s(RS_UW(i) %s RT_UW(i));\n", op2
, op1
);
3943 char* name
= name_for_data_len( insn
);
3944 char* letter
= letter_for_data_len( insn
);
3945 char* maximum
= umax_for_data_len( insn
);
3946 char* op
= (insn
->flags
& GT
) ? ">" : "==";
3949 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3951 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n",
3952 letter
, op
, letter
, letter
, maximum
);
3953 printf(" else GPR_S%s(destreg,i) = 0;\n", letter
);
3960 char* name
= name_for_data_len( insn
);
3961 char* letter
= letter_for_data_len( insn
);
3962 char* op
= (insn
->flags
& GT
) ? ">" : "<";
3965 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3967 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n",
3968 letter
, op
, letter
, letter
, letter
);
3969 printf(" else GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
3976 char* name
= name_for_data_len( insn
);
3977 char* letter
= letter_for_data_len( insn
);
3978 char* min
= min_for_data_len( insn
);
3979 char* max
= max_for_data_len( insn
);
3982 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3984 printf(" if (RT_S%s(i) >= 0)\n", letter
);
3985 printf(" GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
3986 printf(" else if (RT_S%s(i) == %s)\n", letter
, min
);
3987 printf(" GPR_S%s(destreg,i) = %s;\n", letter
, max
);
3989 printf(" GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter
, letter
);
3995 printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n");
3996 printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n");
4000 printf("GPR_UD(destreg,0) = RT_UD(0);\n");
4001 printf("GPR_UD(destreg,1) = RS_UD(0);\n");
4005 printf("GPR_UD(destreg,0) = RS_UD(1);\n");
4006 printf("GPR_UD(destreg,1) = RT_UD(1);\n");
4010 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4011 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
4012 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4013 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
4014 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
4015 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
4016 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
4017 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
4021 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4022 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
4023 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
4024 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
4028 printf("GPR_UH(destreg,0) = RT_UH(2);\n");
4029 printf("GPR_UH(destreg,1) = RT_UH(1);\n");
4030 printf("GPR_UH(destreg,2) = RT_UH(0);\n");
4031 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
4032 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
4033 printf("GPR_UH(destreg,5) = RT_UH(5);\n");
4034 printf("GPR_UH(destreg,6) = RT_UH(4);\n");
4035 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
4039 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
4040 printf("GPR_UW(destreg,1) = RT_UW(1);\n");
4041 printf("GPR_UW(destreg,2) = RT_UW(0);\n");
4042 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
4046 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
4047 printf("GPR_UB(destreg,1) = RS_UB(0);\n");
4048 printf("GPR_UB(destreg,2) = RT_UB(1);\n");
4049 printf("GPR_UB(destreg,3) = RS_UB(1);\n");
4050 printf("GPR_UB(destreg,4) = RT_UB(2);\n");
4051 printf("GPR_UB(destreg,5) = RS_UB(2);\n");
4052 printf("GPR_UB(destreg,6) = RT_UB(3);\n");
4053 printf("GPR_UB(destreg,7) = RS_UB(3);\n");
4054 printf("GPR_UB(destreg,8) = RT_UB(4);\n");
4055 printf("GPR_UB(destreg,9) = RS_UB(4);\n");
4056 printf("GPR_UB(destreg,10) = RT_UB(5);\n");
4057 printf("GPR_UB(destreg,11) = RS_UB(5);\n");
4058 printf("GPR_UB(destreg,12) = RT_UB(6);\n");
4059 printf("GPR_UB(destreg,13) = RS_UB(6);\n");
4060 printf("GPR_UB(destreg,14) = RT_UB(7);\n");
4061 printf("GPR_UB(destreg,15) = RS_UB(7);\n");
4065 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4066 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
4067 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4068 printf("GPR_UH(destreg,3) = RS_UH(1);\n");
4069 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
4070 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
4071 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
4072 printf("GPR_UH(destreg,7) = RS_UH(3);\n");
4076 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4077 printf("GPR_UW(destreg,1) = RS_UW(0);\n");
4078 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
4079 printf("GPR_UW(destreg,3) = RS_UW(1);\n");
4083 printf("GPR_UB(destreg,0) = RT_UB(8);\n");
4084 printf("GPR_UB(destreg,1) = RS_UB(8);\n");
4085 printf("GPR_UB(destreg,2) = RT_UB(9);\n");
4086 printf("GPR_UB(destreg,3) = RS_UB(9);\n");
4087 printf("GPR_UB(destreg,4) = RT_UB(10);\n");
4088 printf("GPR_UB(destreg,5) = RS_UB(10);\n");
4089 printf("GPR_UB(destreg,6) = RT_UB(11);\n");
4090 printf("GPR_UB(destreg,7) = RS_UB(11);\n");
4091 printf("GPR_UB(destreg,8) = RT_UB(12);\n");
4092 printf("GPR_UB(destreg,9) = RS_UB(12);\n");
4093 printf("GPR_UB(destreg,10) = RT_UB(13);\n");
4094 printf("GPR_UB(destreg,11) = RS_UB(13);\n");
4095 printf("GPR_UB(destreg,12) = RT_UB(14);\n");
4096 printf("GPR_UB(destreg,13) = RS_UB(14);\n");
4097 printf("GPR_UB(destreg,14) = RT_UB(15);\n");
4098 printf("GPR_UB(destreg,15) = RS_UB(15);\n");
4102 printf("GPR_UH(destreg,0) = RT_UH(4);\n");
4103 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
4104 printf("GPR_UH(destreg,2) = RT_UH(5);\n");
4105 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
4106 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
4107 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
4108 printf("GPR_UH(destreg,6) = RT_UH(7);\n");
4109 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
4113 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
4114 printf("GPR_UW(destreg,1) = RS_UW(2);\n");
4115 printf("GPR_UW(destreg,2) = RT_UW(3);\n");
4116 printf("GPR_UW(destreg,3) = RS_UW(3);\n");
4120 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
4121 printf("GPR_UB(destreg,1) = RT_UB(2);\n");
4122 printf("GPR_UB(destreg,2) = RT_UB(4);\n");
4123 printf("GPR_UB(destreg,3) = RT_UB(6);\n");
4124 printf("GPR_UB(destreg,4) = RT_UB(8);\n");
4125 printf("GPR_UB(destreg,5) = RT_UB(10);\n");
4126 printf("GPR_UB(destreg,6) = RT_UB(12);\n");
4127 printf("GPR_UB(destreg,7) = RT_UB(14);\n");
4128 printf("GPR_UB(destreg,8) = RS_UB(0);\n");
4129 printf("GPR_UB(destreg,9) = RS_UB(2);\n");
4130 printf("GPR_UB(destreg,10) = RS_UB(4);\n");
4131 printf("GPR_UB(destreg,11) = RS_UB(6);\n");
4132 printf("GPR_UB(destreg,12) = RS_UB(8);\n");
4133 printf("GPR_UB(destreg,13) = RS_UB(10);\n");
4134 printf("GPR_UB(destreg,14) = RS_UB(12);\n");
4135 printf("GPR_UB(destreg,15) = RS_UB(14);\n");
4139 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4140 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
4141 printf("GPR_UH(destreg,2) = RT_UH(4);\n");
4142 printf("GPR_UH(destreg,3) = RT_UH(6);\n");
4143 printf("GPR_UH(destreg,4) = RS_UH(0);\n");
4144 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
4145 printf("GPR_UH(destreg,6) = RS_UH(4);\n");
4146 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
4150 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4151 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
4152 printf("GPR_UW(destreg,2) = RS_UW(0);\n");
4153 printf("GPR_UW(destreg,3) = RS_UW(2);\n");
4157 printf("GPR_UH(destreg,0) = RT_UH(3);\n");
4158 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
4159 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4160 printf("GPR_UH(destreg,3) = RT_UH(0);\n");
4161 printf("GPR_UH(destreg,4) = RT_UH(7);\n");
4162 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
4163 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
4164 printf("GPR_UH(destreg,7) = RT_UH(4);\n");
4168 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4169 printf("GPR_UW(destreg,1) = RT_UW(3);\n");
4170 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
4171 printf("GPR_UW(destreg,3) = RT_UW(2);\n");
4175 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4176 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
4177 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4178 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
4179 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
4180 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
4181 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
4182 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
4186 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4187 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
4188 printf("GPR_UH(destreg,2) = RT_UH(2);\n");
4189 printf("GPR_UH(destreg,3) = RS_UH(2);\n");
4190 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
4191 printf("GPR_UH(destreg,5) = RS_UH(4);\n");
4192 printf("GPR_UH(destreg,6) = RT_UH(6);\n");
4193 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
4196 case PMXX
: /* Parallel move HI or LO / TO or FROM */
4198 if ( (insn
->flags
& (HI
|FROM
)) == (HI
|FROM
) )
4200 printf("GPR_SD(destreg,0) = HI;\n");
4201 printf("GPR_SD(destreg,1) = HI1;\n");
4203 else if ( (insn
->flags
& (LO
|FROM
)) == (LO
|FROM
) )
4205 printf("GPR_SD(destreg,0) = LO;\n");
4206 printf("GPR_SD(destreg,1) = LO1;\n");
4208 else if ( (insn
->flags
& (HI
|TO
)) == (HI
|TO
) )
4210 printf("HI = RS_SD(0);\n");
4211 printf("HI1 = RS_SD(1);\n");
4213 else if ( (insn
->flags
& (LO
|TO
)) == (LO
|TO
) )
4215 printf("LO = RS_SD(0);\n");
4216 printf("LO1 = RS_SD(1);\n");
4222 printf("LO_UW(0) = RS_UW(0);\n");
4223 printf("HI_UW(0) = RS_UW(1);\n");
4224 printf("LO_UW(2) = RS_UW(2);\n");
4225 printf("HI_UW(2) = RS_UW(3);\n");
4229 printf("if (op1 == 0)\n");
4231 printf(" GPR_UW(destreg,0) = LO_UW(0);\n");
4232 printf(" GPR_UW(destreg,1) = HI_UW(0);\n");
4233 printf(" GPR_UW(destreg,2) = LO_UW(2);\n");
4234 printf(" GPR_UW(destreg,3) = HI_UW(2);\n");
4236 printf("else if (op1 == 1)\n");
4238 printf(" GPR_UW(destreg,0) = LO_UW(1);\n");
4239 printf(" GPR_UW(destreg,1) = HI_UW(1);\n");
4240 printf(" GPR_UW(destreg,2) = LO_UW(3);\n");
4241 printf(" GPR_UW(destreg,3) = HI_UW(3);\n");
4243 printf("else if (op1 == 2)\n");
4245 printf(" /* NOTE: This code implements a saturate according to the\n");
4246 printf(" figure on page B-115 and not according to the\n");
4247 printf(" definition on page B-113 */\n");
4248 printf(" signed64 t = ((unsigned64)HI_UW(0) << 32) | (unsigned64)LO_UW(0);\n");
4249 printf(" signed64 u = ((unsigned64)HI_UW(2) << 32) | (unsigned64)LO_UW(2);\n");
4250 printf(" if ( t > SIGNED64 (0x000000007FFFFFFF) )\n");
4251 printf(" GPR_SD(destreg,0) = SIGNED64 (0x000000007FFFFFFF);\n");
4252 printf(" else if ( t < - SIGNED64 (0x0000000080000000) )\n");
4253 printf(" GPR_SD(destreg,0) = - SIGNED64 (0x0000000080000000);\n");
4255 printf(" GPR_SD(destreg,0) = t;\n");
4256 printf(" if ( u > SIGNED64 (0x000000007FFFFFFF) )\n");
4257 printf(" GPR_SD(destreg,1) = SIGNED64 (0x000000007FFFFFFF);\n");
4258 printf(" else if ( u < - SIGNED64 (0x0000000080000000) )\n");
4259 printf(" GPR_SD(destreg,1) = - SIGNED64 (0x0000000080000000);\n");
4261 printf(" GPR_SD(destreg,1) = u;\n");
4263 printf("else if (op1 == 3)\n");
4265 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
4266 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
4267 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
4268 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
4269 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
4270 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
4271 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
4272 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
4274 printf("else if (op1 == 4)\n");
4276 printf(" if (LO_SW(0) > 0x7FFF)\n");
4277 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
4278 printf(" else if (LO_SW(0) < -0x8000)\n");
4279 printf(" GPR_UH(destreg,0) = 0x8000;\n");
4281 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
4283 printf(" if (LO_SW(1) > 0x7FFF)\n");
4284 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
4285 printf(" else if (LO_SW(1) < -0x8000)\n");
4286 printf(" GPR_UH(destreg,1) = 0x8000;\n");
4288 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
4290 printf(" if (HI_SW(0) > 0x7FFF)\n");
4291 printf(" GPR_UH(destreg,2) = 0x7FFF;\n");
4292 printf(" else if (HI_SW(0) < -0x8000)\n");
4293 printf(" GPR_UH(destreg,2) = 0x8000;\n");
4295 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
4297 printf(" if (HI_SW(1) > 0x7FFF)\n");
4298 printf(" GPR_UH(destreg,3) = 0x7FFF;\n");
4299 printf(" else if (HI_SW(1) < -0x8000)\n");
4300 printf(" GPR_UH(destreg,3) = 0x8000;\n");
4302 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
4304 printf(" if (LO_SW(2) > 0x7FFF)\n");
4305 printf(" GPR_UH(destreg,4) = 0x7FFF;\n");
4306 printf(" else if (LO_SW(2) < -0x8000)\n");
4307 printf(" GPR_UH(destreg,4) = 0x8000;\n");
4309 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
4311 printf(" if (LO_SW(3) > 0x7FFF)\n");
4312 printf(" GPR_UH(destreg,5) = 0x7FFF;\n");
4313 printf(" else if (LO_SW(3) < -0x8000)\n");
4314 printf(" GPR_UH(destreg,5) = 0x8000;\n");
4316 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
4318 printf(" if (HI_SW(2) > 0x7FFF)\n");
4319 printf(" GPR_UH(destreg,6) = 0x7FFF;\n");
4320 printf(" else if (HI_SW(2) < -0x8000)\n");
4321 printf(" GPR_UH(destreg,6) = 0x8000;\n");
4323 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
4325 printf(" if (HI_SW(3) > 0x7FFF)\n");
4326 printf(" GPR_UH(destreg,7) = 0x7FFF;\n");
4327 printf(" else if (HI_SW(3) < -0x8000)\n");
4328 printf(" GPR_UH(destreg,7) = 0x8000;\n");
4330 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
4336 printf("unsigned long value;\n");
4337 printf("int test;\n");
4338 printf("int count;\n");
4341 printf("value = RS_UW(0);\n");
4342 printf("count = 0;\n");
4343 printf("test = !!(value & (1 << 31));\n");
4344 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
4345 printf(" count++;\n");
4346 printf("GPR_UW(destreg,0) = count;\n");
4348 printf("value = RS_UW(1);\n");
4349 printf("count = 0;\n");
4350 printf("test = !!(value & (1 << 31));\n");
4351 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
4352 printf(" count++;\n");
4353 printf("GPR_UW(destreg,1) = count;\n");
4358 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
4360 printf(" unsigned32 x = RT_UW(i);\n");
4361 printf(" GPR_UW(destreg,i) = ((x & (1 << 15)) << (31 - 15)) \n");
4362 printf(" | ((x & (31 << 10)) << (19 - 10)) \n");
4363 printf(" | ((x & (31 << 5)) << (11 - 5)) \n");
4364 printf(" | ((x & (31 << 0)) << (3 - 0)); \n");
4370 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
4372 printf(" unsigned32 x = RT_UW(i);\n");
4373 printf(" GPR_UW(destreg,i) = ((x & (1 << 31)) >> (31 - 15)) \n");
4374 printf(" | ((x & (31 << 19)) >> (19 - 10)) \n");
4375 printf(" | ((x & (31 << 11)) >> (11 - 5)) \n");
4376 printf(" | ((x & (31 << 3)) >> (3 - 0)); \n");
4379 /* end-sanitize-r5900 */
4382 fprintf(stderr
,"Warning: Unimplemented opcode: %s\n",insn
->name
) ;
4384 printf("SignalException(ReservedInstruction,instruction);\n");
4388 fprintf(stderr
,"Unrecognised opcode type %d\n",insn
->type
) ;
4393 /*---------------------------------------------------------------------------*/
4395 /* The command-line feature controls are presented in a similar style
4396 to those offered by GCC, in the aim of providing a consistent
4397 interface to the user. */
4399 T_NONE
, /* no argument - mask and value fields control "feature" definition */
4400 T_NUM
, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
4401 T_STRING
/* string argument - optionally prcededed by '=' */
4410 } machine_options
[] = {
4411 {"ips", T_NUM
, MASK_ISA
,0,"\tSelect MIPS ISA version"},
4412 {"cpu", T_STRING
,0,0,"\t\tSelect particular MIPS architecture"},
4413 {"gp64", T_NONE
, FEATURE_GP64
,FEATURE_GP64
,"\t\t\tSelect 64bit GP registers"},
4414 {"gp32", T_NONE
, FEATURE_GP64
,0,"\t\t\tSelect 32bit GP registers"},
4415 {"no-fp", T_NONE
, FEATURE_HASFPU
,0,"\t\tDisable FP simulation"},
4416 {"single-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),(FEATURE_FPSINGLE
| FEATURE_HASFPU
),"\t\tSelect single precision only FPU"},
4417 {"double-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),FEATURE_HASFPU
,"\t\tSelect double precision FPU"},
4421 /* The following architecture identies are those accepted by the "-mcpu" option: */
4422 struct architectures
{
4423 const char *name
; /* ASCII string identifier for command-line, no white-space allowed */
4424 unsigned int idflag
; /* or-ed into "isa" value */
4427 static const struct architectures available_architectures
[] = {
4428 {"4100",ARCH_VR4100
}, /* NEC MIPS VR4100 */
4429 {"3900",ARCH_R3900
}, /* Toshiba R3900 (TX39) */
4430 /* start-sanitize-tx19 */
4431 {"1900",ARCH_R3900
}, /* Toshiba R1900 (TX19) */
4432 /* end-sanitize-tx19 */
4433 /* start-sanitize-r5900 */
4434 {"5900",ARCH_R5900
},
4435 /* end-sanitize-r5900 */
4436 {0, 0} /* terminator */
4439 /*---------------------------------------------------------------------------*/
4447 fprintf(stderr
,"%s: Construct a MIPS simulator engine.\n",name
);
4450 The output of this program is a block of 'C' code designed to be\n\
4451 included into the main simulation control loop of a device specific\n\
4454 fprintf(stderr
,"\nOptions:\n");
4455 fprintf(stderr
," -h --help\t\tProvide this help text\n");
4456 fprintf(stderr
," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
4457 fprintf(stderr
," -w --warnings\t\tEnable all the simulator engine warnings\n");
4459 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++) {
4460 fprintf(stderr
," -m%s",machine_options
[loop
].name
);
4461 switch (machine_options
[loop
].type
) {
4463 fprintf(stderr
,"N (range 0..%d)",machine_options
[loop
].mask
);
4468 fprintf(stderr
,"=name");
4472 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",name
,machine_options
[loop
].type
);
4475 fprintf(stderr
,"%s\n",machine_options
[loop
].desc
);
4478 fprintf(stderr
,"\nAvailable \"-mcpu\" architectures: ");
4479 for (loop
= 0; (available_architectures
[loop
].name
!= 0); loop
++)
4480 fprintf(stderr
,"%s ",available_architectures
[loop
].name
);
4481 fprintf(stderr
,"\n\n");
4484 The \"trace\" and \"warnings\" options do not define the output stream.\n\
4485 They only inform the code that includes the constructed engine to provide\n\
4486 the required features.\n\n\
4487 The \"-mips0\" option forces the construction of a simulator supporting\n\
4488 the highest available MIPS ISA supported.\n");
4493 /*---------------------------------------------------------------------------*/
4501 char *progname
= argv
[0];
4502 unsigned int doarch
= DEF_ISA
;
4503 unsigned int features
= 0; /* default state */
4506 features
|= FEATURE_HASFPU
;
4508 features
|= FEATURE_PROC32
;
4510 features
|= FEATURE_FPSINGLE
;
4512 if (features
& FEATURE_PROC32
)
4513 features
&= ~FEATURE_GP64
;
4515 features
|= FEATURE_GP64
;
4518 int option_index
= 0;
4519 static struct option cmdline
[] = {
4522 {"warnings",0,0,'w'},
4527 c
= getopt_long(argc
,argv
,"hm:tw",cmdline
,&option_index
);
4529 break ; /* out of the while loop */
4532 case 'h' : /* help */
4536 case 'f' : /* fast */
4537 features
|= FEATURE_FAST
;
4540 case 'i' : /* igen formatted output */
4541 features
|= FEATURE_IGEN
;
4544 case 'w' : /* warnings */
4545 features
|= FEATURE_WARNINGS
;
4546 /* TODO: Future extension: Allow better control over the warnings generated:
4547 disable warnings -wnone ~FEATURE_WARNINGS
4548 all possible warnings -wall FEATURE_WARNINGS
4549 pipeline stall occuring -wstall FEATURE_WARN_STALL
4550 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
4551 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
4552 bad r31 use -wr31 FEATURE_WARN_R31
4553 undefined results -wresult FEATURE_WARN_RESULT
4557 case 'm' : /* machine options */
4561 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++)
4562 if (strncmp(machine_options
[loop
].name
,optarg
,strlen(machine_options
[loop
].name
)) == 0) {
4563 char *loptarg
= (optarg
+ strlen(machine_options
[loop
].name
));
4564 switch (machine_options
[loop
].type
) {
4567 fprintf(stderr
,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname
,loptarg
,machine_options
[loop
].name
);
4570 features
&= ~(machine_options
[loop
].mask
);
4571 features
|= machine_options
[loop
].value
;
4575 if (*loptarg
&& *loptarg
== '=')
4578 if (strcmp(machine_options
[loop
].name
,"ips") == 0) {
4582 fprintf(stderr
,"%s: ISA number expected after -mips\n",progname
);
4586 num
= my_strtoul(loptarg
,&loptarg
,10);
4588 if ((num
== ULONG_MAX
) && (errno
= ERANGE
)) {
4589 fprintf(stderr
,"%s: Invalid number given to -mips option\n",progname
);
4594 fprintf(stderr
,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname
,loptarg
);
4598 if (num
> MASK_ISA
) {
4599 fprintf(stderr
,"%s: ISA number %d outside acceptable range (0..%d)\n",progname
,num
,MASK_ISA
);
4603 doarch
= ((doarch
& ~MASK_ISA
) | num
);
4604 if ((num
== 0) || (num
> 2)) {
4605 if ((features
& FEATURE_PROC32
) || !(features
& FEATURE_GP64
))
4606 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp64\n",progname
,num
);
4607 features
|= FEATURE_GP64
;
4608 features
&= ~FEATURE_PROC32
;
4610 if (!(features
& FEATURE_PROC32
) || (features
& FEATURE_GP64
))
4611 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp32\n",progname
,num
);
4612 features
&= ~FEATURE_GP64
;
4613 features
|= FEATURE_PROC32
;
4616 fprintf(stderr
,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname
,optarg
);
4622 if (*loptarg
&& *loptarg
== '=')
4625 if (strcmp(machine_options
[loop
].name
,"cpu") == 0) {
4629 fprintf(stderr
,"%s: Architecture identifier expected after -mcpu\n",progname
);
4633 for (archloop
= 0; (available_architectures
[archloop
].name
!= 0); archloop
++) {
4634 if ((*loptarg
== 'v') || (*loptarg
== 'V'))
4637 if ((*loptarg
== 'r') || (*loptarg
== 'R'))
4640 if (strcmp(available_architectures
[archloop
].name
,loptarg
) == 0) {
4641 doarch
|= available_architectures
[archloop
].idflag
;
4646 if (available_architectures
[archloop
].name
== 0) {
4647 fprintf(stderr
,"%s: Unrecognised MIPS architecture \"%s\"\n",progname
,loptarg
);
4651 fprintf(stderr
,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname
,optarg
);
4657 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",progname
,machine_options
[loop
].type
);
4663 if (machine_options
[loop
].name
== 0) {
4664 fprintf(stderr
,"%s: Unrecognised option: -m%s\n",progname
,optarg
);
4671 /* An error message should already have been displayed */
4675 fprintf(stderr
,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname
,c
);
4680 if (optind
< argc
) {
4681 fprintf(stderr
,"%s: Spurios non-option arguments ",progname
);
4682 while (optind
< argc
)
4683 fprintf(stderr
,"\"%s\" ",argv
[optind
++]);
4684 fprintf(stderr
,"\n");
4688 if ((features
& FEATURE_FAST
) && (features
& FEATURE_WARNINGS
))
4689 fprintf(stderr
,"Warning: Fast model generation selected, along with trace or warnings.\n");
4691 process_instructions(doarch
,features
) ;
4695 /*---------------------------------------------------------------------------*/
4697 /* We can't assume that the compiler for the build system has strtoul,
4698 so we provide our own copy. */
4701 * Copyright (c) 1990 Regents of the University of California.
4702 * All rights reserved.
4704 * Redistribution and use in source and binary forms, with or without
4705 * modification, are permitted provided that the following conditions
4707 * 1. Redistributions of source code must retain the above copyright
4708 * notice, this list of conditions and the following disclaimer.
4709 * 2. Redistributions in binary form must reproduce the above copyright
4710 * notice, this list of conditions and the following disclaimer in the
4711 * documentation and/or other materials provided with the distribution.
4712 * 3. All advertising materials mentioning features or use of this software
4713 * must display the following acknowledgement:
4714 * This product includes software developed by the University of
4715 * California, Berkeley and its contributors.
4716 * 4. Neither the name of the University nor the names of its contributors
4717 * may be used to endorse or promote products derived from this software
4718 * without specific prior written permission.
4720 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4721 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4722 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4723 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4724 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4725 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4726 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4727 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4728 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4729 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4734 * Convert a string to an unsigned long integer.
4736 * Ignores `locale' stuff. Assumes that the upper and lower case
4737 * alphabets and digits are each contiguous.
4739 static unsigned long
4740 my_strtoul(nptr
, endptr
, base
)
4745 register const char *s
= nptr
;
4746 register unsigned long acc
;
4748 register unsigned long cutoff
;
4749 register int neg
= 0, any
, cutlim
;
4752 * See strtol for comments as to the logic used.
4756 } while (isspace(c
));
4760 } else if (c
== '+')
4762 if ((base
== 0 || base
== 16) &&
4763 c
== '0' && (*s
== 'x' || *s
== 'X')) {
4769 base
= c
== '0' ? 8 : 10;
4770 cutoff
= (unsigned long)ULONG_MAX
/ (unsigned long)base
;
4771 cutlim
= (unsigned long)ULONG_MAX
% (unsigned long)base
;
4772 for (acc
= 0, any
= 0;; c
= *s
++) {
4775 else if (isalpha(c
))
4776 c
-= isupper(c
) ? 'A' - 10 : 'a' - 10;
4781 if (any
< 0 || acc
> cutoff
|| (acc
== cutoff
&& c
> cutlim
))
4795 *endptr
= (char *) (any
? s
- 1 : nptr
);
4799 /*---------------------------------------------------------------------------*/
4801 /*> EOF gencode.c <*/