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-tx49 */
484 #define ARCH_R4900 ((unsigned)1 << 28) /* Toshiba r4900 (tx49) */
485 /* end-sanitize-tx49 */
487 /* start-sanitize-tx19 */
488 /* The r1900 (tx19) is a tx39 with a mips16 decoder. For the purposes
489 of implementing the simulator we treat them as the same. */
490 /* end-sanitize-tx19 */
492 /* A list (or'ed) of extension insn sets that can be requested independant of the ISA# */
493 #define MASK_ISA_INDEP (0 \
495 /* start-sanitize-tx49 */ \
497 /* end-sanitize-tx49 */ \
498 /* start-sanitize-r5900 */ \
500 /* end-sanitize-r5900 */ \
503 #define MASK_ISA_DEP ~(MASK_ISA_INDEP | MASK_ISA)
505 /* Very short names for use in the table below to keep it neet. */
506 #define G1 (3 | ARCH_VR4100)
509 /* start-sanitize-r5900 */ \
511 /* end-sanitize-r5900 */ \
515 /* start-sanitize-r5900 */ \
516 /* insn that are not really 5900 insn but were left in */ \
517 /* until we can rewrite the code-gen and libs */ \
519 /* end-sanitize-r5900 */ \
522 #define G4 (2 | ARCH_R3900)
526 /* start-sanitize-tx49 */ \
528 /* end-sanitize-tx49 */ \
529 /* start-sanitize-r5900 */ \
531 /* end-sanitize-r5900 */ \
534 #define G6 (3 | ARCH_R3900)
536 #define G7 (ARCH_R3900 \
537 /* start-sanitize-tx49 */ \
539 /* end-sanitize-tx49 */ \
543 /* start-sanitize-tx49 */ \
545 /* end-sanitize-tx49 */ \
546 /* start-sanitize-r5900 */ \
548 /* end-sanitize-r5900 */ \
552 /* start-sanitize-tx49 */ \
554 /* end-sanitize-tx49 */ \
557 /* start-sanitize-r5900 */
558 #define T5 ARCH_R5900
559 /* end-sanitize-r5900 */
562 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
563 COP0 space. This means that an external decoder should be added
564 when constructing a full VR4100 simulator. However some arithmetic
565 instructions are encoded in the normal instruction space. */
567 struct instruction MIPS_DECODE
[] = {
568 /* The instructions are alphabetical, and not in instruction bit-order: */
569 {"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1
, FPABS
, (FP
)},
570 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL
,ADD
, (WORD
| WORD32
| OVERFLOW
)}, /* rd = rs + rt */
571 {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1
, FPADD
, (FP
)},
572 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
| OVERFLOW
)},
573 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL
,ADD
, (WORD
| WORD32
)}, /* rd = rs + rt */
574 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
)},
575 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL
,AND
, (NONE
)}, /* rd = rs AND rt */
576 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, AND
, (NONE
)},
577 {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S
, BRANCH
, (FP
)},
578 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
)},
579 {"BEQL", G4
,"010100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
| LIKELY
)},
580 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
)},
581 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
582 {"BGEZALL",G4
,"000001sssss10011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
| LIKELY
)},
583 {"BGEZL", G4
,"000001sssss00011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LIKELY
)},
584 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
)},
585 {"BGTZL", G4
,"010111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
| LIKELY
)},
586 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
)},
587 {"BLEZL", G4
,"010110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
| LIKELY
)},
588 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM
, BRANCH
, (LT
)},
589 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
)},
590 {"BLTZALL",G4
,"000001sssss10010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
| LIKELY
)},
591 {"BLTZL", G4
,"000001sssss00010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LIKELY
)},
592 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
)},
593 {"BNEL", G4
,"010101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
| LIKELY
)},
594 {"BREAK", 1,"000000????????????????????001101",SPECIAL
,BREAK
, (NOARG
)},
595 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1
, FPCEIL
, (FP
| FIXED
| DOUBLEWORD
)},
596 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1
, FPCEIL
, (FP
| FIXED
| WORD
)},
597 {"COP0", 1,"010000??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
598 {"COP2", 1,"010010??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
599 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1
, FPCONVERT
,(FP
| DOUBLE
)},
600 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1
, FPCONVERT
,(FP
| FIXED
| DOUBLEWORD
)},
601 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1
, FPCONVERT
,(FP
| SINGLE
)},
602 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1
, FPCONVERT
,(FP
| FIXED
| WORD
)},
603 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1
, FPCOMPARE
,(FP
)},
604 {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
| CONTROL
)},
605 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL
,ADD
, (DOUBLEWORD
| OVERFLOW
)},
606 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| OVERFLOW
)},
607 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL
,ADD
, (DOUBLEWORD
| UNSIGNED
)},
608 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| UNSIGNED
)},
609 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL
,DIV
, (DOUBLEWORD
| HI
| LO
)},
610 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL
,DIV
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
611 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
)},
612 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1
, FPDIV
, (FP
| WORD
| HI
| LO
)},
613 /* start-sanitize-r5900 */
614 {"DIV1", T5
,"011100sssssggggg0000000000011010",MMINORM
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
| PIPE1
)},
615 /* end-sanitize-r5900 */
616 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
)},
617 /* start-sanitize-r5900 */
618 {"DIVU1", T5
,"011100sssssggggg0000000000011011",MMINORM
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
| PIPE1
)},
619 /* end-sanitize-r5900 */
620 {"DMADD16",G1
,"000000sssssggggg0000000000101001",SPECIAL
,MADD16
, (DOUBLEWORD
| HI
| LO
)},
621 /* See note near MULT for explanation of 3op-ness. */
622 {"DMULT", G9
,"000000sssssgggggddddd00000011100",SPECIAL
,MUL
, (OP3
| DOUBLEWORD
| HI
| LO
)},
623 {"DMULTU", G9
,"000000sssssgggggddddd00000011101",SPECIAL
,MUL
, (OP3
| DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
624 {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| DOUBLEWORD
)},
625 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
)},
626 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| REG
)},
627 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| HI32
)}, /* rd = rt << (sa + 32) */
628 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
)},
629 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| REG
)},
630 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| HI32
)}, /* rd = rt >> (sa + 32) */
631 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
)},
632 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| REG
)},
633 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| HI32
)},
634 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL
,SUB
, (DOUBLEWORD
)},
635 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL
,SUB
, (DOUBLEWORD
| UNSIGNED
)},
636 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1
, FPFLOOR
, (FP
| FIXED
| DOUBLEWORD
)},
637 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1
, FPFLOOR
, (FP
| FIXED
| WORD
)},
638 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (NONE
)}, /* NOTE: boundary case due to delay slot address being used */
639 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
)}, /* NOTE: boundary case due to delay slot address being used */
640 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL
,JUMP
, (LINK
| REG
)},
641 {"JALX", 1,"011101jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
| NOT
)},
642 {"JR", 1,"000000sssss000000000000000001000",SPECIAL
,JUMP
, (NONE
)}, /* need to check PC as part of instruction fetch */
643 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
| SIGNEXTEND
)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
644 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
)}, /* NOTE: See "LB" comment */
645 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
)},
646 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
647 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
648 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| LEFT
)}, /* NOTE: See "LB" comment */
649 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| RIGHT
)}, /* NOTE: See "LB" comment */
650 {"LDXC1", G3
,"010011sssssggggg00000rrrrr000001",COP1X
, LOAD
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
651 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
| SIGNEXTEND
)},
652 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
)},
653 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| ATOMIC
| SIGNEXTEND
)},
654 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| ATOMIC
)},
655 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL
, MOVE
, (SHIFT16
)}, /* Cheat and specify sign-extension of immediate field */
656 /* start-sanitize-r5900 */
657 {"LQ", T5
,"011110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (QUADWORD
)},
658 /* end-sanitize-r5900 */
659 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| SIGNEXTEND
)},
660 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
661 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
662 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| LEFT
)},
663 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| RIGHT
)},
664 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
)},
665 {"LWXC1", G3
,"010011sssssggggg00000rrrrr000000",COP1X
, LOAD
, (FP
| WORD
| COPROC
| REG
)},
666 {"MADD", G5
,"011100sssssgggggddddd00000000000",MMINORM
,MADD
, (NONE
)},
667 {"MADDU", G5
,"011100sssssgggggddddd00000000001",MMINORM
,MADD
, (UNSIGNED
)},
668 /* start-sanitize-r5900 */
669 {"MADD1", T5
,"011100sssssgggggddddd00000100000",MMINORM
,MADD
, (PIPE1
)},
670 {"MADDU1", T5
,"011100sssssgggggddddd00000100001",MMINORM
,MADD
, (UNSIGNED
| PIPE1
)},
671 /* end-sanitize-r5900 */
672 {"MADD16", G1
,"000000sssssggggg0000000000101000",SPECIAL
,MADD16
, (WORD
| HI
| LO
)},
673 {"MADD.D", G3
,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X
, FPADD
, (FP
| MULTIPLY
| DOUBLE
)},
674 {"MADD.S", G3
,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X
, FPADD
, (FP
| MULTIPLY
| SINGLE
)},
675 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL
,MOVE
, (HI
| LEFT
)}, /* with following, from and to denoted by usage of LEFT or RIGHT */
676 /* start-sanitize-r5900 */
677 {"MFHI1", T5
,"0111000000000000ddddd00000010000",MMINORM
,MOVE
, (HI
| LEFT
| PIPE1
)},
678 /* end-sanitize-r5900 */
679 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL
,MOVE
, (LO
| LEFT
)},
680 /* start-sanitize-r5900 */
681 {"MFLO1", T5
,"0111000000000000ddddd00000010010",MMINORM
,MOVE
, (LO
| LEFT
| PIPE1
)},
682 {"MFSA", T5
,"0000000000000000ddddd00000101000",SPECIAL
,MxSA
, (FROM
)},
683 /* end-sanitize-r5900 */
684 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL
,MOVE
, (HI
| RIGHT
)},
685 /* start-sanitize-r5900 */
686 {"MTHI1", T5
,"011100sssss000000000000000010001",MMINORM
,MOVE
, (HI
| RIGHT
| PIPE1
)},
687 /* end-sanitize-r5900 */
688 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL
,MOVE
, (LO
| RIGHT
)},
689 /* start-sanitize-r5900 */
690 {"MTLO1", T5
,"011100sssss000000000000000010011",MMINORM
,MOVE
, (LO
| RIGHT
| PIPE1
)},
691 {"MTSA", T5
,"000000sssss000000000000000101001",SPECIAL
,MxSA
, (TO
)},
692 {"MTSAB", T5
,"000001sssss11000iiiiiiiiiiiiiiii",REGIMM
, MTSAB
, (NONE
)},
693 {"MTSAH", T5
,"000001sssss11001iiiiiiiiiiiiiiii",REGIMM
, MTSAH
, (NONE
)},
694 /* end-sanitize-r5900 */
695 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1
, FPMOVE
, (FP
)},
696 {"MOVN", G2
,"000000sssssgggggddddd00000001011",SPECIAL
,MOVE
, (NOT
| EQ
)},
697 {"MOVN", G2
,"01000110mmmgggggvvvvvrrrrr010011",COP1
, FPMOVE
, (FP
| NOT
| EQ
)},
698 {"MOV%c", G3
,"000000sssssqqq0cddddd00000000001",SPECIAL
,FPMOVE
, (FP
| CONDITIONAL
| INTEGER
)},
699 {"MOV%c", G3
,"01000110mmmqqq0cvvvvvrrrrr010001",COP1
, FPMOVE
, (FP
| CONDITIONAL
)},
700 {"MOVZ", G2
,"000000sssssgggggddddd00000001010",SPECIAL
,MOVE
, (EQ
)},
701 {"MOVZ", G2
,"01000110mmmgggggvvvvvrrrrr010010",COP1
, FPMOVE
, (FP
| EQ
)},
702 {"MSUB.D", G3
,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X
, FPSUB
, (FP
| MULTIPLY
| DOUBLE
)},
703 {"MSUB.S", G3
,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X
, FPSUB
, (FP
| MULTIPLY
| SINGLE
)},
704 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1
, FPMUL
, (FP
| HI
| LO
)},
705 /* The 3op version of MULT and MULTU are TX39 (and related chips) specific.
706 They should be removed from other chips sets, so that using the 3op opcode
707 causes a reserved instruction exception, but gencode can't deal with
709 {"MULT", 1,"000000sssssgggggddddd00000011000",SPECIAL
,MUL
, (OP3
| WORD
| WORD32
| HI
| LO
)},
710 /* start-sanitize-r5900 */
711 {"MULT1", T5
,"011100sssssgggggddddd00000011000",MMINORM
,MUL
, (OP3
| WORD
| WORD32
| HI
| LO
| PIPE1
)},
712 /* end-sanitize-r5900 */
713 {"MULTU", 1,"000000sssssgggggddddd00000011001",SPECIAL
,MUL
, (OP3
| WORD
| WORD32
| UNSIGNED
| HI
| LO
)},
714 /* start-sanitize-r5900 */
715 {"MULTU1", T5
,"011100sssssgggggddddd00000011001",MMINORM
,MUL
, (OP3
| WORD
| WORD32
| UNSIGNED
| HI
| LO
| PIPE1
)},
716 /* end-sanitize-r5900 */
717 {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
)},
718 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1
, FPNEG
, (FP
)},
719 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
720 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
721 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
722 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
723 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL
,OR
, (NOT
)},
724 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL
,OR
, (NONE
)},
725 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, OR
, (NONE
)},
727 /* start-sanitize-r5900 */
728 {"PABSH", T5
,"01110000000TTTTTddddd00101101000",MMI1
, PABS
, (HALFWORD
)},
729 {"PABSW", T5
,"01110000000TTTTTddddd00001101000",MMI1
, PABS
, (WORD
)},
731 {"PADDB", T5
,"011100SSSSSTTTTTddddd01000001000",MMI0
, PADD
, (BYTE
)},
732 {"PADDH", T5
,"011100SSSSSTTTTTddddd00100001000",MMI0
, PADD
, (HALFWORD
)},
733 {"PADDW", T5
,"011100SSSSSTTTTTddddd00000001000",MMI0
, PADD
, (WORD
)},
735 {"PADDSB", T5
,"011100SSSSSTTTTTddddd11000001000",MMI0
, PADD
, (BYTE
| SATURATE
)},
736 {"PADDSH", T5
,"011100SSSSSTTTTTddddd10100001000",MMI0
, PADD
, (HALFWORD
| SATURATE
)},
737 {"PADDSW", T5
,"011100SSSSSTTTTTddddd10000001000",MMI0
, PADD
, (WORD
| SATURATE
)},
739 {"PADDUB", T5
,"011100SSSSSTTTTTddddd11000101000",MMI1
, PADD
, (BYTE
| UNSIGNED
)},
740 {"PADDUH", T5
,"011100SSSSSTTTTTddddd10100101000",MMI1
, PADD
, (HALFWORD
| UNSIGNED
)},
741 {"PADDUW", T5
,"011100SSSSSTTTTTddddd10000101000",MMI1
, PADD
, (WORD
| UNSIGNED
)},
743 {"PADSBH", T5
,"011100SSSSSTTTTTddddd00100101000",MMI1
, PADSBH
, (NONE
)},
745 {"PAND", T5
,"011100SSSSSTTTTTddddd10010001001",MMI2
, POP
, (POP_AND
)},
747 {"PCEQB", T5
,"011100SSSSSTTTTTddddd01010101000",MMI1
, PCMP
, (EQ
| BYTE
)},
748 {"PCEQH", T5
,"011100SSSSSTTTTTddddd00110101000",MMI1
, PCMP
, (EQ
| HALFWORD
)},
749 {"PCEQW", T5
,"011100SSSSSTTTTTddddd00010101000",MMI1
, PCMP
, (EQ
| WORD
)},
751 {"PCGTB", T5
,"011100SSSSSTTTTTddddd01010001000",MMI0
, PCMP
, (GT
| BYTE
)},
752 {"PCGTH", T5
,"011100SSSSSTTTTTddddd00110001000",MMI0
, PCMP
, (GT
| HALFWORD
)},
753 {"PCGTW", T5
,"011100SSSSSTTTTTddddd00010001000",MMI0
, PCMP
, (GT
| WORD
)},
755 {"PCPYH", T5
,"01110000000TTTTTddddd11011101001",MMI3
, PCPYH
, (NONE
)},
756 {"PCPYLD", T5
,"011100SSSSSTTTTTddddd01110001001",MMI2
, PCPYLD
, (NONE
)},
757 {"PCPYUD", T5
,"011100SSSSSTTTTTddddd01110101001",MMI3
, PCPYUD
, (NONE
)},
759 {"PDIVBW", T5
,"011100SSSSSTTTTT0000011101001001",MMI2
, PDIVBW
, (NONE
)},
760 {"PDIVUW", T5
,"011100SSSSSTTTTT0000001101101001",MMI3
, PDIVW
, (UNSIGNED
)},
761 {"PDIVW", T5
,"011100SSSSSTTTTT0000001101001001",MMI2
, PDIVW
, (NONE
)},
763 {"PEXCH", T5
,"01110000000TTTTTddddd11010101001",MMI3
, PEXCH
, (NONE
)},
764 {"PEXCW", T5
,"01110000000TTTTTddddd11110101001",MMI3
, PEXCW
, (NONE
)},
765 {"PEXOH", T5
,"01110000000TTTTTddddd11010001001",MMI2
, PEXOH
, (NONE
)},
766 {"PEXOW", T5
,"01110000000TTTTTddddd11110001001",MMI2
, PEXOW
, (NONE
)},
768 {"PEXT5", T5
,"01110000000TTTTTddddd11110001000",MMI0
, PEXT5
, (NONE
)},
770 {"PEXTLB", T5
,"011100SSSSSTTTTTddddd11010001000",MMI0
, PEXTLB
, (NONE
)},
771 {"PEXTLH", T5
,"011100SSSSSTTTTTddddd10110001000",MMI0
, PEXTLH
, (NONE
)},
772 {"PEXTLW", T5
,"011100SSSSSTTTTTddddd10010001000",MMI0
, PEXTLW
, (NONE
)},
773 {"PEXTUB", T5
,"011100SSSSSTTTTTddddd11010101000",MMI1
, PEXTUB
, (NONE
)},
774 {"PEXTUH", T5
,"011100SSSSSTTTTTddddd10110101000",MMI1
, PEXTUH
, (NONE
)},
775 {"PEXTUW", T5
,"011100SSSSSTTTTTddddd10010101000",MMI1
, PEXTUW
, (NONE
)},
777 {"PHMADDH",T5
,"011100SSSSSTTTTTddddd10001001001",MMI2
, PHMADDH
, (NONE
)},
778 {"PHMSUBH",T5
,"011100SSSSSTTTTTddddd10101001001",MMI2
, PHMADDH
, (SUBTRACT
)},
780 {"PINTH", T5
,"011100SSSSSTTTTTddddd01010001001",MMI2
, PINTH
, (NONE
)},
781 {"PINTOH", T5
,"011100SSSSSTTTTTddddd01010101001",MMI3
, PINTOH
, (NONE
)},
783 {"PLZCW", T5
,"011100SSSSS00000ddddd00000000100",MMINORM
,PLZCW
, (NONE
)},
785 {"PMADDH", T5
,"011100SSSSSTTTTTddddd10000001001",MMI2
, PMULTH
, (ADDITION
)},
786 {"PMADDUW",T5
,"011100SSSSSTTTTTddddd00000101001",MMI3
, PMULTW
, (ADDITION
| UNSIGNED
)},
787 {"PMADDW", T5
,"011100SSSSSTTTTTddddd00000001001",MMI2
, PMULTW
, (ADDITION
)},
789 {"PMAXH", T5
,"011100SSSSSTTTTTddddd00111001000",MMI0
, PMAXMIN
, (GT
| HALFWORD
)},
790 {"PMAXW", T5
,"011100SSSSSTTTTTddddd00011001000",MMI0
, PMAXMIN
, (GT
| WORD
)},
792 {"PMFHI", T5
,"0111000000000000ddddd01000001001",MMI2
, PMXX
, (HI
|FROM
)},
793 {"PMFLO", T5
,"0111000000000000ddddd01001001001",MMI2
, PMXX
, (LO
|FROM
)},
795 {"PMFHL", T5
,"0111000000000000dddddaaaaa110000",MMINORM
,PMFHL
, (NONE
)},
797 {"PMINH", T5
,"011100SSSSSTTTTTddddd00111101000",MMI1
, PMAXMIN
, (LT
| HALFWORD
)},
798 {"PMINW", T5
,"011100SSSSSTTTTTddddd00011101000",MMI1
, PMAXMIN
, (LT
| WORD
)},
800 {"PMSUBH", T5
,"011100SSSSSTTTTTddddd10100001001",MMI2
, PMULTH
, (SUBTRACT
)},
801 {"PMSUBW", T5
,"011100SSSSSTTTTTddddd00100001001",MMI2
, PMULTW
, (SUBTRACT
)},
803 {"PMTHI", T5
,"011100SSSSS000000000001000101001",MMI3
, PMXX
, (HI
|TO
)},
804 {"PMTLO", T5
,"011100SSSSS000000000001001101001",MMI3
, PMXX
, (LO
|TO
)},
806 {"PMTHL.LW",T5
,"011100SSSSS000000000000000110001",MMINORM
,PMTHL
, (NONE
)},
808 {"PMULTH", T5
,"011100SSSSSTTTTTddddd11100001001",MMI2
, PMULTH
, (NONE
)},
809 {"PMULTUW",T5
,"011100SSSSSTTTTTddddd01100101001",MMI3
, PMULTW
, (UNSIGNED
)},
810 {"PMULTW", T5
,"011100SSSSSTTTTTddddd01100001001",MMI2
, PMULTW
, (NONE
)},
812 {"PNOR", T5
,"011100SSSSSTTTTTddddd10011101001",MMI3
, POP
, (POP_NOR
)},
813 {"POR", T5
,"011100SSSSSTTTTTddddd10010101001",MMI3
, POP
, (POP_OR
)},
815 {"PPAC5", T5
,"01110000000TTTTTddddd11111001000",MMI0
, PPAC5
, (NONE
)},
817 {"PPACB", T5
,"011100SSSSSTTTTTddddd11011001000",MMI0
, PPACB
, (NONE
)},
818 {"PPACH", T5
,"011100SSSSSTTTTTddddd10111001000",MMI0
, PPACH
, (NONE
)},
819 {"PPACW", T5
,"011100SSSSSTTTTTddddd10011001000",MMI0
, PPACW
, (NONE
)},
821 {"PREVH", T5
,"01110000000TTTTTddddd11011001001",MMI2
, PREVH
, (NONE
)},
822 {"PROT3W", T5
,"01110000000TTTTTddddd11111001001",MMI2
, PROT3W
, (NONE
)},
824 {"PSLLH", T5
,"01110000000TTTTTdddddaaaaa110100",MMINORM
,PSHIFT
, (LEFT
| LOGICAL
| HALFWORD
)},
825 {"PSLLVW", T5
,"011100SSSSSTTTTTddddd00010001001",MMI2
, PSLLVW
, (NONE
)},
826 {"PSLLW", T5
,"01110000000TTTTTdddddaaaaa111100",MMINORM
,PSHIFT
, (LEFT
| LOGICAL
| WORD
)},
828 {"PSRAH", T5
,"01110000000TTTTTdddddaaaaa110111",MMINORM
,PSHIFT
, (RIGHT
| ARITHMETIC
| HALFWORD
)},
829 {"PSRAVW", T5
,"011100SSSSSTTTTTddddd00011101001",MMI3
, PSRAVW
, (NONE
)},
830 {"PSRAW", T5
,"01110000000TTTTTdddddaaaaa111111",MMINORM
,PSHIFT
, (RIGHT
| ARITHMETIC
| WORD
)},
832 {"PSRLH", T5
,"01110000000TTTTTdddddaaaaa110110",MMINORM
,PSHIFT
, (RIGHT
| LOGICAL
| HALFWORD
)},
833 {"PSRLVW", T5
,"011100SSSSSTTTTTddddd00011001001",MMI2
, PSRLVW
, (NONE
)},
834 {"PSRLW", T5
,"01110000000TTTTTdddddaaaaa111110",MMINORM
,PSHIFT
, (RIGHT
| LOGICAL
| WORD
)},
836 {"PSUBB", T5
,"011100SSSSSTTTTTddddd01001001000",MMI0
, PADD
, (SUBTRACT
| BYTE
)},
837 {"PSUBH", T5
,"011100SSSSSTTTTTddddd00101001000",MMI0
, PADD
, (SUBTRACT
| HALFWORD
)},
838 {"PSUBSB", T5
,"011100SSSSSTTTTTddddd11001001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| BYTE
)},
839 {"PSUBSH", T5
,"011100SSSSSTTTTTddddd10101001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| HALFWORD
)},
840 {"PSUBSW", T5
,"011100SSSSSTTTTTddddd10001001000",MMI0
, PADD
, (SUBTRACT
| SATURATE
| WORD
)},
841 {"PSUBUB", T5
,"011100SSSSSTTTTTddddd11001101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| BYTE
)},
842 {"PSUBUH", T5
,"011100SSSSSTTTTTddddd10101101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| HALFWORD
)},
843 {"PSUBUW", T5
,"011100SSSSSTTTTTddddd10001101000",MMI1
, PADD
, (SUBTRACT
| UNSIGNED
| WORD
)},
844 {"PSUBW", T5
,"011100SSSSSTTTTTddddd00001001000",MMI0
, PADD
, (SUBTRACT
| WORD
)},
846 {"PXOR", T5
,"011100SSSSSTTTTTddddd10011001001",MMI2
, POP
, (POP_XOR
)},
847 /* end-sanitize-r5900 */
849 {"PREF", G8
,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, PREFETCH
, (NONE
)},
850 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X
, FPPREFX
, (FP
)},
852 /* start-sanitize-r5900 */
853 {"QFSRV", T5
,"011100SSSSSTTTTTddddd11011101000",MMI1
, QFSRV
, (NONE
)},
854 /* end-sanitize-r5900 */
856 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1
, FPRECIP
, (FP
)},
857 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1
, FPROUND
, (FP
| FIXED
| DOUBLEWORD
)},
858 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1
, FPROUND
, (FP
| FIXED
| WORD
)},
859 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1
, FPSQRT
, (FP
| RECIP
)},
860 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (BYTE
)},
861 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| ATOMIC
)},
862 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| ATOMIC
)},
863 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
)},
864 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
865 {"SDBBP", G7
,"000000????????????????????001110",SPECIAL
,SDBBP
, (NOARG
)},
866 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
867 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| LEFT
)},
868 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| RIGHT
)},
869 {"SDXC1", G3
,"010011sssssgggggvvvvv00000001001",COP1X
, STORE
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
870 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL
, STORE
, (HALFWORD
)},
871 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << sa */
872 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
873 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL
,SET
, (LT
)},
874 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
)},
875 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL
,SET
, (LT
| UNSIGNED
)},
876 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
| UNSIGNED
)},
877 /* start-sanitize-r5900 */
878 {"SQ", T5
,"011111sssssTTTTTeeeeeeeeeeeeeeee",NORMAL
, STORE
, (QUADWORD
)},
879 /* end-sanitize-r5900 */
880 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1
, FPSQRT
, (FP
)},
881 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
882 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
883 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
884 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
885 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL
,SUB
, (WORD
| WORD32
| OVERFLOW
)},
886 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1
, FPSUB
, (FP
)},
887 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL
,SUB
, (WORD
| WORD32
)},
888 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
)},
889 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
890 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
891 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| LEFT
)},
892 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| RIGHT
)},
893 {"SWXC1", G3
,"010011sssssgggggvvvvv00000001000",COP1X
, STORE
, (FP
| WORD
| COPROC
| REG
)},
894 {"SYNC", G4
,"000000000000000000000aaaaa001111",SPECIAL
,SYNC
, (NONE
)}, /* z = 5bit stype field */
895 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL
,SYSCALL
, (NOARG
)},
896 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL
,TRAP
, (EQ
)},
897 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (EQ
)},
898 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL
,TRAP
, (GT
| EQ
)},
899 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
)},
900 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
| UNSIGNED
)},
901 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL
,TRAP
, (GT
| EQ
| UNSIGNED
)},
902 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL
,TRAP
, (LT
)},
903 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
)},
904 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
| UNSIGNED
)},
905 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL
,TRAP
, (LT
| UNSIGNED
)},
906 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL
,TRAP
, (NOT
| EQ
)},
907 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (NOT
| EQ
)},
908 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1
, FPTRUNC
, (FP
| FIXED
| DOUBLEWORD
)},
909 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1
, FPTRUNC
, (FP
| FIXED
| WORD
)},
910 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL
,XOR
, (NONE
)},
911 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, XOR
, (NONE
)},
912 {"CACHE", G6
,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, CACHE
, (NONE
)},
913 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, RSVD
, (NONE
)},
916 static const struct instruction MIPS16_DECODE
[] = {
917 {"ADDIU", 1, "01000xxxddd04444", RRI_A
, ADD
, WORD
| WORD32
},
918 {"ADDIU8", 1, "01001wwwkkkkkkkk", RI
, ADD
, WORD
| WORD32
},
919 {"ADJSP", 1, "01100011KKKKKKKKS", I8
, ADD
, WORD
| WORD32
},
920 {"ADDIUPC", 1, "00001dddAAAAAAAAP", RI
, ADD
, WORD
| WORD32
},
921 {"ADDIUSP", 1, "00000dddAAAAAAAAs", RI
, ADD
, WORD
| WORD32
},
922 {"ADDU", 1, "11100xxxyyyddd01", RRR
, ADD
, WORD
| WORD32
},
923 {"AND", 1, "11101wwwyyy01100", RR
, AND
, NONE
},
924 {"B", 1, "00010qqqqqqqqqqqzZ", I
, BRANCH
, EQ
},
925 {"BEQZ", 1, "00100xxxppppppppz", RI
, BRANCH
, EQ
},
926 {"BNEZ", 1, "00101xxxppppppppz", RI
, BRANCH
, NOT
| EQ
},
927 {"BREAK", 1, "01100??????00101", RR
, BREAK
, NOARG
},
928 {"BTEQZ", 1, "01100000pppppppptz", I8
, BRANCH
, EQ
},
929 {"BTNEZ", 1, "01100001pppppppptz", I8
, BRANCH
, NOT
| EQ
},
930 {"CMP", 1, "11101xxxyyy01010T", RR
, XOR
, NONE
},
931 {"CMPI", 1, "01110xxxUUUUUUUUT", RI
, XOR
, NONE
},
932 {"DADDIU", 3, "01000xxxddd14444", RRI_A
, ADD
, DOUBLEWORD
},
933 {"DADDIU5", 3, "11111101wwwjjjjj", RI64
, ADD
, DOUBLEWORD
},
934 {"DADJSP", 3, "11111011KKKKKKKKS", I64
, ADD
, DOUBLEWORD
},
935 {"DADIUPC", 3, "11111110dddEEEEEP", RI64
, ADD
, DOUBLEWORD
},
936 {"DADIUSP", 3, "11111111dddEEEEEs", RI64
, ADD
, DOUBLEWORD
},
937 {"DADDU", 3, "11100xxxyyyddd00", RRR
, ADD
, DOUBLEWORD
},
938 {"DDIV", 3, "11101xxxyyy11110", RR
, DIV
, DOUBLEWORD
| HI
| LO
},
939 {"DDIVU", 3, "11101xxxyyy11111", RR
, DIV
, DOUBLEWORD
| UNSIGNED
| HI
| LO
},
940 {"DIV", 1, "11101xxxyyy11010", RR
, DIV
, WORD
| WORD32
| SIGNEXTEND
| HI
| LO
},
941 {"DIVU", 1, "11101xxxyyy11011", RR
, DIV
, WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
},
942 {"DMULT", 3, "11101xxxyyy11100", RR
, MUL
, DOUBLEWORD
| HI
| LO
},
943 {"DMULTU", 3, "11101xxxyyy11101", RR
, MUL
, DOUBLEWORD
| UNSIGNED
| HI
| LO
},
944 {"DSLL", 3, "00110dddyyy[[[01", ISHIFT
, SHIFT
, DOUBLEWORD
| LEFT
| LOGICAL
},
945 {"DSLLV", 3, "11101xxxvvv10100", RR
, SHIFT
, DOUBLEWORD
| LEFT
| LOGICAL
| REG
},
946 {"DSRA", 3, "11101]]]vvv10011", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| ARITHMETIC
},
947 {"DSRAV", 3, "11101xxxvvv10111", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| ARITHMETIC
| REG
},
948 {"DSRL", 3, "11101]]]vvv01000", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| LOGICAL
},
949 {"DSRLV", 3, "11101xxxvvv10110", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| LOGICAL
| REG
},
950 {"DSUBU", 3, "11100xxxyyyddd10", RRR
, SUB
, DOUBLEWORD
| UNSIGNED
},
952 /* FIXME: Should we handle these ourselves, or should we require an
953 emulation routine? */
954 {"EXIT", 1, "1110111100001000", RR
, BREAK
, EXIT
},
955 {"ENTRY", 1, "11101??????01000", RR
, BREAK
, ENTRY
},
957 {"EXTEND", 1, "11110eeeeeeeeeee", I
, RSVD
, NOARG
},
958 {"JALR", 1, "11101xxx01000000R", RR
, JUMP
, LINK
| REG
},
959 {"JAL", 1, "00011aaaaaaaaaaa", I
, JUMP
, LINK
},
960 {"JR", 1, "11101xxx00000000", RR
, JUMP
, NONE
},
961 {"JRRA", 1, "1110100000100000r", RR
, JUMP
, NONE
},
962 {"LB", 1, "10000xxxddd55555", RRI
, LOAD
, BYTE
| SIGNEXTEND
},
963 {"LBU", 1, "10100xxxddd55555", RRI
, LOAD
, BYTE
},
964 {"LD", 3, "00111xxxdddDDDDD", RRI
, LOAD
, DOUBLEWORD
},
965 {"LDPC", 3, "11111100dddDDDDDP", RI64
, LOAD
, DOUBLEWORD
},
966 {"LDSP", 3, "11111000dddDDDDDs", RI64
, LOAD
, DOUBLEWORD
},
967 {"LH", 1, "10001xxxdddHHHHH", RRI
, LOAD
, HALFWORD
| SIGNEXTEND
},
968 {"LHU", 1, "10101xxxdddHHHHH", RRI
, LOAD
, HALFWORD
},
969 {"LI", 1, "01101dddUUUUUUUUZ", RI
, OR
, NONE
},
970 {"LW", 1, "10011xxxdddWWWWW", RRI
, LOAD
, WORD
| SIGNEXTEND
},
971 {"LWPC", 1, "10110dddVVVVVVVVP", RI
, LOAD
, WORD
| SIGNEXTEND
},
972 {"LWSP", 1, "10010dddVVVVVVVVs", RI
, LOAD
, WORD
| SIGNEXTEND
},
973 {"LWU", 1, "10111xxxdddWWWWW", RRI
, LOAD
, WORD
},
974 {"MFHI", 1, "11101ddd00010000", RR
, MOVE
, HI
| LEFT
},
975 {"MFLO", 1, "11101ddd00010010", RR
, MOVE
, LO
| LEFT
},
976 {"MOVR32", 1, "01100111dddXXXXXz", I8_MOVR32
, OR
, NONE
},
977 {"MOV32R", 1, "01100101YYYYYxxxz", I8_MOV32R
, OR
, NONE
},
978 {"MULT", 1, "11101xxxyyy11000", RR
, MUL
, WORD
| WORD32
| HI
| LO
},
979 {"MULTU", 1, "11101xxxyyy11001", RR
, MUL
, WORD
| WORD32
| UNSIGNED
| HI
| LO
},
980 {"NEG", 1, "11101dddyyy01011Z", RR
, SUB
, WORD
},
981 {"NOT", 1, "11101dddyyy01111Z", RR
, OR
, NOT
},
982 {"OR", 1, "11101wwwyyy01101", RR
, OR
, NONE
},
983 {"SB", 1, "11000xxxyyy55555", RRI
, STORE
, BYTE
},
984 {"SDBBP", G7
, "11100??????00001", RR
, SDBBP
, NOARG
},
985 {"SD", 3, "01111xxxyyyDDDDD", RRI
, STORE
, DOUBLEWORD
},
986 {"SDSP", 3, "11111001yyyDDDDDs", RI64
, STORE
, DOUBLEWORD
},
987 {"SDRASP", 3, "11111010CCCCCCCCsQ", I64
, STORE
, DOUBLEWORD
},
988 {"SH", 1, "11001xxxyyyHHHHH", RRI
, STORE
, HALFWORD
},
989 {"SLL", 1, "00110dddyyy<<<00", ISHIFT
, SHIFT
, WORD
| LEFT
| LOGICAL
},
990 {"SLLV", 1, "11101xxxvvv00100", RR
, SHIFT
, WORD
| LEFT
| LOGICAL
| REG
},
991 {"SLT", 1, "11101xxxyyy00010T", RR
, SET
, LT
},
992 {"SLTI", 1, "01010xxx88888888T", RI
, SET
, LT
},
993 {"SLTU", 1, "11101xxxyyy00011T", RR
, SET
, LT
| UNSIGNED
},
994 {"SLTIU", 1, "01011xxx88888888T", RI
, SET
, LT
| UNSIGNED
},
995 {"SRA", 1, "00110dddyyy<<<11", ISHIFT
, SHIFT
, WORD
| WORD32
| RIGHT
| ARITHMETIC
},
996 {"SRAV", 1, "11101xxxvvv00111", RR
, SHIFT
, WORD
| WORD32
| RIGHT
| ARITHMETIC
| REG
},
997 {"SRL", 1, "00110dddyyy<<<10", ISHIFT
, SHIFT
, WORD
| WORD32
| RIGHT
| LOGICAL
},
998 {"SRLV", 1, "11101xxxvvv00110", RR
, SHIFT
, WORD
| WORD32
| RIGHT
| LOGICAL
| REG
},
999 {"SUBU", 1, "11100xxxyyyddd11", RRR
, SUB
, WORD
| WORD32
},
1000 {"SW", 1, "11011xxxyyyWWWWW", RRI
, STORE
, WORD
},
1001 {"SWSP", 1, "11010yyyVVVVVVVVs", RI
, STORE
, WORD
},
1002 {"SWRASP", 1, "01100010VVVVVVVVQs", I8
, STORE
, WORD
},
1003 {"XOR", 1, "11101wwwyyy01110", RR
, XOR
, NONE
}
1006 /*---------------------------------------------------------------------------*/
1008 static void print_igen_insn_format
PARAMS ((const char *bitmap
,
1011 const char *options
,
1015 print_igen_insn_format (bitmap
, mark
, data_size
, options
, name
)
1019 const char *options
;
1024 for (chp
= bitmap
; *chp
!= '\0'; chp
++)
1026 if ((isdigit (lch
) && !isdigit (*chp
))
1027 || (!isdigit (lch
) && isdigit (*chp
))
1028 || (!isdigit (lch
) && !isdigit (*chp
) && lch
!= *chp
))
1039 printf ("s"); /* good guess */
1042 printf ("%c", *chp
);
1064 case COP1S
: /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
1084 /* mips16 encoding types. */
1110 printf ("I8_MOVR32");
1113 printf ("I8_MOV32R");
1128 /* start-sanitize-r5900 */
1132 /* end-sanitize-r5900 */
1139 printf (":%s:%s\n", options
, name
);
1142 static void print_igen_insn_models
PARAMS ((unsigned int isa
));
1145 print_igen_insn_models (isa
)
1148 /* common mips ISAs */
1149 switch ((isa
& MASK_ISA
))
1152 printf ("*mipsI:\n");
1154 printf ("*mipsII:\n");
1156 printf ("*mipsIII:\n");
1157 /* start-sanitize-cygnus-never */
1158 printf ("// %s-%s-%s\n", "start", "sanitize", "r5900");
1159 /* end-sanitize-cygnus-never */
1160 /* start-sanitize-r5900 */
1161 printf ("*r5900:\n");
1162 /* end-sanitize-r5900 */
1163 /* start-sanitize-cygnus-never */
1164 printf ("// %s-%s-%s\n", "end", "sanitize", "r5900");
1165 /* end-sanitize-cygnus-never */
1166 printf ("*r3900:\n");
1167 /* start-sanitize-cygnus-never */
1168 printf ("// %s-%s-%s\n", "start", "sanitize", "tx19");
1169 /* end-sanitize-cygnus-never */
1170 /* start-sanitize-tx19 */
1171 printf ("*tx19:\n");
1172 /* end-sanitize-tx19 */
1173 /* start-sanitize-cygnus-never */
1174 printf ("// %s-%s-%s\n", "end", "sanitize", "tx19");
1175 /* end-sanitize-cygnus-never */
1178 /* processor specific ISAs */
1179 if ((isa
& ARCH_VR4100
))
1180 printf ("*vr4100:\n");
1181 /* start-sanitize-r5900 */
1182 if ((isa
& ARCH_R5900
))
1183 printf ("*r5900:\n");
1184 /* end-sanitize-r5900 */
1185 if ((isa
& ARCH_R3900
))
1186 printf ("*r3900:\n");
1190 /*---------------------------------------------------------------------------*/
1192 static int bitmap_val
PARAMS ((const char *, int, int));
1193 static void build_mips16_operands
PARAMS ((const char *));
1194 static void build_instruction
1195 PARAMS ((int, unsigned int, int, const struct instruction
*));
1197 /*---------------------------------------------------------------------------*/
1200 name_for_data_len( insn
)
1201 struct instruction
* insn
;
1203 if (GETDATASIZEINSN(insn
) == BYTE
)
1206 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1209 else if (GETDATASIZEINSN(insn
) == WORD
)
1212 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1213 return "DOUBLEWORD";
1215 /* start-sanitize-r5900 */
1216 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1219 /* end-sanitize-r5900 */
1225 letter_for_data_len( insn
)
1226 struct instruction
* insn
;
1228 if (GETDATASIZEINSN(insn
) == BYTE
)
1231 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1234 else if (GETDATASIZEINSN(insn
) == WORD
)
1237 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1240 /* start-sanitize-r5900 */
1241 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1244 /* end-sanitize-r5900 */
1250 type_for_data_len( insn
, is_signed
)
1251 struct instruction
* insn
;
1254 if (GETDATASIZEINSN(insn
) == BYTE
)
1255 return is_signed
? "int" : "unsigned int";
1257 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1258 return is_signed
? "int" : "unsigned int";
1260 else if (GETDATASIZEINSN(insn
) == WORD
)
1261 return is_signed
? "signed64" : "unsigned64";
1263 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1266 /* start-sanitize-r5900 */
1267 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1270 /* end-sanitize-r5900 */
1276 max_for_data_len( insn
)
1277 struct instruction
* insn
;
1279 if (GETDATASIZEINSN(insn
) == BYTE
)
1282 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1285 else if (GETDATASIZEINSN(insn
) == WORD
)
1286 return "(int)0x7FFFFFFF";
1288 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1291 /* start-sanitize-r5900 */
1292 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1295 /* end-sanitize-r5900 */
1301 min_for_data_len( insn
)
1302 struct instruction
* insn
;
1304 if (GETDATASIZEINSN(insn
) == BYTE
)
1307 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1310 else if (GETDATASIZEINSN(insn
) == WORD
)
1311 return "(int)0x80000000";
1313 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1316 /* start-sanitize-r5900 */
1317 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1320 /* end-sanitize-r5900 */
1326 umax_for_data_len( insn
)
1327 struct instruction
* insn
;
1329 if (GETDATASIZEINSN(insn
) == BYTE
)
1332 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1335 else if (GETDATASIZEINSN(insn
) == WORD
)
1336 return "0xFFFFFFFF";
1338 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1341 /* start-sanitize-r5900 */
1342 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1345 /* end-sanitize-r5900 */
1351 bits_for_data_len( insn
)
1352 struct instruction
* insn
;
1354 if (GETDATASIZEINSN(insn
) == BYTE
)
1357 else if (GETDATASIZEINSN(insn
) == HALFWORD
)
1360 else if (GETDATASIZEINSN(insn
) == WORD
)
1363 else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
)
1366 /* start-sanitize-r5900 */
1367 else if (GETDATASIZEINSN(insn
) == QUADWORD
)
1370 /* end-sanitize-r5900 */
1375 /*---------------------------------------------------------------------------*/
1379 convert_bitmap(bitmap
,onemask
,zeromask
,dontmask
)
1381 unsigned int *onemask
, *zeromask
, *dontmask
;
1383 int loop
; /* current bitmap position */
1384 int lastsp
= -1; /* last bitmap field starting position */
1385 int lastoe
= -1; /* last bitmap field encoding */
1387 *onemask
= 0x00000000;
1388 *zeromask
= 0x00000000;
1389 *dontmask
= 0x00000000;
1391 if (strlen(bitmap
) != 32) {
1392 fprintf(stderr
,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap
);
1396 for (loop
= 0; (loop
< 32); loop
++) {
1398 for (oefield
= 0; (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))); oefield
++)
1399 if (bitmap
[31 - loop
] == opfields
[oefield
].id
)
1401 if (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))) {
1402 if ((lastoe
!= -1) && (lastoe
!= oefield
))
1403 if ((loop
- lastsp
) != (opfields
[lastoe
].flen
)) {
1404 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
);
1408 switch (bitmap
[31 - loop
]) {
1409 case '0' : /* fixed value */
1410 *zeromask
|= (1 << loop
);
1415 case '1' : /* fixed value */
1416 *onemask
|= (1 << loop
);
1421 case '?' : /* fixed value */
1422 *dontmask
|= (1 << loop
);
1427 default : /* check character encoding */
1429 if (opfields
[oefield
].fpos
!= -1) {
1430 /* If flag not set, then check starting position: */
1431 if (lastoe
!= oefield
) {
1432 if (loop
!= opfields
[oefield
].fpos
) {
1433 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
);
1440 *dontmask
|= (1 << loop
);
1445 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
);
1450 /* NOTE: Since we check for the position and size of fields when
1451 parsing the "bitmap" above, we do *NOT* need to check that invalid
1452 field combinations have been used. */
1455 /* Get the value of a 16 bit bitstring for a given shift count and
1459 bitmap_val (bitmap
, shift
, bits
)
1468 s
= bitmap
+ 16 - shift
- bits
;
1469 for (; bits
> 0; --bits
)
1484 /*---------------------------------------------------------------------------*/
1487 build_operands(doisa
,features
,insn
)
1489 unsigned int features
;
1492 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
1493 int finish_jump_flag
= 0;
1495 int check_condition_code
= 0;
1496 int sfield_used
= 0;
1497 int gfield_used
= 0;
1498 int any_operand
= 0;
1500 int current_field_id
= -1;
1503 for (bitpos
=0; bitpos
<32; bitpos
++) {
1504 if (insn
->bitmap
[31-bitpos
] != current_field_id
)
1508 current_field_id
= insn
->bitmap
[31-bitpos
];
1510 for (opindex
= 0; (opindex
< (sizeof(opfields
) / sizeof(operand_encoding
))); opindex
++)
1511 if ((opfields
[opindex
].fpos
!= -1) && (opfields
[opindex
].id
== insn
->bitmap
[31-bitpos
])) {
1515 printf(" %s %s UNUSED = ",opfields
[opindex
].type
,opfields
[opindex
].name
);
1517 if (opfields
[opindex
].flags
& OP_SIGNX
)
1518 printf("SIGNEXTEND((%s)",opfields
[opindex
].type
);
1520 if (opfields
[opindex
].flags
& OP_GPR
)
1523 if (opfields
[opindex
].flags
& OP_SHIFT2
)
1526 printf("((instruction >> %d) & 0x%08X)",opfields
[opindex
].fpos
,((1 << opfields
[opindex
].flen
) - 1));
1528 if (opfields
[opindex
].flags
& OP_SHIFT2
)
1531 if (opfields
[opindex
].flags
& OP_GPR
)
1534 if (opfields
[opindex
].flags
& OP_BITS5
)
1537 if (opfields
[opindex
].flags
& OP_SIGNX
)
1538 printf(",%d)",(opfields
[opindex
].flen
+ ((opfields
[opindex
].flags
& OP_SHIFT2
) ? 2 : 0)));
1542 if (opfields
[opindex
].flags
& OP_GPR1
)
1544 printf(" %s %s1 = GPR1[",opfields
[opindex
].type
,opfields
[opindex
].name
);
1545 printf("((instruction >> %d) & 0x%08X)",
1546 opfields
[opindex
].fpos
,
1547 ((1 << opfields
[opindex
].flen
) - 1));
1551 if (opfields
[opindex
].id
== 'j')
1552 finish_jump_flag
= 1;
1554 if (opfields
[opindex
].id
== 'e')
1557 if (opfields
[opindex
].id
== 'w')
1560 if (opfields
[opindex
].id
== 'w')
1563 if (opfields
[opindex
].id
== 'p')
1564 check_condition_code
= 1;
1566 if (opfields
[opindex
].id
== 's')
1569 if (opfields
[opindex
].id
== 'g')
1575 if ( !any_operand
&& !(insn
->flags
& NOARG
)) {
1576 fprintf(stderr
,"Bitmap error: Instruction with no operand fields \"%s\"\n",insn
->name
) ;
1580 /* Finish constructing the jump address if required: */
1581 if (finish_jump_flag
)
1582 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
1584 /* Now perform required operand checks: */
1586 /* The following code has been removed, since it seems perfectly
1587 reasonable to have a non-aligned offset that is added to another
1588 non-aligned base to create an aligned address. Some more
1589 information on exactly what the MIPS IV specification requires is
1590 needed before deciding on the best strategy. Experimentation with a
1591 VR4300 suggests that we do not need to raise the warning. */
1593 /* For MIPS IV (and onwards), certain instruction operand values
1594 will give undefined results. For the simulator we could
1595 generate explicit exceptions (i.e. ReservedInstruction) to
1596 make it easier to spot invalid use. However, for the moment we
1597 just raise a warning. NOTE: This is a different check to the
1598 later decoding, which checks for the final address being
1601 if (check_mult
!= 0 && check_mult
!= 1) {
1602 printf(" if (instruction & 0x%1X)\n", check_mult
);
1604 /* NOTE: If we change this to a SignalException(), we must
1605 ensure that the following opcode processing is not
1606 executed. i.e. the code falls straight out to the simulator
1608 printf(" sim_io_eprintf(sd,\"Instruction has lo-order offset bits set in instruction\\n\");\n");
1613 /* The extended condition codes only appeared in ISA IV */
1614 if (check_condition_code
&& (doisa
< 4)) {
1615 printf(" if (condition_code != 0)\n");
1617 printf(" SignalException(ReservedInstruction,instruction);\n");
1622 if ((insn
->flags
& WORD32
) && (GETDATASIZEINSN(insn
) != WORD
)) {
1623 fprintf(stderr
,"Error in opcode table: WORD32 set for non-WORD opcode\n");
1628 /* The R4000 book differs slightly from the MIPS IV ISA
1629 manual. An example is the sign-extension of a 64-bit processor
1630 SUBU operation, and what is meant by an Undefined Result. This
1631 is now provided purely as a warning. After examining a HW
1632 implementation, this is now purely a warning... and the actual
1633 operation is performed, with possibly undefined results. */
1634 if (((insn
->flags
& WORD32
) && proc64
) && (features
& FEATURE_WARN_RESULT
)) {
1635 /* The compiler should optimise out an OR with zero */
1636 printf(" if (%s | %s)\n",(sfield_used
? "NOTWORDVALUE(op1)" : "0"),(gfield_used
? "NOTWORDVALUE(op2)" : "0"));
1637 printf(" UndefinedResult();\n") ;
1640 /* Check that the source is a 32bit value */
1641 if ((insn
->flags
& WORD32
) && proc64
) {
1642 /* The compiler should optimise out an OR with zero */
1643 printf(" if (%s | %s)\n",(sfield_used
? "NOTWORDVALUE(op1)" : "0"),(gfield_used
? "NOTWORDVALUE(op2)" : "0"));
1644 printf(" UndefinedResult();\n") ;
1652 /* The mips16 operand table. */
1656 /* The character which appears in the bitmap string. */
1658 /* The type of the variable in the simulator. */
1659 const char *vartype
;
1660 /* The name of the variable in the simulator. */
1662 /* The number of bits. */
1664 /* The number of bits when extended (zero if can not be extended). */
1666 /* The amount by which the short form is shifted when it is used;
1667 for example, the sw instruction has a shift count of 2. */
1673 /* Flags which appears in the mips16 operand table. */
1675 /* Whether this is a mips16 register index. */
1676 #define MIPS16_REG16 (0x1)
1677 /* Whether this is a register value. */
1678 #define MIPS16_REGVAL (0x2)
1679 /* Whether this is a swapped mips32 register index (MOV32R) */
1680 #define MIPS16_REG32_SWAPPED (0x4)
1681 /* Whether this index is also the destination register. */
1682 #define MIPS16_DESTREG (0x8)
1683 /* Whether the short form is unsigned. */
1684 #define MIPS16_UNSP (0x10)
1685 /* Whether the extended form is unsigned. */
1686 #define MIPS16_EXTU (0x20)
1687 /* Implicit stack pointer. */
1688 #define MIPS16_SP (0x40)
1689 /* Implicit program counter. */
1690 #define MIPS16_PC (0x80)
1692 #define MIPS16_ZERO (0x100)
1694 #define MIPS16_TREG (0x200)
1696 #define MIPS16_RA (0x400)
1698 #define MIPS16_JUMP_ADDR (0x800)
1699 /* Branch offset. */
1700 #define MIPS16_BRANCH (0x1000)
1702 /* The mips16 operand table. */
1704 static const struct mips16_op mips16_op_table
[] =
1706 { 'd', "int", "destreg", 3, 0, 0, MIPS16_REG16
},
1707 { 'x', "t_reg", "op1", 3, 0, 0, MIPS16_REG16
| MIPS16_REGVAL
},
1708 { 'w', "t_reg", "op1", 3, 0, 0, MIPS16_REG16
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1709 { 'y', "t_reg", "op2", 3, 0, 0, MIPS16_REG16
| MIPS16_REGVAL
},
1710 { 'v', "t_reg", "op2", 3, 0, 0, MIPS16_REG16
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1711 { 'X', "t_reg", "op1", 5, 0, 0, MIPS16_REGVAL
},
1712 { 'Y', "int", "destreg", 5, 0, 0, MIPS16_REG32_SWAPPED
},
1713 { 'a', "ut_reg", "op1", 11, 0, 0, MIPS16_JUMP_ADDR
},
1714 { 'e', "int", "ext", 11, 0, 0, 0 },
1715 { '<', "int", "op1", 3, 5, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1716 { '>', "int", "op1", 3, 5, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1717 { '[', "int", "op1", 3, 6, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1718 { ']', "int", "op1", 3, 6, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1719 { '4', "int", "op2", 4, 15, 0, 0 },
1720 { '5', "int", "offset", 5, 16, 0, MIPS16_UNSP
},
1721 { 'H', "int", "offset", 5, 16, 1, MIPS16_UNSP
},
1722 { 'W', "int", "offset", 5, 16, 2, MIPS16_UNSP
},
1723 { 'D', "int", "offset", 5, 16, 3, MIPS16_UNSP
},
1724 { 'j', "int", "op2", 5, 16, 0, 0 },
1725 { '8', "int", "op2", 8, 16, 0, MIPS16_UNSP
},
1726 { 'V', "int", "offset", 8, 16, 2, MIPS16_UNSP
},
1727 { 'C', "int", "offset", 8, 16, 3, MIPS16_UNSP
},
1728 { 'U', "int", "op2", 8, 16, 0, MIPS16_UNSP
| MIPS16_EXTU
},
1729 { 'k', "int", "op2", 8, 16, 0, 0 },
1730 { 'K', "int", "op2", 8, 16, 3, 0 },
1731 { 'p', "int", "offset", 8, 16, 0, MIPS16_BRANCH
},
1732 { 'q', "int", "offset", 11, 16, 0, MIPS16_BRANCH
},
1733 { 'A', "int", "op2", 8, 16, 2, MIPS16_UNSP
},
1734 { 'B', "int", "op2", 5, 16, 3, MIPS16_UNSP
},
1735 { 'E', "int", "op2", 5, 16, 2, MIPS16_UNSP
},
1737 /* The remaining operands are special operands which encode implied
1738 arguments. These only appear at the end of a bitmap string, and
1739 do not represent actual bits. */
1740 { 's', "t_reg", "op1", 0, 0, 0, MIPS16_SP
| MIPS16_REGVAL
},
1741 { 'S', "t_reg", "op1", 0, 0, 0, MIPS16_SP
|MIPS16_REGVAL
|MIPS16_DESTREG
},
1742 { 'P', "t_reg", "op1", 0, 0, 0, MIPS16_PC
},
1743 { 'z', "t_reg", "op2", 0, 0, 0, MIPS16_ZERO
},
1744 { 'Z', "t_reg", "op1", 0, 0, 0, MIPS16_ZERO
},
1745 { 't', "t_reg", "op1", 0, 0, 0, MIPS16_TREG
| MIPS16_REGVAL
},
1746 { 'T', "int", "destreg", 0, 0, 0, MIPS16_TREG
},
1747 { 'r', "t_reg", "op1", 0, 0, 0, MIPS16_RA
| MIPS16_REGVAL
},
1748 { 'R', "int", "destreg", 0, 0, 0, MIPS16_RA
},
1749 { 'Q', "t_reg", "op2", 0, 0, 0, MIPS16_RA
| MIPS16_REGVAL
},
1751 { '\0', NULL
, NULL
, 0, 0, 0, 0 }
1754 /* Build mips16 operands. */
1757 build_mips16_operands (bitmap
)
1762 const struct mips16_op
*op
= NULL
;
1763 const struct mips16_op
*ops
[3];
1767 for (s
= bitmap
; *s
!= '\0'; s
++)
1774 /* Make sure we saw the right number of bits for that
1776 if (op
->nbits
!= 0 && (s
- bitmap
) - op
->nbits
!= start
)
1781 if (*s
== '0' || *s
== '1' || *s
== '?')
1786 for (op
= mips16_op_table
; op
->type
!= *s
; ++op
)
1787 if (op
->type
== '\0')
1790 printf (" %s %s = ", op
->vartype
, op
->name
);
1792 printf ("(instruction >> %d) & 0x%x",
1793 16 - (s
- bitmap
) - op
->nbits
,
1794 (1 << op
->nbits
) - 1);
1797 if ((op
->flags
& MIPS16_SP
) != 0)
1799 else if ((op
->flags
& MIPS16_PC
) != 0)
1803 printf ("((INDELAYSLOT () ? (INJALDELAYSLOT () ? cia - 4 : cia - 2) : (have_extendval ? cia - 2 : cia)) & ~ (uword64) 1)");
1804 for (j
= 0; j
< opindex
; j
++)
1805 if (ops
[j
]->shift
!= 0)
1806 printf (" & ~ (uword64) 0x%x", (1 << ops
[j
]->shift
) - 1);
1808 else if ((op
->flags
& MIPS16_ZERO
) != 0)
1810 else if ((op
->flags
& MIPS16_TREG
) != 0)
1812 else if ((op
->flags
& MIPS16_RA
) != 0)
1819 if ((op
->flags
& MIPS16_DESTREG
) != 0)
1820 printf (" int destreg;\n");
1830 /* Make sure we saw the right number of bits for that
1832 if (op
->nbits
!= 0 && 16 - op
->nbits
!= start
)
1836 for (i
= 0; i
< opindex
; i
++)
1839 if ((op
->flags
& MIPS16_REG16
) != 0)
1841 printf (" if (%s < 2)\n", op
->name
);
1842 printf (" %s += 16;\n", op
->name
);
1844 if ((op
->flags
& MIPS16_REG32_SWAPPED
) != 0)
1845 printf (" %s = (%s >> 2) | ((%s & 3) << 3);\n",
1846 op
->name
, op
->name
, op
->name
);
1847 if ((op
->flags
& MIPS16_DESTREG
) != 0)
1848 printf (" destreg = %s;\n", op
->name
);
1849 if ((op
->flags
& MIPS16_REGVAL
) != 0)
1850 printf (" %s = GPR[%s];\n", op
->name
, op
->name
);
1852 if (op
->extbits
!= 0)
1854 printf (" if (have_extendval)\n");
1856 if (op
->extbits
== 16)
1857 printf (" %s |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0);\n",
1859 else if (op
->extbits
== 15)
1860 printf (" %s |= ((extendval & 0xf) << 11) | (extendval & 0x7f0);\n",
1862 else if (op
->extbits
== 6)
1863 printf (" %s = ((extendval >> 6) & 0x1f) | (extendval & 0x20);\n",
1866 printf (" %s = (extendval >> 6) & 0x1f;\n",
1868 if ((op
->flags
& MIPS16_EXTU
) == 0)
1870 printf (" if (%s >= 0x%x)\n",
1871 op
->name
, 1 << (op
->extbits
- 1));
1872 printf (" %s -= 0x%x;\n",
1873 op
->name
, 1 << op
->extbits
);
1875 printf (" have_extendval = 0;\n");
1879 if ((op
->flags
& MIPS16_UNSP
) == 0)
1881 printf (" if (%s >= 0x%x)\n",
1882 op
->name
, 1 << (op
->nbits
- 1));
1883 printf (" %s -= 0x%x;\n",
1884 op
->name
, 1 << op
->nbits
);
1887 printf (" %s <<= %d;\n", op
->name
, op
->shift
);
1888 if (op
->type
== '<' || op
->type
== '>'
1889 || op
->type
== '[' || op
->type
== ']')
1891 printf (" if (%s == 0)\n", op
->name
);
1892 printf (" %s = 8;\n", op
->name
);
1897 if ((op
->flags
& MIPS16_BRANCH
) != 0)
1898 printf (" %s *= 2;\n", op
->name
);
1900 if ((op
->flags
& MIPS16_JUMP_ADDR
) != 0)
1903 printf (" address_word paddr;\n");
1904 printf (" int uncached;\n");
1905 printf (" if (AddressTranslation (PC &~ (uword64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL))\n");
1907 printf (" uword64 memval;\n");
1908 printf (" unsigned int reverse = (ReverseEndian ? 3 : 0);\n");
1909 printf (" unsigned int bigend = (BigEndianCPU ? 3 : 0);\n");
1910 printf (" unsigned int byte;\n");
1911 printf (" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\n");
1912 printf (" LoadMemory (&memval,0,uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
1913 printf (" byte = (((PC &~ (uword64) 1) & 0x7) ^ (bigend << 1));\n");
1914 printf (" memval = (memval >> (8 * byte)) & 0xffff;\n");
1915 printf (" %s = (((%s & 0x1f) << 23)\n", op
->name
, op
->name
);
1916 printf (" | ((%s & 0x3e0) << 13)\n", op
->name
);
1917 printf (" | (memval << 2));\n");
1918 printf (" if ((instruction & 0x400) == 0)\n");
1919 printf (" %s |= 1;\n", op
->name
);
1920 printf (" PC += 2;\n");
1923 printf (" %s |= PC & ~ (uword64) 0x0fffffff;\n", op
->name
);
1927 /* FIXME: Is this the way to detect an unused extend opcode? */
1928 printf (" if (have_extendval)\n");
1929 printf (" SignalException (ReservedInstruction, instruction);\n");
1932 /*---------------------------------------------------------------------------*/
1940 build_endian_shift(proc64
,datalen
,endbit
,direction
,shift
)
1944 e_endshift direction
;
1948 printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit
,endbit
);
1949 printf(" memval %s= %d;\n",direction
== s_left
? "<<" : ">>",shift
);
1956 /*---------------------------------------------------------------------------*/
1957 /* doisa = number of MIPS ISA simulator table is being constructed for.
1958 * proc64 = TRUE if constructing 64bit processor world.
1959 * dofp = boolean, TRUE if FP instructions are to be included.
1960 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
1964 process_instructions(doarch
,features
)
1965 unsigned int doarch
;
1966 unsigned int features
;
1968 int doisa
= (doarch
& MASK_ISA
);
1969 int limit
= (sizeof(MIPS_DECODE
) / sizeof(instruction
));
1970 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
1971 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
1972 int dofp
= (features
& FEATURE_HASFPU
);
1973 int fpsingle
= (features
& FEATURE_FPSINGLE
);
1978 fprintf(stderr
,"process_instructions: invalid structure length\n");
1982 if (proc64
&& (gprlen
!= 64)) {
1983 fprintf(stderr
,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
1987 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
1990 for (loop
= 0; (loop
< limit
); loop
++)
1991 if ((MIPS_DECODE
[loop
].isa
& MASK_ISA
) > maxisa
)
1992 maxisa
= (MIPS_DECODE
[loop
].isa
& MASK_ISA
);
1997 if (!(features
& FEATURE_IGEN
))
1999 printf("#if defined(SIM_MANIFESTS)\n");
2000 printf("#define MIPSISA (%d)\n",doisa
);
2002 printf("#define PROCESSOR_64BIT (1 == 1)\n");
2004 printf("#define PROCESSOR_64BIT (1 == 0)\n");
2005 #if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */
2006 printf("#define LOADDRMASK (0x%08X)\n",0x7);
2008 printf("#define LOADDRMASK (0x%08X)\n",(proc64
? 0x7 : 0x3));
2010 /* The FP registers are the same width as the CPU registers: */
2011 printf("#define GPRLEN (%d)\n",gprlen
);
2012 printf("typedef %s t_reg;\n",((gprlen
== 64) ? "word64" : "int"));
2013 printf("typedef %s ut_reg;\n",((gprlen
== 64) ? "uword64" : "unsigned int"));
2014 printf("typedef %s t_fpreg;\n",((gprlen
== 64) ? "word64" : "int"));
2016 printf("#define HASFPU (1 == 1)\n");
2017 if (features
& FEATURE_FAST
)
2018 printf("#define FASTSIM (1 == 1)\n");
2019 if (features
& FEATURE_WARN_STALL
)
2020 printf("#define WARN_STALL (1 == 1)\n");
2021 if (features
& FEATURE_WARN_LOHI
)
2022 printf("#define WARN_LOHI (1 == 1)\n");
2023 if (features
& FEATURE_WARN_ZERO
)
2024 printf("#define WARN_ZERO (1 == 1)\n");
2025 if (features
& FEATURE_WARN_MEM
)
2026 printf("#define WARN_MEM (1 == 1)\n");
2027 if (features
& FEATURE_WARN_R31
)
2028 printf("#define WARN_R31 (1 == 1)\n");
2029 if (features
& FEATURE_WARN_RESULT
)
2030 printf("#define WARN_RESULT (1 == 1)\n");
2032 printf("#else /* simulator engine */\n");
2034 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
2035 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64
? 64 : 32),doisa
,limit
);
2037 printf("/* %sFP instructions included */\n",(fpsingle
? "Single precision " : ""));
2038 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
2041 printf("#if !defined(PROCESSOR_64BIT)\n");
2042 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
2046 printf("/* Actual instruction decoding block */\n");
2047 printf("if ((vaddr & 1) == 0){\n");
2050 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP
,OP_MASK_OP
);
2051 limit
= (OP_MASK_OP
+ 1);
2053 printf("#ifdef DEBUG\n");
2054 printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n");
2057 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
2058 limit
+= (OP_MASK_SPEC
+ 1);
2060 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_RT
,OP_MASK_RT
);
2061 limit
+= (OP_MASK_RT
+ 1);
2063 printf("else if (num == 0x11) {\n");
2064 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM
,OP_SH_COP1NORM
,(OP_MASK_COP1NORM
<< OP_SH_COP1NORM
));
2065 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP
,OP_SH_COP1CMP
,(OP_MASK_COP1CMP
<< OP_SH_COP1CMP
));
2066 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,(OP_MASK_SPEC
& (OP_MASK_COP1CMP
<< OP_SH_COP1CMP
)));
2068 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
2069 limit
+= (OP_MASK_SPEC
+ 1);
2072 /* To keep this code quick, we just clear out the "to" bit
2073 here. The proper (though slower) code would be to have another
2074 conditional, checking whether this instruction is a branch or
2075 not, before limiting the range to the bottom two bits of the
2077 printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit
,OP_SH_COP1SPEC
,OP_MASK_COP1SPEC
,OP_MASK_COP1SCLR
);
2078 limit
+= (OP_MASK_COP1SPEC
+ 1);
2080 printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
2081 limit
+= (OP_MASK_SPEC
+ 1);
2083 printf("else if (num == 0x1C) {\n");
2084 printf(" int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI
,OP_MASK_MMI
);
2086 printf(" if (mmi_func == 0x08) \n");
2087 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
2088 limit
+= (OP_MASK_MMISUB
+ 1);
2090 printf(" else if (mmi_func == 0x28) \n");
2091 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
2092 limit
+= (OP_MASK_MMISUB
+ 1);
2094 printf(" else if (mmi_func == 0x09) \n");
2095 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
2096 limit
+= (OP_MASK_MMISUB
+ 1);
2098 printf(" else if (mmi_func == 0x29) \n");
2099 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_MMISUB
,OP_MASK_MMISUB
);
2100 limit
+= (OP_MASK_MMISUB
+ 1);
2103 printf(" num = (%d + mmi_func);\n",limit
);
2104 limit
+= (OP_MASK_MMI
+ 1);
2108 printf("/* Total possible switch entries: %d */\n",limit
) ;
2111 printf("#ifdef DEBUG\n");
2112 printf("printf(\"DBG: num = %%d\\n\",num);\n");
2115 printf("switch (num)\n") ;
2119 for (loop
= 0; (loop
< limit
); loop
++) {
2120 /* First check if the insn is in a requested isa# independent set,
2121 then check that the ISA number we are constructing for is
2122 valid, then if the instruction matches any of the
2123 architecture specific flags. NOTE: We allow a selected ISA of
2124 zero to be used to match all standard instructions. */
2125 unsigned int isa
= MIPS_DECODE
[loop
].isa
;
2126 if (((isa
& doarch
& MASK_ISA_INDEP
)
2127 || (((isa
& MASK_ISA
) <= doisa
)
2128 && (((isa
& MASK_ISA_DEP
) == 0) || ((isa
& MASK_ISA_DEP
) & doarch
) != 0)))
2129 && (!(MIPS_DECODE
[loop
].flags
& FP
) || ((MIPS_DECODE
[loop
].flags
& FP
) && dofp
))
2130 || (features
& FEATURE_IGEN
)) {
2131 unsigned int onemask
;
2132 unsigned int zeromask
;
2133 unsigned int dontmask
;
2135 unsigned int number
;
2137 convert_bitmap(MIPS_DECODE
[loop
].bitmap
,&onemask
,&zeromask
,&dontmask
);
2139 if (!(MIPS_DECODE
[loop
].flags
& COPROC
)
2140 && ((GETDATASIZEINSN(&MIPS_DECODE
[loop
]) == DOUBLEWORD
) && !proc64
)
2141 && !(features
& FEATURE_IGEN
)) {
2142 fprintf(stderr
,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE
[loop
].name
);
2147 printf("/* DEBUG: onemask 0x%08X */\n",onemask
) ;
2148 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask
) ;
2149 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask
) ;
2152 switch (MIPS_DECODE
[loop
].mark
) {
2154 mask
= (OP_MASK_OP
<< OP_SH_OP
) ;
2155 number
= ((onemask
>> OP_SH_OP
) & OP_MASK_OP
) ;
2159 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
2160 number
= ((OP_MASK_OP
+ 1) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
2164 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_RT
<< OP_SH_RT
)) ;
2165 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_RT
) & OP_MASK_RT
)) ;
2169 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
2170 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
2174 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_COP1SPEC
<< OP_SH_COP1SPEC
)) ;
2175 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_COP1SPEC
) & OP_MASK_COP1SPEC
)) ;
2179 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
2180 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
)) ;
2184 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
2185 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
2186 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
2187 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
2188 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
2192 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
2193 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
2194 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
2195 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
2196 + (OP_MASK_MMISUB
+ 1)
2197 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
2201 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
2202 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
2203 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
2204 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
2205 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
2206 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
2210 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)
2211 | (OP_MASK_MMISUB
<< OP_SH_MMISUB
));
2212 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
2213 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
2214 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
2215 + ((onemask
>> OP_SH_MMISUB
) & OP_MASK_MMISUB
)) ;
2219 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_MMI
<< OP_SH_MMI
)) ;
2220 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)
2221 + (OP_MASK_SPEC
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1))
2222 + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1) + (OP_MASK_MMISUB
+ 1)
2223 + (OP_MASK_MMISUB
+ 1)
2224 + ((onemask
>> OP_SH_MMI
) & OP_MASK_MMI
)) ;
2228 fprintf(stderr
,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE
[loop
].mark
,loop
,MIPS_DECODE
[loop
].name
) ;
2232 if (!(features
& FEATURE_IGEN
))
2234 printf("case %d : /* \"%s\" %s */\n",number
,MIPS_DECODE
[loop
].name
,MIPS_DECODE
[loop
].bitmap
) ;
2237 printf("/* DEBUG: mask 0x%08X */\n",mask
) ;
2238 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE
[loop
].name
);
2241 /* Check if there are any other explicit bits in the instruction: */
2242 if ((~mask
& (onemask
| zeromask
)) != 0x00000000) {
2243 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask
| zeromask
),onemask
) ;
2245 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2254 /* start-sanitize-cygnus-never */
2255 /* If any sanitization occures, this line should be printed */
2256 if ((MIPS_DECODE
[loop
].isa
& ARCH_R5900
))
2257 printf ("// %s-%s-%s\n", "start", "sanitize", "r5900");
2258 /* end-sanitize-cygnus-never */
2260 print_igen_insn_format (MIPS_DECODE
[loop
].bitmap
,
2261 MIPS_DECODE
[loop
].mark
, /* format-name */
2262 GETDATASIZEINSN (&MIPS_DECODE
[loop
]), /* filter-flags */
2264 MIPS_DECODE
[loop
].name
);
2265 print_igen_insn_models (MIPS_DECODE
[loop
].isa
);
2267 printf (" unsigned32 instruction = instruction_0;\n");
2270 /* Get hold of the operands */
2271 /* NOTE: If we wanted to make the simulator code smaller, we
2272 * could pull these into a common sequence before we perform
2273 * the instruction decoding. However, this would affect the
2274 * performance since unnecessary field extraction would be
2275 * occurring for certain instructions.
2277 * Also we do not perform checking for multiple definitions of a
2278 * particular operand here, since they are caught by the
2279 * compilation of the produced code.
2281 build_operands(doisa
, features
, &MIPS_DECODE
[loop
]);
2285 build_instruction (doisa
, features
, 0, &MIPS_DECODE
[loop
]);
2288 if (!(features
& FEATURE_IGEN
))
2291 printf(" break ;\n") ;
2297 /* start-sanitize-cygnus-never */
2298 /* When sanitized, this output should never be produced */
2299 if ((MIPS_DECODE
[loop
].isa
& ARCH_R5900
))
2300 printf ("// %s-%s-%s\n", "end", "sanitize", "r5900");
2301 /* end-sanitize-cygnus-never */
2308 if (!(features
& FEATURE_IGEN
))
2310 printf("default : /* Unrecognised instruction */\n") ;
2311 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2312 printf(" break ;\n") ;
2316 /* Handle mips16 instructions. The switch table looks like this:
2317 0 - 31: I, RI, and RRI instructions by major.
2318 32 - 35: ISHIFT instructions by function + 32
2319 36 - 37: RRI_A instructions by function + 36
2320 38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38
2321 46 - 49: RRR instructions by function + 46
2322 50 - 81: RR instructions by minor + 50 (except for minor == 0)
2323 82 - 89: I64 and RI64 instructions by funct + 82
2324 90 - 97: jalr (RR minor 0) by y + 90
2326 if (!(features
& FEATURE_IGEN
))
2328 printf ("else {\n");
2329 printf ("static int extendval;\n");
2330 printf ("static int have_extendval;\n");
2331 printf ("int num = ((instruction >> %d) & 0x%08X);\n",
2332 MIPS16OP_SH_OP
, MIPS16OP_MASK_OP
);
2333 printf ("switch (num)\n{\n");
2334 printf ("case 0x6: num = 32 + (instruction & 3); break;\n");
2335 printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n");
2336 printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n");
2337 printf ("case 0x1c: num = 46 + (instruction & 3); break;\n");
2338 printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n");
2339 printf (" if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n");
2340 printf (" break;\n");
2341 printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n");
2342 printf ("default: break;\n}\n");
2343 printf ("switch (num)\n{\n");
2346 for (loop
= 0; loop
< sizeof MIPS16_DECODE
/ sizeof MIPS16_DECODE
[0]; loop
++)
2351 if (! proc64
&& GETDATASIZEINSN (&MIPS16_DECODE
[loop
]) == DOUBLEWORD
)
2354 bitmap
= MIPS16_DECODE
[loop
].bitmap
;
2355 switch (MIPS16_DECODE
[loop
].mark
)
2360 num
= bitmap_val (bitmap
, 11, 5);
2363 num
= 32 + bitmap_val (bitmap
, 0, 2);
2366 num
= 36 + bitmap_val (bitmap
, 4, 1);
2371 num
= 38 + bitmap_val (bitmap
, 8, 3);
2374 num
= 46 + bitmap_val (bitmap
, 0, 2);
2380 minor
= bitmap_val (bitmap
, 0, 5);
2384 num
= 90 + bitmap_val (bitmap
, 5, 3);
2389 num
= 82 + bitmap_val (bitmap
, 8, 3);
2396 if (!(features
& FEATURE_IGEN
))
2398 printf ("case %d: /* \"%s\" %s */\n", num
, MIPS16_DECODE
[loop
].name
,
2405 print_igen_insn_format (bitmap
,
2406 MIPS16_DECODE
[loop
].mark
, /* format-name */
2407 -1, /* filter-flags -- -1 => MIPS16 */
2409 MIPS16_DECODE
[loop
].name
);
2410 printf ("*mips16:\n");
2412 printf (" unsigned32 instruction = instruction_0;\n");
2415 build_mips16_operands (bitmap
);
2419 /* build_instruction doesn't know about extend. */
2421 build_instruction (doisa
, features
, 1, &MIPS16_DECODE
[loop
]);
2424 printf (" extendval = ext;\n");
2425 printf (" have_extendval = 1;\n");
2429 if (!(features
& FEATURE_IGEN
))
2432 printf (" break ;\n") ;
2441 if (!(features
& FEATURE_IGEN
))
2443 printf ("default : /* Unrecognised instruction */\n") ;
2444 printf (" SignalException(ReservedInstruction,instruction);\n") ;
2445 printf (" break ;\n") ;
2448 printf("#endif /* simulator engine */\n");
2454 /* Output the code to execute an instruction, assuming the operands
2455 have already been extracted. */
2458 build_instruction (doisa
, features
, mips16
, insn
)
2460 unsigned int features
;
2462 const struct instruction
*insn
;
2464 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
2465 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
2466 char *regtype
= ((gprlen
== 64) ? "uword64" : "unsigned int");
2468 switch (insn
->type
) {
2469 /* TODO: To make these easier to edit and maintain, they should
2470 actually be provided as source macros (or inline functions)
2471 OUTSIDE this main switch statement. The PPC simulator has a
2472 neater scheme for describing the instruction sequences. */
2477 char *signed_basetype
= "unknown";
2478 char *unsigned_basetype
= "unknown";
2480 switch (GETDATASIZEINSN(insn
)) {
2482 signed_basetype
= "signed int";
2483 unsigned_basetype
= "unsigned int";
2486 signed_basetype
= "word64";
2487 unsigned_basetype
= "uword64";
2490 fprintf(stderr
,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZEINSN(insn
));
2494 if ((insn
->type
) == ADD
) {
2495 printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype
, unsigned_basetype
);
2496 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype
, signed_basetype
);
2497 if (insn
->flags
& OVERFLOW
) {
2498 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
2499 printf(" SignalExceptionIntegerOverflow ();\n");
2502 if (!proc64
|| (insn
->flags
& UNSIGNED
) || (GETDATASIZEINSN(insn
) == DOUBLEWORD
))
2503 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
2504 else /* only sign-extend when placing 32bit result in 64bit processor */
2505 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
2507 printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype
, unsigned_basetype
);
2508 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype
, signed_basetype
);
2509 if (insn
->flags
& OVERFLOW
) { /* different signs => overflow if result_sign != arg_sign */
2510 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
2511 printf(" SignalExceptionIntegerOverflow ();\n");
2514 /* UNSIGNED 32bit operations on a 64bit processor should
2515 *STILL* be sign-extended. We have cheated in the
2516 data-structure, by not marking it with UNSIGNED, and not
2517 setting OVERFLOW. */
2518 if (!proc64
|| (insn
->flags
& UNSIGNED
) || (GETDATASIZEINSN(insn
) == DOUBLEWORD
))
2519 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
2520 else /* only sign-extend when placing 32bit result in 64bit processor */
2521 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
2528 char* pipe
= (insn
->flags
& PIPE1
) ? "1" : "";
2531 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2532 printf(" uword64 mid;\n");
2533 printf(" uword64 midhi;\n");
2534 printf(" uword64 temp;\n");
2535 if ((insn
->flags
& UNSIGNED
) == 0)
2537 printf(" int sign = 0;\n");
2538 printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n");
2539 printf(" if (op2 < 0) { op2 = - op2; ++sign; }\n");
2541 printf(" LO%s = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n",pipe
);
2542 printf(" HI%s = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n",pipe
);
2543 printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
2544 printf(" midhi = SET64HI(WORD64LO(mid));\n");
2545 printf(" temp = (LO%s + midhi);\n",pipe
);
2546 printf(" if ((temp == midhi) ? (LO%s != 0) : (temp < midhi))\n",pipe
);
2547 printf(" HI%s += 1;\n",pipe
);
2548 printf(" HI%s += WORD64HI(mid);\n",pipe
);
2549 printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
2550 printf(" midhi = SET64HI(WORD64LO(mid));\n");
2551 printf(" LO%s = (temp + midhi);\n",pipe
);
2552 printf(" if ((LO%s == midhi) ? (temp != 0) : (LO%s < midhi))\n",pipe
,pipe
);
2553 printf(" HI%s += 1;\n",pipe
);
2554 printf(" HI%s += WORD64HI(mid);\n",pipe
);
2555 if ((insn
->flags
& UNSIGNED
) == 0)
2556 printf(" if (sign & 1) { LO%s = - LO%s; HI%s = (LO%s == 0 ? 0 : -1) - HI%s; }\n",pipe
,pipe
,pipe
,pipe
,pipe
);
2558 if (insn
->flags
& UNSIGNED
)
2559 printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
2561 printf(" uword64 temp = ((word64) op1 * (word64) op2);\n");
2562 printf(" LO%s = SIGNEXTEND((%s)WORD64LO(temp),32);\n",pipe
,regtype
);
2563 printf(" HI%s = SIGNEXTEND((%s)WORD64HI(temp),32);\n",pipe
,regtype
);
2565 if (insn
->flags
& OP3
)
2567 printf(" if ( destreg != 0 )\n");
2568 printf(" GPR[destreg] = LO%s;\n",pipe
);
2575 int boolU
= (insn
->flags
& UNSIGNED
);
2576 char* pipe
= (insn
->flags
& PIPE1
) ? "1" : "";
2580 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2581 printf(" %sword64 d1 = op1;\n", (boolU
? "u" : ""));
2582 printf(" %sword64 d2 = op2;\n", (boolU
? "u" : ""));
2583 printf(" if (d2 == 0)\n");
2585 printf(" LO%s = SIGNED64 (0x8000000000000000);\n", pipe
);
2586 printf(" HI%s = 0;\n", pipe
);
2588 printf(" else if (d2 == -1 && d1 == SIGNED64 (0x8000000000000000))\n");
2590 printf(" LO%s = SIGNED64 (0x8000000000000000);\n", pipe
);
2591 printf(" HI%s = 0;\n", pipe
);
2595 printf(" LO%s = (d1 / d2);\n", pipe
);
2596 printf(" HI%s = (d1 %% d2);\n", pipe
);
2599 printf(" %sint d1 = op1;\n", (boolU
? "unsigned " : ""));
2600 printf(" %sint d2 = op2;\n", (boolU
? "unsigned " : ""));
2601 printf(" if (d2 == 0)\n");
2603 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe
);
2604 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe
);
2606 printf(" else if (d2 == -1 && d1 == 0x80000000)\n");
2608 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe
);
2609 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe
);
2613 printf(" LO%s = SIGNEXTEND((d1 / d2),32);\n", pipe
);
2614 printf(" HI%s = SIGNEXTEND((d1 %% d2),32);\n", pipe
);
2623 int datalen
= GETDATASIZEINSN(insn
);
2624 int bits
= ((datalen
== WORD
) ? 32 : 64);
2625 char *ltype
= ((datalen
== WORD
) ? "unsigned int" : "uword64");
2627 /* Check that the specified SHIFT is valid: */
2628 if ((datalen
== BYTE
) || (datalen
== HALFWORD
)) {
2629 fprintf(stderr
,"Shift \"%s\" specified with BYTE or HALFWORD\n",insn
->name
);
2632 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
2633 fprintf(stderr
,"Shift \"%s\" specified with both LEFT and RIGHT\n",insn
->name
);
2636 if (!(insn
->flags
& LEFT
) && !(insn
->flags
& RIGHT
)) {
2637 fprintf(stderr
,"Shift \"%s\" specified with neither LEFT or RIGHT\n",insn
->name
);
2640 if ((insn
->flags
& LOGICAL
) && (insn
->flags
& ARITHMETIC
)) {
2641 fprintf(stderr
,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",insn
->name
);
2644 if (!(insn
->flags
& LOGICAL
) && !(insn
->flags
& ARITHMETIC
)) {
2645 fprintf(stderr
,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",insn
->name
);
2648 if ((insn
->flags
& LEFT
) && (insn
->flags
& ARITHMETIC
)) {
2649 fprintf(stderr
,"Arithmetic LEFT shift \"%s\" specified\n",insn
->name
);
2653 /* Work around an MSC code generation bug by precomputing a value
2654 * with the sign bit set. */
2655 if (insn
->flags
& ARITHMETIC
)
2656 printf(" %s highbit = (%s)1 << %d;\n", ltype
, ltype
, bits
- 1);
2658 /* If register specified shift, then extract the relevant shift amount: */
2659 if (insn
->flags
& REG
)
2660 printf(" op1 &= 0x%02X;\n",(bits
- 1));
2662 /* If HI32 specified, then shift range is 32..63 */
2663 if (insn
->flags
& HI32
)
2664 printf(" op1 |= (1 << 5);\n");
2666 /* We do not need to perform pre-masking with 0xFFFFFFFF when
2667 dealing with 32bit shift lefts, since the sign-extension
2668 code will replace any remaining hi-bits: */
2669 if (insn
->flags
& LEFT
)
2670 printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
2672 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits
== 32) ? " & 0xFFFFFFFF" : ""));
2674 /* For ARITHMETIC shifts, we must duplicate the sign-bit. We
2675 don't do this if op1 is zero, since it is not needed and
2676 since that would cause an undefined shift of the number of
2677 bits in the type. */
2678 if (insn
->flags
& ARITHMETIC
)
2679 printf(" GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype
,bits
);
2681 /* Ensure WORD values are sign-extended into 64bit registers */
2682 if ((bits
== 32) && (gprlen
== 64))
2683 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits
);
2688 if (insn
->flags
& (HI
| LO
)) {
2689 char *regname
= ((insn
->flags
& LO
) ? "LO" : "HI");
2690 int pipe1
= (insn
->flags
& PIPE1
);
2691 if (insn
->flags
& LEFT
)
2692 printf(" GPR[destreg] = %s%s;\n",regname
,(pipe1
? "1" : ""));
2694 printf(" %s%s = op1;\n",regname
,(pipe1
? "1" : ""));
2697 if (insn
->flags
& SHIFT16
)
2698 printf(" GPR[destreg] = (op2 << 16);\n");
2700 /* perform conditional move */
2701 if (!(insn
->flags
& EQ
)) {
2702 fprintf(stderr
,"Standard conditional %s does not have the equality flag\n",insn
->name
);
2705 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
2706 printf(" GPR[destreg] = op1;\n");
2711 printf(" SyncOperation(op1);\n");
2715 printf(" SignalException(SystemCall,instruction);\n");
2720 printf(" unsigned int break_code = instruction & HALT_INSTRUCTION_MASK;\n");
2721 printf(" if ( break_code == (HALT_INSTRUCTION & HALT_INSTRUCTION_MASK)\n");
2722 printf(" || break_code == (HALT_INSTRUCTION2 & HALT_INSTRUCTION_MASK))\n");
2724 printf(" sim_engine_halt (SD, CPU, NULL, cia,\n");
2725 printf(" sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));\n");
2727 printf(" else if ( break_code == (BREAKPOINT_INSTRUCTION & HALT_INSTRUCTION_MASK)\n");
2728 printf(" || break_code == (BREAKPOINT_INSTRUCTION2 & HALT_INSTRUCTION_MASK))\n");
2730 printf(" if (STATE & simDELAYSLOT)\n");
2731 printf(" PC = cia - 4; /* reference the branch instruction */\n");
2733 printf(" PC = cia;\n");
2734 printf(" sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGTRAP);\n");
2737 printf(" SignalException(BreakPoint,instruction);\n");
2741 printf(" SignalException(DebugBreakPoint,instruction);\n");
2746 int boolNOT
= (insn
->flags
& NOT
);
2747 int boolEQ
= (insn
->flags
& EQ
);
2748 int boolGT
= (insn
->flags
& GT
);
2749 int boolLT
= (insn
->flags
& LT
);
2750 int boolU
= (insn
->flags
& UNSIGNED
);
2752 if (boolGT
&& boolLT
) {
2753 fprintf(stderr
,"GT and LT specified for \"%s\"\n",insn
->name
);
2757 if (boolNOT
&& (boolGT
|| boolLT
)) {
2758 fprintf(stderr
,"NOT specified with GT or LT specified for \"%s\"\n",insn
->name
);
2762 printf(" if ((%sword64)op1 ",(boolU
? "u" : ""));
2763 printf("%c%s",(boolNOT
? '!' : (boolLT
? '<' : (boolGT
? '>' : '='))),(boolEQ
? "=" : ""));
2764 printf(" (%sword64)op2)\n",(boolU
? "u" : ""));
2765 printf(" SignalException(Trap,instruction);\n");
2771 int boolU
= (insn
->flags
& UNSIGNED
);
2773 if (!(insn
->flags
& LT
)) {
2774 fprintf(stderr
,"Set instruction without LT specified \"%s\"\n",insn
->name
);
2778 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU
? "u" : ""),(boolU
? "u" : ""));
2779 printf(" GPR[destreg] = 1;\n");
2781 printf(" GPR[destreg] = 0;\n");
2786 printf(" GPR[destreg] = (op1 & op2);\n");
2790 /* The default mips16 nop instruction does an or to register
2791 zero; catch that case, so that we don't get useless warnings
2792 from the simulator. */
2794 printf (" if (destreg != 0)\n");
2795 printf(" GPR[destreg] = %s(op1 | op2);\n",((insn
->flags
& NOT
) ? "~" : ""));
2799 printf(" GPR[destreg] = (op1 ^ op2);\n");
2803 printf(" DecodeCoproc(instruction);\n");
2807 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
2808 /* The virtual address is translated to a physical address using the TLB */
2809 /* The hint specifies a cache operation for that address */
2810 printf(" address_word vaddr = (op1 + offset);\n");
2811 printf(" address_word paddr;\n");
2812 printf(" int uncached;\n");
2813 /* NOTE: We are assuming that the AddressTranslation is a load: */
2814 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2815 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
2818 case MADD16
: /* VR4100 specific multiply-add instructions */
2819 /* Some of this code is shared with the standard multiply
2820 routines, so an effort should be made to merge where
2822 if (features
& FEATURE_WARN_RESULT
) {
2823 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
2824 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
2825 printf(" sim_io_eprintf(sd,\"MADD16 operation with non-16bit operands\\n\");\n");
2828 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
2829 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2830 printf(" LO = LO + temp;\n");
2832 printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
2833 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype
);
2834 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype
);
2839 case RSVD
: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
2841 printf(" if (CoProcPresent(3))\n");
2842 printf(" SignalExceptionCoProcessorUnusable ();\n");
2845 printf(" SignalException(ReservedInstruction,instruction);\n");
2849 if (insn
->flags
& LINK
) {
2850 if (!(insn
->flags
& REG
))
2851 printf(" int destreg = 31;\n");
2852 printf(" GPR[destreg] = (PC + %d); /* NOTE: The PC is already %d ahead within the simulator */\n",
2853 mips16
? 2 : 4, mips16
? 2 : 4);
2856 if (insn
->flags
& NOT
)
2857 printf(" op1 ^= 1;\n");
2859 printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n");
2860 printf(" so we just truncate it to 32 bits here. */\n");
2861 printf(" op1 = WORD64LO(op1);\n");
2862 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
2863 printf(" DSPC = op1;\n");
2864 if ((insn
->flags
& LINK
)
2865 && ! (insn
->flags
& REG
))
2866 printf(" JALDELAYSLOT();\n");
2868 printf(" DELAYSLOT();\n");
2871 case BRANCH
: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
2872 if (insn
->flags
& FP
) {
2874 printf(" if (condition_code != 0)\n");
2875 printf(" SignalException(ReservedInstruction,instruction);\n");
2876 printf(" else {\n");
2878 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
2879 printf(" int condition = (%s == boolean);\n",((doisa
< 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
2881 if ((insn
->flags
& NOT
) && !(insn
->flags
& EQ
)) {
2882 fprintf(stderr
,"NOT specified when not EQ in \"%s\"\n",insn
->name
);
2885 if ((insn
->flags
& NOT
) && (insn
->flags
& (GT
| LT
))) {
2886 fprintf(stderr
,"NOT specified with GT or LT in \"%s\"\n",insn
->name
);
2890 if (insn
->flags
& GT
)
2891 printf(" int condition = (op1 >%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
2893 if (insn
->flags
& LT
)
2894 printf(" int condition = (op1 <%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
2896 if (insn
->flags
& EQ
)
2897 printf(" int condition = (op1 %c= op2);\n",((insn
->flags
& NOT
) ? '!' : '='));
2900 if (insn
->flags
& LINK
) {
2901 if (features
& FEATURE_WARN_R31
) {
2902 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS
,OP_MASK_RS
);
2903 printf(" sim_io_eprintf(sd,\"Branch with link using r31 as source operand\\n\");\n");
2905 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
2909 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
2910 printf(" if (condition) {\n");
2911 printf(" DSPC = (PC + offset);\n");
2912 printf(" DELAYSLOT();\n");
2915 /* No delayed slots for mips16 branches. */
2916 printf(" if (condition)\n");
2917 printf(" PC = PC + offset;\n");
2919 if ((insn
->flags
& FP
) && (doisa
!= 1)) {
2920 printf(" else if (likely) {\n");
2921 printf(" NULLIFY();\n");
2923 } else if (insn
->flags
& LIKELY
) {
2925 printf(" NULLIFY();\n");
2927 if ((insn
->flags
& FP
) && (doisa
< 4))
2931 case PREFETCH
: /* The beginning is shared with normal load operations */
2935 int isload
= ((insn
->type
== LOAD
) || (insn
->type
== PREFETCH
));
2937 char *accesslength
= "<UNKNOWN>";
2939 switch (GETDATASIZEINSN(insn
)) {
2942 accesslength
= "AccessLength_BYTE";
2947 accesslength
= "AccessLength_HALFWORD";
2952 accesslength
= "AccessLength_WORD";
2957 accesslength
= "AccessLength_DOUBLEWORD";
2959 /* start-sanitize-r5900 */
2963 accesslength
= "AccessLength_QUADWORD";
2965 /* end-sanitize-r5900 */
2968 if (insn
->flags
& REG
)
2969 printf(" address_word vaddr = ((uword64)op1 + op2);\n");
2971 printf(" address_word vaddr = ((uword64)op1 + offset);\n");
2972 printf(" address_word paddr;\n");
2973 printf(" int uncached;\n");
2975 /* The following check should only occur on normal (non-shifted) memory loads */
2976 if ((datalen
!= 1) && !(insn
->flags
& (LEFT
| RIGHT
))) {
2977 printf(" if ((vaddr & %d) != 0)\n",(datalen
- 1));
2978 printf(" SignalException%s();\n",(isload
? "AddressLoad" : "AddressStore"));
2983 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload
? "isLOAD" : "isSTORE"));
2985 if (insn
->type
== PREFETCH
)
2986 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
2989 printf(" uword64 memval = 0;\n");
2990 printf(" uword64 memval1 = 0;\n");
2992 if ((insn
->flags
& COPROC
) && ((datalen
!= 4) && (datalen
!= 8))) {
2993 fprintf(stderr
,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
2997 if (insn
->flags
& (LEFT
| RIGHT
)) {
2998 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
2999 fprintf(stderr
,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",insn
->name
);
3005 if (!(features
& FEATURE_IGEN
))
3008 fprintf(stderr
,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn
->name
);
3012 /* fall through to... */
3015 printf(" uword64 mask = %d;\n",((datalen
== 8) ? 0x7 : 0x3));
3016 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
3017 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
3018 printf(" int byte;\n");
3019 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
3020 printf(" byte = ((vaddr & mask) ^ bigend);\n");
3021 printf(" if (%sBigEndianMem)\n",((insn
->flags
& LEFT
) ? "!" : ""));
3022 printf(" paddr &= ~mask;\n");
3025 if (insn
->flags
& LEFT
)
3027 printf(" LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
3031 printf(" LoadMemory(&memval,&memval1,uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen
- 1));
3035 if (insn
->flags
& LEFT
) {
3037 /* For WORD transfers work out if the value will
3038 be in the top or bottom of the DOUBLEWORD
3041 build_endian_shift(proc64
,datalen
,2,s_right
,32);
3043 if (proc64
&& (datalen
== 4)) {
3044 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
3045 printf(" memval >>= 32;\n");
3049 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen
- 1),(datalen
- 1));
3050 if (proc64
&& (datalen
== 4))
3051 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
3052 } else { /* store */
3053 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen
- 1));
3055 build_endian_shift(proc64
,datalen
,2,s_left
,32);
3057 /* TODO: This is duplicated in the LOAD code
3058 above - and the RIGHT LOAD and STORE code
3059 below. It should be merged if possible. */
3060 if (proc64
&& (datalen
== 4)) {
3061 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
3062 printf(" memval <<= 32;\n");
3066 printf(" StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);\n");
3068 } else { /* RIGHT */
3071 build_endian_shift(proc64
,datalen
,2,s_right
,32);
3073 if (proc64
&& (datalen
== 4)) {
3074 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
3075 printf(" memval >>= 32;\n");
3080 printf(" uword64 srcmask;\n");
3081 /* All of this extra code is just a bodge
3082 required because some hosts don't allow
3083 ((v) << 64). The SPARC just leaves the (v)
3084 value un-touched. */
3085 printf(" if (byte == 0)\n");
3086 printf(" srcmask = 0;\n");
3088 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen
);
3089 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n");
3091 if (proc64
&& (datalen
== 4))
3092 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
3093 } else { /* store */
3094 printf(" memval = ((uword64) op2 << (byte * 8));\n");
3095 build_endian_shift(proc64
,datalen
,2,s_left
,32);
3096 printf(" StoreMemory(uncached,(%s - byte),memval,memval1,paddr,vaddr,isREAL);\n",accesslength
);
3103 fprintf(stderr
,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
3106 } else { /* normal memory transfer */
3107 if (!(features
& FEATURE_IGEN
))
3109 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
3110 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
3112 /* TODO: The R4000 documentation states that a LWU
3113 instruction executed when in a 32bit processor mode
3114 should cause a ReservedInstruction exception. This
3115 will mean adding a run-time check into the code
3121 #if 1 /* see the comments attached to LOADDRMASK above */
3122 printf(" uword64 mask = 0x7;\n");
3124 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
3126 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
3127 printf(" unsigned int reverse UNUSED = (ReverseEndian ? (mask >> shift) : 0);\n");
3128 printf(" unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0);\n");
3129 printf(" unsigned int byte UNUSED;\n");
3131 /* TODO: This should really also check for 32bit world performing 32bit access */
3133 /* not for DOUBLEWORD */
3134 /* start-sanitize-r5900 */
3135 /* not for QUADWORD */
3136 /* end-sanitize-r5900 */
3137 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
3139 printf(" LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength
);
3141 /* The following will only make sense if the
3142 "LoadMemory" above returns a DOUBLEWORD entity */
3144 /* not for DOUBLEWORD */
3145 /* start-sanitize-r5900 */
3146 /* not for QUADWORD */
3147 /* end-sanitize-r5900 */
3159 valmask
= 0xFFFFFFFF;
3163 fprintf(stderr
,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen
,insn
->name
);
3166 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
3167 /* NOTE: The R4000 user manual has the COP_LW
3168 occuring in the same cycle as the rest of the
3169 instruction, yet the MIPS IV shows the operation
3170 happening on the next cycle. To keep the simulator
3171 simple, this code follows the R4000
3172 manual. Experimentation with a silicon
3173 implementation will be needed to ascertain the
3174 correct operation. */
3175 if (insn
->flags
& COPROC
)
3176 printf(" COP_LW(%s,destreg,(unsigned int)",
3177 ((insn
->flags
& REG
)
3179 : "((instruction >> 26) & 0x3)"));
3181 printf(" GPR[destreg] = (");
3183 if (insn
->flags
& SIGNEXTEND
)
3184 printf("SIGNEXTEND(");
3185 printf("((memval >> (8 * byte)) & 0x%08X)",valmask
);
3186 if (insn
->flags
& SIGNEXTEND
)
3187 printf(",%d)",(datalen
* 8));
3190 if (insn
->flags
& COPROC
)
3191 printf(" COP_LD(%s,destreg,memval);;\n",
3192 ((insn
->flags
& REG
)
3194 : "((instruction >> 26) & 0x3)"));
3197 printf(" GPR[destreg] = memval;\n");
3199 printf(" GPR1[destreg] = memval1;\n");
3202 } else { /* store operation */
3203 if ((datalen
== 1) || (datalen
== 2)) {
3205 #if 1 /* see the comments attached to LOADDRMASK above */
3206 printf(" uword64 mask = 0x7;\n");
3208 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
3210 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
3211 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
3212 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
3213 printf(" unsigned int byte;\n");
3215 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
3216 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
3217 printf(" memval = ((uword64) op2 << (8 * byte));\n");
3219 if (datalen
== 4) { /* SC and SW */
3220 #if 1 /* see the comments attached to LOADDRMASK above */
3221 printf(" uword64 mask = 0x7;\n");
3223 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
3225 printf(" unsigned int byte;\n");
3226 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
3227 printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
3228 if (insn
->flags
& COPROC
)
3229 printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n",
3230 ((insn
->flags
& REG
)
3232 : "((instruction >> 26) & 0x3)"),
3233 ((insn
->flags
& FP
) ? "fs" : "destreg"));
3235 printf(" memval = ((uword64) op2 << (8 * byte));\n");
3236 } else if (datalen
<= 8) { /* SD and SCD */
3237 if (! (features
& FEATURE_IGEN
))
3239 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
3240 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
3244 if (insn
->flags
& COPROC
)
3245 printf(" memval = (uword64)COP_SD(%s,%s);\n",
3246 ((insn
->flags
& REG
)
3248 : "((instruction >> 26) & 0x3)"),
3249 ((insn
->flags
& FP
) ? "fs" : "destreg"));
3251 printf(" memval = op2;\n");
3252 } else { /* wider than 8 */
3253 if (insn
->flags
& COPROC
) {
3254 fprintf(stderr
,"COPROC not available for 128 bit operations \"%s\"\n",insn
->name
);
3257 printf(" memval = rt_reg;\n");
3258 printf(" memval1 = rt_reg1;\n");
3261 if (insn
->flags
& ATOMIC
)
3262 printf(" if (LLBIT)\n");
3265 printf(" StoreMemory(uncached,%s,memval,memval1,paddr,vaddr,isREAL);\n",accesslength
);
3269 if (insn
->flags
& ATOMIC
) {
3270 if ((datalen
!= 4) && (datalen
!= 8)) {
3271 fprintf(stderr
,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",insn
->name
);
3275 printf(" LLBIT = 1;\n");
3277 /* The documentation states that:
3279 SC *WILL* fail if coherent store into the same
3280 block occurs, or if an exception occurs between
3281 the LL and SC instructions.
3283 SC *MAY* fail if a load, store or prefetch is
3284 executed on the processor (VR4300 doesn't seem
3285 to), or if the instructions between the LL and
3286 SC are not in a 2048byte contiguous VM range.
3288 SC *MUST* have been preceded by an LL
3289 (i.e. LLBIT will be set), and it must use the
3290 same Vaddr, Paddr and cache-coherence algorithm
3291 as the LL (which means we should store this
3292 information from the load-conditional).
3294 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT
,OP_MASK_RT
);
3305 /* This code could be merged with the PREFIX generation above: */
3306 printf(" address_word vaddr = ((uword64)op1 + (uword64)op2);\n");
3307 printf(" address_word paddr;\n");
3308 printf(" int uncached;\n");
3309 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
3310 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
3314 if (insn
->flags
& CONTROL
) {
3315 /* The following "magic" of interpreting the FP
3316 control-register number would not be needed if we were not
3317 trying to match our internal register numbers with those
3319 printf(" if (to) {\n");
3321 printf(" if (fs == 0) {\n");
3322 printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
3323 printf(" } else if (fs == 31) {\n");
3324 printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
3325 printf(" } /* else NOP */\n");
3326 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
3328 printf(" if (fs == 0) {\n");
3329 printf(" FCR0 = WORD64LO(GPR[ft]);\n");
3330 printf(" } else if (fs == 31) {\n");
3331 printf(" FCR31 = WORD64LO(GPR[ft]);\n");
3332 printf(" } /* else NOP */\n");
3333 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
3335 printf(" } else { /* control from */\n");
3337 printf(" if (fs == 0) {\n");
3338 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
3339 printf(" } else if (fs == 31) {\n");
3340 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
3341 printf(" } /* else NOP */\n");
3343 printf(" if (fs == 0) {\n");
3344 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
3345 printf(" } else if (fs == 31) {\n");
3346 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
3347 printf(" } /* else NOP */\n");
3351 printf(" if (to) {\n");
3352 if (GETDATASIZEINSN(insn
) == WORD
) {
3354 printf(" if (SizeFGR() == 64) {\n");
3355 printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
3356 printf(" } else { \n");
3357 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3360 printf(" if (SizeFGR() == 64)\n");
3361 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
3363 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3364 printf(" FPR_STATE[fs] = fmt_uninterpreted;\n");
3366 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
3368 printf(" if (SizeFGR() == 64) {\n");
3369 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
3370 printf(" } else\n");
3371 printf(" if ((fs & 0x1) == 0)\n");
3373 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
3374 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3376 if (features
& FEATURE_WARN_RESULT
) {
3378 printf(" UndefinedResult();\n");
3381 printf(" if (SizeFGR() == 64) {\n");
3382 printf(" FGR[fs] = GPR[ft];\n");
3383 printf(" FPR_STATE[fs] = fmt_uninterpreted;\n");
3384 printf(" } else\n");
3385 printf(" if ((fs & 0x1) == 0)\n");
3387 printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
3388 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3389 printf(" FPR_STATE[fs + 1] = fmt_uninterpreted;\n");
3390 printf(" FPR_STATE[fs] = fmt_uninterpreted;\n");
3392 if (features
& FEATURE_WARN_RESULT
) {
3394 printf(" UndefinedResult();\n");
3398 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
3401 printf(" } else {\n");
3402 if (GETDATASIZEINSN(insn
) == WORD
) {
3403 if (doisa
< 4) /* write-back occurs in next cycle */
3404 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
3405 else /* in this cycle */
3406 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
3407 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
3409 printf(" if (SizeFGR() == 64) {\n");
3410 printf(" PENDING_FILL(ft,FGR[fs]);\n");
3411 printf(" } else\n");
3412 printf(" if ((fs & 0x1) == 0) {\n");
3413 printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
3414 printf(" } else {\n");
3415 printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3416 if (features
& FEATURE_WARN_RESULT
)
3417 printf(" UndefinedResult();\n");
3420 printf(" if (SizeFGR() == 64)\n");
3421 printf(" GPR[ft] = FGR[fs];\n");
3423 printf(" if ((fs & 0x1) == 0)\n");
3424 printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
3425 printf(" else {\n");
3426 printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3427 if (features
& FEATURE_WARN_RESULT
)
3428 printf(" UndefinedResult();\n");
3432 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
3440 if (insn
->flags
& CONDITIONAL
) {
3441 if (insn
->flags
& INTEGER
) { /* moving GPR - testing FGR */
3442 printf(" if (GETFCC(condition_code) == boolean)\n");
3443 printf(" GPR[destreg] = op1;\n");
3445 if (insn
->flags
& EQ
) /* moving FGR - testing GPR */
3446 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
3448 printf(" if (GETFCC(condition_code) == boolean)\n");
3449 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3451 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
3453 } else { /* simple MOVE */
3454 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3459 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3460 printf(" SignalException(ReservedInstruction,instruction);\n");
3462 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
3466 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3467 printf(" SignalException(ReservedInstruction,instruction);\n");
3469 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
3473 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3474 printf(" SignalException(ReservedInstruction,instruction);\n");
3476 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3480 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3481 printf(" SignalException(ReservedInstruction,instruction);\n");
3483 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3487 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3488 printf(" SignalException(ReservedInstruction,instruction);\n");
3490 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
3494 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3495 printf(" SignalException(ReservedInstruction,instruction);\n");
3497 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)%s));\n",
3498 ((insn
->flags
& RECIP
) ? "Recip" : ""),
3499 ((insn
->flags
& RECIP
) ? ",format" : ""));
3510 switch (insn
->type
) {
3512 op
= "FP_RM_TOPINF";
3515 op
= "FP_RM_TOMINF";
3518 op
= "FP_RM_TOZERO";
3521 op
= "FP_RM_NEAREST";
3524 fprintf(stderr
,"Error: Handled missing for FP reason code %d\n",insn
->type
);
3528 switch (GETDATASIZEINSN(insn
)) {
3536 fprintf(stderr
,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op
);
3539 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3540 printf(" SignalException(ReservedInstruction,instruction);\n");
3542 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type
,op
,type
);
3549 switch (GETDATASIZEINSN(insn
)) {
3551 type
= "fmt_single";
3554 type
= "fmt_double";
3563 fprintf(stderr
,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn
));
3567 /* Not all combinations of conversion are valid at the
3568 moment: When converting to a fixed-point format, only
3569 floating-point sources are allowed. */
3570 printf(" if ((format == %s) | %s)\n",type
,((insn
->flags
& FIXED
) ? "((format == fmt_long) || (format == fmt_word))": "0"));
3571 printf(" SignalException(ReservedInstruction,instruction);\n");
3573 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type
,type
);
3578 if (insn
->flags
& MULTIPLY
) {
3580 switch (GETDATASIZEINSN(insn
)) {
3582 type
= "fmt_single";
3585 type
= "fmt_double";
3588 fprintf(stderr
,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn
));
3591 if (insn
->flags
& NOT
)
3592 printf (" StoreFPR(destreg,%s,Negate(Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
3593 type
, type
, type
, type
, type
, type
, type
);
3595 printf (" StoreFPR(destreg,%s,Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
3596 type
, type
, type
, type
, type
, type
);
3598 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3599 printf(" SignalException(ReservedInstruction,instruction);\n");
3601 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3606 if (insn
->flags
& MULTIPLY
) {
3608 switch (GETDATASIZEINSN(insn
)) {
3610 type
= "fmt_single";
3613 type
= "fmt_double";
3616 fprintf(stderr
,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn
));
3619 if (insn
->flags
& NOT
)
3620 printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
3621 type
, type
, type
, type
, type
, type
, type
);
3623 printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
3624 type
, type
, type
, type
, type
, type
);
3626 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3627 printf(" SignalException(ReservedInstruction,instruction);\n");
3629 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3634 /* For the MIPS I,II or III there *MUST* be at least one
3635 instruction between the compare that sets a condition code
3636 and the branch that tests it. NOTE: However the hardware
3637 does not detect this condition. */
3638 /* Explicitly limit the operation to S and D formats: */
3639 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3640 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3641 printf(" else {\n");
3643 printf(" if (condition_code != 0)\n");
3644 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3648 printf(" int ignore = 0;\n");
3649 printf(" int less = 0;\n");
3650 printf(" int equal = 0;\n");
3651 printf(" int unordered = 1;\n");
3652 printf(" uword64 ofs = ValueFPR(fs,format);\n");
3653 printf(" uword64 oft = ValueFPR(ft,format);\n");
3654 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
3655 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
3656 printf(" FCSR |= FP_CAUSE(IO);\n");
3657 printf(" SignalExceptionFPE ();\n");
3658 printf(" ignore = 1;\n");
3660 printf(" } else {\n");
3661 printf(" less = Less(ofs,oft,format);\n");
3662 printf(" equal = Equal(ofs,oft,format);\n");
3663 printf(" unordered = 0;\n");
3665 printf(" if (!ignore) {\n");
3666 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
3667 printf(" SETFCC(condition_code,condition);\n");
3675 char* pipeline
= (insn
->flags
& PIPE1
) ? "1" : "";
3676 int notsigned
= (insn
->flags
& UNSIGNED
);
3677 char* prodtype
= notsigned
? "uword64" : "word64";
3679 printf("%s prod = (%s)WORD64(WORD64LO(HI%s),WORD64LO(LO%s)) + ((%s)%s(op1%s) * (%s)%s(op2%s));\n",
3680 prodtype
, prodtype
, pipeline
, pipeline
,
3681 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32"),
3682 prodtype
, (notsigned
? "WORD64LO" : "SIGNEXTEND"), (notsigned
? "" : ",32")
3684 printf("LO%s = SIGNEXTEND(prod,32);\n", pipeline
);
3685 printf("HI%s = SIGNEXTEND( WORD64HI(prod), 32);\n", pipeline
);
3686 printf("if( destreg != 0 ) GPR[destreg] = LO%s;\n", pipeline
);
3690 /* start-sanitize-r5900 */
3693 if (insn
->flags
& TO
)
3694 printf("SA = op1;\n");
3696 printf("GPR[destreg] = SA;\n");
3701 printf("SA = ((op1 & 0xF) ^ (op2 & 0xF)) * 8;\n");
3705 printf("SA = ((op1 & 0x7) ^ (op2 & 0x7)) * 16;\n");
3709 printf("int bytes = (SA / 8) %% 16;\n"); /* mod 16 to avoid garbage */
3710 printf("if (SA %% 8)\n");
3711 printf(" SignalException(ReservedInstruction,instruction);\n");
3714 printf(" int i;\n");
3715 printf(" for(i=0;i<(16-bytes);i++)\n");
3716 printf(" GPR_SB(destreg,i) = RT_SB(bytes+i);\n");
3717 printf(" for(;i<16;i++)\n");
3718 printf(" GPR_SB(destreg,i) = RS_SB(i-(16-bytes));\n");
3724 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3725 char* name
= name_for_data_len( insn
);
3726 char* letter
= letter_for_data_len( insn
);
3734 if ( insn
->flags
& UNSIGNED
)
3736 tmptype
= type_for_data_len( insn
, 0/*unsigned*/ );
3738 maximum
= umax_for_data_len( insn
);
3739 maxsat
= (insn
->flags
& SUBTRACT
) ? "0" : maximum
;
3742 else if ( insn
->flags
& SATURATE
)
3744 tmptype
= type_for_data_len( insn
, 1/*signed*/ );
3746 maximum
= max_for_data_len( insn
);
3748 minimum
= min_for_data_len( insn
);
3752 tmptype
= type_for_data_len( insn
, 1/*signed*/ );
3759 printf(" int i;\n");
3760 printf(" for (i=0; i < %sS_IN_MMI_REGS; i++)\n", name
);
3762 printf(" %s s = RS_%s%s(i);\n", tmptype
, signletter
, letter
);
3763 printf(" %s t = RT_%s%s(i);\n", tmptype
, signletter
, letter
);
3764 printf(" %s r = s %s t;\n", tmptype
, op
);
3767 printf(" if (r > %s)\n", maximum
);
3768 printf(" GPR_%s%s(destreg,i) = %s;\n", signletter
, letter
, maxsat
);
3771 printf(" else if (r < %s)\n", minimum
);
3772 printf(" GPR_%s%s(destreg,i) = %s;\n", signletter
, letter
, minimum
);
3777 printf(" GPR_%s%s(destreg,i) = r;\n", signletter
, letter
);
3785 if ( insn
->flags
& SUBTRACT
)
3787 else if ( insn
->flags
& ADDITION
)
3792 printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op
);
3793 printf(" LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op
);
3794 printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op
);
3795 printf(" HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op
);
3796 printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op
);
3797 printf(" LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op
);
3798 printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op
);
3799 printf(" HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op
);
3806 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3807 char* prodtype
= (insn
->flags
& UNSIGNED
) ? "unsigned64" : "signed64";
3808 char* constructor
= (insn
->flags
& UNSIGNED
) ? "UWORD64" : "WORD64";
3810 if ( insn
->flags
& SUBTRACT
)
3813 printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype
, constructor
);
3814 printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype
, constructor
);
3816 else if ( insn
->flags
& ADDITION
)
3819 printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype
, constructor
);
3820 printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype
, constructor
);
3825 printf(" %s sum0 = 0;\n", prodtype
);
3826 printf(" %s sum1 = 0;\n", prodtype
);
3829 printf(" %s prod0 = (%s)RS_%sW(0) * (%s)RT_%sW(0);\n", prodtype
, prodtype
, sign
, prodtype
, sign
);
3830 printf(" %s prod1 = (%s)RS_%sW(2) * (%s)RT_%sW(2);\n", prodtype
, prodtype
, sign
, prodtype
, sign
);
3832 printf(" sum0 %s= prod0;\n", op
);
3833 printf(" sum1 %s= prod1;\n", op
);
3835 printf(" GPR_%sD(destreg,0) = sum0;\n", sign
);
3836 printf(" GPR_%sD(destreg,1) = sum1;\n", sign
);
3838 printf(" LO = SIGNEXTEND( sum0, 32 );\n");
3839 printf(" HI = SIGNEXTEND( WORD64HI(sum0), 32 );\n");
3840 printf(" LO1 = SIGNEXTEND( sum1, 32 );\n");
3841 printf(" HI1 = SIGNEXTEND( WORD64HI(sum1), 32 );\n");
3847 char* sign
= (insn
->flags
& UNSIGNED
) ? "U" : "S";
3849 for (i
= 0; i
< 2; i
++)
3851 char hi
= (i
== 0 ? ' ' : '1');
3853 if (! (insn
->flags
& UNSIGNED
))
3855 printf("if (RT_SW(%d) == -1)\n", d
);
3857 printf(" LO%c = -RS_%sW(%d);\n", hi
, sign
, d
);
3858 printf(" HI%c = 0;\n", hi
);
3859 printf(" }\nelse ");
3861 printf("if (RT_UW(%d) != 0)\n", d
);
3863 printf(" LO%c = (signed32)(RS_%sW(%d) / RT_%sW(%d));\n", hi
, sign
, d
, sign
, d
);
3864 printf(" HI%c = (signed32)(RS_%sW(%d) %% RT_%sW(%d));\n", hi
, sign
, d
, sign
, d
);
3871 printf("signed32 devisor = RT_SH(0);\n");
3872 printf("if (devisor == -1)\n");
3874 printf(" LO_SW(0) = -RS_SW(0);\n");
3875 printf(" HI_SW(0) = 0;\n");
3876 printf(" LO_SW(1) = -RS_SW(1);\n");
3877 printf(" HI_SW(1) = 0;\n");
3878 printf(" LO_SW(2) = -RS_SW(2);\n");
3879 printf(" HI_SW(2) = 0;\n");
3880 printf(" LO_SW(3) = -RS_SW(3);\n");
3881 printf(" HI_SW(3) = 0;\n");
3883 printf("else if (devisor != 0)\n");
3885 printf(" LO_SW(0) = RS_SW(0) / devisor;\n");
3886 printf(" HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n");
3887 printf(" LO_SW(1) = RS_SW(1) / devisor;\n");
3888 printf(" HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n");
3889 printf(" LO_SW(2) = RS_SW(2) / devisor;\n");
3890 printf(" HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n");
3891 printf(" LO_SW(3) = RS_SW(3) / devisor;\n");
3892 printf(" HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n");
3898 printf("for(i=0;i<HALFWORDS_IN_MMI_REGS/2;i++)\n");
3899 printf(" GPR_SH(destreg,i) = RS_SH(i) - RT_SH(i);\n");
3900 printf("for(;i<HALFWORDS_IN_MMI_REGS;i++)\n");
3901 printf(" GPR_SH(destreg,i) = RS_SH(i) + RT_SH(i);\n");
3906 char* op
= (insn
->flags
& SUBTRACT
) ? "-" : "+";
3907 printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op
);
3908 printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op
);
3909 printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op
);
3910 printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op
);
3916 char* name
= name_for_data_len( insn
);
3917 char* letter
= letter_for_data_len( insn
);
3918 char* bits
= bits_for_data_len( insn
);
3919 char* shift
= (insn
->flags
& RIGHT
) ? ">>" : "<<";
3920 char* sign
= (insn
->flags
& ARITHMETIC
) ? "S" : "U";
3922 printf("int shift_by = op1 & (%s-1);\n", bits
);
3924 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3925 printf(" GPR_%s%s(destreg,i) = ", sign
, letter
);
3926 if ( insn
->flags
& ARITHMETIC
)
3927 printf("SIGNEXTEND( ");
3928 printf("(RT_%s%s(i) %s shift_by)", sign
, letter
, shift
);
3929 if ( insn
->flags
& ARITHMETIC
)
3930 printf(", (%s-shift_by) )", bits
);
3936 printf("int s0 = (RS_UB(0) & 0x1F);\n");
3937 printf("int s1 = (RS_UB(8) & 0x1F);\n");
3938 printf("signed32 temp0 = RT_UW(0) << s0;\n");
3939 printf("signed32 temp1 = RT_UW(2) << s1;\n");
3940 printf("GPR_SD(destreg,0) = (signed64)temp0;\n");
3941 printf("GPR_SD(destreg,1) = (signed64)temp1;\n");
3945 printf("GPR_UD(destreg,0) = SIGNEXTEND ( RT_UW(0) >> (RS_UB(0) & 0x1F), 31);\n");
3946 printf("GPR_UD(destreg,1) = SIGNEXTEND ( RT_UW(2) >> (RS_UB(8) & 0x1F), 31);\n");
3950 printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n");
3951 printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n");
3959 if ( GET_OP_FROM_INSN(insn
) == POP_AND
)
3964 else if ( GET_OP_FROM_INSN(insn
) == POP_OR
)
3969 else if ( GET_OP_FROM_INSN(insn
) == POP_NOR
)
3974 else if ( GET_OP_FROM_INSN(insn
) == POP_XOR
)
3981 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3982 printf(" GPR_UW(destreg,i) = %s(RS_UW(i) %s RT_UW(i));\n", op2
, op1
);
3988 char* name
= name_for_data_len( insn
);
3989 char* letter
= letter_for_data_len( insn
);
3990 char* maximum
= umax_for_data_len( insn
);
3991 char* op
= (insn
->flags
& GT
) ? ">" : "==";
3994 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
3996 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n",
3997 letter
, op
, letter
, letter
, maximum
);
3998 printf(" else GPR_S%s(destreg,i) = 0;\n", letter
);
4005 char* name
= name_for_data_len( insn
);
4006 char* letter
= letter_for_data_len( insn
);
4007 char* op
= (insn
->flags
& GT
) ? ">" : "<";
4010 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
4012 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n",
4013 letter
, op
, letter
, letter
, letter
);
4014 printf(" else GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
4021 char* name
= name_for_data_len( insn
);
4022 char* letter
= letter_for_data_len( insn
);
4023 char* min
= min_for_data_len( insn
);
4024 char* max
= max_for_data_len( insn
);
4027 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name
);
4029 printf(" if (RT_S%s(i) >= 0)\n", letter
);
4030 printf(" GPR_S%s(destreg,i) = RT_S%s(i);\n", letter
, letter
);
4031 printf(" else if (RT_S%s(i) == %s)\n", letter
, min
);
4032 printf(" GPR_S%s(destreg,i) = %s;\n", letter
, max
);
4034 printf(" GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter
, letter
);
4040 printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n");
4041 printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n");
4045 printf("GPR_UD(destreg,0) = RT_UD(0);\n");
4046 printf("GPR_UD(destreg,1) = RS_UD(0);\n");
4050 printf("GPR_UD(destreg,0) = RS_UD(1);\n");
4051 printf("GPR_UD(destreg,1) = RT_UD(1);\n");
4055 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4056 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
4057 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4058 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
4059 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
4060 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
4061 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
4062 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
4066 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4067 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
4068 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
4069 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
4073 printf("GPR_UH(destreg,0) = RT_UH(2);\n");
4074 printf("GPR_UH(destreg,1) = RT_UH(1);\n");
4075 printf("GPR_UH(destreg,2) = RT_UH(0);\n");
4076 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
4077 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
4078 printf("GPR_UH(destreg,5) = RT_UH(5);\n");
4079 printf("GPR_UH(destreg,6) = RT_UH(4);\n");
4080 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
4084 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
4085 printf("GPR_UW(destreg,1) = RT_UW(1);\n");
4086 printf("GPR_UW(destreg,2) = RT_UW(0);\n");
4087 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
4091 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
4092 printf("GPR_UB(destreg,1) = RS_UB(0);\n");
4093 printf("GPR_UB(destreg,2) = RT_UB(1);\n");
4094 printf("GPR_UB(destreg,3) = RS_UB(1);\n");
4095 printf("GPR_UB(destreg,4) = RT_UB(2);\n");
4096 printf("GPR_UB(destreg,5) = RS_UB(2);\n");
4097 printf("GPR_UB(destreg,6) = RT_UB(3);\n");
4098 printf("GPR_UB(destreg,7) = RS_UB(3);\n");
4099 printf("GPR_UB(destreg,8) = RT_UB(4);\n");
4100 printf("GPR_UB(destreg,9) = RS_UB(4);\n");
4101 printf("GPR_UB(destreg,10) = RT_UB(5);\n");
4102 printf("GPR_UB(destreg,11) = RS_UB(5);\n");
4103 printf("GPR_UB(destreg,12) = RT_UB(6);\n");
4104 printf("GPR_UB(destreg,13) = RS_UB(6);\n");
4105 printf("GPR_UB(destreg,14) = RT_UB(7);\n");
4106 printf("GPR_UB(destreg,15) = RS_UB(7);\n");
4110 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4111 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
4112 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4113 printf("GPR_UH(destreg,3) = RS_UH(1);\n");
4114 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
4115 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
4116 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
4117 printf("GPR_UH(destreg,7) = RS_UH(3);\n");
4121 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4122 printf("GPR_UW(destreg,1) = RS_UW(0);\n");
4123 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
4124 printf("GPR_UW(destreg,3) = RS_UW(1);\n");
4128 printf("GPR_UB(destreg,0) = RT_UB(8);\n");
4129 printf("GPR_UB(destreg,1) = RS_UB(8);\n");
4130 printf("GPR_UB(destreg,2) = RT_UB(9);\n");
4131 printf("GPR_UB(destreg,3) = RS_UB(9);\n");
4132 printf("GPR_UB(destreg,4) = RT_UB(10);\n");
4133 printf("GPR_UB(destreg,5) = RS_UB(10);\n");
4134 printf("GPR_UB(destreg,6) = RT_UB(11);\n");
4135 printf("GPR_UB(destreg,7) = RS_UB(11);\n");
4136 printf("GPR_UB(destreg,8) = RT_UB(12);\n");
4137 printf("GPR_UB(destreg,9) = RS_UB(12);\n");
4138 printf("GPR_UB(destreg,10) = RT_UB(13);\n");
4139 printf("GPR_UB(destreg,11) = RS_UB(13);\n");
4140 printf("GPR_UB(destreg,12) = RT_UB(14);\n");
4141 printf("GPR_UB(destreg,13) = RS_UB(14);\n");
4142 printf("GPR_UB(destreg,14) = RT_UB(15);\n");
4143 printf("GPR_UB(destreg,15) = RS_UB(15);\n");
4147 printf("GPR_UH(destreg,0) = RT_UH(4);\n");
4148 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
4149 printf("GPR_UH(destreg,2) = RT_UH(5);\n");
4150 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
4151 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
4152 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
4153 printf("GPR_UH(destreg,6) = RT_UH(7);\n");
4154 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
4158 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
4159 printf("GPR_UW(destreg,1) = RS_UW(2);\n");
4160 printf("GPR_UW(destreg,2) = RT_UW(3);\n");
4161 printf("GPR_UW(destreg,3) = RS_UW(3);\n");
4165 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
4166 printf("GPR_UB(destreg,1) = RT_UB(2);\n");
4167 printf("GPR_UB(destreg,2) = RT_UB(4);\n");
4168 printf("GPR_UB(destreg,3) = RT_UB(6);\n");
4169 printf("GPR_UB(destreg,4) = RT_UB(8);\n");
4170 printf("GPR_UB(destreg,5) = RT_UB(10);\n");
4171 printf("GPR_UB(destreg,6) = RT_UB(12);\n");
4172 printf("GPR_UB(destreg,7) = RT_UB(14);\n");
4173 printf("GPR_UB(destreg,8) = RS_UB(0);\n");
4174 printf("GPR_UB(destreg,9) = RS_UB(2);\n");
4175 printf("GPR_UB(destreg,10) = RS_UB(4);\n");
4176 printf("GPR_UB(destreg,11) = RS_UB(6);\n");
4177 printf("GPR_UB(destreg,12) = RS_UB(8);\n");
4178 printf("GPR_UB(destreg,13) = RS_UB(10);\n");
4179 printf("GPR_UB(destreg,14) = RS_UB(12);\n");
4180 printf("GPR_UB(destreg,15) = RS_UB(14);\n");
4184 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4185 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
4186 printf("GPR_UH(destreg,2) = RT_UH(4);\n");
4187 printf("GPR_UH(destreg,3) = RT_UH(6);\n");
4188 printf("GPR_UH(destreg,4) = RS_UH(0);\n");
4189 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
4190 printf("GPR_UH(destreg,6) = RS_UH(4);\n");
4191 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
4195 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4196 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
4197 printf("GPR_UW(destreg,2) = RS_UW(0);\n");
4198 printf("GPR_UW(destreg,3) = RS_UW(2);\n");
4202 printf("GPR_UH(destreg,0) = RT_UH(3);\n");
4203 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
4204 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4205 printf("GPR_UH(destreg,3) = RT_UH(0);\n");
4206 printf("GPR_UH(destreg,4) = RT_UH(7);\n");
4207 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
4208 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
4209 printf("GPR_UH(destreg,7) = RT_UH(4);\n");
4213 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
4214 printf("GPR_UW(destreg,1) = RT_UW(3);\n");
4215 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
4216 printf("GPR_UW(destreg,3) = RT_UW(2);\n");
4220 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4221 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
4222 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
4223 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
4224 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
4225 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
4226 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
4227 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
4231 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
4232 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
4233 printf("GPR_UH(destreg,2) = RT_UH(2);\n");
4234 printf("GPR_UH(destreg,3) = RS_UH(2);\n");
4235 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
4236 printf("GPR_UH(destreg,5) = RS_UH(4);\n");
4237 printf("GPR_UH(destreg,6) = RT_UH(6);\n");
4238 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
4241 case PMXX
: /* Parallel move HI or LO / TO or FROM */
4243 if ( (insn
->flags
& (HI
|FROM
)) == (HI
|FROM
) )
4245 printf("GPR_SD(destreg,0) = HI;\n");
4246 printf("GPR_SD(destreg,1) = HI1;\n");
4248 else if ( (insn
->flags
& (LO
|FROM
)) == (LO
|FROM
) )
4250 printf("GPR_SD(destreg,0) = LO;\n");
4251 printf("GPR_SD(destreg,1) = LO1;\n");
4253 else if ( (insn
->flags
& (HI
|TO
)) == (HI
|TO
) )
4255 printf("HI = RS_SD(0);\n");
4256 printf("HI1 = RS_SD(1);\n");
4258 else if ( (insn
->flags
& (LO
|TO
)) == (LO
|TO
) )
4260 printf("LO = RS_SD(0);\n");
4261 printf("LO1 = RS_SD(1);\n");
4267 printf("LO_UW(0) = RS_UW(0);\n");
4268 printf("HI_UW(0) = RS_UW(1);\n");
4269 printf("LO_UW(2) = RS_UW(2);\n");
4270 printf("HI_UW(2) = RS_UW(3);\n");
4274 printf("if (op1 == 0)\n");
4276 printf(" GPR_UW(destreg,0) = LO_UW(0);\n");
4277 printf(" GPR_UW(destreg,1) = HI_UW(0);\n");
4278 printf(" GPR_UW(destreg,2) = LO_UW(2);\n");
4279 printf(" GPR_UW(destreg,3) = HI_UW(2);\n");
4281 printf("else if (op1 == 1)\n");
4283 printf(" GPR_UW(destreg,0) = LO_UW(1);\n");
4284 printf(" GPR_UW(destreg,1) = HI_UW(1);\n");
4285 printf(" GPR_UW(destreg,2) = LO_UW(3);\n");
4286 printf(" GPR_UW(destreg,3) = HI_UW(3);\n");
4288 printf("else if (op1 == 2)\n");
4290 printf(" /* NOTE: This code implements a saturate according to the\n");
4291 printf(" figure on page B-115 and not according to the\n");
4292 printf(" definition on page B-113 */\n");
4293 printf(" signed64 t = ((unsigned64)HI_UW(0) << 32) | (unsigned64)LO_UW(0);\n");
4294 printf(" signed64 u = ((unsigned64)HI_UW(2) << 32) | (unsigned64)LO_UW(2);\n");
4295 printf(" if ( t > SIGNED64 (0x000000007FFFFFFF) )\n");
4296 printf(" GPR_SD(destreg,0) = SIGNED64 (0x000000007FFFFFFF);\n");
4297 printf(" else if ( t < - SIGNED64 (0x0000000080000000) )\n");
4298 printf(" GPR_SD(destreg,0) = - SIGNED64 (0x0000000080000000);\n");
4300 printf(" GPR_SD(destreg,0) = t;\n");
4301 printf(" if ( u > SIGNED64 (0x000000007FFFFFFF) )\n");
4302 printf(" GPR_SD(destreg,1) = SIGNED64 (0x000000007FFFFFFF);\n");
4303 printf(" else if ( u < - SIGNED64 (0x0000000080000000) )\n");
4304 printf(" GPR_SD(destreg,1) = - SIGNED64 (0x0000000080000000);\n");
4306 printf(" GPR_SD(destreg,1) = u;\n");
4308 printf("else if (op1 == 3)\n");
4310 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
4311 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
4312 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
4313 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
4314 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
4315 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
4316 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
4317 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
4319 printf("else if (op1 == 4)\n");
4321 printf(" if (LO_SW(0) > 0x7FFF)\n");
4322 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
4323 printf(" else if (LO_SW(0) < -0x8000)\n");
4324 printf(" GPR_UH(destreg,0) = 0x8000;\n");
4326 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
4328 printf(" if (LO_SW(1) > 0x7FFF)\n");
4329 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
4330 printf(" else if (LO_SW(1) < -0x8000)\n");
4331 printf(" GPR_UH(destreg,1) = 0x8000;\n");
4333 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
4335 printf(" if (HI_SW(0) > 0x7FFF)\n");
4336 printf(" GPR_UH(destreg,2) = 0x7FFF;\n");
4337 printf(" else if (HI_SW(0) < -0x8000)\n");
4338 printf(" GPR_UH(destreg,2) = 0x8000;\n");
4340 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
4342 printf(" if (HI_SW(1) > 0x7FFF)\n");
4343 printf(" GPR_UH(destreg,3) = 0x7FFF;\n");
4344 printf(" else if (HI_SW(1) < -0x8000)\n");
4345 printf(" GPR_UH(destreg,3) = 0x8000;\n");
4347 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
4349 printf(" if (LO_SW(2) > 0x7FFF)\n");
4350 printf(" GPR_UH(destreg,4) = 0x7FFF;\n");
4351 printf(" else if (LO_SW(2) < -0x8000)\n");
4352 printf(" GPR_UH(destreg,4) = 0x8000;\n");
4354 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
4356 printf(" if (LO_SW(3) > 0x7FFF)\n");
4357 printf(" GPR_UH(destreg,5) = 0x7FFF;\n");
4358 printf(" else if (LO_SW(3) < -0x8000)\n");
4359 printf(" GPR_UH(destreg,5) = 0x8000;\n");
4361 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
4363 printf(" if (HI_SW(2) > 0x7FFF)\n");
4364 printf(" GPR_UH(destreg,6) = 0x7FFF;\n");
4365 printf(" else if (HI_SW(2) < -0x8000)\n");
4366 printf(" GPR_UH(destreg,6) = 0x8000;\n");
4368 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
4370 printf(" if (HI_SW(3) > 0x7FFF)\n");
4371 printf(" GPR_UH(destreg,7) = 0x7FFF;\n");
4372 printf(" else if (HI_SW(3) < -0x8000)\n");
4373 printf(" GPR_UH(destreg,7) = 0x8000;\n");
4375 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
4381 printf("unsigned long value;\n");
4382 printf("int test;\n");
4383 printf("int count;\n");
4386 printf("value = RS_UW(0);\n");
4387 printf("count = 0;\n");
4388 printf("test = !!(value & (1 << 31));\n");
4389 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
4390 printf(" count++;\n");
4391 printf("GPR_UW(destreg,0) = count;\n");
4393 printf("value = RS_UW(1);\n");
4394 printf("count = 0;\n");
4395 printf("test = !!(value & (1 << 31));\n");
4396 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
4397 printf(" count++;\n");
4398 printf("GPR_UW(destreg,1) = count;\n");
4403 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
4405 printf(" unsigned32 x = RT_UW(i);\n");
4406 printf(" GPR_UW(destreg,i) = ((x & (1 << 15)) << (31 - 15)) \n");
4407 printf(" | ((x & (31 << 10)) << (19 - 10)) \n");
4408 printf(" | ((x & (31 << 5)) << (11 - 5)) \n");
4409 printf(" | ((x & (31 << 0)) << (3 - 0)); \n");
4415 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
4417 printf(" unsigned32 x = RT_UW(i);\n");
4418 printf(" GPR_UW(destreg,i) = ((x & (1 << 31)) >> (31 - 15)) \n");
4419 printf(" | ((x & (31 << 19)) >> (19 - 10)) \n");
4420 printf(" | ((x & (31 << 11)) >> (11 - 5)) \n");
4421 printf(" | ((x & (31 << 3)) >> (3 - 0)); \n");
4424 /* end-sanitize-r5900 */
4427 fprintf(stderr
,"Warning: Unimplemented opcode: %s\n",insn
->name
) ;
4429 printf("SignalException(ReservedInstruction,instruction);\n");
4433 fprintf(stderr
,"Unrecognised opcode type %d\n",insn
->type
) ;
4438 /*---------------------------------------------------------------------------*/
4440 /* The command-line feature controls are presented in a similar style
4441 to those offered by GCC, in the aim of providing a consistent
4442 interface to the user. */
4444 T_NONE
, /* no argument - mask and value fields control "feature" definition */
4445 T_NUM
, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
4446 T_STRING
/* string argument - optionally prcededed by '=' */
4455 } machine_options
[] = {
4456 {"ips", T_NUM
, MASK_ISA
,0,"\tSelect MIPS ISA version"},
4457 {"cpu", T_STRING
,0,0,"\t\tSelect particular MIPS architecture"},
4458 {"gp64", T_NONE
, FEATURE_GP64
,FEATURE_GP64
,"\t\t\tSelect 64bit GP registers"},
4459 {"gp32", T_NONE
, FEATURE_GP64
,0,"\t\t\tSelect 32bit GP registers"},
4460 {"no-fp", T_NONE
, FEATURE_HASFPU
,0,"\t\tDisable FP simulation"},
4461 {"single-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),(FEATURE_FPSINGLE
| FEATURE_HASFPU
),"\t\tSelect single precision only FPU"},
4462 {"double-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),FEATURE_HASFPU
,"\t\tSelect double precision FPU"},
4466 /* The following architecture identies are those accepted by the "-mcpu" option: */
4467 struct architectures
{
4468 const char *name
; /* ASCII string identifier for command-line, no white-space allowed */
4469 unsigned int idflag
; /* or-ed into "isa" value */
4472 static const struct architectures available_architectures
[] = {
4473 {"4100",ARCH_VR4100
}, /* NEC MIPS VR4100 */
4474 {"3900",ARCH_R3900
}, /* Toshiba R3900 (TX39) */
4475 /* start-sanitize-tx49 */
4476 {"4900",ARCH_R4900
}, /* Toshiba R4900 (TX49) */
4477 /* end-sanitize-tx49 */
4478 /* start-sanitize-tx19 */
4479 {"1900",ARCH_R3900
}, /* Toshiba R1900 (TX19) */
4480 /* end-sanitize-tx19 */
4481 /* start-sanitize-r5900 */
4482 {"5900",ARCH_R5900
},
4483 /* end-sanitize-r5900 */
4484 {0, 0} /* terminator */
4487 /*---------------------------------------------------------------------------*/
4495 fprintf(stderr
,"%s: Construct a MIPS simulator engine.\n",name
);
4498 The output of this program is a block of 'C' code designed to be\n\
4499 included into the main simulation control loop of a device specific\n\
4502 fprintf(stderr
,"\nOptions:\n");
4503 fprintf(stderr
," -h --help\t\tProvide this help text\n");
4504 fprintf(stderr
," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
4505 fprintf(stderr
," -w --warnings\t\tEnable all the simulator engine warnings\n");
4507 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++) {
4508 fprintf(stderr
," -m%s",machine_options
[loop
].name
);
4509 switch (machine_options
[loop
].type
) {
4511 fprintf(stderr
,"N (range 0..%d)",machine_options
[loop
].mask
);
4516 fprintf(stderr
,"=name");
4520 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",name
,machine_options
[loop
].type
);
4523 fprintf(stderr
,"%s\n",machine_options
[loop
].desc
);
4526 fprintf(stderr
,"\nAvailable \"-mcpu\" architectures: ");
4527 for (loop
= 0; (available_architectures
[loop
].name
!= 0); loop
++)
4528 fprintf(stderr
,"%s ",available_architectures
[loop
].name
);
4529 fprintf(stderr
,"\n\n");
4532 The \"trace\" and \"warnings\" options do not define the output stream.\n\
4533 They only inform the code that includes the constructed engine to provide\n\
4534 the required features.\n\n\
4535 The \"-mips0\" option forces the construction of a simulator supporting\n\
4536 the highest available MIPS ISA supported.\n");
4541 /*---------------------------------------------------------------------------*/
4549 char *progname
= argv
[0];
4550 unsigned int doarch
= DEF_ISA
;
4551 unsigned int features
= 0; /* default state */
4554 features
|= FEATURE_HASFPU
;
4556 features
|= FEATURE_PROC32
;
4558 features
|= FEATURE_FPSINGLE
;
4560 if (features
& FEATURE_PROC32
)
4561 features
&= ~FEATURE_GP64
;
4563 features
|= FEATURE_GP64
;
4566 int option_index
= 0;
4567 static struct option cmdline
[] = {
4570 {"warnings",0,0,'w'},
4575 c
= getopt_long(argc
,argv
,"hm:tw",cmdline
,&option_index
);
4577 break ; /* out of the while loop */
4580 case 'h' : /* help */
4584 case 'f' : /* fast */
4585 features
|= FEATURE_FAST
;
4588 case 'i' : /* igen formatted output */
4589 features
|= FEATURE_IGEN
;
4592 case 'w' : /* warnings */
4593 features
|= FEATURE_WARNINGS
;
4594 /* TODO: Future extension: Allow better control over the warnings generated:
4595 disable warnings -wnone ~FEATURE_WARNINGS
4596 all possible warnings -wall FEATURE_WARNINGS
4597 pipeline stall occuring -wstall FEATURE_WARN_STALL
4598 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
4599 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
4600 bad r31 use -wr31 FEATURE_WARN_R31
4601 undefined results -wresult FEATURE_WARN_RESULT
4605 case 'm' : /* machine options */
4609 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++)
4610 if (strncmp(machine_options
[loop
].name
,optarg
,strlen(machine_options
[loop
].name
)) == 0) {
4611 char *loptarg
= (optarg
+ strlen(machine_options
[loop
].name
));
4612 switch (machine_options
[loop
].type
) {
4615 fprintf(stderr
,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname
,loptarg
,machine_options
[loop
].name
);
4618 features
&= ~(machine_options
[loop
].mask
);
4619 features
|= machine_options
[loop
].value
;
4623 if (*loptarg
&& *loptarg
== '=')
4626 if (strcmp(machine_options
[loop
].name
,"ips") == 0) {
4630 fprintf(stderr
,"%s: ISA number expected after -mips\n",progname
);
4634 num
= my_strtoul(loptarg
,&loptarg
,10);
4636 if ((num
== ULONG_MAX
) && (errno
= ERANGE
)) {
4637 fprintf(stderr
,"%s: Invalid number given to -mips option\n",progname
);
4642 fprintf(stderr
,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname
,loptarg
);
4646 if (num
> MASK_ISA
) {
4647 fprintf(stderr
,"%s: ISA number %d outside acceptable range (0..%d)\n",progname
,num
,MASK_ISA
);
4651 doarch
= ((doarch
& ~MASK_ISA
) | num
);
4652 if ((num
== 0) || (num
> 2)) {
4653 if ((features
& FEATURE_PROC32
) || !(features
& FEATURE_GP64
))
4654 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp64\n",progname
,num
);
4655 features
|= FEATURE_GP64
;
4656 features
&= ~FEATURE_PROC32
;
4658 if (!(features
& FEATURE_PROC32
) || (features
& FEATURE_GP64
))
4659 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp32\n",progname
,num
);
4660 features
&= ~FEATURE_GP64
;
4661 features
|= FEATURE_PROC32
;
4664 fprintf(stderr
,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname
,optarg
);
4670 if (*loptarg
&& *loptarg
== '=')
4673 if (strcmp(machine_options
[loop
].name
,"cpu") == 0) {
4677 fprintf(stderr
,"%s: Architecture identifier expected after -mcpu\n",progname
);
4681 for (archloop
= 0; (available_architectures
[archloop
].name
!= 0); archloop
++) {
4682 if ((*loptarg
== 'v') || (*loptarg
== 'V'))
4685 if ((*loptarg
== 'r') || (*loptarg
== 'R'))
4688 if (strcmp(available_architectures
[archloop
].name
,loptarg
) == 0) {
4689 doarch
|= available_architectures
[archloop
].idflag
;
4694 if (available_architectures
[archloop
].name
== 0) {
4695 fprintf(stderr
,"%s: Unrecognised MIPS architecture \"%s\"\n",progname
,loptarg
);
4699 fprintf(stderr
,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname
,optarg
);
4705 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",progname
,machine_options
[loop
].type
);
4711 if (machine_options
[loop
].name
== 0) {
4712 fprintf(stderr
,"%s: Unrecognised option: -m%s\n",progname
,optarg
);
4719 /* An error message should already have been displayed */
4723 fprintf(stderr
,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname
,c
);
4728 if (optind
< argc
) {
4729 fprintf(stderr
,"%s: Spurios non-option arguments ",progname
);
4730 while (optind
< argc
)
4731 fprintf(stderr
,"\"%s\" ",argv
[optind
++]);
4732 fprintf(stderr
,"\n");
4736 if ((features
& FEATURE_FAST
) && (features
& FEATURE_WARNINGS
))
4737 fprintf(stderr
,"Warning: Fast model generation selected, along with trace or warnings.\n");
4739 process_instructions(doarch
,features
) ;
4743 /*---------------------------------------------------------------------------*/
4745 /* We can't assume that the compiler for the build system has strtoul,
4746 so we provide our own copy. */
4749 * Copyright (c) 1990 Regents of the University of California.
4750 * All rights reserved.
4752 * Redistribution and use in source and binary forms, with or without
4753 * modification, are permitted provided that the following conditions
4755 * 1. Redistributions of source code must retain the above copyright
4756 * notice, this list of conditions and the following disclaimer.
4757 * 2. Redistributions in binary form must reproduce the above copyright
4758 * notice, this list of conditions and the following disclaimer in the
4759 * documentation and/or other materials provided with the distribution.
4760 * 3. All advertising materials mentioning features or use of this software
4761 * must display the following acknowledgement:
4762 * This product includes software developed by the University of
4763 * California, Berkeley and its contributors.
4764 * 4. Neither the name of the University nor the names of its contributors
4765 * may be used to endorse or promote products derived from this software
4766 * without specific prior written permission.
4768 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4769 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4770 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4771 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4772 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4773 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4774 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4775 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4776 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4777 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4782 * Convert a string to an unsigned long integer.
4784 * Ignores `locale' stuff. Assumes that the upper and lower case
4785 * alphabets and digits are each contiguous.
4787 static unsigned long
4788 my_strtoul(nptr
, endptr
, base
)
4793 register const char *s
= nptr
;
4794 register unsigned long acc
;
4796 register unsigned long cutoff
;
4797 register int neg
= 0, any
, cutlim
;
4800 * See strtol for comments as to the logic used.
4804 } while (isspace(c
));
4808 } else if (c
== '+')
4810 if ((base
== 0 || base
== 16) &&
4811 c
== '0' && (*s
== 'x' || *s
== 'X')) {
4817 base
= c
== '0' ? 8 : 10;
4818 cutoff
= (unsigned long)ULONG_MAX
/ (unsigned long)base
;
4819 cutlim
= (unsigned long)ULONG_MAX
% (unsigned long)base
;
4820 for (acc
= 0, any
= 0;; c
= *s
++) {
4823 else if (isalpha(c
))
4824 c
-= isupper(c
) ? 'A' - 10 : 'a' - 10;
4829 if (any
< 0 || acc
> cutoff
|| (acc
== cutoff
&& c
> cutlim
))
4843 *endptr
= (char *) (any
? s
- 1 : nptr
);
4847 /*---------------------------------------------------------------------------*/
4849 /*> EOF gencode.c <*/