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 /* The Makefile currently defines "INSIDE_SIMULATOR" as part of the
26 build. It is not currently used by the MIPS simulator world
29 /* All output sent to stdout is for the simulator engine. All program
30 related warnings and errors should be sent to stderr. */
32 /* The simulator decode table is constructed this way to allow the
33 minimal code required for a particular instruction type to be
34 coded. This avoids a large simulator source file, with lots of
35 build-time conditionals controlling what code is included. However
36 this two-stage process does mean that care must be taken to ensure
37 that the correct decoding source is generated for a particular MIPS
42 We could provide pipeline modelling by splitting the simulation of
43 instructions into seperate bytecodes for each pipeline
44 stage. e.g. for the VR4300 each instruction would generate 5
45 bytecodes, one for each pipeline stage. The simulator control would
46 then insert these into the relevant pipeline slots, and execute a
47 complete slots worth of bytecodes. However, the shape of the
48 pipeline, and what parts of each instruction are executed in each
49 pipeline stage, are different between MIPS implementations. If we
50 were to construct a simulator for a particular MIPS architecture
51 this would be a good solution.
53 To avoid having to provide multiple different pipeline models, a
54 simple approach for dealing with the delay slots, and register
55 dependencies has been used. The "MIPS IV Instruction Set" document
56 (Revision 3.1 - January 1995) details the standard MIPS instruction
57 set, and it defines operations in instruction (not pipe-line)
58 cycles. This means we only need to worry about a few cases where
59 the result is not available until after the next instruction, or
60 where registers in the previous two instruction cycles may be
61 corrupted. The case for corruption only occurs with HI or LO
62 register access, so we can just keep a count within the engine for
63 upto two cycles before marking the register as safe. We then only
64 need to check the safety flag when performing an update that
65 involves the HI or LO register. The only other case is the
66 BC1F/BC1T instructions in the FP unit. For ISAs I, II and III there
67 must be an instruction between the FP CMP and the BC1[FT]. We can
68 perform the same instruction cycle count scheme, so we can raise a
69 warning if an attempt is made to access the condition code early
70 (NOTE: The hardware does not interlock on this operation, so the
71 simulator should just raise a warning).
73 For the situations where a result is not available until later, we
74 implent a slot to hold pending values. After the PC is incremented,
75 and before the instruction is decoded we can execute the required
76 register update (or remainder of instruction processing). */
78 /* The FP instruction decoding is also provided by this code. The
79 instructions are marked as "FP" ones so that we can construct a
80 simulator without an FPU if required. Similarly we mark
81 instructions as Single or Double precision, since some MIPS
82 processors only have single precision FP hardware. */
84 /* NOTE: Ideally all state should be passed as parameters. This allows
85 a single simulator engine to be used for multiple concurrent
86 simulations. More importantly, if a suitably powerful control is in
87 place it will allow speculative simulation, since the context can
88 be saved easily, and then restored after performing some
89 simulation. The down-side is that for certain host architectures it
90 can slow the simulator down (e.g. if globals can be accessed faster
91 than local structures). However, this is not actually the case at
92 the moment. The constructed engine uses direct names (that can be
93 macro definitions). This keeps the engine source smalled (using
94 short-hands), and it also allows the user to control whether they
95 want to use global, or indirected memory locations. i.e. whether
96 they want a single- or multi-threaded simulator engine. */
98 /* The constructed simulator engine contains manifests for each of the
99 features supported. The code that includes the engine can then
100 discover the available features during its build. This information
101 can be used to control run-time features provided by the final
104 /*---------------------------------------------------------------------------*/
106 /* Program defaults */
108 #define DEF_PROC64 (1 == 1)
109 #define DEF_FP (1 == 1)
110 #define DEF_FPSINGLE (1 == 0)
112 #define FEATURE_PROC32 (1 << 0) /* 0 = 64bit; 1 = 32bit */
113 #define FEATURE_HASFPU (1 << 1) /* 0 = no FPU; 1 = include FPU */
114 #define FEATURE_FPSINGLE (1 << 1) /* 0 = double; 1 = single (only used if FEATURE_HASFPU defined) */
115 #define FEATURE_GP64 (1 << 2) /* 0 = GPRLEN 32; 1 = GPRLEN 64 */
116 #define FEATURE_FAST (1 << 17) /* 0 = normal; 1 = disable features that slow performance */
117 #define FEATURE_WARN_STALL (1 << 24) /* 0 = nothing; 1 = generate warnings when pipeline would stall */
118 #define FEATURE_WARN_LOHI (1 << 25) /* 0 = nothing; 1 = generate warnings when LO/HI corrupted */
119 #define FEATURE_WARN_ZERO (1 << 26) /* 0 = nothing; 1 = generate warnings if attempt to write register zero */
120 #define FEATURE_WARN_MEM (1 << 27) /* 0 = nothing; 1 = generate warnings when memory problems are noticed */
121 #define FEATURE_WARN_R31 (1 << 28) /* 0 = nothing; 1 = generate warnings if r31 used dangerously */
122 #define FEATURE_WARN_RESULT (1 << 29) /* 0 = nothing; 1 = generate warnings when undefined results may occur */
125 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31)
127 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
130 /* FEATURE_WARN_STALL */
131 /* If MIPS I we want to raise a warning if an attempt is made to
132 access Rn in an instruction immediately following an Rn update
133 "WARNING : Invalid value read". The simulator engine is designed
134 that the previous value is read in such cases, to allow programs
135 that make use of this feature to execute. *
136 /* If MIPS II or later, attempting to read a register before the
137 update has completed will generate a "WARNING : Processor stall"
138 message (since the processor will lock the pipeline until the value
139 becomes available). */
141 /* FEATURE_WARN_LOHI */
142 /* Warn if an attempt is made to read the HI/LO registers before the
143 update has completed, or if an attempt is made to update the
144 registers whilst an update is occurring. */
146 /* FEATURE_WARN_ZERO */
147 /* Notify the user if an attempt is made to use GPR 0 as a destination. */
149 /* FEATURE_WARN_R31 */
150 /* Notify the user if register r31 (the default procedure call return
151 address) is used unwisely. e.g. If r31 is used as the source in a
152 branch-and-link instruction, it would mean that an exception in the
153 delay slot instruction would not allow the branch to be re-started
154 (since r31 will have been overwritten by the link operation during
155 the first execution of the branch). */
157 /* FEATURE_WARN_RESULT */
158 /* Certain instructions do not raise exceptions when invalid operands
159 are given, they will just result in undefined values being
160 generated. This option controls whether the simulator flags such
163 /*---------------------------------------------------------------------------*/
170 #include "ansidecl.h"
171 #include "opcode/mips.h"
173 /* FIXME: ansidecl.h defines AND. */
177 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
180 static unsigned long my_strtoul ();
184 #define TRUE (1 == 1)
185 #define FALSE (1 == 0)
189 /*---------------------------------------------------------------------------*/
191 /* Holding the instruction table this way makes it easier to check the
192 instruction values defined, and to add instructions to the
193 system. However, it makes the process of constructing the simulator
194 a bit more complicated: */
196 /* The "bitmap" is encoded as follows (NOTE: Only lower-case
197 alphabetic characters should be used, since the letter ordinal is
198 used as a bit position): */
200 typedef struct operand_encoding
{
201 char id
; /* character identifier */
202 int fpos
; /* first bit position */
203 int flen
; /* field length in bits */
209 /* Values for the "flags" field: */
210 #define OP_NONE (0 << 0) /* To keep the source tidy */
211 #define OP_GPR (1 << 0) /* Get operand from integer register bank */
212 #define OP_SIGNX (1 << 1) /* Sign-extend the operand */
213 #define OP_SHIFT2 (1 << 2) /* Shift field left by 2 */
214 #define OP_BITS5 (1 << 3) /* Only take the lo 5-bits of the operand */
216 struct operand_encoding opfields
[] = {
217 {'0',-1,-1,"", "", (OP_NONE
)}, /* special case for explicit zero */
218 {'1',-1,-1,"", "", (OP_NONE
)}, /* special case for explicit one */
219 {'?',-1,-1,"", "", (OP_NONE
)}, /* undefined (do not care at this level) */
220 /* The rest are the explicit operand fields: */
221 {'a', 6, 5,"int", "op1", (OP_NONE
)}, /* shift amount (or hint) */
222 {'b',21, 5,"int", "fr", (OP_NONE
)}, /* fr register */
223 {'c',16, 1,"int", "boolean", (OP_NONE
)}, /* TRUE or FALSE boolean */
224 {'d',11, 5,"int", "destreg", (OP_NONE
)}, /* integer destination/rd register */
225 {'e', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-3bits must be zero) */
226 {'f',17, 1,"int", "likely", (OP_NONE
)}, /* set if branch LIKELY */
227 {'g',16, 5,"t_reg", "op2", (OP_GPR
)}, /* integer source rt register */
228 {'h', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-1bit must be zero) */
229 {'i', 0,16,"t_reg", "op2", (OP_SIGNX
)}, /* signed immediate (op2) */
230 {'j', 0,26,"ut_reg","op1", (OP_SHIFT2
)},/* shifted left 2 bits and combined with hi-order bits of address in the delay slot */
231 {'k',16, 5,"int", "ft", (OP_NONE
)},
232 {'l', 0,16,"t_reg", "offset", (OP_SIGNX
| OP_SHIFT2
)}, /* signed offset shifted left 2 to make 18bit signed offset */
233 {'m',21, 3,"int", "format", (OP_NONE
)}, /* FP format field */
234 {'n',16, 5,"int", "hint", (OP_NONE
)}, /* hint */
235 {'o',21, 5,"t_reg", "op1", (OP_GPR
| OP_BITS5
)}, /* integer source/rs register (but never treated as 32bit word) */
236 {'p', 8, 3,"int", "condition_code",(OP_NONE
)}, /* FP condition code field */
237 {'q',18, 3,"int", "condition_code",(OP_NONE
)}, /* FP condition code field */
238 {'r', 6, 5,"int", "destreg", (OP_NONE
)}, /* FP fd register */
239 {'s',21, 5,"t_reg", "op1", (OP_GPR
)}, /* integer source/rs register */
240 {'t',16, 5,"int", "destreg", (OP_NONE
)}, /* integer target rt (destination) register */
241 {'u', 0, 4,"int", "cmpflags", (OP_NONE
)}, /* FP comparison control flags */
242 {'v',11, 5,"int", "fs", (OP_NONE
)}, /* FP fs register (or PREFX hint) */
243 {'w', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-2bits must be zero) */
244 {'x',23, 1,"int", "to", (OP_NONE
)}, /* TRUE if move To; FALSE if move From */
245 {'y', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset */
246 {'z', 0,16,"ut_reg","op2", (OP_NONE
)}, /* unsigned immediate (zero extended) */
249 /* Main instruction encoding types: */
256 COP1S
, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
260 /* Main instruction families: */
262 ADD
, /* res = operand1 + operand2 */
263 SUB
, /* res = operand1 - operand2 */
264 MUL
, /* res = operand1 * operand2 */
265 DIV
, /* res = operand1 / operand2 */
266 AND
, /* res = operand1 & operand2 */
267 OR
, /* res = operand1 | operand2 */
268 XOR
, /* res = operand1 ^ operand2 */
269 MOVE
, /* res = operand1 */
270 BRANCH
, /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
271 JUMP
, /* execute delay slot instruction before jump */
272 LOAD
, /* load from memory */
273 STORE
, /* store to memory */
274 PREFETCH
, /* prefetch data into cache */
275 SET
, /* set register on result of condition code */
276 SHIFT
, /* perform a logical or arithmetic shift */
277 TRAP
, /* system exception generation */
278 BREAK
, /* system breakpoint exception generation */
279 SYSCALL
, /* system exception generation */
280 SYNC
, /* system cache control */
281 DECODE
, /* co-processor instruction */
282 CACHE
, /* co-processor 0 CACHE instruction */
283 MADD16
, /* VR4100 specific multiply-add extensions */
301 RSVD
/* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
305 #define NONE (0 << 0) /* Zero value (used to keep source tidy) */
306 #define SIM_SH_SIZE (0)
307 #define SIM_MASK_SIZE (0x7)
308 #define BYTE (0) /* 8bit */
309 #define HALFWORD (1) /* 16bit */
310 #define WORD (2) /* 32bit */
311 #define DOUBLEWORD (3) /* 64bit */
312 #define SINGLE (4) /* single precision FP */
313 #define DOUBLE (5) /* double precision FP */
315 /* Shorthand to get the size field from the flags value: */
316 #define GETDATASIZE() ((MIPS_DECODE[loop].flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
318 /* The rest are single bit flags: */
319 #define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
324 #define LIKELY (1 << 8)
325 #define SIGNEXTEND (1 << 9)
326 #define OVERFLOW (1 << 10)
327 #define LINK (1 << 11)
328 #define ATOMIC (1 << 12)
329 #define SHIFT16 (1 << 13)
330 #define REG (1 << 14)
331 #define LEFT (1 << 15) /* Deliberate explicit encodings to allow check for neither, or both */
332 #define RIGHT (1 << 16) /* Mutually exclusive with "LEFT" */
333 #define LOGICAL (1 << 17)
334 #define ARITHMETIC (1 << 18)
335 #define UNSIGNED (1 << 19)
336 #define HI32 (1 << 20)
337 #define HI (1 << 21) /* accesses or updates the HI register */
338 #define LO (1 << 22) /* accesses or updates the LO register */
339 #define WORD32 (1 << 23)
340 #define FP (1 << 24) /* Floating Point operation */
341 #define FIXED (1 << 25) /* fixed point arithmetic */
342 #define COPROC (1 << 26)
343 #define INTEGER (1 << 27)
344 #define CONDITIONAL (1 << 28)
345 #define RECIP (1 << 29)
346 #define CONTROL (1 << 30)
347 #define NOARG (1 << 31) /* Instruction has no (defined) operands */
348 /* NOTE: We can overload the use of certain of these flags, since not
349 all options are applicable to all instruction types. This will free
350 up more space for new flags. */
352 typedef struct instruction
{
353 char *name
; /* ASCII mnemonic name */
354 unsigned int isa
; /* MIPS ISA number where instruction introduced */
355 char *bitmap
; /* 32character string describing instruction operands */
356 inst_type mark
; /* type of MIPS instruction encoding */
357 opcode_type type
; /* main instruction family */
358 unsigned int flags
; /* flags describing instruction features */
360 /* The number of pipeline cycles taken by an instruction varies
361 between MIPS processors. This means that the information must be
362 encoded elsewhere, in a CPU specific structure. */
364 /* NOTE: Undefined instructions cause "Reserved Instruction"
365 exceptions. i.e. if there is no bit-mapping defined then the
366 instruction is deemed to be undefined. */
368 /* NOTE: The "isa" field is also used to encode flags for particular
369 chip architecture extensions. e.g. the NEC VR4100 specific
370 instructions. Normally chip extensions are added via the COP0
371 space. However, the VR4100 (and possibly other devices) also use
372 the normal instruction space. */
373 #define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */
374 /* The other bits are allocated downwards, to avoid renumbering if we
375 have to extend the bits allocated to the pure ISA number. */
376 #define ARCH_VR4100 ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
378 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
379 COP0 space. This means that an external decoder should be added
380 when constructing a full VR4100 simulator. However some arithmetic
381 instructions are encoded in the normal instruction space. */
383 struct instruction MIPS_DECODE
[] = {
384 /* The instructions are alphabetical, and not in instruction bit-order: */
385 {"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1
, FPABS
, (FP
)},
386 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL
,ADD
, (WORD
| WORD32
| OVERFLOW
)}, /* rd = rs + rt */
387 {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1
, FPADD
, (FP
)},
388 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
| OVERFLOW
)},
389 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL
,ADD
, (WORD
| WORD32
)}, /* rd = rs + rt */
390 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
)},
391 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL
,AND
, (NONE
)}, /* rd = rs AND rt */
392 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, AND
, (NONE
)},
393 {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S
, BRANCH
, (FP
)},
394 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
)},
395 {"BEQL", 2,"010100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
| LIKELY
)},
396 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
)},
397 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
398 {"BGEZALL", 2,"000001sssss10011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
399 {"BGEZL", 2,"000001sssss00011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LIKELY
)},
400 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
)},
401 {"BGTZL", 2,"010111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
| LIKELY
)},
402 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
)},
403 {"BLEZL", 2,"010110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
| LIKELY
)},
404 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM
, BRANCH
, (LT
)},
405 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
)},
406 {"BLTZALL", 2,"000001sssss10010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
| LIKELY
)},
407 {"BLTZL", 2,"000001sssss00010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LIKELY
)},
408 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
)},
409 {"BNEL", 2,"010101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
| LIKELY
)},
410 {"BREAK", 1,"000000????????????????????001101",SPECIAL
,BREAK
, (NOARG
)},
411 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1
, FPCEIL
, (FP
| FIXED
| DOUBLEWORD
)},
412 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1
, FPCEIL
, (FP
| FIXED
| WORD
)},
413 {"COP0", 1,"010000??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
414 {"COP2", 1,"010010??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
415 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1
, FPCONVERT
,(FP
| DOUBLE
)},
416 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1
, FPCONVERT
,(FP
| FIXED
| DOUBLEWORD
)},
417 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1
, FPCONVERT
,(FP
| SINGLE
)},
418 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1
, FPCONVERT
,(FP
| FIXED
| WORD
)},
419 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1
, FPCOMPARE
,(FP
)},
420 {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
| CONTROL
)},
421 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL
,ADD
, (DOUBLEWORD
| OVERFLOW
)},
422 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| OVERFLOW
)},
423 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL
,ADD
, (DOUBLEWORD
| UNSIGNED
)},
424 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| UNSIGNED
)},
425 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL
,DIV
, (DOUBLEWORD
| HI
| LO
)},
426 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL
,DIV
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
427 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
)},
428 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1
, FPDIV
, (FP
| WORD
| HI
| LO
)},
429 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
)},
430 {"DMADD16", (ARCH_VR4100
| 3),"000000sssssggggg0000000000101001",SPECIAL
,MADD16
, (DOUBLEWORD
| HI
| LO
)},
431 {"DMULT", 3,"000000sssssggggg0000000000011100",SPECIAL
,MUL
, (DOUBLEWORD
| HI
| LO
)},
432 {"DMULTU", 3,"000000sssssggggg0000000000011101",SPECIAL
,MUL
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
433 {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| DOUBLEWORD
)},
434 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
)},
435 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
)},
436 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| HI32
)}, /* rd = rt << (sa + 32) */
437 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
)},
438 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
)},
439 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| HI32
)}, /* rd = rt >> (sa + 32) */
440 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
)},
441 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
)},
442 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| HI32
)},
443 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL
,SUB
, (DOUBLEWORD
)},
444 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL
,SUB
, (DOUBLEWORD
| UNSIGNED
)},
445 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1
, FPFLOOR
, (FP
| FIXED
| DOUBLEWORD
)},
446 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1
, FPFLOOR
, (FP
| FIXED
| WORD
)},
447 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (NONE
)}, /* NOTE: boundary case due to delay slot address being used */
448 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
)}, /* NOTE: boundary case due to delay slot address being used */
449 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL
,JUMP
, (LINK
| REG
)},
450 {"JR", 1,"000000sssss000000000000000001000",SPECIAL
,JUMP
, (NONE
)}, /* need to check PC as part of instruction fetch */
451 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
| SIGNEXTEND
)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
452 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
)}, /* NOTE: See "LB" comment */
453 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
)},
454 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
455 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
456 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| LEFT
)}, /* NOTE: See "LB" comment */
457 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| RIGHT
)}, /* NOTE: See "LB" comment */
458 {"LDXC1", 4,"010011sssssggggg00000rrrrr000001",COP1X
, LOAD
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
459 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
| SIGNEXTEND
)},
460 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
)},
461 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| ATOMIC
| SIGNEXTEND
)},
462 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| ATOMIC
)},
463 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL
, MOVE
, (SHIFT16
)}, /* Cheat and specify sign-extension of immediate field */
464 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| SIGNEXTEND
)},
465 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
466 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
467 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| LEFT
)},
468 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| RIGHT
)},
469 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
)},
470 {"LWXC1", 4,"010011sssssggggg00000rrrrr000000",COP1X
, LOAD
, (FP
| WORD
| COPROC
| REG
)},
471 {"MADD16", (ARCH_VR4100
| 3),"000000sssssggggg0000000000101000",SPECIAL
,MADD16
, (WORD
| HI
| LO
)},
472 {"MADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X
, FPADD
, (FP
| MULTIPLY
| DOUBLE
)},
473 {"MADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X
, FPADD
, (FP
| MULTIPLY
| SINGLE
)},
474 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL
,MOVE
, (HI
)}, /* with following, from and to denoted by usage of "s" or "d" */
475 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL
,MOVE
, (LO
)},
476 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL
,MOVE
, (HI
)},
477 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL
,MOVE
, (LO
)},
478 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1
, FPMOVE
, (FP
)},
479 {"MOVN", 4,"000000sssssgggggddddd00000001011",SPECIAL
,MOVE
, (NOT
| EQ
)},
480 {"MOVN", 4,"01000110mmmgggggvvvvvrrrrr010011",COP1
, FPMOVE
, (FP
| NOT
| EQ
)},
481 {"MOV%c", 4,"000000sssssqqq0cddddd00000000001",SPECIAL
,FPMOVE
, (FP
| CONDITIONAL
| INTEGER
)},
482 {"MOV%c", 4,"01000110mmmqqq0cvvvvvrrrrr010001",COP1
, FPMOVE
, (FP
| CONDITIONAL
)},
483 {"MOVZ", 4,"000000sssssgggggddddd00000001010",SPECIAL
,MOVE
, (EQ
)},
484 {"MOVZ", 4,"01000110mmmgggggvvvvvrrrrr010010",COP1
, FPMOVE
, (FP
| EQ
)},
485 {"MSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X
, FPSUB
, (FP
| MULTIPLY
| DOUBLE
)},
486 {"MSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X
, FPSUB
, (FP
| MULTIPLY
| SINGLE
)},
487 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1
, FPMUL
, (FP
| HI
| LO
)},
488 {"MULT", 1,"000000sssssggggg0000000000011000",SPECIAL
,MUL
, (WORD
| WORD32
| HI
| LO
)},
489 {"MULTU", 1,"000000sssssggggg0000000000011001",SPECIAL
,MUL
, (WORD
| WORD32
| HI
| LO
)},
490 {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
)},
491 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1
, FPNEG
, (FP
)},
492 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
493 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
494 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
495 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
496 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL
,OR
, (NOT
)},
497 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL
,OR
, (NONE
)},
498 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, OR
, (NONE
)},
499 {"PREF", 4,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, PREFETCH
, (NONE
)},
500 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X
, FPPREFX
, (FP
)},
501 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1
, FPRECIP
, (FP
)},
502 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1
, FPROUND
, (FP
| FIXED
| DOUBLEWORD
)},
503 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1
, FPROUND
, (FP
| FIXED
| WORD
)},
504 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1
, FPSQRT
, (FP
| RECIP
)},
505 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (BYTE
)},
506 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| ATOMIC
)},
507 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| ATOMIC
)},
508 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
)},
509 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
510 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
511 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| LEFT
)},
512 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| RIGHT
)},
513 {"SDXC1", 4,"010011sssssgggggvvvvv00000001001",COP1X
, STORE
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
514 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL
, STORE
, (HALFWORD
)},
515 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << sa */
516 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
517 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL
,SET
, (LT
)},
518 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
)},
519 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL
,SET
, (LT
| UNSIGNED
)},
520 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
| UNSIGNED
)},
521 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1
, FPSQRT
, (FP
)},
522 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
523 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
524 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
525 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
526 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL
,SUB
, (WORD
| WORD32
| OVERFLOW
)},
527 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1
, FPSUB
, (FP
)},
528 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL
,SUB
, (WORD
| WORD32
)},
529 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
)},
530 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
531 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
532 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| LEFT
)},
533 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| RIGHT
)},
534 {"SWXC1", 4,"010011sssssgggggvvvvv00000001000",COP1X
, STORE
, (FP
| WORD
| COPROC
| REG
)},
535 {"SYNC", 2,"000000000000000000000aaaaa001111",SPECIAL
,SYNC
, (NONE
)}, /* z = 5bit stype field */
536 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL
,SYSCALL
, (NOARG
)},
537 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL
,TRAP
, (EQ
)},
538 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (EQ
)},
539 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL
,TRAP
, (GT
| EQ
)},
540 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
)},
541 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
| UNSIGNED
)},
542 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL
,TRAP
, (GT
| EQ
| UNSIGNED
)},
543 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL
,TRAP
, (LT
)},
544 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
)},
545 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
| UNSIGNED
)},
546 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL
,TRAP
, (LT
| UNSIGNED
)},
547 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL
,TRAP
, (NOT
| EQ
)},
548 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (NOT
| EQ
)},
549 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1
, FPTRUNC
, (FP
| FIXED
| DOUBLEWORD
)},
550 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1
, FPTRUNC
, (FP
| FIXED
| WORD
)},
551 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL
,XOR
, (NONE
)},
552 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, XOR
, (NONE
)},
553 {"CACHE", 3,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, CACHE
, (NONE
)},
554 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, RSVD
, (NONE
)},
557 /*---------------------------------------------------------------------------*/
559 /* We use the letter ordinal as the bit-position in our flags field: */
560 #define fieldval(l) (1 << ((l) - 'a'))
563 convert_bitmap(bitmap
,onemask
,zeromask
,dontmask
)
565 unsigned int *onemask
, *zeromask
, *dontmask
;
567 unsigned int flags
= 0x00000000;
568 int loop
; /* current bitmap position */
569 int lastsp
= -1; /* last bitmap field starting position */
570 int lastoe
= -1; /* last bitmap field encoding */
572 *onemask
= 0x00000000;
573 *zeromask
= 0x00000000;
574 *dontmask
= 0x00000000;
576 if (strlen(bitmap
) != 32) {
577 fprintf(stderr
,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap
);
581 for (loop
= 0; (loop
< 32); loop
++) {
583 for (oefield
= 0; (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))); oefield
++)
584 if (bitmap
[31 - loop
] == opfields
[oefield
].id
)
586 if (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))) {
587 if ((lastoe
!= -1) && (lastoe
!= oefield
))
588 if ((loop
- lastsp
) != (opfields
[lastoe
].flen
)) {
589 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
);
593 switch (bitmap
[31 - loop
]) {
594 case '0' : /* fixed value */
595 *zeromask
|= (1 << loop
);
600 case '1' : /* fixed value */
601 *onemask
|= (1 << loop
);
606 case '?' : /* fixed value */
607 *dontmask
|= (1 << loop
);
612 default : /* check character encoding */
614 if (opfields
[oefield
].fpos
!= -1) {
615 /* If flag not set, then check starting position: */
616 if (!(flags
& fieldval(bitmap
[31 - loop
]))) {
617 if (loop
!= opfields
[oefield
].fpos
) {
618 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
);
621 flags
|= fieldval(bitmap
[31 - loop
]);
626 *dontmask
|= (1 << loop
);
631 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
);
636 /* NOTE: Since we check for the position and size of fields when
637 parsing the "bitmap" above, we do *NOT* need to check that invalid
638 field combinations have been used. */
643 /*---------------------------------------------------------------------------*/
646 build_operands(flags
)
650 for (loop
= 0; (loop
< (sizeof(opfields
) / sizeof(operand_encoding
))); loop
++)
651 if ((opfields
[loop
].fpos
!= -1) && (flags
& fieldval(opfields
[loop
].id
))) {
652 printf(" %s %s = ",opfields
[loop
].type
,opfields
[loop
].name
);
654 if (opfields
[loop
].flags
& OP_SIGNX
)
655 printf("SIGNEXTEND((%s)",opfields
[loop
].type
);
657 if (opfields
[loop
].flags
& OP_GPR
)
660 if (opfields
[loop
].flags
& OP_SHIFT2
)
663 printf("((instruction >> %d) & 0x%08X)",opfields
[loop
].fpos
,((1 << opfields
[loop
].flen
) - 1));
665 if (opfields
[loop
].flags
& OP_SHIFT2
)
668 if (opfields
[loop
].flags
& OP_GPR
)
671 if (opfields
[loop
].flags
& OP_BITS5
)
674 if (opfields
[loop
].flags
& OP_SIGNX
)
675 printf(",%d)",(opfields
[loop
].flen
+ ((opfields
[loop
].flags
& OP_SHIFT2
) ? 2 : 0)));
683 /*---------------------------------------------------------------------------*/
691 build_endian_shift(proc64
,datalen
,endbit
,direction
,shift
)
695 e_endshift direction
;
698 if (proc64
&& (datalen
== 4)) {
699 printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit
,endbit
);
700 printf(" memval %s= %d;\n",direction
== s_left
? "<<" : ">>",shift
);
707 /*---------------------------------------------------------------------------*/
708 /* doisa = number of MIPS ISA simulator table is being constructed for.
709 * proc64 = TRUE if constructing 64bit processor world.
710 * dofp = boolean, TRUE if FP instructions are to be included.
711 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
715 process_instructions(doarch
,features
)
717 unsigned int features
;
719 int doisa
= (doarch
& MASK_ISA
);
720 int limit
= (sizeof(MIPS_DECODE
) / sizeof(instruction
));
721 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
722 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
723 int dofp
= (features
& FEATURE_HASFPU
);
724 int fpsingle
= (features
& FEATURE_FPSINGLE
);
729 fprintf(stderr
,"process_instructions: invalid structure length\n");
733 if (proc64
&& (gprlen
!= 64)) {
734 fprintf(stderr
,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
738 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
741 for (loop
= 0; (loop
< limit
); loop
++)
742 if ((MIPS_DECODE
[loop
].isa
& MASK_ISA
) > maxisa
)
743 maxisa
= (MIPS_DECODE
[loop
].isa
& MASK_ISA
);
748 printf("#if defined(SIM_MANIFESTS)\n");
749 printf("#define MIPSISA (%d)\n",doisa
);
751 printf("#define PROCESSOR_64BIT (1 == 1)\n");
753 printf("#define PROCESSOR_64BIT (1 == 0)\n");
754 #if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */
755 printf("#define LOADDRMASK (0x%08X)\n",0x7);
757 printf("#define LOADDRMASK (0x%08X)\n",(proc64
? 0x7 : 0x3));
759 /* The FP registers are the same width as the CPU registers: */
760 printf("#define GPRLEN (%d)\n",gprlen
);
761 printf("typedef %s t_reg;\n",((gprlen
== 64) ? "word64" : "int"));
762 printf("typedef %s ut_reg;\n",((gprlen
== 64) ? "uword64" : "unsigned int"));
763 printf("typedef %s t_fpreg;\n",((gprlen
== 64) ? "word64" : "int"));
765 printf("#define HASFPU (1 == 1)\n");
766 if (features
& FEATURE_FAST
)
767 printf("#define FASTSIM (1 == 1)\n");
768 if (features
& FEATURE_WARN_STALL
)
769 printf("#define WARN_STALL (1 == 1)\n");
770 if (features
& FEATURE_WARN_LOHI
)
771 printf("#define WARN_LOHI (1 == 1)\n");
772 if (features
& FEATURE_WARN_ZERO
)
773 printf("#define WARN_ZERO (1 == 1)\n");
774 if (features
& FEATURE_WARN_MEM
)
775 printf("#define WARN_MEM (1 == 1)\n");
776 if (features
& FEATURE_WARN_R31
)
777 printf("#define WARN_R31 (1 == 1)\n");
778 if (features
& FEATURE_WARN_RESULT
)
779 printf("#define WARN_RESULT (1 == 1)\n");
781 printf("#else /* simulator engine */\n");
783 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
784 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64
? 64 : 32),doisa
,limit
);
786 printf("/* %sFP instructions included */\n",(fpsingle
? "Single precision " : ""));
787 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
790 printf("#if !defined(PROCESSOR_64BIT)\n");
791 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
795 printf("/* Actual instruction decoding block */\n");
799 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP
,OP_MASK_OP
);
800 limit
= (OP_MASK_OP
+ 1);
801 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
802 limit
+= (OP_MASK_SPEC
+ 1);
803 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_RT
,OP_MASK_RT
);
804 limit
+= (OP_MASK_RT
+ 1);
805 printf("else if (num == 0x11) {\n");
806 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM
,OP_SH_COP1NORM
,(OP_MASK_COP1NORM
<< OP_SH_COP1NORM
));
807 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP
,OP_SH_COP1CMP
,(OP_MASK_COP1CMP
<< OP_SH_COP1CMP
));
808 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,(OP_MASK_SPEC
& (OP_MASK_COP1CMP
<< OP_SH_COP1CMP
)));
810 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
811 limit
+= (OP_MASK_SPEC
+ 1);
813 /* To keep this code quick, we just clear out the "to" bit
814 here. The proper (though slower) code would be to have another
815 conditional, checking whether this instruction is a branch or
816 not, before limiting the range to the bottom two bits of the
818 printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit
,OP_SH_COP1SPEC
,OP_MASK_COP1SPEC
,OP_MASK_COP1SCLR
);
819 limit
+= (OP_MASK_COP1SPEC
+ 1);
820 printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
821 limit
+= (OP_MASK_SPEC
+ 1);
822 printf("/* Total possible switch entries: %d */\n",limit
) ;
824 printf("switch (num)\n") ;
827 for (loop
= 0; (loop
< limit
); loop
++) {
828 /* First check that the ISA number we are constructing for is
829 valid, before checking if the instruction matches any of the
830 architecture specific flags. NOTE: We allow a selected ISA of
831 zero to be used to match all standard instructions. */
832 if ((((MIPS_DECODE
[loop
].isa
& MASK_ISA
) <= doisa
) && (((MIPS_DECODE
[loop
].isa
& ~MASK_ISA
) == 0) || ((MIPS_DECODE
[loop
].isa
& ~MASK_ISA
) & doarch
) != 0)) && (!(MIPS_DECODE
[loop
].flags
& FP
) || ((MIPS_DECODE
[loop
].flags
& FP
) && dofp
))) {
833 unsigned int onemask
;
834 unsigned int zeromask
;
835 unsigned int dontmask
;
838 unsigned int flags
= convert_bitmap(MIPS_DECODE
[loop
].bitmap
,&onemask
,&zeromask
,&dontmask
);
839 char *regtype
= ((gprlen
== 64) ? "uword64" : "unsigned int");
841 if (!(MIPS_DECODE
[loop
].flags
& COPROC
) && ((GETDATASIZE() == DOUBLEWORD
) && !proc64
)) {
842 fprintf(stderr
,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE
[loop
].name
);
847 printf("/* DEBUG: onemask 0x%08X */\n",onemask
) ;
848 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask
) ;
849 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask
) ;
852 switch (MIPS_DECODE
[loop
].mark
) {
854 mask
= (OP_MASK_OP
<< OP_SH_OP
) ;
855 number
= ((onemask
>> OP_SH_OP
) & OP_MASK_OP
) ;
859 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
860 number
= ((OP_MASK_OP
+ 1) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
864 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_RT
<< OP_SH_RT
)) ;
865 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_RT
) & OP_MASK_RT
)) ;
869 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
870 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
874 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_COP1SPEC
<< OP_SH_COP1SPEC
)) ;
875 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_COP1SPEC
) & OP_MASK_COP1SPEC
)) ;
879 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
880 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
)) ;
884 fprintf(stderr
,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE
[loop
].mark
,loop
,MIPS_DECODE
[loop
].name
) ;
888 printf("case %d : /* \"%s\" %s */\n",number
,MIPS_DECODE
[loop
].name
,MIPS_DECODE
[loop
].bitmap
) ;
891 printf("/* DEBUG: mask 0x%08X */\n",mask
) ;
892 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE
[loop
].name
);
895 /* Check if there are any other explicit bits in the instruction: */
896 if ((~mask
& (onemask
| zeromask
)) != 0x00000000) {
897 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask
| zeromask
),onemask
) ;
899 printf(" SignalException(ReservedInstruction,instruction);\n") ;
904 if ((flags
== 0) && !(MIPS_DECODE
[loop
].flags
& NOARG
)) {
905 fprintf(stderr
,"Bitmap error: Instruction with no operand fields \"%s\"\n",MIPS_DECODE
[loop
].name
) ;
911 /* Get hold of the operands */
912 /* NOTE: If we wanted to make the simulator code smaller, we
913 * could pull these into a common sequence before we perform
914 * the instruction decoding. However, this would affect the
915 * performance since unnecessary field extraction would be
916 * occurring for certain instructions.
918 * Also we do not perform checking for multiple definitions of a
919 * particular operand here, since they are caught by the
920 * compilation of the produced code.
922 build_operands(flags
);
924 /* Finish constructing the jump address if required: */
925 if (flags
& fieldval('j'))
926 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
928 /* Now perform required operand checks: */
930 /* The following code has been removed, since it seems perfectly
931 reasonable to have a non-aligned offset that is added to another
932 non-aligned base to create an aligned address. Some more
933 information on exactly what the MIPS IV specification requires is
934 needed before deciding on the best strategy. Experimentation with a
935 VR4300 suggests that we do not need to raise the warning. */
937 /* For MIPS IV (and onwards), certain instruction operand values
938 will give undefined results. For the simulator we could
939 generate explicit exceptions (i.e. ReservedInstruction) to
940 make it easier to spot invalid use. However, for the moment we
941 just raise a warning. NOTE: This is a different check to the
942 later decoding, which checks for the final address being
944 if ((flags
& (fieldval('e') | fieldval('w') | fieldval('h'))) && (doisa
>= 4)) {
945 printf(" if (instruction & 0x%1X)\n",((flags
& fieldval('e')) ? 0x7 : ((flags
& fieldval('w')) ? 0x3 : 0x1)));
947 /* NOTE: If we change this to a SignalException(), we must
948 ensure that the following opcode processing is not
949 executed. i.e. the code falls straight out to the simulator
951 printf(" sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
956 /* The extended condition codes only appeared in ISA IV */
957 if ((flags
& fieldval('p')) && (doisa
< 4)) {
958 printf(" if (condition_code != 0)\n");
960 printf(" SignalException(ReservedInstruction,instruction);\n");
965 if ((MIPS_DECODE
[loop
].flags
& WORD32
) && (GETDATASIZE() != WORD
)) {
966 fprintf(stderr
,"Error in opcode table: WORD32 set for non-WORD opcode\n");
971 /* The R4000 book differs slightly from the MIPS IV ISA
972 manual. An example is the sign-extension of a 64-bit processor
973 SUBU operation, and what is meant by an Undefined Result. This
974 is now provided purely as a warning. After examining a HW
975 implementation, this is now purely a warning... and the actual
976 operation is performed, with possibly undefined results. */
977 if (((MIPS_DECODE
[loop
].flags
& WORD32
) && proc64
) && (features
& FEATURE_WARN_RESULT
)) {
978 /* The compiler should optimise out an OR with zero */
979 printf(" if (%s | %s)\n",((flags
& fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags
& fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
980 printf(" UndefinedResult();\n") ;
983 /* Check that the source is a 32bit value */
984 if ((MIPS_DECODE
[loop
].flags
& WORD32
) && proc64
) {
985 /* The compiler should optimise out an OR with zero */
986 printf(" if (%s | %s)\n",((flags
& fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags
& fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
987 printf(" UndefinedResult();\n") ;
994 switch (MIPS_DECODE
[loop
].type
) {
995 /* TODO: To make these easier to edit and maintain, they should
996 actually be provided as source macros (or inline functions)
997 OUTSIDE this main switch statement. The PPC simulator has a
998 neater scheme for describing the instruction sequences. */
1003 char *signed_basetype
= "unknown";
1004 char *unsigned_basetype
= "unknown";
1006 switch (GETDATASIZE()) {
1008 signed_basetype
= "signed int";
1009 unsigned_basetype
= "unsigned int";
1012 signed_basetype
= "word64";
1013 unsigned_basetype
= "uword64";
1016 fprintf(stderr
,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZE());
1020 if ((MIPS_DECODE
[loop
].type
) == ADD
) {
1021 printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype
, unsigned_basetype
);
1022 printf(" %s tempS = (%s)temp;\n", signed_basetype
, signed_basetype
);
1023 if (MIPS_DECODE
[loop
].flags
& OVERFLOW
) {
1024 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
1025 printf(" SignalException(IntegerOverflow);\n");
1028 if (!proc64
|| (MIPS_DECODE
[loop
].flags
& UNSIGNED
) || (GETDATASIZE() == DOUBLEWORD
))
1029 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
1030 else /* only sign-extend when placing 32bit result in 64bit processor */
1031 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
1033 printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype
, unsigned_basetype
);
1034 printf(" %s tempS = (%s)temp;\n", signed_basetype
, signed_basetype
);
1035 if (MIPS_DECODE
[loop
].flags
& OVERFLOW
) { /* different signs => overflow if result_sign != arg_sign */
1036 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
1037 printf(" SignalException(IntegerOverflow);\n");
1040 /* UNSIGNED 32bit operations on a 64bit processor should
1041 *STILL* be sign-extended. We have cheated in the
1042 data-structure, by not marking it with UNSIGNED, and not
1043 setting OVERFLOW. */
1044 if (!proc64
|| (MIPS_DECODE
[loop
].flags
& UNSIGNED
) || (GETDATASIZE() == DOUBLEWORD
))
1045 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
1046 else /* only sign-extend when placing 32bit result in 64bit processor */
1047 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
1053 if (features
& FEATURE_WARN_LOHI
) {
1054 printf(" CHECKHILO(\"Multiplication\");\n");
1057 if (GETDATASIZE() == DOUBLEWORD
) {
1058 printf(" uword64 mid;\n");
1059 printf(" uword64 temp;\n");
1060 printf(" LO = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n");
1061 printf(" HI = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n");
1062 printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
1063 printf(" temp = (LO + SET64HI(WORD64LO(mid)));\n");
1064 printf(" if ((temp == mid) ? (LO != 0) : (temp < mid))\n");
1065 printf(" HI += 1;\n");
1066 printf(" HI += WORD64HI(mid);\n");
1067 printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
1068 printf(" LO = (temp + SET64HI(WORD64LO(mid)));\n");
1069 printf(" if ((LO == mid) ? (temp != 0) : (LO < mid))\n");
1070 printf(" HI += 1;\n");
1071 printf(" HI += WORD64HI(mid);\n");
1073 printf(" uword64 temp = (op1 * op2);\n");
1074 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype
);
1075 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype
);
1082 int boolU
= (MIPS_DECODE
[loop
].flags
& UNSIGNED
);
1084 if (features
& FEATURE_WARN_LOHI
) {
1085 printf(" CHECKHILO(\"Division\");\n");
1088 if (GETDATASIZE() == DOUBLEWORD
) {
1089 printf(" LO = ((%sword64)op1 / (%sword64)op2);\n",(boolU
? "u" : ""),(boolU
? "u" : ""));
1090 printf(" HI = ((%sword64)op1 %c (%sword64)op2);\n",(boolU
? "u" : ""),'%',(boolU
? "u" : ""));
1092 printf(" LO = SIGNEXTEND(((%sint)op1 / (%sint)op2),32);\n",(boolU
? "unsigned " : ""),(boolU
? "unsigned " : ""));
1093 printf(" HI = SIGNEXTEND(((%sint)op1 %c (%sint)op2),32);\n",(boolU
? "unsigned " : ""),'%',(boolU
? "unsigned " : ""));
1101 int datalen
= GETDATASIZE();
1102 int bits
= ((datalen
== WORD
) ? 32 : 64);
1103 char *ltype
= ((datalen
== WORD
) ? "unsigned int" : "uword64");
1105 /* Check that the specified SHIFT is valid: */
1106 if ((datalen
== BYTE
) || (datalen
== HALFWORD
)) {
1107 fprintf(stderr
,"Shift \"%s\" specified with BYTE or HALFWORD\n",MIPS_DECODE
[loop
].name
);
1110 if ((MIPS_DECODE
[loop
].flags
& LEFT
) && (MIPS_DECODE
[loop
].flags
& RIGHT
)) {
1111 fprintf(stderr
,"Shift \"%s\" specified with both LEFT and RIGHT\n",MIPS_DECODE
[loop
].name
);
1114 if (!(MIPS_DECODE
[loop
].flags
& LEFT
) && !(MIPS_DECODE
[loop
].flags
& RIGHT
)) {
1115 fprintf(stderr
,"Shift \"%s\" specified with neither LEFT or RIGHT\n",MIPS_DECODE
[loop
].name
);
1118 if ((MIPS_DECODE
[loop
].flags
& LOGICAL
) && (MIPS_DECODE
[loop
].flags
& ARITHMETIC
)) {
1119 fprintf(stderr
,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",MIPS_DECODE
[loop
].name
);
1122 if (!(MIPS_DECODE
[loop
].flags
& LOGICAL
) && !(MIPS_DECODE
[loop
].flags
& ARITHMETIC
)) {
1123 fprintf(stderr
,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",MIPS_DECODE
[loop
].name
);
1126 if ((MIPS_DECODE
[loop
].flags
& LEFT
) && (MIPS_DECODE
[loop
].flags
& ARITHMETIC
)) {
1127 fprintf(stderr
,"Arithmetic LEFT shift \"%s\" specified\n",MIPS_DECODE
[loop
].name
);
1131 /* If register specified shift, then extract the relevant shift amount: */
1132 if (flags
& fieldval('s'))
1133 printf(" op1 &= 0x%02X;\n",(bits
- 1));
1135 /* If HI32 specified, then shift range is 32..63 */
1136 if (MIPS_DECODE
[loop
].flags
& HI32
)
1137 printf(" op1 |= (1 << 6);\n");
1139 /* We do not need to perform pre-masking with 0xFFFFFFFF when
1140 dealing with 32bit shift lefts, since the sign-extension
1141 code will replace any remaining hi-bits: */
1142 if (MIPS_DECODE
[loop
].flags
& LEFT
)
1143 printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
1145 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits
== 32) ? " & 0xFFFFFFFF" : ""));
1147 /* For ARITHMETIC shifts, we must duplicate the sign-bit */
1148 if (MIPS_DECODE
[loop
].flags
& ARITHMETIC
)
1149 printf(" GPR[destreg] |= ((op2 & ((%s)1 << %d)) ? ((((%s)1 << (op1 + 1)) - 1) << (%d - op1)) : 0);\n",ltype
,(bits
- 1),ltype
,(bits
- 1));
1151 /* Ensure WORD values are sign-extended into 64bit registers */
1152 if ((bits
== 32) && (gprlen
== 64))
1153 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits
);
1158 if (MIPS_DECODE
[loop
].flags
& (HI
| LO
)) {
1159 char *regname
= ((MIPS_DECODE
[loop
].flags
& LO
) ? "LO" : "HI");
1160 if (flags
& fieldval('d'))
1161 printf(" GPR[destreg] = %s;\n",regname
);
1163 if (features
& FEATURE_WARN_LOHI
) {
1164 printf(" if (%sACCESS != 0)\n",regname
);
1165 printf(" sim_warning(\"MT (move-to) over-writing %s register value\");\n",regname
);
1167 printf(" %s = op1;\n",regname
);
1169 if (features
& FEATURE_WARN_LOHI
)
1170 printf(" %sACCESS = 3; /* 3rd instruction will be safe */\n",regname
);
1172 if (MIPS_DECODE
[loop
].flags
& SHIFT16
)
1173 printf(" GPR[destreg] = (op2 << 16);\n");
1175 /* perform conditional move */
1176 if (!(MIPS_DECODE
[loop
].flags
& EQ
)) {
1177 fprintf(stderr
,"Standard conditional %s does not have the equality flag\n",MIPS_DECODE
[loop
].name
);
1180 printf(" if (op2 %c= 0)\n",((MIPS_DECODE
[loop
].flags
& NOT
) ? '!' : '='));
1181 printf(" GPR[destreg] = op1;\n");
1186 printf(" SyncOperation(op1);\n");
1190 printf(" SignalException(SystemCall);\n");
1194 printf(" SignalException(BreakPoint);\n");
1199 int boolNOT
= (MIPS_DECODE
[loop
].flags
& NOT
);
1200 int boolEQ
= (MIPS_DECODE
[loop
].flags
& EQ
);
1201 int boolGT
= (MIPS_DECODE
[loop
].flags
& GT
);
1202 int boolLT
= (MIPS_DECODE
[loop
].flags
& LT
);
1203 int boolU
= (MIPS_DECODE
[loop
].flags
& UNSIGNED
);
1205 if (boolGT
&& boolLT
) {
1206 fprintf(stderr
,"GT and LT specified for \"%s\"\n",MIPS_DECODE
[loop
].name
);
1210 if (boolNOT
&& (boolGT
|| boolLT
)) {
1211 fprintf(stderr
,"NOT specified with GT or LT specified for \"%s\"\n",MIPS_DECODE
[loop
].name
);
1215 printf(" if ((%sword64)op1 ",(boolU
? "u" : ""));
1216 printf("%c%s",(boolNOT
? '!' : (boolLT
? '<' : (boolGT
? '>' : '='))),(boolEQ
? "=" : ""));
1217 printf(" (%sword64)op2)\n",(boolU
? "u" : ""));
1218 printf(" SignalException(Trap);\n");
1224 int boolU
= (MIPS_DECODE
[loop
].flags
& UNSIGNED
);
1226 if (!(MIPS_DECODE
[loop
].flags
& LT
)) {
1227 fprintf(stderr
,"Set instruction without LT specified \"%s\"\n",MIPS_DECODE
[loop
].name
);
1231 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU
? "u" : ""),(boolU
? "u" : ""));
1232 printf(" GPR[destreg] = 1;\n");
1234 printf(" GPR[destreg] = 0;\n");
1239 printf(" GPR[destreg] = (op1 & op2);\n");
1243 printf(" GPR[destreg] = %s(op1 | op2);\n",((MIPS_DECODE
[loop
].flags
& NOT
) ? "~" : ""));
1247 printf(" GPR[destreg] = (op1 ^ op2);\n");
1251 printf(" decode_coproc(instruction);\n");
1255 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
1256 /* The virtual address is translated to a physical address using the TLB */
1257 /* The hint specifies a cache operation for that address */
1258 printf(" uword64 vaddr = (op1 + offset);\n");
1259 printf(" uword64 paddr;\n");
1260 printf(" int uncached;\n");
1261 /* NOTE: We are assuming that the AddressTranslation is a load: */
1262 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
1263 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
1266 case MADD16
: /* VR4100 specific multiply-add instructions */
1267 /* Some of this code is shared with the standard multiply
1268 routines, so an effort should be made to merge where
1270 if (features
& FEATURE_WARN_LOHI
) {
1271 printf(" CHECKHILO(\"Multiply-Add\");\n");
1273 if (features
& FEATURE_WARN_RESULT
) {
1274 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
1275 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
1276 printf(" sim_warning(\"MADD16 operation with non-16bit operands\");\n");
1279 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
1280 if (GETDATASIZE() == DOUBLEWORD
) {
1281 printf(" LO = LO + temp;\n");
1283 printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
1284 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype
);
1285 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype
);
1290 case RSVD
: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
1292 printf(" if (CoProcPresent(3))\n");
1293 printf(" SignalException(CoProcessorUnusable);\n");
1296 printf(" SignalException(ReservedInstruction,instruction);\n");
1300 if (MIPS_DECODE
[loop
].flags
& LINK
) {
1301 if (!(MIPS_DECODE
[loop
].flags
& REG
))
1302 printf(" int destreg = 31;\n");
1303 printf(" GPR[destreg] = (PC + 4); /* NOTE: The PC is already 4 ahead within the simulator */\n");
1306 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
1307 printf(" DSPC = op1;\n");
1308 printf(" DELAYSLOT();\n");
1311 case BRANCH
: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
1312 if (MIPS_DECODE
[loop
].flags
& FP
) {
1314 printf(" if (condition_code != 0)\n");
1315 printf(" SignalException(ReservedInstruction,instruction);\n");
1316 printf(" else {\n");
1318 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
1319 printf(" int condition = (%s == boolean);\n",((doisa
< 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
1321 if ((MIPS_DECODE
[loop
].flags
& NOT
) && !(MIPS_DECODE
[loop
].flags
& EQ
)) {
1322 fprintf(stderr
,"NOT specified when not EQ in \"%s\"\n",MIPS_DECODE
[loop
].name
);
1325 if ((MIPS_DECODE
[loop
].flags
& NOT
) && (MIPS_DECODE
[loop
].flags
& (GT
| LT
))) {
1326 fprintf(stderr
,"NOT specified with GT or LT in \"%s\"\n",MIPS_DECODE
[loop
].name
);
1330 if (MIPS_DECODE
[loop
].flags
& GT
)
1331 printf(" int condition = (op1 >%s 0);\n",((MIPS_DECODE
[loop
].flags
& EQ
) ? "=" : ""));
1333 if (MIPS_DECODE
[loop
].flags
& LT
)
1334 printf(" int condition = (op1 <%s 0);\n",((MIPS_DECODE
[loop
].flags
& EQ
) ? "=" : ""));
1336 if (MIPS_DECODE
[loop
].flags
& EQ
)
1337 printf(" int condition = (op1 %c= op2);\n",((MIPS_DECODE
[loop
].flags
& NOT
) ? '!' : '='));
1340 if (MIPS_DECODE
[loop
].flags
& LINK
) {
1341 if (features
& FEATURE_WARN_R31
) {
1342 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS
,OP_MASK_RS
);
1343 printf(" sim_warning(\"Branch with link using r31 as source operand\");\n");
1345 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
1348 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
1349 printf(" if (condition) {\n");
1350 printf(" DSPC = (PC + offset);\n");
1351 printf(" DELAYSLOT();\n");
1353 if ((MIPS_DECODE
[loop
].flags
& FP
) && (doisa
!= 1)) {
1354 printf(" else if (likely) {\n");
1355 printf(" NULLIFY();\n");
1357 } else if (MIPS_DECODE
[loop
].flags
& LIKELY
) {
1359 printf(" NULLIFY();\n");
1361 if ((MIPS_DECODE
[loop
].flags
& FP
) && (doisa
< 4))
1365 case PREFETCH
: /* The beginning is shared with normal load operations */
1369 int isload
= ((MIPS_DECODE
[loop
].type
== LOAD
) || (MIPS_DECODE
[loop
].type
== PREFETCH
));
1371 char *accesslength
= "<UNKNOWN>";
1373 switch (GETDATASIZE()) {
1376 accesslength
= "AccessLength_BYTE";
1381 accesslength
= "AccessLength_HALFWORD";
1386 accesslength
= "AccessLength_WORD";
1391 accesslength
= "AccessLength_DOUBLEWORD";
1395 if (MIPS_DECODE
[loop
].flags
& REG
)
1396 printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
1398 printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
1399 printf(" uword64 paddr;\n");
1400 printf(" int uncached;\n");
1402 /* The following check should only occur on normal (non-shifted) memory loads */
1403 if ((datalen
!= 1) && !(MIPS_DECODE
[loop
].flags
& (LEFT
| RIGHT
))) {
1404 printf(" if ((vaddr & %d) != 0)\n",(datalen
- 1));
1405 printf(" SignalException(%s);\n",(isload
? "AddressLoad" : "AddressStore"));
1410 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload
? "isLOAD" : "isSTORE"));
1412 if (MIPS_DECODE
[loop
].type
== PREFETCH
)
1413 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
1416 printf(" %s memval;\n",(proc64
? "uword64" : "unsigned int"));
1418 if ((MIPS_DECODE
[loop
].flags
& COPROC
) && ((datalen
!= 4) && (datalen
!= 8))) {
1419 fprintf(stderr
,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE
[loop
].name
);
1423 if (MIPS_DECODE
[loop
].flags
& (LEFT
| RIGHT
)) {
1424 if ((MIPS_DECODE
[loop
].flags
& LEFT
) && (MIPS_DECODE
[loop
].flags
& RIGHT
)) {
1425 fprintf(stderr
,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",MIPS_DECODE
[loop
].name
);
1432 fprintf(stderr
,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",MIPS_DECODE
[loop
].name
);
1435 /* fall through to... */
1438 char *maskstr
= ((datalen
== 8) ? "((uword64)-1)" : "0xFFFFFFFF");
1440 printf(" uword64 mask = %d;\n",((datalen
== 8) ? 0x7 : 0x3));
1441 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
1442 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
1443 printf(" int byte;\n");
1444 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
1445 printf(" byte = ((vaddr & mask) ^ bigend);\n");
1446 printf(" if (%sBigEndianMem)\n",((MIPS_DECODE
[loop
].flags
& LEFT
) ? "!" : ""));
1447 printf(" paddr &= ~mask;\n");
1450 if (MIPS_DECODE
[loop
].flags
& LEFT
)
1451 printf(" memval = LoadMemory(uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
1453 printf(" memval = LoadMemory(uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen
- 1));
1456 if (MIPS_DECODE
[loop
].flags
& LEFT
) {
1458 /* For WORD transfers work out if the value will
1459 be in the top or bottom of the DOUBLEWORD
1462 build_endian_shift(proc64
,datalen
,2,s_right
,32);
1464 if (proc64
&& (datalen
== 4)) {
1465 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1466 printf(" memval >>= 32;\n");
1470 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen
- 1),(datalen
- 1));
1471 if (proc64
&& (datalen
== 4))
1472 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
1473 } else { /* store */
1474 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen
- 1));
1476 build_endian_shift(proc64
,datalen
,2,s_left
,32);
1478 /* TODO: This is duplicated in the LOAD code
1479 above - and the RIGHT LOAD and STORE code
1480 below. It should be merged if possible. */
1481 if (proc64
&& (datalen
== 4)) {
1482 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1483 printf(" memval <<= 32;\n");
1487 printf(" StoreMemory(uncached,byte,memval,paddr,vaddr,isREAL);\n");
1489 } else { /* RIGHT */
1492 build_endian_shift(proc64
,datalen
,2,s_right
,32);
1494 if (proc64
&& (datalen
== 4)) {
1495 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1496 printf(" memval >>= 32;\n");
1501 printf(" uword64 srcmask;\n");
1502 /* All of this extra code is just a bodge
1503 required because some hosts don't allow
1504 ((v) << 64). The SPARC just leaves the (v)
1505 value un-touched. */
1506 printf(" if (byte == 0)\n");
1507 printf(" srcmask = 0;\n");
1509 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen
);
1510 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n",datalen
);
1512 if (proc64
&& (datalen
== 4))
1513 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
1514 } else { /* store */
1515 printf(" memval = (op2 << (byte * 8));\n");
1516 printf(" StoreMemory(uncached,(%s - byte),memval,paddr,vaddr,isREAL);\n",accesslength
);
1523 fprintf(stderr
,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE
[loop
].name
);
1526 } else { /* normal memory transfer */
1527 if (!(MIPS_DECODE
[loop
].flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (MIPS_DECODE
[loop
].flags
& UNSIGNED
))) && !proc64
) {
1528 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",MIPS_DECODE
[loop
].name
);
1530 /* TODO: The R4000 documentation states that a LWU
1531 instruction executed when in a 32bit processor mode
1532 should cause a ReservedInstruction exception. This
1533 will mean adding a run-time check into the code
1538 #if 1 /* see the comments attached to LOADDRMASK above */
1539 printf(" uword64 mask = 0x7;\n");
1541 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
1543 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
1544 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
1545 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
1546 printf(" unsigned int byte;\n");
1548 /* TODO: This should really also check for 32bit world performing 32bit access */
1549 if (datalen
!= 8) /* not for DOUBLEWORD */
1550 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
1552 printf(" memval = LoadMemory(uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength
);
1554 /* The following will only make sense if the
1555 "LoadMemory" above returns a DOUBLEWORD entity */
1556 if (datalen
!= 8) { /* not for DOUBLEWORD */
1568 valmask
= 0xFFFFFFFF;
1572 fprintf(stderr
,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen
,MIPS_DECODE
[loop
].name
);
1575 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
1576 /* NOTE: The R4000 user manual has the COP_LW
1577 occuring in the same cycle as the rest of the
1578 instruction, yet the MIPS IV shows the operation
1579 happening on the next cycle. To keep the simulator
1580 simple, this code follows the R4000
1581 manual. Experimentation with a silicon
1582 implementation will be needed to ascertain the
1583 correct operation. */
1584 if (MIPS_DECODE
[loop
].flags
& COPROC
)
1585 printf(" COP_LW(((instruction >> 26) & 0x3),destreg,(unsigned int)");
1587 printf(" GPR[destreg] = (");
1589 if (MIPS_DECODE
[loop
].flags
& SIGNEXTEND
)
1590 printf("SIGNEXTEND(");
1591 printf("((memval >> (8 * byte)) & 0x%08X)",valmask
);
1592 if (MIPS_DECODE
[loop
].flags
& SIGNEXTEND
)
1593 printf(",%d)",(datalen
* 8));
1596 if (MIPS_DECODE
[loop
].flags
& COPROC
)
1597 printf(" COP_LD(((instruction >> 26) & 0x3),destreg,memval);;\n");
1599 printf(" GPR[destreg] = memval;\n");
1601 } else { /* store operation */
1602 if ((datalen
== 1) || (datalen
== 2)) {
1604 #if 1 /* see the comments attached to LOADDRMASK above */
1605 printf(" uword64 mask = 0x7;\n");
1607 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
1609 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
1610 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
1611 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
1612 printf(" unsigned int byte;\n");
1614 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
1615 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
1616 printf(" memval = (op2 << (8 * byte));\n");
1618 if (proc64
&& (datalen
== 4)) { /* proc64 SC and SW */
1619 #if 1 /* see the comments attached to LOADDRMASK above */
1620 printf(" uword64 mask = 0x7;\n");
1622 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
1624 printf(" unsigned int byte;\n");
1625 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
1626 printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
1627 if (MIPS_DECODE
[loop
].flags
& COPROC
)
1628 printf(" memval = (((uword64)COP_SW(((instruction >> 26) & 0x3),%s)) << (8 * byte));\n",((MIPS_DECODE
[loop
].flags
& FP
) ? "fs" : "destreg"));
1630 printf(" memval = (op2 << (8 * byte));\n");
1631 } else { /* !proc64 SC and SW, plus proc64 SD and SCD */
1632 if (MIPS_DECODE
[loop
].flags
& COPROC
)
1633 printf(" memval = (uword64)COP_S%c(((instruction >> 26) & 0x3),%s);\n",((datalen
== 8) ? 'D' : 'W'),((MIPS_DECODE
[loop
].flags
& FP
) ? "fs" : "destreg"));
1635 printf(" memval = op2;\n");
1638 if (MIPS_DECODE
[loop
].flags
& ATOMIC
)
1639 printf(" if (LLBIT)\n");
1642 printf(" StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength
);
1646 if (MIPS_DECODE
[loop
].flags
& ATOMIC
) {
1647 if ((datalen
!= 4) && (datalen
!= 8)) {
1648 fprintf(stderr
,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",MIPS_DECODE
[loop
].name
);
1652 printf(" LLBIT = 1;\n");
1654 /* The documentation states that:
1656 SC *WILL* fail if coherent store into the same
1657 block occurs, or if an exception occurs between
1658 the LL and SC instructions.
1660 SC *MAY* fail if a load, store or prefetch is
1661 executed on the processor (VR4300 doesn't seem
1662 to), or if the instructions between the LL and
1663 SC are not in a 2048byte contiguous VM range.
1665 SC *MUST* have been preceded by an LL
1666 (i.e. LLBIT will be set), and it must use the
1667 same Vaddr, Paddr and cache-coherence algorithm
1668 as the LL (which means we should store this
1669 information from the load-conditional).
1671 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT
,OP_MASK_RT
);
1682 /* This code could be merged with the PREFIX generation above: */
1683 printf(" uword64 vaddr = ((uword64)op1 + (uword64)op2);\n");
1684 printf(" uword64 paddr;\n");
1685 printf(" int uncached;\n");
1686 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
1687 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
1691 if (MIPS_DECODE
[loop
].flags
& CONTROL
) {
1692 /* The following "magic" of interpreting the FP
1693 control-register number would not be needed if we were not
1694 trying to match our internal register numbers with those
1696 printf(" if (to) {\n");
1698 printf(" if (fs == 0) {\n");
1699 printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
1700 printf(" } else if (fs == 31) {\n");
1701 printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
1702 printf(" } /* else NOP */\n");
1703 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
1705 printf(" if (fs == 0) {\n");
1706 printf(" FCR0 = WORD64LO(GPR[ft]);\n");
1707 printf(" } else if (fs == 31) {\n");
1708 printf(" FCR31 = WORD64LO(GPR[ft]);\n");
1709 printf(" } /* else NOP */\n");
1710 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
1712 printf(" } else { /* control from */\n");
1714 printf(" if (fs == 0) {\n");
1715 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
1716 printf(" } else if (fs == 31) {\n");
1717 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
1718 printf(" } /* else NOP */\n");
1720 printf(" if (fs == 0) {\n");
1721 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
1722 printf(" } else if (fs == 31) {\n");
1723 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
1724 printf(" } /* else NOP */\n");
1728 printf(" if (to) {\n");
1729 if (GETDATASIZE() == WORD
) {
1731 printf(" if (SizeFGR() == 64) {\n");
1732 printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
1733 printf(" } else { \n");
1734 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
1737 printf(" if (SizeFGR() == 64)\n");
1738 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
1740 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
1741 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
1743 } else if (GETDATASIZE() == DOUBLEWORD
) {
1745 printf(" if (SizeFGR() == 64) {\n");
1746 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
1747 printf(" } else\n");
1748 printf(" if ((fs & 0x1) == 0)\n");
1750 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
1751 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
1753 if (features
& FEATURE_WARN_RESULT
) {
1755 printf(" UndefinedResult();\n");
1758 printf(" if (SizeFGR() == 64) {\n");
1759 printf(" FGR[fs] = GPR[ft];\n");
1760 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
1761 printf(" } else\n");
1762 printf(" if ((fs & 0x1) == 0)\n");
1764 printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
1765 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
1766 printf(" fpr_state[fs + 1] = fmt_uninterpreted;\n");
1767 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
1769 if (features
& FEATURE_WARN_RESULT
) {
1771 printf(" UndefinedResult();\n");
1775 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
1778 printf(" } else {\n");
1779 if (GETDATASIZE() == WORD
) {
1780 if (doisa
< 4) /* write-back occurs in next cycle */
1781 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
1782 else /* in this cycle */
1783 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
1784 } else if (GETDATASIZE() == DOUBLEWORD
) {
1786 printf(" if (SizeFGR() == 64) {\n");
1787 printf(" PENDING_FILL(ft,FGR[fs]);\n");
1788 printf(" } else\n");
1789 printf(" if ((fs & 0x1) == 0) {\n");
1790 printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
1791 printf(" } else {\n");
1792 printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
1793 if (features
& FEATURE_WARN_RESULT
)
1794 printf(" UndefinedResult();\n");
1797 printf(" if (SizeFGR() == 64)\n");
1798 printf(" GPR[ft] = FGR[fs];\n");
1800 printf(" if ((fs & 0x1) == 0)\n");
1801 printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
1802 printf(" else {\n");
1803 printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
1804 if (features
& FEATURE_WARN_RESULT
)
1805 printf(" UndefinedResult();\n");
1809 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
1817 if (MIPS_DECODE
[loop
].flags
& CONDITIONAL
) {
1818 if (MIPS_DECODE
[loop
].flags
& INTEGER
) { /* moving GPR - testing FGR */
1819 printf(" if (GETFCC(condition_code) == boolean)\n");
1820 printf(" GPR[destreg] = op1;\n");
1822 if (MIPS_DECODE
[loop
].flags
& EQ
) /* moving FGR - testing GPR */
1823 printf(" if (op2 %c= 0)\n",((MIPS_DECODE
[loop
].flags
& NOT
) ? '!' : '='));
1825 printf(" if (GETFCC(condition_code) == boolean)\n");
1826 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
1828 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
1830 } else { /* simple MOVE */
1831 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
1836 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1837 printf(" SignalException(ReservedInstruction,instruction);\n");
1839 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
1843 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1844 printf(" SignalException(ReservedInstruction,instruction);\n");
1846 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
1850 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1851 printf(" SignalException(ReservedInstruction,instruction);\n");
1853 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1857 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1858 printf(" SignalException(ReservedInstruction,instruction);\n");
1860 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1864 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1865 printf(" SignalException(ReservedInstruction,instruction);\n");
1867 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
1871 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1872 printf(" SignalException(ReservedInstruction,instruction);\n");
1874 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((MIPS_DECODE
[loop
].flags
& RECIP
) ? "Recip" : ""));
1885 switch (MIPS_DECODE
[loop
].type
) {
1887 op
= "FP_RM_TOPINF";
1890 op
= "FP_RM_TOMINF";
1893 op
= "FP_RM_TOZERO";
1896 op
= "FP_RM_NEAREST";
1899 fprintf(stderr
,"Error: Handled missing for FP reason code %d\n",MIPS_DECODE
[loop
].type
);
1903 switch (GETDATASIZE()) {
1911 fprintf(stderr
,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op
);
1914 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1915 printf(" SignalException(ReservedInstruction,instruction);\n");
1917 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type
,op
,type
);
1924 switch (GETDATASIZE()) {
1926 type
= "fmt_single";
1929 type
= "fmt_double";
1938 fprintf(stderr
,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZE());
1942 /* Not all combinations of conversion are valid at the
1943 moment: When converting to a fixed-point format, only
1944 floating-point sources are allowed. */
1945 printf(" if ((format == %s) | %s)\n",type
,((MIPS_DECODE
[loop
].flags
& FIXED
) ? "((format == fmt_long) || (format == fmt_word))": "0"));
1946 printf(" SignalException(ReservedInstruction,instruction);\n");
1948 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type
,type
);
1953 if (MIPS_DECODE
[loop
].flags
& MULTIPLY
) {
1955 switch (GETDATASIZE()) {
1957 type
= "fmt_single";
1960 type
= "fmt_double";
1963 fprintf(stderr
,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZE());
1966 printf(" StoreFPR(destreg,%s,%s(Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",type
,((MIPS_DECODE
[loop
].flags
& NOT
) ? "Negate" : ""),type
,type
,type
,type
,type
,type
);
1968 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1969 printf(" SignalException(ReservedInstruction,instruction);\n");
1971 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1976 if (MIPS_DECODE
[loop
].flags
& MULTIPLY
) {
1978 switch (GETDATASIZE()) {
1980 type
= "fmt_single";
1983 type
= "fmt_double";
1986 fprintf(stderr
,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZE());
1989 printf(" StoreFPR(destreg,%s,%s(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",type
,((MIPS_DECODE
[loop
].flags
& NOT
) ? "Negate" : ""),type
,type
,type
,type
,type
,type
);
1991 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1992 printf(" SignalException(ReservedInstruction,instruction);\n");
1994 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1999 /* For the MIPS I,II or III there *MUST* be at least one
2000 instruction between the compare that sets a condition code
2001 and the branch that tests it. NOTE: However the hardware
2002 does not detect this condition. */
2003 /* Explicitly limit the operation to S and D formats: */
2004 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2005 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2006 printf(" else {\n");
2008 printf(" if ((cmpflags & (1 << 3)) || (condition_code != 0))\n");
2009 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2013 printf(" int ignore = 0;\n");
2014 printf(" int less = 0;\n");
2015 printf(" int equal = 0;\n");
2016 printf(" int unordered = 1;\n");
2017 printf(" uword64 ofs = ValueFPR(fs,format);\n");
2018 printf(" uword64 oft = ValueFPR(ft,format);\n");
2019 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
2020 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
2021 printf(" FCSR |= FP_CAUSE(IO);\n");
2022 printf(" SignalException(FPE);\n");
2023 printf(" ignore = 1;\n");
2025 printf(" } else {\n");
2026 printf(" less = Less(ofs,oft,format);\n");
2027 printf(" equal = Equal(ofs,oft,format);\n");
2028 printf(" unordered = 0;\n");
2030 printf(" if (!ignore) {\n");
2031 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
2032 printf(" SETFCC(condition_code,condition);\n");
2039 fprintf(stderr
,"Unrecognised opcode type %d\n",MIPS_DECODE
[loop
].type
) ;
2044 printf(" break ;\n") ;
2048 printf("default : /* Unrecognised instruction */\n") ;
2049 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2050 printf(" break ;\n") ;
2052 printf("#endif /* simulator engine */\n");
2057 /*---------------------------------------------------------------------------*/
2059 /* The command-line feature controls are presented in a similar style
2060 to those offered by GCC, in the aim of providing a consistent
2061 interface to the user. */
2063 T_NONE
, /* no argument - mask and value fields control "feature" definition */
2064 T_NUM
, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
2065 T_STRING
/* string argument - optionally prcededed by '=' */
2074 } machine_options
[] = {
2075 {"ips", T_NUM
, MASK_ISA
,0,"\tSelect MIPS ISA version"},
2076 {"cpu", T_STRING
,0,0,"\t\tSelect particular MIPS architecture"},
2077 {"gp64", T_NONE
, FEATURE_GP64
,FEATURE_GP64
,"\t\t\tSelect 64bit GP registers"},
2078 {"gp32", T_NONE
, FEATURE_GP64
,0,"\t\t\tSelect 32bit GP registers"},
2079 {"no-fp", T_NONE
, FEATURE_HASFPU
,0,"\t\tDisable FP simulation"},
2080 {"single-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),(FEATURE_FPSINGLE
| FEATURE_HASFPU
),"\t\tSelect single precision only FPU"},
2081 {"double-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),FEATURE_HASFPU
,"\t\tSelect double precision FPU"},
2085 /* The following architecture identies are those accepted by the "-mcpu" option: */
2086 struct architectures
{
2087 const char *name
; /* ASCII string identifier for command-line, no white-space allowed */
2088 unsigned int idflag
; /* or-ed into "isa" value */
2091 static const struct architectures available_architectures
[] = {
2092 {"4100",ARCH_VR4100
}, /* NEC MIPS VR4100 */
2093 {0, 0} /* terminator */
2096 /*---------------------------------------------------------------------------*/
2104 fprintf(stderr
,"%s: Construct a MIPS simulator engine.\n",name
);
2107 The output of this program is a block of 'C' code designed to be\n\
2108 included into the main simulation control loop of a device specific\n\
2111 fprintf(stderr
,"\nOptions:\n");
2112 fprintf(stderr
," -h --help\t\tProvide this help text\n");
2113 fprintf(stderr
," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
2114 fprintf(stderr
," -w --warnings\t\tEnable all the simulator engine warnings\n");
2116 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++) {
2117 fprintf(stderr
," -m%s",machine_options
[loop
].name
);
2118 switch (machine_options
[loop
].type
) {
2120 fprintf(stderr
,"N (range 0..%d)",machine_options
[loop
].mask
);
2125 fprintf(stderr
,"=name");
2129 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",machine_options
[loop
].type
);
2132 fprintf(stderr
,"%s\n",machine_options
[loop
].desc
);
2135 fprintf(stderr
,"\nAvailable \"-mcpu\" architectures: ");
2136 for (loop
= 0; (available_architectures
[loop
].name
!= 0); loop
++)
2137 fprintf(stderr
,"%s ",available_architectures
[loop
].name
);
2138 fprintf(stderr
,"\n\n");
2141 The \"trace\" and \"warnings\" options do not define the output stream.\n\
2142 They only inform the code that includes the constructed engine to provide\n\
2143 the required features.\n\n\
2144 The \"-mips0\" option forces the construction of a simulator supporting\n\
2145 the highest available MIPS ISA supported.\n");
2150 /*---------------------------------------------------------------------------*/
2158 char *progname
= argv
[0];
2159 unsigned int doarch
= DEF_ISA
;
2160 unsigned int features
= 0; /* default state */
2163 features
|= FEATURE_HASFPU
;
2165 features
|= FEATURE_PROC32
;
2167 features
|= FEATURE_FPSINGLE
;
2169 if (features
& FEATURE_PROC32
)
2170 features
&= ~FEATURE_GP64
;
2172 features
|= FEATURE_GP64
;
2175 int this_option_optind
= (optind
? optind
: 1);
2176 int option_index
= 0;
2177 static struct option cmdline
[] = {
2180 {"warnings",0,0,'w'},
2184 c
= getopt_long(argc
,argv
,"hm:tw",cmdline
,&option_index
);
2186 break ; /* out of the while loop */
2189 case 'h' : /* help */
2193 case 'f' : /* fast */
2194 features
|= FEATURE_FAST
;
2197 case 'w' : /* warnings */
2198 features
|= FEATURE_WARNINGS
;
2199 /* TODO: Future extension: Allow better control over the warnings generated:
2200 disable warnings -wnone ~FEATURE_WARNINGS
2201 all possible warnings -wall FEATURE_WARNINGS
2202 pipeline stall occuring -wstall FEATURE_WARN_STALL
2203 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
2204 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
2205 bad r31 use -wr31 FEATURE_WARN_R31
2206 undefined results -wresult FEATURE_WARN_RESULT
2210 case 'm' : /* machine options */
2214 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++)
2215 if (strncmp(machine_options
[loop
].name
,optarg
,strlen(machine_options
[loop
].name
)) == 0) {
2216 char *loptarg
= (optarg
+ strlen(machine_options
[loop
].name
));
2217 switch (machine_options
[loop
].type
) {
2220 fprintf(stderr
,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname
,loptarg
,machine_options
[loop
].name
);
2223 features
&= ~(machine_options
[loop
].mask
);
2224 features
|= machine_options
[loop
].value
;
2228 if (*loptarg
&& *loptarg
== '=')
2231 if (strcmp(machine_options
[loop
].name
,"ips") == 0) {
2235 fprintf(stderr
,"%s: ISA number expected after -mips\n",progname
);
2239 num
= my_strtoul(loptarg
,&loptarg
,10);
2241 if ((num
== ULONG_MAX
) && (errno
= ERANGE
)) {
2242 fprintf(stderr
,"%s: Invalid number given to -mips option\n",progname
);
2247 fprintf(stderr
,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname
,loptarg
);
2251 if (num
> MASK_ISA
) {
2252 fprintf(stderr
,"%s: ISA number %d outside acceptable range (0..%d)\n",progname
,num
,MASK_ISA
);
2256 doarch
= ((doarch
& ~MASK_ISA
) | num
);
2257 if ((num
== 0) || (num
> 2)) {
2258 if ((features
& FEATURE_PROC32
) || !(features
& FEATURE_GP64
))
2259 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp64\n",progname
,num
);
2260 features
|= FEATURE_GP64
;
2261 features
&= ~FEATURE_PROC32
;
2263 if (!(features
& FEATURE_PROC32
) || (features
& FEATURE_GP64
))
2264 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp32\n",progname
,num
);
2265 features
&= ~FEATURE_GP64
;
2266 features
|= FEATURE_PROC32
;
2269 fprintf(stderr
,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname
,optarg
);
2275 if (*loptarg
&& *loptarg
== '=')
2278 if (strcmp(machine_options
[loop
].name
,"cpu") == 0) {
2282 fprintf(stderr
,"%s: Architecture identifier expected after -mcpu\n",progname
);
2286 for (archloop
= 0; (available_architectures
[archloop
].name
!= 0); archloop
++) {
2287 if ((*loptarg
== 'v') || (*loptarg
== 'V'))
2290 if (*loptarg
&& (*loptarg
== 'r') || (*loptarg
== 'R'))
2293 if (strcmp(available_architectures
[archloop
].name
,loptarg
) == 0) {
2294 doarch
|= available_architectures
[archloop
].idflag
;
2299 if (available_architectures
[archloop
].name
== 0) {
2300 fprintf(stderr
,"%s: Unrecognised MIPS architecture \"%s\"\n",progname
,loptarg
);
2304 fprintf(stderr
,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname
,optarg
);
2310 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",progname
,machine_options
[loop
].type
);
2316 if (machine_options
[loop
].name
== 0) {
2317 fprintf(stderr
,"%s: Unrecognised option: -m%s\n",progname
,optarg
);
2324 /* An error message should already have been displayed */
2328 fprintf(stderr
,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname
,c
);
2333 if (optind
< argc
) {
2334 fprintf(stderr
,"%s: Spurios non-option arguments ",progname
);
2335 while (optind
< argc
)
2336 fprintf(stderr
,"\"%s\" ",argv
[optind
++]);
2337 fprintf(stderr
,"\n");
2341 if ((features
& FEATURE_FAST
) && (features
& FEATURE_WARNINGS
))
2342 fprintf(stderr
,"Warning: Fast model generation selected, along with trace or warnings.\n");
2344 process_instructions(doarch
,features
) ;
2348 /*---------------------------------------------------------------------------*/
2350 /* We can't assume that the compiler for the build system has strtoul,
2351 so we provide our own copy. */
2354 * Copyright (c) 1990 Regents of the University of California.
2355 * All rights reserved.
2357 * Redistribution and use in source and binary forms, with or without
2358 * modification, are permitted provided that the following conditions
2360 * 1. Redistributions of source code must retain the above copyright
2361 * notice, this list of conditions and the following disclaimer.
2362 * 2. Redistributions in binary form must reproduce the above copyright
2363 * notice, this list of conditions and the following disclaimer in the
2364 * documentation and/or other materials provided with the distribution.
2365 * 3. All advertising materials mentioning features or use of this software
2366 * must display the following acknowledgement:
2367 * This product includes software developed by the University of
2368 * California, Berkeley and its contributors.
2369 * 4. Neither the name of the University nor the names of its contributors
2370 * may be used to endorse or promote products derived from this software
2371 * without specific prior written permission.
2373 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2374 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2375 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2376 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2377 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2378 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2379 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2380 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2381 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2382 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2387 * Convert a string to an unsigned long integer.
2389 * Ignores `locale' stuff. Assumes that the upper and lower case
2390 * alphabets and digits are each contiguous.
2392 static unsigned long
2393 my_strtoul(nptr
, endptr
, base
)
2398 register const char *s
= nptr
;
2399 register unsigned long acc
;
2401 register unsigned long cutoff
;
2402 register int neg
= 0, any
, cutlim
;
2405 * See strtol for comments as to the logic used.
2409 } while (isspace(c
));
2413 } else if (c
== '+')
2415 if ((base
== 0 || base
== 16) &&
2416 c
== '0' && (*s
== 'x' || *s
== 'X')) {
2422 base
= c
== '0' ? 8 : 10;
2423 cutoff
= (unsigned long)ULONG_MAX
/ (unsigned long)base
;
2424 cutlim
= (unsigned long)ULONG_MAX
% (unsigned long)base
;
2425 for (acc
= 0, any
= 0;; c
= *s
++) {
2428 else if (isalpha(c
))
2429 c
-= isupper(c
) ? 'A' - 10 : 'a' - 10;
2434 if (any
< 0 || acc
> cutoff
|| acc
== cutoff
&& c
> cutlim
)
2448 *endptr
= (char *) (any
? s
- 1 : nptr
);
2452 /*---------------------------------------------------------------------------*/
2454 /*> EOF gencode.c <*/