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_io_eprintf(sd,\"Instruction has lo-order offset bits set in instruction\\n\");\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(" SignalExceptionIntegerOverflow ();\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(" SignalExceptionIntegerOverflow ();\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_io_eprintf(sd,\"MT (move-to) over-writing %s register value\\n\");\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(" DecodeCoproc(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_io_eprintf(sd,\"MADD16 operation with non-16bit operands\\n\");\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(" SignalExceptionCoProcessorUnusable ();\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_io_eprintf(sd,\"Branch with link using r31 as source operand\\n\");\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)%s));\n",
3460 ((insn
->flags
& RECIP
) ? "Recip" : ""),
3461 ((insn
->flags
& RECIP
) ? ",format" : ""));
3472 switch (insn
->type
) {
3474 op
= "FP_RM_TOPINF";
3477 op
= "FP_RM_TOMINF";
3480 op
= "FP_RM_TOZERO";
3483 op
= "FP_RM_NEAREST";
3486 fprintf(stderr
,"Error: Handled missing for FP reason code %d\n",insn
->type
);
3490 switch (GETDATASIZEINSN(insn
)) {
3498 fprintf(stderr
,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op
);
3501 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3502 printf(" SignalException(ReservedInstruction,instruction);\n");
3504 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type
,op
,type
);
3511 switch (GETDATASIZEINSN(insn
)) {
3513 type
= "fmt_single";
3516 type
= "fmt_double";
3525 fprintf(stderr
,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn
));
3529 /* Not all combinations of conversion are valid at the
3530 moment: When converting to a fixed-point format, only
3531 floating-point sources are allowed. */
3532 printf(" if ((format == %s) | %s)\n",type
,((insn
->flags
& FIXED
) ? "((format == fmt_long) || (format == fmt_word))": "0"));
3533 printf(" SignalException(ReservedInstruction,instruction);\n");
3535 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type
,type
);
3540 if (insn
->flags
& MULTIPLY
) {
3542 switch (GETDATASIZEINSN(insn
)) {
3544 type
= "fmt_single";
3547 type
= "fmt_double";
3550 fprintf(stderr
,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn
));
3553 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
);
3555 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3556 printf(" SignalException(ReservedInstruction,instruction);\n");
3558 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3563 if (insn
->flags
& MULTIPLY
) {
3565 switch (GETDATASIZEINSN(insn
)) {
3567 type
= "fmt_single";
3570 type
= "fmt_double";
3573 fprintf(stderr
,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn
));
3576 if (insn
->flags
& NOT
)
3577 printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
3578 type
, type
, type
, type
, type
, type
, type
);
3580 printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
3581 type
, type
, type
, type
, type
, type
);
3583 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3584 printf(" SignalException(ReservedInstruction,instruction);\n");
3586 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3591 /* For the MIPS I,II or III there *MUST* be at least one
3592 instruction between the compare that sets a condition code
3593 and the branch that tests it. NOTE: However the hardware
3594 does not detect this condition. */
3595 /* Explicitly limit the operation to S and D formats: */
3596 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3597 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3598 printf(" else {\n");
3600 printf(" if (condition_code != 0)\n");
3601 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3605 printf(" int ignore = 0;\n");
3606 printf(" int less = 0;\n");
3607 printf(" int equal = 0;\n");
3608 printf(" int unordered = 1;\n");
3609 printf(" uword64 ofs = ValueFPR(fs,format);\n");
3610 printf(" uword64 oft = ValueFPR(ft,format);\n");
3611 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
3612 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
3613 printf(" FCSR |= FP_CAUSE(IO);\n");
3614 printf(" SignalExceptionFPE ();\n");
3615 printf(" ignore = 1;\n");
3617 printf(" } else {\n");
3618 printf(" less = Less(ofs,oft,format);\n");
3619 printf(" equal = Equal(ofs,oft,format);\n");
3620 printf(" unordered = 0;\n");
3622 printf(" if (!ignore) {\n");
3623 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
3624 printf(" SETFCC(condition_code,condition);\n");
3632 char* pipeline
= (insn
->flags
& PIPE1
) ? "1" : "";
3633 int notsigned
= (insn
->flags
& UNSIGNED
);
3634 char* prodtype
= notsigned
? "uword64" : "word64";
3636 printf("%s prod = (%s)WORD64(WORD64LO(HI%s),WORD64LO(LO%s)) + ((%s)%s(op1%s) * (%s)%s(op2%s));\n",
3637 prodtype
, prodtype
, pipeline
, pipeline
,
3638 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32"),
3639 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32")
3641 printf("LO%s = SIGNEXTEND(prod,32);\n", pipeline
);
3642 printf("HI%s = SIGNEXTEND( WORD64HI(prod), 32);\n", pipeline
);
3643 printf("if( destreg != 0 ) GPR[destreg] = LO%s;\n", pipeline
);
3647 /* start-sanitize-r5900 */
3650 if (insn
->flags
& TO
)
3651 printf("SA = op1;\n");
3653 printf("GPR[destreg] = SA;\n");
3658 printf("SA = ((op1 & 0xF) ^ (op2 & 0xF)) * 8;\n");
3662 printf("SA = ((op1 & 0x7) ^ (op2 & 0x7)) * 16;\n");
3666 printf("int bytes = (SA / 8) %% 16;\n"); /* mod 16 to avoid garbage */
3667 printf("if (SA %% 8)\n");
3668 printf(" SignalException(ReservedInstruction,instruction);\n");
3671 printf(" int i;\n");
3672 printf(" for(i=0;i<(16-bytes);i++)\n");
3673 printf(" GPR_SB(destreg,i) = RT_SB(bytes+i);\n");
3674 printf(" for(;i<16;i++)\n");
3675 printf(" GPR_SB(destreg,i) = RS_SB(i-(16-bytes));\n");
3681 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3682 char* name
= name_for_data_len( insn
);
3683 char* letter
= letter_for_data_len( insn
);
3691 if ( insn
->flags
& UNSIGNED
)
3693 tmptype
= type_for_data_len( insn
, 0/*unsigned*/ );
3695 maximum
= umax_for_data_len( insn
);
3696 maxsat
= (insn
->flags
& SUBTRACT
) ? "0" : maximum
;
3699 else if ( insn
->flags
& SATURATE
)
3701 tmptype
= type_for_data_len( insn
, 1/*signed*/ );
3703 maximum
= max_for_data_len( insn
);
3705 minimum
= min_for_data_len( insn
);
3709 tmptype
= type_for_data_len( insn
, 1/*signed*/ );
3716 printf(" int i;\n");
3717 printf(" for (i=0; i < %sS_IN_MMI_REGS; i++)\n", name
);
3719 printf(" %s s = RS_%s%s(i);\n", tmptype
, signletter
, letter
);
3720 printf(" %s t = RT_%s%s(i);\n", tmptype
, signletter
, letter
);
3721 printf(" %s r = s %s t;\n", tmptype
, op
);
3724 printf(" if (r > %s)\n", maximum
);
3725 printf(" GPR_%s%s(destreg,i) = %s;\n", signletter
, letter
, maxsat
);
3728 printf(" else if (r < %s)\n", minimum
);
3729 printf(" GPR_%s%s(destreg,i) = %s;\n", signletter
, letter
, minimum
);
3734 printf(" GPR_%s%s(destreg,i) = r;\n", signletter
, letter
);
3742 if ( insn
->flags
& SUBTRACT
)
3744 else if ( insn
->flags
& ADDITION
)
3749 printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op
);
3750 printf(" LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op
);
3751 printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op
);
3752 printf(" HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op
);
3753 printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op
);
3754 printf(" LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op
);
3755 printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op
);
3756 printf(" HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op
);
3763 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3764 char* prodtype
= (insn
->flags
& UNSIGNED
) ? "unsigned64" : "signed64";
3765 char* constructor
= (insn
->flags
& UNSIGNED
) ? "UWORD64" : "WORD64";
3767 if ( insn
->flags
& SUBTRACT
)
3770 printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype
, constructor
);
3771 printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype
, constructor
);
3773 else if ( insn
->flags
& ADDITION
)
3776 printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype
, constructor
);
3777 printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype
, constructor
);
3782 printf(" %s sum0 = 0;\n", prodtype
);
3783 printf(" %s sum1 = 0;\n", prodtype
);
3786 printf(" %s prod0 = (%s)RS_%sW(0) * (%s)RT_%sW(0);\n", prodtype
, prodtype
, sign
, prodtype
, sign
);
3787 printf(" %s prod1 = (%s)RS_%sW(2) * (%s)RT_%sW(2);\n", prodtype
, prodtype
, sign
, prodtype
, sign
);
3789 printf(" sum0 %s= prod0;\n", op
);
3790 printf(" sum1 %s= prod1;\n", op
);
3792 printf(" GPR_%sD(destreg,0) = sum0;\n", sign
);
3793 printf(" GPR_%sD(destreg,1) = sum1;\n", sign
);
3795 printf(" LO = SIGNEXTEND( sum0, 32 );\n");
3796 printf(" HI = SIGNEXTEND( WORD64HI(sum0), 32 );\n");
3797 printf(" LO1 = SIGNEXTEND( sum1, 32 );\n");
3798 printf(" HI1 = SIGNEXTEND( WORD64HI(sum1), 32 );\n");
3804 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3806 for (i
= 0; i
< 2; i
++)
3808 char hi
= (i
== 0 ? ' ' : '1');
3810 if (! (insn
->flags
& UNSIGNED
))
3812 printf("if (RT_SW(%d) == -1)\n", d
);
3814 printf(" LO%c = -RS_%sW(%d);\n", hi
, sign
, d
);
3815 printf(" HI%c = 0;\n", hi
);
3816 printf(" }\nelse ");
3818 printf("if (RT_UW(%d) != 0)\n", d
);
3820 printf(" LO%c = (signed32)(RS_%sW(%d) / RT_%sW(%d));\n", hi
, sign
, d
, sign
, d
);
3821 printf(" HI%c = (signed32)(RS_%sW(%d) %% RT_%sW(%d));\n", hi
, sign
, d
, sign
, d
);
3828 printf("signed32 devisor = RT_SH(0);\n");
3829 printf("if (devisor == -1)\n");
3831 printf(" LO_SW(0) = -RS_SW(0);\n");
3832 printf(" HI_SW(0) = 0;\n");
3833 printf(" LO_SW(1) = -RS_SW(1);\n");
3834 printf(" HI_SW(1) = 0;\n");
3835 printf(" LO_SW(2) = -RS_SW(2);\n");
3836 printf(" HI_SW(2) = 0;\n");
3837 printf(" LO_SW(3) = -RS_SW(3);\n");
3838 printf(" HI_SW(3) = 0;\n");
3840 printf("else if (devisor != 0)\n");
3842 printf(" LO_SW(0) = RS_SW(0) / devisor;\n");
3843 printf(" HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n");
3844 printf(" LO_SW(1) = RS_SW(1) / devisor;\n");
3845 printf(" HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n");
3846 printf(" LO_SW(2) = RS_SW(2) / devisor;\n");
3847 printf(" HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n");
3848 printf(" LO_SW(3) = RS_SW(3) / devisor;\n");
3849 printf(" HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n");
3855 printf("for(i=0;i<HALFWORDS_IN_MMI_REGS/2;i++)\n");
3856 printf(" GPR_SH(destreg,i) = RS_SH(i) - RT_SH(i);\n");
3857 printf("for(;i<HALFWORDS_IN_MMI_REGS;i++)\n");
3858 printf(" GPR_SH(destreg,i) = RS_SH(i) + RT_SH(i);\n");
3863 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3864 printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op
);
3865 printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op
);
3866 printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op
);
3867 printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op
);
3873 char* name
= name_for_data_len( insn
);
3874 char* letter
= letter_for_data_len( insn
);
3875 char* bits
= bits_for_data_len( insn
);
3876 char* shift
= (insn
->flags
& RIGHT
) ? ">>" : "<<";
3877 char* sign
= (insn
->flags
& ARITHMETIC
) ? "S" : "U";
3879 printf("int shift_by = op1 & (%s-1);\n", bits
);
3881 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3882 printf(" GPR_%s%s(destreg,i) = ", sign
, letter
);
3883 if ( insn
->flags
& ARITHMETIC
)
3884 printf("SIGNEXTEND( ");
3885 printf("(RT_%s%s(i) %s shift_by)", sign
, letter
, shift
);
3886 if ( insn
->flags
& ARITHMETIC
)
3887 printf(", (%s-shift_by) )", bits
);
3893 printf("int s0 = (RS_UB(0) & 0x1F);\n");
3894 printf("int s1 = (RS_UB(8) & 0x1F);\n");
3895 printf("signed32 temp0 = RT_UW(0) << s0;\n");
3896 printf("signed32 temp1 = RT_UW(2) << s1;\n");
3897 printf("GPR_SD(destreg,0) = (signed64)temp0;\n");
3898 printf("GPR_SD(destreg,1) = (signed64)temp1;\n");
3902 printf("GPR_UD(destreg,0) = SIGNEXTEND ( RT_UW(0) >> (RS_UB(0) & 0x1F), 31);\n");
3903 printf("GPR_UD(destreg,1) = SIGNEXTEND ( RT_UW(2) >> (RS_UB(8) & 0x1F), 31);\n");
3907 printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n");
3908 printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n");
3916 if ( GET_OP_FROM_INSN(insn
) == POP_AND
)
3921 else if ( GET_OP_FROM_INSN(insn
) == POP_OR
)
3926 else if ( GET_OP_FROM_INSN(insn
) == POP_NOR
)
3931 else if ( GET_OP_FROM_INSN(insn
) == POP_XOR
)
3938 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3939 printf(" GPR_UW(destreg,i) = %s(RS_UW(i) %s RT_UW(i));\n", op2
, op1
);
3945 char* name
= name_for_data_len( insn
);
3946 char* letter
= letter_for_data_len( insn
);
3947 char* maximum
= umax_for_data_len( insn
);
3948 char* op
= (insn
->flags
& GT
) ? ">" : "==";
3951 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3953 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n",
3954 letter
, op
, letter
, letter
, maximum
);
3955 printf(" else GPR_S%s(destreg,i) = 0;\n", letter
);
3962 char* name
= name_for_data_len( insn
);
3963 char* letter
= letter_for_data_len( insn
);
3964 char* op
= (insn
->flags
& GT
) ? ">" : "<";
3967 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3969 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n",
3970 letter
, op
, letter
, letter
, letter
);
3971 printf(" else GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
3978 char* name
= name_for_data_len( insn
);
3979 char* letter
= letter_for_data_len( insn
);
3980 char* min
= min_for_data_len( insn
);
3981 char* max
= max_for_data_len( insn
);
3984 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3986 printf(" if (RT_S%s(i) >= 0)\n", letter
);
3987 printf(" GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
3988 printf(" else if (RT_S%s(i) == %s)\n", letter
, min
);
3989 printf(" GPR_S%s(destreg,i) = %s;\n", letter
, max
);
3991 printf(" GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter
, letter
);
3997 printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n");
3998 printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n");
4002 printf("GPR_UD(destreg,0) = RT_UD(0);\n");
4003 printf("GPR_UD(destreg,1) = RS_UD(0);\n");
4007 printf("GPR_UD(destreg,0) = RS_UD(1);\n");
4008 printf("GPR_UD(destreg,1) = RT_UD(1);\n");
4012 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4013 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
4014 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4015 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
4016 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
4017 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
4018 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
4019 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
4023 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4024 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
4025 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
4026 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
4030 printf("GPR_UH(destreg,0) = RT_UH(2);\n");
4031 printf("GPR_UH(destreg,1) = RT_UH(1);\n");
4032 printf("GPR_UH(destreg,2) = RT_UH(0);\n");
4033 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
4034 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
4035 printf("GPR_UH(destreg,5) = RT_UH(5);\n");
4036 printf("GPR_UH(destreg,6) = RT_UH(4);\n");
4037 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
4041 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
4042 printf("GPR_UW(destreg,1) = RT_UW(1);\n");
4043 printf("GPR_UW(destreg,2) = RT_UW(0);\n");
4044 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
4048 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
4049 printf("GPR_UB(destreg,1) = RS_UB(0);\n");
4050 printf("GPR_UB(destreg,2) = RT_UB(1);\n");
4051 printf("GPR_UB(destreg,3) = RS_UB(1);\n");
4052 printf("GPR_UB(destreg,4) = RT_UB(2);\n");
4053 printf("GPR_UB(destreg,5) = RS_UB(2);\n");
4054 printf("GPR_UB(destreg,6) = RT_UB(3);\n");
4055 printf("GPR_UB(destreg,7) = RS_UB(3);\n");
4056 printf("GPR_UB(destreg,8) = RT_UB(4);\n");
4057 printf("GPR_UB(destreg,9) = RS_UB(4);\n");
4058 printf("GPR_UB(destreg,10) = RT_UB(5);\n");
4059 printf("GPR_UB(destreg,11) = RS_UB(5);\n");
4060 printf("GPR_UB(destreg,12) = RT_UB(6);\n");
4061 printf("GPR_UB(destreg,13) = RS_UB(6);\n");
4062 printf("GPR_UB(destreg,14) = RT_UB(7);\n");
4063 printf("GPR_UB(destreg,15) = RS_UB(7);\n");
4067 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4068 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
4069 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4070 printf("GPR_UH(destreg,3) = RS_UH(1);\n");
4071 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
4072 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
4073 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
4074 printf("GPR_UH(destreg,7) = RS_UH(3);\n");
4078 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4079 printf("GPR_UW(destreg,1) = RS_UW(0);\n");
4080 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
4081 printf("GPR_UW(destreg,3) = RS_UW(1);\n");
4085 printf("GPR_UB(destreg,0) = RT_UB(8);\n");
4086 printf("GPR_UB(destreg,1) = RS_UB(8);\n");
4087 printf("GPR_UB(destreg,2) = RT_UB(9);\n");
4088 printf("GPR_UB(destreg,3) = RS_UB(9);\n");
4089 printf("GPR_UB(destreg,4) = RT_UB(10);\n");
4090 printf("GPR_UB(destreg,5) = RS_UB(10);\n");
4091 printf("GPR_UB(destreg,6) = RT_UB(11);\n");
4092 printf("GPR_UB(destreg,7) = RS_UB(11);\n");
4093 printf("GPR_UB(destreg,8) = RT_UB(12);\n");
4094 printf("GPR_UB(destreg,9) = RS_UB(12);\n");
4095 printf("GPR_UB(destreg,10) = RT_UB(13);\n");
4096 printf("GPR_UB(destreg,11) = RS_UB(13);\n");
4097 printf("GPR_UB(destreg,12) = RT_UB(14);\n");
4098 printf("GPR_UB(destreg,13) = RS_UB(14);\n");
4099 printf("GPR_UB(destreg,14) = RT_UB(15);\n");
4100 printf("GPR_UB(destreg,15) = RS_UB(15);\n");
4104 printf("GPR_UH(destreg,0) = RT_UH(4);\n");
4105 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
4106 printf("GPR_UH(destreg,2) = RT_UH(5);\n");
4107 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
4108 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
4109 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
4110 printf("GPR_UH(destreg,6) = RT_UH(7);\n");
4111 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
4115 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
4116 printf("GPR_UW(destreg,1) = RS_UW(2);\n");
4117 printf("GPR_UW(destreg,2) = RT_UW(3);\n");
4118 printf("GPR_UW(destreg,3) = RS_UW(3);\n");
4122 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
4123 printf("GPR_UB(destreg,1) = RT_UB(2);\n");
4124 printf("GPR_UB(destreg,2) = RT_UB(4);\n");
4125 printf("GPR_UB(destreg,3) = RT_UB(6);\n");
4126 printf("GPR_UB(destreg,4) = RT_UB(8);\n");
4127 printf("GPR_UB(destreg,5) = RT_UB(10);\n");
4128 printf("GPR_UB(destreg,6) = RT_UB(12);\n");
4129 printf("GPR_UB(destreg,7) = RT_UB(14);\n");
4130 printf("GPR_UB(destreg,8) = RS_UB(0);\n");
4131 printf("GPR_UB(destreg,9) = RS_UB(2);\n");
4132 printf("GPR_UB(destreg,10) = RS_UB(4);\n");
4133 printf("GPR_UB(destreg,11) = RS_UB(6);\n");
4134 printf("GPR_UB(destreg,12) = RS_UB(8);\n");
4135 printf("GPR_UB(destreg,13) = RS_UB(10);\n");
4136 printf("GPR_UB(destreg,14) = RS_UB(12);\n");
4137 printf("GPR_UB(destreg,15) = RS_UB(14);\n");
4141 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4142 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
4143 printf("GPR_UH(destreg,2) = RT_UH(4);\n");
4144 printf("GPR_UH(destreg,3) = RT_UH(6);\n");
4145 printf("GPR_UH(destreg,4) = RS_UH(0);\n");
4146 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
4147 printf("GPR_UH(destreg,6) = RS_UH(4);\n");
4148 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
4152 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4153 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
4154 printf("GPR_UW(destreg,2) = RS_UW(0);\n");
4155 printf("GPR_UW(destreg,3) = RS_UW(2);\n");
4159 printf("GPR_UH(destreg,0) = RT_UH(3);\n");
4160 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
4161 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4162 printf("GPR_UH(destreg,3) = RT_UH(0);\n");
4163 printf("GPR_UH(destreg,4) = RT_UH(7);\n");
4164 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
4165 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
4166 printf("GPR_UH(destreg,7) = RT_UH(4);\n");
4170 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4171 printf("GPR_UW(destreg,1) = RT_UW(3);\n");
4172 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
4173 printf("GPR_UW(destreg,3) = RT_UW(2);\n");
4177 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4178 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
4179 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4180 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
4181 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
4182 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
4183 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
4184 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
4188 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4189 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
4190 printf("GPR_UH(destreg,2) = RT_UH(2);\n");
4191 printf("GPR_UH(destreg,3) = RS_UH(2);\n");
4192 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
4193 printf("GPR_UH(destreg,5) = RS_UH(4);\n");
4194 printf("GPR_UH(destreg,6) = RT_UH(6);\n");
4195 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
4198 case PMXX
: /* Parallel move HI or LO / TO or FROM */
4200 if ( (insn
->flags
& (HI
|FROM
)) == (HI
|FROM
) )
4202 printf("GPR_SD(destreg,0) = HI;\n");
4203 printf("GPR_SD(destreg,1) = HI1;\n");
4205 else if ( (insn
->flags
& (LO
|FROM
)) == (LO
|FROM
) )
4207 printf("GPR_SD(destreg,0) = LO;\n");
4208 printf("GPR_SD(destreg,1) = LO1;\n");
4210 else if ( (insn
->flags
& (HI
|TO
)) == (HI
|TO
) )
4212 printf("HI = RS_SD(0);\n");
4213 printf("HI1 = RS_SD(1);\n");
4215 else if ( (insn
->flags
& (LO
|TO
)) == (LO
|TO
) )
4217 printf("LO = RS_SD(0);\n");
4218 printf("LO1 = RS_SD(1);\n");
4224 printf("LO_UW(0) = RS_UW(0);\n");
4225 printf("HI_UW(0) = RS_UW(1);\n");
4226 printf("LO_UW(2) = RS_UW(2);\n");
4227 printf("HI_UW(2) = RS_UW(3);\n");
4231 printf("if (op1 == 0)\n");
4233 printf(" GPR_UW(destreg,0) = LO_UW(0);\n");
4234 printf(" GPR_UW(destreg,1) = HI_UW(0);\n");
4235 printf(" GPR_UW(destreg,2) = LO_UW(2);\n");
4236 printf(" GPR_UW(destreg,3) = HI_UW(2);\n");
4238 printf("else if (op1 == 1)\n");
4240 printf(" GPR_UW(destreg,0) = LO_UW(1);\n");
4241 printf(" GPR_UW(destreg,1) = HI_UW(1);\n");
4242 printf(" GPR_UW(destreg,2) = LO_UW(3);\n");
4243 printf(" GPR_UW(destreg,3) = HI_UW(3);\n");
4245 printf("else if (op1 == 2)\n");
4247 printf(" /* NOTE: This code implements a saturate according to the\n");
4248 printf(" figure on page B-115 and not according to the\n");
4249 printf(" definition on page B-113 */\n");
4250 printf(" signed64 t = ((unsigned64)HI_UW(0) << 32) | (unsigned64)LO_UW(0);\n");
4251 printf(" signed64 u = ((unsigned64)HI_UW(2) << 32) | (unsigned64)LO_UW(2);\n");
4252 printf(" if ( t > SIGNED64 (0x000000007FFFFFFF) )\n");
4253 printf(" GPR_SD(destreg,0) = SIGNED64 (0x000000007FFFFFFF);\n");
4254 printf(" else if ( t < - SIGNED64 (0x0000000080000000) )\n");
4255 printf(" GPR_SD(destreg,0) = - SIGNED64 (0x0000000080000000);\n");
4257 printf(" GPR_SD(destreg,0) = t;\n");
4258 printf(" if ( u > SIGNED64 (0x000000007FFFFFFF) )\n");
4259 printf(" GPR_SD(destreg,1) = SIGNED64 (0x000000007FFFFFFF);\n");
4260 printf(" else if ( u < - SIGNED64 (0x0000000080000000) )\n");
4261 printf(" GPR_SD(destreg,1) = - SIGNED64 (0x0000000080000000);\n");
4263 printf(" GPR_SD(destreg,1) = u;\n");
4265 printf("else if (op1 == 3)\n");
4267 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
4268 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
4269 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
4270 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
4271 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
4272 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
4273 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
4274 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
4276 printf("else if (op1 == 4)\n");
4278 printf(" if (LO_SW(0) > 0x7FFF)\n");
4279 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
4280 printf(" else if (LO_SW(0) < -0x8000)\n");
4281 printf(" GPR_UH(destreg,0) = 0x8000;\n");
4283 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
4285 printf(" if (LO_SW(1) > 0x7FFF)\n");
4286 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
4287 printf(" else if (LO_SW(1) < -0x8000)\n");
4288 printf(" GPR_UH(destreg,1) = 0x8000;\n");
4290 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
4292 printf(" if (HI_SW(0) > 0x7FFF)\n");
4293 printf(" GPR_UH(destreg,2) = 0x7FFF;\n");
4294 printf(" else if (HI_SW(0) < -0x8000)\n");
4295 printf(" GPR_UH(destreg,2) = 0x8000;\n");
4297 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
4299 printf(" if (HI_SW(1) > 0x7FFF)\n");
4300 printf(" GPR_UH(destreg,3) = 0x7FFF;\n");
4301 printf(" else if (HI_SW(1) < -0x8000)\n");
4302 printf(" GPR_UH(destreg,3) = 0x8000;\n");
4304 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
4306 printf(" if (LO_SW(2) > 0x7FFF)\n");
4307 printf(" GPR_UH(destreg,4) = 0x7FFF;\n");
4308 printf(" else if (LO_SW(2) < -0x8000)\n");
4309 printf(" GPR_UH(destreg,4) = 0x8000;\n");
4311 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
4313 printf(" if (LO_SW(3) > 0x7FFF)\n");
4314 printf(" GPR_UH(destreg,5) = 0x7FFF;\n");
4315 printf(" else if (LO_SW(3) < -0x8000)\n");
4316 printf(" GPR_UH(destreg,5) = 0x8000;\n");
4318 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
4320 printf(" if (HI_SW(2) > 0x7FFF)\n");
4321 printf(" GPR_UH(destreg,6) = 0x7FFF;\n");
4322 printf(" else if (HI_SW(2) < -0x8000)\n");
4323 printf(" GPR_UH(destreg,6) = 0x8000;\n");
4325 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
4327 printf(" if (HI_SW(3) > 0x7FFF)\n");
4328 printf(" GPR_UH(destreg,7) = 0x7FFF;\n");
4329 printf(" else if (HI_SW(3) < -0x8000)\n");
4330 printf(" GPR_UH(destreg,7) = 0x8000;\n");
4332 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
4338 printf("unsigned long value;\n");
4339 printf("int test;\n");
4340 printf("int count;\n");
4343 printf("value = RS_UW(0);\n");
4344 printf("count = 0;\n");
4345 printf("test = !!(value & (1 << 31));\n");
4346 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
4347 printf(" count++;\n");
4348 printf("GPR_UW(destreg,0) = count;\n");
4350 printf("value = RS_UW(1);\n");
4351 printf("count = 0;\n");
4352 printf("test = !!(value & (1 << 31));\n");
4353 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
4354 printf(" count++;\n");
4355 printf("GPR_UW(destreg,1) = count;\n");
4360 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
4362 printf(" unsigned32 x = RT_UW(i);\n");
4363 printf(" GPR_UW(destreg,i) = ((x & (1 << 15)) << (31 - 15)) \n");
4364 printf(" | ((x & (31 << 10)) << (19 - 10)) \n");
4365 printf(" | ((x & (31 << 5)) << (11 - 5)) \n");
4366 printf(" | ((x & (31 << 0)) << (3 - 0)); \n");
4372 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
4374 printf(" unsigned32 x = RT_UW(i);\n");
4375 printf(" GPR_UW(destreg,i) = ((x & (1 << 31)) >> (31 - 15)) \n");
4376 printf(" | ((x & (31 << 19)) >> (19 - 10)) \n");
4377 printf(" | ((x & (31 << 11)) >> (11 - 5)) \n");
4378 printf(" | ((x & (31 << 3)) >> (3 - 0)); \n");
4381 /* end-sanitize-r5900 */
4384 fprintf(stderr
,"Warning: Unimplemented opcode: %s\n",insn
->name
) ;
4386 printf("SignalException(ReservedInstruction,instruction);\n");
4390 fprintf(stderr
,"Unrecognised opcode type %d\n",insn
->type
) ;
4395 /*---------------------------------------------------------------------------*/
4397 /* The command-line feature controls are presented in a similar style
4398 to those offered by GCC, in the aim of providing a consistent
4399 interface to the user. */
4401 T_NONE
, /* no argument - mask and value fields control "feature" definition */
4402 T_NUM
, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
4403 T_STRING
/* string argument - optionally prcededed by '=' */
4412 } machine_options
[] = {
4413 {"ips", T_NUM
, MASK_ISA
,0,"\tSelect MIPS ISA version"},
4414 {"cpu", T_STRING
,0,0,"\t\tSelect particular MIPS architecture"},
4415 {"gp64", T_NONE
, FEATURE_GP64
,FEATURE_GP64
,"\t\t\tSelect 64bit GP registers"},
4416 {"gp32", T_NONE
, FEATURE_GP64
,0,"\t\t\tSelect 32bit GP registers"},
4417 {"no-fp", T_NONE
, FEATURE_HASFPU
,0,"\t\tDisable FP simulation"},
4418 {"single-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),(FEATURE_FPSINGLE
| FEATURE_HASFPU
),"\t\tSelect single precision only FPU"},
4419 {"double-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),FEATURE_HASFPU
,"\t\tSelect double precision FPU"},
4423 /* The following architecture identies are those accepted by the "-mcpu" option: */
4424 struct architectures
{
4425 const char *name
; /* ASCII string identifier for command-line, no white-space allowed */
4426 unsigned int idflag
; /* or-ed into "isa" value */
4429 static const struct architectures available_architectures
[] = {
4430 {"4100",ARCH_VR4100
}, /* NEC MIPS VR4100 */
4431 {"3900",ARCH_R3900
}, /* Toshiba R3900 (TX39) */
4432 /* start-sanitize-tx19 */
4433 {"1900",ARCH_R3900
}, /* Toshiba R1900 (TX19) */
4434 /* end-sanitize-tx19 */
4435 /* start-sanitize-r5900 */
4436 {"5900",ARCH_R5900
},
4437 /* end-sanitize-r5900 */
4438 {0, 0} /* terminator */
4441 /*---------------------------------------------------------------------------*/
4449 fprintf(stderr
,"%s: Construct a MIPS simulator engine.\n",name
);
4452 The output of this program is a block of 'C' code designed to be\n\
4453 included into the main simulation control loop of a device specific\n\
4456 fprintf(stderr
,"\nOptions:\n");
4457 fprintf(stderr
," -h --help\t\tProvide this help text\n");
4458 fprintf(stderr
," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
4459 fprintf(stderr
," -w --warnings\t\tEnable all the simulator engine warnings\n");
4461 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++) {
4462 fprintf(stderr
," -m%s",machine_options
[loop
].name
);
4463 switch (machine_options
[loop
].type
) {
4465 fprintf(stderr
,"N (range 0..%d)",machine_options
[loop
].mask
);
4470 fprintf(stderr
,"=name");
4474 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",name
,machine_options
[loop
].type
);
4477 fprintf(stderr
,"%s\n",machine_options
[loop
].desc
);
4480 fprintf(stderr
,"\nAvailable \"-mcpu\" architectures: ");
4481 for (loop
= 0; (available_architectures
[loop
].name
!= 0); loop
++)
4482 fprintf(stderr
,"%s ",available_architectures
[loop
].name
);
4483 fprintf(stderr
,"\n\n");
4486 The \"trace\" and \"warnings\" options do not define the output stream.\n\
4487 They only inform the code that includes the constructed engine to provide\n\
4488 the required features.\n\n\
4489 The \"-mips0\" option forces the construction of a simulator supporting\n\
4490 the highest available MIPS ISA supported.\n");
4495 /*---------------------------------------------------------------------------*/
4503 char *progname
= argv
[0];
4504 unsigned int doarch
= DEF_ISA
;
4505 unsigned int features
= 0; /* default state */
4508 features
|= FEATURE_HASFPU
;
4510 features
|= FEATURE_PROC32
;
4512 features
|= FEATURE_FPSINGLE
;
4514 if (features
& FEATURE_PROC32
)
4515 features
&= ~FEATURE_GP64
;
4517 features
|= FEATURE_GP64
;
4520 int option_index
= 0;
4521 static struct option cmdline
[] = {
4524 {"warnings",0,0,'w'},
4529 c
= getopt_long(argc
,argv
,"hm:tw",cmdline
,&option_index
);
4531 break ; /* out of the while loop */
4534 case 'h' : /* help */
4538 case 'f' : /* fast */
4539 features
|= FEATURE_FAST
;
4542 case 'i' : /* igen formatted output */
4543 features
|= FEATURE_IGEN
;
4546 case 'w' : /* warnings */
4547 features
|= FEATURE_WARNINGS
;
4548 /* TODO: Future extension: Allow better control over the warnings generated:
4549 disable warnings -wnone ~FEATURE_WARNINGS
4550 all possible warnings -wall FEATURE_WARNINGS
4551 pipeline stall occuring -wstall FEATURE_WARN_STALL
4552 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
4553 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
4554 bad r31 use -wr31 FEATURE_WARN_R31
4555 undefined results -wresult FEATURE_WARN_RESULT
4559 case 'm' : /* machine options */
4563 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++)
4564 if (strncmp(machine_options
[loop
].name
,optarg
,strlen(machine_options
[loop
].name
)) == 0) {
4565 char *loptarg
= (optarg
+ strlen(machine_options
[loop
].name
));
4566 switch (machine_options
[loop
].type
) {
4569 fprintf(stderr
,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname
,loptarg
,machine_options
[loop
].name
);
4572 features
&= ~(machine_options
[loop
].mask
);
4573 features
|= machine_options
[loop
].value
;
4577 if (*loptarg
&& *loptarg
== '=')
4580 if (strcmp(machine_options
[loop
].name
,"ips") == 0) {
4584 fprintf(stderr
,"%s: ISA number expected after -mips\n",progname
);
4588 num
= my_strtoul(loptarg
,&loptarg
,10);
4590 if ((num
== ULONG_MAX
) && (errno
= ERANGE
)) {
4591 fprintf(stderr
,"%s: Invalid number given to -mips option\n",progname
);
4596 fprintf(stderr
,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname
,loptarg
);
4600 if (num
> MASK_ISA
) {
4601 fprintf(stderr
,"%s: ISA number %d outside acceptable range (0..%d)\n",progname
,num
,MASK_ISA
);
4605 doarch
= ((doarch
& ~MASK_ISA
) | num
);
4606 if ((num
== 0) || (num
> 2)) {
4607 if ((features
& FEATURE_PROC32
) || !(features
& FEATURE_GP64
))
4608 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp64\n",progname
,num
);
4609 features
|= FEATURE_GP64
;
4610 features
&= ~FEATURE_PROC32
;
4612 if (!(features
& FEATURE_PROC32
) || (features
& FEATURE_GP64
))
4613 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp32\n",progname
,num
);
4614 features
&= ~FEATURE_GP64
;
4615 features
|= FEATURE_PROC32
;
4618 fprintf(stderr
,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname
,optarg
);
4624 if (*loptarg
&& *loptarg
== '=')
4627 if (strcmp(machine_options
[loop
].name
,"cpu") == 0) {
4631 fprintf(stderr
,"%s: Architecture identifier expected after -mcpu\n",progname
);
4635 for (archloop
= 0; (available_architectures
[archloop
].name
!= 0); archloop
++) {
4636 if ((*loptarg
== 'v') || (*loptarg
== 'V'))
4639 if ((*loptarg
== 'r') || (*loptarg
== 'R'))
4642 if (strcmp(available_architectures
[archloop
].name
,loptarg
) == 0) {
4643 doarch
|= available_architectures
[archloop
].idflag
;
4648 if (available_architectures
[archloop
].name
== 0) {
4649 fprintf(stderr
,"%s: Unrecognised MIPS architecture \"%s\"\n",progname
,loptarg
);
4653 fprintf(stderr
,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname
,optarg
);
4659 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",progname
,machine_options
[loop
].type
);
4665 if (machine_options
[loop
].name
== 0) {
4666 fprintf(stderr
,"%s: Unrecognised option: -m%s\n",progname
,optarg
);
4673 /* An error message should already have been displayed */
4677 fprintf(stderr
,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname
,c
);
4682 if (optind
< argc
) {
4683 fprintf(stderr
,"%s: Spurios non-option arguments ",progname
);
4684 while (optind
< argc
)
4685 fprintf(stderr
,"\"%s\" ",argv
[optind
++]);
4686 fprintf(stderr
,"\n");
4690 if ((features
& FEATURE_FAST
) && (features
& FEATURE_WARNINGS
))
4691 fprintf(stderr
,"Warning: Fast model generation selected, along with trace or warnings.\n");
4693 process_instructions(doarch
,features
) ;
4697 /*---------------------------------------------------------------------------*/
4699 /* We can't assume that the compiler for the build system has strtoul,
4700 so we provide our own copy. */
4703 * Copyright (c) 1990 Regents of the University of California.
4704 * All rights reserved.
4706 * Redistribution and use in source and binary forms, with or without
4707 * modification, are permitted provided that the following conditions
4709 * 1. Redistributions of source code must retain the above copyright
4710 * notice, this list of conditions and the following disclaimer.
4711 * 2. Redistributions in binary form must reproduce the above copyright
4712 * notice, this list of conditions and the following disclaimer in the
4713 * documentation and/or other materials provided with the distribution.
4714 * 3. All advertising materials mentioning features or use of this software
4715 * must display the following acknowledgement:
4716 * This product includes software developed by the University of
4717 * California, Berkeley and its contributors.
4718 * 4. Neither the name of the University nor the names of its contributors
4719 * may be used to endorse or promote products derived from this software
4720 * without specific prior written permission.
4722 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4723 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4724 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4725 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4726 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4727 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4728 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4729 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4730 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4731 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4736 * Convert a string to an unsigned long integer.
4738 * Ignores `locale' stuff. Assumes that the upper and lower case
4739 * alphabets and digits are each contiguous.
4741 static unsigned long
4742 my_strtoul(nptr
, endptr
, base
)
4747 register const char *s
= nptr
;
4748 register unsigned long acc
;
4750 register unsigned long cutoff
;
4751 register int neg
= 0, any
, cutlim
;
4754 * See strtol for comments as to the logic used.
4758 } while (isspace(c
));
4762 } else if (c
== '+')
4764 if ((base
== 0 || base
== 16) &&
4765 c
== '0' && (*s
== 'x' || *s
== 'X')) {
4771 base
= c
== '0' ? 8 : 10;
4772 cutoff
= (unsigned long)ULONG_MAX
/ (unsigned long)base
;
4773 cutlim
= (unsigned long)ULONG_MAX
% (unsigned long)base
;
4774 for (acc
= 0, any
= 0;; c
= *s
++) {
4777 else if (isalpha(c
))
4778 c
-= isupper(c
) ? 'A' - 10 : 'a' - 10;
4783 if (any
< 0 || acc
> cutoff
|| (acc
== cutoff
&& c
> cutlim
))
4797 *endptr
= (char *) (any
? s
- 1 : nptr
);
4801 /*---------------------------------------------------------------------------*/
4803 /*> EOF gencode.c <*/